Browse Source

*** empty log message ***

Paul Sheer 26 years ago
parent
commit
f36e99f150
10 changed files with 11929 additions and 0 deletions
  1. 2262 0
      edit/edit.c
  2. 835 0
      edit/edit.h
  3. 2870 0
      edit/editcmd.c
  4. 140 0
      edit/editcmddef.h
  5. 736 0
      edit/editdraw.c
  6. 461 0
      edit/editmenu.c
  7. 182 0
      edit/editoptions.c
  8. 1212 0
      edit/editwidget.c
  9. 2881 0
      edit/syntax.c
  10. 350 0
      edit/wordproc.c

+ 2262 - 0
edit/edit.c

@@ -0,0 +1,2262 @@
+/* editor low level data handling and cursor fundamentals.
+
+   Copyright (C) 1996, 1997 the Free Software Foundation
+   
+   Authors: 1996, 1997 Paul Sheer
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define _EDIT_C THIS_IS
+
+#include <config.h>
+#if defined(OS2_NT)
+#    include <io.h>
+#    include <fcntl.h>
+#endif
+#include "edit.h"
+
+#ifdef SCO_FLAVOR
+#	include <sys/timeb.h>
+#endif /* SCO_FLAVOR */
+#include <time.h>	/* for ctime() */
+
+/*
+ *
+ * here's a quick sketch of the layout: (don't run this through indent.)
+ * 
+ * (b1 is buffers1 and b2 is buffers2)
+ * 
+ *                                       |
+ * \0\0\0\0\0m e _ f i l e . \nf i n . \n|T h i s _ i s _ s o\0\0\0\0\0\0\0\0\0
+ * ______________________________________|______________________________________
+ *                                       |
+ * ...  |  b2[2]   |  b2[1]   |  b2[0]   |  b1[0]   |  b1[1]   |  b1[2]   | ...
+ *      |->        |->        |->        |->        |->        |->        |
+ *                                       |
+ *           _<------------------------->|<----------------->_
+ *                   WEdit->curs2        |   WEdit->curs1
+ *           ^                           |                   ^
+ *           |                          ^|^                  |
+ *         cursor                       |||                cursor
+ *                                      |||
+ *                              file end|||file beginning
+ *                                       |
+ *                                       |
+ * 
+ *           _
+ * This_is_some_file
+ * fin.
+ *
+ *
+ */
+
+/*
+   returns a byte from any location in the file.
+   Returns '\n' if out of bounds.
+ */
+
+#ifndef NO_INLINE_GETBYTE
+
+int edit_get_byte (WEdit * edit, long byte_index)
+{
+    unsigned long p;
+    if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0)
+	return '\n';
+
+    if (byte_index >= edit->curs1) {
+	p = edit->curs1 + edit->curs2 - byte_index - 1;
+	return edit->buffers2[p >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (p & M_EDIT_BUF_SIZE) - 1];
+    } else {
+	return edit->buffers1[byte_index >> S_EDIT_BUF_SIZE][byte_index & M_EDIT_BUF_SIZE];
+    }
+}
+
+#endif
+
+char *edit_get_buffer_as_text (WEdit * e)
+{
+    int l, i;
+    char *t;
+    l = e->curs1 + e->curs2;
+    t = CMalloc (l + 1);
+    for (i = 0; i < l; i++)
+	t[i] = edit_get_byte (e, i);
+    t[l] = 0;
+    return t;
+}
+
+/* Initialisation routines */
+
+/* returns 1 on error */
+/* loads file OR text into buffers. Only one must be none-NULL. */
+/* cursor set to start of file */
+int init_dynamic_edit_buffers (WEdit * edit, const char *filename, const char *text)
+{
+    long buf;
+    int j, file = 0, buf2;
+
+    for (j = 0; j <= MAXBUFF; j++) {
+	edit->buffers1[j] = NULL;
+	edit->buffers2[j] = NULL;
+    }
+
+    if (filename)
+	if ((file = open ((char *) filename, O_RDONLY | MY_O_TEXT)) == -1) {
+/* The file-name is printed after the ':' */
+	    edit_error_dialog (_(" Error "), get_sys_error (catstrs (_(" Failed trying to open file for reading: "), filename, " ", 0)));
+	    return 1;
+	}
+    edit->curs2 = edit->last_byte;
+
+    buf2 = edit->curs2 >> S_EDIT_BUF_SIZE;
+
+    edit->buffers2[buf2] = CMalloc (EDIT_BUF_SIZE);
+
+    if (filename)
+	read (file, (char *) edit->buffers2[buf2] + EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE), edit->curs2 & M_EDIT_BUF_SIZE);
+    else {
+	memcpy (edit->buffers2[buf2] + EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE), text, edit->curs2 & M_EDIT_BUF_SIZE);
+	text += edit->curs2 & M_EDIT_BUF_SIZE;
+    }
+
+    for (buf = buf2 - 1; buf >= 0; buf--) {
+	edit->buffers2[buf] = CMalloc (EDIT_BUF_SIZE);
+	if (filename)
+	    read (file, (char *) edit->buffers2[buf], EDIT_BUF_SIZE);
+	else {
+	    memcpy (edit->buffers2[buf], text, EDIT_BUF_SIZE);
+	    text += EDIT_BUF_SIZE;
+	}
+    }
+
+    edit->curs1 = 0;
+    if (filename)
+	close (file);
+
+    return 0;
+}
+
+/* returns 1 on error */
+int edit_load_file (WEdit * edit, const char *filename, const char *text, unsigned long text_size)
+{
+    struct stat s;
+    int file;
+
+    if (text) {
+	edit->last_byte = text_size;
+	filename = NULL;
+    } else {
+#if defined(MIDNIGHT) || defined(GTK)
+	if ((file = open ((char *) filename, O_RDONLY)) < 0)
+	{
+		close(creat((char *) filename, 0666));
+		if ((file = open ((char *) filename, O_RDONLY)) < 0) {
+			edit_error_dialog (_(" Error "), get_sys_error (catstrs (" Fail trying to open the file, ", filename, ", for reading ", 0)));
+			return 1;
+		}
+		edit->delete_file = 1;
+	}
+#else
+	if ((file = open ((char *) filename, O_RDONLY)) < 0) {
+	    edit_error_dialog (_(" Error "), get_sys_error (catstrs (_(" Failed trying to open file for reading: "), filename, " ", 0)));
+	    return 1;
+	}
+#endif
+	if (stat ((char *) filename, &s) < 0) {
+	    close (file);
+/* The file-name is printed after the ':' */
+	    edit_error_dialog (_(" Error "), get_sys_error (catstrs (_(" Cannot get size/permissions info on file: "), filename, " ", 0)));
+	    return 1;
+	}
+	if (S_ISDIR (s.st_mode) || S_ISSOCK (s.st_mode)
+	    || S_ISFIFO (s.st_mode)) {
+	    close (file);
+/* The file-name is printed after the ':' */
+	    edit_error_dialog (_(" Error "), catstrs (_(" Not an ordinary file: "), filename, " ", 0));
+	    return 1;
+	}
+	if (s.st_size >= SIZE_LIMIT) {
+	    close (file);
+/* The file-name is printed after the ':' */
+	    edit_error_dialog (_(" Error "), catstrs (_(" File is too large: "), \
+		filename, _(" \n Increase edit.h:MAXBUF and recompile the editor. "), 0));
+	    return 1;
+	}
+	close (file);
+	edit->last_byte = s.st_size;
+	edit->stat = s;
+    }
+
+    return init_dynamic_edit_buffers (edit, filename, text);
+}
+
+#ifdef MIDNIGHT
+#define space_width 1
+#else
+int space_width;
+extern int option_long_whitespace;
+extern unsigned char per_char[256];
+
+void edit_set_space_width (int s)
+{
+    space_width = s;
+}
+
+#endif
+
+/* fills in the edit struct. returns 0 on fail. Pass edit as NULL for this function to do an malloc for you */
+WEdit *edit_init (WEdit * edit, int lines, int columns, const char *filename, const char *text, const char *dir, unsigned long text_size)
+{
+    char *f;
+#ifndef MIDNIGHT
+    if (option_long_whitespace)
+	edit_set_space_width (per_char[' '] * 2);
+    else
+	edit_set_space_width (per_char[' ']);
+#endif
+    if (!edit)
+	edit = malloc (sizeof (WEdit));
+    if (!edit) {
+	edit_error_dialog (_(" Error "), _(" Error allocating memory "));
+	return 0;
+    }
+    memset (&(edit->from_here), 0, (unsigned long) &(edit->to_here) - (unsigned long) &(edit->from_here));
+#ifndef MIDNIGHT
+    edit->max_column = columns * FONT_MEAN_WIDTH;
+#endif
+    edit->num_widget_lines = lines;
+    edit->num_widget_columns = columns;
+    edit->stat.st_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+    edit->stat.st_uid = getuid ();
+    edit->stat.st_gid = getgid ();
+    edit->bracket = -1;
+    if (!dir)
+	dir = "";
+    f = (char *) filename;
+    if (filename)
+	f = catstrs (dir, filename, 0);
+    if (edit_load_file (edit, f, text, text_size)) {
+/* edit_load_file already gives an error message */
+	free (edit);
+	return 0;
+    }
+    edit->force |= REDRAW_PAGE;
+    if (filename) {
+	filename = catstrs (dir, filename, 0);
+	edit_split_filename (edit, (char *) filename);
+    } else {
+	edit->filename = strdup ("");
+	edit->dir = strdup(dir);
+    }
+    edit->stack_size = START_STACK_SIZE;
+    edit->stack_size_mask = START_STACK_SIZE - 1;
+    edit->undo_stack = malloc ((edit->stack_size + 10) * sizeof (long));
+    if (!edit->undo_stack) {
+	edit_error_dialog (_(" Error "), _(" Error allocating memory "));
+	free (edit);
+	return 0;
+    }
+    edit->total_lines = edit_count_lines (edit, 0, edit->last_byte);
+    edit_load_syntax (edit, 0, 0);
+    {
+	int fg, bg;
+	edit_get_syntax_color (edit, -1, &fg, &bg);
+    }
+    return edit;
+}
+
+
+/* clear the edit struct, freeing everything in it. returns 1 on success */
+int edit_clean (WEdit * edit)
+{
+    if (edit) {
+	int j = 0;
+	edit_free_syntax_rules (edit);
+	for (; j <= MAXBUFF; j++) {
+	    if (edit->buffers1[j] != NULL)
+		free (edit->buffers1[j]);
+	    if (edit->buffers2[j] != NULL)
+		free (edit->buffers2[j]);
+	}
+
+	if (edit->undo_stack)
+	    free (edit->undo_stack);
+	if (edit->filename)
+	    free (edit->filename);
+	if (edit->dir)
+	    free (edit->dir);
+/* we don't want to clear the widget */
+	memset (&(edit->from_here), 0, (unsigned long) &(edit->to_here) - (unsigned long) &(edit->from_here));
+	return 1;
+    }
+    return 0;
+}
+
+
+/* returns 1 on success */
+int edit_renew (WEdit * edit)
+{
+    int lines = edit->num_widget_lines;
+    int columns = edit->num_widget_columns;
+    char *dir;
+
+    if (edit->dir)
+	dir = strdup (edit->dir);
+    else
+	dir = 0;
+    
+    edit_clean (edit);
+    if (!edit_init (edit, lines, columns, 0, "", dir, 0))
+	return 0;
+    return 1;
+}
+
+/* returns 1 on success */
+int edit_reload (WEdit * edit, const char *filename, const char *text, const char *dir, unsigned long text_size)
+{
+    int lines = edit->num_widget_lines;
+    int columns = edit->num_widget_columns;
+    edit_clean (edit);
+    if (!edit_init (edit, lines, columns, filename, text, dir, text_size)) {
+	return 0;
+    }
+    return 1;
+}
+
+
+/*
+   Recording stack for undo:
+   The following is an implementation of a compressed stack. Identical
+   pushes are recorded by a negative prefix indicating the number of times the
+   same char was pushed. This saves space for repeated curs-left or curs-right
+   delete etc.
+
+   eg:
+
+  pushed:       stored:
+
+   a
+   b             a
+   b            -3
+   b             b
+   c  -->       -4
+   c             c
+   c             d
+   c
+   d
+
+   If the stack long int is 0-255 it represents a normal insert (from a backspace),
+   256-512 is an insert ahead (from a delete), If it is betwen 600 and 700 it is one
+   of the cursor functions #define'd in edit.h. 1000 through 700'000'000 is to
+   set edit->mark1 position. 700'000'000 through 1400'000'000 is to set edit->mark2
+   position.
+
+   The only way the curser moves or the buffer is changed is through the routines:
+   insert, backspace, insert_ahead, delete, and cursor_move.
+   These record the reverse undo movements onto the stack each time they are
+   called.
+
+   Each key press results in a set of actions (insert; delete ...). So each time
+   a key is pressed the current position of start_display is pushed as
+   KEY_PRESS + start_display. Then for undoing, we pop until we get to a number
+   over KEY_PRESS. We then assign this number less KEY_PRESS to start_display. So undo
+   tracks scrolling and key actions exactly. (KEY_PRESS is about (2^31) * (2/3) = 1400'000'000)
+
+*/
+
+static int push_action_disabled = 0;
+
+void edit_push_action (WEdit * edit, long c,...)
+{
+    unsigned long sp = edit->stack_pointer;
+    unsigned long spm1;
+    long *t;
+/* first enlarge the stack if necessary */
+    if (sp > edit->stack_size - 10) {	/* say */
+	if (option_max_undo < 256)
+	    option_max_undo = 256;
+	if (edit->stack_size < option_max_undo) {
+	    t = malloc ((edit->stack_size * 2 + 10) * sizeof (long));
+	    if (t) {
+		memcpy (t, edit->undo_stack, sizeof (long) * edit->stack_size);
+		free (edit->undo_stack);
+		edit->undo_stack = t;
+		edit->stack_size <<= 1;
+		edit->stack_size_mask = edit->stack_size - 1;
+	    }
+	}
+    }
+    spm1 = (edit->stack_pointer - 1) & edit->stack_size_mask;
+    if (push_action_disabled)
+	return;
+
+#ifdef FAST_MOVE_CURSOR
+    if (c == CURS_LEFT_LOTS || c == CURS_RIGHT_LOTS) {
+	va_list ap;
+	edit->undo_stack[sp] = c == CURS_LEFT_LOTS ? CURS_LEFT : CURS_RIGHT;
+	edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask;
+	va_start (ap, c);
+	c = -(va_arg (ap, int));
+	va_end (ap);
+    } else
+#endif				/* ! FAST_MOVE_CURSOR */
+    if (spm1 != edit->stack_bottom && ((sp - 2) & edit->stack_size_mask) != edit->stack_bottom) {
+	int d;
+	if (edit->undo_stack[spm1] < 0) {
+	    d = edit->undo_stack[(sp - 2) & edit->stack_size_mask];
+	    if (d == c) {
+		if (edit->undo_stack[spm1] > -1000000000) {
+		    if (c < KEY_PRESS)	/* --> no need to push multiple do-nothings */
+			edit->undo_stack[spm1]--;
+		    return;
+		}
+	    }
+/* #define NO_STACK_CURSMOVE_ANIHILATION */
+#ifndef NO_STACK_CURSMOVE_ANIHILATION
+	    else if ((c == CURS_LEFT && d == CURS_RIGHT)
+		     || (c == CURS_RIGHT && d == CURS_LEFT)) {	/* a left then a right anihilate each other */
+		if (edit->undo_stack[spm1] == -2)
+		    edit->stack_pointer = spm1;
+		else
+		    edit->undo_stack[spm1]++;
+		return;
+	    }
+#endif
+	} else {
+	    d = edit->undo_stack[spm1];
+	    if (d == c) {
+		if (c >= KEY_PRESS)
+		    return;	/* --> no need to push multiple do-nothings */
+		edit->undo_stack[sp] = -2;
+		goto check_bottom;
+	    }
+#ifndef NO_STACK_CURSMOVE_ANIHILATION
+	    else if ((c == CURS_LEFT && d == CURS_RIGHT)
+		     || (c == CURS_RIGHT && d == CURS_LEFT)) {	/* a left then a right anihilate each other */
+		edit->stack_pointer = spm1;
+		return;
+	    }
+#endif
+	}
+    }
+    edit->undo_stack[sp] = c;
+  check_bottom:
+
+    edit->stack_pointer = (edit->stack_pointer + 1) & edit->stack_size_mask;
+
+/*if the sp wraps round and catches the stack_bottom then erase the first set of actions on the stack to make space - by moving stack_bottom forward one "key press" */
+    c = (edit->stack_pointer + 2) & edit->stack_size_mask;
+    if (c == edit->stack_bottom || ((c + 1) & edit->stack_size_mask) == edit->stack_bottom)
+	do {
+	    edit->stack_bottom = (edit->stack_bottom + 1) & edit->stack_size_mask;
+	} while (edit->undo_stack[edit->stack_bottom] < KEY_PRESS && edit->stack_bottom != edit->stack_pointer);
+
+/*If a single key produced enough pushes to wrap all the way round then we would notice that the [stack_bottom] does not contain KEY_PRESS. The stack is then initialised: */
+    if (edit->stack_pointer != edit->stack_bottom && edit->undo_stack[edit->stack_bottom] < KEY_PRESS)
+	edit->stack_bottom = edit->stack_pointer = 0;
+}
+
+/*
+   TODO: if the user undos until the stack bottom, and the stack has not wrapped,
+   then the file should be as it was when he loaded up. Then set edit->modified to 0.
+ */
+long pop_action (WEdit * edit)
+{
+    long c;
+    unsigned long sp = edit->stack_pointer;
+    if (sp == edit->stack_bottom) {
+	return STACK_BOTTOM;
+    }
+    sp = (sp - 1) & edit->stack_size_mask;
+    if ((c = edit->undo_stack[sp]) >= 0) {
+/*	edit->undo_stack[sp] = '@'; */
+	edit->stack_pointer = (edit->stack_pointer - 1) & edit->stack_size_mask;
+	return c;
+    }
+    if (sp == edit->stack_bottom) {
+	return STACK_BOTTOM;
+    }
+    c = edit->undo_stack[(sp - 1) & edit->stack_size_mask];
+    if (edit->undo_stack[sp] == -2) {
+/*      edit->undo_stack[sp] = '@'; */
+	edit->stack_pointer = sp;
+    } else
+	edit->undo_stack[sp]++;
+
+    return c;
+}
+
+
+/* is called whenever a modification is made by one of the four routines below */
+static inline void edit_modification (WEdit * edit)
+{
+    edit->modified = 1;
+}
+
+
+/*
+   Basic low level single character buffer alterations and movements at the cursor.
+   Returns char passed over, inserted or removed.
+ */
+
+void edit_insert (WEdit * edit, int c)
+{
+/* check if file has grown to large */
+    if (edit->last_byte >= SIZE_LIMIT)
+	return;
+
+/* first we must update the position of the display window */
+    if (edit->curs1 < edit->start_display) {
+	edit->start_display++;
+	if (c == '\n')
+	    edit->start_line++;
+    }
+/* now we must update some info on the file and check if a redraw is required */
+    if (c == '\n') {
+	edit->curs_line++;
+	edit->total_lines++;
+	edit->force |= REDRAW_LINE_ABOVE | REDRAW_AFTER_CURSOR;
+    }
+/* tell that we've modified the file */
+    edit_modification (edit);
+
+/* save the reverse command onto the undo stack */
+    edit_push_action (edit, BACKSPACE);
+
+/* update markers */
+    edit->mark1 += (edit->mark1 > edit->curs1);
+    edit->mark2 += (edit->mark2 > edit->curs1);
+    edit->last_get_rule += (edit->last_get_rule > edit->curs1);
+
+/* add a new buffer if we've reached the end of the last one */
+    if (!(edit->curs1 & M_EDIT_BUF_SIZE))
+	edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
+
+/* perfprm the insertion */
+    edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->curs1 & M_EDIT_BUF_SIZE] = (unsigned char) c;
+
+/* update file length */
+    edit->last_byte++;
+
+/* update cursor position */
+    edit->curs1++;
+}
+
+
+/* same as edit_insert and move left */
+void edit_insert_ahead (WEdit * edit, int c)
+{
+    if (edit->last_byte >= SIZE_LIMIT)
+	return;
+    if (edit->curs1 < edit->start_display) {
+	edit->start_display++;
+	if (c == '\n')
+	    edit->start_line++;
+    }
+    if (c == '\n') {
+	edit->total_lines++;
+	edit->force |= REDRAW_AFTER_CURSOR;
+    }
+    edit_modification (edit);
+    edit_push_action (edit, DELETE);
+
+    edit->mark1 += (edit->mark1 >= edit->curs1);
+    edit->mark2 += (edit->mark2 >= edit->curs1);
+    edit->last_get_rule += (edit->last_get_rule >= edit->curs1);
+
+    if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE))
+	edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
+    edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c;
+
+    edit->last_byte++;
+    edit->curs2++;
+}
+
+
+int edit_delete (WEdit * edit)
+{
+    int p;
+    if (!edit->curs2)
+	return 0;
+
+    edit->mark1 -= (edit->mark1 > edit->curs1);
+    edit->mark2 -= (edit->mark2 > edit->curs1);
+    edit->last_get_rule -= (edit->last_get_rule > edit->curs1);
+
+    p = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - ((edit->curs2 - 1) & M_EDIT_BUF_SIZE) - 1];
+
+    if (!(edit->curs2 & M_EDIT_BUF_SIZE)) {
+	free (edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE]);
+	edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = NULL;
+    }
+    edit->last_byte--;
+    edit->curs2--;
+
+    if (p == '\n') {
+	edit->total_lines--;
+	edit->force |= REDRAW_AFTER_CURSOR;
+    }
+    edit_push_action (edit, p + 256);
+    if (edit->curs1 < edit->start_display) {
+	edit->start_display--;
+	if (p == '\n')
+	    edit->start_line--;
+    }
+    edit_modification (edit);
+
+    return p;
+}
+
+
+int edit_backspace (WEdit * edit)
+{
+    int p;
+    if (!edit->curs1)
+	return 0;
+
+    edit->mark1 -= (edit->mark1 >= edit->curs1);
+    edit->mark2 -= (edit->mark2 >= edit->curs1);
+    edit->last_get_rule -= (edit->last_get_rule >= edit->curs1);
+
+    p = *(edit->buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE] + ((edit->curs1 - 1) & M_EDIT_BUF_SIZE));
+    if (!((edit->curs1 - 1) & M_EDIT_BUF_SIZE)) {
+	free (edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]);
+	edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = NULL;
+    }
+    edit->last_byte--;
+    edit->curs1--;
+
+    if (p == '\n') {
+	edit->curs_line--;
+	edit->total_lines--;
+	edit->force |= REDRAW_AFTER_CURSOR;
+    }
+    edit_push_action (edit, p);
+
+    if (edit->curs1 < edit->start_display) {
+	edit->start_display--;
+	if (p == '\n')
+	    edit->start_line--;
+    }
+    edit_modification (edit);
+
+    return p;
+}
+
+#ifdef FAST_MOVE_CURSOR
+
+#define memqcpy(edit,d,s,i)						\
+	{								\
+	    unsigned long next;						\
+	    char *dest = d;						\
+	    char *src = s;						\
+	    int n = i;							\
+	    while ((next =						\
+		    (unsigned long) memccpy (dest, src, '\n', n))) {	\
+		edit->curs_line--;					\
+		next -= (unsigned long) dest;				\
+		n -= next;						\
+		src += next;						\
+		dest += next;						\
+	    }								\
+	}
+
+int edit_move_backward_lots (WEdit * edit, long increment)
+{
+    int r, s, t;
+    char *p;
+
+    if (increment > edit->curs1)
+	increment = edit->curs1;
+    if (increment <= 0)
+	return -1;
+    edit_push_action (edit, CURS_RIGHT_LOTS, increment);
+
+    t = r = EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE);
+    if (r > increment)
+	r = increment;
+    s = edit->curs1 & M_EDIT_BUF_SIZE;
+
+    p = 0;
+    if (s > r) {
+	memqcpy (edit, edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - r,
+	      edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] + s - r, r);
+    } else {
+	if (s) {
+	    memqcpy (edit, edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - s,
+		     edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE], s);
+	    p = edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE];
+	    edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = 0;
+	}
+	memqcpy (edit, edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + t - r,
+		 edit->buffers1[(edit->curs1 >> S_EDIT_BUF_SIZE) - 1] + EDIT_BUF_SIZE - (r - s), r - s);
+    }
+    increment -= r;
+    edit->curs1 -= r;
+    edit->curs2 += r;
+    if (!(edit->curs2 & M_EDIT_BUF_SIZE)) {
+	if (p)
+	    edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p;
+	else
+	    edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
+    } else {
+	if (p)
+	    free (p);
+    }
+
+    s = edit->curs1 & M_EDIT_BUF_SIZE;
+    while (increment) {
+	p = 0;
+	r = EDIT_BUF_SIZE;
+	if (r > increment)
+	    r = increment;
+	t = s;
+	if (r < t)
+	    t = r;
+	memqcpy (edit,
+		 edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + EDIT_BUF_SIZE - t,
+		 edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] + s - t,
+		 t);
+	if (r >= s) {
+	    if (t) {
+		p = edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE];
+		edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = 0;
+	    }
+	    memqcpy (edit,
+		     edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] + EDIT_BUF_SIZE - r,
+		     edit->buffers1[(edit->curs1 >> S_EDIT_BUF_SIZE) - 1] + EDIT_BUF_SIZE - (r - s),
+		     r - s);
+	}
+	increment -= r;
+	edit->curs1 -= r;
+	edit->curs2 += r;
+	if (!(edit->curs2 & M_EDIT_BUF_SIZE)) {
+	    if (p)
+		edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = p;
+	    else
+		edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
+	} else {
+	    if (p)
+		free (p);
+	}
+    }
+    return edit_get_byte (edit, edit->curs1);
+}
+
+#endif		/* ! FAST_MOVE_CURSOR */
+
+/* moves the curser right or left: increment positive or negative respectively */
+int edit_cursor_move (WEdit * edit, long increment)
+{
+/* this is the same as a combination of two of the above routines, with only one push onto the undo stack */
+    int c;
+
+#ifdef FAST_MOVE_CURSOR
+    if (increment < -256) {
+	edit->force |= REDRAW_PAGE;
+	return edit_move_backward_lots (edit, -increment);
+    }
+#endif		/* ! FAST_MOVE_CURSOR */
+
+    if (increment < 0) {
+	for (; increment < 0; increment++) {
+	    if (!edit->curs1)
+		return -1;
+
+	    edit_push_action (edit, CURS_RIGHT);
+
+	    c = edit_get_byte (edit, edit->curs1 - 1);
+	    if (!((edit->curs2 + 1) & M_EDIT_BUF_SIZE))
+		edit->buffers2[(edit->curs2 + 1) >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
+	    edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1] = c;
+	    edit->curs2++;
+	    c = edit->buffers1[(edit->curs1 - 1) >> S_EDIT_BUF_SIZE][(edit->curs1 - 1) & M_EDIT_BUF_SIZE];
+	    if (!((edit->curs1 - 1) & M_EDIT_BUF_SIZE)) {
+		free (edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE]);
+		edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = NULL;
+	    }
+	    edit->curs1--;
+	    if (c == '\n') {
+		edit->curs_line--;
+		edit->force |= REDRAW_LINE_BELOW;
+	    }
+	}
+
+	return c;
+    } else if (increment > 0) {
+	for (; increment > 0; increment--) {
+	    if (!edit->curs2)
+		return -2;
+
+	    edit_push_action (edit, CURS_LEFT);
+
+	    c = edit_get_byte (edit, edit->curs1);
+	    if (!(edit->curs1 & M_EDIT_BUF_SIZE))
+		edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE] = malloc (EDIT_BUF_SIZE);
+	    edit->buffers1[edit->curs1 >> S_EDIT_BUF_SIZE][edit->curs1 & M_EDIT_BUF_SIZE] = c;
+	    edit->curs1++;
+	    c = edit->buffers2[(edit->curs2 - 1) >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - ((edit->curs2 - 1) & M_EDIT_BUF_SIZE) - 1];
+	    if (!(edit->curs2 & M_EDIT_BUF_SIZE)) {
+		free (edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE]);
+		edit->buffers2[edit->curs2 >> S_EDIT_BUF_SIZE] = 0;
+	    }
+	    edit->curs2--;
+	    if (c == '\n') {
+		edit->curs_line++;
+		edit->force |= REDRAW_LINE_ABOVE;
+	    }
+	}
+	return c;
+    } else
+	return -3;
+}
+
+/* These functions return positions relative to lines */
+
+/* returns index of last char on line + 1 */
+long edit_eol (WEdit * edit, long current)
+{
+    if (current < edit->last_byte) {
+	for (;; current++)
+#if 0
+	    if (current == edit->last_byte || edit_get_byte (edit, current) == '\n')
+#else
+	    if (edit_get_byte (edit, current) == '\n')
+#endif
+		break;
+    } else
+	return edit->last_byte;
+    return current;
+}
+
+/* returns index of first char on line */
+long edit_bol (WEdit * edit, long current)
+{
+    if (current > 0) {
+	for (;; current--)
+#if 0
+	    if (current == 0 || edit_get_byte (edit, current - 1) == '\n')
+#else
+	    if (edit_get_byte (edit, current - 1) == '\n')
+#endif
+		break;
+    } else
+	return 0;
+    return current;
+}
+
+
+int edit_count_lines (WEdit * edit, long current, int upto)
+{
+    int lines = 0;
+    if (upto > edit->last_byte)
+	upto = edit->last_byte;
+    if (current < 0)
+	current = 0;
+    while (current < upto)
+	if (edit_get_byte (edit, current++) == '\n')
+	    lines++;
+    return lines;
+}
+
+
+/* If lines is zero this returns the count of lines from current to upto. */
+/* If upto is zero returns index of lines forward current. */
+long edit_move_forward (WEdit * edit, long current, int lines, long upto)
+{
+    if (upto) {
+	return edit_count_lines (edit, current, upto);
+    } else {
+	int next;
+	if (lines < 0)
+	    lines = 0;
+	while (lines--) {
+	    next = edit_eol (edit, current) + 1;
+	    if (next > edit->last_byte)
+		break;
+	    else
+		current = next;
+	}
+	return current;
+    }
+}
+
+
+/* Returns offset of 'lines' lines up from current */
+long edit_move_backward (WEdit * edit, long current, int lines)
+{
+    if (lines < 0)
+	lines = 0;
+    current = edit_bol (edit, current);
+    while((lines--) && current != 0)
+	current = edit_bol (edit, current - 1);
+    return current;
+}
+
+#ifdef MIDNIGHT
+/* If cols is zero this returns the count of columns from current to upto. */
+/* If upto is zero returns index of cols across from current. */
+long edit_move_forward3 (WEdit * edit, long current, int cols, long upto)
+{
+    long p, q;
+    int col = 0;
+
+    if (upto) {
+	q = upto;
+	cols = -10;
+    } else
+	q = edit->last_byte + 2;
+
+    for (col = 0, p = current; p < q; p++) {
+	int c;
+	if (cols != -10) {
+	    if (col == cols)
+		return p;
+	    if (col > cols)
+		return p - 1;
+	}
+	c = edit_get_byte (edit, p);
+	if (c == '\r')
+	    continue;
+	else
+	if (c == '\t')
+	    col += TAB_SIZE - col % TAB_SIZE;
+	else
+	    col++;
+	/*if(edit->nroff ... */
+	if (c == '\n') {
+	    if (upto)
+		return col;
+	    else
+		return p;
+	}
+    }
+    return (float) col;
+}
+#endif
+
+/* returns the current column position of the cursor */
+int edit_get_col (WEdit * edit)
+{
+    return edit_move_forward3 (edit, edit_bol (edit, edit->curs1), 0, edit->curs1);
+}
+
+
+/* Scrolling functions */
+
+void edit_update_curs_row (WEdit * edit)
+{
+    edit->curs_row = edit->curs_line - edit->start_line;
+}
+
+void edit_update_curs_col (WEdit * edit)
+{
+    edit->curs_col = edit_move_forward3(edit, edit_bol(edit, edit->curs1), 0, edit->curs1);
+}
+
+/*moves the display start position up by i lines */
+void edit_scroll_upward (WEdit * edit, unsigned long i)
+{
+    int lines_above = edit->start_line;
+    if (i > lines_above)
+	i = lines_above;
+    if (i) {
+	edit->start_line -= i;
+	edit->start_display = edit_move_backward (edit, edit->start_display, i);
+	edit->force |= REDRAW_PAGE;
+	edit->force &= (0xfff - REDRAW_CHAR_ONLY);
+    }
+    edit_update_curs_row(edit);
+}
+
+
+/* returns 1 if could scroll, 0 otherwise */
+void edit_scroll_downward (WEdit * edit, int i)
+{
+    int lines_below;
+    lines_below = edit->total_lines - edit->start_line - (edit->num_widget_lines - 1);
+    if (lines_below > 0) {
+	if (i > lines_below)
+	    i = lines_below;
+	edit->start_line += i;
+	edit->start_display = edit_move_forward (edit, edit->start_display, i, 0);
+	edit->force |= REDRAW_PAGE;
+	edit->force &= (0xfff - REDRAW_CHAR_ONLY);
+    }
+    edit_update_curs_row(edit);
+}
+
+void edit_scroll_right (WEdit * edit, int i)
+{
+    edit->force |= REDRAW_PAGE;
+    edit->force &= (0xfff - REDRAW_CHAR_ONLY);
+    edit->start_col -= i;
+}
+
+void edit_scroll_left (WEdit * edit, int i)
+{
+    if (edit->start_col) {
+	edit->start_col += i;
+	if (edit->start_col > 0)
+	    edit->start_col = 0;
+	edit->force |= REDRAW_PAGE;
+	edit->force &= (0xfff - REDRAW_CHAR_ONLY);
+    }
+}
+
+/* high level cursor movement commands */
+
+static int is_in_indent (WEdit *edit)
+{
+    long p = edit_bol (edit, edit->curs1);
+    while (p < edit->curs1)
+	if (!strchr (" \t", edit_get_byte (edit, p++)))
+	    return 0;
+    return 1;
+}
+
+static int left_of_four_spaces (WEdit *edit);
+
+void edit_move_to_prev_col (WEdit * edit, long p)
+{
+    edit_cursor_move (edit, edit_move_forward3 (edit, p, edit->prev_col, 0) - edit->curs1);
+
+    if (is_in_indent (edit) && option_fake_half_tabs) {
+	edit_update_curs_col (edit);
+	if (space_width)
+	if (edit->curs_col % (HALF_TAB_SIZE * space_width)) {
+	    int q = edit->curs_col;
+	    edit->curs_col -= (edit->curs_col % (HALF_TAB_SIZE * space_width));
+	    p = edit_bol (edit, edit->curs1);
+	    edit_cursor_move (edit, edit_move_forward3 (edit, p, edit->curs_col, 0) - edit->curs1);
+	    if (!left_of_four_spaces (edit))
+		edit_cursor_move (edit, edit_move_forward3 (edit, p, q, 0) - edit->curs1);
+	}
+    }
+}
+
+
+/* move i lines */
+static void edit_move_up (WEdit * edit, unsigned long i, int scroll)
+{
+    long p, l = edit->curs_line;
+
+    if (i > l)
+	i = l;
+    if (i) {
+	if (i > 1)
+	    edit->force |= REDRAW_PAGE;
+	if (scroll)
+	    edit_scroll_upward (edit, i);
+
+	p = edit_bol (edit, edit->curs1);
+	edit_cursor_move (edit, (p = edit_move_backward (edit, p, i)) - edit->curs1);
+	edit_move_to_prev_col (edit, p);
+
+	edit->search_start = edit->curs1;
+	edit->found_len = 0;
+    }
+}
+
+int is_blank (WEdit * edit, long offset)
+{
+    long s, f;
+    int c;
+    s = edit_bol (edit, offset);
+    f = edit_eol (edit, offset) - 1;
+    while (s <= f) {
+	c = edit_get_byte (edit, s++);
+	if ((c > ' ' && c <= '~') || c >= 160)	/* non-printables on a line are considered "blank" */
+	    return 0;
+    }
+    return 1;
+}
+
+int line_is_blank (WEdit * edit, long line)
+{
+    static long p = -1, l = 0;
+    if (p == -1 || abs (l - line) > abs (edit->curs_line - line)) {
+	l = edit->curs_line;
+	p = edit->curs1;
+    }
+    if (line < l)
+	p = edit_move_backward (edit, p, l - line);
+    else if (line > l)
+	p = edit_move_forward (edit, p, line - l, 0);
+    l = line;
+    return is_blank (edit, p);
+}
+
+/* moves up until a blank line is reached, or until just 
+   before a non-blank line is reached */
+static void edit_move_up_paragraph (WEdit * edit, int scroll)
+{
+    int i;
+    if (edit->curs_line <= 1) {
+	i = 0;
+    } else {
+	if (line_is_blank (edit, edit->curs_line)) {
+	    if (line_is_blank (edit, edit->curs_line - 1)) {
+		for (i = edit->curs_line - 1; i; i--)
+		    if (!line_is_blank (edit, i)) {
+			i++;
+			break;
+		    }
+	    } else {
+		for (i = edit->curs_line - 1; i; i--)
+		    if (line_is_blank (edit, i))
+			break;
+	    }
+	} else {
+	    for (i = edit->curs_line - 1; i; i--)
+		if (line_is_blank (edit, i))
+		    break;
+	}
+    }
+    edit_move_up (edit, edit->curs_line - i, scroll);
+}
+
+/* move i lines */
+static void edit_move_down (WEdit * edit, int i, int scroll)
+{
+    long p, l = edit->total_lines - edit->curs_line;
+
+    if (i > l)
+	i = l;
+    if (i) {
+	if (i > 1)
+	    edit->force |= REDRAW_PAGE;
+	if (scroll)
+	    edit_scroll_downward (edit, i);
+	p = edit_bol (edit, edit->curs1);
+	edit_cursor_move (edit, (p = edit_move_forward (edit, p, i, 0)) - edit->curs1);
+	edit_move_to_prev_col (edit, p);
+
+	edit->search_start = edit->curs1;
+	edit->found_len = 0;
+    }
+}
+
+/* moves down until a blank line is reached, or until just
+   before a non-blank line is reached */
+static void edit_move_down_paragraph (WEdit * edit, int scroll)
+{
+    int i;
+    if (edit->curs_line >= edit->total_lines - 1) {
+	i = edit->total_lines;
+    } else {
+	if (line_is_blank (edit, edit->curs_line)) {
+	    if (line_is_blank (edit, edit->curs_line + 1)) {
+		for (i = edit->curs_line + 1; i; i++)
+		    if (!line_is_blank (edit, i) || i > edit->total_lines) {
+			i--;
+			break;
+		    }
+	    } else {
+		for (i = edit->curs_line + 1; i; i++)
+		    if (line_is_blank (edit, i) || i >= edit->total_lines)
+			break;
+	    }
+	} else {
+	    for (i = edit->curs_line + 1; i; i++)
+		if (line_is_blank (edit, i) || i >= edit->total_lines)
+		    break;
+	}
+    }
+    edit_move_down (edit, i - edit->curs_line, scroll);
+}
+
+static void edit_begin_page (WEdit *edit)
+{
+    edit_update_curs_row (edit);
+    edit_move_up (edit, edit->curs_row, 0);
+}
+
+static void edit_end_page (WEdit *edit)
+{
+    edit_update_curs_row (edit);
+    edit_move_down (edit, edit->num_widget_lines - edit->curs_row - 1, 0);
+}
+
+
+/* goto beginning of text */
+static void edit_move_to_top (WEdit * edit)
+{
+    if (edit->curs_line) {
+	edit_cursor_move (edit, -edit->curs1);
+	edit_move_to_prev_col (edit, 0);
+	edit->force |= REDRAW_PAGE;
+	edit->search_start = 0;
+	edit_update_curs_row(edit);
+    }
+}
+
+
+/* goto end of text */
+static void edit_move_to_bottom (WEdit * edit)
+{
+    if (edit->curs_line < edit->total_lines) {
+	edit_cursor_move (edit, edit->curs2);
+	edit->start_display = edit->last_byte;
+	edit->start_line = edit->total_lines;
+	edit_update_curs_row(edit);
+	edit_scroll_upward (edit, edit->num_widget_lines - 1);
+	edit->force |= REDRAW_PAGE;
+    }
+}
+
+/* goto beginning of line */
+static void edit_cursor_to_bol (WEdit * edit)
+{
+    edit_cursor_move (edit, edit_bol (edit, edit->curs1) - edit->curs1);
+    edit->search_start = edit->curs1;
+    edit->prev_col = edit_get_col (edit);
+}
+
+/* goto end of line */
+static void edit_cursor_to_eol (WEdit * edit)
+{
+    edit_cursor_move (edit, edit_eol (edit, edit->curs1) - edit->curs1);
+    edit->search_start = edit->curs1;
+    edit->prev_col = edit_get_col (edit);
+}
+
+/* move cursor to line 'line' */
+void edit_move_to_line (WEdit * e, long line)
+{
+    if(line < e->curs_line)
+	edit_move_up (e, e->curs_line - line, 0);
+    else
+	edit_move_down (e, line - e->curs_line, 0);
+    edit_scroll_screen_over_cursor (e);
+}
+
+/* scroll window so that first visible line is 'line' */
+void edit_move_display (WEdit * e, long line)
+{
+    if(line < e->start_line)
+	edit_scroll_upward (e, e->start_line - line);
+    else
+	edit_scroll_downward (e, line - e->start_line);
+}
+
+/* save markers onto undo stack */
+void edit_push_markers (WEdit * edit)
+{
+    edit_push_action (edit, MARK_1 + edit->mark1);
+    edit_push_action (edit, MARK_2 + edit->mark2);
+}
+
+void free_selections (void)
+{
+    int i;
+    for (i = 0; i < NUM_SELECTION_HISTORY; i++)
+	if (selection_history[i].text) {
+	    free (selection_history[i].text);
+	    selection_history[i].text = 0;
+	    selection_history[i].len = 0;
+	}
+    current_selection = 0;
+}
+
+/* return -1 on nothing to store or error, zero otherwise */
+void edit_get_selection (WEdit * edit)
+{
+    long start_mark, end_mark;
+    if (eval_marks (edit, &start_mark, &end_mark))
+	return;
+    if (selection_history[current_selection].len < 4096)	/* large selections should not be held -- to save memory */
+	current_selection = (current_selection + 1) % NUM_SELECTION_HISTORY;
+    selection_history[current_selection].len = end_mark - start_mark;
+    if (selection_history[current_selection].text)
+	free (selection_history[current_selection].text);
+    selection_history[current_selection].text = malloc (selection_history[current_selection].len + 1);
+    if (!selection_history[current_selection].text) {
+	selection_history[current_selection].text = malloc (1);
+	*selection_history[current_selection].text = 0;
+	selection_history[current_selection].len = 0;
+    } else {
+	unsigned char *p = selection_history[current_selection].text;
+	for (; start_mark < end_mark; start_mark++)
+	    *p++ = edit_get_byte (edit, start_mark);
+	*p = 0;
+    }
+    selection.text = selection_history[current_selection].text;
+    selection.len = selection_history[current_selection].len;
+}
+
+void edit_set_markers (WEdit * edit, long m1, long m2, int c1, int c2)
+{
+    edit->mark1 = m1;
+    edit->mark2 = m2;
+    edit->column1 = c1;
+    edit->column2 = c2;
+}
+
+
+/* highlight marker toggle */
+void edit_mark_cmd (WEdit * edit, int unmark)
+{
+    edit_push_markers (edit);
+    if (unmark) {
+	edit_set_markers (edit, 0, 0, 0, 0);
+	edit->force |= REDRAW_PAGE;
+    } else {
+	if (edit->mark2 >= 0) {
+	    edit_set_markers (edit, edit->curs1, -1, edit->curs_col, edit->curs_col);
+	    edit->force |= REDRAW_PAGE;
+	} else
+	    edit_set_markers (edit, edit->mark1, edit->curs1, edit->column1, edit->curs_col);
+    }
+}
+
+int my_type_of (int c)
+{
+    if (c < ' ' && c > 0)
+	return 1;
+    if (strchr ("+_-.", c))
+	if (strchr (option_whole_chars_move, c))
+	    return 3;
+    if (!strcasechr (option_whole_chars_move, c))
+	return 2;
+    if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c >= 160)
+	return 3;
+    return c;
+}
+
+void edit_left_word_move (WEdit * edit)
+{
+    do {
+	edit_cursor_move (edit, -1);
+	if (!edit->curs1)
+	    break;
+    } while (my_type_of (edit_get_byte (edit, edit->curs1))
+	     ==
+	     my_type_of (edit_get_byte (edit, edit->curs1 - 1)));
+}
+
+static void edit_left_word_move_cmd (WEdit * edit)
+{
+    edit_left_word_move (edit);
+    if (strchr (option_whole_chars_move, ' '))
+	if (strchr ("\t ", edit_get_byte (edit, edit->curs1)))
+	    edit_left_word_move (edit);
+    edit->force |= REDRAW_PAGE;
+}
+
+void edit_right_word_move (WEdit * edit)
+{
+    do {
+	edit_cursor_move (edit, 1);
+	if (edit->curs1 >= edit->last_byte)
+	    break;
+    } while (my_type_of (edit_get_byte (edit, edit->curs1 - 1))
+	     ==
+	     my_type_of (edit_get_byte (edit, edit->curs1)));
+}
+
+static void edit_right_word_move_cmd (WEdit * edit)
+{
+    edit_right_word_move (edit);
+    if (strchr (option_whole_chars_move, ' '))
+	if (strchr ("\t ", edit_get_byte (edit, edit->curs1)))
+	    edit_right_word_move (edit);
+    edit->force |= REDRAW_PAGE;
+}
+
+
+static void edit_right_delete_word (WEdit * edit)
+{
+    int c;
+    do {
+	c = edit_delete (edit);
+    } while (my_type_of (c) == my_type_of (edit_get_byte (edit, edit->curs1)));
+}
+
+static void edit_left_delete_word (WEdit * edit)
+{
+    int c;
+    do {
+	c = edit_backspace (edit);
+    } while (my_type_of (c) == my_type_of (edit_get_byte (edit, edit->curs1 - 1)));
+}
+
+extern int column_highlighting;
+
+/*
+   the start column position is not recorded, and hence does not
+   undo as it happed. But who would notice.
+ */
+void edit_do_undo (WEdit * edit)
+{
+    long ac;
+    long count = 0;
+
+    push_action_disabled = 1;	/* don't record undo's onto undo stack! */
+
+    while ((ac = pop_action (edit)) < KEY_PRESS) {
+	switch ((int) ac) {
+	case STACK_BOTTOM:
+	    goto done_undo;
+	case CURS_RIGHT:
+	    edit_cursor_move (edit, 1);
+	    break;
+	case CURS_LEFT:
+	    edit_cursor_move (edit, -1);
+	    break;
+	case BACKSPACE:
+	    edit_backspace (edit);
+	    break;
+	case DELETE:
+	    edit_delete (edit);
+	    break;
+	case COLUMN_ON:
+	    column_highlighting = 1;
+	    break;
+	case COLUMN_OFF:
+	    column_highlighting = 0;
+	    break;
+	}
+	if (ac >= 256 && ac < 512)
+	    edit_insert_ahead (edit, ac - 256);
+	if (ac >= 0 && ac < 256)
+	    edit_insert (edit, ac);
+
+	if (ac >= MARK_1 - 2 && ac < MARK_2 - 2) {
+	    edit->mark1 = ac - MARK_1;
+	    edit->column1 = edit_move_forward3 (edit, edit_bol (edit, edit->mark1), 0, edit->mark1);
+	} else if (ac >= MARK_2 - 2 && ac < KEY_PRESS) {
+	    edit->mark2 = ac - MARK_2;
+	    edit->column2 = edit_move_forward3 (edit, edit_bol (edit, edit->mark2), 0, edit->mark2);
+	}
+	if (count++)
+	    edit->force |= REDRAW_PAGE;		/* more than one pop usually means something big */
+    }
+
+    if (edit->start_display > ac - KEY_PRESS) {
+	edit->start_line -= edit_count_lines (edit, ac - KEY_PRESS, edit->start_display);
+	edit->force |= REDRAW_PAGE;
+    } else if (edit->start_display < ac - KEY_PRESS) {
+	edit->start_line += edit_count_lines (edit, edit->start_display, ac - KEY_PRESS);
+	edit->force |= REDRAW_PAGE;
+    }
+    edit->start_display = ac - KEY_PRESS;	/* see push and pop above */
+    edit_update_curs_row (edit);
+
+  done_undo:;
+    push_action_disabled = 0;
+}
+
+static void edit_delete_to_line_end (WEdit * edit)
+{
+    for (;;) {
+	if (edit_get_byte (edit, edit->curs1) == '\n')
+	    break;
+	if (!edit->curs2)
+	    break;
+	edit_delete (edit);
+    }
+}
+
+static void edit_delete_to_line_begin (WEdit * edit)
+{
+    for (;;) {
+	if (edit_get_byte (edit, edit->curs1 - 1) == '\n')
+	    break;
+	if (!edit->curs1)
+	    break;
+	edit_backspace (edit);
+    }
+}
+
+void edit_delete_line (WEdit * edit)
+{
+    int c;
+    do {
+	c = edit_delete (edit);
+    } while (c != '\n' && c);
+    do {
+	c = edit_backspace (edit);
+    } while (c != '\n' && c);
+    if (c)
+	edit_insert (edit, '\n');
+}
+
+static void insert_spaces_tab (WEdit * edit)
+{
+    int i = option_tab_spacing;
+    while (i--)
+	edit_insert (edit, ' ');
+}
+
+static int is_aligned_on_a_tab (WEdit * edit)
+{
+    edit_update_curs_col (edit);
+    if ((edit->curs_col % (TAB_SIZE * space_width)) && edit->curs_col % (TAB_SIZE * space_width) != (HALF_TAB_SIZE * space_width))
+	return 0;		/* not alligned on a tab */
+    return 1;
+}
+
+static int right_of_four_spaces (WEdit *edit)
+{
+    int i, ch = 0;
+    for (i = 1; i <= HALF_TAB_SIZE; i++)
+	ch |= edit_get_byte (edit, edit->curs1 - i);
+    if (ch == ' ')
+	return is_aligned_on_a_tab (edit);
+    return 0;
+}
+
+static int left_of_four_spaces (WEdit *edit)
+{
+    int i, ch = 0;
+    for (i = 0; i < HALF_TAB_SIZE; i++)
+	ch |= edit_get_byte (edit, edit->curs1 + i);
+    if (ch == ' ')
+	return is_aligned_on_a_tab (edit);
+    return 0;
+}
+
+int edit_indent_width (WEdit * edit, long p)
+{
+    long q = p;
+    while (strchr ("\t ", edit_get_byte (edit, q)) && q < edit->last_byte - 1)	/* move to the end of the leading whitespace of the line */
+	q++;
+    return edit_move_forward3 (edit, p, 0, q);	/* count the number of columns of indentation */
+}
+
+void edit_insert_indent (WEdit * edit, int indent)
+{
+#ifndef MIDNIGHT
+    indent /= space_width;
+#endif
+    if (!option_fill_tabs_with_spaces) {
+	while (indent >= TAB_SIZE) {
+	    edit_insert (edit, '\t');
+	    indent -= TAB_SIZE;
+	}
+    }
+    while (indent--)
+	edit_insert (edit, ' ');
+}
+
+static void edit_auto_indent (WEdit * edit, int always)
+{
+    long p;
+    int indent;
+    p = edit->curs1;
+    while (strchr ("\t\n\r ", edit_get_byte (edit, p - 1)) && p > 0)	/* move back/up to a line with text */
+	p--;
+    indent = edit_indent_width (edit, edit_bol (edit, p));
+    if (edit->curs_col < indent)
+	indent = edit->curs_col;
+    edit_insert_indent (edit, indent);
+}
+
+static void edit_double_newline (WEdit * edit)
+{
+    edit_insert (edit, '\n');
+    if (edit_get_byte (edit, edit->curs1) == '\n')
+	return;
+    if (edit_get_byte (edit, edit->curs1 - 2) == '\n')
+	return;
+    edit->force |= REDRAW_PAGE;
+    edit_insert (edit, '\n');
+}
+
+static void edit_tab_cmd (WEdit * edit)
+{
+    int i;
+
+    if (option_fake_half_tabs) {
+	if (is_in_indent (edit)) {
+	    /*insert a half tab (usually four spaces) unless there is a
+	       half tab already behind, then delete it and insert a 
+	       full tab. */
+	    if (right_of_four_spaces (edit)) {
+		for (i = 1; i <= HALF_TAB_SIZE; i++)
+		    edit_backspace (edit);
+		if (option_fill_tabs_with_spaces) {
+		    insert_spaces_tab (edit);
+		} else {
+		    edit_insert (edit, '\t');
+		}
+	    } else {
+		for (i = 1; i <= HALF_TAB_SIZE; i++)
+		    edit_insert (edit, ' ');
+	    }
+	    return;
+	}
+    }
+    if (option_fill_tabs_with_spaces) {
+	insert_spaces_tab (edit);
+    } else {
+	edit_insert (edit, '\t');
+    }
+    return;
+}
+
+void format_paragraph (WEdit * edit, int force);
+
+static void check_and_wrap_line (WEdit * edit)
+{
+    int curs, c;
+    if (!option_typewriter_wrap)
+	return;
+    edit_update_curs_col (edit);
+#ifdef MIDNIGHT
+    if (edit->curs_col < option_word_wrap_line_length)
+#else
+    if (edit->curs_col < option_word_wrap_line_length * FONT_MEAN_WIDTH)
+#endif
+	return;
+    curs = edit->curs1;
+    for (;;) {
+	curs--;
+	c = edit_get_byte (edit, curs);
+	if (c == '\n' || curs <= 0) {
+	    edit_insert (edit, '\n');
+	    return;
+	}
+	if (c == ' ' || c == '\t') {
+	    int current = edit->curs1;
+	    edit_cursor_move (edit, curs - edit->curs1 + 1);
+	    edit_insert (edit, '\n');
+	    edit_cursor_move (edit, current - edit->curs1 + 1);
+	    return;
+	}
+    }
+}
+
+void edit_execute_macro (WEdit * edit, struct macro macro[], int n);
+
+/* either command or char_for_insertion must be passed as -1 */
+int edit_execute_cmd (WEdit * edit, int command, int char_for_insertion);
+
+#ifdef MIDNIGHT
+int edit_translate_key (WEdit * edit, unsigned int x_keycode, long x_key, int x_state, int *cmd, int *ch)
+{
+    int command = -1;
+    int char_for_insertion = -1;
+
+#include "edit_key_translator.c"
+
+    *cmd = command;
+    *ch = char_for_insertion;
+
+    if((command == -1 || command == 0) && char_for_insertion == -1)  /* unchanged, key has no function here */
+	return 0;
+    return 1;
+}
+#endif
+
+void edit_push_key_press (WEdit * edit)
+{
+    edit_push_action (edit, KEY_PRESS + edit->start_display);
+    if (edit->mark2 == -1)
+	edit_push_action (edit, MARK_1 + edit->mark1);
+}
+
+/* this find the matching bracket in either direction, and sets edit->bracket */
+void edit_find_bracket (WEdit * edit)
+{
+    if (option_find_bracket) {
+	const char *b = "{}{[][()(", *p;
+	static int last_bracket = -1;
+	int i = 1, a, inc = -1, c, d, n = 0, j = 0;
+	long q;
+
+	edit->bracket = -1;
+	c = edit_get_byte (edit, edit->curs1);
+	p = strchr (b, c);
+	edit_update_curs_row (edit);
+	if (p) {
+	    d = p[1];
+	    if (strchr ("{[(", c))
+		inc = 1;
+	    for (q = edit->curs1 + inc;; q += inc) {
+		if (q >= edit->last_byte || q < edit->start_display || j++ > 10000)
+		    break;
+		a = edit_get_byte (edit, q);
+		if (inc > 0 && a == '\n')
+		    n++;
+		if (n >= edit->num_widget_lines - edit->curs_row)	/* out of screen */
+		    break;
+		i += (a == c) - (a == d);
+		if (!i) {
+		    edit->bracket = q;
+		    break;
+		}
+	    }
+	}
+	if (last_bracket != edit->bracket)
+	    edit->force |= REDRAW_PAGE;
+	last_bracket = edit->bracket;
+    }
+}
+
+
+/* this executes a command as though the user initiated it through a key press. */
+/* callback with WIDGET_KEY as a message calls this after translating the key
+   press */
+/* this can be used to pass any command to the editor. Same as sendevent with
+   msg = WIDGET_COMMAND and par = command  except the screen wouldn't update */
+/* one of command or char_for_insertion must be passed as -1 */
+/* commands are executed, and char_for_insertion is inserted at the cursor */
+/* returns 0 if the command is a macro that was not found, 1 otherwise */
+int edit_execute_key_command (WEdit * edit, int command, int char_for_insertion)
+{
+    int r;
+    if (command == CK_Begin_Record_Macro) {
+	edit->macro_i = 0;
+	edit->force |= REDRAW_CHAR_ONLY | REDRAW_LINE;
+	return command;
+    }
+    if (command == CK_End_Record_Macro && edit->macro_i != -1) {
+	edit->force |= REDRAW_COMPLETELY;
+	edit_save_macro_cmd (edit, edit->macro, edit->macro_i);
+	edit->macro_i = -1;
+	return command;
+    }
+    if (edit->macro_i >= 0 && edit->macro_i < MAX_MACRO_LENGTH - 1) {
+	edit->macro[edit->macro_i].command = command;
+	edit->macro[edit->macro_i++].ch = char_for_insertion;
+    }
+/* record the beginning of a set of editing actions initiated by a key press */
+    if (command != CK_Undo)
+	edit_push_key_press (edit);
+
+    r = edit_execute_cmd (edit, command, char_for_insertion);
+#ifdef GTK
+    if (edit->stopped && edit->widget->destroy_me) {
+	(*edit->widget->destroy_me) (edit->widget->destroy_me_user_data);
+	return 0;
+    }
+#endif
+    if (column_highlighting)
+	edit->force |= REDRAW_PAGE;
+
+    return r;
+}
+
+#ifdef MIDNIGHT
+static const char *shell_cmd[] = SHELL_COMMANDS_i
+#else
+static void (*user_commamd) (WEdit *, int) = 0;
+void edit_set_user_command (void (*func) (WEdit *, int))
+{
+    user_commamd = func;
+}
+
+#endif
+
+void edit_mail_dialog (WEdit * edit);
+
+/* 
+   This executes a command at a lower level than macro recording.
+   It also does not push a key_press onto the undo stack. This means
+   that if it is called many times, a single undo command will undo
+   all of them. It also does not check for the Undo command.
+   Returns 0 if the command is a macro that was not found, 1
+   otherwise.
+ */
+int edit_execute_cmd (WEdit * edit, int command, int char_for_insertion)
+{
+    int result = 1;
+    edit->force |= REDRAW_LINE;
+    if (edit->found_len || column_highlighting)
+/* the next key press will unhighlight the found string, so update whole page */
+	edit->force |= REDRAW_PAGE;
+
+    if (command / 100 == 6) {	/* a highlight command like shift-arrow */
+	column_highlighting = 0;
+	if (!edit->highlight || (edit->mark2 != -1 && edit->mark1 != edit->mark2)) {
+	    edit_mark_cmd (edit, 1);	/* clear */
+	    edit_mark_cmd (edit, 0);	/* marking on */
+	}
+	edit->highlight = 1;
+    } else {			/* any other command */
+	if (edit->highlight)
+	    edit_mark_cmd (edit, 0);	/* clear */
+	edit->highlight = 0;
+    }
+
+/* first check for undo */
+    if (command == CK_Undo) {
+	edit_do_undo (edit);
+	edit->found_len = 0;
+	edit->prev_col = edit_get_col (edit);
+	edit->search_start = edit->curs1;
+	return 1;
+    }
+/* An ordinary key press */
+    if (char_for_insertion >= 0) {
+	if (edit->overwrite) {
+	    if (edit_get_byte (edit, edit->curs1) != '\n')
+		edit_delete (edit);
+	}
+	edit_insert (edit, char_for_insertion);
+	if (option_auto_para_formatting) {
+	    format_paragraph (edit, 0);
+	    edit->force |= REDRAW_PAGE;
+	} else
+	    check_and_wrap_line (edit);
+	edit->found_len = 0;
+	edit->prev_col = edit_get_col (edit);
+	edit->search_start = edit->curs1;
+	edit_find_bracket (edit);
+	return 1;
+    }
+    switch (command) {
+    case CK_Begin_Page:
+    case CK_End_Page:
+    case CK_Begin_Page_Highlight:
+    case CK_End_Page_Highlight:
+    case CK_Word_Left:
+    case CK_Word_Right:
+    case CK_Up:
+    case CK_Down:
+    case CK_Word_Left_Highlight:
+    case CK_Word_Right_Highlight:
+    case CK_Up_Highlight:
+    case CK_Down_Highlight:
+	if (edit->mark2 == -1)
+	    break;		/*marking is following the cursor: may need to highlight a whole line */
+    case CK_Left:
+    case CK_Right:
+    case CK_Left_Highlight:
+    case CK_Right_Highlight:
+	edit->force |= REDRAW_CHAR_ONLY;
+    }
+
+/* basic cursor key commands */
+    switch (command) {
+    case CK_BackSpace:
+	if (option_backspace_through_tabs && is_in_indent (edit)) {
+	    while (edit_get_byte (edit, edit->curs1 - 1) != '\n'
+		   && edit->curs1 > 0)
+		edit_backspace (edit);
+	    break;
+	} else {
+	    if (option_fake_half_tabs) {
+		int i;
+		if (is_in_indent (edit) && right_of_four_spaces (edit)) {
+		    for (i = 0; i < HALF_TAB_SIZE; i++)
+			edit_backspace (edit);
+		    break;
+		}
+	    }
+	}
+	edit_backspace (edit);
+	break;
+    case CK_Delete:
+	if (option_fake_half_tabs) {
+	    int i;
+	    if (is_in_indent (edit) && left_of_four_spaces (edit)) {
+		for (i = 1; i <= HALF_TAB_SIZE; i++)
+		    edit_delete (edit);
+		break;
+	    }
+	}
+	edit_delete (edit);
+	break;
+    case CK_Delete_Word_Left:
+	edit_left_delete_word (edit);
+	break;
+    case CK_Delete_Word_Right:
+	edit_right_delete_word (edit);
+	break;
+    case CK_Delete_Line:
+	edit_delete_line (edit);
+	break;
+    case CK_Delete_To_Line_End:
+	edit_delete_to_line_end (edit);
+	break;
+    case CK_Delete_To_Line_Begin:
+	edit_delete_to_line_begin (edit);
+	break;
+    case CK_Enter:
+	if (option_auto_para_formatting) {
+	    edit_double_newline (edit);
+	    if (option_return_does_auto_indent)
+		edit_auto_indent (edit, 0);
+	    format_paragraph (edit, 0);
+	} else if (option_return_does_auto_indent) {
+	    edit_insert (edit, '\n');
+	    edit_auto_indent (edit, 0);
+	} else {
+	    edit_insert (edit, '\n');
+	}
+	break;
+    case CK_Return:
+	edit_insert (edit, '\n');
+	break;
+
+    case CK_Page_Up:
+    case CK_Page_Up_Highlight:
+	edit_move_up (edit, edit->num_widget_lines - 1, 1);
+	break;
+    case CK_Page_Down:
+    case CK_Page_Down_Highlight:
+	edit_move_down (edit, edit->num_widget_lines - 1, 1);
+	break;
+    case CK_Left:
+    case CK_Left_Highlight:
+	if (option_fake_half_tabs) {
+	    if (is_in_indent (edit) && right_of_four_spaces (edit)) {
+		edit_cursor_move (edit, -HALF_TAB_SIZE);
+		edit->force &= (0xFFF - REDRAW_CHAR_ONLY);
+		break;
+	    }
+	}
+	edit_cursor_move (edit, -1);
+	break;
+    case CK_Right:
+    case CK_Right_Highlight:
+	if (option_fake_half_tabs) {
+	    if (is_in_indent (edit) && left_of_four_spaces (edit)) {
+		edit_cursor_move (edit, HALF_TAB_SIZE);
+		edit->force &= (0xFFF - REDRAW_CHAR_ONLY);
+		break;
+	    }
+	}
+	edit_cursor_move (edit, 1);
+	break;
+    case CK_Begin_Page:
+    case CK_Begin_Page_Highlight:
+	edit_begin_page (edit);
+	break;
+    case CK_End_Page:
+    case CK_End_Page_Highlight:
+	edit_end_page (edit);
+	break;
+    case CK_Word_Left:
+    case CK_Word_Left_Highlight:
+	edit_left_word_move_cmd (edit);
+	break;
+    case CK_Word_Right:
+    case CK_Word_Right_Highlight:
+	edit_right_word_move_cmd (edit);
+	break;
+    case CK_Up:
+    case CK_Up_Highlight:
+	edit_move_up (edit, 1, 0);
+	break;
+    case CK_Down:
+    case CK_Down_Highlight:
+	edit_move_down (edit, 1, 0);
+	break;
+    case CK_Paragraph_Up:
+    case CK_Paragraph_Up_Highlight:
+	edit_move_up_paragraph (edit, 0);
+	break;
+    case CK_Paragraph_Down:
+    case CK_Paragraph_Down_Highlight:
+	edit_move_down_paragraph (edit, 0);
+	break;
+    case CK_Scroll_Up:
+    case CK_Scroll_Up_Highlight:
+	edit_move_up (edit, 1, 1);
+	break;
+    case CK_Scroll_Down:
+    case CK_Scroll_Down_Highlight:
+	edit_move_down (edit, 1, 1);
+	break;
+    case CK_Home:
+    case CK_Home_Highlight:
+	edit_cursor_to_bol (edit);
+	break;
+    case CK_End:
+    case CK_End_Highlight:
+	edit_cursor_to_eol (edit);
+	break;
+
+    case CK_Tab:
+	edit_tab_cmd (edit);
+	if (option_auto_para_formatting) {
+	    format_paragraph (edit, 0);
+	    edit->force |= REDRAW_PAGE;
+	} else
+	    check_and_wrap_line (edit);
+	break;
+
+    case CK_Toggle_Insert:
+	edit->overwrite = (edit->overwrite == 0);
+#ifndef MIDNIGHT
+#ifdef GTK
+/* *** */
+#else
+	CSetCursorColor (edit->overwrite ? color_palette (24) : color_palette (19));
+#endif
+#endif
+	break;
+
+    case CK_Mark:
+	if (edit->mark2 >= 0) {
+	    if (column_highlighting)
+		edit_push_action (edit, COLUMN_ON);
+	    column_highlighting = 0;
+	}
+	edit_mark_cmd (edit, 0);
+	break;
+    case CK_Column_Mark:
+	if (!column_highlighting)
+	    edit_push_action (edit, COLUMN_OFF);
+	column_highlighting = 1;
+	edit_mark_cmd (edit, 0);
+	break;
+    case CK_Unmark:
+	if (column_highlighting)
+	    edit_push_action (edit, COLUMN_ON);
+	column_highlighting = 0;
+	edit_mark_cmd (edit, 1);
+	break;
+
+    case CK_Beginning_Of_Text:
+    case CK_Beginning_Of_Text_Highlight:
+	edit_move_to_top (edit);
+	break;
+    case CK_End_Of_Text:
+    case CK_End_Of_Text_Highlight:
+	edit_move_to_bottom (edit);
+	break;
+
+    case CK_Copy:
+	edit_block_copy_cmd (edit);
+	break;
+    case CK_Remove:
+	edit_block_delete_cmd (edit);
+	break;
+    case CK_Move:
+	edit_block_move_cmd (edit);
+	break;
+
+    case CK_XStore:
+	edit_copy_to_X_buf_cmd (edit);
+	break;
+    case CK_XCut:
+	edit_cut_to_X_buf_cmd (edit);
+	break;
+    case CK_XPaste:
+	edit_paste_from_X_buf_cmd (edit);
+	break;
+    case CK_Selection_History:
+	edit_paste_from_history (edit);
+	break;
+
+    case CK_Save_As:
+#ifndef MIDNIGHT
+/*	if (COptionsOf (edit->widget) & EDITOR_NO_FILE) */
+	if (edit->widget->options & EDITOR_NO_FILE)
+	    break;
+#endif
+	edit_save_as_cmd (edit);
+	break;
+    case CK_Save:
+#ifndef MIDNIGHT
+	if (COptionsOf (edit->widget) & EDITOR_NO_FILE)
+	    break;
+#endif
+	edit_save_confirm_cmd (edit);
+	break;
+    case CK_Load:
+#ifndef MIDNIGHT
+	if (COptionsOf (edit->widget) & EDITOR_NO_FILE)
+	    break;
+#endif
+	edit_load_cmd (edit);
+	break;
+    case CK_Save_Block:
+	edit_save_block_cmd (edit);
+	break;
+    case CK_Insert_File:
+	edit_insert_file_cmd (edit);
+	break;
+
+    case CK_Find:
+	edit_search_cmd (edit, 0);
+	break;
+    case CK_Find_Again:
+	edit_search_cmd (edit, 1);
+	break;
+    case CK_Replace:
+	edit_replace_cmd (edit, 0);
+	break;
+    case CK_Replace_Again:
+	edit_replace_cmd (edit, 1);
+	break;
+
+    case CK_Exit:
+	edit_quit_cmd (edit);
+	break;
+    case CK_New:
+	edit_new_cmd (edit);
+	break;
+
+    case CK_Help:
+	edit_help_cmd (edit);
+	break;
+
+    case CK_Refresh:
+	edit_refresh_cmd (edit);
+	break;
+
+    case CK_Date:{
+	    time_t t;
+	    time (&t);
+	    edit_printf (edit, ctime (&t));
+	    edit->force |= REDRAW_PAGE;
+	    break;
+	}
+    case CK_Goto:
+	edit_goto_cmd (edit);
+	break;
+    case CK_Paragraph_Format:
+	format_paragraph (edit, 1);
+	edit->force |= REDRAW_PAGE;
+	break;
+    case CK_Delete_Macro:
+	edit_delete_macro_cmd (edit);
+	break;
+#ifdef MIDNIGHT
+    case CK_Sort:
+	edit_sort_cmd (edit);
+	break;
+    case CK_Mail:
+	edit_mail_dialog (edit);
+	break;
+#endif
+
+/* These commands are not handled and must be handled by the user application */
+#ifndef MIDNIGHT
+    case CK_Sort:
+    case CK_Mail:
+#endif
+    case CK_Complete:
+    case CK_Cancel:
+    case CK_Save_Desktop:
+    case CK_New_Window:
+    case CK_Cycle:
+    case CK_Save_And_Quit:
+    case CK_Check_Save_And_Quit:
+    case CK_Run_Another:
+	result = 0;
+	break;
+    case CK_Menu:
+#ifdef GTK
+	if (edit->widget->menubar)
+	    gtk_menu_popup (GTK_MENU(
+		(GTK_MENU_ITEM (g_list_nth_data (GTK_MENU_BAR (edit->widget->menubar)->menu_shell.children, 0)))->submenu
+	    ), 0, 0, 0, 0, 1, 0);
+	result = 1;
+#else
+	result = 0;
+#endif
+	break;
+    }
+
+#ifdef MIDNIGHT
+/* CK_Pipe_Block */
+    if ((command / 1000) == 1)	/* a shell command */
+	edit_block_process_cmd (edit, shell_cmd[command - 1000], 1);
+#else
+    if ((command / 1000) == 1)	/* a user defined command */
+	if (user_commamd)
+	    (*user_commamd) (edit, command - 1000);
+#endif
+
+    if (command > CK_Macro (0) && command <= CK_Last_Macro) {	/* a macro command */
+	struct macro m[MAX_MACRO_LENGTH];
+	int nm;
+	if ((result = edit_load_macro_cmd (edit, m, &nm, command - 2000)))
+	    edit_execute_macro (edit, m, nm);
+    }
+/* keys which must set the col position, and the search vars */
+    switch (command) {
+    case CK_Find:
+    case CK_Find_Again:
+    case CK_Replace:
+    case CK_Replace_Again:
+	edit->prev_col = edit_get_col (edit);
+	return 1;
+	break;
+    case CK_Up:
+    case CK_Up_Highlight:
+    case CK_Down:
+    case CK_Down_Highlight:
+    case CK_Page_Up:
+    case CK_Page_Up_Highlight:
+    case CK_Page_Down:
+    case CK_Page_Down_Highlight:
+    case CK_Beginning_Of_Text:
+    case CK_Beginning_Of_Text_Highlight:
+    case CK_End_Of_Text:
+    case CK_End_Of_Text_Highlight:
+    case CK_Paragraph_Up:
+    case CK_Paragraph_Up_Highlight:
+    case CK_Paragraph_Down:
+    case CK_Paragraph_Down_Highlight:
+    case CK_Scroll_Up:
+    case CK_Scroll_Up_Highlight:
+    case CK_Scroll_Down:
+    case CK_Scroll_Down_Highlight:
+	edit->search_start = edit->curs1;
+	edit->found_len = 0;
+	edit_find_bracket (edit);
+	return 1;
+	break;
+    default:
+	edit->found_len = 0;
+	edit->prev_col = edit_get_col (edit);
+	edit->search_start = edit->curs1;
+    }
+    edit_find_bracket (edit);
+
+    if (option_auto_para_formatting) {
+	switch (command) {
+	case CK_BackSpace:
+	case CK_Delete:
+	case CK_Delete_Word_Left:
+	case CK_Delete_Word_Right:
+	case CK_Delete_To_Line_End:
+	case CK_Delete_To_Line_Begin:
+	    format_paragraph (edit, 0);
+	    edit->force |= REDRAW_PAGE;
+	}
+    }
+    return result;
+}
+
+
+/* either command or char_for_insertion must be passed as -1 */
+/* returns 0 if command is a macro that was not found, 1 otherwise */
+int edit_execute_command (WEdit * edit, int command, int char_for_insertion)
+{
+    int r;
+    r = edit_execute_cmd (edit, command, char_for_insertion);
+    edit_update_screen (edit);
+    return r;
+}
+
+void edit_execute_macro (WEdit * edit, struct macro macro[], int n)
+{
+    int i = 0;
+    edit->force |= REDRAW_PAGE;
+    for (; i < n; i++) {
+	edit_execute_cmd (edit, macro[i].command, macro[i].ch);
+    }
+    edit_update_screen (edit);
+}
+

+ 835 - 0
edit/edit.h

@@ -0,0 +1,835 @@
+#ifndef __EDIT_H
+#define __EDIT_H
+
+#ifdef MIDNIGHT
+
+#ifdef HAVE_SLANG
+#define HAVE_SYNTAXH 1
+#endif
+
+#    include <stdio.h>
+#    include <stdarg.h>
+#    include <sys/types.h>
+#    ifdef HAVE_UNISTD_H
+#    	 include <unistd.h>
+#    endif
+#    include <string.h>
+#    include "src/tty.h"
+#    include <sys/stat.h>
+#    include <errno.h>
+     
+#    ifdef HAVE_FCNTL_H
+#        include <fcntl.h>
+#    endif
+     
+#    include <stdlib.h>
+#    include <malloc.h>
+
+#else       /* ! MIDNIGHT */
+
+#    include "global.h"
+#    include <stdio.h>
+#    include <stdarg.h>
+#    include <sys/types.h>
+     
+#    	 ifdef HAVE_UNISTD_H
+#    	     include <unistd.h>
+#    	 endif
+     
+#ifdef GTK
+#    include <string.h>
+#else
+#    include <my_string.h>
+#endif
+#    include <sys/stat.h>
+     
+#    ifdef HAVE_FCNTL_H
+#    	 include <fcntl.h>
+#    endif
+     
+#    include <stdlib.h>
+#    include <stdarg.h>
+
+#    if TIME_WITH_SYS_TIME
+#    	 include <sys/time.h>
+#    	 include <time.h>
+#    else
+#    	 if HAVE_SYS_TIME_H
+#    	     include <sys/time.h>
+#    	 else
+#    	     include <time.h>
+#    	 endif
+#    endif
+ 
+#    include "regex.h"
+
+#endif
+
+#ifndef MIDNIGHT
+
+#    include <signal.h>
+#    include <X11/Xlib.h>
+#    include <X11/Xutil.h>
+#    include <X11/Xresource.h>
+#    include "lkeysym.h"
+#ifndef GTK
+#    include "coolwidget.h"
+#    include "app_glob.c"
+#    include "coollocal.h"
+#    include "stringtools.h"
+#else
+#    include "gtk/gtk.h"
+#    include "gdk/gdkprivate.h"
+#    include "gdk/gdk.h"
+#    include "gtkedit.h"
+#    include "editcmddef.h"
+#    ifdef _
+#        define _(x) x
+#        define N_(x) x
+#    endif
+#endif
+
+#else
+
+#    include "src/main.h"		/* for char *shell */
+#    include "src/mad.h"
+#    include "src/dlg.h"
+#    include "src/widget.h"
+#    include "src/color.h"
+#    include "src/dialog.h"
+#    include "src/mouse.h"
+#    include "src/global.h"
+#    include "src/help.h"
+#    include "src/key.h"
+#    include "src/wtools.h"		/* for QuickWidgets */
+#    include "src/win.h"
+#    include "vfs/vfs.h"
+#    include "src/menu.h"
+#    include "src/regex.h"
+#    define WANT_WIDGETS
+     
+#    define WIDGET_COMMAND (WIDGET_USER + 10)
+#    define N_menus 5
+
+#endif
+
+#ifdef GTK
+/* unistd.h defines _POSIX_VERSION on POSIX.1 systems. */
+#if defined(HAVE_DIRENT_H) || defined(_POSIX_VERSION)
+#   include <dirent.h>
+#   define NLENGTH(dirent) (strlen ((dirent)->d_name))
+#else
+#   define dirent direct
+#   define NLENGTH(dirent) ((dirent)->d_namlen)
+
+#   ifdef HAVE_SYS_NDIR_H
+#       include <sys/ndir.h>
+#   endif /* HAVE_SYS_NDIR_H */
+
+#   ifdef HAVE_SYS_DIR_H
+#       include <sys/dir.h>
+#   endif /* HAVE_SYS_DIR_H */
+
+#   ifdef HAVE_NDIR_H
+#       include <ndir.h>
+#   endif /* HAVE_NDIR_H */
+#endif /* not (HAVE_DIRENT_H or _POSIX_VERSION) */
+#define _(x) x
+#define N_(x) x
+#include "vfs/vfs.h"
+#include "intl/libgettext.h"
+#    define CDisplay gdk_display
+#    define CRoot gdk_root_parent
+#    define Window GtkEdit *
+#endif
+
+#define SEARCH_DIALOG_OPTION_NO_SCANF	1
+#define SEARCH_DIALOG_OPTION_NO_REGEX	2
+#define SEARCH_DIALOG_OPTION_NO_CASE	4
+#define SEARCH_DIALOG_OPTION_BACKWARDS	8
+
+#define SYNTAX_FILE "/.cedit/syntax"
+#define CLIP_FILE "/.cedit/cooledit.clip"
+#define MACRO_FILE "/.cedit/cooledit.macros"
+#define BLOCK_FILE "/.cedit/cooledit.block"
+#define ERROR_FILE "/.cedit/cooledit.error"
+#define TEMP_FILE "/.cedit/cooledit.temp"
+#define SCRIPT_FILE "/.cedit/cooledit.script"
+#define EDIT_DIR "/.cedit"
+
+#define EDIT_KEY_EMULATION_NORMAL 0
+#define EDIT_KEY_EMULATION_EMACS  1
+
+#define REDRAW_LINE          (1 << 0)
+#define REDRAW_LINE_ABOVE    (1 << 1)
+#define REDRAW_LINE_BELOW    (1 << 2)
+#define REDRAW_AFTER_CURSOR  (1 << 3)
+#define REDRAW_BEFORE_CURSOR (1 << 4)
+#define REDRAW_PAGE          (1 << 5)
+#define REDRAW_IN_BOUNDS     (1 << 6)
+#define REDRAW_CHAR_ONLY     (1 << 7)
+#define REDRAW_COMPLETELY    (1 << 8)
+
+#define MOD_ABNORMAL		(1 << 0)
+#define MOD_UNDERLINED		(1 << 1)
+#define MOD_BOLD		(1 << 2)
+#define MOD_HIGHLIGHTED		(1 << 3)
+#define MOD_MARKED		(1 << 4)
+#define MOD_ITALIC		(1 << 5)
+#define MOD_CURSOR		(1 << 6)
+#define MOD_INVERSE		(1 << 7)
+
+#ifndef MIDNIGHT
+#    ifdef GTK
+#        define EDIT_TEXT_HORIZONTAL_OFFSET 0
+#        define EDIT_TEXT_VERTICAL_OFFSET 0
+#    else
+#        define EDIT_TEXT_HORIZONTAL_OFFSET 4
+#        define EDIT_TEXT_VERTICAL_OFFSET 3
+#    endif
+#else
+#    define EDIT_TEXT_HORIZONTAL_OFFSET 0
+#    define EDIT_TEXT_VERTICAL_OFFSET 1
+#    define FONT_OFFSET_X 0
+#    define FONT_OFFSET_Y 0
+#endif
+
+#define EDIT_RIGHT_EXTREME option_edit_right_extreme
+#define EDIT_LEFT_EXTREME option_edit_left_extreme
+#define EDIT_TOP_EXTREME option_edit_top_extreme
+#define EDIT_BOTTOM_EXTREME option_edit_bottom_extreme
+
+#define MAX_MACRO_LENGTH 1024
+
+/*there are a maximum of ... */
+#define MAXBUFF 1024
+/*... edit buffers, each of which is ... */
+#define EDIT_BUF_SIZE 0x10000
+/* ...bytes in size. */
+
+/*x / EDIT_BUF_SIZE equals x >> ... */
+#define S_EDIT_BUF_SIZE 16
+
+/* x % EDIT_BUF_SIZE is equal to x && ... */
+#define M_EDIT_BUF_SIZE 0xFFFF
+
+#define SIZE_LIMIT (EDIT_BUF_SIZE * (MAXBUFF - 2))
+/* Note a 16k stack is 64k of data and enough to hold (usually) around 10
+   pages of undo info. */
+
+/* undo stack */
+#define START_STACK_SIZE 32
+
+
+/*some codes that may be pushed onto or returned from the undo stack: */
+#define CURS_LEFT 601
+#define CURS_RIGHT 602
+#define DELETE 603
+#define BACKSPACE 604
+#define STACK_BOTTOM 605
+#define CURS_LEFT_LOTS 606
+#define CURS_RIGHT_LOTS 607
+#define COLUMN_ON 608
+#define COLUMN_OFF 609
+#define MARK_1 1000
+#define MARK_2 700000000
+#define KEY_PRESS 1400000000
+
+/*Tabs spaces: (sofar only HALF_TAB_SIZE is used: */
+#define TAB_SIZE		option_tab_spacing
+#define HALF_TAB_SIZE		((int) option_tab_spacing / 2)
+
+struct macro {
+    short command;
+    short ch;
+};
+
+struct selection {
+   unsigned char * text;
+   int len;
+};
+
+
+#define RULE_CONTEXT		0x00FFF000UL
+#define RULE_CONTEXT_SHIFT	12
+#define RULE_WORD		0x00000FFFUL
+#define RULE_WORD_SHIFT		0
+#define RULE_ON_LEFT_BORDER	0x02000000UL
+#define RULE_ON_RIGHT_BORDER	0x01000000UL
+
+struct key_word {
+    char *keyword;
+    char first;
+    char last;
+    char *whole_word_chars_left;
+    char *whole_word_chars_right;
+#define NO_COLOR ((unsigned long) -1);
+    int line_start;
+    int bg;
+    int fg;
+};
+
+struct context_rule {
+    int rule_number;
+    char *left;
+    char first_left;
+    char last_left;
+    char line_start_left;
+    char *right;
+    char first_right;
+    char last_right;
+    char line_start_right;
+    int single_char;
+    int between_delimiters;
+    char *whole_word_chars_left;
+    char *whole_word_chars_right;
+    unsigned char *conflicts;
+    char *keyword_first_chars;
+    char *keyword_last_chars;
+/* first word is word[1] */
+    struct key_word **keyword;
+};
+
+
+
+struct editor_widget {
+#ifdef MIDNIGHT
+    Widget widget;
+#elif defined(GTK)
+    GtkEdit *widget;
+#else
+    struct cool_widget *widget;
+#endif
+#define from_here num_widget_lines
+    int num_widget_lines;
+    int num_widget_columns;
+
+#ifdef MIDNIGHT
+    int have_frame;
+#else
+    int stopped;
+#endif
+
+    char *filename;		/* Name of the file */
+    char *dir;			/* current directory */
+
+/* dynamic buffers and curser position for editor: */
+    long curs1;			/*position of the cursor from the beginning of the file. */
+    long curs2;			/*position from the end of the file */
+    unsigned char *buffers1[MAXBUFF + 1];	/*all data up to curs1 */
+    unsigned char *buffers2[MAXBUFF + 1];	/*all data from end of file down to curs2 */
+
+/* search variables */
+    long search_start;		/* First character to start searching from */
+    int found_len;		/* Length of found string or 0 if none was found */
+    long found_start;		/* the found word from a search - start position */
+
+/* display information */
+    long last_byte;		/* Last byte of file */
+    long start_display;		/* First char displayed */
+    long start_col;		/* First displayed column, negative */
+    long max_column;		/* The maximum cursor position ever reached used to calc hori scroll bar */
+    long curs_row;		/*row position of curser on the screen */
+    long curs_col;		/*column position on screen */
+    int force;			/* how much of the screen do we redraw? */
+    unsigned char overwrite;
+    unsigned char modified;	/*has the file been changed?: 1 if char inserted or
+				   deleted at all since last load or save */
+#if defined(MIDNIGHT) || defined(GTK)
+    int delete_file;			/* has the file been created in edit_load_file? Delete
+			           it at end of editing when it hasn't been modified 
+				   or saved */
+#endif				   
+    unsigned char highlight;
+    long prev_col;		/*recent column position of the curser - used when moving
+				   up or down past lines that are shorter than the current line */
+    long curs_line;		/*line number of the cursor. */
+    long start_line;		/*line nummber of the top of the page */
+
+/* file info */
+    long total_lines;		/*total lines in the file */
+    long mark1;			/*position of highlight start */
+    long mark2;			/*position of highlight end */
+    int column1;			/*position of column highlight start */
+    int column2;			/*position of column highlight end */
+    long bracket;		/*position of a matching bracket */
+
+/* undo stack and pointers */
+    unsigned long stack_pointer;
+    long *undo_stack;
+    unsigned long stack_size;
+    unsigned long stack_size_mask;
+    unsigned long stack_bottom;
+    struct stat stat;
+
+/* syntax higlighting */
+    struct context_rule **rules;
+    long last_get_rule;
+    unsigned long rule;
+    char *syntax_type;		/* description of syntax highlighting type being used */
+    int explicit_syntax;	/* have we forced the syntax hi. type in spite of the filename? */
+
+    int to_here;		/* dummy marker */
+
+
+/* macro stuff */
+    int macro_i;		/* -1 if not recording index to macro[] otherwise */
+    struct macro macro[MAX_MACRO_LENGTH];
+};
+
+typedef struct editor_widget WEdit;
+
+#ifndef MIDNIGHT
+
+void edit_render_expose (WEdit * edit, XExposeEvent * xexpose);
+#ifndef GTK
+void edit_render_tidbits (struct cool_widget *w);
+int eh_editor (CWidget * w, XEvent * xevent, CEvent * cwevent);
+#endif
+void edit_draw_menus (Window parent, int x, int y);
+void edit_run_make (void);
+void edit_change_directory (void);
+int edit_man_page_cmd (WEdit * edit);
+void edit_search_replace_dialog (Window parent, int x, int y, char **search_text, char **replace_text, char **arg_order, char *heading, int option);
+void edit_search_dialog (WEdit * edit, char **search_text);
+long edit_find (long search_start, unsigned char *expr, int *len, long last_byte, int (*get_byte) (void *, long), void *data);
+void edit_set_foreground_colors (unsigned long normal, unsigned long bold, unsigned long italic);
+void edit_set_background_colors (unsigned long normal, unsigned long abnormal, unsigned long marked, unsigned long marked_abnormal, unsigned long highlighted);
+void edit_set_cursor_color (unsigned long c);
+void draw_options_dialog (Window parent, int x, int y);
+void CRefreshEditor (WEdit * edit);
+void edit_set_user_command (void (*func) (WEdit *, int));
+void edit_draw_this_line_proportional (WEdit * edit, long b, int curs_row, int start_column, int end_column);
+unsigned char get_international_character (unsigned char key_press);
+void edit_set_user_key_function (int (*user_def_key_func) (unsigned int, unsigned int, KeySym keysym));
+
+#else
+
+int edit_drop_hotkey_menu (WEdit * e, int key);
+void edit_menu_cmd (WEdit * e);
+void edit_init_menu_emacs (void);
+void edit_init_menu_normal (void);
+void edit_done_menu (void);
+int edit_raw_key_query (char *heading, char *query, int cancel);
+char *strcasechr (const unsigned char *s, int c);
+int edit (const char *_file, int line);
+int edit_translate_key (WEdit * edit, unsigned int x_keycode, long x_key, int x_state, int *cmd, int *ch);
+
+#endif
+
+#ifndef NO_INLINE_GETBYTE
+int edit_get_byte (WEdit * edit, long byte_index);
+#else
+static inline int edit_get_byte (WEdit * edit, long byte_index)
+{
+    unsigned long p;
+    if (byte_index >= (edit->curs1 + edit->curs2) || byte_index < 0)
+	return '\n';
+
+    if (byte_index >= edit->curs1) {
+	p = edit->curs1 + edit->curs2 - byte_index - 1;
+	return edit->buffers2[p >> S_EDIT_BUF_SIZE][EDIT_BUF_SIZE - (p & M_EDIT_BUF_SIZE) - 1];
+    } else {
+	return edit->buffers1[byte_index >> S_EDIT_BUF_SIZE][byte_index & M_EDIT_BUF_SIZE];
+    }
+}
+#endif
+
+char *edit_get_buffer_as_text (WEdit * edit);
+int edit_load_file (WEdit * edit, const char *filename, const char *text, unsigned long text_size);
+int edit_count_lines (WEdit * edit, long current, int upto);
+long edit_move_forward (WEdit * edit, long current, int lines, long upto);
+long edit_move_forward3 (WEdit * edit, long current, int cols, long upto);
+long edit_move_backward (WEdit * edit, long current, int lines);
+void edit_scroll_screen_over_cursor (WEdit * edit);
+void edit_render_keypress (WEdit * edit);
+void edit_scroll_upward (WEdit * edit, unsigned long i);
+void edit_scroll_downward (WEdit * edit, int i);
+void edit_scroll_right (WEdit * edit, int i);
+void edit_scroll_left (WEdit * edit, int i);
+int edit_get_col (WEdit * edit);
+long edit_bol (WEdit * edit, long current);
+long edit_eol (WEdit * edit, long current);
+void edit_update_curs_row (WEdit * edit);
+void edit_update_curs_col (WEdit * edit);
+
+void edit_block_copy_cmd (WEdit * edit);
+void edit_block_move_cmd (WEdit * edit);
+int edit_block_delete_cmd (WEdit * edit);
+int edit_block_delete (WEdit * edit);
+void edit_delete_line (WEdit * edit);
+
+int edit_delete (WEdit * edit);
+void edit_insert (WEdit * edit, int c);
+int edit_cursor_move (WEdit * edit, long increment);
+void edit_push_action (WEdit * edit, long c,...);
+void edit_push_key_press (WEdit * edit);
+void edit_insert_ahead (WEdit * edit, int c);
+int edit_save_file (WEdit * edit, const char *filename);
+int edit_save_cmd (WEdit * edit);
+int edit_save_confirm_cmd (WEdit * edit);
+int edit_save_as_cmd (WEdit * edit);
+WEdit *edit_init (WEdit * edit, int lines, int columns, const char *filename, const char *text, const char *dir, unsigned long text_size);
+int edit_clean (WEdit * edit);
+int edit_renew (WEdit * edit);
+int edit_new_cmd (WEdit * edit);
+int edit_reload (WEdit * edit, const char *filename, const char *text, const char *dir, unsigned long text_size);
+int edit_load_cmd (WEdit * edit);
+void edit_mark_cmd (WEdit * edit, int unmark);
+void edit_set_markers (WEdit * edit, long m1, long m2, int c1, int c2);
+void edit_push_markers (WEdit * edit);
+void edit_quit_cmd (WEdit * edit);
+void edit_replace_cmd (WEdit * edit, int again);
+void edit_search_cmd (WEdit * edit, int again);
+int edit_save_block_cmd (WEdit * edit);
+int edit_insert_file_cmd (WEdit * edit);
+int edit_insert_file (WEdit * edit, const char *filename);
+void edit_block_process_cmd (WEdit * edit, const char *shell_cmd, int block);
+char *catstrs (const char *first,...);
+void edit_refresh_cmd (WEdit * edit);
+void edit_date_cmd (WEdit * edit);
+void edit_goto_cmd (WEdit * edit);
+int eval_marks (WEdit * edit, long *start_mark, long *end_mark);
+void edit_status (WEdit * edit);
+int edit_execute_command (WEdit * edit, int command, int char_for_insertion);
+int edit_execute_key_command (WEdit * edit, int command, int char_for_insertion);
+void edit_update_screen (WEdit * edit);
+int edit_printf (WEdit * e, const char *fmt,...);
+int edit_print_string (WEdit * e, const char *s);
+void edit_move_to_line (WEdit * e, long line);
+void edit_move_display (WEdit * e, long line);
+void edit_word_wrap (WEdit * edit);
+unsigned char *edit_get_block (WEdit * edit, long start, long finish, int *l);
+int edit_sort_cmd (WEdit * edit);
+void edit_help_cmd (WEdit * edit);
+void edit_left_word_move (WEdit * edit);
+void edit_right_word_move (WEdit * edit);
+void edit_get_selection (WEdit * edit);
+
+int edit_save_macro_cmd (WEdit * edit, struct macro macro[], int n);
+int edit_load_macro_cmd (WEdit * edit, struct macro macro[], int *n, int k);
+void edit_delete_macro_cmd (WEdit * edit);
+
+int edit_copy_to_X_buf_cmd (WEdit * edit);
+int edit_cut_to_X_buf_cmd (WEdit * edit);
+void edit_paste_from_X_buf_cmd (WEdit * edit);
+
+void edit_paste_from_history (WEdit *edit);
+
+void edit_split_filename (WEdit * edit, char *name);
+
+#ifdef MIDNIGHT
+#define CWidget Widget
+#elif defined(GTK)
+#define CWidget GtkEdit
+#endif
+void edit_set_syntax_change_callback (void (*callback) (CWidget *));
+void edit_load_syntax (WEdit * edit, char **names, char *type);
+void edit_free_syntax_rules (WEdit * edit);
+void edit_get_syntax_color (WEdit * edit, long byte_index, int *fg, int *bg);
+
+
+#ifdef MIDNIGHT
+
+/* put OS2/NT/WIN95 defines here */
+
+#    ifdef OS2_NT
+#    	 define MY_O_TEXT O_TEXT
+#    else
+#    	 define MY_O_TEXT 0
+#    endif
+
+#    define FONT_PIX_PER_LINE 1
+#    define FONT_MEAN_WIDTH 1
+     
+#    define get_sys_error(s) (s)
+#    define open mc_open
+#    define close(f) mc_close(f)
+#    define read(f,b,c) mc_read(f,b,c)
+#    define write(f,b,c) mc_write(f,b,c)
+#    define stat(f,s) mc_stat(f,s)
+#    define mkdir(s,m) mc_mkdir(s,m)
+#    define itoa MY_itoa
+
+#    define edit_get_load_file(d,f,h) input_dialog (h, " Enter file name: ", f)
+#    define edit_get_save_file(d,f,h) input_dialog (h, " Enter file name: ", f)
+#    define CMalloc(x) malloc(x)
+     
+#    define set_error_msg(s) edit_init_error_msg = strdup(s)
+
+#    ifdef _EDIT_C
+
+#         define edit_error_dialog(h,s) set_error_msg(s)
+char *edit_init_error_msg = NULL;
+
+#    else				/* ! _EDIT_C */
+
+#    define edit_error_dialog(h,s) query_dialog (h, s, 0, 1, _("&Dismiss"))
+#    define edit_message_dialog(h,s) query_dialog (h, s, 0, 1, _("&Ok"))
+extern char *edit_init_error_msg;
+
+#    endif				/* ! _EDIT_C */
+
+
+#    define get_error_msg(s) edit_init_error_msg
+#    define edit_query_dialog2(h,t,a,b) query_dialog(h,t,0,2,a,b)
+#    define edit_query_dialog3(h,t,a,b,c) query_dialog(h,t,0,3,a,b,c)
+#    define edit_query_dialog4(h,t,a,b,c,d) query_dialog(h,t,0,4,a,b,c,d)
+
+#else				/* ! MIDNIGHT */
+
+#    ifdef GTK
+#        define get_sys_error(s) (s)
+
+#        define open mc_open
+#        define close(f) mc_close(f)
+#        define read(f,b,c) mc_read(f,b,c)
+#        define write(f,b,c) mc_write(f,b,c)
+#        define stat(f,s) mc_stat(f,s)
+#        define mkdir(s,m) mc_mkdir(s,m)
+
+#        define itoa MY_itoa
+#        define CMalloc(x) malloc(x)
+
+#        define EDITOR_NO_FILE			(1<<3)
+#        define EDITOR_NO_SCROLL		(1<<4)
+#        define EDITOR_NO_TEXT			(1<<5)
+#        define EDITOR_HORIZ_SCROLL		(1<<6)
+
+#include <gdk/gdkprivate.h>
+#        define CWindowOf(w) (w)
+#        define CHeightOf(w) ((w)->editable.widget.allocation.height)
+#        define CWidthOf(w) ((w)->editable.widget.allocation.width)
+#        define COptionsOf(w) ((w)->options)
+
+#        define cache_type unsigned int
+
+/* font dimensions */
+#        define FONT_OVERHEAD		gtk_edit_option_text_line_spacing
+#        define FONT_BASE_LINE		(FONT_OVERHEAD + gtk_edit_option_font_ascent)
+#        define FONT_HEIGHT		(gtk_edit_option_font_ascent + gtk_edit_option_font_descent)
+#        define FONT_PIX_PER_LINE	(FONT_OVERHEAD + FONT_HEIGHT)
+#        define FONT_MEAN_WIDTH	gtk_edit_option_font_mean_width
+
+#        define FONT_OFFSET_X 0
+#        define FONT_OFFSET_Y		FONT_BASE_LINE
+
+#        define per_char gtk_edit_font_width_per_char
+
+#        ifndef _GTK_EDIT_C
+extern guchar gtk_edit_font_width_per_char[256];
+extern int gtk_edit_option_text_line_spacing;
+extern int gtk_edit_option_font_ascent;
+extern int gtk_edit_option_font_descent;
+extern int gtk_edit_option_font_mean_width;
+extern int gtk_edit_fixed_font;
+#        endif
+
+/* start temporary */
+
+#        define COLOR_BLACK 0
+#        define COLOR_WHITE 1
+#        define CURSOR_TYPE_EDITOR 0
+
+#        define WIN_MESSAGES GTK_WINDOW_TOPLEVEL, 20, 20
+#        define option_text_line_spacing 1
+#        define fixed_font 0
+
+#define color_palette(x) win->color[x].pixel
+
+#define DndNotDnd	-1
+#define DndUnknown	0
+#define DndRawData	1
+#define DndFile		2
+#define DndFiles	3
+#define DndText		4
+#define DndDir		5
+#define DndLink		6
+#define DndExe		7
+#define DndURL		8
+#define DndMIME         9
+
+#define DndEND		10
+
+#define dnd_null_term_type(d) \
+	((d) == DndFile || (d) == DndText || (d) == DndDir || \
+	(d) == DndLink || (d) == DndExe || (d) == DndURL)
+
+
+
+/* end temporary */
+
+#    else
+
+#        define WIN_MESSAGES edit->widget->mainid, 20, 20
+
+#    endif
+
+#    define MY_O_TEXT 0
+
+#    ifdef GTK
+
+#        ifndef min
+#            define min(x,y)     (((x) < (y)) ? (x) : (y))
+#        endif
+
+#        ifndef max
+#            define max(x,y)     (((x) > (y)) ? (x) : (y))
+#        endif
+
+/*
+extern Display             *gdk_display;
+extern Window               gdk_root_window;
+*/
+
+enum {
+ match_file, match_normal
+};
+
+#        define edit_get_load_file(d,f,h) gtk_edit_dialog_get_load_file(d,f,h)
+#        define edit_get_save_file(d,f,h) gtk_edit_dialog_get_save_file(d,f,h)
+#        define edit_error_dialog(h,t) gtk_edit_dialog_error(h,"%s",t)
+#        define edit_message_dialog(h,t) gtk_edit_dialog_message(0,h,"%s",t)
+#        define edit_query_dialog2(h,t,a,b) gtk_edit_dialog_query(h,t,a,b,0)
+#        define edit_query_dialog3(h,t,a,b,c) gtk_edit_dialog_query(h,t,a,b,c,0)
+#        define edit_query_dialog4(h,t,a,b,c,d) gtk_edit_dialog_query(h,t,a,b,c,d,0)
+
+#        define CError(x) printf("Error: %s\n",x)
+#        define CIsDropAcknowledge(a,b) DndNotDnd
+#        define CGetDrop(e,d,s,x,y) DndNotDnd
+#        define CDropAcknowledge(x) 
+/* #        define edit_get_syntax_color(e,i,f,b)  */
+#        define get_international_character(k) 0
+#        define compose_key_pressed 0
+
+#    else
+
+#        define edit_get_load_file(d,f,h) CGetLoadFile(WIN_MESSAGES,d,f,h)
+#        define edit_get_save_file(d,f,h) CGetSaveFile(WIN_MESSAGES,d,f,h)
+#        define edit_error_dialog(h,t) CErrorDialog(WIN_MESSAGES,h,"%s",t)
+#        define edit_message_dialog(h,t) CMessageDialog(WIN_MESSAGES,0,h,"%s",t)
+#        define edit_query_dialog2(h,t,a,b) CQueryDialog(WIN_MESSAGES,h,t,a,b,0)
+#        define edit_query_dialog3(h,t,a,b,c) CQueryDialog(WIN_MESSAGES,h,t,a,b,c,0)
+#        define edit_query_dialog4(h,t,a,b,c,d) CQueryDialog(WIN_MESSAGES,h,t,a,b,c,d,0)
+#    endif
+
+#endif				/* ! MIDNIGHT */
+
+extern char *home_dir;
+
+#define NUM_SELECTION_HISTORY 32
+
+#ifdef _EDIT_C
+
+struct selection selection =
+{0, 0};
+int current_selection = 0;
+/* Note: selection.text = selection_history[current_selection].text */
+struct selection selection_history[NUM_SELECTION_HISTORY] =
+{
+    {0, 0},
+    {0, 0},
+    {0, 0},
+    {0, 0},
+    {0, 0},
+    {0, 0},
+    {0, 0},
+    {0, 0},
+    {0, 0},
+    {0, 0},
+};
+
+#ifdef MIDNIGHT
+/*
+   what editor are we going to emulate? one of EDIT_KEY_EMULATION_NORMAL
+   or EDIT_KEY_EMULATION_EMACS
+ */
+int edit_key_emulation = EDIT_KEY_EMULATION_NORMAL;
+#endif	/* ! MIDNIGHT */
+
+int option_word_wrap_line_length = 72;
+int option_typewriter_wrap = 0;
+int option_auto_para_formatting = 0;
+int option_international_characters = 0;
+int option_tab_spacing = 8;
+int option_fill_tabs_with_spaces = 0;
+int option_return_does_auto_indent = 1;
+int option_backspace_through_tabs = 0;
+int option_fake_half_tabs = 1;
+int option_save_mode = 0;
+int option_backup_ext_int = -1;
+int option_find_bracket = 1;
+int option_max_undo = 32768;
+
+int option_editor_fg_normal = 26;
+int option_editor_fg_bold = 8;
+int option_editor_fg_italic = 10;
+
+int option_edit_right_extreme = 0;
+int option_edit_left_extreme = 0;
+int option_edit_top_extreme = 0;
+int option_edit_bottom_extreme = 0;
+
+int option_editor_bg_normal = 1;
+int option_editor_bg_abnormal = 0;
+int option_editor_bg_marked = 2;
+int option_editor_bg_marked_abnormal = 9;
+int option_editor_bg_highlighted = 12;
+int option_editor_fg_cursor = 18;
+
+char *option_whole_chars_search = "0123456789abcdefghijklmnopqrstuvwxyz_";
+char *option_whole_chars_move = "0123456789abcdefghijklmnopqrstuvwxyz_; ,[](){}";
+char *option_backup_ext = "~";
+
+#else				/* ! _EDIT_C */
+
+extern struct selection selection;
+extern struct selection selection_history[];
+extern int current_selection;
+
+#ifdef MIDNIGHT
+/*
+   what editor are we going to emulate? one of EDIT_KEY_EMULATION_NORMAL
+   or EDIT_KEY_EMULATION_EMACS
+ */
+extern int edit_key_emulation;
+#endif	/* ! MIDNIGHT */
+
+extern int option_word_wrap_line_length;
+extern int option_typewriter_wrap;
+extern int option_auto_para_formatting;
+extern int option_international_characters;
+extern int option_tab_spacing;
+extern int option_fill_tabs_with_spaces;
+extern int option_return_does_auto_indent;
+extern int option_backspace_through_tabs;
+extern int option_fake_half_tabs;
+extern int option_save_mode;
+extern int option_backup_ext_int;
+extern int option_find_bracket;
+extern int option_max_undo;
+
+extern int option_editor_fg_normal;
+extern int option_editor_fg_bold;
+extern int option_editor_fg_italic;
+
+extern int option_edit_right_extreme;
+extern int option_edit_left_extreme;
+extern int option_edit_top_extreme;
+extern int option_edit_bottom_extreme;
+
+extern int option_editor_bg_normal;
+extern int option_editor_bg_abnormal;
+extern int option_editor_bg_marked;
+extern int option_editor_bg_marked_abnormal;
+extern int option_editor_bg_highlighted;
+extern int option_editor_fg_cursor;
+
+extern char *option_whole_chars_search;
+extern char *option_whole_chars_move;
+extern char *option_backup_ext;
+
+extern int edit_confirm_save;
+
+#endif				/* ! _EDIT_C */
+#endif 				/* __EDIT_H */

+ 2870 - 0
edit/editcmd.c

@@ -0,0 +1,2870 @@
+/* editor high level editing commands.
+
+   Copyright (C) 1996, 1997 the Free Software Foundation
+
+   Authors: 1996, 1997 Paul Sheer
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* #define PIPE_BLOCKS_SO_READ_BYTE_BY_BYTE */
+
+#include <config.h>
+#ifdef OS2_NT
+#include <io.h>
+#include <fcntl.h>
+#endif
+#include <ctype.h>
+#include "edit.h"
+#include "editcmddef.h"
+
+#ifndef MIDNIGHT
+#include <X11/Xatom.h>
+#ifndef GTK
+#include "loadfile.h"
+#endif
+#endif
+
+/* globals: */
+
+/* search and replace: */
+int replace_scanf = 0;
+int replace_regexp = 0;
+int replace_all = 0;
+int replace_prompt = 1;
+int replace_whole = 0;
+int replace_case = 0;
+int replace_backwards = 0;
+
+/* queries on a save */
+#ifdef MIDNIGHT
+int edit_confirm_save = 1;
+#else
+int edit_confirm_save = 0;
+#endif
+
+#define NUM_REPL_ARGS 16
+#define MAX_REPL_LEN 1024
+
+#if defined(MIDNIGHT) || defined(GTK)
+
+static inline int my_lower_case (int c)
+{
+    return tolower(c);
+}
+
+char *strcasechr (const unsigned char *s, int c)
+{
+    for (; my_lower_case ((int) *s) != my_lower_case (c); ++s)
+	if (*s == '\0')
+	    return 0;
+    return (char *) s;
+}
+
+#ifdef MIDNIGHT
+#include "../src/mad.h"
+#endif
+
+#ifndef HAVE_MEMMOVE
+/* for Christophe */
+static void *memmove (void *dest, const void *src, size_t n)
+{
+    char *t, *s;
+
+    if (dest <= src) {
+	t = (char *) dest;
+	s = (char *) src;
+	while (n--)
+	    *t++ = *s++;
+    } else {
+	t = (char *) dest + n;
+	s = (char *) src + n;
+	while (n--)
+	    *--t = *--s;
+    }
+    return dest;
+}
+#endif
+
+/* #define itoa MY_itoa  <---- this line is now in edit.h */
+char *itoa (int i)
+{
+    static char t[14];
+    char *s = t + 13;
+    int j = i;
+    *s-- = 0;
+    do {
+	*s-- = i % 10 + '0';
+    } while ((i = i / 10));
+    if (j < 0)
+	*s-- = '-';
+    return ++s;
+}
+
+/*
+   This joins strings end on end and allocates memory for the result.
+   The result is later automatically free'd and must not be free'd
+   by the caller.
+ */
+char *catstrs (const char *first,...)
+{
+    static char *stacked[16] =
+    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    static int i = 0;
+    va_list ap;
+    int len;
+    char *data;
+
+    if (!first)
+	return 0;
+
+    len = strlen (first);
+    va_start (ap, first);
+
+    while ((data = va_arg (ap, char *)) != 0)
+	 len += strlen (data);
+
+    len++;
+
+    i = (i + 1) % 16;
+    if (stacked[i])
+	free (stacked[i]);
+
+    stacked[i] = malloc (len);
+    va_end (ap);
+    va_start (ap, first);
+    strcpy (stacked[i], first);
+    while ((data = va_arg (ap, char *)) != 0)
+	 strcat (stacked[i], data);
+    va_end (ap);
+
+    return stacked[i];
+}
+#endif
+
+#ifdef MIDNIGHT
+
+void edit_help_cmd (WEdit * edit)
+{
+    char *hlpdir = concat_dir_and_file (mc_home, "mc.hlp");
+    interactive_display (hlpdir, "[Internal File Editor]");
+    free (hlpdir);
+    edit->force |= REDRAW_COMPLETELY;
+}
+
+void edit_refresh_cmd (WEdit * edit)
+{
+#ifndef HAVE_SLANG
+    clr_scr();
+    do_refresh();
+#else
+    {
+	int fg, bg;
+	edit_get_syntax_color (edit, -1, &fg, &bg);
+    }
+    touchwin(stdscr);
+#endif
+    mc_refresh();
+    doupdate();
+}
+
+#else
+
+void edit_help_cmd (WEdit * edit)
+{
+}
+
+void edit_refresh_cmd (WEdit * edit)
+{
+    int fg, bg;
+    edit_get_syntax_color (edit, -1, &fg, &bg);
+    edit->force |= REDRAW_COMPLETELY;
+}
+
+void CRefreshEditor (WEdit * edit)
+{
+    edit_refresh_cmd (edit);
+}
+
+#endif
+
+#ifndef MIDNIGHT
+#ifndef GTK
+
+/* three argument open */
+int my_open (const char *pathname, int flags,...)
+{
+    int file;
+    va_list ap;
+
+    file = open ((char *) pathname, O_RDONLY);
+    if (file < 0 && (flags & O_CREAT)) {	/* must it be created ? */
+	mode_t mode;
+	va_start(ap, flags);
+	mode = va_arg(ap, mode_t);
+	va_end(ap);
+	return creat ((char *) pathname, mode);
+    }
+    close (file);
+    return open ((char *) pathname, flags);
+}
+
+#define open my_open
+
+#endif
+#endif
+
+/* "Oleg Yu. Repin" <repin@ssd.sscc.ru> added backup filenames
+    ...thanks -paul */
+
+/*  If 0 (quick save) then  a) create/truncate <filename> file,
+			    b) save to <filename>;
+    if 1 (safe save) then   a) save to <tempnam>,
+			    b) rename <tempnam> to <filename>;
+    if 2 (do backups) then  a) save to <tempnam>,
+			    b) rename <filename> to <filename.backup_ext>,
+			    c) rename <tempnam> to <filename>. */
+
+/* returns 0 on error */
+int edit_save_file (WEdit * edit, const char *filename)
+{
+    long buf;
+    long filelen = 0;
+    int file;
+    char *savename = (char *) filename;
+    int this_save_mode;
+
+    if ((file = open (savename, O_WRONLY)) == -1) {
+	this_save_mode = 0;		/* the file does not exists yet, so no safe save or backup necessary */
+    } else {
+	close (file);
+	this_save_mode = option_save_mode;
+    }
+
+    if (this_save_mode > 0) {
+	char *savedir = ".", *slashpos = strrchr (filename, '/');
+	if (slashpos != 0) {
+	    savedir = strdup (filename);
+	    if (savedir == 0)
+		return 0;
+	    savedir[slashpos - filename + 1] = '\0';
+	}
+#ifdef HAVE_MAD
+	savename = strdup (tempnam (savedir, "cooledit"));
+#else
+	savename = tempnam (savedir, "cooledit");
+#endif
+	if (slashpos)
+	    free (savedir);
+	if (!savename)
+	    return 0;
+    }
+    if ((file = open (savename, O_CREAT | O_WRONLY | O_TRUNC | MY_O_TEXT, edit->stat.st_mode)) == -1) {
+	if (this_save_mode > 0)
+	    free (savename);
+	return 0;
+    }
+    chown (savename, edit->stat.st_uid, edit->stat.st_gid);
+    buf = 0;
+    while (buf <= (edit->curs1 >> S_EDIT_BUF_SIZE) - 1) {
+	filelen += write (file, (char *) edit->buffers1[buf], EDIT_BUF_SIZE);
+	buf++;
+    }
+    filelen += write (file, (char *) edit->buffers1[buf], edit->curs1 & M_EDIT_BUF_SIZE);
+
+    if (edit->curs2) {
+	edit->curs2--;
+	buf = (edit->curs2 >> S_EDIT_BUF_SIZE);
+	filelen += write (file, (char *) edit->buffers2[buf] + EDIT_BUF_SIZE - (edit->curs2 & M_EDIT_BUF_SIZE) - 1, 1 + (edit->curs2 & M_EDIT_BUF_SIZE));
+	buf--;
+	while (buf >= 0) {
+	    filelen += write (file, (char *) edit->buffers2[buf], EDIT_BUF_SIZE);
+	    buf--;
+	}
+	edit->curs2++;
+    }
+    close (file);
+
+    if (filelen == edit->last_byte) {
+	if (this_save_mode == 2) {
+	    if (rename (filename, catstrs (filename, option_backup_ext, 0)) == -1) {	/* catstrs free's automatically */
+		free (savename);
+		return 0;
+	    }
+	}
+	if (this_save_mode > 0) {
+	    if (rename (savename, filename) == -1) {
+		free (savename);
+		return 0;
+	    }
+	    free (savename);
+	}
+	return 1;
+    } else {
+	if (this_save_mode > 0)
+	    free (savename);
+	return 0;
+    }
+}
+
+#ifdef MIDNIGHT
+/*
+   I changed this from Oleg's original routine so
+   that option_backup_ext works with coolwidgets as well. This
+   does mean there is a memory leak - paul.
+ */
+void menu_save_mode_cmd (void)
+{
+#define DLG_X 36
+#define DLG_Y 10
+    static char *str_result;
+    static int save_mode_new;
+    static char *str[] =
+    {
+	"Quick save ",
+	"Safe save ",
+	"Do backups -->"};
+    static QuickWidget widgets[] =
+    {
+	{quick_button, 18, DLG_X, 7, DLG_Y, "&Cancel", 0,
+	 B_CANCEL, 0, 0, XV_WLAY_DONTCARE, "c"},
+	{quick_button, 6, DLG_X, 7, DLG_Y, "&Ok", 0,
+	 B_ENTER, 0, 0, XV_WLAY_DONTCARE, "o"},
+	{quick_input, 23, DLG_X, 5, DLG_Y, 0, 9,
+	 0, 0, &str_result, XV_WLAY_DONTCARE, "i"},
+	{quick_label, 22, DLG_X, 4, DLG_Y, "Extension:", 0,
+	 0, 0, 0, XV_WLAY_DONTCARE, "savemext"},
+	{quick_radio, 4, DLG_X, 3, DLG_Y, "", 3,
+	 0, &save_mode_new, str, XV_WLAY_DONTCARE, "t"},
+	{0}};
+    static QuickDialog dialog =
+/* NLS ? */
+    {DLG_X, DLG_Y, -1, -1, " Edit Save Mode ", "[Edit Save Mode]",
+     "esm", widgets};
+
+    widgets[2].text = option_backup_ext;
+    widgets[4].value = option_save_mode;
+    if (quick_dialog (&dialog) != B_ENTER)
+	return;
+    option_save_mode = save_mode_new;
+    option_backup_ext = str_result;	/* this is a memory leak */
+    option_backup_ext_int = 0;
+    str_result[min (strlen (str_result), sizeof (int))] = '\0';
+    memcpy ((char *) &option_backup_ext_int, str_result, strlen (option_backup_ext));
+}
+
+#endif
+
+#ifdef MIDNIGHT
+
+void edit_split_filename (WEdit * edit, char *f)
+{
+    if (edit->filename)
+	free (edit->filename);
+    edit->filename = strdup (f);
+    if (edit->dir)
+	free (edit->dir);
+    edit->dir = strdup ("");
+}
+
+#else
+
+#ifdef GTK
+
+static char cwd[1040];
+
+static char *canonicalize_pathname (char *p)
+{
+    char *q, *r;
+
+    if (*p != '/') {
+	if (strlen (cwd) == 0) {
+#ifdef HAVE_GETCWD
+	    getcwd (cwd, MAX_PATH_LEN);
+#else
+	    getwd (cwd);
+#endif
+	}
+	r = malloc (strlen (cwd) + strlen (p) + 2);
+	strcpy (r, cwd);
+	strcat (r, "/");
+	strcat (r, p);
+	p = r;
+    }
+    r = q = malloc (strlen (p) + 2);
+    for (;;) {
+	if (!*p) {
+	    *q = '\0';
+	    break;
+	}
+	if (*p != '/') {
+	    *q++ = *p++;
+	} else {
+	    while (*p == '/') {
+		*q = '/';
+		if (!strncmp (p, "/./", 3) || !strcmp (p, "/."))
+		    p++;
+		else if (!strncmp (p, "/../", 4) || !strcmp (p, "/..")) {
+		    p += 2;
+		    *q = ' ';
+		    q = strrchr (r, '/');
+		    if (!q) {
+			q = r;
+			*q = '/';
+		    }
+		}
+		p++;
+	    }
+	    q++;
+	}
+    }
+/* get rid of trailing / */
+    if (r[0] && r[1])
+	if (*--q == '/')
+	    *q = '\0';
+    return r;
+}
+
+#endif		/* GTK */
+
+
+void edit_split_filename (WEdit * edit, char *longname)
+{
+    char *exp, *p;
+    exp = canonicalize_pathname (longname);	/* this ensures a full path */
+    if (edit->filename)
+	free (edit->filename);
+    if (edit->dir)
+	free (edit->dir);
+    p = strrchr (exp, '/');
+    edit->filename = strdup (++p);
+    *p = 0;
+    edit->dir = strdup (exp);
+    free (exp);
+}
+
+#endif		/* ! MIDNIGHT */
+
+/*  here we want to warn the user of overwriting an existing file, but only if they
+   have made a change to the filename */
+/* returns 1 on success */
+int edit_save_as_cmd (WEdit * edit)
+{
+/* This heads the 'Save As' dialog box */
+    char *exp = 0;
+    int different_filename = 0;
+
+    exp = edit_get_save_file (edit->dir, edit->filename, _(" Save As "));
+    edit_push_action (edit, KEY_PRESS + edit->start_display);
+    edit->force |= REDRAW_COMPLETELY;
+
+    if (exp) {
+	if (!*exp) {
+	    free (exp);
+	    return 0;
+	} else {
+	    if (strcmp(catstrs (edit->dir, edit->filename, 0), exp)) {
+		int file;
+		different_filename = 1;
+		if ((file = open ((char *) exp, O_RDONLY)) != -1) {	/* the file exists */
+		    close (file);
+		    if (edit_query_dialog2 (_(" Warning "), 
+		    _(" A file already exists with this name. "), 
+/* Push buttons to over-write the current file, or cancel the operation */
+		    _("Overwrite"), _("Cancel")))
+			return 0;
+		}
+	    }
+	    if (edit_save_file (edit, exp)) {
+		edit_split_filename (edit, exp);
+		free (exp);
+		edit->modified = 0;
+#if defined(MIDNIGHT) || defined(GTK)
+	        edit->delete_file = 0;
+#endif		
+		if (different_filename && !edit->explicit_syntax)
+		    edit_load_syntax (edit, 0, 0);
+		return 1;
+	    } else {
+		free (exp);
+		edit_error_dialog (_(" Save as "), get_sys_error (_(" Error trying to save file. ")));
+		return 0;
+	    }
+	}
+    } else
+	return 0;
+}
+
+/* {{{ Macro stuff starts here */
+
+#ifdef MIDNIGHT
+int raw_callback (struct Dlg_head *h, int key, int Msg)
+{
+    switch (Msg) {
+    case DLG_DRAW:
+	attrset (REVERSE_COLOR);
+	dlg_erase (h);
+	draw_box (h, 1, 1, h->lines - 2, h->cols - 2);
+
+	attrset (COLOR_HOT_NORMAL);
+	dlg_move (h, 1, 2);
+	printw (h->title);
+	break;
+
+    case DLG_KEY:
+	h->running = 0;
+	h->ret_value = key;
+	return 1;
+    }
+    return 0;
+}
+
+/* gets a raw key from the keyboard. Passing cancel = 1 draws
+   a cancel button thus allowing c-c etc.. Alternatively, cancel = 0 
+   will return the next key pressed */
+int edit_raw_key_query (char *heading, char *query, int cancel)
+{
+    int w = strlen (query) + 7;
+    struct Dlg_head *raw_dlg = create_dlg (0, 0, 7, w, dialog_colors,
+/* NLS ? */
+					 raw_callback, "[Raw Key Query]",
+					   "raw_key_input",
+					   DLG_CENTER | DLG_TRYUP);
+    x_set_dialog_title (raw_dlg, heading);
+    raw_dlg->raw = 1;		/* to return even a tab key */
+    if (cancel)
+	add_widget (raw_dlg, button_new (4, w / 2 - 5, B_CANCEL, NORMAL_BUTTON, "Cancel", 0, 0, 0));
+    add_widget (raw_dlg, label_new (3 - cancel, 2, query, 0));
+    add_widget (raw_dlg, input_new (3 - cancel, w - 5, INPUT_COLOR, 2, "", 0));
+    run_dlg (raw_dlg);
+    w = raw_dlg->ret_value;
+    destroy_dlg (raw_dlg);
+    if (cancel)
+	if (w == XCTRL ('g') || w == XCTRL ('c') || w == ESC_CHAR || w == B_CANCEL)
+	    return 0;
+/* hence ctrl-a (=B_CANCEL), ctrl-g, ctrl-c, and Esc are cannot returned */
+    return w;
+}
+
+#else
+
+int edit_raw_key_query (char *heading, char *query, int cancel)
+{
+#ifdef GTK
+    /* *** */
+    return 0;
+#else
+    return CKeySymMod (CRawkeyQuery (0, 0, 0, heading, query));
+#endif
+}
+
+#endif
+
+/* creates a macro file if it doesn't exist */
+static FILE *edit_open_macro_file (const char *r)
+{
+    char *filename;
+    int file;
+    filename = catstrs (home_dir, MACRO_FILE, 0);
+    if ((file = open (filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
+	return 0;
+    close (file);
+    return fopen (filename, r);
+}
+
+#define MAX_MACROS 1024
+static int saved_macro[MAX_MACROS + 1] =
+{0, 0};
+static int saved_macros_loaded = 0;
+
+/*
+   This is just to stop the macro file be loaded over and over for keys
+   that aren't defined to anything. On slow systems this could be annoying.
+ */
+int macro_exists (int k)
+{
+    int i;
+    for (i = 0; i < MAX_MACROS && saved_macro[i]; i++)
+	if (saved_macro[i] == k)
+	    return i;
+    return -1;
+}
+
+/* returns 1 on error */
+int edit_delete_macro (WEdit * edit, int k)
+{
+    struct macro macro[MAX_MACRO_LENGTH];
+    FILE *f, *g;
+    int s, i, n, j = 0;
+
+    if (saved_macros_loaded)
+	if ((j = macro_exists (k)) < 0)
+	    return 0;
+    g = fopen (catstrs (home_dir, TEMP_FILE, 0), "w");
+    if (!g) {
+/* This heads the delete macro error dialog box */
+	edit_error_dialog (_(" Delete macro "),
+/* 'Open' = load temp file */
+		 get_sys_error (_(" Error trying to open temp file ")));
+	return 1;
+    }
+    f = edit_open_macro_file ("r");
+    if (!f) {
+/* This heads the delete macro error dialog box */
+	edit_error_dialog (_(" Delete macro "),
+/* 'Open' = load temp file */
+		get_sys_error (_(" Error trying to open macro file ")));
+	fclose (g);
+	return 1;
+    }
+    for (;;) {
+	n = fscanf (f, _("key '%d 0': "), &s);
+	if (!n || n == EOF)
+	    break;
+	n = 0;
+	while (fscanf (f, "%hd %hd, ", &macro[n].command, &macro[n].ch))
+	    n++;
+	fscanf (f, ";\n");
+	if (s != k) {
+	    fprintf (g, _("key '%d 0': "), s);
+	    for (i = 0; i < n; i++)
+		fprintf (g, "%hd %hd, ", macro[i].command, macro[i].ch);
+	    fprintf (g, ";\n");
+	}
+    };
+    fclose (f);
+    fclose (g);
+    if (rename (catstrs (home_dir, TEMP_FILE, 0), catstrs (home_dir, MACRO_FILE, 0)) == -1) {
+/* This heads the delete macro error dialog box */
+	edit_error_dialog (_(" Delete macro "),
+	   get_sys_error (_(" Error trying to overwrite macro file ")));
+	return 1;
+    }
+    if (saved_macros_loaded)
+	memmove (saved_macro + j, saved_macro + j + 1, sizeof (int) * (MAX_MACROS - j - 1));
+    return 0;
+}
+
+/* returns 0 on error */
+int edit_save_macro_cmd (WEdit * edit, struct macro macro[], int n)
+{
+    FILE *f;
+    int s, i;
+
+    edit->force |= REDRAW_COMPLETELY;
+    edit_push_action (edit, KEY_PRESS + edit->start_display);
+/* This heads the 'Macro' dialog box */
+    s = edit_raw_key_query (_(" Macro "),
+/* Input line for a single key press follows the ':' */
+    _(" Press the macro's new hotkey: "), 1);
+    if (s) {
+	if (edit_delete_macro (edit, s))
+	    return 0;
+	f = edit_open_macro_file ("a+");
+	if (f) {
+	    fprintf (f, _("key '%d 0': "), s);
+	    for (i = 0; i < n; i++)
+		fprintf (f, "%hd %hd, ", macro[i].command, macro[i].ch);
+	    fprintf (f, ";\n");
+	    fclose (f);
+	    if (saved_macros_loaded) {
+		for (i = 0; i < MAX_MACROS && saved_macro[i]; i++);
+		saved_macro[i] = s;
+	    }
+	    return 1;
+	} else
+/* This heads the 'Save Macro' dialog box */
+	    edit_error_dialog (_(" Save macro "), get_sys_error (_(" Error trying to open macro file ")));
+    }
+    return 0;
+}
+
+void edit_delete_macro_cmd (WEdit * edit)
+{
+    int command;
+
+#ifdef MIDNIGHT
+    command = CK_Macro (edit_raw_key_query (_(" Delete Macro "), _(" Press macro hotkey: "), 1));
+#else
+/* This heads the 'Delete Macro' dialog box */
+#ifdef GTK
+/* *** */
+    command = 0;
+#else
+    command = CK_Macro (CKeySymMod (CRawkeyQuery (0, 0, 0, _(" Delete Macro "), 
+/* Input line for a single key press follows the ':' */
+    _(" Press macro hotkey: "))));
+#endif
+#endif
+
+    if (command == CK_Macro (0))
+	return;
+
+    edit_delete_macro (edit, command - 2000);
+}
+
+/* return 0 on error */
+int edit_load_macro_cmd (WEdit * edit, struct macro macro[], int *n, int k)
+{
+    FILE *f;
+    int s, i = 0, found = 0;
+
+    if (saved_macros_loaded)
+	if (macro_exists (k) < 0)
+	    return 0;
+
+    if ((f = edit_open_macro_file ("r"))) {
+	struct macro dummy;
+	do {
+	    int u;
+	    u = fscanf (f, _("key '%d 0': "), &s);
+	    if (!u || u == EOF)
+		break;
+	    if (!saved_macros_loaded)
+		saved_macro[i++] = s;
+	    if (!found) {
+		*n = 0;
+		while (*n < MAX_MACRO_LENGTH && 2 == fscanf (f, "%hd %hd, ", &macro[*n].command, &macro[*n].ch))
+		    (*n)++;
+	    } else {
+		while (2 == fscanf (f, "%hd %hd, ", &dummy.command, &dummy.ch));
+	    }
+	    fscanf (f, ";\n");
+	    if (s == k)
+		found = 1;
+	} while (!found || !saved_macros_loaded);
+	if (!saved_macros_loaded) {
+	    saved_macro[i] = 0;
+	    saved_macros_loaded = 1;
+	}
+	fclose (f);
+	return found;
+    } else
+/* This heads the 'Load Macro' dialog box */
+	edit_error_dialog (_(" Load macro "),
+		get_sys_error (_(" Error trying to open macro file ")));
+    return 0;
+}
+
+/* }}} Macro stuff starts here */
+
+/* returns 1 on success */
+int edit_save_confirm_cmd (WEdit * edit)
+{
+    char *f;
+
+    if (edit_confirm_save) {
+#ifdef MIDNIGHT
+	f = catstrs (_(" Confirm save file? : "), edit->filename, " ", 0);
+#else
+	f = catstrs (_(" Confirm save file? : "), edit->dir, edit->filename, " ", 0);
+#endif
+/* Buttons to 'Confirm save file' query */
+	if (edit_query_dialog2 (_(" Save file "), f, _("Save"), _("Cancel")))
+	    return 0;
+    }
+    return edit_save_cmd (edit);
+}
+
+
+/* returns 1 on success */
+int edit_save_cmd (WEdit * edit)
+{
+    edit->force |= REDRAW_COMPLETELY;
+    if (!edit_save_file (edit, catstrs (edit->dir, edit->filename, 0)))
+	return edit_save_as_cmd (edit);
+    edit->modified = 0;
+#if defined(MIDNIGHT) || defined(GTK)
+    edit->delete_file = 0;
+#endif		
+
+    return 1;
+}
+
+
+/* returns 1 on success */
+int edit_new_cmd (WEdit * edit)
+{
+    edit->force |= REDRAW_COMPLETELY;
+    if (edit->modified)
+	if (edit_query_dialog2 (_ (" Warning "), _ (" Current text was modified without a file save. \n Continue discards these changes. "), _ ("Continue"), _ ("Cancel")))
+	    return 0;
+    edit->modified = 0;
+    return edit_renew (edit);	/* if this gives an error, something has really screwed up */
+}
+
+/* returns 1 on error */
+int edit_load_file_from_filename (WEdit *edit, char *exp)
+{
+    int file;
+    if ((file = open ((char *) exp, O_RDONLY, MY_O_TEXT)) != -1) {
+	close (file);
+	edit_reload (edit, exp, 0, "", 0);
+	edit_split_filename (edit, exp);
+	edit->modified = 0;
+	return 0;
+    } else {
+/* Heads the 'Load' file dialog box */
+	edit_error_dialog (_ (" Load "), get_sys_error (_ (" Error trying to open file for reading ")));
+    }
+    return 1;
+}
+
+int edit_load_cmd (WEdit * edit)
+{
+    char *exp;
+    edit->force |= REDRAW_COMPLETELY;
+
+    if (edit->modified)
+	if (edit_query_dialog2 (_ (" Warning "), _ (" Current text was modified without a file save. \n Continue discards these changes. "), _ ("Continue"), _ ("Cancel")))
+	    return 0;
+
+    exp = edit_get_load_file (edit->dir, edit->filename, _ (" Load "));
+
+    if (exp) {
+	if (*exp)
+	    edit_load_file_from_filename (edit, exp);
+	free (exp);
+    }
+    return 0;
+}
+
+/*
+   if mark2 is -1 then marking is from mark1 to the cursor.
+   Otherwise its between the markers. This handles this.
+   Returns 1 if no text is marked.
+ */
+int eval_marks (WEdit * edit, long *start_mark, long *end_mark)
+{
+    if (edit->mark1 != edit->mark2) {
+	if (edit->mark2 >= 0) {
+	    *start_mark = min (edit->mark1, edit->mark2);
+	    *end_mark = max (edit->mark1, edit->mark2);
+	} else {
+	    *start_mark = min (edit->mark1, edit->curs1);
+	    *end_mark = max (edit->mark1, edit->curs1);
+	    edit->column2 = edit->curs_col;
+	}
+	return 0;
+    } else {
+	*start_mark = *end_mark = 0;
+	edit->column2 = edit->column1 = 0;
+	return 1;
+    }
+}
+
+/*Block copy, move and delete commands */
+extern int column_highlighting;
+
+#ifdef MIDNIGHT
+#define space_width 1
+#else
+extern int space_width;
+#endif
+
+void edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width)
+{
+    long cursor;
+    int i, col;
+    cursor = edit->curs1;
+    col = edit_get_col (edit);
+    for (i = 0; i < size; i++) {
+	if (data[i] == '\n') {	/* fill in and move to next line */
+	    int l;
+	    long p;
+	    if (edit_get_byte (edit, edit->curs1) != '\n') {
+		l = width - (edit_get_col (edit) - col);
+		while (l > 0) {
+		    edit_insert (edit, ' ');
+		    l -= space_width;
+		}
+	    }
+	    for (p = edit->curs1;; p++) {
+		if (p == edit->last_byte)
+		    edit_insert_ahead (edit, '\n');
+		if (edit_get_byte (edit, p) == '\n') {
+		    p++;
+		    break;
+		}
+	    }
+	    edit_cursor_move (edit, edit_move_forward3 (edit, p, col, 0) - edit->curs1);
+	    l = col - edit_get_col (edit);
+	    while (l >= space_width) {
+		edit_insert (edit, ' ');
+		l -= space_width;
+	    }
+	    continue;
+	}
+	edit_insert (edit, data[i]);
+    }
+    edit_cursor_move (edit, cursor - edit->curs1);
+}
+
+
+void edit_block_copy_cmd (WEdit * edit)
+{
+    long start_mark, end_mark, current = edit->curs1;
+    int size, x;
+    unsigned char *copy_buf;
+
+    edit_update_curs_col (edit);
+    x = edit->curs_col;
+    if (eval_marks (edit, &start_mark, &end_mark))
+	return;
+    if (column_highlighting)
+	if ((x >= edit->column1 && x < edit->column2) || (x > edit->column2 && x <= edit->column1))
+	    return;
+
+    copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
+
+/* all that gets pushed are deletes hence little space is used on the stack */
+
+    edit_push_markers (edit);
+
+    if (column_highlighting) {
+	edit_insert_column_of_text (edit, copy_buf, size, abs (edit->column2 - edit->column1));
+    } else {
+	while (size--)
+	    edit_insert_ahead (edit, copy_buf[size]);
+    }
+
+    free (copy_buf);
+    edit_scroll_screen_over_cursor (edit);
+
+    if (column_highlighting) {
+	edit_set_markers (edit, 0, 0, 0, 0);
+	edit_push_action (edit, COLUMN_ON);
+	column_highlighting = 0;
+    } else if (start_mark < current && end_mark > current)
+	edit_set_markers (edit, start_mark, end_mark + end_mark - start_mark, 0, 0);
+
+    edit->force |= REDRAW_PAGE;
+}
+
+
+void edit_block_move_cmd (WEdit * edit)
+{
+    long count;
+    long current;
+    unsigned char *copy_buf;
+    long start_mark, end_mark;
+    int deleted = 0;
+    int x = 0;
+
+    if (eval_marks (edit, &start_mark, &end_mark))
+	return;
+    if (column_highlighting) {
+	edit_update_curs_col (edit);
+	x = edit->curs_col;
+	if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
+	    if ((x > edit->column1 && x < edit->column2) || (x > edit->column2 && x < edit->column1))
+		return;
+    } else if (start_mark <= edit->curs1 && end_mark >= edit->curs1)
+	return;
+
+    if ((end_mark - start_mark) > option_max_undo / 2)
+	if (edit_query_dialog2 (_ (" Warning "), _ (" Block is large, you may not be able to undo this action. "), _ ("Continue"), _ ("Cancel")))
+	    return;
+
+    edit_push_markers (edit);
+    current = edit->curs1;
+    if (column_highlighting) {
+	int size, c1, c2, line;
+	line = edit->curs_line;
+	if (edit->mark2 < 0)
+	    edit_mark_cmd (edit, 0);
+	c1 = min (edit->column1, edit->column2);
+	c2 = max (edit->column1, edit->column2);
+	copy_buf = edit_get_block (edit, start_mark, end_mark, &size);
+	if (x < c2) {
+	    edit_block_delete_cmd (edit);
+	    deleted = 1;
+	}
+	edit_move_to_line (edit, line);
+	edit_cursor_move (edit, edit_move_forward3 (edit, edit_bol (edit, edit->curs1), x, 0) - edit->curs1);
+	edit_insert_column_of_text (edit, copy_buf, size, c2 - c1);
+	if (!deleted) {
+	    line = edit->curs_line;
+	    edit_update_curs_col (edit);
+	    x = edit->curs_col;
+	    edit_block_delete_cmd (edit);
+	    edit_move_to_line (edit, line);
+	    edit_cursor_move (edit, edit_move_forward3 (edit, edit_bol (edit, edit->curs1), x, 0) - edit->curs1);
+	}
+	edit_set_markers (edit, 0, 0, 0, 0);
+	edit_push_action (edit, COLUMN_ON);
+	column_highlighting = 0;
+    } else {
+	copy_buf = malloc (end_mark - start_mark);
+	edit_cursor_move (edit, start_mark - edit->curs1);
+	edit_scroll_screen_over_cursor (edit);
+	count = start_mark;
+	while (count < end_mark) {
+	    copy_buf[end_mark - count - 1] = edit_delete (edit);
+	    count++;
+	}
+	edit_scroll_screen_over_cursor (edit);
+	edit_cursor_move (edit, current - edit->curs1 - (((current - edit->curs1) > 0) ? end_mark - start_mark : 0));
+	edit_scroll_screen_over_cursor (edit);
+	while (count-- > start_mark)
+	    edit_insert_ahead (edit, copy_buf[end_mark - count - 1]);
+	edit_set_markers (edit, edit->curs1, edit->curs1 + end_mark - start_mark, 0, 0);
+    }
+    edit_scroll_screen_over_cursor (edit);
+    free (copy_buf);
+    edit->force |= REDRAW_PAGE;
+}
+
+void edit_cursor_to_bol (WEdit * edit);
+
+void edit_delete_column_of_text (WEdit * edit)
+{
+    long p, q, r, m1, m2;
+    int b, c, d;
+    int n;
+
+    eval_marks (edit, &m1, &m2);
+    n = edit_move_forward (edit, m1, 0, m2) + 1;
+    c = edit_move_forward3 (edit, edit_bol (edit, m1), 0, m1);
+    d = edit_move_forward3 (edit, edit_bol (edit, m2), 0, m2);
+
+    b = min (c, d);
+    c = max (c, d);
+
+    while (n--) {
+	r = edit_bol (edit, edit->curs1);
+	p = edit_move_forward3 (edit, r, b, 0);
+	q = edit_move_forward3 (edit, r, c, 0);
+	if (p < m1)
+	    p = m1;
+	if (q > m2)
+	    q = m2;
+	edit_cursor_move (edit, p - edit->curs1);
+	while (q > p) {		/* delete line between margins */
+	    if (edit_get_byte (edit, edit->curs1) != '\n')
+		edit_delete (edit);
+	    q--;
+	}
+	if (n)			/* move to next line except on the last delete */
+	    edit_cursor_move (edit, edit_move_forward (edit, edit->curs1, 1, 0) - edit->curs1);
+    }
+}
+
+int edit_block_delete (WEdit * edit)
+{
+    long count;
+    long start_mark, end_mark;
+    if (eval_marks (edit, &start_mark, &end_mark))
+	return 0;
+    if (column_highlighting && edit->mark2 < 0)
+	edit_mark_cmd (edit, 0);
+    if ((end_mark - start_mark) > option_max_undo / 2)
+/* Warning message with a query to continue or cancel the operation */
+	if (edit_query_dialog2 (_ (" Warning "), _ (" Block is large, you may not be able to undo this action. "), _ (" Continue "), _ (" Cancel ")))
+	    return 1;
+    edit_push_markers (edit);
+    edit_cursor_move (edit, start_mark - edit->curs1);
+    edit_scroll_screen_over_cursor (edit);
+    count = start_mark;
+    if (start_mark < end_mark) {
+	if (column_highlighting) {
+	    if (edit->mark2 < 0)
+		edit_mark_cmd (edit, 0);
+	    edit_delete_column_of_text (edit);
+	} else {
+	    while (count < end_mark) {
+		edit_delete (edit);
+		count++;
+	    }
+	}
+    }
+    edit_set_markers (edit, 0, 0, 0, 0);
+    edit->force |= REDRAW_PAGE;
+    return 0;
+}
+
+/* returns 1 if canceelled by user */
+int edit_block_delete_cmd (WEdit * edit)
+{
+    long start_mark, end_mark;
+    if (eval_marks (edit, &start_mark, &end_mark)) {
+	edit_delete_line (edit);
+	return 0;
+    }
+    return edit_block_delete (edit);
+}
+
+
+#ifdef MIDNIGHT
+
+#define INPUT_INDEX 9
+#define SEARCH_DLG_HEIGHT 10
+#define REPLACE_DLG_HEIGHT 15
+#define B_REPLACE_ALL B_USER+1
+#define B_SKIP_REPLACE B_USER+2
+
+int edit_replace_prompt (WEdit * edit, char *replace_text, int xpos, int ypos)
+{
+    if (replace_prompt) {
+	QuickWidget quick_widgets[] =
+	{
+/* NLS  for hotkeys? */
+	    {quick_button, 14, 18, 3, 6, "&Cancel", 0, B_CANCEL, 0,
+	     0, XV_WLAY_DONTCARE, NULL},
+	    {quick_button, 9, 18, 3, 6, "Replace &all", 0, B_REPLACE_ALL, 0,
+	     0, XV_WLAY_DONTCARE, NULL},
+	    {quick_button, 6, 18, 3, 6, "&Skip", 0, B_SKIP_REPLACE, 0,
+	     0, XV_WLAY_DONTCARE, NULL},
+	    {quick_button, 2, 18, 3, 6, "&Replace", 0, B_ENTER, 0,
+	     0, XV_WLAY_DONTCARE, NULL},
+	    {quick_label, 2, 50, 2, 6, 0,
+	     0, 0, 0, XV_WLAY_DONTCARE, 0},
+	    {0}};
+
+	quick_widgets[4].text = catstrs (_(" Replace with: "), replace_text, 0);
+
+	{
+	    QuickDialog Quick_input =
+	    {66, 6, 0, 0, N_(" Replace "),
+	     "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
+
+	    Quick_input.widgets = quick_widgets;
+
+	    Quick_input.xpos = xpos;
+	    Quick_input.ypos = ypos;
+	    return quick_dialog (&Quick_input);
+	}
+    } else
+	return 0;
+}
+
+
+
+void edit_replace_dialog (WEdit * edit, char **search_text, char **replace_text, char **arg_order)
+{
+    int treplace_scanf = replace_scanf;
+    int treplace_regexp = replace_regexp;
+    int treplace_all = replace_all;
+    int treplace_prompt = replace_prompt;
+    int treplace_backwards = replace_backwards;
+    int treplace_whole = replace_whole;
+    int treplace_case = replace_case;
+
+    char *tsearch_text;
+    char *treplace_text;
+    char *targ_order;
+    QuickWidget quick_widgets[] =
+    {
+	{quick_button, 6, 10, 12, REPLACE_DLG_HEIGHT, "&Cancel", 0, B_CANCEL, 0,
+	 0, XV_WLAY_DONTCARE, NULL},
+	{quick_button, 2, 10, 12, REPLACE_DLG_HEIGHT, "&Ok", 0, B_ENTER, 0,
+	 0, XV_WLAY_DONTCARE, NULL},
+	{quick_checkbox, 25, 50, 11, REPLACE_DLG_HEIGHT, "Scanf &expression", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{quick_checkbox, 25, 50, 10, REPLACE_DLG_HEIGHT, "Replace &all", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{quick_checkbox, 25, 50, 9, REPLACE_DLG_HEIGHT, "Pr&ompt on replace", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{quick_checkbox, 4, 50, 11, REPLACE_DLG_HEIGHT, "&Backwards", 0, 0, 
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{quick_checkbox, 4, 50, 10, REPLACE_DLG_HEIGHT, "&Regular exprssn", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{quick_checkbox, 4, 50, 9, REPLACE_DLG_HEIGHT, "&Whole words only", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{quick_checkbox, 4, 50, 8, REPLACE_DLG_HEIGHT, "Case &sensitive", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{quick_input,    3, 50, 7, REPLACE_DLG_HEIGHT, "", 44, 0, 0,
+	 0, XV_WLAY_BELOWCLOSE, "edit-argord"},
+	{quick_label, 2, 50, 6, REPLACE_DLG_HEIGHT, " Enter replacement argument order eg. 3,2,1,4 ", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, 0},
+	{quick_input, 3, 50, 5, REPLACE_DLG_HEIGHT, "", 44, 0, 0,
+	 0, XV_WLAY_BELOWCLOSE, "edit-replace"},
+	{quick_label, 2, 50, 4, REPLACE_DLG_HEIGHT, " Enter replacement string", 0, 0, 0,
+	 0, XV_WLAY_DONTCARE, 0},
+	{quick_input, 3, 50, 3, REPLACE_DLG_HEIGHT, "", 44, 0, 0,
+	 0, XV_WLAY_BELOWCLOSE, "edit-search"},
+	{quick_label, 2, 50, 2, REPLACE_DLG_HEIGHT, " Enter search string", 0, 0, 0,
+	 0, XV_WLAY_DONTCARE, 0},
+	{0}};
+
+    quick_widgets[2].result = &treplace_scanf;
+    quick_widgets[3].result = &treplace_all;
+    quick_widgets[4].result = &treplace_prompt;
+    quick_widgets[5].result = &treplace_backwards;
+    quick_widgets[6].result = &treplace_regexp;
+    quick_widgets[7].result = &treplace_whole;
+    quick_widgets[8].result = &treplace_case;
+    quick_widgets[9].str_result = &targ_order;
+    quick_widgets[9].text = *arg_order;
+    quick_widgets[11].str_result = &treplace_text;
+    quick_widgets[11].text = *replace_text;
+    quick_widgets[13].str_result = &tsearch_text;
+    quick_widgets[13].text = *search_text;
+    {
+	QuickDialog Quick_input =
+	{50, REPLACE_DLG_HEIGHT, -1, 0, N_(" Replace "),
+	 "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
+
+	Quick_input.widgets = quick_widgets;
+
+	if (quick_dialog (&Quick_input) != B_CANCEL) {
+	    *arg_order = *(quick_widgets[INPUT_INDEX].str_result);
+	    *replace_text = *(quick_widgets[INPUT_INDEX + 2].str_result);
+	    *search_text = *(quick_widgets[INPUT_INDEX + 4].str_result);
+	    replace_scanf = treplace_scanf;
+	    replace_backwards = treplace_backwards;
+	    replace_regexp = treplace_regexp;
+	    replace_all = treplace_all;
+	    replace_prompt = treplace_prompt;
+	    replace_whole = treplace_whole;
+	    replace_case = treplace_case;
+	    return;
+	} else {
+	    *arg_order = NULL;
+	    *replace_text = NULL;
+	    *search_text = NULL;
+	    return;
+	}
+    }
+}
+
+
+void edit_search_dialog (WEdit * edit, char **search_text)
+{
+    int treplace_scanf = replace_scanf;
+    int treplace_regexp = replace_regexp;
+    int treplace_whole = replace_whole;
+    int treplace_case = replace_case;
+    int treplace_backwards = replace_backwards;
+
+    char *tsearch_text;
+    QuickWidget quick_widgets[] =
+    {
+	{quick_button, 6, 10, 7, SEARCH_DLG_HEIGHT, "&Cancel", 0, B_CANCEL, 0,
+	 0, XV_WLAY_DONTCARE, NULL},
+	{quick_button, 2, 10, 7, SEARCH_DLG_HEIGHT, "&Ok", 0, B_ENTER, 0,
+	 0, XV_WLAY_DONTCARE, NULL},
+	{quick_checkbox, 25, 50, 6, SEARCH_DLG_HEIGHT, "Scanf &expression", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL },
+	{quick_checkbox, 25, 50, 5, SEARCH_DLG_HEIGHT, "&Backwards", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{quick_checkbox, 4, 50, 6, SEARCH_DLG_HEIGHT, "&Regular exprssn", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{quick_checkbox, 4, 50, 5, SEARCH_DLG_HEIGHT, "&Whole words only", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{quick_checkbox, 4, 50, 4, SEARCH_DLG_HEIGHT, "Case &sensitive", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{quick_input, 3, 50, 3, SEARCH_DLG_HEIGHT, "", 44, 0, 0,
+	 0, XV_WLAY_BELOWCLOSE, "edit-search"},
+	{quick_label, 2, 50, 2, SEARCH_DLG_HEIGHT, " Enter search string", 0, 0, 0,
+	 0, XV_WLAY_DONTCARE, 0},
+	{0}};
+
+    quick_widgets[2].result = &treplace_scanf;
+    quick_widgets[3].result = &treplace_backwards;
+    quick_widgets[4].result = &treplace_regexp;
+    quick_widgets[5].result = &treplace_whole;
+    quick_widgets[6].result = &treplace_case;
+    quick_widgets[7].str_result = &tsearch_text;
+    quick_widgets[7].text = *search_text;
+
+    {
+	QuickDialog Quick_input =
+	{50, SEARCH_DLG_HEIGHT, -1, 0, N_(" Search "),
+	 "[Input Line Keys]", "quick_input", 0 /*quick_widgets */ };
+
+	Quick_input.widgets = quick_widgets;
+
+	if (quick_dialog (&Quick_input) != B_CANCEL) {
+	    *search_text = *(quick_widgets[7].str_result);
+	    replace_scanf = treplace_scanf;
+	    replace_backwards = treplace_backwards;
+	    replace_regexp = treplace_regexp;
+	    replace_whole = treplace_whole;
+	    replace_case = treplace_case;
+	    return;
+	} else {
+	    *search_text = NULL;
+	    return;
+	}
+    }
+}
+
+
+#else
+
+#define B_ENTER 0
+#define B_SKIP_REPLACE 1
+#define B_REPLACE_ALL 2
+#define B_CANCEL 3
+
+extern CWidget *wedit;
+
+#ifndef GTK
+
+void edit_search_replace_dialog (Window parent, int x, int y, char **search_text, char **replace_text, char **arg_order, char *heading, int option)
+{
+    Window win;
+    XEvent xev;
+    CEvent cev;
+    CState s;
+    int xh, yh, h, xb, ys, yc, yb, yr;
+    CWidget *m;
+
+    CBackupState (&s);
+    CDisable ("*");
+
+    win = CDrawHeadedDialog ("replace", parent, x, y, heading);
+    CGetHintPos (&xh, &h);
+
+/* NLS hotkey ? */
+    CIdent ("replace")->position = WINDOW_ALWAYS_RAISED;
+/* An input line comes after the ':' */
+    (CDrawText ("replace.t1", win, xh, h, _(" Enter search text : ")))->hotkey = 'E';
+
+    CGetHintPos (0, &yh);
+    (m = CDrawTextInput ("replace.sinp", win, xh, yh, 10, AUTO_HEIGHT, 256, *search_text))->hotkey = 'E';
+
+    if (replace_text) {
+	CGetHintPos (0, &yh);
+	(CDrawText ("replace.t2", win, xh, yh, _(" Enter replace text : ")))->hotkey = 'n';
+	CGetHintPos (0, &yh);
+	(CDrawTextInput ("replace.rinp", win, xh, yh, 10, AUTO_HEIGHT, 256, *replace_text))->hotkey = 'n';
+	CGetHintPos (0, &yh);
+	(CDrawText ("replace.t3", win, xh, yh, _(" Enter argument order : ")))->hotkey = 'o';
+	CGetHintPos (0, &yh);
+	(CDrawTextInput ("replace.ainp", win, xh, yh, 10, AUTO_HEIGHT, 256, *arg_order))->hotkey = 'o';
+/* Tool hint */
+	CSetToolHint ("replace.ainp", _("Enter the order of replacement of your scanf format specifiers"));
+	CSetToolHint ("replace.t3", _("Enter the order of replacement of your scanf format specifiers"));
+    }
+    CGetHintPos (0, &yh);
+    ys = yh;
+/* The following are check boxes */
+    CDrawSwitch ("replace.ww", win, xh, yh, replace_whole, _(" Whole words only "), 0);
+    CGetHintPos (0, &yh);
+    CDrawSwitch ("replace.case", win, xh, yh, replace_case, _(" Case sensitive "), 0);
+    yc = yh;
+    CGetHintPos (0, &yh);
+    CDrawSwitch ("replace.reg", win, xh, yh, replace_regexp, _(" Regular expression "), 1);
+    CSetToolHint ("replace.reg", _("See the regex man page for how to compose a regular expression"));
+    CSetToolHint ("replace.reg.label", _("See the regex man page for how to compose a regular expression"));
+    yb = yh;
+    CGetHintPos (0, &yh);
+    CGetHintPos (&xb, 0);
+
+    if (option & SEARCH_DIALOG_OPTION_BACKWARDS) {
+	CDrawSwitch ("replace.bkwd", win, xh, yh, replace_backwards, _(" Backwards "), 0);
+/* Tool hint */
+	CSetToolHint ("replace.bkwd", _("Warning: Searching backward can be slow"));
+	CSetToolHint ("replace.bkwd.label", _("Warning: Searching backward can be slow"));
+	yb = yh;
+    }
+    if (replace_text) {
+	if (option & SEARCH_DIALOG_OPTION_BACKWARDS)
+	    yr = yc;
+	else
+	    yr = ys;
+    } else {
+	yr = yb;
+    }
+
+    if (replace_text) {
+	CDrawSwitch ("replace.pr", win, xb, yr, replace_prompt, _(" Prompt on replace "), 0);
+/* Tool hint */
+	CSetToolHint ("replace.pr", _("Ask before making each replacement"));
+	CGetHintPos (0, &yr);
+	CDrawSwitch ("replace.all", win, xb, yr, replace_all, _(" Replace all "), 0);
+	CGetHintPos (0, &yr);
+    }
+    CDrawSwitch ("replace.scanf", win, xb, yr, replace_scanf, _(" Scanf expression "), 1);
+/* Tool hint */
+    CSetToolHint ("replace.scanf", _("Allows entering of a C format string, see the scanf man page"));
+
+    get_hint_limits (&x, &y);
+    CDrawPixmapButton ("replace.ok", win, x - WIDGET_SPACING - TICK_BUTTON_WIDTH, h, PIXMAP_BUTTON_TICK);
+/* Tool hint */
+    CSetToolHint ("replace.ok", _("Begin search, Enter"));
+    CDrawPixmapButton ("replace.cancel", win, x - WIDGET_SPACING - TICK_BUTTON_WIDTH, h + WIDGET_SPACING + TICK_BUTTON_WIDTH, PIXMAP_BUTTON_CROSS);
+/* Tool hint */
+    CSetToolHint ("replace.cancel", _("Abort this dialog, Esc"));
+    CSetSizeHintPos ("replace");
+    CMapDialog ("replace");
+
+    m = CIdent ("replace");
+    CSetWidgetSize ("replace.sinp", m->width - WIDGET_SPACING * 3 - 4 - TICK_BUTTON_WIDTH, (CIdent ("replace.sinp"))->height);
+    if (replace_text) {
+	CSetWidgetSize ("replace.rinp", m->width - WIDGET_SPACING * 3 - 4 - TICK_BUTTON_WIDTH, (CIdent ("replace.rinp"))->height);
+	CSetWidgetSize ("replace.ainp", m->width - WIDGET_SPACING * 3 - 4 - TICK_BUTTON_WIDTH, (CIdent ("replace.ainp"))->height);
+    }
+    CFocus (CIdent ("replace.sinp"));
+
+    for (;;) {
+	CNextEvent (&xev, &cev);
+	if (!CIdent ("replace")) {
+	    *search_text = 0;
+	    break;
+	}
+	if (!strcmp (cev.ident, "replace.cancel") || cev.command == CK_Cancel) {
+	    *search_text = 0;
+	    break;
+	}
+	if (!strcmp (cev.ident, "replace.reg") || !strcmp (cev.ident, "replace.scanf")) {
+	    if (CIdent ("replace.reg")->keypressed || CIdent ("replace.scanf")->keypressed) {
+		if (!(CIdent ("replace.case")->keypressed)) {
+		    CIdent ("replace.case")->keypressed = 1;
+		    CExpose ("replace.case");
+		}
+	    }
+	}
+	if (!strcmp (cev.ident, "replace.ok") || cev.command == CK_Enter) {
+	    if (replace_text) {
+		replace_all = CIdent ("replace.all")->keypressed;
+		replace_prompt = CIdent ("replace.pr")->keypressed;
+		*replace_text = strdup (CIdent ("replace.rinp")->text);
+		*arg_order = strdup (CIdent ("replace.ainp")->text);
+	    }
+	    *search_text = strdup (CIdent ("replace.sinp")->text);
+	    replace_whole = CIdent ("replace.ww")->keypressed;
+	    replace_case = CIdent ("replace.case")->keypressed;
+	    replace_scanf = CIdent ("replace.scanf")->keypressed;
+	    replace_regexp = CIdent ("replace.reg")->keypressed;
+
+	    if (option & SEARCH_DIALOG_OPTION_BACKWARDS) {
+		replace_backwards = CIdent ("replace.bkwd")->keypressed;
+	    } else {
+		replace_backwards = 0;
+	    }
+
+	    break;
+	}
+    }
+    CDestroyWidget ("replace");
+    CRestoreState (&s);
+}
+
+void edit_search_dialog (WEdit * edit, char **search_text)
+{
+/* Heads the 'Search' dialog box */
+    edit_search_replace_dialog (WIN_MESSAGES, search_text, 0, 0, _(" Search "), SEARCH_DIALOG_OPTION_BACKWARDS);
+}
+
+void edit_replace_dialog (WEdit * edit, char **search_text, char **replace_text, char **arg_order)
+{
+/* Heads the 'Replace' dialog box */
+    edit_search_replace_dialog (WIN_MESSAGES, search_text, replace_text, arg_order, _(" Replace "), SEARCH_DIALOG_OPTION_BACKWARDS);
+}
+
+#else
+
+#include <libgnomeui/gtkcauldron.h>
+#include <libgnomeui/gnome-stock.h>
+
+void edit_search_dialog (WEdit * edit, char **search_text)
+{
+    char *s;
+    s = gtk_dialog_cauldron (
+				"Search", GTK_CAULDRON_TOPLEVEL,
+				" ( (Enter search text)d | %Egxf )xf / ( ( %Cd // %Cd // %Cd ) || ( %Cd // %Cd )xf )xf / ( %Bxfgrq || %Bxfgq )f",
+				search_text, "search",
+				"Whole word", &replace_whole,
+				"Case sensitive", &replace_case,
+				"Regular expression", &replace_regexp,
+				"Backwards", &replace_backwards,
+				"Scanf expression", &replace_scanf,
+				GNOME_STOCK_BUTTON_OK,
+				GNOME_STOCK_BUTTON_CANCEL
+	);
+    if (s == GTK_CAULDRON_ESCAPE || !s || s == GNOME_STOCK_BUTTON_CANCEL)
+	*search_text = 0;
+    return;
+}
+
+void edit_replace_dialog (WEdit * edit, char **search_text, char **replace_text, char **arg_order)
+{
+    char *s;
+    s = gtk_dialog_cauldron (
+				"Search", GTK_CAULDRON_TOPLEVEL,
+				" ( (Enter search text)d | %Egxf )xf / ( (Enter replace text)d | %Egxf )xf / ( (Enter argument order)d | %Egxf )xf / ( ( %Cd // %Cd // %Cd // %Cd ) || ( %Cd // %Cd // %Cd )xf )xf / ( %Bxfgrq || %Bxfgq )f",
+				search_text, "search",
+				replace_text, "replace",
+				arg_order, "arg_order",
+				"Whole word", &replace_whole,
+				"Case sensitive", &replace_case,
+				"Regular expression", &replace_regexp,
+				"Backwards", &replace_backwards,
+				"Prompt on replace", &replace_prompt,
+				"Replace all", &replace_all,
+				"Scanf expression", &replace_scanf,
+				GNOME_STOCK_BUTTON_OK,
+				GNOME_STOCK_BUTTON_CANCEL
+	);
+    if (s == GTK_CAULDRON_ESCAPE || !s || s == GNOME_STOCK_BUTTON_CANCEL)
+	*search_text = 0;
+    return;
+}
+
+#endif
+
+#ifdef GTK
+
+int edit_replace_prompt (WEdit * edit, char *replace_text, int xpos, int ypos)
+{
+    if (replace_prompt) {
+	char *s;
+	s = gtk_dialog_cauldron (
+				    "Replace", GTK_CAULDRON_TOPLEVEL,
+		  " ( (Replace with:)d %Ld )xf / ( %Bxfrq || %Bxfq || %Bxfq || %Bxfgq )f",
+				    replace_text,
+				    "Replace", "Skip", "Replace All",
+				    GNOME_STOCK_BUTTON_CANCEL
+	    );
+	if (s == GTK_CAULDRON_ESCAPE || !s || s == GNOME_STOCK_BUTTON_CANCEL)
+	    return B_CANCEL;
+	if (!strcmp (s, "Replace All"))
+	    return B_REPLACE_ALL;
+	if (!strcmp (s, "Skip"))
+	    return B_SKIP_REPLACE;
+	if (!strcmp (s, "Replace"))
+	    return B_ENTER;
+    }
+    return 0;
+}
+
+#else
+
+int edit_replace_prompt (WEdit * edit, char *replace_text, int xpos, int ypos)
+{
+    if (replace_prompt) {
+	int q;
+	char *p, *r = 0;
+	r = p = malloc (strlen (replace_text) + NUM_REPL_ARGS * 2);
+	strcpy (p, replace_text);
+	while ((p = strchr (p, '%'))) {		/* convert "%" to "%%" so no convertion is attempted */
+	    memmove (p + 2, p + 1, strlen (p) + 1);
+	    *(++p) = '%';
+	    p++;
+	}
+	edit->force |= REDRAW_COMPLETELY;
+	q = edit_query_dialog4 (_(" Replace "), 
+/* This is for the confirm replace dialog box. The replaced string comes after the ':' */
+	catstrs (_(" Replace with: "), r, 0), 
+/* Buttons for the confirm replace dialog box. */
+	_("Replace"), _("Skip"), _("Replace all"), _("Cancel"));
+	if (r)
+	    free (r);
+	switch (q) {
+	case 0:
+	    return B_ENTER;
+	case 1:
+	    return B_SKIP_REPLACE;
+	case 2:
+	    return B_REPLACE_ALL;
+	case -1:
+	case 3:
+	    return B_CANCEL;
+	}
+    }
+    return 0;
+}
+
+#endif
+
+#endif
+
+long sargs[NUM_REPL_ARGS][256 / sizeof (long)];
+
+#define SCANF_ARGS sargs[0], sargs[1], sargs[2], sargs[3], \
+		     sargs[4], sargs[5], sargs[6], sargs[7], \
+		     sargs[8], sargs[9], sargs[10], sargs[11], \
+		     sargs[12], sargs[13], sargs[14], sargs[15]
+
+#define PRINTF_ARGS sargs[argord[0]], sargs[argord[1]], sargs[argord[2]], sargs[argord[3]], \
+		     sargs[argord[4]], sargs[argord[5]], sargs[argord[6]], sargs[argord[7]], \
+		     sargs[argord[8]], sargs[argord[9]], sargs[argord[10]], sargs[argord[11]], \
+		     sargs[argord[12]], sargs[argord[13]], sargs[argord[14]], sargs[argord[15]]
+
+/* This function is a modification of mc-3.2.10/src/view.c:regexp_view_search() */
+/* returns -3 on error in pattern, -1 on not found, found_len = 0 if either */
+int string_regexp_search (char *pattern, char *string, int len, int match_type, int match_bol, int icase, int *found_len)
+{
+    static regex_t r;
+    regmatch_t pmatch[1];
+    static char *old_pattern = NULL;
+    static int old_type, old_icase;
+
+    if (!old_pattern || strcmp (old_pattern, pattern) || old_type != match_type || old_icase != icase) {
+	if (old_pattern) {
+	    regfree (&r);
+	    free (old_pattern);
+	    old_pattern = 0;
+	}
+	if (regcomp (&r, pattern, REG_EXTENDED | (icase ? REG_ICASE : 0))) {
+	    *found_len = 0;
+	    return -3;
+	}
+	old_pattern = strdup (pattern);
+	old_type = match_type;
+	old_icase = icase;
+    }
+    if (regexec (&r, string, 1, pmatch, ((match_bol || match_type != match_normal) ? 0 : REG_NOTBOL)) != 0) {
+	*found_len = 0;
+	return -1;
+    }
+    *found_len = pmatch[0].rm_eo - pmatch[0].rm_so;
+    return (pmatch[0].rm_so);
+}
+
+/* thanks to  Liviu Daia <daia@stoilow.imar.ro>  for getting this
+   (and the above) routines to work properly - paul */
+
+long edit_find_string (long start, unsigned char *exp, int *len, long last_byte, int (*get_byte) (void *, long), void *data, int once_only)
+{
+    long p, q = 0;
+    long l = strlen ((char *) exp), f = 0;
+    int n = 0;
+
+    for (p = 0; p < l; p++)	/* count conversions... */
+	if (exp[p] == '%')
+	    if (exp[++p] != '%')	/* ...except for "%%" */
+		n++;
+
+    if (replace_scanf || replace_regexp) {
+	int c;
+	unsigned char *buf;
+	unsigned char mbuf[MAX_REPL_LEN * 2 + 3];
+
+	replace_scanf = (!replace_regexp);	/* can't have both */
+
+	buf = mbuf;
+
+	if (replace_scanf) {
+	    unsigned char e[MAX_REPL_LEN];
+	    if (n >= NUM_REPL_ARGS)
+		return -3;
+
+	    if (replace_case) {
+		for (p = start; p < last_byte && p < start + MAX_REPL_LEN; p++)
+		    buf[p - start] = (*get_byte) (data, p);
+	    } else {
+		for (p = 0; exp[p] != 0; p++)
+		    exp[p] = my_lower_case (exp[p]);
+		for (p = start; p < last_byte && p < start + MAX_REPL_LEN; p++) {
+		    c = (*get_byte) (data, p);
+		    buf[p - start] = my_lower_case (c);
+		}
+	    }
+
+	    buf[(q = p - start)] = 0;
+	    strcpy ((char *) e, (char *) exp);
+	    strcat ((char *) e, "%n");
+	    exp = e;
+
+	    while (q) {
+		*((int *) sargs[n]) = 0;	/* --> here was the problem - now fixed: good */
+		if (n == sscanf ((char *) buf, (char *) exp, SCANF_ARGS)) {
+		    if (*((int *) sargs[n])) {
+			*len = *((int *) sargs[n]);
+			return start;
+		    }
+		}
+		if (once_only)
+		    return -2;
+		if (q + start < last_byte) {
+		    if (replace_case) {
+			buf[q] = (*get_byte) (data, q + start);
+		    } else {
+			c = (*get_byte) (data, q + start);
+			buf[q] = my_lower_case (c);
+		    }
+		    q++;
+		}
+		buf[q] = 0;
+		start++;
+		buf++;		/* move the window along */
+		if (buf == mbuf + MAX_REPL_LEN) {	/* the window is about to go past the end of array, so... */
+		    memmove (mbuf, buf, strlen ((char *) buf) + 1);	/* reset it */
+		    buf = mbuf;
+		}
+		q--;
+	    }
+	} else {	/* regexp matching */
+	    long offset = 0;
+	    int found_start, match_bol, move_win = 0; 
+
+	    while (start + offset < last_byte) {
+		match_bol = (offset == 0 || (*get_byte) (data, start + offset - 1) == '\n');
+		if (!move_win) {
+		    p = start + offset;
+		    q = 0;
+		}
+		for (; p < last_byte && q < MAX_REPL_LEN; p++, q++) {
+		    mbuf[q] = (*get_byte) (data, p);
+		    if (mbuf[q] == '\n')
+			break;
+		}
+		q++;
+		offset += q;
+		mbuf[q] = 0;
+
+		buf = mbuf;
+		while (q) {
+		    found_start = string_regexp_search ((char *) exp, (char *) buf, q, match_normal, match_bol, !replace_case, len);
+
+		    if (found_start <= -2) {	/* regcomp/regexec error */
+			*len = 0;
+			return -3;
+		    }
+		    else if (found_start == -1)	/* not found: try next line */
+			break;
+		    else if (*len == 0) { /* null pattern: try again at next character */
+			q--;
+			buf++;
+			match_bol = 0;
+			continue;
+		    }
+		    else	/* found */
+			return (start + offset - q + found_start);
+		}
+		if (once_only)
+		    return -2;
+
+		if (buf[q - 1] != '\n') { /* incomplete line: try to recover */
+		    buf = mbuf + MAX_REPL_LEN / 2;
+		    q = strlen ((char *) buf);
+		    memmove (mbuf, buf, q);
+		    p = start + q;
+		    move_win = 1;
+		}
+		else
+		    move_win = 0;
+	    }
+	}
+    } else {
+ 	*len = strlen ((char *) exp);
+	if (replace_case) {
+	    for (p = start; p <= last_byte - l; p++) {
+ 		if ((*get_byte) (data, p) == (unsigned char)exp[0]) {	/* check if first char matches */
+		    for (f = 0, q = 0; q < l && f < 1; q++)
+ 			if ((*get_byte) (data, q + p) != (unsigned char)exp[q])
+			    f = 1;
+		    if (f == 0)
+			return p;
+		}
+		if (once_only)
+		    return -2;
+	    }
+	} else {
+	    for (p = 0; exp[p] != 0; p++)
+		exp[p] = my_lower_case (exp[p]);
+
+	    for (p = start; p <= last_byte - l; p++) {
+		if (my_lower_case ((*get_byte) (data, p)) == (unsigned char)exp[0]) {
+		    for (f = 0, q = 0; q < l && f < 1; q++)
+			if (my_lower_case ((*get_byte) (data, q + p)) != (unsigned char)exp[q])
+			    f = 1;
+		    if (f == 0)
+			return p;
+		}
+		if (once_only)
+		    return -2;
+	    }
+	}
+    }
+    return -2;
+}
+
+
+long edit_find_forwards (long search_start, unsigned char *exp, int *len, long last_byte, int (*get_byte) (void *, long), void *data, int once_only)
+{				/*front end to find_string to check for
+				   whole words */
+    long p;
+    p = search_start;
+
+    while ((p = edit_find_string (p, exp, len, last_byte, get_byte, data, once_only)) >= 0) {
+	if (replace_whole) {
+/*If the bordering chars are not in option_whole_chars_search then word is whole */
+	    if (!strcasechr (option_whole_chars_search, (*get_byte) (data, p - 1))
+		&& !strcasechr (option_whole_chars_search, (*get_byte) (data, p + *len)))
+		return p;
+	    if (once_only)
+		return -2;
+	} else
+	    return p;
+	if (once_only)
+	    break;
+	p++;			/*not a whole word so continue search. */
+    }
+    return p;
+}
+
+long edit_find (long search_start, unsigned char *exp, int *len, long last_byte, int (*get_byte) (void *, long), void *data)
+{
+    long p;
+    if (replace_backwards) {
+	while (search_start >= 0) {
+	    p = edit_find_forwards (search_start, exp, len, last_byte, get_byte, data, 1);
+	    if (p == search_start)
+		return p;
+	    search_start--;
+	}
+    } else {
+	return edit_find_forwards (search_start, exp, len, last_byte, get_byte, data, 0);
+    }
+    return -2;
+}
+
+#define is_digit(x) ((x) >= '0' && (x) <= '9')
+
+#define snprintf(v) { \
+		*p1++ = *p++; \
+		*p1++ = '%'; \
+		*p1++ = 'n'; \
+		*p1 = '\0'; \
+		sprintf(s,q1,v,&n); \
+		s += n; \
+	    }
+
+/* this function uses the sprintf command to do a vprintf */
+/* it takes pointers to arguments instead of the arguments themselves */
+int sprintf_p (char *str, const char *fmt,...)
+{
+    va_list ap;
+    int n;
+    char *q, *p, *s = str;
+    char q1[32];
+    char *p1;
+
+    va_start (ap, fmt);
+    p = q = (char *) fmt;
+
+    while ((p = strchr (p, '%'))) {
+	n = (int) ((unsigned long) p - (unsigned long) q);
+	strncpy (s, q, n);	/* copy stuff between format specifiers */
+	s += n;
+	*s = 0;
+	q = p;
+	p1 = q1;
+	*p1++ = *p++;
+	if (*p == '%') {
+	    p++;
+	    *s++ = '%';
+	    q = p;
+	    continue;
+	}
+	if (*p == 'n') {
+	    p++;
+/* do nothing */
+	    q = p;
+	    continue;
+	}
+	if (*p == '#')
+	    *p1++ = *p++;
+	if (*p == '0')
+	    *p1++ = *p++;
+	if (*p == '-')
+	    *p1++ = *p++;
+	if (*p == '+')
+	    *p1++ = *p++;
+	if (*p == '*') {
+	    p++;
+	    strcpy (p1, itoa (*va_arg (ap, int *)));	/* replace field width with a number */
+	    p1 += strlen (p1);
+	} else {
+	    while (is_digit (*p))
+		*p1++ = *p++;
+	}
+	if (*p == '.')
+	    *p1++ = *p++;
+	if (*p == '*') {
+	    p++;
+	    strcpy (p1, itoa (*va_arg (ap, int *)));	/* replace precision with a number */
+	    p1 += strlen (p1);
+	} else {
+	    while (is_digit (*p))
+		*p1++ = *p++;
+	}
+/* flags done, now get argument */
+	if (*p == 's') {
+	    snprintf (va_arg (ap, char *));
+	} else if (*p == 'h') {
+	    if (strchr ("diouxX", *p))
+		snprintf (*va_arg (ap, short *));
+	} else if (*p == 'l') {
+	    *p1++ = *p++;
+	    if (strchr ("diouxX", *p))
+		snprintf (*va_arg (ap, long *));
+	} else if (strchr ("cdiouxX", *p)) {
+	    snprintf (*va_arg (ap, int *));
+	} else if (*p == 'L') {
+	    *p1++ = *p++;
+	    if (strchr ("EefgG", *p))
+		snprintf (*va_arg (ap, double *));	/* should be long double */
+	} else if (strchr ("EefgG", *p)) {
+	    snprintf (*va_arg (ap, double *));
+	} else if (strchr ("DOU", *p)) {
+	    snprintf (*va_arg (ap, long *));
+	} else if (*p == 'p') {
+	    snprintf (*va_arg (ap, void **));
+	}
+	q = p;
+    }
+    va_end (ap);
+    sprintf (s, q);		/* print trailing leftover */
+    return (unsigned long) s - (unsigned long) str + strlen (s);
+}
+
+static void regexp_error (WEdit *edit)
+{
+/* "Error: Syntax error in regular expression, or scanf expression contained too many %'s */
+    edit_error_dialog (_(" Error "), _(" Invalid regular expression, or scanf expression with to many conversions "));
+}
+
+/* call with edit = 0 before shutdown to close memory leaks */
+void edit_replace_cmd (WEdit * edit, int again)
+{
+    static char *old1 = NULL;
+    static char *old2 = NULL;
+    static char *old3 = NULL;
+    char *exp1 = "";
+    char *exp2 = "";
+    char *exp3 = "";
+    int replace_yes;
+    int replace_continue;
+    int i = 0;
+    long times_replaced = 0, last_search;
+    char fin_string[32];
+    int argord[NUM_REPL_ARGS];
+
+    if (!edit) {
+	if (old1) {
+	    free (old1);
+	    old1 = 0;
+	}
+	if (old2) {
+	    free (old2);
+	    old2 = 0;
+	}
+	if (old3) {
+	    free (old3);
+	    old3 = 0;
+	}
+	return;
+    }
+
+    last_search = edit->last_byte;
+
+    edit->force |= REDRAW_COMPLETELY;
+
+    exp1 = old1 ? old1 : exp1;
+    exp2 = old2 ? old2 : exp2;
+    exp3 = old3 ? old3 : exp3;
+
+    if (again) {
+	if (!old1 || !old2)
+	    return;
+	exp1 = strdup (old1);
+	exp2 = strdup (old2);
+	exp3 = strdup (old3);
+    } else {
+	edit_push_action (edit, KEY_PRESS + edit->start_display);
+	edit_replace_dialog (edit, &exp1, &exp2, &exp3);
+    }
+
+    if (!exp1 || !*exp1) {
+	edit->force = REDRAW_COMPLETELY;
+	if (exp1) {
+	    free (exp1);
+	    free (exp2);
+	    free (exp3);
+	}
+	return;
+    }
+    if (old1)
+	free (old1);
+    if (old2)
+	free (old2);
+    if (old3)
+	free (old3);
+    old1 = strdup (exp1);
+    old2 = strdup (exp2);
+    old3 = strdup (exp3);
+
+    {
+	char *s;
+	int ord;
+	while ((s = strchr (exp3, ' ')))
+	    memmove (s, s + 1, strlen (s));
+	s = exp3;
+	for (i = 0; i < NUM_REPL_ARGS; i++) {
+	    if ((unsigned long) s != 1 && s < exp3 + strlen (exp3)) {
+		if ((ord = atoi (s)))
+		    argord[i] = ord - 1;
+		else
+		    argord[i] = i;
+		s = strchr (s, ',') + 1;
+	    } else
+		argord[i] = i;
+	}
+    }
+
+    replace_continue = replace_all;
+
+    if (edit->found_len && edit->search_start == edit->found_start + 1 && replace_backwards)
+	edit->search_start--;
+
+    if (edit->found_len && edit->search_start == edit->found_start - 1 && !replace_backwards)
+	edit->search_start++;
+
+    do {
+	int len = 0;
+	long new_start;
+	new_start = edit_find (edit->search_start, (unsigned char *) exp1, &len, last_search,
+			(int (*) (void *, long)) edit_get_byte, (void *) edit);
+	if (new_start == -3) {
+	    regexp_error (edit);
+	    break;
+	}
+	edit->search_start = new_start;
+	/*returns negative on not found or error in pattern */
+
+	if (edit->search_start >= 0) {
+	    edit->found_start = edit->search_start;
+	    i = edit->found_len = len;
+
+	    edit_cursor_move (edit, edit->search_start - edit->curs1);
+	    edit_scroll_screen_over_cursor (edit);
+
+	    replace_yes = 1;
+
+	    if (replace_prompt) {
+		int l;
+		l = edit->curs_row - edit->num_widget_lines / 3;
+		if (l > 0)
+		    edit_scroll_downward (edit, l);
+		if (l < 0)
+		    edit_scroll_upward (edit, -l);
+
+		edit_scroll_screen_over_cursor (edit);
+		edit->force |= REDRAW_PAGE;
+		edit_render_keypress (edit);
+
+		/*so that undo stops at each query */
+		edit_push_key_press (edit);
+
+		switch (edit_replace_prompt (edit, exp2,	/*and prompt 2/3 down */
+					     edit->num_widget_columns / 2 - 33, edit->num_widget_lines * 2 / 3)) {
+		case B_ENTER:
+		    break;
+		case B_SKIP_REPLACE:
+		    replace_yes = 0;
+		    break;
+		case B_REPLACE_ALL:
+		    replace_prompt = 0;
+		    replace_continue = 1;
+		    break;
+		case B_CANCEL:
+		    replace_yes = 0;
+		    replace_continue = 0;
+		    break;
+		}
+	    }
+	    if (replace_yes) {	/* delete then insert new */
+		if (replace_scanf) {
+		    char repl_str[MAX_REPL_LEN + 2];
+		    if (sprintf_p (repl_str, exp2, PRINTF_ARGS) >= 0) {
+			times_replaced++;
+			while (i--)
+			    edit_delete (edit);
+			while (repl_str[++i])
+			    edit_insert (edit, repl_str[i]);
+		    } else {
+			edit_error_dialog (_(" Replace "), 
+/* "Invalid regexp string or scanf string" */
+			_(" Error in replacement format string. "));
+			replace_continue = 0;
+		    }
+		} else {
+		    times_replaced++;
+		    while (i--)
+			edit_delete (edit);
+		    while (exp2[++i])
+			edit_insert (edit, exp2[i]);
+		}
+		edit->found_len = i;
+	    }
+/* so that we don't find the same string again */
+	    if (replace_backwards) {
+		last_search = edit->search_start;
+		edit->search_start--;
+	    } else {
+		edit->search_start += i;
+		last_search = edit->last_byte;
+	    }
+	    edit_scroll_screen_over_cursor (edit);
+	} else {
+	    edit->search_start = edit->curs1;	/* try and find from right here for next search */
+	    edit_update_curs_col (edit);
+
+	    edit->force |= REDRAW_PAGE;
+	    edit_render_keypress (edit);
+	    if (times_replaced) {
+		sprintf (fin_string, _(" %ld replacements made. "), times_replaced);
+		edit_message_dialog (_(" Replace "), fin_string);
+	    } else
+		edit_message_dialog (_(" Replace "), _(" Search string not found. "));
+	    replace_continue = 0;
+	}
+    } while (replace_continue);
+
+    free (exp1);
+    free (exp2);
+    free (exp3);
+    edit->force = REDRAW_COMPLETELY;
+    edit_scroll_screen_over_cursor (edit);
+}
+
+
+
+
+void edit_search_cmd (WEdit * edit, int again)
+{
+    static char *old = NULL;
+    char *exp = "";
+
+    if (!edit) {
+	if (old) {
+	    free (old);
+	    old = 0;
+	}
+	return;
+    }
+
+    exp = old ? old : exp;
+    if (again) {		/*ctrl-hotkey for search again. */
+	if (!old)
+	    return;
+	exp = strdup (old);
+    } else {
+	edit_search_dialog (edit, &exp);
+	edit_push_action (edit, KEY_PRESS + edit->start_display);
+    }
+
+    if (exp) {
+	if (*exp) {
+	    int len = 0;
+	    if (old)
+		free (old);
+	    old = strdup (exp);
+
+	    if (edit->found_len && edit->search_start == edit->found_start + 1 && replace_backwards)
+		edit->search_start--;
+
+	    if (edit->found_len && edit->search_start == edit->found_start - 1 && !replace_backwards)
+		edit->search_start++;
+
+	    edit->search_start = edit_find (edit->search_start, (unsigned char *) exp, &len, edit->last_byte,
+		   (int (*)(void *, long)) edit_get_byte, (void *) edit);
+
+	    if (edit->search_start >= 0) {
+		edit->found_start = edit->search_start;
+		edit->found_len = len;
+
+		edit_cursor_move (edit, edit->search_start - edit->curs1);
+		edit_scroll_screen_over_cursor (edit);
+		if (replace_backwards)
+		    edit->search_start--;
+		else
+		    edit->search_start++;
+	    } else if (edit->search_start == -3) {
+		edit->search_start = edit->curs1;
+		regexp_error (edit);
+	    } else {
+		edit->search_start = edit->curs1;
+		edit_error_dialog (_(" Search "), _(" Search string not found. "));
+	    }
+	}
+	free (exp);
+    }
+    edit->force |= REDRAW_COMPLETELY;
+    edit_scroll_screen_over_cursor (edit);
+}
+
+
+/* Real edit only */
+void edit_quit_cmd (WEdit * edit)
+{
+    edit_push_action (edit, KEY_PRESS + edit->start_display);
+
+#ifndef MIDNIGHT
+    if (edit->stopped)
+	return;
+#endif
+
+    edit->force |= REDRAW_COMPLETELY;
+    if (edit->modified) {
+#ifdef GTK
+	char *r;
+	r = gtk_dialog_cauldron (_ (" Quit "), GTK_CAULDRON_TOPLEVEL, " [ ( %Lxf )xf ]xf / ( %Bgxfq || %Bgxfq || %Bgxfq ) ",
+				     _ (" Current text was modified without a file save. \n Save with exit? "), GNOME_STOCK_BUTTON_CANCEL, GNOME_STOCK_BUTTON_YES, GNOME_STOCK_BUTTON_NO);
+	if (!strcmp (r, GNOME_STOCK_BUTTON_YES)) {
+	    edit_push_markers (edit);
+	    edit_set_markers (edit, 0, 0, 0, 0);
+	    if (!edit_save_cmd (edit))
+		return;
+	} else if (!strcmp (r, GNOME_STOCK_BUTTON_NO)) {
+	    if (edit->delete_file)
+		unlink (catstrs (edit->dir, edit->filename, 0));
+	} else {
+	    return;
+	}
+#else
+#ifdef MIDNIGHT
+	switch (edit_query_dialog3 (_ (" Quit "), _ (" File was modified, Save with exit? "), _ ("Cancel quit"), _ ("&Yes"), _ ("&No"))) {
+#else
+/* Confirm 'Quit' dialog box */
+	switch (edit_query_dialog3 (_ (" Quit "),
+				    _ (" Current text was modified without a file save. \n Save with exit? "), _ (" &Cancel quit "), _ (" &Yes "), _ (" &No "))) {
+#endif
+	case 1:
+	    edit_push_markers (edit);
+	    edit_set_markers (edit, 0, 0, 0, 0);
+	    if (!edit_save_cmd (edit))
+		return;
+	    break;
+	case 2:
+#ifdef MIDNIGHT
+	    if (edit->delete_file)
+		unlink (catstrs (edit->dir, edit->filename, 0));
+#endif
+	    break;
+	case 0:
+	case -1:
+	    return;
+	}
+#endif
+    }
+#if defined(MIDNIGHT) || defined(GTK)
+    else if (edit->delete_file)
+	unlink (catstrs (edit->dir, edit->filename, 0));
+#endif
+#ifdef MIDNIGHT
+    edit->widget.parent->running = 0;
+#else
+    edit->stopped = 1;
+#endif
+}
+
+#define TEMP_BUF_LEN 1024
+
+/* returns a null terminated length of text. Result must be free'd */
+unsigned char *edit_get_block (WEdit * edit, long start, long finish, int *l)
+{
+    unsigned char *s, *r;
+    r = s = malloc (finish - start + 1);
+    if (column_highlighting) {
+	*l = 0;
+	while (start < finish) {	/* copy from buffer, excluding chars that are out of the column 'margins' */
+	    int c, x;
+	    x = edit_move_forward3 (edit, edit_bol (edit, start), 0, start);
+	    c = edit_get_byte (edit, start);
+	    if ((x >= edit->column1 && x < edit->column2)
+	     || (x >= edit->column2 && x < edit->column1) || c == '\n') {
+		*s++ = c;
+		(*l)++;
+	    }
+	    start++;
+	}
+    } else {
+	*l = finish - start;
+	while (start < finish)
+	    *s++ = edit_get_byte (edit, start++);
+    }
+    *s = 0;
+    return r;
+}
+
+/* save block, returns 1 on success */
+int edit_save_block (WEdit * edit, const char *filename, long start, long finish)
+{
+    int len, file;
+
+    if ((file = open ((char *) filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
+	return 0;
+
+    if (column_highlighting) {
+	unsigned char *block, *p;
+	int r;
+	p = block = edit_get_block (edit, start, finish, &len);
+	while (len) {
+	    r = write (file, p, len);
+	    if (r < 0)
+		break;
+	    p += r;
+	    len -= r;
+	}
+	free (block);
+    } else {
+	unsigned char *buf;
+	int i = start, end;
+	len = finish - start;
+	buf = malloc (TEMP_BUF_LEN);
+	while (start != finish) {
+	    end = min (finish, start + TEMP_BUF_LEN);
+	    for (; i < end; i++)
+		buf[i - start] = edit_get_byte (edit, i);
+	    len -= write (file, (char *) buf, end - start);
+	    start = end;
+	}
+	free (buf);
+    }
+    close (file);
+    if (len)
+	return 0;
+    return 1;
+}
+
+/* copies a block to clipboard file */
+static int edit_save_block_to_clip_file (WEdit * edit, long start, long finish)
+{
+    return edit_save_block (edit, catstrs (home_dir, CLIP_FILE, 0), start, finish);
+}
+
+#ifndef MIDNIGHT
+
+void paste_text (WEdit * edit, unsigned char *data, unsigned int nitems)
+{
+    if (data) {
+	data += nitems - 1;
+	while (nitems--)
+	    edit_insert_ahead (edit, *data--);
+    }
+    edit->force |= REDRAW_COMPLETELY;
+}
+
+char *selection_get_line (void *data, int line)
+{
+    static unsigned char t[1024];
+    struct selection *s;
+    int i = 0;
+    s = (struct selection *) data;
+    line = (current_selection + line + 1) % NUM_SELECTION_HISTORY;
+    if (s[line].text) {
+	unsigned char *p = s[line].text;
+	int c, j;
+	for (j = 0; j < s[line].len; j++) {
+	    c = *p++;
+	    if ((c < ' ' || (c > '~' && c < 160)) && c != '\t') {
+		t[i++] = '.';
+		t[i++] = '\b';
+		t[i++] = '.';
+	    } else
+		t[i++] = c;
+	    if (i > 1020)
+		break;
+	}
+    }
+    t[i] = 0;
+    return (char *) t;
+}
+
+void edit_paste_from_history (WEdit * edit)
+{
+    int i, c;
+
+    edit_update_curs_col (edit);
+    edit_update_curs_row (edit);
+
+    c = max (20, edit->num_widget_columns - 5);
+
+#ifdef GTK
+#if 0
+/* *** */
+    i = gtk_edit_list_box_dialog (c, 10,
+	       0, NUM_SELECTION_HISTORY - 10, NUM_SELECTION_HISTORY - 1, NUM_SELECTION_HISTORY,
+	       selection_get_line, (void *) selection_history);
+#else
+    i = -1;
+#endif
+#else
+    i = CListboxDialog (WIN_MESSAGES, c, 10,
+	       0, NUM_SELECTION_HISTORY - 10, NUM_SELECTION_HISTORY - 1, NUM_SELECTION_HISTORY,
+	       selection_get_line, (void *) selection_history);
+#endif
+
+    if (i < 0)
+	return;
+
+    i = (current_selection + i + 1) % NUM_SELECTION_HISTORY;
+
+    paste_text (edit, selection_history[i].text, selection_history[i].len);
+    edit->force |= REDRAW_COMPLETELY;
+}
+
+/* copies a block to the XWindows buffer */
+static int edit_XStore_block (WEdit * edit, long start, long finish)
+{
+    edit_get_selection (edit);
+    if (selection.len <= 512 * 1024) {	/* we don't want to fill up the server */
+	XStoreBytes (CDisplay, (char *) selection.text, (int) selection.len);
+	return 0;
+    } else
+	return 1;
+}
+
+int edit_copy_to_X_buf_cmd (WEdit * edit)
+{
+    long start_mark, end_mark;
+    if (eval_marks (edit, &start_mark, &end_mark))
+	return 0;
+    edit_XStore_block (edit, start_mark, end_mark);
+    if (!edit_save_block_to_clip_file (edit, start_mark, end_mark)) {
+	edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
+	return 1;
+    }
+#ifdef GTK
+#if 0
+    gtk_set_selection_owner (CWindowOf (edit->widget));
+#else
+    /* *** */
+    printf ("gtk_set_selection_owner\n");
+#endif
+#else
+    XSetSelectionOwner (CDisplay, XA_PRIMARY, CWindowOf (edit->widget), CurrentTime);
+#endif
+    edit_mark_cmd (edit, 1);
+    return 0;
+}
+
+int edit_cut_to_X_buf_cmd (WEdit * edit)
+{
+    long start_mark, end_mark;
+    if (eval_marks (edit, &start_mark, &end_mark))
+	return 0;
+    edit_XStore_block (edit, start_mark, end_mark);
+    if (!edit_save_block_to_clip_file (edit, start_mark, end_mark)) {
+	edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
+	return 1;
+    }
+    edit_block_delete_cmd (edit);
+#ifdef GTK
+#if 0
+    gtk_set_selection_owner (CWindowOf (edit->widget));
+#else
+    printf ("gtk_set_selection_owner\n");
+#endif
+#else
+    XSetSelectionOwner (CDisplay, XA_PRIMARY, CWindowOf (edit->widget), CurrentTime);
+#endif
+    edit_mark_cmd (edit, 1);
+    return 0;
+}
+
+void selection_paste (WEdit * edit, Window win, unsigned prop, int delete);
+
+void edit_paste_from_X_buf_cmd (WEdit * edit)
+{
+    if (selection.text)
+	paste_text (edit, selection.text, selection.len);
+    else if (!XGetSelectionOwner (CDisplay, XA_PRIMARY))
+#ifdef GTK
+/* *** */
+	;
+#else
+	selection_paste (edit, CRoot, XA_CUT_BUFFER0, False);
+#endif
+    else
+#ifdef GTK
+#if 0
+    gtk_convert_selection ();
+#else
+    /* *** */
+#endif
+#else
+	XConvertSelection (CDisplay, XA_PRIMARY, XA_STRING,
+			   XInternAtom (CDisplay, "VT_SELECTION", False),
+			   CWindowOf (edit->widget), CurrentTime);
+#endif
+    edit->force |= REDRAW_PAGE;
+}
+
+#else				/* MIDNIGHT */
+
+void edit_paste_from_history (WEdit *edit)
+{
+}
+
+int edit_copy_to_X_buf_cmd (WEdit * edit)
+{
+    long start_mark, end_mark;
+    if (eval_marks (edit, &start_mark, &end_mark))
+	return 0;
+    if (!edit_save_block_to_clip_file (edit, start_mark, end_mark)) {
+	edit_error_dialog (_(" Copy to clipboard "), get_sys_error (_(" Unable to save to file. ")));
+	return 1;
+    }
+    edit_mark_cmd (edit, 1);
+    return 0;
+}
+
+int edit_cut_to_X_buf_cmd (WEdit * edit)
+{
+    long start_mark, end_mark;
+    if (eval_marks (edit, &start_mark, &end_mark))
+	return 0;
+    if (!edit_save_block_to_clip_file (edit, start_mark, end_mark)) {
+	edit_error_dialog (_(" Cut to clipboard "), _(" Unable to save to file. "));
+	return 1;
+    }
+    edit_block_delete_cmd (edit);
+    edit_mark_cmd (edit, 1);
+    return 0;
+}
+
+void edit_paste_from_X_buf_cmd (WEdit * edit)
+{
+    edit_insert_file (edit, catstrs (home_dir, CLIP_FILE, 0));
+}
+
+#endif				/* MIDMIGHT */
+
+void edit_goto_cmd (WEdit *edit)
+{
+    char *f;
+    static int l = 0;
+#ifdef MIDNIGHT
+    char s[12];
+    sprintf (s, "%d", l);
+    f = input_dialog (_(" Goto line "), _(" Enter line: "), l ? s : "");
+#else
+#ifdef GTK
+#if 0
+    f = gtk_edit_dialog_input ("goto", 150, l ? itoa (l) : "", _(" Goto line "), _(" Enter line: "));
+#else
+    /* *** */
+#endif
+#else
+    f = CInputDialog ("goto", WIN_MESSAGES, 150, l ? itoa (l) : "", _(" Goto line "), _(" Enter line: "));
+#endif
+#endif
+    if (f) {
+	if (*f) {
+	    l = atoi (f);
+	    edit_move_display (edit, l - edit->num_widget_lines / 2 - 1);
+	    edit_move_to_line (edit, l - 1);
+	    edit->force |= REDRAW_COMPLETELY;
+	    free (f);
+	}
+    }
+}
+
+/*returns 1 on success */
+int edit_save_block_cmd (WEdit * edit) {
+    long start_mark, end_mark;
+    char *exp;
+    if (eval_marks (edit, &start_mark, &end_mark))
+	return 1;
+
+    exp = edit_get_save_file (edit->dir, catstrs (home_dir, CLIP_FILE, 0), _(" Save Block "));
+
+    edit->force |= REDRAW_COMPLETELY;
+    edit_push_action (edit, KEY_PRESS + edit->start_display);
+
+    if (exp) {
+	if (!*exp) {
+	    free (exp);
+	    return 0;
+	} else {
+	    if (edit_save_block (edit, exp, start_mark, end_mark)) {
+		free (exp);
+		edit->force |= REDRAW_COMPLETELY;
+		return 1;
+	    } else {
+		free (exp);
+		edit->force |= REDRAW_COMPLETELY;
+		edit_error_dialog (_(" Save Block "), get_sys_error (_(" Error trying to save file. ")));
+		return 0;
+	    }
+	}
+    } else
+	return 0;
+}
+
+
+/* inserts a file at the cursor, returns 1 on success */
+int edit_insert_file (WEdit * edit, const char *filename)
+{
+    int i, file, blocklen;
+    long current = edit->curs1;
+    unsigned char *buf;
+
+    if ((file = open ((char *) filename, O_RDONLY)) == -1)
+	return 0;
+    buf = malloc (TEMP_BUF_LEN);
+    while ((blocklen = read (file, (char *) buf, TEMP_BUF_LEN)) > 0) {
+	for (i = 0; i < blocklen; i++)
+	    edit_insert (edit, buf[i]);
+    }
+    edit_cursor_move (edit, current - edit->curs1);
+    free (buf);
+    close (file);
+    if (blocklen)
+	return 0;
+    return 1;
+}
+
+
+/* returns 1 on success */
+int edit_insert_file_cmd (WEdit * edit) {
+    char *exp = edit_get_load_file (edit->dir, catstrs (home_dir, CLIP_FILE, 0), _(" Insert File "));
+    edit->force |= REDRAW_COMPLETELY;
+
+    edit_push_action (edit, KEY_PRESS + edit->start_display);
+
+    if (exp) {
+	if (!*exp) {
+	    free (exp);
+	    return 0;
+	} else {
+	    if (edit_insert_file (edit, exp)) {
+		free (exp);
+		return 1;
+	    } else {
+		free (exp);
+		edit_error_dialog (_(" Insert file "), get_sys_error (_(" Error trying to insert file. ")));
+		return 0;
+	    }
+	}
+    } else
+	return 0;
+}
+
+#ifdef MIDNIGHT
+
+/* sorts a block, returns -1 on system fail, 1 on cancel and 0 on success */
+int edit_sort_cmd (WEdit * edit)
+{
+    static char *old = 0;
+    char *exp;
+    long start_mark, end_mark;
+    int e;
+
+    if (eval_marks (edit, &start_mark, &end_mark)) {
+/* Not essential to translate */
+	edit_error_dialog (_(" Sort block "), _(" You must first highlight a block of text. "));
+	return 0;
+    }
+    edit_save_block (edit, catstrs (home_dir, BLOCK_FILE, 0), start_mark, end_mark);
+
+    exp = old ? old : "";
+
+    exp = input_dialog (_(" Run Sort "), 
+/* Not essential to translate */
+    _(" Enter sort options (see manpage) separated by whitespace: "), "");
+
+    if (!exp)
+	return 1;
+    if (old)
+	free (old);
+    old = exp;
+
+    e = system (catstrs (" sort ", exp, " ", home_dir, BLOCK_FILE, " > ", home_dir, TEMP_FILE, 0));
+    if (e) {
+	if (e == -1 || e == 127) {
+	    edit_error_dialog (_(" Sort "), 
+/* Not essential to translate */
+	    get_sys_error (_(" Error trying to execute sort command ")));
+	} else {
+	    char q[8];
+	    sprintf (q, "%d ", e);
+	    edit_error_dialog (_(" Sort "), 
+/* Not essential to translate */
+	    catstrs (_(" Sort returned non-zero: "), q, 0));
+	}
+	return -1;
+    }
+
+    edit->force |= REDRAW_COMPLETELY;
+
+    if (edit_block_delete_cmd (edit))
+	return 1;
+    edit_insert_file (edit, catstrs (home_dir, TEMP_FILE, 0));
+    return 0;
+}
+
+/* if block is 1, a block must be highlighted and the shell command
+   processes it. If block is 0 the shell command is a straight system
+   command, that just produces some output which is to be inserted */
+void edit_block_process_cmd (WEdit * edit, const char *shell_cmd, int block)
+{
+    long start_mark, end_mark;
+    struct stat s;
+    char *f = NULL, *b = NULL;
+
+    if (block) {
+	if (eval_marks (edit, &start_mark, &end_mark)) {
+	    edit_error_dialog (_(" Process block "), 
+/* Not essential to translate */
+		_(" You must first highlight a block of text. "));
+	    return;
+	}
+	edit_save_block (edit, b = catstrs (home_dir, BLOCK_FILE, 0), start_mark, end_mark);
+	my_system (0, shell, catstrs (home_dir, shell_cmd, 0));
+	edit_refresh_cmd (edit);
+    } else {
+	my_system (0, shell, shell_cmd);
+	edit_refresh_cmd (edit);
+    }
+
+    edit->force |= REDRAW_COMPLETELY;
+
+    f = catstrs (home_dir, ERROR_FILE, 0);
+
+    if (block) {
+	if (stat (f, &s) == 0) {
+	    if (!s.st_size) {	/* no error messages */
+		if (edit_block_delete_cmd (edit))
+		    return;
+		edit_insert_file (edit, b);
+		return;
+	    } else {
+		edit_insert_file (edit, f);
+		return;
+	    }
+	} else {
+/* Not essential to translate */
+	    edit_error_dialog (_(" Process block "), 
+/* Not essential to translate */
+	    get_sys_error (_(" Error trying to stat file ")));
+	    return;
+	}
+    }
+}
+
+#endif
+
+int edit_execute_cmd (WEdit * edit, int command, int char_for_insertion);
+
+/* prints at the cursor */
+/* returns the number of chars printed */
+int edit_print_string (WEdit * e, const char *s)
+{
+    int i = 0;
+    while (s[i])
+	edit_execute_cmd (e, -1, s[i++]);
+    e->force |= REDRAW_COMPLETELY;
+    edit_update_screen (e);
+    return i;
+}
+
+int edit_printf (WEdit * e, const char *fmt,...)
+{
+    int i;
+    va_list pa;
+    char s[1024];
+    va_start (pa, fmt);
+    sprintf (s, fmt, pa);
+    i = edit_print_string (e, s);
+    va_end (pa);
+    return i;
+}
+
+#ifdef MIDNIGHT
+
+/* FIXME: does this function break NT_OS2 ? */
+
+static void pipe_mail (WEdit *edit, char *to, char *subject, char *cc)
+{
+    FILE *p;
+    char *s;
+    s = malloc (4096);
+    sprintf (s, "mail -s \"%s\" -c \"%s\" \"%s\"", subject, cc, to);
+    p = popen (s, "w");
+    if (!p) {
+	free (s);
+	return;
+    } else {
+	long i;
+	for (i = 0; i < edit->last_byte; i++)
+	    fputc (edit_get_byte (edit, i), p);
+	pclose (p);
+    }
+    free (s);
+}
+
+#define MAIL_DLG_HEIGHT 12
+
+void edit_mail_dialog (WEdit * edit)
+{
+    char *tmail_to;
+    char *tmail_subject;
+    char *tmail_cc;
+
+    static char *mail_cc_last = 0;
+    static char *mail_subject_last = 0;
+    static char *mail_to_last = 0;
+
+    QuickDialog Quick_input =
+    {50, MAIL_DLG_HEIGHT, -1, 0, N_(" Mail "),
+/* NLS ? */
+     "[Input Line Keys]", "quick_input", 0};
+
+    QuickWidget quick_widgets[] =
+    {
+/* NLS ? */
+	{quick_button, 6, 10, 9, MAIL_DLG_HEIGHT, "&Cancel", 0, B_CANCEL, 0,
+	 0, XV_WLAY_DONTCARE, NULL},
+	{quick_button, 2, 10, 9, MAIL_DLG_HEIGHT, "&Ok", 0, B_ENTER, 0,
+	 0, XV_WLAY_DONTCARE, NULL},
+	{quick_input, 3, 50, 8, MAIL_DLG_HEIGHT, "", 44, 0, 0,
+	 0, XV_WLAY_BELOWCLOSE, "mail-dlg-input"},
+	{quick_label, 2, 50, 7, MAIL_DLG_HEIGHT, " Copies to", 0, 0, 0,
+	 0, XV_WLAY_DONTCARE, 0},
+	{quick_input, 3, 50, 6, MAIL_DLG_HEIGHT, "", 44, 0, 0,
+	 0, XV_WLAY_BELOWCLOSE, "mail-dlg-input-2"},
+	{quick_label, 2, 50, 5, MAIL_DLG_HEIGHT, " Subject", 0, 0, 0,
+	 0, XV_WLAY_DONTCARE, 0},
+	{quick_input, 3, 50, 4, MAIL_DLG_HEIGHT, "", 44, 0, 0,
+	 0, XV_WLAY_BELOWCLOSE, "mail-dlg-input-3"},
+	{quick_label, 2, 50, 3, MAIL_DLG_HEIGHT, " To", 0, 0, 0,
+	 0, XV_WLAY_DONTCARE, 0},
+	{quick_label, 2, 50, 2, MAIL_DLG_HEIGHT, " mail -s <subject> -c <cc> <to>", 0, 0, 0,
+	 0, XV_WLAY_DONTCARE, 0},
+	{0}};
+
+    quick_widgets[2].str_result = &tmail_cc;
+    quick_widgets[2].text = mail_cc_last ? mail_cc_last : "";
+    quick_widgets[4].str_result = &tmail_subject;
+    quick_widgets[4].text = mail_subject_last ? mail_subject_last : "";
+    quick_widgets[6].str_result = &tmail_to;
+    quick_widgets[6].text = mail_to_last ? mail_to_last : "";
+
+    Quick_input.widgets = quick_widgets;
+
+    if (quick_dialog (&Quick_input) != B_CANCEL) {
+	if (mail_cc_last)
+	    free (mail_cc_last);
+	if (mail_subject_last)
+	    free (mail_subject_last);
+	if (mail_to_last)
+	    free (mail_to_last);
+	mail_cc_last = *(quick_widgets[2].str_result);
+	mail_subject_last = *(quick_widgets[4].str_result);
+	mail_to_last = *(quick_widgets[6].str_result);
+	pipe_mail (edit, mail_to_last, mail_subject_last, mail_cc_last);
+    }
+}
+
+#endif
+

+ 140 - 0
edit/editcmddef.h

@@ -0,0 +1,140 @@
+#ifndef __EDIT_CMD_DEF_H
+#define __EDIT_CMD_DEF_H
+
+/*  in the distant future, keyboards will be invented with a
+    seperate key for each one of these commands   *sigh*      */
+
+/* cursor movements */
+#define CK_No_Command 		-1
+#define CK_BackSpace 		1
+#define CK_Delete 		2
+#define CK_Enter 		3
+#define CK_Page_Up 		4
+#define CK_Page_Down 		5
+#define CK_Left 		6
+#define CK_Right 		7
+#define CK_Word_Left 		8
+#define CK_Word_Right 		9
+#define CK_Up 			10
+#define CK_Down 		11
+#define CK_Home			12
+#define CK_End 			13
+#define CK_Tab 			14
+#define CK_Undo			15
+#define CK_Beginning_Of_Text    16
+#define CK_End_Of_Text		17
+#define CK_Scroll_Up		18
+#define CK_Scroll_Down		19
+#define CK_Return		20
+#define CK_Begin_Page		21
+#define CK_End_Page		22
+#define CK_Delete_Word_Left	23
+#define CK_Delete_Word_Right	24
+#define CK_Paragraph_Up		25
+#define CK_Paragraph_Down	26
+
+
+/* file commands */
+#define CK_Save 		101
+#define CK_Load 		102
+#define CK_New  		103
+#define CK_Save_As		104
+
+/* block commands */
+#define CK_Mark 		201
+#define CK_Copy 		202
+#define CK_Move 		203
+#define CK_Remove 		204
+#define CK_Unmark 		206
+#define CK_Save_Block		207
+#define CK_Column_Mark 	208
+
+/* search and replace */
+#define CK_Find			301
+#define CK_Find_Again		302
+#define CK_Replace		303
+#define CK_Replace_Again	304
+
+/* misc */
+#define CK_Insert_File		401
+#define CK_Exit			402
+#define CK_Toggle_Insert        403
+#define CK_Help			404
+#define CK_Date			405
+#define CK_Refresh		406
+#define CK_Goto			407
+#define CK_Delete_Line		408
+#define CK_Delete_To_Line_End	409
+#define CK_Delete_To_Line_Begin	410
+#define CK_Man_Page		411
+#define CK_Sort			412
+#define CK_Mail			413
+#define CK_Cancel		414
+#define CK_Complete		415
+#define CK_Paragraph_Format	416
+
+/* application control */
+#define CK_Save_Desktop		451
+#define CK_New_Window		452
+#define CK_Cycle		453
+#define CK_Menu			454
+#define CK_Save_And_Quit	455
+#define CK_Run_Another		456
+#define CK_Check_Save_And_Quit	457
+#define CK_Maximise		458
+
+/* macro */
+#define CK_Begin_Record_Macro	501
+#define CK_End_Record_Macro	502
+#define CK_Delete_Macro		503
+
+/* highlight commands */
+#define CK_Page_Up_Highlight 		604
+#define CK_Page_Down_Highlight 		605
+#define CK_Left_Highlight 		606
+#define CK_Right_Highlight 		607
+#define CK_Word_Left_Highlight 		608
+#define CK_Word_Right_Highlight 	609
+#define CK_Up_Highlight 		610
+#define CK_Down_Highlight 		611
+#define CK_Home_Highlight		612
+#define CK_End_Highlight 		613
+#define CK_Beginning_Of_Text_Highlight	614
+#define CK_End_Of_Text_Highlight	615
+#define CK_Begin_Page_Highlight		616
+#define CK_End_Page_Highlight		617
+#define CK_Scroll_Up_Highlight		618
+#define CK_Scroll_Down_Highlight	619
+#define CK_Paragraph_Up_Highlight	620
+#define CK_Paragraph_Down_Highlight	621
+
+/* X clipboard operations */
+
+#define CK_XStore		701
+#define CK_XCut			702
+#define CK_XPaste		703
+#define CK_Selection_History	704
+
+#ifdef MIDNIGHT		/* cooledit now has its own full-featured script editor and executor */
+/*
+   Process a block through a shell command: CK_Pipe_Block(i) executes shell_cmd[i].
+   shell_cmd[i] must process the file ~/cooledit.block and output ~/cooledit.block
+   which is then inserted into the text in place of the original block. shell_cmd[i] must
+   also produce a file homedir/cooledit.error . If this file is not empty an error will
+   have been assumed to have occured, and the block will not be replaced.
+   TODO: bring up a viewer to display the error message instead of inserting
+   it into the text, which is annoying.
+ */
+#define CK_Pipe_Block(i)	(1000+(i))
+#define SHELL_COMMANDS_i {"/.cedit/edit.indent.rc", "/.cedit/edit.spell.rc", /* and so on */ 0};
+#else
+#define CK_User_Command(i)	(1000+(i))
+#endif
+
+/* execute a macro */
+#define CK_Macro(i)		(2000+(i))
+#define CK_Last_Macro		CK_Macro(0x7FFF)
+
+
+#endif
+

+ 736 - 0
edit/editdraw.c

@@ -0,0 +1,736 @@
+/* editor text drawing.
+
+   Copyright (C) 1996, 1997 the Free Software Foundation
+
+   Authors: 1996, 1997 Paul Sheer
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <config.h>
+#include "edit.h"
+
+#define MAX_LINE_LEN 1024
+
+#ifndef MIDNIGHT
+#ifndef GTK
+#include "app_glob.c"
+#include "coollocal.h"
+#endif
+#else
+#include "../src/mad.h"
+#endif
+
+extern int column_highlighting;
+
+void status_string (WEdit * edit, char *s, int w, int fill, int font_width)
+{
+    int i;
+    char t[160];		/* 160 just to be sure */
+/* The field lengths just prevents the status line from shortening to much */
+    sprintf (t, "[%c%c%c%c] %2ld:%3ld+%2ld=%3ld/%3ld - *%-4ld/%4ldb=%3d",
+	     edit->mark1 != edit->mark2 ? ( column_highlighting ? 'C' : 'B') : '-',
+	     edit->modified ? 'M' : '-', edit->macro_i < 0 ? '-' : 'R',
+	     edit->overwrite == 0 ? '-' : 'O',
+	     edit->curs_col / font_width, edit->start_line + 1, edit->curs_row,
+	     edit->curs_line + 1, edit->total_lines + 1, edit->curs1,
+	     edit->last_byte, edit->curs1 < edit->last_byte
+	     ? edit_get_byte (edit, edit->curs1) : -1);
+    sprintf (s, "%.*s", w + 1, t);
+    i = strlen (s);
+    s[i] = ' ';
+    i = w;
+    do {
+	if (strchr (" +-*=/:b", s[i]))	/* chop off the last word/number */
+	    break;
+	s[i] = fill;
+    } while (i--);
+    s[i] = fill;
+    s[w] = 0;
+}
+
+
+#ifdef MIDNIGHT
+
+/* how to get as much onto the status line as is numerically possible :) */
+void edit_status (WEdit * edit)
+{
+    int w, i, t;
+    char *s;
+    w = edit->widget.cols - (edit->have_frame * 2);
+    s = malloc (w + 15);
+    if (w < 4)
+	w = 4;
+    memset (s, ' ', w);
+    attrset (SELECTED_COLOR);
+    if (w > 4) {
+	widget_move (edit, edit->have_frame, edit->have_frame);
+	i = w > 24 ? 18 : w - 6;
+	i = i < 13 ? 13 : i;
+	sprintf (s, "%s", name_trunc (edit->filename ? edit->filename : "", i));
+	i += strlen (s);
+	s[strlen (s)] = ' ';
+	t = w - 20;
+	if (t < 0)
+	    t = 0;
+	status_string (edit, s + 20, t, ' ', 1);
+    } else {
+	s[w] = 0;
+    }
+    printw ("%.*s", w, s);
+    attrset (NORMAL_COLOR);
+    free (s);
+}
+
+#else
+
+#ifndef GTK
+extern int fixed_font;
+#endif
+
+void rerender_text (CWidget * wdt);
+
+#ifdef GTK
+
+void edit_status (WEdit *edit)
+{
+    int w, i, t;
+    char id[33];
+    char s[160];
+    w = edit->num_widget_columns - 1;
+    if (w > 150)
+	w = 150;
+    if (w < 0)
+	w = 0;
+    memset (s, 0, w);
+    if (w > 1) {
+	i = w > 24 ? 18 : w - 6;
+	i = i < 13 ? 13 : i;
+	sprintf (s, "%s", name_trunc (edit->filename ? edit->filename : "", i));
+	i = strlen (s);
+	s[i] = ' ';
+	s[i + 1] = ' ';
+	t = w - i - 2;
+	if (t < 0)
+	    t = 0;
+	status_string (edit, s + i + 2, t, 0, FONT_MEAN_WIDTH);
+    }
+    s[w] = 0;
+    if (strcmp (s, GTK_LABEL(edit->widget->status)->label))
+	gtk_label_set (GTK_LABEL(edit->widget->status), s);
+}
+
+#else
+
+void edit_status (WEdit * edit)
+{
+    if ((COptionsOf (edit->widget) & EDITOR_NO_TEXT)) {
+	return;
+    } else {
+	int w, i, t;
+	CWidget *wdt;
+	char id[33];
+	char s[160];
+	w = edit->num_widget_columns - 1;
+	if (w > 150)
+	    w = 150;
+	if (w < 0)
+	    w = 0;
+	memset (s, 0, w);
+	if (w > 1) {
+	    i = w > 24 ? 18 : w - 6;
+	    i = i < 13 ? 13 : i;
+	    sprintf (s, "%s", name_trunc (edit->filename ? edit->filename : "", i));
+	    i = strlen (s);
+	    s[i] = ' ';
+	    s[i+1] = ' ';
+	    t = w - i - 2;
+	    if (t < 0)
+		t = 0;
+	    status_string (edit, s + i + 2, t, 0, FONT_MEAN_WIDTH);
+	}
+	s[w] = 0;
+	strcpy (id, CIdentOf (edit->widget));
+	strcat (id, ".text");
+	wdt = CIdent (id);
+	free (wdt->text);
+	wdt->text = strdup (s);
+	CSetWidgetSize (id, CWidthOf (edit->widget), CHeightOf (wdt));
+	rerender_text (wdt);
+    }
+}
+
+#endif
+
+#endif
+
+
+/* boolean */
+int cursor_in_screen (WEdit * edit, long row)
+{
+    if (row < 0 || row >= edit->num_widget_lines)
+	return 0;
+    else
+	return 1;
+}
+
+/* returns rows from the first displayed line to the cursor */
+int cursor_from_display_top (WEdit * edit)
+{
+    if (edit->curs1 < edit->start_display)
+	return -edit_move_forward (edit, edit->curs1, 0, edit->start_display);
+    else
+	return edit_move_forward (edit, edit->start_display, 0, edit->curs1);
+}
+
+/* returns how far the cursor is out of the screen */
+int cursor_out_of_screen (WEdit * edit)
+{
+    int row = cursor_from_display_top (edit);
+    if (row >= edit->num_widget_lines)
+	return row - edit->num_widget_lines + 1;
+    if (row < 0)
+	return row;
+    return 0;
+}
+
+#ifndef MIDNIGHT
+extern unsigned char per_char[256];
+int edit_width_of_long_printable (int c);
+#endif
+
+/* this scrolls the text so that cursor is on the screen */
+void edit_scroll_screen_over_cursor (WEdit * edit)
+{
+    int p, l;
+    int outby;
+    p = edit_get_col (edit);
+    edit_update_curs_row (edit);
+#ifdef MIDNIGHT
+    outby = p + edit->start_col - edit->num_widget_columns + 1 + (EDIT_RIGHT_EXTREME + edit->found_len);
+#else
+    outby = p + edit->start_col - CWidthOf (edit->widget) + 7 + (EDIT_RIGHT_EXTREME + edit->found_len) * FONT_MEAN_WIDTH + edit_width_of_long_printable (edit_get_byte (edit, edit->curs1));
+#endif
+    if (outby > 0)
+	edit_scroll_right (edit, outby);
+#ifdef MIDNIGHT
+    outby = EDIT_LEFT_EXTREME - p - edit->start_col;
+#else
+    outby = EDIT_LEFT_EXTREME * FONT_MEAN_WIDTH - p - edit->start_col;
+#endif
+    if (outby > 0)
+	edit_scroll_left (edit, outby);
+    p = edit->curs_row;
+    l = 0;
+    if (edit->found_len != 0)
+	l = edit->num_widget_lines / 5;
+    outby = p - edit->num_widget_lines + 1 + EDIT_BOTTOM_EXTREME + l;
+    if (outby > 0)
+	edit_scroll_downward (edit, outby);
+    outby = EDIT_TOP_EXTREME - p + l;
+    if (outby > 0)
+	edit_scroll_upward (edit, outby);
+    edit_update_curs_row (edit);
+}
+
+
+#ifndef MIDNIGHT
+
+#define CACHE_WIDTH 256
+#define CACHE_HEIGHT 128
+
+int EditExposeRedraw = 0;
+int EditClear = 0;
+
+/* background colors: marked is refers to mouse highlighting, highlighted refers to a found string. */
+unsigned long edit_abnormal_color, edit_marked_abnormal_color;
+unsigned long edit_highlighted_color, edit_marked_color;
+unsigned long edit_normal_background_color;
+
+/* foreground colors */
+unsigned long edit_normal_foreground_color, edit_bold_color;
+unsigned long edit_italic_color;
+
+/* cursor color */
+unsigned long edit_cursor_color;
+
+void edit_set_foreground_colors (unsigned long normal, unsigned long bold, unsigned long italic)
+{
+    edit_normal_foreground_color = normal;
+    edit_bold_color = bold;
+    edit_italic_color = italic;
+}
+
+void edit_set_background_colors (unsigned long normal, unsigned long abnormal, unsigned long marked, unsigned long marked_abnormal, unsigned long highlighted)
+{
+    edit_abnormal_color = abnormal;
+    edit_marked_abnormal_color = marked_abnormal;
+    edit_marked_color = marked;
+    edit_highlighted_color = highlighted;
+    edit_normal_background_color = normal;
+}
+
+void edit_set_cursor_color (unsigned long c)
+{
+    edit_cursor_color = c;
+}
+
+#else
+
+#define BOLD_COLOR        MARKED_COLOR
+#define UNDERLINE_COLOR   VIEW_UNDERLINED_COLOR
+#define MARK_COLOR        SELECTED_COLOR
+#define DEF_COLOR         NORMAL_COLOR
+
+static void set_color (int font)
+{
+    attrset (font);
+}
+
+#define edit_move(x,y) widget_move(edit, y, x);
+
+static void print_to_widget (WEdit * edit, long row, int start_col, float start_col_real, long end_col, unsigned int line[])
+{
+    int x = (float) start_col_real + EDIT_TEXT_HORIZONTAL_OFFSET;
+    int x1 = start_col + EDIT_TEXT_HORIZONTAL_OFFSET;
+    int y = row + EDIT_TEXT_VERTICAL_OFFSET;
+
+    set_color (DEF_COLOR);
+    edit_move (x1, y);
+    hline (' ', end_col + 1 - EDIT_TEXT_HORIZONTAL_OFFSET - x1);
+
+    edit_move (x + FONT_OFFSET_X, y + FONT_OFFSET_Y);
+    {
+	unsigned int *p = line;
+	int textchar = ' ';
+	long style;
+
+	while (*p) {
+	    style = *p >> 8;
+	    textchar = *p & 0xFF;
+#ifdef HAVE_SYNTAXH
+	    if (!(style & (0xFF - MOD_ABNORMAL - MOD_CURSOR)))
+		SLsmg_set_color ((*p & 0x007F0000) >> 16);
+#endif
+	    if (style & MOD_ABNORMAL)
+		textchar = '.';
+	    if (style & MOD_HIGHLIGHTED) {
+		set_color (BOLD_COLOR);
+	    } else if (style & MOD_MARKED) {
+		set_color (MARK_COLOR);
+	    }
+	    if (style & MOD_UNDERLINED) {
+		set_color (UNDERLINE_COLOR);
+	    }
+	    if (style & MOD_BOLD) {
+		set_color (BOLD_COLOR);
+	    }
+	    addch (textchar);
+	    p++;
+	}
+    }
+}
+
+/* b pointer to begining of line */
+static void edit_draw_this_line (WEdit * edit, long b, long row, long start_col, long end_col)
+{
+    static unsigned int line[MAX_LINE_LEN];
+    unsigned int *p = line;
+    long m1 = 0, m2 = 0, q, c1, c2;
+    int col, start_col_real;
+    unsigned int c;
+    int fg, bg;
+    int i;
+
+    edit_get_syntax_color (edit, b - 1, &fg, &bg);
+    q = edit_move_forward3 (edit, b, start_col - edit->start_col, 0);
+    start_col_real = (col = (int) edit_move_forward3 (edit, b, 0, q)) + edit->start_col;
+    c1 = min (edit->column1, edit->column2);
+    c2 = max (edit->column1, edit->column2);
+
+    if (col + 16 > -edit->start_col) {
+	eval_marks (edit, &m1, &m2);
+
+	if (row <= edit->total_lines - edit->start_line) {
+	    while (col <= end_col - edit->start_col) {
+		*p = 0;
+		if (q == edit->curs1)
+		    *p |= MOD_CURSOR * 256;
+		if (q >= m1 && q < m2) {
+		    if (column_highlighting) {
+			int x;
+			x = edit_move_forward3 (edit, b, 0, q);
+			if (x >= c1 && x < c2)
+			    *p |= MOD_MARKED * 256;
+		    } else
+			*p |= MOD_MARKED * 256;
+		}
+		if (q == edit->bracket)
+		    *p |= MOD_BOLD * 256;
+		if (q >= edit->found_start && q < edit->found_start + edit->found_len)
+		    *p |= MOD_HIGHLIGHTED * 256;
+		c = edit_get_byte (edit, q);
+		edit_get_syntax_color (edit, q, &fg, &bg);
+/* we don't use bg for mc - fg contains both */
+		*p |= fg << 16;
+		q++;
+		switch (c) {
+		case '\n':
+		    col = end_col - edit->start_col + 1;	/* quit */
+		    *(p++) |= ' ';
+		    break;
+		case '\t':
+		    i = TAB_SIZE - ((int) col % TAB_SIZE);
+		    *p |= ' ';
+		    c = *(p++) & (0xFFFFFFFF - MOD_CURSOR * 256);
+		    col += i;
+		    while (--i)
+			*(p++) = c;
+		    break;
+		case '\r':
+		    break;
+		default:
+		    if (is_printable (c)) {
+			*(p++) |= c;
+		    } else {
+			*(p++) = '.';
+			*p |= (256 * MOD_ABNORMAL);
+		    }
+		    col++;
+		    break;
+		}
+	    }
+	}
+    } else {
+	start_col_real = start_col = 0;
+    }
+    *p = 0;
+
+    print_to_widget (edit, row, start_col, start_col_real, end_col, line);
+}
+
+#endif
+
+#ifdef MIDNIGHT
+
+#define key_pending(x) (!is_idle())
+
+#else
+
+int edit_mouse_pending (Window win);
+#define edit_draw_this_line edit_draw_this_line_proportional
+
+static int key_pending (WEdit * edit)
+{
+#ifdef GTK
+    /* ******* */
+#else
+    if (!(edit->force & REDRAW_COMPLETELY) && !EditExposeRedraw)
+	return CKeyPending ();
+#endif
+    return 0;
+}
+
+#endif
+
+
+/* b for pointer to begining of line */
+static void edit_draw_this_char (WEdit * edit, long curs, long row)
+{
+    int b = edit_bol (edit, curs);
+#ifdef MIDNIGHT
+    edit_draw_this_line (edit, b, row, 0, edit->num_widget_columns - 1);
+#else
+    edit_draw_this_line (edit, b, row, 0, CWidthOf (edit->widget));
+#endif
+}
+
+/* cursor must be in screen for other than REDRAW_PAGE passed in force */
+void render_edit_text (WEdit * edit, long start_row, long start_column, long end_row, long end_column)
+{
+    long row = 0, curs_row;
+    static int prev_curs_row = 0;
+    static long prev_start_display = 0;
+    static int prev_start_col = 0;
+    static long prev_curs = 0;
+    unsigned long syntax_rule;
+
+#ifndef MIDNIGHT
+    static unsigned long prev_win = 0;
+#endif
+    int fg, bg;
+
+    int force = edit->force;
+    long b;
+
+    edit_get_syntax_color (edit, edit->start_display - 1, &fg, &bg);
+    syntax_rule = edit->rule;
+
+/*
+   if the position of the page has not moved then we can draw the cursor character only.
+   This will prevent line flicker when using arrow keys.
+ */
+    if ((!(force & REDRAW_CHAR_ONLY)) || (force & REDRAW_PAGE)
+#ifndef MIDNIGHT
+#ifdef GTK
+	|| prev_win != ((GdkWindowPrivate *) CWindowOf (edit->widget)->text_area)->xwindow
+#else
+	|| prev_win != CWindowOf (edit->widget)
+#endif
+#endif
+	) {
+	if (!(force & REDRAW_IN_BOUNDS)) {	/* !REDRAW_IN_BOUNDS means to ignore bounds and redraw whole rows */
+	    start_row = 0;
+	    end_row = edit->num_widget_lines - 1;
+	    start_column = 0;
+#ifdef MIDNIGHT
+	    end_column = edit->num_widget_columns - 1;
+#else
+	    end_column = CWidthOf (edit->widget);
+#endif
+	}
+	if (force & REDRAW_PAGE) {
+	    row = start_row;
+	    b = edit_move_forward (edit, edit->start_display, start_row, 0);
+	    while (row <= end_row) {
+		if (key_pending (edit))
+		    goto exit_render;
+		edit_draw_this_line (edit, b, row, start_column, end_column);
+		b = edit_move_forward (edit, b, 1, 0);
+		row++;
+	    }
+	} else {
+	    curs_row = edit->curs_row;
+
+	    if (force & REDRAW_BEFORE_CURSOR) {
+		if (start_row < curs_row) {
+		    long upto = curs_row - 1 <= end_row ? curs_row - 1 : end_row;
+		    row = start_row;
+		    b = edit->start_display;
+		    while (row <= upto) {
+			if (key_pending (edit))
+			    goto exit_render;
+			edit_draw_this_line (edit, b, row, start_column, end_column);
+			b = edit_move_forward (edit, b, 1, 0);
+		    }
+		}
+	    }
+/*          if (force & REDRAW_LINE) {          ---> default */
+	    b = edit_bol (edit, edit->curs1);
+	    if (curs_row >= start_row && curs_row <= end_row) {
+		if (key_pending (edit))
+		    goto exit_render;
+		edit_draw_this_line (edit, b, curs_row, start_column, end_column);
+	    }
+	    if (force & REDRAW_AFTER_CURSOR) {
+		if (end_row > curs_row) {
+		    row = curs_row + 1 < start_row ? start_row : curs_row + 1;
+		    b = edit_move_forward (edit, b, 1, 0);
+		    while (row <= end_row) {
+			if (key_pending (edit))
+			    goto exit_render;
+			edit_draw_this_line (edit, b, row, start_column, end_column);
+			b = edit_move_forward (edit, b, 1, 0);
+			row++;
+		    }
+		}
+	    }
+	    if (force & REDRAW_LINE_ABOVE && curs_row >= 1) {
+		row = curs_row - 1;
+		b = edit_move_backward (edit, edit_bol (edit, edit->curs1), 1);
+		if (row >= start_row && row <= end_row) {
+		    if (key_pending (edit))
+			goto exit_render;
+		    edit_draw_this_line (edit, b, row, start_column, end_column);
+		}
+	    }
+	    if (force & REDRAW_LINE_BELOW && row < edit->num_widget_lines - 1) {
+		row = curs_row + 1;
+		b = edit_bol (edit, edit->curs1);
+		b = edit_move_forward (edit, b, 1, 0);
+		if (row >= start_row && row <= end_row) {
+		    if (key_pending (edit))
+			goto exit_render;
+		    edit_draw_this_line (edit, b, row, start_column, end_column);
+		}
+	    }
+	}
+    } else {
+	if (prev_curs_row < edit->curs_row) {	/* with the new text highlighting, we must draw from the top down */
+	    edit_draw_this_char (edit, prev_curs, prev_curs_row);
+	    edit_draw_this_char (edit, edit->curs1, edit->curs_row);
+	} else {
+	    edit_draw_this_char (edit, edit->curs1, edit->curs_row);
+	    edit_draw_this_char (edit, prev_curs, prev_curs_row);
+	}
+    }
+
+    edit->force = 0;
+
+    prev_curs_row = edit->curs_row;
+    prev_curs = edit->curs1;
+    prev_start_display = edit->start_display;
+    prev_start_col = edit->start_col;
+#ifndef MIDNIGHT
+#ifdef GTK
+    prev_win = ((GdkWindowPrivate *) CWindowOf (edit->widget)->text_area)->xwindow;
+#else
+    prev_win = CWindowOf (edit->widget);
+#endif
+#endif
+  exit_render:
+    edit->last_get_rule = edit->start_display - 1;
+    edit->rule = syntax_rule;
+}
+
+
+
+#ifndef MIDNIGHT
+
+void edit_convert_expose_to_area (XExposeEvent * xexpose, int *row1, int *col1, int *row2, int *col2)
+{
+    *col1 = xexpose->x - EDIT_TEXT_HORIZONTAL_OFFSET;
+    *row1 = (xexpose->y - EDIT_TEXT_VERTICAL_OFFSET) / FONT_PIX_PER_LINE;
+    *col2 = xexpose->x + xexpose->width + EDIT_TEXT_HORIZONTAL_OFFSET + 3;
+    *row2 = (xexpose->y + xexpose->height - EDIT_TEXT_VERTICAL_OFFSET) / FONT_PIX_PER_LINE;
+}
+
+#ifdef GTK
+
+void edit_render_tidbits (GtkEdit * edit)
+{
+    return;
+}
+
+#else
+
+void edit_render_tidbits (CWidget * wdt)
+{
+    int isfocussed;
+    int w = wdt->width, h = wdt->height;
+    Window win;
+
+    win = wdt->winid;
+    isfocussed = (win == CGetFocus ());
+
+    CSetColor (COLOR_FLAT);
+
+    if (isfocussed) {
+	render_bevel (win, 0, 0, w - 1, h - 1, 3, 1);	/*most outer border bevel */
+    } else {
+	render_bevel (win, 2, 2, w - 3, h - 3, 1, 1);	/*border bevel */
+	render_bevel (win, 0, 0, w - 1, h - 1, 2, 0);	/*most outer border bevel */
+    }
+}
+
+#endif
+
+void edit_set_space_width (int s);
+extern int option_long_whitespace;
+
+#endif
+
+void edit_render (WEdit * edit, int page, int row_start, int col_start, int row_end, int col_end)
+{
+    int f = 0;
+#ifdef GTK
+    GtkEdit *win;
+#endif
+    if (page)			/* if it was an expose event, 'page' would be set */
+	edit->force |= REDRAW_PAGE | REDRAW_IN_BOUNDS;
+    f = edit->force & (REDRAW_PAGE | REDRAW_COMPLETELY);
+
+#ifdef MIDNIGHT
+    if (edit->force & REDRAW_COMPLETELY)
+	redraw_labels (edit->widget.parent, (Widget *) edit);
+#else
+    if (option_long_whitespace)
+	edit_set_space_width (per_char[' '] * 2);
+    else
+	edit_set_space_width (per_char[' ']);
+#ifdef GTK
+    win = (GtkEdit *) edit->widget;
+#endif
+    edit_set_foreground_colors (
+				 color_palette (option_editor_fg_normal),
+				   color_palette (option_editor_fg_bold),
+				   color_palette (option_editor_fg_italic)
+	);
+    edit_set_background_colors (
+				 color_palette (option_editor_bg_normal),
+			       color_palette (option_editor_bg_abnormal),
+				 color_palette (option_editor_bg_marked),
+			color_palette (option_editor_bg_marked_abnormal),
+			     color_palette (option_editor_bg_highlighted)
+	);
+    edit_set_cursor_color (
+			      color_palette (option_editor_fg_cursor)
+	);
+
+#ifdef GTK
+    /* *********** */
+#else
+    if (!EditExposeRedraw)
+	set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
+#endif
+#endif
+
+    render_edit_text (edit, row_start, col_start, row_end, col_end);
+    if (edit->force)		/* edit->force != 0 means a key was pending and the redraw 
+				   was halted, so next time we must redraw everything in case stuff
+				   was left undrawn from a previous key press */
+	edit->force |= REDRAW_PAGE;
+#ifndef MIDNIGHT
+    if (f) {
+	edit_render_tidbits (edit->widget);
+#ifdef GTK
+    /*  ***************** */
+#else
+	CSetColor (edit_normal_background_color);
+	CLine (CWindowOf (edit->widget), 3, 3, 3, CHeightOf (edit->widget) - 4);
+#endif
+    }
+#endif
+}
+
+#ifndef MIDNIGHT
+void edit_render_expose (WEdit * edit, XExposeEvent * xexpose)
+{
+    int row_start, col_start, row_end, col_end;
+    EditExposeRedraw = 1;
+    edit->num_widget_lines = (CHeightOf (edit->widget) - 6) / FONT_PIX_PER_LINE;
+    edit->num_widget_columns = (CWidthOf (edit->widget) - 7) / FONT_MEAN_WIDTH;
+    if (edit->force & (REDRAW_PAGE | REDRAW_COMPLETELY)) {
+	edit->force |= REDRAW_PAGE | REDRAW_COMPLETELY;
+	edit_render_keypress (edit);
+    } else {
+	edit_convert_expose_to_area (xexpose, &row_start, &col_start, &row_end, &col_end);
+	edit_render (edit, 1, row_start, col_start, row_end, col_end);
+    }
+    EditExposeRedraw = 0;
+}
+
+void edit_render_keypress (WEdit * edit)
+{
+    edit_render (edit, 0, 0, 0, 0, 0);
+}
+
+#else
+
+void edit_render_keypress (WEdit * edit)
+{
+    edit_render (edit, 0, 0, 0, 0, 0);
+}
+
+#endif

+ 461 - 0
edit/editmenu.c

@@ -0,0 +1,461 @@
+/* editor menu definitions and initialisation
+
+   Copyright (C) 1996 the Free Software Foundation
+
+   Authors: 1996, 1997 Paul Sheer
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#include <config.h>
+#include "edit.h"
+
+#include "editcmddef.h"
+
+#ifdef MIDNIGHT
+
+#include "../src/mad.h"
+
+extern int edit_key_emulation;
+extern WEdit *wedit;
+extern WButtonBar *edit_bar;
+extern Dlg_head *edit_dlg;
+extern WMenu *edit_menubar;
+
+#undef edit_message_dialog
+#define edit_message_dialog(w,x,y,h,s) query_dialog (h, s, 0, 1, "&Ok")
+#define CFocus(x) 
+
+static void menu_cmd (int i)
+{
+    send_message (wedit->widget.parent, (Widget *) wedit, WIDGET_COMMAND, i);
+}
+
+static void menu_key (int i)
+{
+    send_message (wedit->widget.parent, (Widget *) wedit, WIDGET_KEY, i);
+}
+
+void edit_wrap_cmd ()
+{
+    char *f;
+    char s[12];
+    sprintf (s, "%d", option_word_wrap_line_length);
+    f = input_dialog (_(" Word wrap "), 
+/* Not essential to translate */
+    _(" Enter line length, 0 for off: "), s);
+    if (f) {
+	if (*f) {
+	    option_word_wrap_line_length = atoi (f);
+	    free (f);
+	}
+    }
+}
+
+void edit_about_cmd ()
+{
+    edit_message_dialog (wedit->mainid, 20, 20, " About ",
+		      "\n"
+		      "                 Cooledit  v2.1\n"
+		      "\n"
+		      " Copyright (C) 1996 the Free Software Foundation\n"
+		      "\n"
+		      "       A user friendly text editor written\n"
+		      "           for the Midnight Commander.\n"
+	);
+}
+
+void menu_mail_cmd (void)		{ menu_cmd (CK_Mail); }
+void menu_load_cmd (void)		{ menu_cmd (CK_Load); }
+void menu_new_cmd (void)		{ menu_cmd (CK_New); }
+void menu_save_cmd (void)		{ menu_cmd (CK_Save); }
+void menu_save_as_cmd (void)		{ menu_cmd (CK_Save_As); }
+void menu_insert_file_cmd (void)	{ menu_cmd (CK_Insert_File); }
+void menu_quit_cmd (void)		{ menu_cmd (CK_Exit); }
+void menu_mark_cmd (void)		{ menu_cmd (CK_Mark); }
+void menu_markcol_cmd (void)		{ menu_cmd (CK_Column_Mark); }
+void menu_ins_cmd (void)		{ menu_cmd (CK_Toggle_Insert); }
+void menu_copy_cmd (void)		{ menu_cmd (CK_Copy); }
+void menu_move_cmd (void)		{ menu_cmd (CK_Move); }
+void menu_delete_cmd (void)		{ menu_cmd (CK_Remove); }
+void menu_cut_cmd (void)		{ menu_cmd (CK_Save_Block); }
+void menu_search_cmd (void)		{ menu_cmd (CK_Find); }
+void menu_search_again_cmd (void)	{ menu_cmd (CK_Find_Again); }
+void menu_replace_cmd (void)		{ menu_cmd (CK_Replace); }
+void menu_begin_record_cmd (void)	{ menu_cmd (CK_Begin_Record_Macro); }
+void menu_end_record_cmd (void)		{ menu_cmd (CK_End_Record_Macro); }
+void menu_wrap_cmd (void)		{ edit_wrap_cmd (); }
+void menu_exec_macro_cmd (void)		{ menu_key (XCTRL ('a')); }
+void menu_exec_macro_delete_cmd (void)	{ menu_cmd (CK_Delete_Macro); }
+void menu_c_form_cmd (void)		{ menu_key (KEY_F (19)); }
+void menu_ispell_cmd (void)		{ menu_cmd (CK_Pipe_Block (1)); }
+void menu_sort_cmd (void)		{ menu_cmd (CK_Sort); }
+void menu_date_cmd (void)		{ menu_cmd (CK_Date); }
+void menu_undo_cmd (void)		{ menu_cmd (CK_Undo); }
+void menu_beginning_cmd (void)		{ menu_cmd (CK_Beginning_Of_Text); }
+void menu_end_cmd (void)		{ menu_cmd (CK_End_Of_Text); }
+void menu_refresh_cmd (void)		{ menu_cmd (CK_Refresh); }
+void menu_goto_line (void)		{ menu_cmd (CK_Goto); }
+void menu_lit_cmd (void)		{ menu_key (XCTRL ('q')); }
+void menu_format_paragraph (void)	{ menu_cmd (CK_Paragraph_Format); }
+void edit_options_dialog (void);
+void menu_options (void)		{ edit_options_dialog (); }
+
+static menu_entry FileMenu[] =
+{
+    {' ', N_("&Open/load...     C-o"), 'O', menu_load_cmd},
+    {' ', N_("&New              C-n"), 'N', menu_new_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Save              F2"), 'S', menu_save_cmd},
+    {' ', N_("save &As...       F12"), 'A', menu_save_as_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Insert file...   F15"), 'I', menu_insert_file_cmd},
+    {' ', N_("copy to &File...  C-f"), 'F', menu_cut_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("a&Bout...            "), 'B', edit_about_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Quit             F10"), 'Q', menu_quit_cmd}
+ };
+
+static menu_entry FileMenuEmacs[] =
+{
+    {' ', N_("&Open/load...     C-o"), 'O', menu_load_cmd},
+    {' ', N_("&New            C-x k"), 'N', menu_new_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Save              F2"), 'S', menu_save_cmd},
+    {' ', N_("save &As...       F12"), 'A', menu_save_as_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Insert file...   F15"), 'I', menu_insert_file_cmd},
+    {' ', N_("copy to &File...     "), 'F', menu_cut_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("a&Bout...            "), 'B', edit_about_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Quit             F10"), 'Q', menu_quit_cmd}
+};
+
+static menu_entry EditMenu[] =
+{
+    {' ', N_("&Toggle Mark       F3"), 'T', menu_mark_cmd},
+    {' ', N_("&Mark Columns    S-F3"), 'T', menu_markcol_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("toggle &Ins/overw Ins"), 'I', menu_ins_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Copy              F5"), 'C', menu_copy_cmd},
+    {' ', N_("&Move              F6"), 'M', menu_move_cmd},
+    {' ', N_("&Delete            F8"), 'D', menu_delete_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Undo             C-u"), 'U', menu_undo_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Beginning     C-PgUp"), 'B', menu_beginning_cmd},
+    {' ', N_("&End           C-PgDn"), 'E', menu_end_cmd}
+};
+
+static menu_entry EditMenuEmacs[] =
+{
+    {' ', N_("&Toggle Mark       F3"), 'T', menu_mark_cmd},
+    {' ', N_("&Mark Columns    S-F3"), 'T', menu_markcol_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("toggle &Ins/overw Ins"), 'I', menu_ins_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Copy              F5"), 'C', menu_copy_cmd},
+    {' ', N_("&Move              F6"), 'M', menu_move_cmd},
+    {' ', N_("&Delete            F8"), 'D', menu_delete_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Undo             C-u"), 'U', menu_undo_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Beginning     C-PgUp"), 'B', menu_beginning_cmd},
+    {' ', N_("&End           C-PgDn"), 'E', menu_end_cmd}
+};
+
+static menu_entry SearReplMenu[] =
+{
+    {' ', N_("&Search...         F7"), 'S', menu_search_cmd},
+    {' ', N_("search &Again     F17"), 'A', menu_search_again_cmd},
+    {' ', N_("&Replace...        F4"), 'R', menu_replace_cmd}
+};
+
+static menu_entry SearReplMenuEmacs[] =
+{
+    {' ', N_("&Search...         F7"), 'S', menu_search_cmd},
+    {' ', N_("search &Again     F17"), 'A', menu_search_again_cmd},
+    {' ', N_("&Replace...        F4"), 'R', menu_replace_cmd}
+};
+
+static menu_entry CmdMenu[] =
+{
+    {' ', N_("&Goto line...            M-l"), 'G', menu_goto_line},
+    {' ', "", ' ', 0},
+    {' ', N_("insert &Literal...       C-q"), 'L', menu_lit_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Refresh screen          C-l"), 'R', menu_refresh_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Start record macro      C-r"), 'S', menu_begin_record_cmd},
+    {' ', N_("&Finish record macro...  C-r"), 'F', menu_end_record_cmd},
+    {' ', N_("&Execute macro...   C-a, KEY"), 'E', menu_exec_macro_cmd},
+    {' ', N_("delete macr&O...            "), 'O', menu_exec_macro_delete_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("insert &Date/time           "), 'D', menu_date_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("format p&Aragraph        M-p"), 'A', menu_format_paragraph},
+    {' ', N_("'ispell' s&Pell check    C-p"), 'P', menu_ispell_cmd},
+    {' ', N_("sor&T...                 M-t"), 'T', menu_sort_cmd},
+    {' ', N_("'indent' &C Formatter    F19"), 'C', menu_c_form_cmd},
+    {' ', N_("&Mail...                    "), 'M', menu_mail_cmd}
+};
+
+static menu_entry CmdMenuEmacs[] =
+{
+    {' ', N_("&Goto line...            M-l"), 'G', menu_goto_line},
+    {' ', "", ' ', 0},
+    {' ', N_("insert &Literal...       C-q"), 'L', menu_lit_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Refresh screen          C-l"), 'R', menu_refresh_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("&Start record macro      C-r"), 'S', menu_begin_record_cmd},
+    {' ', N_("&Finish record macro...  C-r"), 'F', menu_end_record_cmd},
+    {' ', N_("&Execute macro... C-x e, KEY"), 'E', menu_exec_macro_cmd},
+    {' ', N_("delete macr&O...            "), 'o', menu_exec_macro_delete_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("insert &Date/time           "), 'D', menu_date_cmd},
+    {' ', "", ' ', 0},
+    {' ', N_("format p&Aragraph        M-p"), 'a', menu_format_paragraph},
+    {' ', N_("'ispell' s&Pell check    M-$"), 'P', menu_ispell_cmd},
+    {' ', N_("sor&T...                 M-t"), 'T', menu_sort_cmd},
+    {' ', N_("'indent' &C Formatter    F19"), 'C', menu_c_form_cmd}
+};
+
+extern void menu_save_mode_cmd (void);
+
+static menu_entry OptMenu[] =
+{
+    {' ', N_("&General...  "), 'G', menu_options},
+    {' ', N_("&Save mode..."), 'S', menu_save_mode_cmd}
+#if 0
+    {' ', N_("&Layout..."),    'L', menu_layout_cmd}
+#endif
+};
+
+static menu_entry OptMenuEmacs[] =
+{
+    {' ', N_("&General...  "), 'G', menu_options},
+    {' ', N_("&Save mode..."), 'S', menu_save_mode_cmd}
+#if 0
+    {' ', N_("&Layout..."),    'L', menu_layout_cmd}
+#endif
+};
+
+#define menu_entries(x) sizeof(x)/sizeof(menu_entry)
+
+Menu EditMenuBar[N_menus];
+
+void edit_init_menu_normal (void)
+{
+    EditMenuBar[0] = create_menu (_(" File "), FileMenu, menu_entries (FileMenu));
+    EditMenuBar[1] = create_menu (_(" Edit "), EditMenu, menu_entries (EditMenu));
+    EditMenuBar[2] = create_menu (_(" Sear/Repl "), SearReplMenu, menu_entries (SearReplMenu));
+    EditMenuBar[3] = create_menu (_(" Command "), CmdMenu, menu_entries (CmdMenu));
+    EditMenuBar[4] = create_menu (_(" Options "), OptMenu, menu_entries (OptMenu));
+}
+
+void edit_init_menu_emacs (void)
+{
+    EditMenuBar[0] = create_menu (_(" File "), FileMenuEmacs, menu_entries (FileMenuEmacs));
+    EditMenuBar[1] = create_menu (_(" Edit "), EditMenuEmacs, menu_entries (EditMenuEmacs));
+    EditMenuBar[2] = create_menu (_(" Sear/Repl "), SearReplMenuEmacs, menu_entries (SearReplMenuEmacs));
+    EditMenuBar[3] = create_menu (_(" Command "), CmdMenuEmacs, menu_entries (CmdMenuEmacs));
+    EditMenuBar[4] = create_menu (_(" Options "), OptMenuEmacs, menu_entries (OptMenuEmacs));
+}
+
+void edit_done_menu (void)
+{
+    int i;
+    for (i = 0; i < N_menus; i++)
+	destroy_menu (EditMenuBar[i]);
+}
+
+
+void edit_drop_menu_cmd (WEdit * e, int which)
+{
+    if (edit_menubar->active)
+	return;
+    edit_menubar->active = 1;
+    edit_menubar->dropped = drop_menus;
+    edit_menubar->previous_selection = which >= 0 ? which : dlg_item_number (edit_dlg);
+    if (which >= 0)
+	edit_menubar->selected = which;
+    dlg_select_widget (edit_dlg, edit_menubar);
+}
+
+
+void edit_menu_cmd (WEdit * e)
+{
+    edit_drop_menu_cmd (e, -1);
+}
+
+
+int edit_drop_hotkey_menu (WEdit * e, int key)
+{
+    int m = 0;
+    switch (key) {
+    case ALT ('f'):
+	if (edit_key_emulation == EDIT_KEY_EMULATION_EMACS)
+	    return 0;
+	m = 0;
+	break;
+    case ALT ('e'):
+	m = 1;
+	break;
+    case ALT ('s'):
+	m = 2;
+	break;
+    case ALT ('c'):
+	m = 3;
+	break;
+    case ALT ('o'):
+	m = 4;
+	break;
+    default:
+	return 0;
+    }
+
+    edit_drop_menu_cmd (e, m);
+    return 1;
+}
+
+
+#else				/* !MIDNIGHT */
+
+
+extern CWidget *wedit;
+
+void CSetEditMenu (const char *ident)
+{
+    wedit = CIdent (ident);
+}
+
+CWidget *CGetEditMenu (void)
+{
+    return wedit;
+}
+
+static void menu_cmd (unsigned long i)
+{
+    XEvent e;
+    if (wedit) {
+	memset (&e, 0, sizeof (XEvent));
+	e.type = EditorCommand;
+	e.xkey.keycode = i;
+	e.xkey.window = wedit->winid;
+	CFocus (wedit);
+	CSendEvent (&e);
+    }
+}
+
+void CEditMenuCommand (int i)
+{
+    menu_cmd ((unsigned long) i);
+}
+
+static void menu_key (KeySym i, int state)
+{
+    int cmd, ch;
+    if (edit_translate_key (0, i, state, &cmd, &ch)) {
+	if (cmd > 0)
+	    menu_cmd (cmd);
+    }
+}
+
+static void menu_ctrl_key (unsigned long i)
+{
+    menu_key ((KeySym) i, ControlMask);
+}
+
+void CDrawEditMenuButtons (const char *ident, Window parent, Window focus_return, int x, int y)
+{
+    int d;
+
+    CDrawMenuButton (catstrs (ident, ".filemenu", 0), parent, focus_return, x, y, AUTO_WIDTH, AUTO_HEIGHT, 8,
+/* The following are menu options. Do not change the key bindings (eg. C-o) and preserve '\t' */
+		     _(" File "),
+		     _("Open...\tC-o"), '~', menu_cmd, CK_Load,
+		     _("New\tC-n"), '~', menu_cmd, CK_New,
+		     "", ' ', 0, 0,
+		     _("Save\tF2"), '~', menu_cmd, CK_Save,
+		     _("Save as...\tF12"), '~', menu_cmd, CK_Save_As,
+		     "", ' ', 0, 0,
+		     _("Insert file...\tF15"), '~', menu_cmd, CK_Insert_File,
+		     _("Copy to file...\tC-f"), '~', menu_cmd, CK_Save_Block
+	);
+/* Tool hint */
+    CSetToolHint (catstrs (ident, ".filemenu", 0), _("Disk operations"));
+
+    CGetHintPos (&x, &d);
+
+    CDrawMenuButton (catstrs (ident, ".editmenu", 0), parent, focus_return, x, y, AUTO_WIDTH, AUTO_HEIGHT, 15,
+		     _(" Edit "),
+		     _("Toggle mark\tF3"), '~', menu_cmd, CK_Mark,
+		     _("Toggle mark columns\tC-b"), '~', menu_cmd, CK_Column_Mark,
+		     "", ' ', 0, 0,
+		     _("Toggle insert/overwrite\tIns"), '~', menu_cmd, CK_Toggle_Insert,
+		     "", ' ', 0, 0,
+		     _("Copy block to cursor\tF5"), '~', menu_cmd, CK_Copy,
+		     _("Move block to cursor\tF6"), '~', menu_cmd, CK_Move,
+		     _("Delete block\tF8/C-Del"), '~', menu_cmd, CK_Remove,
+		     "", ' ', 0, 0,
+		     _("Copy block to clipbrd\tC-Ins"), '~', menu_cmd, CK_XStore,
+		     _("Cut block to clipbrd\tS-Del"), '~', menu_cmd, CK_XCut,
+		     _("Paste block from clipbrd\tS-Ins"), '~', menu_cmd, CK_XPaste,
+		     _("Selection history\tM-Ins"), '~', menu_cmd, CK_Selection_History,
+		     "", ' ', 0, 0,
+		     _("Undo\tC-BackSpace"), '~', menu_cmd, CK_Undo
+	);
+/* Tool hint */
+    CSetToolHint (catstrs (ident, ".editmenu", 0), _("Manipulating blocks of text"));
+
+    CGetHintPos (&x, &d);
+
+    CDrawMenuButton (catstrs (ident, ".searchmenu", 0), parent, focus_return, x, y, AUTO_WIDTH, AUTO_HEIGHT, 4,
+		     _(" Srch/Replce "),
+		     _("Search...\tF7"), '~', menu_cmd, CK_Find,
+		     _("Search again\tF17"), '~', menu_cmd, CK_Find_Again,
+		     _("Replace...\tF4"), '~', menu_cmd, CK_Replace,
+		     _("Replace again\tF14"), '~', menu_cmd, CK_Replace_Again
+	);
+/* Tool hint */
+    CSetToolHint (catstrs (ident, ".searchmenu", 0), _("Search for and replace text"));
+
+    CGetHintPos (&x, &d);
+
+    CDrawMenuButton (catstrs (ident, ".commandmenu", 0), parent, focus_return, x, y, AUTO_WIDTH, AUTO_HEIGHT, 11,
+		     _(" Command "),
+		     _("Goto line...\tM-l"), '~', menu_cmd, CK_Goto,
+		     "", ' ', 0, 0,
+		     _("Start record macro\tC-r"), '~', menu_cmd, CK_Begin_Record_Macro,
+		     _("Finish record macro...\tC-r"), '~', menu_cmd, CK_End_Record_Macro,
+		     _("Execute macro...\tC-a, KEY"), '~', menu_ctrl_key, XK_a,
+		     _("Delete macro...\t"), '~', menu_cmd, CK_Delete_Macro,
+		     "", ' ', 0, 0,
+		     _("Insert date/time\tC-d"), '~', menu_cmd, CK_Date,
+		     _("Format paragraph\tM-p"), '~', menu_cmd, CK_Paragraph_Format,
+		     "", ' ', 0, 0,
+		     _("Refresh display\tC-l"), '~', menu_cmd, CK_Refresh
+	);
+/* Tool hint */
+    CSetToolHint (catstrs (ident, ".commandmenu", 0), _("Macros and internal commands"));
+}
+
+
+#endif				/* !MIDNIGHT */
+

+ 182 - 0
edit/editoptions.c

@@ -0,0 +1,182 @@
+/* editor options dialog box
+
+   Copyright (C) 1996, 1997 the Free Software Foundation
+
+   Authors: 1996, 1997 Paul Sheer
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <config.h>
+#include "edit.h"
+
+#define OPT_DLG_H 15
+#define OPT_DLG_W 72
+
+#ifndef USE_INTERNAL_EDIT
+#define USE_INTERNAL_EDIT 1
+#endif
+
+#include "../src/main.h"	/* extern int option_this_and_that ... */
+
+char *key_emu_str[] =
+{"Intuitive", "Emacs"};
+
+char *wrap_str[] =
+{N_("None"), N_("Dynamic paragraphing"), N_("Type writer wrap")};
+
+extern int option_syntax_highlighting;
+
+void edit_options_dialog (void)
+{
+    char wrap_length[32], tab_spacing[32], *p, *q;
+    int wrap_mode = 0;
+    int tedit_key_emulation = edit_key_emulation;
+    int toption_fill_tabs_with_spaces = option_fill_tabs_with_spaces;
+    int tedit_confirm_save = edit_confirm_save;
+    int tedit_syntax_highlighting = option_syntax_highlighting;
+    int toption_return_does_auto_indent = option_return_does_auto_indent;
+    int toption_backspace_through_tabs = option_backspace_through_tabs;
+    int toption_fake_half_tabs = option_fake_half_tabs;
+
+    QuickWidget quick_widgets[] =
+    {
+/*0 */
+	{quick_button, 6, 10, OPT_DLG_H - 3, OPT_DLG_H, "&Cancel", 0, B_CANCEL, 0,
+	 0, XV_WLAY_DONTCARE, NULL},
+/*1 */
+	{quick_button, 2, 10, OPT_DLG_H - 3, OPT_DLG_H, "&Ok", 0, B_ENTER, 0,
+	 0, XV_WLAY_DONTCARE, NULL},
+/*2 */
+	{quick_label, OPT_DLG_W / 2, OPT_DLG_W, OPT_DLG_H - 4, OPT_DLG_H, "Word wrap line length : ", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+/*3 */
+	{quick_input, OPT_DLG_W / 2 + 24, OPT_DLG_W, OPT_DLG_H - 4, OPT_DLG_H, "", OPT_DLG_W / 2 - 4 - 24, 0,
+	 0, 0, XV_WLAY_DONTCARE, "i"},
+/*4 */
+	{quick_label, OPT_DLG_W / 2, OPT_DLG_W, OPT_DLG_H - 5, OPT_DLG_H, "Tab spacing : ", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+/*5 */
+	{quick_input, OPT_DLG_W / 2 + 24, OPT_DLG_W, OPT_DLG_H - 5, OPT_DLG_H, "", OPT_DLG_W / 2 - 4 - 24, 0,
+	 0, 0, XV_WLAY_DONTCARE, "i"},
+/*6 */
+#if !defined(MIDNIGHT) || defined(HAVE_SYNTAXH)
+#define OA 1
+	{quick_checkbox, OPT_DLG_W / 2 + 1, OPT_DLG_W, OPT_DLG_H - 7, OPT_DLG_H, "syntax h&Ighlighting", 8, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+#else
+#define OA 0
+#endif
+/*7 */
+	{quick_checkbox, OPT_DLG_W / 2 + 1, OPT_DLG_W, OPT_DLG_H - 8, OPT_DLG_H, "confir&M before saving", 6, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+/*8 */
+	{quick_checkbox, OPT_DLG_W / 2 + 1, OPT_DLG_W, OPT_DLG_H - 9, OPT_DLG_H, "&Fill tabs with spaces", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+/*9 */
+	{quick_checkbox, OPT_DLG_W / 2 + 1, OPT_DLG_W, OPT_DLG_H - 10, OPT_DLG_H, "&Return does auto indent", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+/*10 */
+	{quick_checkbox, OPT_DLG_W / 2 + 1, OPT_DLG_W, OPT_DLG_H - 11, OPT_DLG_H, "&Backspace through tabs", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+/*11 */
+	{quick_checkbox, OPT_DLG_W / 2 + 1, OPT_DLG_W, OPT_DLG_H - 12, OPT_DLG_H, "&Fake half tabs", 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+/*12 */
+	{quick_radio, 5, OPT_DLG_W, OPT_DLG_H - 6, OPT_DLG_H, "", 3, 0,
+	 0, wrap_str, XV_WLAY_DONTCARE, "wrapm"},
+/*13 */
+	{quick_label, 4, OPT_DLG_W, OPT_DLG_H - 7, OPT_DLG_H, N_("Wrap mode"), 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+/*14 */
+      {quick_radio, 5, OPT_DLG_W, OPT_DLG_H - 11, OPT_DLG_H, "", 2, 0,
+       0, key_emu_str, XV_WLAY_DONTCARE, "keyemu"},
+/*15 */
+	{quick_label, 4, OPT_DLG_W, OPT_DLG_H - 12, OPT_DLG_H, N_("Key emulation"), 0, 0,
+	 0, 0, XV_WLAY_DONTCARE, NULL},
+	{0}};
+
+    sprintf (wrap_length, "%d", option_word_wrap_line_length);
+    sprintf (tab_spacing, "%d", option_tab_spacing);
+
+    quick_widgets[3].text = wrap_length;
+    quick_widgets[3].str_result = &p;
+    quick_widgets[5].text = tab_spacing;
+    quick_widgets[5].str_result = &q;
+    quick_widgets[5 + OA].result = &tedit_syntax_highlighting;
+    quick_widgets[6 + OA].result = &tedit_confirm_save;
+    quick_widgets[7 + OA].result = &toption_fill_tabs_with_spaces;
+    quick_widgets[8 + OA].result = &toption_return_does_auto_indent;
+    quick_widgets[9 + OA].result = &toption_backspace_through_tabs;
+    quick_widgets[10 + OA].result = &toption_fake_half_tabs;
+
+    if (option_auto_para_formatting)
+	wrap_mode = 1;
+    else if (option_typewriter_wrap)
+	wrap_mode = 2;
+    else
+	wrap_mode = 0;
+
+    quick_widgets[11 + OA].result = &wrap_mode;
+    quick_widgets[11 + OA].value = wrap_mode;
+
+    quick_widgets[13 + OA].result = &tedit_key_emulation;
+    quick_widgets[13 + OA].value = tedit_key_emulation;
+
+    {
+	QuickDialog Quick_options =
+	{OPT_DLG_W, OPT_DLG_H, -1, 0, " Editor Options ",
+	 "", "quick_input", 0};
+
+	Quick_options.widgets = quick_widgets;
+
+	if (quick_dialog (&Quick_options) != B_CANCEL) {
+	    if (p) {
+		option_word_wrap_line_length = atoi (p);
+		free (p);
+	    }
+	    if (q) {
+		option_tab_spacing = atoi (q);
+		if (option_tab_spacing < 0)
+		    option_tab_spacing = 2;
+		option_tab_spacing += option_tab_spacing & 1;
+		free (q);
+	    }
+	    option_syntax_highlighting = *quick_widgets[5 + OA].result;
+	    edit_confirm_save = *quick_widgets[6 + OA].result;
+	    option_fill_tabs_with_spaces = *quick_widgets[7 + OA].result;
+	    option_return_does_auto_indent = *quick_widgets[8 + OA].result;
+	    option_backspace_through_tabs = *quick_widgets[9 + OA].result;
+	    option_fake_half_tabs = *quick_widgets[10 + OA].result;
+
+	    if (*quick_widgets[11 + OA].result == 1) {
+		option_auto_para_formatting = 1;
+		option_typewriter_wrap = 0;
+	    } else if (*quick_widgets[11 + OA].result == 2) {
+		option_auto_para_formatting = 0;
+		option_typewriter_wrap = 1;
+	    } else {
+		option_auto_para_formatting = 0;
+		option_typewriter_wrap = 0;
+	    }
+
+	    edit_key_emulation = *quick_widgets[13 + OA].result;
+
+	    return;
+	} else {
+	    return;
+	}
+    }
+}
+

+ 1212 - 0
edit/editwidget.c

@@ -0,0 +1,1212 @@
+/* editor initialisation and callback handler.
+
+   Copyright (C) 1996, 1997 the Free Software Foundation
+
+   Authors: 1996, 1997 Paul Sheer
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+#include <config.h>
+#include "edit.h"
+
+#ifndef MIDNIGHT
+#include <X11/Xmd.h>		/* CARD32 */
+#include <X11/Xatom.h>
+#ifndef GTK
+#include "app_glob.c"
+#include "coollocal.h"
+#endif
+#include "editcmddef.h"
+#include "mousemark.h"
+#endif
+
+
+#ifndef MIDNIGHT
+
+extern int EditExposeRedraw;
+CWidget *wedit = 0;
+
+void edit_destroy_callback (CWidget * w)
+{
+    if (w) {
+	edit_clean (w->editor);
+	if (w->editor)
+	    free (w->editor);
+	w->editor = NULL;
+    } else
+/* NLS ? */
+	CError ("Trying to destroy non-existing editor widget.\n");
+}
+
+#ifdef GTK
+
+#else
+void link_hscrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * xevent, CEvent * cwevent, int whichscrbutton);
+#endif
+
+/* returns the position in the edit buffer of a window click */
+long edit_get_click_pos (WEdit * edit, int x, int y)
+{
+    long click;
+/* (1) goto to left margin */
+    click = edit_bol (edit, edit->curs1);
+
+/* (1) move up or down */
+    if (y > (edit->curs_row + 1))
+	click = edit_move_forward (edit, click, y - (edit->curs_row + 1), 0);
+    if (y < (edit->curs_row + 1))
+	click = edit_move_backward (edit, click, (edit->curs_row + 1) - y);
+
+/* (3) move right to x pos */
+    click = edit_move_forward3 (edit, click, x - edit->start_col - 1, 0);
+    return click;
+}
+
+void edit_translate_xy (int xs, int ys, int *x, int *y)
+{
+    *x = xs - EDIT_TEXT_HORIZONTAL_OFFSET;
+    *y = (ys - EDIT_TEXT_VERTICAL_OFFSET - option_text_line_spacing / 2 - 1) / FONT_PIX_PER_LINE + 1;
+}
+
+extern int just_dropped_something;
+
+static void mouse_redraw (WEdit * edit, long click)
+{
+    edit->force |= REDRAW_PAGE | REDRAW_LINE;
+    edit_update_curs_row (edit);
+    edit_update_curs_col (edit);
+    edit->prev_col = edit_get_col (edit);
+    edit_update_screen (edit);
+    edit->search_start = click;
+}
+
+static void xy (int x, int y, int *x_return, int *y_return)
+{
+    edit_translate_xy (x, y, x_return, y_return);
+}
+
+static long cp (WEdit *edit, int x, int y)
+{
+    return edit_get_click_pos (edit, x, y);
+}
+
+/* return 1 if not marked */
+static int marks (WEdit * edit, long *start, long *end)
+{
+    return eval_marks (edit, start, end);
+}
+
+int column_highlighting = 0;
+
+static int erange (WEdit * edit, long start, long end, int click)
+{
+    if (column_highlighting) {
+	int x;
+	x = edit_move_forward3 (edit, edit_bol (edit, click), 0, click);
+	if ((x >= edit->column1 && x < edit->column2)
+	    || (x > edit->column2 && x <= edit->column1))
+	    return (start <= click && click < end);
+	else
+	    return 0;
+    }
+    return (start <= click && click < end);
+}
+
+static void fin_mark (WEdit *edit)
+{
+    if (edit->mark2 < 0)
+	edit_mark_cmd (edit, 0);
+}
+
+static void move_mark (WEdit *edit)
+{
+    edit_mark_cmd (edit, 1);
+    edit_mark_cmd (edit, 0);
+}
+
+static void release_mark (WEdit *edit, XEvent *event)
+{
+    if (edit->mark2 < 0)
+	edit_mark_cmd (edit, 0);
+    else
+	edit_mark_cmd (edit, 1);
+    if (edit->mark1 != edit->mark2 && event) {
+	edit_get_selection (edit);
+#ifdef GTK
+#if 0
+/* *** */
+	gtk_set_selection_owner (CWindowOf (edit->widget));
+#endif
+#else
+	XSetSelectionOwner (CDisplay, XA_PRIMARY, CWindowOf (edit->widget), event->xbutton.time);
+#endif
+    }
+}
+
+static char *get_block (WEdit * edit, long start_mark, long end_mark, int *type, int *l)
+{
+    char *t;
+    t = (char *) edit_get_block (edit, start_mark, end_mark, l);
+    if (strlen (t) < *l)
+	*type = DndRawData;	/* if there are nulls in the data, send as raw */
+    else
+	*type = DndText;	/* else send as text */
+    return t;
+}
+
+static void move (WEdit *edit, long click, int y)
+{
+    edit_cursor_move (edit, click - edit->curs1);
+}
+
+static void dclick (WEdit *edit, XEvent *event)
+{
+    edit_mark_cmd (edit, 1);
+    edit_right_word_move (edit);
+    edit_mark_cmd (edit, 0);
+    edit_left_word_move (edit);
+    release_mark (edit, event);
+}
+
+static void redraw (WEdit *edit, long click)
+{
+    mouse_redraw (edit, click);
+}
+
+void edit_insert_column_of_text (WEdit * edit, unsigned char *data, int size, int width);
+
+/* strips out the first i chars and returns a null terminated string, result must be free'd */
+char *filename_from_url (char *data, int size, int i)
+{
+    char *p, *f;
+    int l;
+    for (p = data + i; (unsigned long) p - (unsigned long) data < size && *p && *p != '\n'; p++);
+    l = (unsigned long) p - (unsigned long) data - i;
+    f = malloc (l + 1);
+    memcpy (f, data + i, l);
+    f[l] = '\0';
+    return f;
+}
+
+static int insert_drop (WEdit * e, Window from, unsigned char *data, int size, int xs, int ys, Atom type, Atom action)
+{
+#ifndef GTK
+    long start_mark = 0, end_mark = 0;
+    int x, y;
+
+    edit_translate_xy (xs, ys, &x, &y);
+/* musn't be able to drop into a block, otherwise a single click will copy a block: */
+    if (eval_marks (e, &start_mark, &end_mark))
+	goto fine;
+    if (start_mark > e->curs1 || e->curs1 >= end_mark)
+	goto fine;
+    if (column_highlighting) {
+	if (!((x >= e->column1 && x < e->column2)
+	      || (x > e->column2 && x <= e->column1)))
+	    goto fine;
+    }
+    return 1;
+  fine:
+    if (from == e->widget->winid && action == CDndClass->XdndActionMove) {
+	edit_block_move_cmd (e);
+	edit_mark_cmd (e, 1);
+	return 0;
+    } else if (from == e->widget->winid) {
+	edit_block_copy_cmd (e);
+	return 0;
+    } else {			/*  data from another widget, or from another application */
+	edit_push_action (e, KEY_PRESS + e->start_display);
+	if (type == XInternAtom (CDisplay, "url/url", False)) {
+	    if (!strncmp ((char *) data, "file:/", 6)) {
+		char *f;
+		edit_insert_file (e, f = filename_from_url ((char *) data, size, strlen ("file:")));
+		free (f);
+	    } else {
+		while (size--)
+		    edit_insert_ahead (e, data[size]);
+	    }
+	} else {
+	    if (column_highlighting) {
+		edit_insert_column_of_text (e, data, size, abs (e->column2 - e->column1));
+	    } else {
+		while (size--)
+		    edit_insert_ahead (e, data[size]);
+	    }
+	}
+    }
+    CExpose (e->widget->ident);
+#endif
+    return 0;
+}
+
+static char *mime_majors[2] =
+    {"text", 0};
+
+struct mouse_funcs edit_mouse_funcs =
+{
+    0,
+    (void (*)(int, int, int *, int *)) xy,
+    (long (*)(void *, int, int)) cp,
+    (int (*)(void *, long *, long *)) marks,
+    (int (*)(void *, long, long, long)) erange,
+    (void (*)(void *)) fin_mark,
+    (void (*)(void *)) move_mark,
+    (void (*)(void *, XEvent *)) release_mark,
+    (char *(*)(void *, long, long, int *, int *)) get_block,
+    (void (*)(void *, long, int)) move,
+    0,
+    (void (*)(void *, XEvent *)) dclick,
+    (void (*)(void *, long)) redraw,
+    (int (*)(void *, Window, unsigned char *, int, int, int, Atom, Atom)) insert_drop,
+    (void (*)(void *)) edit_block_delete,
+    DndText,
+    mime_majors
+};
+
+#ifndef GTK
+
+extern int option_editor_bg_normal;
+void edit_tri_cursor (Window win);
+
+/* starting_directory is for the filebrowser */
+CWidget *CDrawEditor (const char *identifier, Window parent, int x, int y,
+	   int width, int height, const char *text, const char *filename,
+		const char *starting_directory, unsigned int options, unsigned long text_size)
+{
+    static made_directory = 0;
+    int extra_space_for_hscroll = 0;
+    CWidget *w;
+    WEdit *e;
+
+    if (options & EDITOR_HORIZ_SCROLL)
+	extra_space_for_hscroll = 8;
+
+    wedit = w = CSetupWidget (identifier, parent, x, y,
+			      width + 7, height + 6, C_EDITOR_WIDGET,
+		   ExposureMask | ButtonPressMask | ButtonReleaseMask | \
+		     KeyPressMask | KeyReleaseMask | ButtonMotionMask | \
+			      PropertyChangeMask | StructureNotifyMask | \
+			      EnterWindowMask | LeaveWindowMask, color_palette (option_editor_bg_normal), 1);
+
+    xdnd_set_dnd_aware (CDndClass, w->winid, 0);
+    xdnd_set_type_list (CDndClass, w->winid, xdnd_typelist_send[DndText]);
+
+    edit_tri_cursor (w->winid);
+    w->options = options | WIDGET_TAKES_SELECTION;
+
+    w->destroy = edit_destroy_callback;
+    if (filename)
+	w->label = strdup (filename);
+    else
+	w->label = strdup ("");
+
+    if (!made_directory) {
+	mkdir (catstrs (home_dir, EDIT_DIR, 0), 0700);
+	made_directory = 1;
+    }
+    e = w->editor = CMalloc (sizeof (WEdit));
+    w->funcs = mouse_funcs_new (w->editor, &edit_mouse_funcs);
+
+    if (!w->editor) {
+/* Not essential to translate */
+	CError (_ ("Error initialising editor.\n"));
+	return 0;
+    }
+    w->editor->widget = w;
+    e = w->editor = edit_init (e, height / FONT_PIX_PER_LINE, width / FONT_MEAN_WIDTH, filename, text, starting_directory, text_size);
+    w->funcs->data = (void *) w->editor;
+    if (!e) {
+	CDestroyWidget (w->ident);
+	return 0;
+    }
+    e->macro_i = -1;
+    e->widget = w;
+
+    set_hint_pos (x + width + 7 + WIDGET_SPACING, y + height + 6 + WIDGET_SPACING + extra_space_for_hscroll);
+    if (extra_space_for_hscroll) {
+	w->hori_scrollbar = CDrawHorizontalScrollbar (catstrs (identifier, ".hsc", 0), parent,
+		x, y + height + 6, width + 6, 12, 0, 0);
+	CSetScrollbarCallback (w->hori_scrollbar->ident, w->ident, link_hscrollbar_to_editor);
+    }
+    if (!(options & EDITOR_NO_TEXT))
+	CDrawText (catstrs (identifier, ".text", 0), parent, x, y + height + 6 + WIDGET_SPACING + extra_space_for_hscroll, "%s", e->filename);
+    if (!(options & EDITOR_NO_SCROLL)) {
+	w->vert_scrollbar = CDrawVerticalScrollbar (catstrs (identifier, ".vsc", 0), parent,
+		x + width + 7 + WIDGET_SPACING, y, height + 6, 20, 0, 0);
+	CSetScrollbarCallback (w->vert_scrollbar->ident, w->ident, link_scrollbar_to_editor);
+    }
+    return w;
+}
+
+#endif
+
+#ifdef GTK
+
+void update_scroll_bars (WEdit * e)
+{
+
+}
+
+#else
+
+void update_scroll_bars (WEdit * e)
+{
+    int i, x1, x2;
+    CWidget *scroll;
+    scroll = e->widget->vert_scrollbar;
+    if (scroll) {
+	i = e->total_lines - e->start_line + 1;
+	if (i > e->num_widget_lines)
+	    i = e->num_widget_lines;
+	if (e->total_lines) {
+	    x1 = (double) 65535.0 *e->start_line / (e->total_lines + 1);
+	    x2 = (double) 65535.0 *i / (e->total_lines + 1);
+	} else {
+	    x1 = 0;
+	    x2 = 65535;
+	}
+	if (x1 != scroll->firstline || x2 != scroll->numlines) {
+	    scroll->firstline = x1;
+	    scroll->numlines = x2;
+	    EditExposeRedraw = 1;
+	    render_scrollbar (scroll);
+	    EditExposeRedraw = 0;
+	}
+    }
+    scroll = e->widget->hori_scrollbar;
+    if (scroll) {
+	i = e->max_column - (-e->start_col) + 1;
+	if (i > e->num_widget_columns * FONT_MEAN_WIDTH)
+	    i = e->num_widget_columns * FONT_MEAN_WIDTH;
+	x1 = (double) 65535.0 *(-e->start_col) / (e->max_column + 1);
+	x2 = (double) 65535.0 *i / (e->max_column + 1);
+	if (x1 != scroll->firstline || x2 != scroll->numlines) {
+	    scroll->firstline = x1;
+	    scroll->numlines = x2;
+	    EditExposeRedraw = 1;
+	    render_scrollbar (scroll);
+	    EditExposeRedraw = 0;
+	}
+    }
+}
+
+#endif
+
+void edit_mouse_mark (WEdit * edit, XEvent * event, int double_click)
+{
+    edit_update_curs_row (edit);
+    edit_update_curs_col (edit);
+    if (event->type != MotionNotify) {
+	edit_push_action (edit, KEY_PRESS + edit->start_display);
+	if (edit->mark2 == -1)
+	    edit_push_action (edit, MARK_1 + edit->mark1);	/* mark1 must be following the cursor */
+    }
+    if (event->type == ButtonPress) {
+	edit->highlight = 0;
+	edit->found_len = 0;
+    }
+    mouse_mark (
+	event,
+	double_click,
+	edit->widget->funcs
+    );
+}
+
+#ifdef GTK
+
+#else
+
+void link_scrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * xevent, CEvent * cwevent, int whichscrbutton)
+{
+    int i, start_line;
+    WEdit *e;
+    e = editor->editor;
+    if (!e)
+	return;
+    if (!e->widget->vert_scrollbar)
+	return;
+    start_line = e->start_line;
+    if ((xevent->type == ButtonRelease || xevent->type == MotionNotify) && whichscrbutton == 3) {
+	edit_move_display (e, (double) scrollbar->firstline * e->total_lines / 65535.0 + 1);
+    } else if (xevent->type == ButtonPress && (cwevent->button == Button1 || cwevent->button == Button2)) {
+	switch (whichscrbutton) {
+	case 1:
+	    edit_move_display (e, e->start_line - e->num_widget_lines + 1);
+	    break;
+	case 2:
+	    edit_move_display (e, e->start_line - 1);
+	    break;
+	case 5:
+	    edit_move_display (e, e->start_line + 1);
+	    break;
+	case 4:
+	    edit_move_display (e, e->start_line + e->num_widget_lines - 1);
+	    break;
+	}
+    }
+    if (e->total_lines)
+	scrollbar->firstline = (double) 65535.0 *e->start_line / (e->total_lines + 1);
+    else
+	scrollbar->firstline = 0;
+    i = e->total_lines - e->start_line + 1;
+    if (i > e->num_widget_lines)
+	i = e->num_widget_lines;
+    if (e->total_lines)
+	scrollbar->numlines = (double) 65535.0 *i / (e->total_lines + 1);
+    else
+	scrollbar->numlines = 65535;
+    if (start_line != e->start_line) {
+	e->force |= REDRAW_PAGE | REDRAW_LINE;
+	set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
+	if (CCheckWindowEvent (xevent->xany.window, ButtonReleaseMask | ButtonMotionMask, 0))
+	    return;
+    }
+    if (e->force) {
+	edit_render_keypress (e);
+	edit_status (e);
+    }
+}
+
+#endif
+
+#ifdef GTK
+
+#else
+
+void link_hscrollbar_to_editor (CWidget * scrollbar, CWidget * editor, XEvent * xevent, CEvent * cwevent, int whichscrbutton)
+{
+    int i, start_col;
+    WEdit *e;
+    e = editor->editor;
+    if (!e)
+	return;
+    if (!e->widget->hori_scrollbar)
+	return;
+    start_col = (-e->start_col);
+    if ((xevent->type == ButtonRelease || xevent->type == MotionNotify) && whichscrbutton == 3) {
+	e->start_col = (double) scrollbar->firstline * e->max_column / 65535.0 + 1;
+	e->start_col -= e->start_col % FONT_MEAN_WIDTH;
+	if (e->start_col < 0)
+	    e->start_col = 0;
+	e->start_col = (-e->start_col);
+    } else if (xevent->type == ButtonPress && (cwevent->button == Button1 || cwevent->button == Button2)) {
+	switch (whichscrbutton) {
+	case 1:
+	    edit_scroll_left (e, (e->num_widget_columns - 1) * FONT_MEAN_WIDTH);
+	    break;
+	case 2:
+	    edit_scroll_left (e, FONT_MEAN_WIDTH);
+	    break;
+	case 5:
+	    edit_scroll_right (e, FONT_MEAN_WIDTH);
+	    break;
+	case 4:
+	    edit_scroll_right (e, (e->num_widget_columns - 1) * FONT_MEAN_WIDTH);
+	    break;
+	}
+    }
+    scrollbar->firstline = (double) 65535.0 *(-e->start_col) / (e->max_column + 1);
+    i = e->max_column - (-e->start_col) + 1;
+    if (i > e->num_widget_columns * FONT_MEAN_WIDTH)
+	i = e->num_widget_columns * FONT_MEAN_WIDTH;
+    scrollbar->numlines = (double) 65535.0 *i / (e->max_column + 1);
+    if (start_col != (-e->start_col)) {
+	e->force |= REDRAW_PAGE | REDRAW_LINE;
+	set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
+	if (CCheckWindowEvent (xevent->xany.window, ButtonReleaseMask | ButtonMotionMask, 0))
+	    return;
+    }
+    if (e->force) {
+	edit_render_keypress (e);
+	edit_status (e);
+    }
+}
+
+#endif
+
+/* 
+   This section comes from rxvt-2.21b1/src/screen.c by
+   Robert Nation <nation@rocket.sanders.lockheed.com> &
+   mods by mj olesen <olesen@me.QueensU.CA>
+
+   Changes made for cooledit
+ */
+void selection_send (XSelectionRequestEvent * rq)
+{
+    XEvent ev;
+    static Atom xa_targets = None;
+    if (xa_targets == None)
+	xa_targets = XInternAtom (CDisplay, "TARGETS", False);
+
+    ev.xselection.type = SelectionNotify;
+    ev.xselection.property = None;
+    ev.xselection.display = rq->display;
+    ev.xselection.requestor = rq->requestor;
+    ev.xselection.selection = rq->selection;
+    ev.xselection.target = rq->target;
+    ev.xselection.time = rq->time;
+
+    if (rq->target == xa_targets) {
+	/*
+	 * On some systems, the Atom typedef is 64 bits wide.
+	 * We need to have a typedef that is exactly 32 bits wide,
+	 * because a format of 64 is not allowed by the X11 protocol.
+	 */
+	typedef CARD32 Atom32;
+
+	Atom32 target_list[2];
+
+	target_list[0] = (Atom32) xa_targets;
+	target_list[1] = (Atom32) XA_STRING;
+
+	XChangeProperty (CDisplay, rq->requestor, rq->property,
+		xa_targets, 8 * sizeof (target_list[0]), PropModeReplace,
+			 (unsigned char *) target_list,
+			 sizeof (target_list) / sizeof (target_list[0]));
+	ev.xselection.property = rq->property;
+    } else if (rq->target == XA_STRING) {
+	XChangeProperty (CDisplay, rq->requestor, rq->property,
+			 XA_STRING, 8, PropModeReplace,
+			 selection.text, selection.len);
+	ev.xselection.property = rq->property;
+    }
+    XSendEvent (CDisplay, rq->requestor, False, 0, &ev);
+}
+
+/*{{{ paste selection */
+
+/*
+ * Respond to a notification that a primary selection has been sent
+ */
+void paste_prop (void *data, void (*insert) (void *, int), Window win, unsigned prop, int delete)
+{
+    long nread;
+    unsigned long bytes_after;
+
+    if (prop == None)
+	return;
+
+    nread = 0;
+    do {
+	unsigned char *s;
+	Atom actual_type;
+	int actual_fmt, i;
+	unsigned long nitems;
+
+#ifdef GTK
+#if 0
+/* *** */
+	if (gtk_get_window_property (win, prop,
+				nread / 4, 65536, delete,
+			      AnyPropertyType, &actual_type, &actual_fmt,
+				&nitems, &bytes_after,
+				&s) != Success) {
+	    XFree (s);
+	    return;
+	}
+#endif
+#else
+	if (XGetWindowProperty (CDisplay, win, prop,
+				nread / 4, 65536, delete,
+			      AnyPropertyType, &actual_type, &actual_fmt,
+				&nitems, &bytes_after,
+				&s) != Success) {
+	    XFree (s);
+	    return;
+	}
+#endif
+	nread += nitems;
+	for (i = 0; i < nitems; i++)
+	    (*insert) (data, s[i]);
+	XFree (s);
+    } while (bytes_after);
+}
+
+void selection_paste (WEdit * edit, Window win, unsigned prop, int delete)
+{
+    long c;
+    c = edit->curs1;
+    paste_prop ((void *) edit,
+		(void (*)(void *, int)) edit_insert,
+		win, prop, delete);
+    edit_cursor_move (edit, c - edit->curs1);
+    edit->force |= REDRAW_COMPLETELY | REDRAW_LINE;
+}
+
+/*}}} */
+
+void selection_clear (void)
+{
+    selection.text = 0;
+    selection.len = 0;
+}
+
+void edit_update_screen (WEdit * e)
+{
+    if (!e)
+	return;
+    if (!e->force)
+	return;
+
+    edit_scroll_screen_over_cursor (e);
+    edit_update_curs_row (e);
+    edit_update_curs_col (e);
+    update_scroll_bars (e);
+    edit_status (e);
+
+    if (e->force & REDRAW_COMPLETELY)
+	e->force |= REDRAW_PAGE;
+
+/* pop all events for this window for internal handling */
+    if (e->force & (REDRAW_CHAR_ONLY | REDRAW_COMPLETELY)) {
+	edit_render_keypress (e);
+#ifdef GTK
+    } else if (
+#if 0
+/* *** */
+    gtk_edit_key_pending () || gtk_edit_mouse_pending ()
+#else
+    0
+#endif
+    ) {
+#else
+    } else if (CCheckWindowEvent (e->widget->winid, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask, 0)
+	       || CKeyPending ()) {
+#endif
+	e->force |= REDRAW_PAGE;
+	return;
+    } else {
+	edit_render_keypress (e);
+    }
+}
+
+extern int space_width;
+
+#ifdef HAVE_DND
+#define free_data if (data) {free(data);data=0;}
+
+/* handles drag and drop */
+void handle_client_message (CWidget * w, XEvent * xevent)
+{
+    int data_type;
+    unsigned char *data = 0;
+    unsigned long size;
+    int xs, ys;
+    long start_line;
+    int x, y, r, deleted = 0;
+    long click;
+    unsigned int state;
+    long start_mark = 0, end_mark = 0;
+    WEdit *e = w->editor;
+
+/* see just below for a comment on what this is for: */
+    if (CIsDropAcknowledge (xevent, &state) != DndNotDnd) {
+	if (!(state & Button1Mask) && just_dropped_something) {
+	    edit_push_action (e, KEY_PRESS + e->start_display);
+	    edit_block_delete_cmd (e);
+	}
+	return;
+    }
+    data_type = CGetDrop (xevent, &data, &size, &xs, &ys);
+
+    if (data_type == DndNotDnd || xs < 0 || ys < 0 || xs >= CWidthOf (w) || ys >= CHeightOf (w)) {
+	free_data;
+	return;
+    }
+    edit_translate_xy (xs, ys, &x, &y);
+    click = edit_get_click_pos (e, x, y);
+
+    r = eval_marks (e, &start_mark, &end_mark);
+/* musn't be able to drop into a block, otherwise a single click will copy a block: */
+    if (r)
+	goto fine;
+    if (start_mark > click || click >= end_mark)
+	goto fine;
+    if (column_highlighting) {
+	if (!((x >= e->column1 && x < e->column2)
+	      || (x > e->column2 && x <= e->column1)))
+	    goto fine;
+    }
+    free_data;
+    return;
+  fine:
+    edit_push_action (e, KEY_PRESS + e->start_display);
+
+/* drops to the same window moving to the left: */
+    start_line = e->start_line;
+    if (xevent->xclient.data.l[2] == xevent->xclient.window && !(xevent->xclient.data.l[1] & Button1Mask))
+	if ((column_highlighting && x < max (e->column1, e->column2)) || !column_highlighting) {
+	    edit_block_delete_cmd (e);
+	    deleted = 1;
+	}
+    edit_update_curs_row (e);
+    edit_move_display (e, start_line);
+    click = edit_get_click_pos (e, x, y);	/* click pos changes with edit_block_delete_cmd() */
+    edit_cursor_move (e, click - e->curs1);
+    if (data_type == DndFile) {
+	edit_insert_file (e, (char *) data);
+    } else if (data_type != DndFiles) {
+	if (dnd_null_term_type (data_type)) {
+	    int len;
+	    len = strlen ((char *) data);
+	    size = min (len, size);
+	}
+	if (column_highlighting) {
+	    edit_insert_column_of_text (e, data, size, abs (e->column2 - e->column1));
+	} else {
+	    while (size--)
+		edit_insert_ahead (e, data[size]);
+	}
+    } else {
+	while (size--)
+	    edit_insert_ahead (e, data[size] ? data[size] : '\n');
+    }
+
+/* drops to the same window moving to the right: */
+    if (xevent->xclient.data.l[2] == xevent->xclient.window && !(xevent->xclient.data.l[1] & Button1Mask))
+	if (column_highlighting && !deleted)
+	    edit_block_delete_cmd (e);
+
+/* The drop has now been successfully recieved. We can now send an acknowledge
+   event back to the window that send the data. When this window recieves
+   the acknowledge event, the app can decide whether or not to delete the data.
+   This allows text to be safely moved betweem text windows without the
+   risk of data being lost. In our case, drag with button1 is a copy
+   drag, while drag with any other button is a move drag (i.e. the sending
+   application must delete its selection after recieving an acknowledge
+   event). We must not, however, send an acknowledge signal if a filelist
+   (for example) was passed to us, since the sender might take this to
+   mean that all those files can be deleted! The two types we can acknowledge
+   are: */
+    if (xevent->xclient.data.l[2] != xevent->xclient.window)	/* drops to the same window */
+	if (data_type == DndText || data_type == DndRawData)
+	    CDropAcknowledge (xevent);
+    e->force |= REDRAW_COMPLETELY | REDRAW_LINE;
+    free_data;
+}
+#endif
+
+#ifndef GTK
+
+int eh_editor (CWidget * w, XEvent * xevent, CEvent * cwevent)
+{
+    WEdit *e = w->editor;
+    int r = 0;
+    static int old_tab_spacing = -1;
+
+    if (!e)
+	return 0;
+
+    if (old_tab_spacing != option_tab_spacing)
+	e->force |= REDRAW_COMPLETELY + REDRAW_LINE;
+    old_tab_spacing = option_tab_spacing;
+
+    if (xevent->type == KeyPress) {
+	if (xevent->xkey.keycode == 0x31 && xevent->xkey.state == 0xD) {
+	    CSetColor (color_palette (18));
+	    CRectangle (w->winid, 0, 0, w->width, w->height);
+	}
+    }
+    switch (xevent->type) {
+    case SelectionNotify:
+	selection_paste (e, xevent->xselection.requestor, xevent->xselection.property, True);
+	r = 1;
+	break;
+    case SelectionRequest:
+	selection_send (&(xevent->xselectionrequest));
+	return 1;
+/*  case SelectionClear:   ---> This is handled by coolnext.c: CNextEvent() */
+#ifdef HAVE_DND
+    case ClientMessage:
+	handle_client_message (w, xevent);
+	r = 1;
+#endif
+	break;
+    case ButtonPress:
+	CFocus (w);
+	edit_render_tidbits (w);
+    case ButtonRelease:
+	if (xevent->xbutton.state & ControlMask) {
+	    if (!column_highlighting)
+		edit_push_action (e, COLUMN_OFF);
+	    column_highlighting = 1;
+	} else {
+	    if (column_highlighting)
+		edit_push_action (e, COLUMN_ON);
+	    column_highlighting = 0;
+	}
+    case MotionNotify:
+	if (!xevent->xmotion.state && xevent->type == MotionNotify)
+	    return 0;
+	resolve_button (xevent, cwevent);
+	edit_mouse_mark (e, xevent, cwevent->double_click);
+	break;
+    case Expose:
+	edit_render_expose (e, &(xevent->xexpose));
+	return 1;
+    case FocusIn:
+	CSetCursorColor (e->overwrite ? color_palette (24) : color_palette (19));
+    case FocusOut:
+	edit_render_tidbits (w);
+	e->force |= REDRAW_CHAR_ONLY | REDRAW_LINE;
+	edit_render_keypress (e);
+	return 1;
+	break;
+    case KeyRelease:
+#if 0
+	if (column_highlighting) {
+	    column_highlighting = 0;
+	    e->force = REDRAW_COMPLETELY | REDRAW_LINE;
+	    edit_mark_cmd (e, 1);
+	}
+#endif
+	break;
+    case KeyPress:
+	cwevent->ident = w->ident;
+	if (!cwevent->command && cwevent->insert < 0) {		/* no translation */
+	    if ((cwevent->key == XK_r || cwevent->key == XK_R) && (cwevent->state & ControlMask)) {
+		cwevent->command = e->macro_i < 0 ? CK_Begin_Record_Macro : CK_End_Record_Macro;
+	    } else {
+		cwevent->command = CKeySymMod (xevent);
+		if (cwevent->command > 0)
+		    cwevent->command = CK_Macro (cwevent->command);
+		else
+		    break;
+	    }
+	}
+	r = edit_execute_key_command (e, cwevent->command, cwevent->insert);
+	if (r)
+	    edit_update_screen (e);
+	return r;
+	break;
+    case EditorCommand:
+	cwevent->ident = w->ident;
+	cwevent->command = xevent->xkey.keycode;
+	r = cwevent->handled = edit_execute_key_command (e, xevent->xkey.keycode, -1);
+	if (r)
+	    edit_update_screen (e);
+	return r;
+    default:
+	return 0;
+    }
+    edit_update_screen (e);
+    return r;
+}
+
+#endif	/* ! GTK */
+
+#else
+
+WEdit *wedit;
+WButtonBar *edit_bar;
+Dlg_head *edit_dlg;
+WMenu *edit_menubar;
+
+int column_highlighting = 0;
+
+static int edit_callback (Dlg_head * h, WEdit * edit, int msg, int par);
+
+static int edit_mode_callback (struct Dlg_head *h, int id, int msg)
+{
+    return 0;
+}
+
+int edit_event (WEdit * edit, Gpm_Event * event, int *result)
+{
+    *result = MOU_NORMAL;
+    edit_update_curs_row (edit);
+    edit_update_curs_col (edit);
+    if (event->type & (GPM_DOWN | GPM_DRAG | GPM_UP)) {
+	if (event->y > 1 && event->x > 0
+	    && event->x <= edit->num_widget_columns
+	    && event->y <= edit->num_widget_lines + 1) {
+	    if (edit->mark2 != -1 && event->type & (GPM_UP | GPM_DRAG))
+		return 1;	/* a lone up mustn't do anything */
+	    if (event->type & (GPM_DOWN | GPM_UP))
+		edit_push_key_press (edit);
+	    edit_cursor_move (edit, edit_bol (edit, edit->curs1) - edit->curs1);
+	    if (--event->y > (edit->curs_row + 1))
+		edit_cursor_move (edit,
+				  edit_move_forward (edit, edit->curs1, event->y - (edit->curs_row + 1), 0)
+				  - edit->curs1);
+	    if (event->y < (edit->curs_row + 1))
+		edit_cursor_move (edit,
+				  +edit_move_backward (edit, edit->curs1, (edit->curs_row + 1) - event->y)
+				  - edit->curs1);
+	    edit_cursor_move (edit, (int) edit_move_forward3 (edit, edit->curs1,
+		       event->x - edit->start_col - 1, 0) - edit->curs1);
+	    edit->prev_col = edit_get_col (edit);
+	    if (event->type & GPM_DOWN) {
+		edit_mark_cmd (edit, 1);	/* reset */
+		edit->highlight = 0;
+	    }
+	    if (!(event->type & GPM_DRAG))
+		edit_mark_cmd (edit, 0);
+	    edit->force |= REDRAW_COMPLETELY;
+	    edit_update_curs_row (edit);
+	    edit_update_curs_col (edit);
+	    edit_update_screen (edit);
+	    return 1;
+	}
+    }
+    return 0;
+}
+
+
+
+int menubar_event (Gpm_Event * event, WMenu * menubar);		/* menu.c */
+
+int edit_mouse_event (Gpm_Event * event, void *x)
+{
+    int result;
+    if (edit_event ((WEdit *) x, event, &result))
+	return result;
+    else
+	return menubar_event (event, edit_menubar);
+}
+
+extern Menu EditMenuBar[5];
+
+int edit (const char *_file, int line)
+{
+    static int made_directory = 0;
+    int framed = 0;
+    int midnight_colors[4];
+    char *text = 0;
+
+    if (option_backup_ext_int != -1) {
+	option_backup_ext = malloc (sizeof(int) + 1);
+	option_backup_ext[sizeof(int)] = '\0';
+	memcpy (option_backup_ext, (char *) &option_backup_ext_int, sizeof (int));
+    }
+
+    if (!made_directory) {
+	mkdir (catstrs (home_dir, EDIT_DIR, 0), 0700);
+	made_directory = 1;
+    }
+    if (_file) {
+	if (!(*_file)) {
+	    _file = 0;
+	    text = "";
+	}
+    } else
+	text = "";
+
+    if (!(wedit = edit_init (NULL, LINES - 2, COLS, _file, text, "", 0))) {
+	message (1, _(" Error "), get_error_msg (""));
+	return 0;
+    }
+    wedit->macro_i = -1;
+
+    /* Create a new dialog and add it widgets to it */
+    edit_dlg = create_dlg (0, 0, LINES, COLS, midnight_colors,
+			   edit_mode_callback, "[Internal File Editor]",
+			   "edit",
+			   DLG_NONE);
+
+    edit_dlg->raw = 1;		/*so that tab = '\t' key works */
+
+    init_widget (&(wedit->widget), 0, 0, LINES - 1, COLS,
+		 (callback_fn) edit_callback,
+		 (destroy_fn) edit_clean,
+		 (mouse_h) edit_mouse_event, 0);
+
+    widget_want_cursor (wedit->widget, 1);
+
+    edit_bar = buttonbar_new (1);
+
+    if (!framed) {
+	switch (edit_key_emulation) {
+	case EDIT_KEY_EMULATION_NORMAL:
+	    edit_init_menu_normal ();	/* editmenu.c */
+	    break;
+	case EDIT_KEY_EMULATION_EMACS:
+	    edit_init_menu_emacs ();	/* editmenu.c */
+	    break;
+	}
+	edit_menubar = menubar_new (0, 0, COLS, EditMenuBar, N_menus);
+    }
+    add_widget (edit_dlg, wedit);
+
+    if (!framed)
+	add_widget (edit_dlg, edit_menubar);
+
+    add_widget (edit_dlg, edit_bar);
+    edit_move_display (wedit, line - 1);
+    edit_move_to_line (wedit, line - 1);
+
+    run_dlg (edit_dlg);
+
+    if (!framed)
+	edit_done_menu ();	/* editmenu.c */
+
+    destroy_dlg (edit_dlg);
+
+    return 1;
+}
+
+static void edit_my_define (Dlg_head * h, int idx, char *text,
+			    void (*fn) (WEdit *), WEdit * edit)
+{
+    define_label_data (h, (Widget *) edit, idx, text, (buttonbarfn) fn, edit);
+}
+
+
+void cmd_F1 (WEdit * edit)
+{
+    send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (1));
+}
+
+void cmd_F2 (WEdit * edit)
+{
+    send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (2));
+}
+
+void cmd_F3 (WEdit * edit)
+{
+    send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (3));
+}
+
+void cmd_F4 (WEdit * edit)
+{
+    send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (4));
+}
+
+void cmd_F5 (WEdit * edit)
+{
+    send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (5));
+}
+
+void cmd_F6 (WEdit * edit)
+{
+    send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (6));
+}
+
+void cmd_F7 (WEdit * edit)
+{
+    send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (7));
+}
+
+void cmd_F8 (WEdit * edit)
+{
+    send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (8));
+}
+
+void cmd_F9 (WEdit * edit)
+{
+    send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (9));
+}
+
+void cmd_F10 (WEdit * edit)
+{
+    send_message (edit->widget.parent, (Widget *) edit, WIDGET_KEY, KEY_F (10));
+}
+
+void edit_labels (WEdit * edit)
+{
+    Dlg_head *h = edit->widget.parent;
+
+    edit_my_define (h, 1, _("Help"), cmd_F1, edit);
+    edit_my_define (h, 2, _("Save"), cmd_F2, edit);
+    edit_my_define (h, 3, _("Mark"), cmd_F3, edit);
+    edit_my_define (h, 4, _("Replac"), cmd_F4, edit);
+    edit_my_define (h, 5, _("Copy"), cmd_F5, edit);
+    edit_my_define (h, 6, _("Move"), cmd_F6, edit);
+    edit_my_define (h, 7, _("Search"), cmd_F7, edit);
+    edit_my_define (h, 8, _("Delete"), cmd_F8, edit);
+    if (!edit->have_frame)
+	edit_my_define (h, 9, _("PullDn"), edit_menu_cmd, edit);
+    edit_my_define (h, 10, _("Quit"), cmd_F10, edit);
+
+    redraw_labels (h, (Widget *) edit);
+}
+
+
+long get_key_state ()
+{
+    return (long) get_modifier ();
+}
+
+void edit_adjust_size (Dlg_head * h)
+{
+    WEdit *edit;
+    WButtonBar *edit_bar;
+
+    edit = (WEdit *) find_widget_type (h, (callback_fn) edit_callback);
+    edit_bar = (WButtonBar *) edit->widget.parent->current->next->widget;
+    widget_set_size (&edit->widget, 0, 0, LINES - 1, COLS);
+    widget_set_size (&edit_bar->widget, LINES - 1, 0, 1, COLS);
+    widget_set_size (&edit_menubar->widget, 0, 0, 1, COLS);
+
+#ifdef RESIZABLE_MENUBAR
+	menubar_arrange(edit_menubar);
+#endif
+}
+
+void edit_update_screen (WEdit * e)
+{
+    edit_scroll_screen_over_cursor (e);
+
+    edit_update_curs_col (e);
+    edit_status (e);
+
+/* pop all events for this window for internal handling */
+
+    if (!is_idle ()) {
+	e->force |= REDRAW_PAGE;
+	return;
+    }
+    if (e->force & REDRAW_COMPLETELY)
+	e->force |= REDRAW_PAGE;
+    edit_render_keypress (e);
+}
+
+static int edit_callback (Dlg_head * h, WEdit * e, int msg, int par)
+{
+    switch (msg) {
+    case WIDGET_INIT:
+	e->force |= REDRAW_COMPLETELY;
+	edit_labels (e);
+	break;
+    case WIDGET_DRAW:
+	e->force |= REDRAW_COMPLETELY;
+	e->num_widget_lines = LINES - 2;
+	e->num_widget_columns = COLS;
+    case WIDGET_FOCUS:
+	edit_update_screen (e);
+	return 1;
+    case WIDGET_KEY:{
+	    int cmd, ch;
+	    if (edit_drop_hotkey_menu (e, par))		/* first check alt-f, alt-e, alt-s, etc for drop menus */
+		return 1;
+	    if (!edit_translate_key (e, 0, par, get_key_state (), &cmd, &ch))
+		return 0;
+	    edit_execute_key_command (e, cmd, ch);
+	    edit_update_screen (e);
+	}
+	return 1;
+    case WIDGET_COMMAND:
+	edit_execute_key_command (e, par, -1);
+	edit_update_screen (e);
+	return 1;
+    case WIDGET_CURSOR:
+	widget_move (&e->widget, e->curs_row + EDIT_TEXT_VERTICAL_OFFSET, e->curs_col + e->start_col);
+	return 1;
+    }
+    return default_proc (h, msg, par);
+}
+
+#endif

+ 2881 - 0
edit/syntax.c

@@ -0,0 +1,2881 @@
+/* editor syntax highlighting.
+
+   Copyright (C) 1996, 1997, 1998 the Free Software Foundation
+
+   Authors: 1998 Paul Sheer
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <config.h>
+#if defined(MIDNIGHT) || defined(GTK)
+#include "edit.h"
+#else
+#include "coolwidget.h"
+#endif
+
+#if !defined(MIDNIGHT) || defined(HAVE_SYNTAXH)
+
+int option_syntax_highlighting = 1;
+
+/* these three functions are called from the outside */
+void edit_load_syntax (WEdit * edit, char **names, char *type);
+void edit_free_syntax_rules (WEdit * edit);
+void edit_get_syntax_color (WEdit * edit, long byte_index, int *fg, int *bg);
+
+static void *syntax_malloc (size_t x)
+{
+    void *p;
+    p = malloc (x);
+    memset (p, 0, x);
+    return p;
+}
+
+#define syntax_free(x) {if(x){free(x);(x)=0;}}
+
+static int compare_word_to_right (WEdit * edit, long i, char *text, char *whole_left, char *whole_right, int line_start)
+{
+    char *p;
+    int c, d, j;
+    if (!*text)
+	return 0;
+    c = edit_get_byte (edit, i - 1);
+    if (line_start)
+	if (c != '\n')
+	    return 0;
+    if (whole_left)
+	if (strchr (whole_left, c))
+	    return 0;
+    for (p = text; *p; p++, i++) {
+	switch (*p) {
+	case '\001':
+	    p++;
+	    for (;;) {
+		c = edit_get_byte (edit, i);
+		if (c == *p)
+		    break;
+		if (c == '\n')
+		    return 0;
+		i++;
+	    }
+	    break;
+	case '\002':
+	    p++;
+	    j = 0;
+	    for (;;) {
+		c = edit_get_byte (edit, i);
+		if (c == *p)
+		    j = i;
+		if (j && strchr (p + 1, c))		/* c exists further down, so it will get matched later */
+		    break;
+		if (c == '\n' || c == '\t' || c == ' ') {
+		    if (!j)
+			return 0;
+		    i = j;
+		    break;
+		}
+		if (whole_right)
+		    if (!strchr (whole_right, c)) {
+			if (!j)
+			    return 0;
+			i = j;
+			break;
+		    }
+		i++;
+	    }
+	    break;
+	case '\003':
+	    p++;
+#if 0
+	    c = edit_get_byte (edit, i++);
+	    for (j = 0; p[j] != '\003'; j++)
+		if (c == p[j])
+		    goto found_char1;
+	    return 0;
+	  found_char1:
+#endif
+	    c = -1;
+	    for (;; i++) {
+		d = c;
+		c = edit_get_byte (edit, i);
+		for (j = 0; p[j] != '\003'; j++)
+		    if (c == p[j])
+			goto found_char2;
+		break;
+	      found_char2:
+		j = c;		/* dummy command */
+	    }
+	    i--;
+	    while (*p != '\003')
+		p++;
+	    if (p[1] == d)
+		i--;
+	    break;
+#if 0
+	case '\004':
+	    p++;
+	    c = edit_get_byte (edit, i++);
+	    for (j = 0; p[j] != '\004'; j++)
+		if (c == p[j])
+		    return 0;
+	    for (;; i++) {
+		c = edit_get_byte (edit, i);
+		for (j = 0; p[j] != '\004'; j++)
+		    if (c == p[j])
+			goto found_char4;
+		continue;
+	      found_char4:
+		break;
+	    }
+	    i--;
+	    while (*p != '\004')
+		p++;
+	    break;
+#endif
+	default:
+	    if (*p != edit_get_byte (edit, i))
+		return 0;
+	}
+    }
+    if (whole_right)
+	if (strchr (whole_right, edit_get_byte (edit, i)))
+	    return 0;
+    return 1;
+}
+
+static int compare_word_to_left (WEdit * edit, long i, char *text, char *whole_left, char *whole_right, int line_start)
+{
+    char *p;
+    int c, d, j;
+    if (!*text)
+	return 0;
+    if (whole_right)
+	if (strchr (whole_right, edit_get_byte (edit, i + 1)))
+	    return 0;
+    for (p = text + strlen (text) - 1; (unsigned long) p >= (unsigned long) text; p--, i--) {
+	switch (*p) {
+	case '\001':
+	    p--;
+	    for (;;) {
+		c = edit_get_byte (edit, i);
+		if (c == *p)
+		    break;
+		if (c == '\n')
+		    return 0;
+		i--;
+	    }
+	    break;
+	case '\002':
+	    p--;
+	    for (;;) {
+		c = edit_get_byte (edit, i);
+		if (c == *p)
+		    break;
+		if (c == '\n' || c == '\t' || c == ' ')
+		    return 0;
+		if (whole_right)
+		    if (!strchr (whole_right, c))
+			return 0;
+		i--;
+	    }
+	    break;
+	case '\003':
+	    while (*(--p) != '\003');
+	    p++;
+#if 0
+	    c = edit_get_byte (edit, i--);
+	    for (j = 0; p[j] != '\003'; j++)
+		if (c == p[j])
+		    goto found_char1;
+	    return 0;
+	  found_char1:
+#endif
+	    c = -1;
+	    d = '\0';
+	    for (;; i--) {
+		d = c;
+		c = edit_get_byte (edit, i);
+		for (j = 0; p[j] != '\003'; j++)
+		    if (c == p[j])
+			goto found_char2;
+		break;
+	      found_char2:
+		j = c;	/* dummy command */
+	    }
+	    i++;
+	    p--;
+	    if (*(p - 1) == d)
+		i++;
+	    break;
+#if 0
+	case '\004':
+	    while (*(--p) != '\004');
+	    d = *p;
+	    p++;
+	    c = edit_get_byte (edit, i--);
+	    for (j = 0; p[j] != '\004'; j++)
+		if (c == p[j])
+		    return 0;
+	    for (;; i--) {
+		c = edit_get_byte (edit, i);
+		for (j = 0; p[j] != '\004'; j++)
+		    if (c == p[j] || c == '\n' || c == d)
+			goto found_char4;
+		continue;
+	      found_char4:
+		break;
+	    }
+	    i++;
+	    p--;
+	    break;
+#endif
+	default:
+	    if (*p != edit_get_byte (edit, i))
+		return 0;
+	}
+    }
+    c = edit_get_byte (edit, i);
+    if (line_start)
+	if (c != '\n')
+	    return 0;
+    if (whole_left)
+	if (strchr (whole_left, c))
+	    return 0;
+    return 1;
+}
+
+
+#if 0
+#define debug_printf(x,y) fprintf(stderr,x,y)
+#else
+#define debug_printf(x,y)
+#endif
+
+static inline unsigned long apply_rules_going_right (WEdit * edit, long i, unsigned long rule)
+{
+    struct context_rule *r;
+    int context, contextchanged = 0, keyword, c1, c2;
+    int found_right = 0, found_left = 0, keyword_foundleft = 0;
+    int done = 0;
+    unsigned long border;
+    context = (rule & RULE_CONTEXT) >> RULE_CONTEXT_SHIFT;
+    keyword = (rule & RULE_WORD) >> RULE_WORD_SHIFT;
+    border = rule & (RULE_ON_LEFT_BORDER | RULE_ON_RIGHT_BORDER);
+    c1 = edit_get_byte (edit, i - 1);
+    c2 = edit_get_byte (edit, i);
+    if (!c2 || !c1)
+	return rule;
+
+    debug_printf ("%c->", c1);
+    debug_printf ("%c ", c2);
+
+/* check to turn off a keyword */
+    if (keyword) {
+	struct key_word *k;
+	k = edit->rules[context]->keyword[keyword];
+	if (c1 == '\n')
+	    keyword = 0;
+	if (k->last == c1 && compare_word_to_left (edit, i - 1, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start)) {
+	    keyword = 0;
+	    keyword_foundleft = 1;
+	    debug_printf ("keyword=%d ", keyword);
+	}
+    }
+    debug_printf ("border=%s ", border ? ((border & RULE_ON_LEFT_BORDER) ? "left" : "right") : "off");
+
+/* check to turn off a context */
+    if (context && !keyword) {
+	r = edit->rules[context];
+	if (r->first_right == c2 && compare_word_to_right (edit, i, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right) \
+	    &&!(rule & RULE_ON_RIGHT_BORDER)) {
+	    debug_printf ("A:3 ", 0);
+	    found_right = 1;
+	    border = RULE_ON_RIGHT_BORDER;
+	    if (r->between_delimiters)
+		context = 0;
+	} else if (!found_left) {
+	    if (r->last_right == c1 && compare_word_to_left (edit, i - 1, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right) \
+		&&(rule & RULE_ON_RIGHT_BORDER)) {
+/* always turn off a context at 4 */
+		debug_printf ("A:4 ", 0);
+		found_left = 1;
+		border = 0;
+		if (!keyword_foundleft)
+		    context = 0;
+	    } else if (r->last_left == c1 && compare_word_to_left (edit, i - 1, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left) \
+		       &&(rule & RULE_ON_LEFT_BORDER)) {
+/* never turn off a context at 2 */
+		debug_printf ("A:2 ", 0);
+		found_left = 1;
+		border = 0;
+	    }
+	}
+    }
+    debug_printf ("\n", 0);
+
+/* check to turn on a keyword */
+    if (!keyword) {
+	char *p;
+	p = (r = edit->rules[context])->keyword_first_chars;
+	while ((p = strchr (p + 1, c2))) {
+	    struct key_word *k;
+	    int count;
+	    count = (unsigned long) p - (unsigned long) r->keyword_first_chars;
+	    k = r->keyword[count];
+	    if (compare_word_to_right (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start)) {
+		keyword = count;
+		debug_printf ("keyword=%d ", keyword);
+		break;
+	    }
+	}
+    }
+/* check to turn on a context */
+    if (!context) {
+	int count;
+	for (count = 1; edit->rules[count] && !done; count++) {
+	    r = edit->rules[count];
+	    if (!found_left) {
+		if (r->last_right == c1 && compare_word_to_left (edit, i - 1, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right) \
+		    &&(rule & RULE_ON_RIGHT_BORDER)) {
+		    debug_printf ("B:4 count=%d", count);
+		    found_left = 1;
+		    border = 0;
+		    context = 0;
+		    contextchanged = 1;
+		    keyword = 0;
+		} else if (r->last_left == c1 && compare_word_to_left (edit, i - 1, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left) \
+			   &&(rule & RULE_ON_LEFT_BORDER)) {
+		    debug_printf ("B:2 ", 0);
+		    found_left = 1;
+		    border = 0;
+		    if (r->between_delimiters) {
+			context = count;
+			contextchanged = 1;
+			keyword = 0;
+			debug_printf ("context=%d ", context);
+			if (r->first_right == c2 && compare_word_to_right (edit, i, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right)) {
+			    debug_printf ("B:3 ", 0);
+			    found_right = 1;
+			    border = RULE_ON_RIGHT_BORDER;
+			    context = 0;
+			}
+		    }
+		    break;
+		}
+	    }
+	    if (!found_right) {
+		if (r->first_left == c2 && compare_word_to_right (edit, i, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left)) {
+		    debug_printf ("B:1 ", 0);
+		    found_right = 1;
+		    border = RULE_ON_LEFT_BORDER;
+		    if (!r->between_delimiters) {
+			debug_printf ("context=%d ", context);
+			if (!keyword)
+			    context = count;
+		    }
+		    break;
+		}
+	    }
+	}
+    }
+    if (!keyword && contextchanged) {
+	char *p;
+	p = (r = edit->rules[context])->keyword_first_chars;
+	while ((p = strchr (p + 1, c2))) {
+	    struct key_word *k;
+	    int coutner;
+	    coutner = (unsigned long) p - (unsigned long) r->keyword_first_chars;
+	    k = r->keyword[coutner];
+	    if (compare_word_to_right (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start)) {
+		keyword = coutner;
+		debug_printf ("keyword=%d ", keyword);
+		break;
+	    }
+	}
+    }
+    debug_printf ("border=%s ", border ? ((border & RULE_ON_LEFT_BORDER) ? "left" : "right") : "off");
+    debug_printf ("keyword=%d ", keyword);
+
+    debug_printf (" %d#\n\n", context);
+
+    return (context << RULE_CONTEXT_SHIFT) | (keyword << RULE_WORD_SHIFT) | border;
+}
+
+static inline int resolve_left_delim (WEdit * edit, long i, struct context_rule *r, int s)
+{
+    int c, count;
+    if (!r->conflicts)
+	return s;
+    for (;;) {
+	c = edit_get_byte (edit, i);
+	if (c == '\n')
+	    break;
+	for (count = 1; r->conflicts[count]; count++) {
+	    struct context_rule *p;
+	    p = edit->rules[r->conflicts[count]];
+	    if (!p)
+		break;
+	    if (p->first_left == c && r->between_delimiters == p->between_delimiters && compare_word_to_right (edit, i, p->left, p->whole_word_chars_left, r->whole_word_chars_right, p->line_start_left))
+		return r->conflicts[count];
+	}
+	i--;
+    }
+    return 0;
+}
+
+static inline unsigned long apply_rules_going_left (WEdit * edit, long i, unsigned long rule)
+{
+    struct context_rule *r;
+    int context, contextchanged = 0, keyword, c2, c1;
+    int found_left = 0, found_right = 0, keyword_foundright = 0;
+    int done = 0;
+    unsigned long border;
+    context = (rule & RULE_CONTEXT) >> RULE_CONTEXT_SHIFT;
+    keyword = (rule & RULE_WORD) >> RULE_WORD_SHIFT;
+    border = rule & (RULE_ON_RIGHT_BORDER | RULE_ON_LEFT_BORDER);
+    c1 = edit_get_byte (edit, i);
+    c2 = edit_get_byte (edit, i + 1);
+    if (!c2 || !c1)
+	return rule;
+
+    debug_printf ("%c->", c2);
+    debug_printf ("%c ", c1);
+
+/* check to turn off a keyword */
+    if (keyword) {
+	struct key_word *k;
+	k = edit->rules[context]->keyword[keyword];
+	if (c2 == '\n')
+	    keyword = 0;
+	if ((k->first == c2 && compare_word_to_right (edit, i + 1, k->keyword, k->whole_word_chars_right, k->whole_word_chars_left, k->line_start)) || (c2 == '\n')) {
+	    keyword = 0;
+	    keyword_foundright = 1;
+	    debug_printf ("keyword=%d ", keyword);
+	}
+    }
+    debug_printf ("border=%s ", border ? ((border & RULE_ON_RIGHT_BORDER) ? "right" : "left") : "off");
+
+/* check to turn off a context */
+    if (context && !keyword) {
+	r = edit->rules[context];
+	if (r->last_left == c1 && compare_word_to_left (edit, i, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left) \
+	    &&!(rule & RULE_ON_LEFT_BORDER)) {
+	    debug_printf ("A:2 ", 0);
+	    found_left = 1;
+	    border = RULE_ON_LEFT_BORDER;
+	    if (r->between_delimiters)
+		context = 0;
+	} else if (!found_right) {
+	    if (r->first_left == c2 && compare_word_to_right (edit, i + 1, r->left, r->whole_word_chars_right, r->whole_word_chars_left, r->line_start_left) \
+		&&(rule & RULE_ON_LEFT_BORDER)) {
+/* always turn off a context at 4 */
+		debug_printf ("A:1 ", 0);
+		found_right = 1;
+		border = 0;
+		if (!keyword_foundright)
+		    context = 0;
+	    } else if (r->first_right == c2 && compare_word_to_right (edit, i + 1, r->right, r->whole_word_chars_right, r->whole_word_chars_left, r->line_start_right) \
+		       &&(rule & RULE_ON_RIGHT_BORDER)) {
+/* never turn off a context at 2 */
+		debug_printf ("A:3 ", 0);
+		found_right = 1;
+		border = 0;
+	    }
+	}
+    }
+    debug_printf ("\n", 0);
+
+/* check to turn on a keyword */
+    if (!keyword) {
+	char *p;
+	p = (r = edit->rules[context])->keyword_last_chars;
+	while ((p = strchr (p + 1, c1))) {
+	    struct key_word *k;
+	    int count;
+	    count = (unsigned long) p - (unsigned long) r->keyword_last_chars;
+	    k = r->keyword[count];
+	    if (compare_word_to_left (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start)) {
+		keyword = count;
+		debug_printf ("keyword=%d ", keyword);
+		break;
+	    }
+	}
+    }
+/* check to turn on a context */
+    if (!context) {
+	int count;
+	for (count = 1; edit->rules[count] && !done; count++) {
+	    r = edit->rules[count];
+	    if (!found_right) {
+		if (r->first_left == c2 && compare_word_to_right (edit, i + 1, r->left, r->whole_word_chars_right, r->whole_word_chars_left, r->line_start_left) \
+		    &&(rule & RULE_ON_LEFT_BORDER)) {
+		    debug_printf ("B:1 count=%d", count);
+		    found_right = 1;
+		    border = 0;
+		    context = 0;
+		    contextchanged = 1;
+		    keyword = 0;
+		} else if (r->first_right == c2 && compare_word_to_right (edit, i + 1, r->right, r->whole_word_chars_right, r->whole_word_chars_left, r->line_start_right) \
+			   &&(rule & RULE_ON_RIGHT_BORDER)) {
+		    if (!(c2 == '\n' && r->single_char)) {
+			debug_printf ("B:3 ", 0);
+			found_right = 1;
+			border = 0;
+			if (r->between_delimiters) {
+			    debug_printf ("context=%d ", context);
+			    context = resolve_left_delim (edit, i, r, count);
+			    contextchanged = 1;
+			    keyword = 0;
+			    if (r->last_left == c1 && compare_word_to_left (edit, i, r->left, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_left)) {
+				debug_printf ("B:2 ", 0);
+				found_left = 1;
+				border = RULE_ON_LEFT_BORDER;
+				context = 0;
+			    }
+			}
+			break;
+		    }
+		}
+	    }
+	    if (!found_left) {
+		if (r->last_right == c1 && compare_word_to_left (edit, i, r->right, r->whole_word_chars_left, r->whole_word_chars_right, r->line_start_right)) {
+		    if (!(c1 == '\n' && r->single_char)) {
+			debug_printf ("B:4 ", 0);
+			found_left = 1;
+			border = RULE_ON_RIGHT_BORDER;
+			if (!keyword)
+			    if (!r->between_delimiters)
+				context = resolve_left_delim (edit, i - 1, r, count);
+			break;
+		    }
+		}
+	    }
+	}
+    }
+    if (!keyword && contextchanged) {
+	char *p;
+	p = (r = edit->rules[context])->keyword_last_chars;
+	while ((p = strchr (p + 1, c1))) {
+	    struct key_word *k;
+	    int coutner;
+	    coutner = (unsigned long) p - (unsigned long) r->keyword_last_chars;
+	    k = r->keyword[coutner];
+	    if (compare_word_to_left (edit, i, k->keyword, k->whole_word_chars_left, k->whole_word_chars_right, k->line_start)) {
+		keyword = coutner;
+		debug_printf ("keyword=%d ", keyword);
+		break;
+	    }
+	}
+    }
+    debug_printf ("border=%s ", border ? ((border & RULE_ON_RIGHT_BORDER) ? "right" : "left") : "off");
+    debug_printf ("keyword=%d ", keyword);
+
+    debug_printf (" %d#\n\n", context);
+
+    return (context << RULE_CONTEXT_SHIFT) | (keyword << RULE_WORD_SHIFT) | border;
+}
+
+
+static unsigned long edit_get_rule (WEdit * edit, long byte_index)
+{
+    long i;
+    if (byte_index < 0) {
+	edit->last_get_rule = -1;
+	edit->rule = 0;
+	return 0;
+    }
+#if 0
+    if (byte_index < edit->last_get_rule_start_display) {
+/* this is for optimisation */
+	for (i = edit->last_get_rule_start_display - 1; i >= byte_index; i--)
+	    edit->rule_start_display = apply_rules_going_left (edit, i, edit->rule_start_display);
+	edit->last_get_rule_start_display = byte_index;
+	edit->rule = edit->rule_start_display;
+    } else
+#endif
+    if (byte_index > edit->last_get_rule) {
+	for (i = edit->last_get_rule + 1; i <= byte_index; i++)
+	    edit->rule = apply_rules_going_right (edit, i, edit->rule);
+    } else if (byte_index < edit->last_get_rule) {
+	for (i = edit->last_get_rule - 1; i >= byte_index; i--)
+	    edit->rule = apply_rules_going_left (edit, i, edit->rule);
+    }
+    edit->last_get_rule = byte_index;
+    return edit->rule;
+}
+
+static void translate_rule_to_color (WEdit * edit, unsigned long rule, int *fg, int *bg)
+{
+    struct key_word *k;
+    k = edit->rules[(rule & RULE_CONTEXT) >> RULE_CONTEXT_SHIFT]->keyword[(rule & RULE_WORD) >> RULE_WORD_SHIFT];
+    *bg = k->bg;
+    *fg = k->fg;
+}
+
+void edit_get_syntax_color (WEdit * edit, long byte_index, int *fg, int *bg)
+{
+    unsigned long rule;
+    if (!edit->rules || byte_index >= edit->last_byte || !option_syntax_highlighting) {
+#ifdef MIDNIGHT
+	*fg = NORMAL_COLOR;
+#else
+	*fg = NO_COLOR;
+	*bg = NO_COLOR;
+#endif
+    } else {
+	rule = edit_get_rule (edit, byte_index);
+	translate_rule_to_color (edit, rule, fg, bg);
+    }
+}
+
+
+/*
+   Returns 0 on error/eof or a count of the number of bytes read
+   including the newline. Result must be free'd.
+ */
+static int read_one_line (char **line, FILE * f)
+{
+    char *p;
+    int len = 256, c, r = 0, i = 0;
+    p = syntax_malloc (len);
+    for (;;) {
+	c = fgetc (f);
+	if (c == -1) {
+	    r = 0;
+	    break;
+	} else if (c == '\n') {
+	    r = i + 1;		/* extra 1 for the newline just read */
+	    break;
+	} else {
+	    if (i >= len - 1) {
+		char *q;
+		q = syntax_malloc (len * 2);
+		memcpy (q, p, len);
+		syntax_free (p);
+		p = q;
+		len *= 2;
+	    }
+	    p[i++] = c;
+	}
+    }
+    p[i] = 0;
+    *line = p;
+    return r;
+}
+
+static char *strdup_convert (char *s)
+{
+#if 0
+    int e = 0;
+#endif
+    char *r, *p;
+    p = r = strdup (s);
+    while (*s) {
+	switch (*s) {
+	case '\\':
+	    s++;
+	    switch (*s) {
+	    case 'n':
+		*p = '\n';
+		break;
+	    case 'r':
+		*p = '\r';
+		break;
+	    case 't':
+		*p = '\t';
+		break;
+	    case 's':
+		*p = ' ';
+		break;
+	    case '*':
+		*p = '*';
+		break;
+	    case '\\':
+		*p = '\\';
+		break;
+	    case '[':
+	    case ']':
+		if ((unsigned long) p == (unsigned long) r || strlen (s) == 1)
+		    *p = *s;
+		else {
+#if 0
+		    if (!strncmp (s, "[^", 2)) {
+			*p = '\004';
+			e = 1;
+			s++;
+		    } else {
+			if (e)
+			    *p = '\004';
+			else
+#endif
+			    *p = '\003';
+#if 0
+			e = 0;
+		    }
+#endif
+		}
+		break;
+	    default:
+		*p = *s;
+		break;
+	    }
+	    break;
+	case '*':
+/* a * or + at the beginning or end of the line must be interpreted literally */
+	    if ((unsigned long) p == (unsigned long) r || strlen (s) == 1)
+		*p = '*';
+	    else
+		*p = '\001';
+	    break;
+	case '+':
+	    if ((unsigned long) p == (unsigned long) r || strlen (s) == 1)
+		*p = '+';
+	    else
+		*p = '\002';
+	    break;
+	default:
+	    *p = *s;
+	    break;
+	}
+	s++;
+	p++;
+    }
+    *p = 0;
+    return r;
+}
+
+#define whiteness(x) ((x) == '\t' || (x) == '\n' || (x) == ' ')
+
+static void get_args (char *l, char **args, int *argc)
+{
+    *argc = 0;
+    l--;
+    for (;;) {
+	char *p;
+	for (p = l + 1; *p && whiteness (*p); p++);
+	if (!*p)
+	    break;
+	for (l = p + 1; *l && !whiteness (*l); l++);
+	*l = '\0';
+	*args = strdup_convert (p);
+	(*argc)++;
+	args++;
+    }
+    *args = 0;
+}
+
+static void free_args (char **args)
+{
+    while (*args) {
+	syntax_free (*args);
+	*args = 0;
+	args++;
+    }
+}
+
+#define check_a {if(!*a){result=line;break;}}
+#define check_not_a {if(*a){result=line;break;}}
+
+#ifdef MIDNIGHT
+
+int try_alloc_color_pair (char *fg, char *bg);
+
+int this_try_alloc_color_pair (char *fg, char *bg)
+{
+    char f[80], b[80], *p;
+    if (bg)
+	if (!*bg)
+	    bg = 0;
+    if (fg)
+	if (!*fg)
+	    fg = 0;
+    if (fg) {
+	strcpy (f, fg);
+	p = strchr (f, '/');
+	if (p)
+	    *p = '\0';
+	fg = f;
+    }
+    if (bg) {
+	strcpy (b, bg);
+	p = strchr (b, '/');
+	if (p)
+	    *p = '\0';
+	bg = b;
+    }
+    return try_alloc_color_pair (fg, bg);
+}
+#else
+#ifdef GTK
+int allocate_color (WEdit *edit, gchar *color);
+
+int this_allocate_color (WEdit *edit, char *fg)
+{
+    char *p;
+    if (fg)
+	if (!*fg)
+	    fg = 0;
+    if (!fg)
+	return allocate_color (edit, 0);
+    p = strchr (fg, '/');
+    if (!p)
+	return allocate_color (edit, fg);
+    return allocate_color (edit, p + 1);
+}
+#else
+int this_allocate_color (WEdit *edit, char *fg)
+{
+    char *p;
+    if (fg)
+	if (!*fg)
+	    fg = 0;
+    if (!fg)
+	return allocate_color (0);
+    p = strchr (fg, '/');
+    if (!p)
+	return allocate_color (fg);
+    return allocate_color (p + 1);
+}
+#endif
+#endif
+
+/* returns line number on error */
+static int edit_read_syntax_rules (WEdit * edit, FILE * f)
+{
+    char *fg, *bg;
+    char last_fg[32] = "", last_bg[32] = "";
+    char whole_right[256];
+    char whole_left[256];
+    char *args[1024], *l = 0;
+    int line = 0;
+    struct context_rule **r, *c;
+    int num_words = -1, num_contexts = -1;
+    int argc, result = 0;
+    int i, j;
+
+    args[0] = 0;
+
+    strcpy (whole_left, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_01234567890");
+    strcpy (whole_right, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_01234567890");
+
+    r = edit->rules = syntax_malloc (256 * sizeof (struct context_rule *));
+
+    for (;;) {
+	char **a;
+	line++;
+	if (!read_one_line (&l, f))
+	    break;
+	get_args (l, args, &argc);
+	a = args + 1;
+	if (!args[0]) {
+	    /* do nothing */
+	} else if (!strcmp (args[0], "wholechars")) {
+	    check_a;
+	    if (!strcmp (*a, "left")) {
+		a++;
+		strcpy (whole_left, *a);
+	    } else if (!strcmp (*a, "right")) {
+		a++;
+		strcpy (whole_right, *a);
+	    } else {
+		strcpy (whole_left, *a);
+		strcpy (whole_right, *a);
+	    }
+	    a++;
+	    check_not_a;
+	} else if (!strcmp (args[0], "context")) {
+	    check_a;
+	    if (num_contexts == -1) {
+		if (strcmp (*a, "default")) {	/* first context is the default */
+		    *a = 0;
+		    check_a;
+		}
+		a++;
+		c = r[0] = syntax_malloc (sizeof (struct context_rule));
+		c->left = strdup (" ");
+		c->right = strdup (" ");
+		num_contexts = 0;
+	    } else {
+		c = r[num_contexts] = syntax_malloc (sizeof (struct context_rule));
+		if (!strcmp (*a, "exclusive")) {
+		    a++;
+		    c->between_delimiters = 1;
+		}
+		check_a;
+		if (!strcmp (*a, "whole")) {
+		    a++;
+		    c->whole_word_chars_left = strdup (whole_left);
+		    c->whole_word_chars_right = strdup (whole_right);
+		} else if (!strcmp (*a, "wholeleft")) {
+		    a++;
+		    c->whole_word_chars_left = strdup (whole_left);
+		} else if (!strcmp (*a, "wholeright")) {
+		    a++;
+		    c->whole_word_chars_right = strdup (whole_right);
+		}
+		check_a;
+		if (!strcmp (*a, "linestart")) {
+		    a++;
+		    c->line_start_left = 1;
+		}
+		check_a;
+		c->left = strdup (*a++);
+		check_a;
+		if (!strcmp (*a, "linestart")) {
+		    a++;
+		    c->line_start_right = 1;
+		}
+		check_a;
+		c->right = strdup (*a++);
+		c->last_left = c->left[strlen (c->left) - 1];
+		c->last_right = c->right[strlen (c->right) - 1];
+		c->first_left = *c->left;
+		c->first_right = *c->right;
+		c->single_char = (strlen (c->right) == 1);
+	    }
+	    c->keyword = syntax_malloc (1024 * sizeof (struct key_word *));
+	    num_words = 1;
+	    c->keyword[0] = syntax_malloc (sizeof (struct key_word));
+	    fg = *a;
+	    if (*a)
+		a++;
+	    bg = *a;
+	    if (*a)
+		a++;
+	    strcpy (last_fg, fg ? fg : "");
+	    strcpy (last_bg, bg ? bg : "");
+#ifdef MIDNIGHT
+	    c->keyword[0]->fg = this_try_alloc_color_pair (fg, bg);
+#else
+	    c->keyword[0]->fg = this_allocate_color (edit, fg);
+	    c->keyword[0]->bg = this_allocate_color (edit, bg);
+#endif
+	    c->keyword[0]->keyword = strdup (" ");
+	    check_not_a;
+	    num_contexts++;
+	} else if (!strcmp (args[0], "keyword")) {
+	    struct key_word *k;
+	    if (num_words == -1)
+		*a = 0;
+	    check_a;
+	    k = r[num_contexts - 1]->keyword[num_words] = syntax_malloc (sizeof (struct key_word));
+	    if (!strcmp (*a, "whole")) {
+		a++;
+		k->whole_word_chars_left = strdup (whole_left);
+		k->whole_word_chars_right = strdup (whole_right);
+	    } else if (!strcmp (*a, "wholeleft")) {
+		a++;
+		k->whole_word_chars_left = strdup (whole_left);
+	    } else if (!strcmp (*a, "wholeright")) {
+		a++;
+		k->whole_word_chars_right = strdup (whole_right);
+	    }
+	    check_a;
+	    if (!strcmp (*a, "linestart")) {
+		a++;
+		k->line_start = 1;
+	    }
+	    check_a;
+	    if (!strcmp (*a, "whole")) {
+		*a = 0;
+		check_a;
+	    }
+	    k->keyword = strdup (*a++);
+	    k->last = k->keyword[strlen (k->keyword) - 1];
+	    k->first = *k->keyword;
+	    fg = *a;
+	    if (*a)
+		a++;
+	    bg = *a;
+	    if (*a)
+		a++;
+	    if (!fg)
+		fg = last_fg;
+	    if (!bg)
+		bg = last_bg;
+#ifdef MIDNIGHT
+	    k->fg = this_try_alloc_color_pair (fg, bg);
+#else
+	    k->fg = this_allocate_color (edit, fg);
+	    k->bg = this_allocate_color (edit, bg);
+#endif
+	    check_not_a;
+	    num_words++;
+	} else if (!strncmp (args[0], "#", 1)) {
+	    /* do nothing for comment */
+	} else if (!strcmp (args[0], "file")) {
+	    break;
+	} else {		/* anything else is an error */
+	    *a = 0;
+	    check_a;
+	}
+	free_args (args);
+	syntax_free (l);
+    }
+    free_args (args);
+    syntax_free (l);
+
+    if (result)
+	return result;
+
+    if (num_contexts == -1) {
+	result = line;
+	return result;
+    }
+    for (i = 1; edit->rules[i]; i++) {
+	for (j = i + 1; edit->rules[j]; j++) {
+	    if (strstr (edit->rules[j]->right, edit->rules[i]->right) && strcmp (edit->rules[i]->right, "\n")) {
+		unsigned char *s;
+		if (!edit->rules[i]->conflicts)
+		    edit->rules[i]->conflicts = syntax_malloc (sizeof (unsigned char) * 260);
+		s = edit->rules[i]->conflicts;
+		s[strlen ((char *) s)] = (unsigned char) j;
+	    }
+	}
+    }
+
+    {
+	char first_chars[1024], *p;
+	char last_chars[1024], *q;
+	for (i = 0; edit->rules[i]; i++) {
+	    c = edit->rules[i];
+	    p = first_chars;
+	    q = last_chars;
+	    *p++ = (char) 1;
+	    *q++ = (char) 1;
+	    for (j = 1; c->keyword[j]; j++) {
+		*p++ = c->keyword[j]->first;
+		*q++ = c->keyword[j]->last;
+	    }
+	    *p = '\0';
+	    *q = '\0';
+	    c->keyword_first_chars = strdup (first_chars);
+	    c->keyword_last_chars = strdup (last_chars);
+	}
+    }
+
+    return result;
+}
+
+void (*syntax_change_callback) (CWidget *) = 0;
+
+void edit_set_syntax_change_callback (void (*callback) (CWidget *))
+{
+    syntax_change_callback = callback;
+}
+
+void edit_free_syntax_rules (WEdit * edit)
+{
+    int i, j;
+    if (!edit)
+	return;
+    if (!edit->rules)
+	return;
+    syntax_free (edit->syntax_type);
+    if (syntax_change_callback)
+#ifdef MIDNIGHT
+	(*syntax_change_callback) (&edit->widget);
+#else
+	(*syntax_change_callback) (edit->widget);
+#endif
+    for (i = 0; edit->rules[i]; i++) {
+	if (edit->rules[i]->keyword) {
+	    for (j = 0; edit->rules[i]->keyword[j]; j++) {
+		syntax_free (edit->rules[i]->keyword[j]->keyword);
+		syntax_free (edit->rules[i]->keyword[j]->whole_word_chars_left);
+		syntax_free (edit->rules[i]->keyword[j]->whole_word_chars_right);
+		syntax_free (edit->rules[i]->keyword[j]);
+	    }
+	}
+	syntax_free (edit->rules[i]->conflicts);
+	syntax_free (edit->rules[i]->left);
+	syntax_free (edit->rules[i]->right);
+	syntax_free (edit->rules[i]->whole_word_chars_left);
+	syntax_free (edit->rules[i]->whole_word_chars_right);
+	syntax_free (edit->rules[i]->keyword);
+	syntax_free (edit->rules[i]->keyword_first_chars);
+	syntax_free (edit->rules[i]->keyword_last_chars);
+	syntax_free (edit->rules[i]);
+    }
+    syntax_free (edit->rules);
+}
+
+#define CURRENT_SYNTAX_RULES_VERSION "33"
+
+char *syntax_text = 
+"# syntax rules version " CURRENT_SYNTAX_RULES_VERSION "\n"
+"# (after the slash is a Cooledit color, 0-26 or any of the X colors in rgb.txt)\n"
+"# black\n"
+"# red\n"
+"# green\n"
+"# brown\n"
+"# blue\n"
+"# magenta\n"
+"# cyan\n"
+"# lightgray\n"
+"# gray\n"
+"# brightred\n"
+"# brightgreen\n"
+"# yellow\n"
+"# brightblue\n"
+"# brightmagenta\n"
+"# brightcyan\n"
+"# white\n"
+"\n"
+"###############################################################################\n"
+"file ..\\*\\\\.diff$ Unified\\sDiff\\sOutput ^diff.\\*(-u|--unified)\n"
+"# yawn\n"
+"context default\n"
+"    keyword linestart @@*@@	green/16\n"
+"    keyword linestart \\s black/0 white/26\n"
+"context linestart diff \\n white/26 red/9\n"
+"context linestart --- \\n brightmagenta/20\n"
+"context linestart +++ \\n brightmagenta/20\n"
+"context linestart + \\n brightgreen/6\n"
+"context linestart - \\n brightred/18\n"
+"context linestart A \\n white/26 black/0\n"
+"context linestart B \\n white/26 black/0\n"
+"context linestart C \\n white/26 black/0\n"
+"context linestart D \\n white/26 black/0\n"
+"context linestart E \\n white/26 black/0\n"
+"context linestart F \\n white/26 black/0\n"
+"context linestart G \\n white/26 black/0\n"
+"context linestart H \\n white/26 black/0\n"
+"context linestart I \\n white/26 black/0\n"
+"context linestart J \\n white/26 black/0\n"
+"context linestart K \\n white/26 black/0\n"
+"context linestart L \\n white/26 black/0\n"
+"context linestart M \\n white/26 black/0\n"
+"context linestart N \\n white/26 black/0\n"
+"context linestart O \\n white/26 black/0\n"
+"context linestart P \\n white/26 black/0\n"
+"context linestart Q \\n white/26 black/0\n"
+"context linestart R \\n white/26 black/0\n"
+"context linestart S \\n white/26 black/0\n"
+"context linestart T \\n white/26 black/0\n"
+"context linestart U \\n white/26 black/0\n"
+"context linestart V \\n white/26 black/0\n"
+"context linestart W \\n white/26 black/0\n"
+"context linestart X \\n white/26 black/0\n"
+"context linestart Y \\n white/26 black/0\n"
+"context linestart Z \\n white/26 black/0\n"
+"\n"
+"###############################################################################\n"
+"file ..\\*\\\\.lsm$ LSM\\sFile\n"
+"\n"
+"context default\n"
+"    keyword linestart Begin3		brightmagenta/20\n"
+"    keyword linestart Title:\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s	red/9  yellow/24\n"
+"    keyword linestart Version:\\s\\s\\s\\s\\s\\s\\s\\s	red/9  yellow/24\n"
+"    keyword linestart Entered-date:\\s\\s\\s	red/9  yellow/24\n"
+"    keyword linestart Description:\\s\\s\\s\\s	red/9  yellow/24\n"
+"    keyword linestart Keywords:\\s\\s\\s\\s\\s\\s\\s	red/9  yellow/24\n"
+"    keyword linestart Alternate-site:\\s	red/9  yellow/24\n"
+"    keyword linestart Primary-site:\\s\\s\\s	red/9  yellow/24\n"
+"    keyword linestart Original-site:\\s\\s	red/9  yellow/24\n"
+"    keyword linestart Platforms:\\s\\s\\s\\s\\s\\s	red/9  yellow/24\n"
+"    keyword linestart Copying-policy:\\s	red/9  yellow/24\n"
+"    keyword linestart End			brightmagenta/20\n"
+"\n"
+"    keyword linestart \\t\\t				white/26 yellow/24\n"
+"    keyword linestart \\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s	white/26 yellow/24\n"
+"    keyword whole GPL	green/6\n"
+"    keyword whole BSD	green/6\n"
+"    keyword whole Shareware	green/6\n"
+"    keyword whole sunsite.unc.edu	green/6\n"
+"    keyword wholeright \\s*.tar.gz	green/6\n"
+"    keyword wholeright \\s*.lsm	green/6\n"
+"\n"
+"context linestart Author:\\s\\s\\s\\s\\s\\s\\s\\s\\s \\n brightred/19\n"
+"    keyword whole \\s*@*\\s(*)		cyan/16\n"
+"\n"
+"context linestart Maintained-by:\\s\\s \\n brightred/19\n"
+"    keyword whole \\s*@*\\s(*)		cyan/16\n"
+"\n"
+"###############################################################################\n"
+"file ..\\*\\\\.sh$ Shell\\sScript ^#!/.\\*/(ksh|bash|sh|pdkzsh)$\n"
+"\n"
+"context default\n"
+"    keyword whole for yellow/24\n"
+"    keyword whole in yellow/24\n"
+"    keyword whole do yellow/24\n"
+"    keyword whole done yellow/24\n"
+"    keyword whole select yellow/24\n"
+"    keyword whole case yellow/24\n"
+"    keyword whole if yellow/24\n"
+"    keyword whole then yellow/24\n"
+"    keyword whole elif yellow/24\n"
+"    keyword whole else yellow/24\n"
+"    keyword whole fi yellow/24\n"
+"    keyword whole while yellow/24\n"
+"    keyword whole until yellow/24\n"
+"    keyword ;; brightred/18\n"
+"    keyword ` brightred/18\n"
+"    keyword '*' green/6\n"
+"    keyword \" green/6\n"
+"    keyword ; brightcyan/17\n"
+"    keyword $(*) brightgreen/16\n"
+"    keyword ${*} brightgreen/16\n"
+"    keyword { brightcyan/14\n"
+"    keyword } brightcyan/14\n"
+"\n"
+"    keyword whole linestart #!/bin/\\[abkpct\\]sh brightcyan/17 black/0\n"
+"\n"
+"    keyword $\\* brightred/18\n"
+"    keyword $@ brightred/18\n"
+"    keyword $# brightred/18\n"
+"    keyword $? brightred/18\n"
+"    keyword $- brightred/18\n"
+"    keyword $$ brightred/18\n"
+"    keyword $! brightred/18\n"
+"    keyword $_ brightred/18\n"
+"\n"
+"    keyword wholeright $\\[0123456789\\]0 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]1 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]2 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]3 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]4 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]5 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]6 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]7 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]8 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]9 brightred/18\n"
+"\n"
+"    keyword wholeright $+A brightgreen/16\n"
+"    keyword wholeright $+B brightgreen/16\n"
+"    keyword wholeright $+C brightgreen/16\n"
+"    keyword wholeright $+D brightgreen/16\n"
+"    keyword wholeright $+E brightgreen/16\n"
+"    keyword wholeright $+F brightgreen/16\n"
+"    keyword wholeright $+G brightgreen/16\n"
+"    keyword wholeright $+H brightgreen/16\n"
+"    keyword wholeright $+I brightgreen/16\n"
+"    keyword wholeright $+J brightgreen/16\n"
+"    keyword wholeright $+K brightgreen/16\n"
+"    keyword wholeright $+L brightgreen/16\n"
+"    keyword wholeright $+M brightgreen/16\n"
+"    keyword wholeright $+N brightgreen/16\n"
+"    keyword wholeright $+O brightgreen/16\n"
+"    keyword wholeright $+P brightgreen/16\n"
+"    keyword wholeright $+Q brightgreen/16\n"
+"    keyword wholeright $+R brightgreen/16\n"
+"    keyword wholeright $+S brightgreen/16\n"
+"    keyword wholeright $+T brightgreen/16\n"
+"    keyword wholeright $+U brightgreen/16\n"
+"    keyword wholeright $+V brightgreen/16\n"
+"    keyword wholeright $+W brightgreen/16\n"
+"    keyword wholeright $+X brightgreen/16\n"
+"    keyword wholeright $+Y brightgreen/16\n"
+"    keyword wholeright $+Z brightgreen/16\n"
+"\n"
+"    keyword wholeright $+a brightgreen/16\n"
+"    keyword wholeright $+b brightgreen/16\n"
+"    keyword wholeright $+c brightgreen/16\n"
+"    keyword wholeright $+d brightgreen/16\n"
+"    keyword wholeright $+e brightgreen/16\n"
+"    keyword wholeright $+f brightgreen/16\n"
+"    keyword wholeright $+g brightgreen/16\n"
+"    keyword wholeright $+h brightgreen/16\n"
+"    keyword wholeright $+i brightgreen/16\n"
+"    keyword wholeright $+j brightgreen/16\n"
+"    keyword wholeright $+k brightgreen/16\n"
+"    keyword wholeright $+l brightgreen/16\n"
+"    keyword wholeright $+m brightgreen/16\n"
+"    keyword wholeright $+n brightgreen/16\n"
+"    keyword wholeright $+o brightgreen/16\n"
+"    keyword wholeright $+p brightgreen/16\n"
+"    keyword wholeright $+q brightgreen/16\n"
+"    keyword wholeright $+r brightgreen/16\n"
+"    keyword wholeright $+s brightgreen/16\n"
+"    keyword wholeright $+t brightgreen/16\n"
+"    keyword wholeright $+u brightgreen/16\n"
+"    keyword wholeright $+v brightgreen/16\n"
+"    keyword wholeright $+w brightgreen/16\n"
+"    keyword wholeright $+x brightgreen/16\n"
+"    keyword wholeright $+y brightgreen/16\n"
+"    keyword wholeright $+z brightgreen/16\n"
+"\n"
+"    keyword wholeright $+0 brightgreen/16\n"
+"    keyword wholeright $+1 brightgreen/16\n"
+"    keyword wholeright $+2 brightgreen/16\n"
+"    keyword wholeright $+3 brightgreen/16\n"
+"    keyword wholeright $+4 brightgreen/16\n"
+"    keyword wholeright $+5 brightgreen/16\n"
+"    keyword wholeright $+6 brightgreen/16\n"
+"    keyword wholeright $+7 brightgreen/16\n"
+"    keyword wholeright $+8 brightgreen/16\n"
+"    keyword wholeright $+9 brightgreen/16\n"
+"\n"
+"    keyword $ brightgreen/16\n"
+"\n"
+"    keyword wholeleft function*() brightblue/11\n"
+"\n"
+"    keyword whole arch cyan/14\n"
+"    keyword whole ash cyan/14\n"
+"    keyword whole awk cyan/14\n"
+"    keyword whole basename cyan/14\n"
+"    keyword whole bash cyan/14\n"
+"    keyword whole basnemae cyan/14\n"
+"    keyword whole bg_backup cyan/14\n"
+"    keyword whole bg_restore cyan/14\n"
+"    keyword whole bsh cyan/14\n"
+"    keyword whole cat cyan/14\n"
+"    keyword whole chgrp cyan/14\n"
+"    keyword whole chmod cyan/14\n"
+"    keyword whole chown cyan/14\n"
+"    keyword whole cp cyan/14\n"
+"    keyword whole cpio cyan/14\n"
+"    keyword whole csh cyan/14\n"
+"    keyword whole date cyan/14\n"
+"    keyword whole dd cyan/14\n"
+"    keyword whole df cyan/14\n"
+"    keyword whole dmesg cyan/14\n"
+"    keyword whole dnsdomainname cyan/14\n"
+"    keyword whole doexec cyan/14\n"
+"    keyword whole domainname cyan/14\n"
+"    keyword whole echo cyan/14\n"
+"    keyword whole ed cyan/14\n"
+"    keyword whole egrep cyan/14\n"
+"    keyword whole ex cyan/14\n"
+"    keyword whole false cyan/14\n"
+"    keyword whole fgrep cyan/14\n"
+"    keyword whole fsconf cyan/14\n"
+"    keyword whole gawk cyan/14\n"
+"    keyword whole grep cyan/14\n"
+"    keyword whole gunzip cyan/14\n"
+"    keyword whole gzip cyan/14\n"
+"    keyword whole hostname cyan/14\n"
+"    keyword whole igawk cyan/14\n"
+"    keyword whole ipcalc cyan/14\n"
+"    keyword whole kill cyan/14\n"
+"    keyword whole ksh cyan/14\n"
+"    keyword whole linuxconf cyan/14\n"
+"    keyword whole ln cyan/14\n"
+"    keyword whole login cyan/14\n"
+"    keyword whole lpdconf cyan/14\n"
+"    keyword whole ls cyan/14\n"
+"    keyword whole mail cyan/14\n"
+"    keyword whole mkdir cyan/14\n"
+"    keyword whole mknod cyan/14\n"
+"    keyword whole mktemp cyan/14\n"
+"    keyword whole more cyan/14\n"
+"    keyword whole mount cyan/14\n"
+"    keyword whole mt cyan/14\n"
+"    keyword whole mv cyan/14\n"
+"    keyword whole netconf cyan/14\n"
+"    keyword whole netstat cyan/14\n"
+"    keyword whole nice cyan/14\n"
+"    keyword whole nisdomainname cyan/14\n"
+"    keyword whole ping cyan/14\n"
+"    keyword whole ps cyan/14\n"
+"    keyword whole pwd cyan/14\n"
+"    keyword whole red cyan/14\n"
+"    keyword whole remadmin cyan/14\n"
+"    keyword whole rm cyan/14\n"
+"    keyword whole rmdir cyan/14\n"
+"    keyword whole rpm cyan/14\n"
+"    keyword whole sed cyan/14\n"
+"    keyword whole setserial cyan/14\n"
+"    keyword whole sh cyan/14\n"
+"    keyword whole sleep cyan/14\n"
+"    keyword whole sort cyan/14\n"
+"    keyword whole stty cyan/14\n"
+"    keyword whole su cyan/14\n"
+"    keyword whole sync cyan/14\n"
+"    keyword whole taper cyan/14\n"
+"    keyword whole tar cyan/14\n"
+"    keyword whole tcsh cyan/14\n"
+"    keyword whole touch cyan/14\n"
+"    keyword whole true cyan/14\n"
+"    keyword whole umount cyan/14\n"
+"    keyword whole uname cyan/14\n"
+"    keyword whole userconf cyan/14\n"
+"    keyword whole usleep cyan/14\n"
+"    keyword whole vi cyan/14\n"
+"    keyword whole view cyan/14\n"
+"    keyword whole vim cyan/14\n"
+"    keyword whole xconf cyan/14\n"
+"    keyword whole ypdomainname cyan/14\n"
+"    keyword whole zcat cyan/14\n"
+"    keyword whole zsh cyan/14\n"
+"\n"
+"context # \\n brown/22\n"
+"\n"
+"context exclusive ` ` white/26 black/0\n"
+"    keyword '*' green/6\n"
+"    keyword \" green/6\n"
+"    keyword ; brightcyan/17\n"
+"    keyword $(*) brightgreen/16\n"
+"    keyword ${*} brightgreen/16\n"
+"    keyword { brightcyan/14\n"
+"    keyword } brightcyan/14\n"
+"\n"
+"    keyword $\\* brightred/18\n"
+"    keyword $@ brightred/18\n"
+"    keyword $# brightred/18\n"
+"    keyword $? brightred/18\n"
+"    keyword $- brightred/18\n"
+"    keyword $$ brightred/18\n"
+"    keyword $! brightred/18\n"
+"    keyword $_ brightred/18\n"
+"\n"
+"    keyword wholeright $\\[0123456789\\]0 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]1 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]2 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]3 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]4 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]5 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]6 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]7 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]8 brightred/18\n"
+"    keyword wholeright $\\[0123456789\\]9 brightred/18\n"
+"\n"
+"    keyword wholeright $+A brightgreen/16\n"
+"    keyword wholeright $+B brightgreen/16\n"
+"    keyword wholeright $+C brightgreen/16\n"
+"    keyword wholeright $+D brightgreen/16\n"
+"    keyword wholeright $+E brightgreen/16\n"
+"    keyword wholeright $+F brightgreen/16\n"
+"    keyword wholeright $+G brightgreen/16\n"
+"    keyword wholeright $+H brightgreen/16\n"
+"    keyword wholeright $+I brightgreen/16\n"
+"    keyword wholeright $+J brightgreen/16\n"
+"    keyword wholeright $+K brightgreen/16\n"
+"    keyword wholeright $+L brightgreen/16\n"
+"    keyword wholeright $+M brightgreen/16\n"
+"    keyword wholeright $+N brightgreen/16\n"
+"    keyword wholeright $+O brightgreen/16\n"
+"    keyword wholeright $+P brightgreen/16\n"
+"    keyword wholeright $+Q brightgreen/16\n"
+"    keyword wholeright $+R brightgreen/16\n"
+"    keyword wholeright $+S brightgreen/16\n"
+"    keyword wholeright $+T brightgreen/16\n"
+"    keyword wholeright $+U brightgreen/16\n"
+"    keyword wholeright $+V brightgreen/16\n"
+"    keyword wholeright $+W brightgreen/16\n"
+"    keyword wholeright $+X brightgreen/16\n"
+"    keyword wholeright $+Y brightgreen/16\n"
+"    keyword wholeright $+Z brightgreen/16\n"
+"\n"
+"    keyword wholeright $+a brightgreen/16\n"
+"    keyword wholeright $+b brightgreen/16\n"
+"    keyword wholeright $+c brightgreen/16\n"
+"    keyword wholeright $+d brightgreen/16\n"
+"    keyword wholeright $+e brightgreen/16\n"
+"    keyword wholeright $+f brightgreen/16\n"
+"    keyword wholeright $+g brightgreen/16\n"
+"    keyword wholeright $+h brightgreen/16\n"
+"    keyword wholeright $+i brightgreen/16\n"
+"    keyword wholeright $+j brightgreen/16\n"
+"    keyword wholeright $+k brightgreen/16\n"
+"    keyword wholeright $+l brightgreen/16\n"
+"    keyword wholeright $+m brightgreen/16\n"
+"    keyword wholeright $+n brightgreen/16\n"
+"    keyword wholeright $+o brightgreen/16\n"
+"    keyword wholeright $+p brightgreen/16\n"
+"    keyword wholeright $+q brightgreen/16\n"
+"    keyword wholeright $+r brightgreen/16\n"
+"    keyword wholeright $+s brightgreen/16\n"
+"    keyword wholeright $+t brightgreen/16\n"
+"    keyword wholeright $+u brightgreen/16\n"
+"    keyword wholeright $+v brightgreen/16\n"
+"    keyword wholeright $+w brightgreen/16\n"
+"    keyword wholeright $+x brightgreen/16\n"
+"    keyword wholeright $+y brightgreen/16\n"
+"    keyword wholeright $+z brightgreen/16\n"
+"\n"
+"    keyword wholeright $+0 brightgreen/16\n"
+"    keyword wholeright $+1 brightgreen/16\n"
+"    keyword wholeright $+2 brightgreen/16\n"
+"    keyword wholeright $+3 brightgreen/16\n"
+"    keyword wholeright $+4 brightgreen/16\n"
+"    keyword wholeright $+5 brightgreen/16\n"
+"    keyword wholeright $+6 brightgreen/16\n"
+"    keyword wholeright $+7 brightgreen/16\n"
+"    keyword wholeright $+8 brightgreen/16\n"
+"    keyword wholeright $+9 brightgreen/16\n"
+"\n"
+"    keyword $ brightgreen/16\n"
+"\n"
+"    keyword whole arch cyan/14\n"
+"    keyword whole ash cyan/14\n"
+"    keyword whole awk cyan/14\n"
+"    keyword whole basename cyan/14\n"
+"    keyword whole bash cyan/14\n"
+"    keyword whole basnemae cyan/14\n"
+"    keyword whole bg_backup cyan/14\n"
+"    keyword whole bg_restore cyan/14\n"
+"    keyword whole bsh cyan/14\n"
+"    keyword whole cat cyan/14\n"
+"    keyword whole chgrp cyan/14\n"
+"    keyword whole chmod cyan/14\n"
+"    keyword whole chown cyan/14\n"
+"    keyword whole cp cyan/14\n"
+"    keyword whole cpio cyan/14\n"
+"    keyword whole csh cyan/14\n"
+"    keyword whole date cyan/14\n"
+"    keyword whole dd cyan/14\n"
+"    keyword whole df cyan/14\n"
+"    keyword whole dmesg cyan/14\n"
+"    keyword whole dnsdomainname cyan/14\n"
+"    keyword whole doexec cyan/14\n"
+"    keyword whole domainname cyan/14\n"
+"    keyword whole echo cyan/14\n"
+"    keyword whole ed cyan/14\n"
+"    keyword whole egrep cyan/14\n"
+"    keyword whole ex cyan/14\n"
+"    keyword whole false cyan/14\n"
+"    keyword whole fgrep cyan/14\n"
+"    keyword whole fsconf cyan/14\n"
+"    keyword whole gawk cyan/14\n"
+"    keyword whole grep cyan/14\n"
+"    keyword whole gunzip cyan/14\n"
+"    keyword whole gzip cyan/14\n"
+"    keyword whole hostname cyan/14\n"
+"    keyword whole igawk cyan/14\n"
+"    keyword whole ipcalc cyan/14\n"
+"    keyword whole kill cyan/14\n"
+"    keyword whole ksh cyan/14\n"
+"    keyword whole linuxconf cyan/14\n"
+"    keyword whole ln cyan/14\n"
+"    keyword whole login cyan/14\n"
+"    keyword whole lpdconf cyan/14\n"
+"    keyword whole ls cyan/14\n"
+"    keyword whole mail cyan/14\n"
+"    keyword whole mkdir cyan/14\n"
+"    keyword whole mknod cyan/14\n"
+"    keyword whole mktemp cyan/14\n"
+"    keyword whole more cyan/14\n"
+"    keyword whole mount cyan/14\n"
+"    keyword whole mt cyan/14\n"
+"    keyword whole mv cyan/14\n"
+"    keyword whole netconf cyan/14\n"
+"    keyword whole netstat cyan/14\n"
+"    keyword whole nice cyan/14\n"
+"    keyword whole nisdomainname cyan/14\n"
+"    keyword whole ping cyan/14\n"
+"    keyword whole ps cyan/14\n"
+"    keyword whole pwd cyan/14\n"
+"    keyword whole red cyan/14\n"
+"    keyword whole remadmin cyan/14\n"
+"    keyword whole rm cyan/14\n"
+"    keyword whole rmdir cyan/14\n"
+"    keyword whole rpm cyan/14\n"
+"    keyword whole sed cyan/14\n"
+"    keyword whole setserial cyan/14\n"
+"    keyword whole sh cyan/14\n"
+"    keyword whole sleep cyan/14\n"
+"    keyword whole sort cyan/14\n"
+"    keyword whole stty cyan/14\n"
+"    keyword whole su cyan/14\n"
+"    keyword whole sync cyan/14\n"
+"    keyword whole taper cyan/14\n"
+"    keyword whole tar cyan/14\n"
+"    keyword whole tcsh cyan/14\n"
+"    keyword whole touch cyan/14\n"
+"    keyword whole true cyan/14\n"
+"    keyword whole umount cyan/14\n"
+"    keyword whole uname cyan/14\n"
+"    keyword whole userconf cyan/14\n"
+"    keyword whole usleep cyan/14\n"
+"    keyword whole vi cyan/14\n"
+"    keyword whole view cyan/14\n"
+"    keyword whole vim cyan/14\n"
+"    keyword whole xconf cyan/14\n"
+"    keyword whole ypdomainname cyan/14\n"
+"    keyword whole zcat cyan/14\n"
+"    keyword whole zsh cyan/14\n"
+"\n"
+"###############################################################################\n"
+"file ..\\*\\\\.(pl|PL])$ Perl\\sProgram\\s(no\\srules\\syet) ^#!/.\\*/perl$\n"
+"context default\n"
+"    keyword whole linestart #!/\\[abcdefghijklmnopqrstuvwxyz\\]/\\[abcdefghijklmnopqrstuvwxyz\\]/\\[abcdefghijklmnopqrstuvwxyz\\]/\\[abcdefghijklmnopqrstuvwxyz\\]/bin/perl brightcyan/17 black/0\n"
+"    keyword whole linestart #!/\\[abcdefghijklmnopqrstuvwxyz\\]/\\[abcdefghijklmnopqrstuvwxyz\\]/\\[abcdefghijklmnopqrstuvwxyz\\]/bin/perl brightcyan/17 black/0\n"
+"    keyword whole linestart #!/\\[abcdefghijklmnopqrstuvwxyz\\]/\\[abcdefghijklmnopqrstuvwxyz\\]/bin/perl brightcyan/17 black/0\n"
+"    keyword whole linestart #!/\\[abcdefghijklmnopqrstuvwxyz\\]/bin/perl brightcyan/17 black/0\n"
+"    keyword whole linestart #!/bin/perl brightcyan/17 black/0\n"
+"\n"
+"\n"
+"###############################################################################\n"
+"file ..\\*\\\\.(py|PY])$ Python\\sProgram ^#!/.\\*/python$\n"
+"context default\n"
+"    keyword whole : brightred/18\n"
+"    keyword whole self brightred/18\n"
+"    keyword whole access yellow/24\n"
+"    keyword whole and yellow/24\n"
+"    keyword whole break yellow/24\n"
+"    keyword whole class yellow/24\n"
+"    keyword whole continue yellow/24\n"
+"    keyword whole def yellow/24\n"
+"    keyword whole del yellow/24\n"
+"    keyword whole elif yellow/24\n"
+"    keyword whole else yellow/24\n"
+"    keyword whole except yellow/24\n"
+"    keyword whole exec yellow/24\n"
+"    keyword whole finally yellow/24\n"
+"    keyword whole for yellow/24\n"
+"    keyword whole from yellow/24\n"
+"    keyword whole global yellow/24\n"
+"    keyword whole if yellow/24\n"
+"    keyword whole import yellow/24\n"
+"    keyword whole in yellow/24\n"
+"    keyword whole is yellow/24\n"
+"    keyword whole lambda yellow/24\n"
+"    keyword whole not yellow/24\n"
+"    keyword whole or yellow/24\n"
+"    keyword whole pass yellow/24\n"
+"    keyword whole print yellow/24\n"
+"    keyword whole raise yellow/24\n"
+"    keyword whole return yellow/24\n"
+"    keyword whole try yellow/24\n"
+"    keyword whole while yellow/24\n"
+"\n"
+"    keyword whole abs brightcyan/17\n"
+"    keyword whole apply brightcyan/17\n"
+"    keyword whole callable brightcyan/17\n"
+"    keyword whole chr brightcyan/17\n"
+"    keyword whole cmp brightcyan/17\n"
+"    keyword whole coerce brightcyan/17\n"
+"    keyword whole compile brightcyan/17\n"
+"    keyword whole delattr brightcyan/17\n"
+"    keyword whole dir brightcyan/17\n"
+"    keyword whole divmod brightcyan/17\n"
+"    keyword whole eval brightcyan/17\n"
+"    keyword whole exec brightcyan/17\n"
+"    keyword whole execfile brightcyan/17\n"
+"    keyword whole filter brightcyan/17\n"
+"    keyword whole float brightcyan/17\n"
+"    keyword whole getattr brightcyan/17\n"
+"    keyword whole globals brightcyan/17\n"
+"    keyword whole hasattr brightcyan/17\n"
+"    keyword whole hash brightcyan/17\n"
+"    keyword whole hex brightcyan/17\n"
+"    keyword whole id brightcyan/17\n"
+"    keyword whole input brightcyan/17\n"
+"    keyword whole int brightcyan/17\n"
+"    keyword whole len brightcyan/17\n"
+"    keyword whole locals brightcyan/17\n"
+"    keyword whole long brightcyan/17\n"
+"    keyword whole map brightcyan/17\n"
+"    keyword whole max brightcyan/17\n"
+"    keyword whole min brightcyan/17\n"
+"    keyword whole oct brightcyan/17\n"
+"    keyword whole open brightcyan/17\n"
+"    keyword whole ord brightcyan/17\n"
+"    keyword whole pow brightcyan/17\n"
+"    keyword whole range brightcyan/17\n"
+"    keyword whole raw_input brightcyan/17\n"
+"    keyword whole reduce brightcyan/17\n"
+"    keyword whole reload brightcyan/17\n"
+"    keyword whole repr brightcyan/17\n"
+"    keyword whole round brightcyan/17\n"
+"    keyword whole setattr brightcyan/17\n"
+"    keyword whole str brightcyan/17\n"
+"    keyword whole tuple brightcyan/17\n"
+"    keyword whole type brightcyan/17\n"
+"    keyword whole vars brightcyan/17\n"
+"    keyword whole xrange brightcyan/17\n"
+"\n"
+"    keyword whole atof magenta/23\n"
+"    keyword whole atoi magenta/23\n"
+"    keyword whole atol magenta/23\n"
+"    keyword whole expandtabs magenta/23\n"
+"    keyword whole find magenta/23\n"
+"    keyword whole rfind magenta/23\n"
+"    keyword whole index magenta/23\n"
+"    keyword whole rindex magenta/23\n"
+"    keyword whole count magenta/23\n"
+"    keyword whole split magenta/23\n"
+"    keyword whole splitfields magenta/23\n"
+"    keyword whole join magenta/23\n"
+"    keyword whole joinfields magenta/23\n"
+"    keyword whole strip magenta/23\n"
+"    keyword whole swapcase magenta/23\n"
+"    keyword whole upper magenta/23\n"
+"    keyword whole lower magenta/23\n"
+"    keyword whole ljust magenta/23\n"
+"    keyword whole rjust magenta/23\n"
+"    keyword whole center magenta/23\n"
+"    keyword whole zfill magenta/23\n"
+"\n"
+"    keyword whole __init__ lightgray/13\n"
+"    keyword whole __del__ lightgray/13\n"
+"    keyword whole __repr__ lightgray/13\n"
+"    keyword whole __str__ lightgray/13\n"
+"    keyword whole __cmp__ lightgray/13\n"
+"    keyword whole __hash__ lightgray/13\n"
+"    keyword whole __call__ lightgray/13\n"
+"    keyword whole __getattr__ lightgray/13\n"
+"    keyword whole __setattr__ lightgray/13\n"
+"    keyword whole __delattr__ lightgray/13\n"
+"    keyword whole __len__ lightgray/13\n"
+"    keyword whole __getitem__ lightgray/13\n"
+"    keyword whole __setitem__ lightgray/13\n"
+"    keyword whole __delitem__ lightgray/13\n"
+"    keyword whole __getslice__ lightgray/13\n"
+"    keyword whole __setslice__ lightgray/13\n"
+"    keyword whole __delslice__ lightgray/13\n"
+"    keyword whole __add__ lightgray/13\n"
+"    keyword whole __sub__ lightgray/13\n"
+"    keyword whole __mul__ lightgray/13\n"
+"    keyword whole __div__ lightgray/13\n"
+"    keyword whole __mod__ lightgray/13\n"
+"    keyword whole __divmod__ lightgray/13\n"
+"    keyword whole __pow__ lightgray/13\n"
+"    keyword whole __lshift__ lightgray/13\n"
+"    keyword whole __rshift__ lightgray/13\n"
+"    keyword whole __and__ lightgray/13\n"
+"    keyword whole __xor__ lightgray/13\n"
+"    keyword whole __or__ lightgray/13\n"
+"    keyword whole __neg__ lightgray/13\n"
+"    keyword whole __pos__ lightgray/13\n"
+"    keyword whole __abs__ lightgray/13\n"
+"    keyword whole __invert__ lightgray/13\n"
+"    keyword whole __nonzero__ lightgray/13\n"
+"    keyword whole __coerce__ lightgray/13\n"
+"    keyword whole __int__ lightgray/13\n"
+"    keyword whole __long__ lightgray/13\n"
+"    keyword whole __float__ lightgray/13\n"
+"    keyword whole __oct__ lightgray/13\n"
+"    keyword whole __hex__ lightgray/13\n"
+"\n"
+"    keyword whole __init__ lightgray/13\n"
+"    keyword whole __del__ lightgray/13\n"
+"    keyword whole __repr__ lightgray/13\n"
+"    keyword whole __str__ lightgray/13\n"
+"    keyword whole __cmp__ lightgray/13\n"
+"    keyword whole __hash__ lightgray/13\n"
+"    keyword whole __call__ lightgray/13\n"
+"    keyword whole __getattr__ lightgray/13\n"
+"    keyword whole __setattr__ lightgray/13\n"
+"    keyword whole __delattr__ lightgray/13\n"
+"    keyword whole __len__ lightgray/13\n"
+"    keyword whole __getitem__ lightgray/13\n"
+"    keyword whole __setitem__ lightgray/13\n"
+"    keyword whole __delitem__ lightgray/13\n"
+"    keyword whole __getslice__ lightgray/13\n"
+"    keyword whole __setslice__ lightgray/13\n"
+"    keyword whole __delslice__ lightgray/13\n"
+"    keyword whole __add__ lightgray/13\n"
+"    keyword whole __sub__ lightgray/13\n"
+"    keyword whole __mul__ lightgray/13\n"
+"    keyword whole __div__ lightgray/13\n"
+"    keyword whole __mod__ lightgray/13\n"
+"    keyword whole __divmod__ lightgray/13\n"
+"    keyword whole __pow__ lightgray/13\n"
+"    keyword whole __lshift__ lightgray/13\n"
+"    keyword whole __rshift__ lightgray/13\n"
+"    keyword whole __and__ lightgray/13\n"
+"    keyword whole __xor__ lightgray/13\n"
+"    keyword whole __or__ lightgray/13\n"
+"    keyword whole __neg__ lightgray/13\n"
+"    keyword whole __pos__ lightgray/13\n"
+"    keyword whole __abs__ lightgray/13\n"
+"    keyword whole __invert__ lightgray/13\n"
+"    keyword whole __nonzero__ lightgray/13\n"
+"    keyword whole __coerce__ lightgray/13\n"
+"    keyword whole __int__ lightgray/13\n"
+"    keyword whole __long__ lightgray/13\n"
+"    keyword whole __float__ lightgray/13\n"
+"    keyword whole __oct__ lightgray/13\n"
+"    keyword whole __hex__ lightgray/13\n"
+"\n"
+"    keyword whole __radd__ lightgray/13\n"
+"    keyword whole __rsub__ lightgray/13\n"
+"    keyword whole __rmul__ lightgray/13\n"
+"    keyword whole __rdiv__ lightgray/13\n"
+"    keyword whole __rmod__ lightgray/13\n"
+"    keyword whole __rdivmod__ lightgray/13\n"
+"    keyword whole __rpow__ lightgray/13\n"
+"    keyword whole __rlshift__ lightgray/13\n"
+"    keyword whole __rrshift__ lightgray/13\n"
+"    keyword whole __rand__ lightgray/13\n"
+"    keyword whole __rxor__ lightgray/13\n"
+"    keyword whole __ror__ lightgray/13\n"
+"\n"
+"    keyword whole __*__ brightred/18\n"
+"\n"
+"context \"\"\" \"\"\" brown/22\n"
+"context # \\n brown/22\n"
+"context \" \" green/6\n"
+"    keyword \\\\\" brightgreen/16\n"
+"    keyword %% brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]e brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]E brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]f brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]g brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]G brightgreen/16\n"
+"    keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]d brightgreen/16\n"
+"    keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]i brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]o brightgreen/16\n"
+"    keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]u brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]x brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]X brightgreen/16\n"
+"    keyword %\\[hl\\]n brightgreen/16\n"
+"    keyword %\\[.\\]\\[0123456789\\]s brightgreen/16\n"
+"    keyword %[*] brightgreen/16\n"
+"    keyword %c brightgreen/16\n"
+"    keyword \\\\\\\\ brightgreen/16\n"
+"    keyword \\\\' brightgreen/16\n"
+"    keyword \\\\a brightgreen/16\n"
+"    keyword \\\\b brightgreen/16\n"
+"    keyword \\\\t brightgreen/16\n"
+"    keyword \\\\n brightgreen/16\n"
+"    keyword \\\\v brightgreen/16\n"
+"    keyword \\\\f brightgreen/16\n"
+"    keyword \\\\r brightgreen/16\n"
+"    keyword \\\\0 brightgreen/16\n"
+"\n"
+"context ' ' green/6\n"
+"    keyword \\\\\" brightgreen/16\n"
+"    keyword %% brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]e brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]E brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]f brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]g brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]G brightgreen/16\n"
+"    keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]d brightgreen/16\n"
+"    keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]i brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]o brightgreen/16\n"
+"    keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]u brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]x brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]X brightgreen/16\n"
+"    keyword %\\[hl\\]n brightgreen/16\n"
+"    keyword %\\[.\\]\\[0123456789\\]s brightgreen/16\n"
+"    keyword %[*] brightgreen/16\n"
+"    keyword %c brightgreen/16\n"
+"    keyword \\\\\\\\ brightgreen/16\n"
+"    keyword \\\\' brightgreen/16\n"
+"    keyword \\\\a brightgreen/16\n"
+"    keyword \\\\b brightgreen/16\n"
+"    keyword \\\\t brightgreen/16\n"
+"    keyword \\\\n brightgreen/16\n"
+"    keyword \\\\v brightgreen/16\n"
+"    keyword \\\\f brightgreen/16\n"
+"    keyword \\\\r brightgreen/16\n"
+"    keyword \\\\0 brightgreen/16\n"
+"\n"
+"###############################################################################\n"
+"file ..\\*\\\\.(man|[0-9n])$ NROFF\\sSource\n"
+"\n"
+"context default\n"
+"    keyword \\\\fP brightgreen/6\n"
+"    keyword \\\\fR brightgreen/6\n"
+"    keyword \\\\fB brightgreen/6\n"
+"    keyword \\\\fI brightgreen/6\n"
+"    keyword linestart .AS cyan/5\n"
+"    keyword linestart .Ar cyan/5\n"
+"    keyword linestart .At cyan/5\n"
+"    keyword linestart .BE cyan/5\n"
+"    keyword linestart .BH cyan/5\n"
+"    keyword linestart .BI cyan/5\n"
+"    keyword linestart .BR cyan/5\n"
+"    keyword linestart .BS cyan/5\n"
+"    keyword linestart .Bd cyan/5\n"
+"    keyword linestart .Bk cyan/5\n"
+"    keyword linestart .Bl cyan/5\n"
+"    keyword linestart .Bu cyan/5\n"
+"    keyword linestart .Bx cyan/5\n"
+"    keyword linestart .CE cyan/5\n"
+"    keyword linestart .CM cyan/5\n"
+"    keyword linestart .CS cyan/5\n"
+"    keyword linestart .CT cyan/5\n"
+"    keyword linestart .CW cyan/5\n"
+"    keyword linestart .Cm cyan/5\n"
+"    keyword linestart .Co cyan/5\n"
+"    keyword linestart .DA cyan/5\n"
+"    keyword linestart .DE cyan/5\n"
+"    keyword linestart .DS cyan/5\n"
+"    keyword linestart .DT cyan/5\n"
+"    keyword linestart .Dd cyan/5\n"
+"    keyword linestart .De cyan/5\n"
+"    keyword linestart .Dl cyan/5\n"
+"    keyword linestart .Dq cyan/5\n"
+"    keyword linestart .Ds cyan/5\n"
+"    keyword linestart .Dt cyan/5\n"
+"    keyword linestart .Dv cyan/5\n"
+"    keyword linestart .EE cyan/5\n"
+"    keyword linestart .EN cyan/5\n"
+"    keyword linestart .EQ cyan/5\n"
+"    keyword linestart .EX cyan/5\n"
+"    keyword linestart .Ed cyan/5\n"
+"    keyword linestart .Ee cyan/5\n"
+"    keyword linestart .Ek cyan/5\n"
+"    keyword linestart .El cyan/5\n"
+"    keyword linestart .Em cyan/5\n"
+"    keyword linestart .En cyan/5\n"
+"    keyword linestart .Ev cyan/5\n"
+"    keyword linestart .Ex cyan/5\n"
+"    keyword linestart .FI cyan/5\n"
+"    keyword linestart .FL cyan/5\n"
+"    keyword linestart .FN cyan/5\n"
+"    keyword linestart .FT cyan/5\n"
+"    keyword linestart .Fi cyan/5\n"
+"    keyword linestart .Fl cyan/5\n"
+"    keyword linestart .Fn cyan/5\n"
+"    keyword linestart .HP cyan/5\n"
+"    keyword linestart .HS cyan/5\n"
+"    keyword linestart .Hh cyan/5\n"
+"    keyword linestart .Hi cyan/5\n"
+"    keyword linestart .IB cyan/5\n"
+"    keyword linestart .IP cyan/5\n"
+"    keyword linestart .IR cyan/5\n"
+"    keyword linestart .IX cyan/5\n"
+"    keyword linestart .Ic cyan/5\n"
+"    keyword linestart .Id cyan/5\n"
+"    keyword linestart .Ip cyan/5\n"
+"    keyword linestart .It cyan/5\n"
+"    keyword linestart .LI cyan/5\n"
+"    keyword linestart .LO cyan/5\n"
+"    keyword linestart .LP cyan/5\n"
+"    keyword linestart .LR cyan/5\n"
+"    keyword linestart .Li cyan/5\n"
+"    keyword linestart .MF cyan/5\n"
+"    keyword linestart .ML cyan/5\n"
+"    keyword linestart .MU cyan/5\n"
+"    keyword linestart .MV cyan/5\n"
+"    keyword linestart .N cyan/5\n"
+"    keyword linestart .NF cyan/5\n"
+"    keyword linestart .Nd cyan/5\n"
+"    keyword linestart .Nm cyan/5\n"
+"    keyword linestart .No cyan/5\n"
+"    keyword linestart .OP cyan/5\n"
+"    keyword linestart .Oc cyan/5\n"
+"    keyword linestart .Oo cyan/5\n"
+"    keyword linestart .Op cyan/5\n"
+"    keyword linestart .Os cyan/5\n"
+"    keyword linestart .PD cyan/5\n"
+"    keyword linestart .PN cyan/5\n"
+"    keyword linestart .PP cyan/5\n"
+"    keyword linestart .PU cyan/5\n"
+"    keyword linestart .Pa cyan/5\n"
+"    keyword linestart .Pf cyan/5\n"
+"    keyword linestart .Pp cyan/5\n"
+"    keyword linestart .Pq cyan/5\n"
+"    keyword linestart .Pr cyan/5\n"
+"    keyword linestart .Ps cyan/5\n"
+"    keyword linestart .Ql cyan/5\n"
+"    keyword linestart .RB cyan/5\n"
+"    keyword linestart .RE cyan/5\n"
+"    keyword linestart .RI cyan/5\n"
+"    keyword linestart .RS cyan/5\n"
+"    keyword linestart .RT cyan/5\n"
+"    keyword linestart .Re cyan/5\n"
+"    keyword linestart .Rs cyan/5\n"
+"    keyword linestart .SB cyan/5\n"
+"    keyword linestart .SH cyan/5\n"
+"    keyword linestart .SM cyan/5\n"
+"    keyword linestart .SP cyan/5\n"
+"    keyword linestart .SS cyan/5\n"
+"    keyword linestart .Sa cyan/5\n"
+"    keyword linestart .Sh cyan/5\n"
+"    keyword linestart .Sm cyan/5\n"
+"    keyword linestart .Sp cyan/5\n"
+"    keyword linestart .Sq cyan/5\n"
+"    keyword linestart .Ss cyan/5\n"
+"    keyword linestart .St cyan/5\n"
+"    keyword linestart .Sx cyan/5\n"
+"    keyword linestart .Sy cyan/5\n"
+"    keyword linestart .TE cyan/5\n"
+"    keyword linestart .TH cyan/5\n"
+"    keyword linestart .TP cyan/5\n"
+"    keyword linestart .TQ cyan/5\n"
+"    keyword linestart .TS cyan/5\n"
+"    keyword linestart .Tn cyan/5\n"
+"    keyword linestart .Tp cyan/5\n"
+"    keyword linestart .UC cyan/5\n"
+"    keyword linestart .Uh cyan/5\n"
+"    keyword linestart .Ux cyan/5\n"
+"    keyword linestart .VE cyan/5\n"
+"    keyword linestart .VS cyan/5\n"
+"    keyword linestart .Va cyan/5\n"
+"    keyword linestart .Vb cyan/5\n"
+"    keyword linestart .Ve cyan/5\n"
+"    keyword linestart .Xc cyan/5\n"
+"    keyword linestart .Xe cyan/5\n"
+"    keyword linestart .Xr cyan/5\n"
+"    keyword linestart .YN cyan/5\n"
+"    keyword linestart .ad cyan/5\n"
+"    keyword linestart .am cyan/5\n"
+"    keyword linestart .bd cyan/5\n"
+"    keyword linestart .bp cyan/5\n"
+"    keyword linestart .br cyan/5\n"
+"    keyword linestart .ce cyan/5\n"
+"    keyword linestart .cs cyan/5\n"
+"    keyword linestart .de cyan/5\n"
+"    keyword linestart .ds cyan/5\n"
+"    keyword linestart .ec cyan/5\n"
+"    keyword linestart .eh cyan/5\n"
+"    keyword linestart .el cyan/5\n"
+"    keyword linestart .eo cyan/5\n"
+"    keyword linestart .ev cyan/5\n"
+"    keyword linestart .fc cyan/5\n"
+"    keyword linestart .fi cyan/5\n"
+"    keyword linestart .ft cyan/5\n"
+"    keyword linestart .hy cyan/5\n"
+"    keyword linestart .iX cyan/5\n"
+"    keyword linestart .ie cyan/5\n"
+"    keyword linestart .if cyan/5\n"
+"    keyword linestart .ig cyan/5\n"
+"    keyword linestart .in cyan/5\n"
+"    keyword linestart .ll cyan/5\n"
+"    keyword linestart .lp cyan/5\n"
+"    keyword linestart .ls cyan/5\n"
+"    keyword linestart .mk cyan/5\n"
+"    keyword linestart .na cyan/5\n"
+"    keyword linestart .ne cyan/5\n"
+"    keyword linestart .nf cyan/5\n"
+"    keyword linestart .nh cyan/5\n"
+"    keyword linestart .nr cyan/5\n"
+"    keyword linestart .ns cyan/5\n"
+"    keyword linestart .oh cyan/5\n"
+"    keyword linestart .ps cyan/5\n"
+"    keyword linestart .re cyan/5\n"
+"    keyword linestart .rm cyan/5\n"
+"    keyword linestart .rn cyan/5\n"
+"    keyword linestart .rr cyan/5\n"
+"    keyword linestart .so cyan/5\n"
+"    keyword linestart .sp cyan/5\n"
+"    keyword linestart .ss cyan/5\n"
+"    keyword linestart .ta cyan/5\n"
+"    keyword linestart .ti cyan/5\n"
+"    keyword linestart .tm cyan/5\n"
+"    keyword linestart .tr cyan/5\n"
+"    keyword linestart .ul cyan/5\n"
+"    keyword linestart .vs cyan/5\n"
+"    keyword linestart .zZ cyan/5\n"
+"    keyword linestart .e cyan/5\n"
+"    keyword linestart .d cyan/5\n"
+"    keyword linestart .h cyan/5\n"
+"    keyword linestart .B cyan/5\n"
+"    keyword linestart .I cyan/5\n"
+"    keyword linestart .R cyan/5\n"
+"    keyword linestart .P cyan/5\n"
+"    keyword linestart .L cyan/5\n"
+"    keyword linestart .V cyan/5\n"
+"    keyword linestart .F cyan/5\n"
+"    keyword linestart .T cyan/5\n"
+"    keyword linestart .X cyan/5\n"
+"    keyword linestart .Y cyan/5\n"
+"    keyword linestart .b cyan/5\n"
+"    keyword linestart .l cyan/5\n"
+"    keyword linestart .i cyan/5\n"
+"\n"
+"context exclusive linestart .SH \\n brightred/18\n"
+"context exclusive linestart .TH \\n brightred/18\n"
+"context exclusive linestart .B \\n magenta/23\n"
+"context exclusive linestart .I \\n yellow/24\n"
+"context exclusive linestart .nf linestart .fi green/15\n"
+"\n"
+"# font changes should end in a \\fP\n"
+"context exclusive \\\\fB \\\\fP magenta/23\n"
+"context exclusive \\\\fI \\\\fP yellow/24\n"
+"context linestart .\\\\\" \\n brown/22\n"
+"\n"
+"###############################################################################\n"
+"# Assumes you've set a dark background, e.g. navy blue.\n"
+"file ..\\*\\\\.(htm|html|HTM|HTML)$ HTML\\sFile\n"
+"\n"
+"context default white/25\n"
+"    keyword whole &*; brightgreen/16\n"
+"context <!-- --> white/26\n"
+"context < > brightcyan/17\n"
+"    keyword \"http:*\" magenta/22\n"
+"    keyword \"ftp:*\" magenta/22\n"
+"    keyword \"mailto:*\" magenta/22\n"
+"    keyword \"gopher:*\" magenta/22\n"
+"    keyword \"telnet:*\" magenta/22\n"
+"    keyword \"file:*\" magenta/22\n"
+"    keyword \"*.gif\" brightred/19\n"
+"    keyword \"*.jpg\" brightred/19\n"
+"    keyword \"*.png\" brightred/19\n"
+"    keyword \"*\" cyan/5\n"
+"\n"
+"###############################################################################\n"
+"# Pascal (BP7 IDE alike)\n"
+"file ..\\*\\\\.(pp|PP|pas|PAS|)$ Pascal Program\n"
+"context default yellow/24\n"
+"    keyword whole absolute white/25\n"
+"    keyword whole and white/25\n"
+"    keyword whole array white/25\n"
+"    keyword whole as white/25\n"
+"    keyword whole asm white/25\n"
+"    keyword whole assembler white/25\n"
+"    keyword whole begin white/25\n"
+"    keyword whole break white/25\n"
+"    keyword whole case white/25\n"
+"    keyword whole class white/25\n"
+"    keyword whole const white/25\n"
+"    keyword whole continue white/25\n"
+"    keyword whole constructor white/25\n"
+"    keyword whole destructor white/25\n"
+"    keyword whole dispose white/25\n"
+"    keyword whole div white/25\n"
+"    keyword whole do white/25\n"
+"    keyword whole downto white/25\n"
+"    keyword whole else white/25\n"
+"    keyword whole end white/25\n"
+"    keyword whole except white/25\n"
+"    keyword whole exit white/25\n"
+"    keyword whole export white/25\n"
+"    keyword whole exports white/25\n"
+"    keyword whole external white/25\n"
+"    keyword whole fail white/25\n"
+"    keyword whole far white/25\n"
+"    keyword whole false white/25\n"
+"    keyword whole file white/25\n"
+"    keyword whole finally white/25\n"
+"    keyword whole for white/25\n"
+"    keyword whole forward white/25\n"
+"    keyword whole function white/25\n"
+"    keyword whole goto white/25\n"
+"    keyword whole if white/25\n"
+"    keyword whole implementation white/25\n"
+"    keyword whole in white/25\n"
+"    keyword whole inherited white/25\n"
+"    keyword whole initialization white/25\n"
+"    keyword whole inline white/25\n"
+"    keyword whole interface white/25\n"
+"    keyword whole interrupt white/25\n"
+"    keyword whole is white/25\n"
+"    keyword whole label white/25\n"
+"    keyword whole library white/25\n"
+"    keyword whole mod white/25\n"
+"    keyword whole near white/25\n"
+"    keyword whole new white/25\n"
+"    keyword whole nil white/25\n"
+"    keyword whole not white/25\n"
+"    keyword whole object white/25\n"
+"    keyword whole of white/25\n"
+"    keyword whole on white/25\n"
+"    keyword whole operator white/25\n"
+"    keyword whole or white/25\n"
+"    keyword whole otherwise white/25\n"
+"    keyword whole packed white/25\n"
+"    keyword whole procedure white/25\n"
+"    keyword whole program white/25\n"
+"    keyword whole property white/25\n"
+"    keyword whole raise white/25\n"
+"    keyword whole record white/25\n"
+"    keyword whole repeat white/25\n"
+"    keyword whole self white/25\n"
+"    keyword whole set white/25\n"
+"    keyword whole shl white/25\n"
+"    keyword whole shr white/25\n"
+"    keyword whole string white/25\n"
+"    keyword whole then white/25\n"
+"    keyword whole to white/25\n"
+"    keyword whole true white/25\n"
+"    keyword whole try white/25\n"
+"    keyword whole type white/25\n"
+"    keyword whole unit white/25\n"
+"    keyword whole until white/25\n"
+"    keyword whole uses white/25\n"
+"    keyword whole var white/25\n"
+"    keyword whole virtual white/25\n"
+"    keyword whole while white/25\n"
+"    keyword whole with white/25\n"
+"    keyword whole xor white/25\n"
+"    keyword whole .. white/25\n"
+"    \n"
+"    keyword > cyan/5\n"
+"    keyword < cyan/5\n"
+"    keyword \\+ cyan/5\n"
+"    keyword - cyan/5\n"
+"    keyword / cyan/5\n"
+"    keyword % cyan/5\n"
+"    keyword = cyan/5\n"
+"    keyword [ cyan/5\n"
+"    keyword ] cyan/5\n"
+"    keyword ( cyan/5\n"
+"    keyword ) cyan/5\n"
+"    keyword , cyan/5\n"
+"    keyword . cyan/5\n"
+"    keyword : cyan/5\n"
+"    keyword ; cyan/5\n"
+"    keyword {$*} brightred/19\n"
+"\n"
+"context ' ' brightcyan/22\n"
+"context // \\n brown/22\n"
+"context (\\* \\*) brown/22\n"
+"# context {$ } brightred/19\n"
+"#    keyword \\[ABCDEFGHIJKLMNOPQRSTUVWXYZ\\]\\[-\\+\\] brightgreen/16\n"
+"#    keyword $* brightgreen/16\n"
+"context { } lightgray/22\n"
+"\n"
+"\n"
+"###############################################################################\n"
+"file ..\\*\\\\.tex$ LaTeX\\s2.09\\sDocument\n"
+"context default\n"
+"wholechars left \\\\\n"
+"wholechars right abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\n"
+"\n"
+"# type style\n"
+"    keyword whole \\\\tiny yellow/24\n"
+"    keyword whole \\\\scriptsize yellow/24\n"
+"    keyword whole \\\\footnotesize yellow/24\n"
+"    keyword whole \\\\small yellow/24\n"
+"    keyword whole \\\\normalsize yellow/24\n"
+"    keyword whole \\\\large yellow/24\n"
+"    keyword whole \\\\Large yellow/24\n"
+"    keyword whole \\\\LARGE yellow/24\n"
+"    keyword whole \\\\huge yellow/24\n"
+"    keyword whole \\\\Huge yellow/24\n"
+"\n"
+"# accents and symbols\n"
+"    keyword whole \\\\`{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\'{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\^{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\\"{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\~{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\={\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\.{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\u{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\v{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\H{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\t{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\c{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\d{\\[aeiouAEIOU\\]} yellow/24\n"
+"    keyword whole \\\\b{\\[aeiouAEIOU\\]} yellow/24\n"
+"\n"
+"    keyword whole \\\\dag yellow/24\n"
+"    keyword whole \\\\ddag yellow/24\n"
+"    keyword whole \\\\S yellow/24\n"
+"    keyword whole \\\\P yellow/24\n"
+"    keyword whole \\\\copyright yellow/24\n"
+"    keyword whole \\\\pounds yellow/24\n"
+"\n"
+"# sectioning and table of contents\n"
+"    keyword whole \\\\part[*]{*} brightred/19\n"
+"    keyword whole \\\\part{*} brightred/19\n"
+"    keyword whole \\\\part\\*{*} brightred/19\n"
+"    keyword whole \\\\chapter[*]{*} brightred/19\n"
+"    keyword whole \\\\chapter{*} brightred/19\n"
+"    keyword whole \\\\chapter\\*{*} brightred/19\n"
+"    keyword whole \\\\section[*]{*} brightred/19\n"
+"    keyword whole \\\\section{*} brightred/19\n"
+"    keyword whole \\\\section\\*{*} brightred/19\n"
+"    keyword whole \\\\subsection[*]{*} brightred/19\n"
+"    keyword whole \\\\subsection{*} brightred/19\n"
+"    keyword whole \\\\subsection\\*{*} brightred/19\n"
+"    keyword whole \\\\subsubsection[*]{*} brightred/19\n"
+"    keyword whole \\\\subsubsection{*} brightred/19\n"
+"    keyword whole \\\\subsubsection\\*{*} brightred/19\n"
+"    keyword whole \\\\paragraph[*]{*} brightred/19\n"
+"    keyword whole \\\\paragraph{*} brightred/19\n"
+"    keyword whole \\\\paragraph\\*{*} brightred/19\n"
+"    keyword whole \\\\subparagraph[*]{*} brightred/19\n"
+"    keyword whole \\\\subparagraph{*} brightred/19\n"
+"    keyword whole \\\\subparagraph\\*{*} brightred/19\n"
+"\n"
+"    keyword whole \\\\appendix brightred/19\n"
+"    keyword whole \\\\tableofcontents brightred/19\n"
+"\n"
+"# misc\n"
+"    keyword whole \\\\item[*] yellow/24\n"
+"    keyword whole \\\\item yellow/24\n"
+"    keyword whole \\\\\\\\ yellow/24\n"
+"    keyword \\\\\\s yellow/24 black/0\n"
+"    keyword %% yellow/24\n"
+"\n"
+"# docuement and page styles    \n"
+"    keyword whole \\\\documentstyle[*]{*} yellow/20\n"
+"    keyword whole \\\\documentstyle{*} yellow/20\n"
+"    keyword whole \\\\pagestyle{*} yellow/20\n"
+"\n"
+"# cross references\n"
+"    keyword whole \\\\label{*} yellow/24\n"
+"    keyword whole \\\\ref{*} yellow/24\n"
+"\n"
+"# bibliography and citations\n"
+"    keyword whole \\\\bibliography{*} yellow/24\n"
+"    keyword whole \\\\bibitem[*]{*} yellow/24\n"
+"    keyword whole \\\\bibitem{*} yellow/24\n"
+"    keyword whole \\\\cite[*]{*} yellow/24\n"
+"    keyword whole \\\\cite{*} yellow/24\n"
+"\n"
+"# splitting the input\n"
+"    keyword whole \\\\input{*} yellow/20\n"
+"    keyword whole \\\\include{*} yellow/20\n"
+"    keyword whole \\\\includeonly{*} yellow/20\n"
+"\n"
+"# line breaking\n"
+"    keyword whole \\\\linebreak[\\[01234\\]] yellow/24\n"
+"    keyword whole \\\\nolinebreak[\\[01234\\]] yellow/24\n"
+"    keyword whole \\\\linebreak yellow/24\n"
+"    keyword whole \\\\nolinebreak yellow/24\n"
+"    keyword whole \\\\[+] yellow/24\n"
+"    keyword whole \\\\- yellow/24\n"
+"    keyword whole \\\\sloppy yellow/24\n"
+"\n"
+"# page breaking\n"
+"    keyword whole \\\\pagebreak[\\[01234\\]] yellow/24\n"
+"    keyword whole \\\\nopagebreak[\\[01234\\]] yellow/24\n"
+"    keyword whole \\\\pagebreak yellow/24\n"
+"    keyword whole \\\\nopagebreak yellow/24\n"
+"    keyword whole \\\\samepage yellow/24\n"
+"    keyword whole \\\\newpage yellow/24\n"
+"    keyword whole \\\\clearpage yellow/24\n"
+"\n"
+"# defintiions\n"
+"    keyword \\\\newcommand{*}[*] cyan/5\n"
+"    keyword \\\\newcommand{*} cyan/5\n"
+"    keyword \\\\newenvironment{*}[*]{*} cyan/5\n"
+"    keyword \\\\newenvironment{*}{*} cyan/5\n"
+"\n"
+"# boxes\n"
+"\n"
+"# begins and ends\n"
+"    keyword \\\\begin{document} brightred/14\n"
+"    keyword \\\\begin{equation} brightred/14\n"
+"    keyword \\\\begin{eqnarray} brightred/14\n"
+"    keyword \\\\begin{quote} brightred/14\n"
+"    keyword \\\\begin{quotation} brightred/14\n"
+"    keyword \\\\begin{center} brightred/14\n"
+"    keyword \\\\begin{verse} brightred/14\n"
+"    keyword \\\\begin{verbatim} brightred/14\n"
+"    keyword \\\\begin{itemize} brightred/14\n"
+"    keyword \\\\begin{enumerate} brightred/14\n"
+"    keyword \\\\begin{description} brightred/14\n"
+"    keyword \\\\begin{array} brightred/14\n"
+"    keyword \\\\begin{tabular} brightred/14\n"
+"    keyword \\\\begin{thebibliography}{*} brightred/14\n"
+"    keyword \\\\begin{sloppypar} brightred/14\n"
+"\n"
+"    keyword \\\\end{document} brightred/14\n"
+"    keyword \\\\end{equation} brightred/14\n"
+"    keyword \\\\end{eqnarray} brightred/14\n"
+"    keyword \\\\end{quote} brightred/14\n"
+"    keyword \\\\end{quotation} brightred/14\n"
+"    keyword \\\\end{center} brightred/14\n"
+"    keyword \\\\end{verse} brightred/14\n"
+"    keyword \\\\end{verbatim} brightred/14\n"
+"    keyword \\\\end{itemize} brightred/14\n"
+"    keyword \\\\end{enumerate} brightred/14\n"
+"    keyword \\\\end{description} brightred/14\n"
+"    keyword \\\\end{array} brightred/14\n"
+"    keyword \\\\end{tabular} brightred/14\n"
+"    keyword \\\\end{thebibliography}{*} brightred/14\n"
+"    keyword \\\\end{sloppypar} brightred/14\n"
+"\n"
+"    keyword \\\\begin{*} brightcyan/16\n"
+"    keyword \\\\end{*} brightcyan/16\n"
+"\n"
+"    keyword \\\\theorem{*}{*} yellow/24\n"
+"\n"
+"# if all else fails\n"
+"    keyword whole \\\\+[*]{*}{*}{*} brightcyan/17\n"
+"    keyword whole \\\\+[*]{*}{*} brightcyan/17\n"
+"    keyword whole \\\\+{*}{*}{*}{*} brightcyan/17\n"
+"    keyword whole \\\\+{*}{*}{*} brightcyan/17\n"
+"    keyword whole \\\\+{*}{*} brightcyan/17\n"
+"    keyword whole \\\\+{*} brightcyan/17\n"
+"    keyword \\\\\\[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\\]\\n brightcyan/17\n"
+"    keyword \\\\\\[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\\]\\s brightcyan/17\n"
+"    keyword \\\\\\[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\\]\\t brightcyan/17\n"
+"\n"
+"context \\\\pagenumbering{ } yellow/20\n"
+"    keyword arabic brightcyan/17\n"
+"    keyword roman brightcyan/17\n"
+"    keyword alph brightcyan/17\n"
+"    keyword Roman brightcyan/17\n"
+"    keyword Alph brightcyan/17\n"
+"\n"
+"context % \\n brown/22\n"
+"\n"
+"# mathematical formulas\n"
+"context $ $ brightgreen/6\n"
+"context exclusive \\\\begin{equation} \\\\end{equation} brightgreen/6\n"
+"context exclusive \\\\begin{eqnarray} \\\\end{eqnarray} brightgreen/6\n"
+"\n"
+"\n"
+"###############################################################################\n"
+"file ..\\*\\\\.([chC]|CC|cxx|cc|cpp|CPP|CXX)$ C/C\\+\\+\\sProgram\n"
+"context default\n"
+"    keyword whole auto yellow/24\n"
+"    keyword whole break yellow/24\n"
+"    keyword whole case yellow/24\n"
+"    keyword whole char yellow/24\n"
+"    keyword whole const yellow/24\n"
+"    keyword whole continue yellow/24\n"
+"    keyword whole default yellow/24\n"
+"    keyword whole do yellow/24\n"
+"    keyword whole double yellow/24\n"
+"    keyword whole else yellow/24\n"
+"    keyword whole enum yellow/24\n"
+"    keyword whole extern yellow/24\n"
+"    keyword whole float yellow/24\n"
+"    keyword whole for yellow/24\n"
+"    keyword whole goto yellow/24\n"
+"    keyword whole if yellow/24\n"
+"    keyword whole int yellow/24\n"
+"    keyword whole long yellow/24\n"
+"    keyword whole register yellow/24\n"
+"    keyword whole return yellow/24\n"
+"    keyword whole short yellow/24\n"
+"    keyword whole signed yellow/24\n"
+"    keyword whole sizeof yellow/24\n"
+"    keyword whole static yellow/24\n"
+"    keyword whole struct yellow/24\n"
+"    keyword whole switch yellow/24\n"
+"    keyword whole typedef yellow/24\n"
+"    keyword whole union yellow/24\n"
+"    keyword whole unsigned yellow/24\n"
+"    keyword whole void yellow/24\n"
+"    keyword whole volatile yellow/24\n"
+"    keyword whole while yellow/24\n"
+"    keyword whole asm yellow/24\n"
+"    keyword whole catch yellow/24\n"
+"    keyword whole class yellow/24\n"
+"    keyword whole friend yellow/24\n"
+"    keyword whole delete yellow/24\n"
+"    keyword whole inline yellow/24\n"
+"    keyword whole new yellow/24\n"
+"    keyword whole operator yellow/24\n"
+"    keyword whole private yellow/24\n"
+"    keyword whole protected yellow/24\n"
+"    keyword whole public yellow/24\n"
+"    keyword whole this yellow/24\n"
+"    keyword whole throw yellow/24\n"
+"    keyword whole template yellow/24\n"
+"    keyword whole try yellow/24\n"
+"    keyword whole virtual yellow/24\n"
+"    keyword whole bool yellow/24\n"
+"    keyword whole const_cast yellow/24\n"
+"    keyword whole dynamic_cast yellow/24\n"
+"    keyword whole explicit yellow/24\n"
+"    keyword whole false yellow/24\n"
+"    keyword whole mutable yellow/24\n"
+"    keyword whole namespace yellow/24\n"
+"    keyword whole reinterpret_cast yellow/24\n"
+"    keyword whole static_cast yellow/24\n"
+"    keyword whole true yellow/24\n"
+"    keyword whole typeid yellow/24\n"
+"    keyword whole typename yellow/24\n"
+"    keyword whole using yellow/24\n"
+"    keyword whole wchar_t yellow/24\n"
+"    keyword whole ... yellow/24\n"
+"\n"
+"    keyword /\\* brown/22\n"
+"    keyword \\*/ brown/22\n"
+"\n"
+"    keyword '\\s' brightgreen/16\n"
+"    keyword '+' brightgreen/16\n"
+"    keyword > yellow/24\n"
+"    keyword < yellow/24\n"
+"    keyword \\+ yellow/24\n"
+"    keyword - yellow/24\n"
+"    keyword \\* yellow/24\n"
+"#    keyword / yellow/24\n"
+"    keyword % yellow/24\n"
+"    keyword = yellow/24\n"
+"    keyword != yellow/24\n"
+"    keyword == yellow/24\n"
+"    keyword { brightcyan/14\n"
+"    keyword } brightcyan/14\n"
+"    keyword ( brightcyan/15\n"
+"    keyword ) brightcyan/15\n"
+"    keyword [ brightcyan/14\n"
+"    keyword ] brightcyan/14\n"
+"    keyword , brightcyan/14\n"
+"    keyword : brightcyan/14\n"
+"    keyword ; brightmagenta/19\n"
+"context exclusive /\\* \\*/ brown/22\n"
+"context // \\n brown/22\n"
+"context linestart # \\n brightred/18\n"
+"    keyword \\\\\\n yellow/24\n"
+"    keyword /\\**\\*/ brown/22\n"
+"    keyword \"+\" red/19\n"
+"    keyword <+> red/19\n"
+"context \" \" green/6\n"
+"    keyword \\\\\" brightgreen/16\n"
+"    keyword %% brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]e brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]E brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]f brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]g brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[L\\]G brightgreen/16\n"
+"    keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]d brightgreen/16\n"
+"    keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]i brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]o brightgreen/16\n"
+"    keyword %\\[0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]u brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]x brightgreen/16\n"
+"    keyword %\\[#0\\s-\\+,\\]\\[0123456789\\]\\[.\\]\\[0123456789\\]\\[hl\\]X brightgreen/16\n"
+"    keyword %\\[hl\\]n brightgreen/16\n"
+"    keyword %\\[.\\]\\[0123456789\\]s brightgreen/16\n"
+"    keyword %[*] brightgreen/16\n"
+"    keyword %c brightgreen/16\n"
+"    keyword \\\\\\\\ brightgreen/16\n"
+"    keyword \\\\' brightgreen/16\n"
+"    keyword \\\\a brightgreen/16\n"
+"    keyword \\\\b brightgreen/16\n"
+"    keyword \\\\t brightgreen/16\n"
+"    keyword \\\\n brightgreen/16\n"
+"    keyword \\\\v brightgreen/16\n"
+"    keyword \\\\f brightgreen/16\n"
+"    keyword \\\\r brightgreen/16\n"
+"    keyword \\\\0 brightgreen/16\n"
+"\n"
+"###############################################################################\n"
+"file .\\*ChangeLog$ GNU\\sDistribution\\sChangeLog\\sFile\n"
+"\n"
+"context default\n"
+"    keyword \\s+() brightmagenta/23\n"
+"    keyword \\t+() brightmagenta/23\n"
+"\n"
+"context linestart \\t\\* : brightcyan/17\n"
+"context linestart \\s\\s\\s\\s\\s\\s\\s\\s\\* : brightcyan/17\n"
+"\n"
+"context linestart 19+-+\\s \\n            yellow/24\n"
+"    keyword <+@+> 			brightred/19\n"
+"context linestart 20+-+\\s \\n            yellow/24\n"
+"    keyword <+@+> 			brightred/19\n"
+"context linestart Mon\\s+\\s+\\s+\\s \\n     yellow/24\n"
+"    keyword <+@+> 			brightred/19\n"
+"context linestart Tue\\s+\\s+\\s+\\s \\n     yellow/24\n"
+"    keyword <+@+> 			brightred/19\n"
+"context linestart Wed\\s+\\s+\\s+\\s \\n     yellow/24\n"
+"    keyword <+@+> 			brightred/19\n"
+"context linestart Thu\\s+\\s+\\s+\\s \\n     yellow/24\n"
+"    keyword <+@+> 			brightred/19\n"
+"context linestart Fri\\s+\\s+\\s+\\s \\n     yellow/24\n"
+"    keyword <+@+> 			brightred/19\n"
+"context linestart Sat\\s+\\s+\\s+\\s \\n     yellow/24\n"
+"    keyword <+@+> 			brightred/19\n"
+"context linestart Sun\\s+\\s+\\s+\\s \\n     yellow/24\n"
+"    keyword <+@+> 			brightred/19\n"
+"\n"
+"\n"
+"###############################################################################\n"
+"file .\\*Makefile[\\\\\\.a-z]\\*$ Makefile\n"
+"\n"
+"context default\n"
+"    keyword $(*) yellow/24\n"
+"    keyword ${*} brightgreen/16\n"
+"    keyword whole linestart include magenta\n"
+"    keyword whole linestart endif magenta\n"
+"    keyword whole linestart ifeq magenta\n"
+"    keyword whole linestart ifneq magenta\n"
+"    keyword whole linestart else magenta\n"
+"    keyword linestart \\t lightgray/13 red\n"
+"    keyword whole .PHONY white/25\n"
+"    keyword whole .NOEXPORT white/25\n"
+"    keyword = white/25\n"
+"    keyword : yellow/24\n"
+"    keyword \\\\\\n yellow/24\n"
+"# this handles strange cases like @something@@somethingelse@ properly\n"
+"    keyword whole @+@ brightmagenta/23 black/0\n"
+"    keyword @+@ brightmagenta/23 black/0\n"
+"\n"
+"context linestart # \\n brown/22\n"
+"    keyword whole @+@ brightmagenta/23 black/0\n"
+"    keyword @+@ brightmagenta/23 black/0\n"
+"\n"
+"context exclusive = \\n brightcyan/17\n"
+"    keyword \\\\\\n yellow/24\n"
+"    keyword $(*) yellow/24\n"
+"    keyword ${*} brightgreen/16\n"
+"    keyword linestart \\t lightgray/13 red\n"
+"    keyword whole @+@ brightmagenta/23 black/0\n"
+"    keyword @+@ brightmagenta/23 black/0\n"
+"\n"
+"context exclusive linestart \\t \\n\n"
+"    keyword \\\\\\n yellow/24\n"
+"    keyword $(*) yellow/24\n"
+"    keyword ${*} brightgreen/16\n"
+"    keyword linestart \\t lightgray/13 red\n"
+"    keyword whole @+@ brightmagenta/23 black/0\n"
+"    keyword @+@ brightmagenta/23 black/0\n"
+"\n"
+"###############################################################################\n"
+"\n"
+"file .\\*syntax$ Syntax\\sHighlighting\\sdefinitions\n"
+"\n"
+"context default\n"
+"    keyword whole keyw\\ord yellow/24\n"
+"    keyword whole whole\\[\\t\\s\\]l\\inestart brightcyan/17\n"
+"    keyword whole whole\\[\\t\\s\\]l\\inestart brightcyan/17\n"
+"    keyword whole wh\\oleleft\\[\\t\\s\\]l\\inestart brightcyan/17\n"
+"    keyword whole wh\\oleright\\[\\t\\s\\]l\\inestart brightcyan/17\n"
+"    keyword whole l\\inestart\\[\\t\\s\\]wh\\ole\n"
+"    keyword whole l\\inestart\\[\\t\\s\\]wh\\ole\n"
+"    keyword whole l\\inestart\\[\\t\\s\\]wh\\oleleft\n"
+"    keyword whole l\\inestart\\[\\t\\s\\]wh\\oleright\n"
+"    keyword wholeleft whole\\s brightcyan/17\n"
+"    keyword wholeleft whole\\t brightcyan/17\n"
+"    keyword whole wh\\oleleft brightcyan/17\n"
+"    keyword whole wh\\oleright brightcyan/17\n"
+"    keyword whole lin\\[e\\]start brightcyan/17\n"
+"    keyword whole c\\ontext\\[\\t\\s\\]exclusive brightred/18\n"
+"    keyword whole c\\ontext\\[\\t\\s\\]default brightred/18\n"
+"    keyword whole c\\ontext brightred/18\n"
+"    keyword whole wh\\olechars\\[\\t\\s\\]left brightcyan/17\n"
+"    keyword whole wh\\olechars\\[\\t\\s\\]right brightcyan/17\n"
+"    keyword whole wh\\olechars brightcyan/17\n"
+"    keyword whole f\\ile brightgreen/6\n"
+"\n"
+"    keyword whole 0 lightgray/0	blue/26\n"
+"    keyword whole 1 lightgray/1	blue/26\n"
+"    keyword whole 2 lightgray/2	blue/26\n"
+"    keyword whole 3 lightgray/3	blue/26\n"
+"    keyword whole 4 lightgray/4	blue/26\n"
+"    keyword whole 5 lightgray/5	blue/26\n"
+"    keyword whole 6 lightgray/6\n"
+"    keyword whole 7 lightgray/7\n"
+"    keyword whole 8 lightgray/8\n"
+"    keyword whole 9 lightgray/9\n"
+"    keyword whole 10 lightgray/10\n"
+"    keyword whole 11 lightgray/11\n"
+"    keyword whole 12 lightgray/12\n"
+"    keyword whole 13 lightgray/13\n"
+"    keyword whole 14 lightgray/14\n"
+"    keyword whole 15 lightgray/15\n"
+"    keyword whole 16 lightgray/16\n"
+"    keyword whole 17 lightgray/17\n"
+"    keyword whole 18 lightgray/18\n"
+"    keyword whole 19 lightgray/19\n"
+"    keyword whole 20 lightgray/20\n"
+"    keyword whole 21 lightgray/21\n"
+"    keyword whole 22 lightgray/22\n"
+"    keyword whole 23 lightgray/23\n"
+"    keyword whole 24 lightgray/24\n"
+"    keyword whole 25 lightgray/25\n"
+"    keyword whole 26 lightgray/26\n"
+"\n"
+"    keyword wholeleft black\\/ black/0\n"
+"    keyword wholeleft red\\/ red/DarkRed\n"
+"    keyword wholeleft green\\/ green/green3\n"
+"    keyword wholeleft brown\\/ brown/saddlebrown\n"
+"    keyword wholeleft blue\\/ blue/blue3\n"
+"    keyword wholeleft magenta\\/ magenta/magenta3\n"
+"    keyword wholeleft cyan\\/ cyan/cyan3\n"
+"    keyword wholeleft lightgray\\/ lightgray/lightgray\n"
+"    keyword wholeleft gray\\/ gray/gray\n"
+"    keyword wholeleft brightred\\/ brightred/red\n"
+"    keyword wholeleft brightgreen\\/ brightgreen/green1\n"
+"    keyword wholeleft yellow\\/ yellow/yellow\n"
+"    keyword wholeleft brightblue\\/ brightblue/blue1\n"
+"    keyword wholeleft brightmagenta\\/ brightmagenta/magenta\n"
+"    keyword wholeleft brightcyan\\/ brightcyan/cyan1\n"
+"    keyword wholeleft white\\/ white/26\n"
+"\n"
+"context linestart # \\n brown/22\n"
+"\n"
+"file \\.\\* Help\\ssupport\\sother\\sfile\\stypes\n"
+"context default\n"
+"file \\.\\* by\\scoding\\srules\\sin\\s~/.cedit/syntax.\n"
+"context default\n"
+"file \\.\\* See\\sman/syntax\\sin\\sthe\\ssource\\sdistribution\n"
+"context default\n"
+"file \\.\\* and\\sconsult\\sthe\\sman\\spage.\n"
+"context default\n"
+"\n";
+
+
+FILE *upgrade_syntax_file (char *syntax_file)
+{
+    FILE *f;
+    char line[80];
+    f = fopen (syntax_file, "r");
+    if (!f) {
+	f = fopen (syntax_file, "w");
+	if (!f)
+	    return 0;
+	fprintf (f, "%s", syntax_text);
+	fclose (f);
+	return fopen (syntax_file, "r");
+    }
+    memset (line, 0, 79);
+    fread (line, 80, 1, f);
+    if (!strstr (line, "syntax rules version")) {
+	goto rename_rule_file;
+    } else {
+	char *p;
+	p = strstr (line, "version") + strlen ("version") + 1;
+	if (atoi (p) < atoi (CURRENT_SYNTAX_RULES_VERSION)) {
+	    char s[1024];
+	  rename_rule_file:
+	    strcpy (s, syntax_file);
+	    strcat (s, ".OLD");
+	    unlink (s);
+	    rename (syntax_file, s);
+	    unlink (syntax_file);	/* might rename() fail ? */
+#if defined(MIDNIGHT) || defined(GTK)
+	    edit_message_dialog (" Load Syntax Rules ", " Your syntax rule file is outdated \n A new rule file is being installed. \n Your old rule file has been saved with a .OLD extension. ");
+#else
+	    CMessageDialog (0, 20, 20, 0, " Load Syntax Rules ", " Your syntax rule file is outdated \n A new rule file is being installed. \n Your old rule file has been saved with a .OLD extension. ");
+#endif
+	    return upgrade_syntax_file (syntax_file);
+	} else {
+	    rewind (f);
+	    return (f);
+	}
+    }
+    return 0;			/* not reached */
+}
+
+/* returns -1 on file error, line number on error in file syntax */
+static int edit_read_syntax_file (WEdit * edit, char **names, char *syntax_file, char *editor_file, char *first_line, char *type)
+{
+    FILE *f;
+    regex_t r, r2;
+    regmatch_t pmatch[1];
+    char *args[1024], *l;
+    int line = 0;
+    int argc;
+    int result = 0;
+    int count = 0;
+
+    f = upgrade_syntax_file (syntax_file);
+    if (!f)
+	return -1;
+    args[0] = 0;
+
+    for (;;) {
+	line++;
+	if (!read_one_line (&l, f))
+	    break;
+	get_args (l, args, &argc);
+	if (!args[0]) {
+	} else if (!strcmp (args[0], "file")) {
+	    if (!args[1] || !args[2]) {
+		result = line;
+		break;
+	    }
+	    if (regcomp (&r, args[1], REG_EXTENDED)) {
+		result = line;
+		break;
+	    }
+	    if (regcomp (&r2, args[3] ? args[3] : "^nEvEr MaTcH aNyThInG$", REG_EXTENDED)) {
+		result = line;
+		break;
+	    }
+	    if (names) {
+		names[count++] = strdup (args[2]);
+		names[count] = 0;
+	    } else if (type) {
+		if (!strcmp (type, args[2]))
+		    goto found_type;
+	    } else if (editor_file && edit) {
+		if (!regexec (&r, editor_file, 1, pmatch, 0) || !regexec (&r2, first_line, 1, pmatch, 0)) {
+		    int line_error;
+		  found_type:
+		    line_error = edit_read_syntax_rules (edit, f);
+		    if (line_error)
+			result = line + line_error;
+		    else {
+			syntax_free (edit->syntax_type);
+			edit->syntax_type = strdup (args[2]);
+			if (syntax_change_callback)
+#ifdef MIDNIGHT
+			    (*syntax_change_callback) (&edit->widget);
+#else
+			    (*syntax_change_callback) (edit->widget);
+#endif
+/* if there are no rules then turn off syntax highlighting for speed */
+			if (!edit->rules[1])
+			    if (!edit->rules[0]->keyword[1])
+				edit_free_syntax_rules (edit);
+		    }
+		    break;
+		}
+	    }
+	}
+	free_args (args);
+	syntax_free (l);
+    }
+    free_args (args);
+    syntax_free (l);
+
+    fclose (f);
+
+    return result;
+}
+
+static char *get_first_editor_line (WEdit * edit)
+{
+    int i;
+    static char s[256];
+    s[0] = '\0';
+    if (!edit)
+	return s;
+    for (i = 0; i < 255; i++) {
+	s[i] = edit_get_byte (edit, i);
+	if (s[i] == '\n') {
+	    s[i] = '\0';
+	    break;
+	}
+    }
+    s[255] = '\0';
+    return s;
+}
+
+/* loads rules into edit struct. one of edit or names must be zero. if
+   edit is zero, a list of types will be stored into name. type may be zero
+   in which case the type will be selected according to the filename. */
+void edit_load_syntax (WEdit * edit, char **names, char *type)
+{
+    int r;
+    char *f;
+
+    edit_free_syntax_rules (edit);
+
+#ifdef MIDNIGHT
+    if (!SLtt_Use_Ansi_Colors)
+	return;
+#endif
+
+    if (edit) {
+	if (!edit->filename)
+	    return;
+	if (!*edit->filename && !type)
+	    return;
+    }
+    f = catstrs (home_dir, SYNTAX_FILE, 0);
+    r = edit_read_syntax_file (edit, names, f, edit ? edit->filename : 0, get_first_editor_line (edit), type);
+    if (r == -1) {
+	edit_free_syntax_rules (edit);
+	edit_error_dialog (_ (" Load syntax file "), _ (" File access error "));
+	return;
+    }
+    if (r) {
+	char s[80];
+	edit_free_syntax_rules (edit);
+	sprintf (s, _ (" Syntax error in file %s on line %d "), f, r);
+	edit_error_dialog (_ (" Load syntax file "), s);
+	return;
+    }
+}
+
+#else
+
+int option_syntax_highlighting = 0;
+
+void edit_load_syntax (WEdit * edit, char **names, char *type)
+{
+    return;
+}
+
+void edit_free_syntax_rules (WEdit * edit)
+{
+    return;
+}
+
+void edit_get_syntax_color (WEdit * edit, long byte_index, int *fg, int *bg)
+{
+    *fg = NORMAL_COLOR;
+}
+
+#endif		/* !defined(MIDNIGHT) || defined(HAVE_SYNTAXH) */
+

+ 350 - 0
edit/wordproc.c

@@ -0,0 +1,350 @@
+/* wordproc.c - word-processor mode for the editor: does dynamic
+		paragraph formatting.
+   Copyright (C) 1996 Paul Sheer
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+ */
+
+#include <config.h>
+#include "edit.h"
+
+#ifdef MIDNIGHT
+#define tab_width option_tab_spacing
+#endif
+
+int line_is_blank (WEdit * edit, long line);
+
+#define NO_FORMAT_CHARS_START "-+*\\,.;:&>"
+
+static long line_start (WEdit * edit, long line)
+{
+    static long p = -1, l = 0;
+    int c;
+    if (p == -1 || abs (l - line) > abs (edit->curs_line - line)) {
+	l = edit->curs_line;
+	p = edit->curs1;
+    }
+    if (line < l)
+	p = edit_move_backward (edit, p, l - line);
+    else if (line > l)
+	p = edit_move_forward (edit, p, line - l, 0);
+    l = line;
+    p = edit_bol (edit, p);
+    while (strchr ("\t ", c = edit_get_byte (edit, p)))
+	p++;
+    return p;
+}
+
+static int bad_line_start (WEdit * edit, long p)
+{
+    int c;
+    c = edit_get_byte (edit, p);
+    if (c == '.') {		/* `...' is acceptable */
+	if (edit_get_byte (edit, p + 1) == '.')
+	    if (edit_get_byte (edit, p + 2) == '.')
+		return 0;
+	return 1;
+    }
+    if (c == '-') {
+	if (edit_get_byte (edit, p + 1) == '-')
+	    if (edit_get_byte (edit, p + 2) == '-')
+		return 0;	/* `---' is acceptable */
+	return 1;
+    }
+    if (strchr (NO_FORMAT_CHARS_START, c))
+	return 1;
+    return 0;
+}
+
+static long begin_paragraph (WEdit * edit, long p, int force)
+{
+    int i;
+    for (i = edit->curs_line - 1; i > 0; i--) {
+	if (line_is_blank (edit, i)) {
+	    i++;
+	    break;
+	}
+	if (force) {
+	    if (bad_line_start (edit, line_start (edit, i))) {
+		i++;
+		break;
+	    }
+	}
+    }
+    return edit_move_backward (edit, edit_bol (edit, edit->curs1), edit->curs_line - i);
+}
+
+static long end_paragraph (WEdit * edit, long p, int force)
+{
+    int i;
+    for (i = edit->curs_line + 1; i < edit->total_lines; i++) {
+	if (line_is_blank (edit, i)) {
+	    i--;
+	    break;
+	}
+	if (force)
+	    if (bad_line_start (edit, line_start (edit, i))) {
+		i--;
+		break;
+	    }
+    }
+    return edit_eol (edit, edit_move_forward (edit, edit_bol (edit, edit->curs1), i - edit->curs_line, 0));
+}
+
+static char *get_paragraph (WEdit * edit, long p, long q, int indent, int *size)
+{
+    char *s, *t;
+    t = malloc ((q - p) + 2 * (q - p) / option_word_wrap_line_length + 10);
+    if (!t)
+	return 0;
+    for (s = t; p < q; p++, s++) {
+	if (indent)
+	    if (edit_get_byte (edit, p - 1) == '\n')
+		while (strchr ("\t ", edit_get_byte (edit, p)))
+		    p++;
+	*s = edit_get_byte (edit, p);
+    }
+    *size = (unsigned long) s - (unsigned long) t;
+    t[*size] = '\n';
+    return t;
+}
+
+static void strip_newlines (char *t, int size)
+{
+    char *p = t;
+    while (size--) {
+	*p = *p == '\n' ? ' ' : *p;
+	p++;
+    }
+}
+
+#ifndef MIDNIGHT
+int edit_width_of_long_printable (int c);
+#endif
+/* 
+   This is a copy of the function 
+   int calc_text_pos (WEdit * edit, long b, long *q, int l)
+   in propfont.c  :(
+   It calculates the number of chars in a line specified to length l in pixels
+ */
+extern int tab_width;
+static inline int next_tab_pos (int x)
+{
+    return x += tab_width - x % tab_width;
+}
+static int line_pixel_length (char *t, long b, int l)
+{
+    int x = 0, c, xn = 0;
+    for (;;) {
+	c = t[b];
+	switch (c) {
+	case '\n':
+	    return b;
+	case '\t':
+	    xn = next_tab_pos (x);
+	    break;
+	default:
+#ifdef MIDNIGHT
+	    xn = x + 1;
+#else
+	    xn = x + edit_width_of_long_printable (c);
+#endif
+	    break;
+	}
+	if (xn > l)
+	    break;
+	x = xn;
+	b++;
+    }
+    return b;
+}
+
+/* find the start of a word */
+static int next_word_start (char *t, int q, int size)
+{
+    int i;
+    for (i = q;; i++) {
+	switch (t[i]) {
+	case '\n':
+	    return -1;
+	case '\t':
+	case ' ':
+	    for (;; i++) {
+		if (t[i] == '\n')
+		    return -1;
+		if (t[i] != ' ' && t[i] != '\t')
+		    return i;
+	    }
+	    break;
+	}
+    }
+}
+
+/* find the start of a word */
+static int word_start (char *t, int q, int size)
+{
+    int i = q;
+    if (t[q] == ' ' || t[q] == '\t')
+	return next_word_start (t, q, size);
+    for (;;) {
+	int c;
+	if (!i)
+	    return -1;
+	c = t[i - 1];
+	if (c == '\n')
+	    return -1;
+	if (c == ' ' || c == '\t')
+	    return i;
+	i--;
+    }
+}
+
+/* replaces ' ' with '\n' to properly format a paragraph */
+static void format_this (char *t, int size, int indent)
+{
+    int q = 0, ww;
+    strip_newlines (t, size);
+    ww = option_word_wrap_line_length * FONT_MEAN_WIDTH - indent;
+    if (ww < FONT_MEAN_WIDTH * 2)
+	ww = FONT_MEAN_WIDTH * 2;
+    for (;;) {
+	int p;
+	q = line_pixel_length (t, q, ww);
+	if (q > size)
+	    break;
+	if (t[q] == '\n')
+	    break;
+	p = word_start (t, q, size);
+	if (p == -1)
+	    q = next_word_start (t, q, size);	/* Return the end of the word if the beginning 
+						   of the word is at the beginning of a line 
+						   (i.e. a very long word) */
+	else
+	    q = p;
+	if (q == -1)	/* end of paragraph */
+	    break;
+	if (q)
+	    t[q - 1] = '\n';
+    }
+}
+
+static void replace_at (WEdit * edit, long q, int c)
+{
+    edit_cursor_move (edit, q - edit->curs1);
+    edit_delete (edit);
+    edit_insert_ahead (edit, c);
+}
+
+void edit_insert_indent (WEdit * edit, int indent);
+
+/* replaces a block of text */
+static void put_paragraph (WEdit * edit, char *t, long p, long q, int indent, int size)
+{
+    long cursor;
+    int i, c = 0;
+    cursor = edit->curs1;
+    if (indent)
+	while (strchr ("\t ", edit_get_byte (edit, p)))
+	    p++;
+    for (i = 0; i < size; i++, p++) {
+	if (i && indent) {
+	    if (t[i - 1] == '\n' && c == '\n') {
+		while (strchr ("\t ", edit_get_byte (edit, p)))
+		    p++;
+	    } else if (t[i - 1] == '\n') {
+		long curs;
+		edit_cursor_move (edit, p - edit->curs1);
+		curs = edit->curs1;
+		edit_insert_indent (edit, indent);
+		if (cursor >= curs)
+		    cursor += edit->curs1 - p;
+		p = edit->curs1;
+	    } else if (c == '\n') {
+		edit_cursor_move (edit, p - edit->curs1);
+		while (strchr ("\t ", edit_get_byte (edit, p))) {
+		    edit_delete (edit);
+		    if (cursor > edit->curs1)
+			cursor--;
+		}
+		p = edit->curs1;
+	    }
+	}
+	c = edit_get_byte (edit, p);
+	if (c != t[i])
+	    replace_at (edit, p, t[i]);
+    }
+    edit_cursor_move (edit, cursor - edit->curs1);	/* restore cursor position */
+}
+
+int edit_indent_width (WEdit * edit, long p);
+
+static int test_indent (WEdit * edit, long p, long q)
+{
+    int indent;
+    indent = edit_indent_width (edit, p++);
+    if (!indent)
+	return 0;
+    for (; p < q; p++)
+	if (edit_get_byte (edit, p - 1) == '\n')
+	    if (indent != edit_indent_width (edit, p))
+		return 0;
+    return indent;
+}
+
+void format_paragraph (WEdit * edit, int force)
+{
+    long p, q;
+    int size;
+    char *t;
+    int indent = 0;
+    if (option_word_wrap_line_length < 2)
+	return;
+    if (line_is_blank (edit, edit->curs_line))
+	return;
+    p = begin_paragraph (edit, edit->curs1, force);
+    q = end_paragraph (edit, edit->curs1, force);
+    indent = test_indent (edit, p, q);
+    t = get_paragraph (edit, p, q, indent, &size);
+    if (!t)
+	return;
+    if (!force) {
+	int i;
+	if (strchr (NO_FORMAT_CHARS_START, *t)) {
+	    free (t);
+	    return;
+	}
+	for (i = 0; i < size - 1; i++) {
+	    if (t[i] == '\n') {
+		if (strchr (NO_FORMAT_CHARS_START "\t ", t[i + 1])) {
+		    free (t);
+		    return;
+		}
+	    }
+	}
+    }
+    format_this (t, q - p, indent);
+    put_paragraph (edit, t, p, q, indent, size);
+    free (t);
+}
+
+
+
+
+
+
+
+
+
+