]> skyeroc.xyz Git - dgamelaunch/commitdiff
Throw out virus in favor of ee, which is much more newbie-friendly and somewhat
authorJoshua Kwan <joshk@triplehelix.org>
Fri, 23 Jan 2004 18:14:48 +0000 (18:14 +0000)
committerJoshua Kwan <joshk@triplehelix.org>
Fri, 23 Jan 2004 18:14:48 +0000 (18:14 +0000)
less iffy than virus.

git-svn-id: svn://katsu.triplehelix.org/dgamelaunch/trunk@150 db0b04b0-f4d1-0310-9a6d-de3e77497b0e

Bugs
Changelog
dgamelaunch.c
ee.c [new file with mode: 0644]
virus.c [deleted file]

diff --git a/Bugs b/Bugs
index 8c2eef10e61f17c4608453a0cacdbed42999cb9a..3a38dc150a6c0887611296880c35bffa39908d06 100644 (file)
--- a/Bugs
+++ b/Bugs
@@ -1,6 +1 @@
-* Since virus kept calling alarm() on itself, I removed SIGALRM handling
-altogether, which breaks occasional refresh of the bottom status line.
-I don't consider this a huge bug, but if one day I, or someone else, 
-gets really bored, the full solution to this would be to bring back
-the virus signal handling, and just clear the alarm calls before exiting
-and going back to dgamelaunch code (or clear the alarm() handlers).
+None!!
index 4ae30b9498e930c3ab81e42eb9bde768b9563b48..47bb244c95fd601848fd70ba28a392431f864f7c 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,12 +1,7 @@
 1.4 (2003/12/27)
-       * Major cleanups - remove most uses of strcpy() and strcat(), except
-         in virus.c, replace with snprintf.
+       * Major cleanups - remove most uses of strcpy() and strcat()
        * Add support for mailing users while they are playing.
          [nh343-simple_mail.diff is needed]
-       * Rip out some crazy getopt code that was causing virus to go crazy
-         after a "q!" Since dgamelaunch only passes up to argv[1] to virus
-         *ever*, just make it use argv[1] and panic if argc < 2, which should
-         never happen anyway.
        * Add a confirmation to the change password screen so people like me
          don't change their passwords by accident all the time.
        * Remove many unused variables and make some functions void because
@@ -37,6 +32,7 @@
        * Port to FreeBSD 5 and Solaris (as of yet, untested)
        * Switched to own version of getnstr() that always accepts both
          ^H and ^?
+       * Replace virus with ee!!
 
 1.3.10 (2003/10/22)
        * Added a mode flag to the open call for inprogress lock files.
index 3ddece55e4bffcc1fbd5e2a50ff79e13c9230db6..ac71e5058e352878d5c81d7ff8f2a09580ab181a 100644 (file)
@@ -53,6 +53,7 @@
 #include <sys/types.h>
 #include <sys/file.h>           /* for flock() */
 #include <sys/time.h>
+#include <sys/wait.h>
 
 #ifndef __FreeBSD__
 # include <crypt.h>
@@ -88,7 +89,7 @@
 extern FILE* yyin;
 extern int yyparse ();
 
-extern int vi_main (int argc, char **argv);
+extern int ee_main (int argc, char **argv);
 extern int ttyplay_main (char *ttyfile, int mode, int rstripgfx);
 extern int ttyrec_main (char *);
 extern int master;
@@ -716,7 +717,7 @@ drawmenu ()
     {
       mvprintw (banner.len + 2, 1, "Logged in as: %s", me->username);
       mvaddstr (banner.len + 4, 1, "c) Change password");
-      mvaddstr (banner.len + 5, 1, "o) Edit option file (requires vi use)");
+      mvaddstr (banner.len + 5, 1, "o) Edit option file (uses ee)");
       mvaddstr (banner.len + 6, 1, "w) Watch games in progress");
       mvaddstr (banner.len + 7, 1, "p) Play nethack!");
       mvaddstr (banner.len + 8, 1, "q) Quit");
@@ -1175,20 +1176,37 @@ editoptions ()
 {
   FILE *rcfile;
   char *myargv[3];
+  pid_t editor;
 
   rcfile = fopen (rcfilename, "r");
   printf (" read");
   if (!rcfile)                  /* should not really happen except for old users */
     write_canned_rcfile (rcfilename);
 
-  /* use virus to edit */
+  /* use ee to edit */
 
   myargv[0] = "";
   myargv[1] = rcfilename;
   myargv[2] = 0;
 
   endwin ();
-  vi_main (2, myargv);
+
+  editor = fork();
+
+  if (editor == -1)
+  {
+    perror("fork");
+    graceful_exit(114);
+  }
+  else if (editor == 0)
+  {
+    ee_main (2, myargv);
+    exit(0);
+  }
+  else
+    waitpid(editor, NULL, 0);
+    
+
   refresh ();
 }
 
diff --git a/ee.c b/ee.c
new file mode 100644 (file)
index 0000000..4c6cc3d
--- /dev/null
+++ b/ee.c
@@ -0,0 +1,4790 @@
+/*
+ |     ee (easy editor)
+ |
+ |     An easy to use, simple screen oriented editor.
+ |
+ |     written by Hugh Mahon
+ |
+ |     THIS MATERIAL IS PROVIDED "AS IS".  THERE ARE
+ |     NO WARRANTIES OF ANY KIND WITH REGARD TO THIS
+ |     MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE
+ |     IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ |     FITNESS FOR A PARTICULAR PURPOSE.  Neither
+ |     Hewlett-Packard nor Hugh Mahon shall be liable
+ |     for errors contained herein, nor for
+ |     incidental or consequential damages in
+ |     connection with the furnishing, performance or
+ |     use of this material.  Neither Hewlett-Packard
+ |     nor Hugh Mahon assumes any responsibility for
+ |     the use or reliability of this software or
+ |     documentation.  This software and
+ |     documentation is totally UNSUPPORTED.  There
+ |     is no support contract available.  Hewlett-
+ |     Packard has done NO Quality Assurance on ANY
+ |     of the program or documentation.  You may find
+ |     the quality of the materials inferior to
+ |     supported materials.
+ |
+ |     This software is not a product of Hewlett-Packard, Co., or any 
+ |     other company.  No support is implied or offered with this software.
+ |     You've got the source, and you're on your own.
+ |
+ |     This software may be distributed under the terms of Larry Wall's 
+ |     Artistic license, a copy of which is included in this distribution. 
+ |
+ |     This notice must be included with this software and any derivatives.
+ |
+ |     This editor was purposely developed to be simple, both in 
+ |     interface and implementation.  This editor was developed to 
+ |     address a specific audience: the user who is new to computers 
+ |     (especially UNIX).
+ |     
+ |     ee is not aimed at technical users; for that reason more 
+ |     complex features were intentionally left out.  In addition, 
+ |     ee is intended to be compiled by people with little computer 
+ |     experience, which means that it needs to be small, relatively 
+ |     simple in implementation, and portable.
+ |
+ |     This software and documentation contains
+ |     proprietary information which is protected by
+ |     copyright.  All rights are reserved.
+ |
+ |     $Header: /var/cvs/dgamelaunch/ee.c,v 1.1 2004/01/23 18:14:48 joshk Exp $
+ |
+ */
+
+char *ee_copyright_message = 
+"Copyright (c) 1986, 1990, 1991, 1992, 1993, 1994, 1995, 1996 Hugh Mahon ";
+
+char *ee_long_notice[] = {
+       "This software and documentation contains", 
+       "proprietary information which is protected by", 
+       "copyright.  All rights are reserved."
+       };
+
+char *version = "@(#) ee, version 1.4.1  $Revision: 1.1 $";
+
+#define catgetlocal(a, b) (b)
+
+#include <curses.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <pwd.h>
+
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#ifndef SIGCHLD
+#define SIGCHLD SIGCLD
+#endif
+
+#define TAB 9
+#define max(a, b)      (a > b ? a : b)
+#define min(a, b)      (a < b ? a : b)
+
+/*
+ |     defines for type of data to show in info window
+ */
+
+#define CONTROL_KEYS 1
+#define COMMANDS     2
+
+struct text {
+       unsigned char *line;            /* line of characters           */
+       int line_number;                /* line number                  */
+       int line_length;        /* actual number of characters in the line */
+       int max_length; /* maximum number of characters the line handles */
+       struct text *next_line;         /* next line of text            */
+       struct text *prev_line;         /* previous line of text        */
+       };
+
+struct text *first_line;       /* first line of current buffer         */
+struct text *dlt_line;         /* structure for info on deleted line   */
+struct text *curr_line;                /* current line cursor is on            */
+struct text *tmp_line;         /* temporary line pointer               */
+struct text *srch_line;                /* temporary pointer for search routine */
+
+struct files {         /* structure to store names of files to be edited*/
+       unsigned char *name;            /* name of file                         */
+       struct files *next_name;
+       };
+
+struct files *top_of_stack = NULL;
+
+int d_wrd_len;                 /* length of deleted word               */
+int position;                  /* offset in bytes from begin of line   */
+int scr_pos;                   /* horizontal position                  */
+int scr_vert;                  /* vertical position on screen          */
+int scr_horz;                  /* horizontal position on screen        */
+int tmp_vert, tmp_horz;
+int input_file;                        /* indicate to read input file          */
+int recv_file;                 /* indicate reading a file              */
+int edit;                      /* continue executing while true        */
+int gold;                      /* 'gold' function key pressed          */
+int fildes;                    /* file descriptor                      */
+int case_sen;                  /* case sensitive search flag           */
+int last_line;                 /* last line for text display           */
+int last_col;                  /* last column for text display         */
+int horiz_offset = 0;          /* offset from left edge of text        */
+int clear_com_win;             /* flag to indicate com_win needs clearing */
+int text_changes = FALSE;      /* indicate changes have been made to text */
+int get_fd;                    /* file descriptor for reading a file   */
+int info_window = TRUE;                /* flag to indicate if help window visible */
+int info_type = CONTROL_KEYS;  /* flag to indicate type of info to display */
+int expand_tabs = TRUE;                /* flag for expanding tabs              */
+int right_margin = 0;          /* the right margin                     */
+int observ_margins = TRUE;     /* flag for whether margins are observed */
+int temp_stdin;                        /* temporary storage for stdin          */
+int temp_stdout;               /* temp storage for stdout descriptor   */
+int temp_stderr;               /* temp storage for stderr descriptor   */
+int pipe_out[2];               /* pipe file desc for output            */
+int pipe_in[2];                        /* pipe file descriptors for input      */
+int out_pipe;                  /* flag that info is piped out          */
+int in_pipe;                   /* flag that info is piped in           */
+int formatted = FALSE;         /* flag indicating paragraph formatted  */
+int auto_format = FALSE;       /* flag for auto_format mode            */
+int restricted = FALSE;                /* flag to indicate restricted mode     */
+int nohighlight = FALSE;       /* turns off highlighting               */
+int eightbit = TRUE;           /* eight bit character flag             */
+int local_LINES = 0;           /* copy of LINES, to detect when win resizes */
+int local_COLS = 0;            /* copy of COLS, to detect when win resizes  */
+int curses_initialized = FALSE;        /* flag indicating if curses has been started*/
+int emacs_keys_mode = FALSE;   /* mode for if emacs key binings are used    */
+int ee_chinese = FALSE;                /* allows handling of multi-byte characters  */
+                               /* by checking for high bit in a byte the    */
+                               /* code recognizes a two-byte character      */
+                               /* sequence                                  */
+
+unsigned char *point;          /* points to current position in line   */
+unsigned char *srch_str;       /* pointer for search string            */
+unsigned char *u_srch_str;     /* pointer to non-case sensitive search */
+unsigned char *srch_1;         /* pointer to start of suspect string   */
+unsigned char *srch_2;         /* pointer to next character of string  */
+unsigned char *srch_3;
+unsigned char *in_file_name = NULL;    /* name of input file           */
+char *tmp_file;        /* temporary file name                  */
+unsigned char *d_char;         /* deleted character                    */
+unsigned char *d_word;         /* deleted word                         */
+unsigned char *d_line;         /* deleted line                         */
+char in_string[513];   /* buffer for reading a file            */
+unsigned char *start_at_line = NULL;   /* move to this line at start of session*/
+int in;                                /* input character                      */
+
+FILE *temp_fp;                 /* temporary file pointer               */
+FILE *bit_bucket;              /* file pointer to /dev/null            */
+
+char *table[] = { 
+       "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "\t", "^J", 
+       "^K", "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", 
+       "^V", "^W", "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_"
+       };
+
+WINDOW *com_win;
+WINDOW *text_win;
+WINDOW *help_win;
+WINDOW *info_win;
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define P_(s) s
+#else
+#define P_(s) ()
+#endif
+
+
+/*
+ |     The following structure allows menu items to be flexibly declared.
+ |     The first item is the string describing the selection, the second 
+ |     is the address of the procedure to call when the item is selected,
+ |     and the third is the argument for the procedure.
+ |
+ |     For those systems with i18n, the string should be accompanied by a
+ |     catalog number.  The 'int *' should be replaced with 'void *' on 
+ |     systems with that type.
+ |
+ |     The first menu item will be the title of the menu, with NULL 
+ |     parameters for the procedure and argument, followed by the menu items.
+ |
+ |     If the procedure value is NULL, the menu item is displayed, but no 
+ |     procedure is called when the item is selected.  The number of the 
+ |     item will be returned.  If the third (argument) parameter is -1, no 
+ |     argument is given to the procedure when it is called.
+ */
+
+struct menu_entries {
+       char *item_string;
+       int (*procedure)P_((struct menu_entries *));
+       struct menu_entries *ptr_argument;
+       int (*iprocedure)P_((int));
+       void (*nprocedure)P_((void));
+       int argument;
+       };
+
+int main P_((int argc, char *argv[]));
+unsigned char *resiz_line P_((int factor, struct text *rline, int rpos));
+void insert P_((int character));
+void delete P_((int disp));
+void scanline P_((unsigned char *pos));
+int tabshift P_((int temp_int));
+int out_char P_((WINDOW *window, int character, int column));
+int len_char P_((int character, int column));
+void draw_line P_((int vertical, int horiz, unsigned char *ptr, int t_pos, int length));
+void insert_line P_((int disp));
+struct text *txtalloc P_((void));
+struct files *name_alloc P_((void));
+unsigned char *next_word P_((unsigned char *string));
+void prev_word P_((void));
+void control P_((void));
+void emacs_control P_((void));
+void bottom P_((void));
+void top P_((void));
+void nextline P_((void));
+void prevline P_((void));
+void left P_((int disp));
+void right P_((int disp));
+void find_pos P_((void));
+void up P_((void));
+void down P_((void));
+void function_key P_((void));
+void command_prompt P_((void));
+void command P_((char *cmd_str1));
+int scan P_((char *line, int offset, int column));
+char *get_string P_((char *prompt, int advance));
+int compare P_((char *string1, char *string2, int sensitive));
+void goto_line P_((char *cmd_str));
+void midscreen P_((int line, unsigned char *pnt));
+void get_options P_((int numargs, char *arguments[]));
+void check_fp P_((void));
+void get_file P_((char *file_name));
+void get_line P_((int length, unsigned char *in_string, int *append));
+void draw_screen P_((void));
+void ee_finish P_((void));
+int quit P_((int noverify));
+void edit_abort P_((int arg));
+void delete_text P_((void));
+int write_file P_((char *file_name, int fd));
+int search P_((int display_message));
+void search_prompt P_((void));
+void del_char P_((void));
+void undel_char P_((void));
+void del_word P_((void));
+void undel_word P_((void));
+void del_line P_((void));
+void undel_line P_((void));
+void adv_word P_((void));
+void move_rel P_((char *direction, int lines));
+void eol P_((void));
+void bol P_((void));
+void adv_line P_((void));
+void set_up_term P_((void));
+void resize_check P_((void));
+int menu_op P_((struct menu_entries *));
+void paint_menu P_((struct menu_entries menu_list[], int max_width, int max_height, int list_size, int top_offset, WINDOW *menu_win, int off_start, int vert_size));
+void help P_((void));
+void paint_info_win P_((void));
+void no_info_window P_((void));
+void create_info_window P_((void));
+int file_op P_((int arg));
+void leave_op P_((void));
+void redraw P_((void));
+int Blank_Line P_((struct text *test_line));
+void Format P_((void));
+void ee_init P_((void));
+void echo_string P_((char *string));
+int first_word_len P_((struct text *test_line));
+void Auto_Format P_((void));
+void modes_op P_((void));
+char *is_in_string P_((char *string, char *substring));
+char *resolve_name P_((char *name));
+int restrict_mode P_((void));
+int unique_test P_((char *string, char *list[]));
+void strings_init P_((void));
+
+#undef P_
+/*
+ |     allocate space here for the strings that will be in the menu
+ */
+
+struct menu_entries modes_menu[] = {
+       {"", NULL, NULL, NULL, NULL, 0},        /* title                */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 1. tabs to spaces    */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 2. case sensitive search*/
+       {"", NULL, NULL, NULL, NULL, -1},       /* 3. margins observed  */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 4. auto-paragraph    */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 5. eightbit characters*/
+       {"", NULL, NULL, NULL, NULL, -1},       /* 6. info window       */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 7. emacs key bindings*/
+       {"", NULL, NULL, NULL, NULL, -1},       /* 8. right margin      */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 9. chinese text      */
+       {NULL, NULL, NULL, NULL, NULL, -1}      /* terminator           */
+       };
+
+char *mode_strings[11]; 
+
+#define NUM_MODES_ITEMS 10
+
+struct menu_entries config_dump_menu[] = {
+       {"", NULL, NULL, NULL, NULL, 0}, 
+       {"", NULL, NULL, NULL, NULL, -1},
+       {"", NULL, NULL, NULL, NULL, -1},
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+struct menu_entries leave_menu[] = {
+       {"", NULL, NULL, NULL, NULL, -1}, 
+       {"", NULL, NULL, NULL, ee_finish, -1}, 
+       {"", NULL, NULL, quit, NULL, TRUE}, 
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+#define READ_FILE 1
+#define WRITE_FILE 2
+#define SAVE_FILE 3
+
+struct menu_entries file_menu[] = {
+       {"", NULL, NULL, NULL, NULL, -1},
+       {"", NULL, NULL, file_op, NULL, READ_FILE},
+       {"", NULL, NULL, file_op, NULL, WRITE_FILE},
+       {"", NULL, NULL, file_op, NULL, SAVE_FILE},
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+struct menu_entries search_menu[] = {
+       {"", NULL, NULL, NULL, NULL, 0}, 
+       {"", NULL, NULL, NULL, search_prompt, -1},
+       {"", NULL, NULL, search, NULL, TRUE},
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+struct menu_entries main_menu[] = {
+       {"", NULL, NULL, NULL, NULL, -1}, 
+       {"", NULL, NULL, NULL, leave_op, -1}, 
+       {"", NULL, NULL, NULL, help, -1},
+       {"", menu_op, file_menu, NULL, NULL, -1}, 
+       {"", NULL, NULL, NULL, redraw, -1}, 
+       {"", NULL, NULL, NULL, modes_op, -1}, 
+       {"", menu_op, search_menu, NULL, NULL, -1}, 
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+char *help_text[23];
+char *control_keys[5];
+
+char *emacs_help_text[22];
+char *emacs_control_keys[5];
+
+char *command_strings[5];
+char *commands[32];
+char *init_strings[22];
+
+#define MENU_WARN 1
+
+#define max_alpha_char 36
+
+/*
+ |     Declarations for strings for localization
+ */
+
+char *com_win_message;         /* to be shown in com_win if no info window */
+char *no_file_string;
+char *ascii_code_str;
+char *command_str;
+char *file_write_prompt_str;
+char *file_read_prompt_str;
+char *char_str;
+char *unkn_cmd_str;
+char *non_unique_cmd_msg;
+char *line_num_str;
+char *line_len_str;
+char *current_file_str;
+char *usage0;
+char *usage1;
+char *usage2;
+char *usage3;
+char *usage4;
+char *file_is_dir_msg;
+char *new_file_msg;
+char *cant_open_msg;
+char *open_file_msg;
+char *file_read_fin_msg;
+char *reading_file_msg;
+char *read_only_msg;
+char *file_read_lines_msg;
+char *save_file_name_prompt;
+char *file_not_saved_msg;
+char *changes_made_prompt;
+char *yes_char;
+char *file_exists_prompt;
+char *create_file_fail_msg;
+char *writing_file_msg;
+char *file_written_msg;
+char *searching_msg;
+char *str_not_found_msg;
+char *search_prompt_str;
+char *continue_msg;
+char *menu_cancel_msg;
+char *menu_size_err_msg;
+char *press_any_key_msg;
+char *shell_prompt;
+char *formatting_msg;
+char *shell_echo_msg;
+char *margin_prompt;
+char *restricted_msg;
+char *ON;
+char *OFF;
+char *HELP;
+char *WRITE;
+char *READ;
+char *LINE;
+char *FILE_str;
+char *CHARACTER;
+char *REDRAW;
+char *RESEQUENCE;
+char *AUTHOR;
+char *ee_VERSION;
+char *CASE;
+char *NOCASE;
+char *EXPAND;
+char *NOEXPAND;
+char *Exit_string;
+char *QUIT_string;
+char *INFO;
+char *NOINFO;
+char *MARGINS;
+char *NOMARGINS;
+char *AUTOFORMAT;
+char *NOAUTOFORMAT;
+char *Echo;
+char *PRINTCOMMAND;
+char *RIGHTMARGIN;
+char *HIGHLIGHT;
+char *NOHIGHLIGHT;
+char *EIGHTBIT;
+char *NOEIGHTBIT;
+char *EMACS_string;
+char *NOEMACS_string;
+char *conf_dump_err_msg;
+char *conf_dump_success_msg;
+char *conf_not_saved_msg;
+char *ree_no_file_msg;
+char *cancel_string;
+char *menu_too_lrg_msg;
+char *more_above_str, *more_below_str;
+
+char *chinese_cmd, *nochinese_cmd;
+
+#ifndef __STDC__
+#ifndef HAS_STDLIB
+extern char *malloc();
+extern char *realloc();
+extern char *getenv();
+FILE *fopen();                 /* declaration for open function        */
+#endif /* HAS_STDLIB */
+#endif /* __STDC__ */
+
+int
+ee_main(argc, argv)            /* beginning of main program            */
+int argc;
+char *argv[];
+{
+       int counter;
+
+       for (counter = 1; counter < 24; counter++)
+               signal(counter, SIG_IGN);
+
+       signal(SIGCHLD, SIG_DFL);
+       signal(SIGSEGV, SIG_DFL);
+       signal(SIGINT, edit_abort);
+       d_char = malloc(3);     /* provide a buffer for multi-byte chars */
+       d_word = malloc(150);
+       *d_word = (char) NULL;
+       d_line = NULL;
+       dlt_line = txtalloc();
+       dlt_line->line = d_line;
+       dlt_line->line_length = 0;
+       curr_line = first_line = txtalloc();
+       curr_line->line = point = malloc(10);
+       curr_line->line_length = 1;
+       curr_line->max_length = 10;
+       curr_line->prev_line = NULL;
+       curr_line->next_line = NULL;
+       curr_line->line_number  = 1;
+       srch_str = NULL;
+       u_srch_str = NULL;
+       position = 1;
+       scr_pos =0;
+       scr_vert = 0;
+       scr_horz = 0;
+       bit_bucket = fopen("/dev/null", "w");
+       edit = TRUE;
+       gold = case_sen = FALSE;
+       strings_init();
+       ee_init();
+       if (argc > 0 )
+               get_options(argc, argv);
+       set_up_term();
+       if (right_margin == 0)
+               right_margin = COLS - 1;
+       if (top_of_stack == NULL)
+       {
+               if (restrict_mode())
+               {
+                       wmove(com_win, 0, 0);
+                       werase(com_win);
+                       wprintw(com_win, ree_no_file_msg);
+                       wrefresh(com_win);
+                       edit_abort(0);
+               }
+               wprintw(com_win, no_file_string);
+               wrefresh(com_win);
+       }
+       else
+               check_fp();
+
+       clear_com_win = TRUE;
+
+       while(edit) 
+       {
+               wrefresh(text_win);
+               in = wgetch(text_win);
+               if (in == -1)
+                       exit(0);
+
+               resize_check();
+
+               if (clear_com_win)
+               {
+                       clear_com_win = FALSE;
+                       wmove(com_win, 0, 0);
+                       werase(com_win);
+                       if (!info_window)
+                       {
+                               wprintw(com_win, "%s", com_win_message);
+                       }
+                       wrefresh(com_win);
+               }
+
+               if (in > 255)
+                       function_key();
+               else if ((in == '\10') || (in == 127))
+               {
+                       in = 8;         /* make sure key is set to backspace */
+                       delete(TRUE);
+               }
+               else if ((in > 31) || (in == 9))
+                       insert(in);
+               else if ((in >= 0) && (in <= 31))
+               {
+                       if (emacs_keys_mode)
+                               emacs_control();
+                       else
+                               control();
+               }
+       }
+       return(0);
+}
+
+unsigned char *
+resiz_line(factor, rline, rpos)        /* resize the line to length + factor*/
+int factor;            /* resize factor                                */
+struct text *rline;    /* position in line                             */
+int rpos;
+{
+       unsigned char *rpoint;
+       int resiz_var;
+       rline->max_length += factor;
+       rpoint = rline->line = realloc(rline->line, rline->max_length );
+       for (resiz_var = 1 ; (resiz_var < rpos) ; resiz_var++)
+               rpoint++;
+       return(rpoint);
+}
+
+void 
+insert(character)              /* insert character into line           */
+int character;                 /* new character                        */
+{
+       int counter;
+       int value;
+       unsigned char *temp;    /* temporary pointer                    */
+       unsigned char *temp2;   /* temporary pointer                    */
+
+       if ((character == '\011') && (expand_tabs))
+       {
+               counter = len_char('\011', scr_horz);
+               for (; counter > 0; counter--)
+                       insert(' ');
+               if (auto_format)
+                       Auto_Format();
+               return;
+       }
+       text_changes = TRUE;
+       if ((curr_line->max_length - curr_line->line_length) < 5)
+               point = resiz_line(10, curr_line, position);
+       curr_line->line_length++;
+       temp = point;
+       counter = position;
+       while (counter < curr_line->line_length)        /* find end of line */
+       {
+               counter++;
+               temp++;
+       }
+       temp++;                 /* increase length of line by one       */
+       while (point < temp)
+       {
+               temp2=temp - 1;
+               *temp= *temp2;  /* shift characters over by one         */
+               temp--;
+       }
+       *point = character;     /* insert new character                 */
+       wclrtoeol(text_win);
+       if (((character >= 0) && (character < ' ')) || (character >= 127)) /* check for TAB character*/
+       {
+               scr_pos = scr_horz += out_char(text_win, character, scr_horz);
+               point++;
+               position++;
+       }
+       else
+       {
+               waddch(text_win, character);
+               scr_pos = ++scr_horz;
+               point++;
+               position ++;
+       }
+
+       if ((observ_margins) && (right_margin < scr_pos))
+       {
+               counter = position;
+               while (scr_pos > right_margin)
+                       prev_word();
+               if (scr_pos == 0)
+               {
+                       while (position < counter)
+                               right(TRUE);
+               }
+               else
+               {
+                       counter -= position;
+                       insert_line(TRUE);
+                       for (value = 0; value < counter; value++)
+                               right(TRUE);
+               }
+       }
+
+       if ((scr_horz - horiz_offset) > last_col)
+       {
+               horiz_offset += 8;
+               midscreen(scr_vert, point);
+       }
+
+       if ((auto_format) && (character == ' ') && (!formatted))
+               Auto_Format();
+       else if ((character != ' ') && (character != '\t'))
+               formatted = FALSE;
+
+       draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
+}
+
+void 
+delete(disp)                   /* delete character             */
+int disp;
+{
+       unsigned char *tp;
+       unsigned char *temp2;
+       struct text *temp_buff;
+       int temp_vert;
+       int temp_pos;
+       int del_width = 1;
+
+       if (point != curr_line->line)   /* if not at beginning of line  */
+       {
+               text_changes = TRUE;
+               temp2 = tp = point;
+               if ((ee_chinese) && (position >= 2) && (*(point - 2) > 127))
+               {
+                       del_width = 2;
+               }
+               tp -= del_width;
+               point -= del_width;
+               position -= del_width;
+               temp_pos = position;
+               curr_line->line_length -= del_width;
+               if ((*tp < ' ') || (*tp >= 127))        /* check for TAB */
+                       scanline(tp);
+               else
+                       scr_horz -= del_width;
+               scr_pos = scr_horz;
+               if (in == 8)
+               {
+                       if (del_width == 1)
+                               *d_char = *point; /* save deleted character  */
+                       else
+                       {
+                               d_char[0] = *point;
+                               d_char[1] = *(point + 1);
+                       }
+                       d_char[del_width] = (unsigned char) NULL;
+               }
+               while (temp_pos <= curr_line->line_length)
+               {
+                       temp_pos++;
+                       *tp = *temp2;
+                       tp++;
+                       temp2++;
+               }
+               if (scr_horz < horiz_offset)
+               {
+                       horiz_offset -= 8;
+                       midscreen(scr_vert, point);
+               }
+       }
+       else if (curr_line->prev_line != NULL)
+       {
+               text_changes = TRUE;
+               left(disp);                     /* go to previous line  */
+               temp_buff = curr_line->next_line;
+               point = resiz_line(temp_buff->line_length, curr_line, position);
+               if (temp_buff->next_line != NULL)
+                       temp_buff->next_line->prev_line = curr_line;
+               curr_line->next_line = temp_buff->next_line;
+               temp2 = temp_buff->line;
+               if (in == 8)
+               {
+                       d_char[0] = '\n';
+                       d_char[1] = (unsigned char) NULL;
+               }
+               tp = point;
+               temp_pos = 1;
+               while (temp_pos < temp_buff->line_length)
+               {
+                       curr_line->line_length++;
+                       temp_pos++;
+                       *tp = *temp2;
+                       tp++;
+                       temp2++;
+               }
+               *tp = (char) NULL;
+               free(temp_buff->line);
+               free(temp_buff);
+               temp_buff = curr_line;
+               temp_vert = scr_vert;
+               scr_pos = scr_horz;
+               if (scr_vert < last_line)
+               {
+                       wmove(text_win, scr_vert + 1, 0);
+                       wdeleteln(text_win);
+               }
+               while ((temp_buff != NULL) && (temp_vert < last_line))
+               {
+                       temp_buff = temp_buff->next_line;
+                       temp_vert++;
+               }
+               if ((temp_vert == last_line) && (temp_buff != NULL))
+               {
+                       tp = temp_buff->line;
+                       wmove(text_win, last_line,0);
+                       wclrtobot(text_win);
+                       draw_line(last_line, 0, tp, 1, temp_buff->line_length);
+                       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+               }
+       }
+       draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
+       formatted = FALSE;
+}
+
+void 
+scanline(pos)  /* find the proper horizontal position for the pointer  */
+unsigned char *pos;
+{
+       int temp;
+       unsigned char *ptr;
+
+       ptr = curr_line->line;
+       temp = 0;
+       while (ptr < pos)
+       {
+               if (*ptr <= 8)
+                       temp += 2;
+               else if (*ptr == 9)
+                       temp += tabshift(temp);
+               else if ((*ptr >= 10) && (*ptr <= 31))
+                       temp += 2;
+               else if ((*ptr >= 32) && (*ptr < 127))
+                       temp++;
+               else if (*ptr == 127)
+                       temp += 2;
+               else if (!eightbit)
+                       temp += 5;
+               else
+                       temp++;
+               ptr++;
+       }
+       scr_horz = temp;
+       if ((scr_horz - horiz_offset) > last_col)
+       {
+               horiz_offset = (scr_horz - (scr_horz % 8)) - (COLS - 8);
+               midscreen(scr_vert, point);
+       }
+       else if (scr_horz < horiz_offset)
+       {
+               horiz_offset = max(0, (scr_horz - (scr_horz % 8)));
+               midscreen(scr_vert, point);
+       }
+}
+
+int 
+tabshift(temp_int)             /* give the number of spaces to shift   */
+int temp_int;
+{
+       int leftover;
+
+       leftover = ((temp_int + 1) % 8);
+       if (leftover == 0)
+               return (1);
+       else
+               return (9 - leftover);
+}
+
+int 
+out_char(window, character, column)    /* output non-printing character */
+WINDOW *window;
+int character;
+int column;
+{
+       int i1, i2;
+       unsigned char *string;
+       char string2[8];
+
+       if (character == TAB)
+       {
+               i1 = tabshift(column);
+               for (i2 = 0; 
+                 (i2 < i1) && (((column+i2+1)-horiz_offset) < last_col); i2++)
+               {
+                       waddch(window, ' ');
+               }
+               return(i1);
+       }
+       else if ((character >= '\0') && (character < ' '))
+       {
+               string = table[(int) character];
+       }
+       else if ((character < 0) || (character >= 127))
+       {
+               if (character == 127)
+                       string = "^?";
+               else if (!eightbit)
+               {
+                       sprintf(string2, "<%d>", (character < 0) ? (character + 256) : character);
+                       string = string2;
+               }
+               else
+               {
+                       waddch(window, character );
+                       return(1);
+               }
+       }
+       else
+       {
+               waddch(window, character);
+               return(1);
+       }
+       for (i2 = 0; (string[i2] != (char) NULL) && (((column+i2+1)-horiz_offset) < last_col); i2++)
+               waddch(window, string[i2]);
+       return(strlen(string));
+}
+
+int 
+len_char(character, column)    /* return the length of the character   */
+char character;
+int column;    /* the column must be known to provide spacing for tabs */
+{
+       int length;
+
+       if (character == '\t')
+               length = tabshift(column);
+       else if ((character >= 0) && (character < 32))
+               length = 2;
+       else if ((character >= 32) && (character <= 126))
+               length = 1;
+       else if (character == 127)
+               length = 2;
+       else if (((character > 126) || (character < 0)) && (!eightbit))
+               length = 5;
+       else
+               length = 1;
+
+       return(length);
+}
+
+void 
+draw_line(vertical, horiz, ptr, t_pos, length) /* redraw line from current position */
+int vertical;  /* current vertical position on screen          */
+int horiz;     /* current horizontal position on screen        */
+unsigned char *ptr;    /* pointer to line                              */
+int t_pos;     /* current position (offset in bytes) from bol  */
+int length;    /* length (in bytes) of line                    */
+{
+       int d;          /* partial length of special or tab char to display  */
+       unsigned char *temp;    /* temporary pointer to position in line             */
+       int abs_column; /* offset in screen units from begin of line         */
+       int column;     /* horizontal position on screen                     */
+       int row;        /* vertical position on screen                       */
+       int posit;      /* temporary position indicator within line          */
+
+       abs_column = horiz;
+       column = horiz - horiz_offset;
+       row = vertical;
+       temp = ptr;
+       d = 0;
+       posit = t_pos;
+       if (column < 0)
+       {
+               wmove(text_win, row, 0);
+               wclrtoeol(text_win);
+       }
+       while (column < 0)
+       {
+               d = len_char(*temp, abs_column);
+               abs_column += d;
+               column += d;
+               posit++;
+               temp++;
+       }
+       wmove(text_win, row, column);
+       wclrtoeol(text_win);
+       while ((posit < length) && (column <= last_col))
+       {
+               if ((*temp < 32) || (*temp >= 127))
+               {
+                       column += len_char(*temp, abs_column);
+                       abs_column += out_char(text_win, *temp, abs_column);
+               }
+               else
+               {
+                       abs_column++;
+                       column++;
+                       waddch(text_win, *temp);
+               }
+               posit++;
+               temp++;
+       }
+       if (column < last_col)
+               wclrtoeol(text_win);
+       wmove(text_win, vertical, (horiz - horiz_offset));
+}
+
+void 
+insert_line(disp)                      /* insert new line              */
+int disp;
+{
+       int temp_pos;
+       int temp_pos2;
+       unsigned char *temp;
+       unsigned char *extra;
+       struct text *temp_nod;
+
+       text_changes = TRUE;
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+       wclrtoeol(text_win);
+       temp_nod= txtalloc();
+       temp_nod->line = extra= malloc(10);
+       temp_nod->line_length = 1;
+       temp_nod->max_length = 10;
+       temp_nod->line_number = curr_line->line_number + 1;
+       temp_nod->next_line = curr_line->next_line;
+       if (temp_nod->next_line != NULL)
+               temp_nod->next_line->prev_line = temp_nod;
+       temp_nod->prev_line = curr_line;
+       curr_line->next_line = temp_nod;
+       temp_pos2 = position;
+       temp = point;
+       if (temp_pos2 < curr_line->line_length)
+       {
+               temp_pos = 1;
+               while (temp_pos2 < curr_line->line_length)
+               {
+                       if ((temp_nod->max_length - temp_nod->line_length)< 5)
+                               extra = resiz_line(10, temp_nod, temp_pos);
+                       temp_nod->line_length++;
+                       temp_pos++;
+                       temp_pos2++;
+                       *extra= *temp;
+                       extra++;
+                       temp++;
+               }
+               temp=point;
+               *temp = (char) NULL;
+               temp = resiz_line((1 - temp_nod->line_length), curr_line, position);
+               curr_line->line_length = 1 + temp - curr_line->line;
+       }
+       curr_line->line_length = position;
+       curr_line = temp_nod;
+       *extra = (char) NULL;
+       position = 1;
+       point= curr_line->line;
+       if (disp)
+       {
+               if (scr_vert < last_line)
+               {
+                       scr_vert++;
+                       wclrtoeol(text_win);
+                       wmove(text_win, scr_vert, 0);
+                       winsertln(text_win);
+               }
+               else
+               {
+                       wmove(text_win, 0,0);
+                       wdeleteln(text_win);
+                       wmove(text_win, last_line,0);
+                       wclrtobot(text_win);
+               }
+               scr_pos = scr_horz = 0;
+               if (horiz_offset)
+               {
+                       horiz_offset = 0;
+                       midscreen(scr_vert, point);
+               }
+               draw_line(scr_vert, scr_horz, point, position,
+                       curr_line->line_length);
+       }
+}
+
+struct text *txtalloc()                /* allocate space for line structure    */
+{
+       return((struct text *) malloc(sizeof( struct text)));
+}
+
+struct files *name_alloc()     /* allocate space for file name list node */
+{
+       return((struct files *) malloc(sizeof( struct files)));
+}
+
+unsigned char *next_word(string)               /* move to next word in string          */
+unsigned char *string;
+{
+       while ((*string != (char) NULL) && ((*string != 32) && (*string != 9)))
+               string++;
+       while ((*string != (char) NULL) && ((*string == 32) || (*string == 9)))
+               string++;
+       return(string);
+}
+
+void 
+prev_word()    /* move to start of previous word in text       */
+{
+       if (position != 1)
+       {
+               if ((position != 1) && ((point[-1] == ' ') || (point[-1] == '\t')))
+               {       /* if at the start of a word    */
+                       while ((position != 1) && ((*point != ' ') && (*point != '\t')))
+                               left(TRUE);
+               }
+               while ((position != 1) && ((*point == ' ') || (*point == '\t')))
+                       left(TRUE);
+               while ((position != 1) && ((*point != ' ') && (*point != '\t')))
+                       left(TRUE);
+               if ((position != 1) && ((*point == ' ') || (*point == '\t')))
+                       right(TRUE);
+       }
+       else
+               left(TRUE);
+}
+
+void 
+control()                      /* use control for commands             */
+{
+       char *string;
+
+       if (in == 1)            /* control a    */
+       {
+               string = get_string(ascii_code_str, TRUE);
+               if (*string != (char) NULL)
+               {
+                       in = atoi(string);
+                       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+                       insert(in);
+               }
+               free(string);
+       }
+       else if (in == 2)       /* control b    */
+               bottom();
+       else if (in == 3)       /* control c    */
+       {
+               command_prompt();
+       }
+       else if (in == 4)       /* control d    */
+               down();
+       else if (in == 5)       /* control e    */
+               search_prompt();
+       else if (in == 6)       /* control f    */
+               undel_char();
+       else if (in == 7)       /* control g    */
+               bol();
+       else if (in == 8)       /* control h    */
+               delete(TRUE);
+       else if (in == 9)       /* control i    */
+               ;
+       else if (in == 10)      /* control j    */
+               insert_line(TRUE);
+       else if (in == 11)      /* control k    */
+               del_char();
+       else if (in == 12)      /* control l    */
+               left(TRUE);
+       else if (in == 13)      /* control m    */
+               insert_line(TRUE);
+       else if (in == 14)      /* control n    */
+               move_rel("d", max(5, (last_line - 5)));
+       else if (in == 15)      /* control o    */
+               eol();
+       else if (in == 16)      /* control p    */
+               move_rel("u", max(5, (last_line - 5)));
+       else if (in == 17)      /* control q    */
+               ;
+       else if (in == 18)      /* control r    */
+               right(TRUE);
+       else if (in == 19)      /* control s    */
+               ;
+       else if (in == 20)      /* control t    */
+               top();
+       else if (in == 21)      /* control u    */
+               up();
+       else if (in == 22)      /* control v    */
+               undel_word();
+       else if (in == 23)      /* control w    */
+               del_word();
+       else if (in == 24)      /* control x    */
+               search(TRUE);
+       else if (in == 25)      /* control y    */
+               del_line();
+       else if (in == 26)      /* control z    */
+               undel_line();
+       else if (in == 27)      /* control [ (escape)   */
+       {
+               menu_op(main_menu);
+       }       
+}
+
+/*
+ |     Emacs control-key bindings
+ */
+
+void 
+emacs_control()
+{
+       char *string;
+
+       if (in == 1)            /* control a    */
+               bol();
+       else if (in == 2)       /* control b    */
+               left(TRUE);
+       else if (in == 3)       /* control c    */
+       {
+               command_prompt();
+       }
+       else if (in == 4)       /* control d    */
+               del_char();
+       else if (in == 5)       /* control e    */
+               eol();
+       else if (in == 6)       /* control f    */
+               right(TRUE);
+       else if (in == 7)       /* control g    */
+               move_rel("u", max(5, (last_line - 5)));
+       else if (in == 8)       /* control h    */
+               delete(TRUE);
+       else if (in == 9)       /* control i    */
+               ;
+       else if (in == 10)      /* control j    */
+               undel_char();
+       else if (in == 11)      /* control k    */
+               del_line();
+       else if (in == 12)      /* control l    */
+               undel_line();
+       else if (in == 13)      /* control m    */
+               insert_line(TRUE);
+       else if (in == 14)      /* control n    */
+               down();
+       else if (in == 15)      /* control o    */
+       {
+               string = get_string(ascii_code_str, TRUE);
+               if (*string != (char) NULL)
+               {
+                       in = atoi(string);
+                       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+                       insert(in);
+               }
+               free(string);
+       }
+       else if (in == 16)      /* control p    */
+               up();
+       else if (in == 17)      /* control q    */
+               ;
+       else if (in == 18)      /* control r    */
+               undel_word();
+       else if (in == 19)      /* control s    */
+               ;
+       else if (in == 20)      /* control t    */
+               top();
+       else if (in == 21)      /* control u    */
+               bottom();
+       else if (in == 22)      /* control v    */
+               move_rel("d", max(5, (last_line - 5)));
+       else if (in == 23)      /* control w    */
+               del_word();
+       else if (in == 24)      /* control x    */
+               search(TRUE);
+       else if (in == 25)      /* control y    */
+               search_prompt();
+       else if (in == 26)      /* control z    */
+               adv_word();
+       else if (in == 27)      /* control [ (escape)   */
+       {
+               menu_op(main_menu);
+       }       
+}
+
+void 
+bottom()                       /* go to bottom of file                 */
+{
+       while (curr_line->next_line != NULL)
+               curr_line = curr_line->next_line;
+       point = curr_line->line;
+       if (horiz_offset)
+               horiz_offset = 0;
+       position = 1;
+       midscreen(last_line, point);
+       scr_pos = scr_horz;
+}
+
+void 
+top()                          /* go to top of file                    */
+{
+       while (curr_line->prev_line != NULL)
+               curr_line = curr_line->prev_line;
+       point = curr_line->line;
+       if (horiz_offset)
+               horiz_offset = 0;
+       position = 1;
+       midscreen(0, point);
+       scr_pos = scr_horz;
+}
+
+void 
+nextline()                     /* move pointers to start of next line  */
+{
+       curr_line = curr_line->next_line;
+       point = curr_line->line;
+       position = 1;
+       if (scr_vert == last_line)
+       {
+               wmove(text_win, 0,0);
+               wdeleteln(text_win);
+               wmove(text_win, last_line,0);
+               wclrtobot(text_win);
+               draw_line(last_line,0,point,1,curr_line->line_length);
+       }
+       else
+               scr_vert++;
+}
+
+void 
+prevline()                     /* move pointers to start of previous line*/
+{
+       curr_line = curr_line->prev_line;
+       point = curr_line->line;
+       position = 1;
+       if (scr_vert == 0)
+       {
+               winsertln(text_win);
+               draw_line(0,0,point,1,curr_line->line_length);
+       }
+       else
+               scr_vert--;
+       while (position < curr_line->line_length)
+       {
+               position++;
+               point++;
+       }
+}
+
+void 
+left(disp)                             /* move left one character      */
+int disp;
+{
+       if (point != curr_line->line)   /* if not at begin of line      */
+       {
+               if ((ee_chinese) && (position >= 2) && (*(point - 2) > 127))
+               {
+                       point--;
+                       position--;
+               }
+               point--;
+               position--;
+               scanline(point);
+               wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+               scr_pos = scr_horz;
+       }
+       else if (curr_line->prev_line != NULL)
+       {
+               if (!disp)
+               {
+                       curr_line = curr_line->prev_line;
+                       point = curr_line->line + curr_line->line_length;
+                       position = curr_line->line_length;
+                       return;
+               }
+               position = 1;
+               prevline();
+               scanline(point);
+               scr_pos = scr_horz;
+               wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+       }
+}
+
+void 
+right(disp)                            /* move right one character     */
+int disp;
+{
+       if (position < curr_line->line_length)
+       {
+               if ((ee_chinese) && (*point > 127) && 
+                   ((curr_line->line_length - position) >= 2))
+               {
+                       point++;
+                       position++;
+               }
+               point++;
+               position++;
+               scanline(point);
+               wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+               scr_pos = scr_horz;
+       }
+       else if (curr_line->next_line != NULL)
+       {
+               if (!disp)
+               {
+                       curr_line = curr_line->next_line;
+                       point = curr_line->line;
+                       position = 1;
+                       return;
+               }
+               nextline();
+               scr_pos = scr_horz = 0;
+               if (horiz_offset)
+               {
+                       horiz_offset = 0;
+                       midscreen(scr_vert, point);
+               }
+               wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+               position = 1;   
+       }
+}
+
+void 
+find_pos()             /* move to the same column as on other line     */
+{
+       scr_horz = 0;
+       position = 1;
+       while ((scr_horz < scr_pos) && (position < curr_line->line_length))
+       {
+               if (*point == 9)
+                       scr_horz += tabshift(scr_horz);
+               else if (*point < ' ')
+                       scr_horz += 2;
+               else if ((ee_chinese) && (*point > 127) && 
+                   ((curr_line->line_length - position) >= 2))
+               {
+                       scr_horz += 2;
+                       point++;
+                       position++;
+               }
+               else
+                       scr_horz++;
+               position++;
+               point++;
+       }
+       if ((scr_horz - horiz_offset) > last_col)
+       {
+               horiz_offset = (scr_horz - (scr_horz % 8)) - (COLS - 8);
+               midscreen(scr_vert, point);
+       }
+       else if (scr_horz < horiz_offset)
+       {
+               horiz_offset = max(0, (scr_horz - (scr_horz % 8)));
+               midscreen(scr_vert, point);
+       }
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void 
+up()                                   /* move up one line             */
+{
+       if (curr_line->prev_line != NULL)
+       {
+               prevline();
+               point = curr_line->line;
+               find_pos();
+       }
+}
+
+void 
+down()                                 /* move down one line           */
+{
+       if (curr_line->next_line != NULL)
+       {
+               nextline();
+               find_pos();
+       }
+}
+
+void 
+function_key()                         /* process function key         */
+{
+       if (in == KEY_LEFT)
+               left(TRUE);
+       else if (in == KEY_RIGHT)
+               right(TRUE);
+       else if ( in == KEY_HOME)
+               top();
+       else if ( in == KEY_UP)
+               up();
+       else if (in == KEY_DOWN)
+               down();
+       else if (in == KEY_NPAGE)
+               move_rel("d", max( 5, (last_line - 5)));
+       else if (in == KEY_PPAGE)
+               move_rel("u", max(5, (last_line - 5)));
+       else if (in == KEY_DL)
+               del_line();
+       else if (in == KEY_DC)
+               del_char();
+       else if (in == KEY_BACKSPACE)
+               delete(TRUE);
+       else if (in == KEY_IL)
+       {               /* insert a line before current line    */
+               insert_line(TRUE);
+               left(TRUE);
+       }
+       else if (in == KEY_F(1))
+               gold = !gold;
+       else if (in == KEY_F(2))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       undel_line();
+               }
+               else
+                       undel_char();
+       }
+       else if (in == KEY_F(3))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       undel_word();
+               }
+               else
+                       del_word();
+       }
+       else if (in == KEY_F(4))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       paint_info_win();
+                       midscreen(scr_vert, point);
+               }
+               else
+                       adv_word();
+       }
+       else if (in == KEY_F(5))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       search_prompt();
+               }
+               else
+                       search(TRUE);
+       }
+       else if (in == KEY_F(6))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       bottom();
+               }
+               else
+                       top();
+       }
+       else if (in == KEY_F(7))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       eol();
+               }
+               else
+                       bol();
+       }
+       else if (in == KEY_F(8))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       command_prompt();
+               } 
+               else
+                       adv_line();
+       }
+}
+
+void 
+command_prompt()
+{
+       char *cmd_str;
+       int result;
+
+       info_type = COMMANDS;
+       paint_info_win();
+       cmd_str = get_string(command_str, TRUE);
+       if ((result = unique_test(cmd_str, commands)) != 1)
+       {
+               werase(com_win);
+               wmove(com_win, 0, 0);
+               if (result == 0)
+                       wprintw(com_win, unkn_cmd_str, cmd_str);
+               else
+                       wprintw(com_win, non_unique_cmd_msg);
+
+               wrefresh(com_win);
+
+               info_type = CONTROL_KEYS;
+               paint_info_win();
+
+               if (cmd_str != NULL)
+                       free(cmd_str);
+               return;
+       }
+       command(cmd_str);
+       wrefresh(com_win);
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+       info_type = CONTROL_KEYS;
+       paint_info_win();
+       if (cmd_str != NULL)
+               free(cmd_str);
+}
+
+void 
+command(cmd_str1)              /* process commands from keyboard       */
+char *cmd_str1;
+{
+       char *cmd_str2 = NULL;
+       char *cmd_str = cmd_str1;
+
+       clear_com_win = TRUE;
+       if (compare(cmd_str, HELP, FALSE))
+               help();
+       else if (compare(cmd_str, WRITE, FALSE))
+       {
+               if (restrict_mode())
+               {
+                       return;
+               }
+               cmd_str = next_word(cmd_str);
+               if (*cmd_str == (char) NULL)
+               {
+                       cmd_str = cmd_str2 = get_string(file_write_prompt_str, TRUE);
+               }
+               tmp_file = resolve_name(cmd_str);
+               write_file(tmp_file, -1);
+               if (tmp_file != cmd_str)
+                       free(tmp_file);
+       }
+       else if (compare(cmd_str, READ, FALSE))
+       {
+               if (restrict_mode())
+               {
+                       return;
+               }
+               cmd_str = next_word(cmd_str);
+               if (*cmd_str == (char) NULL)
+               {
+                       cmd_str = cmd_str2 = get_string(file_read_prompt_str, TRUE);
+               }
+               tmp_file = cmd_str;
+               recv_file = TRUE;
+               tmp_file = resolve_name(cmd_str);
+               check_fp();
+               if (tmp_file != cmd_str)
+                       free(tmp_file);
+       }
+       else if (compare(cmd_str, LINE, FALSE))
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, line_num_str, curr_line->line_number);
+               wprintw(com_win, line_len_str, curr_line->line_length);
+       }
+       else if (compare(cmd_str, FILE_str, FALSE))
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               if (in_file_name == NULL)
+                       wprintw(com_win, no_file_string);
+               else
+                       wprintw(com_win, current_file_str, in_file_name);
+       }
+       else if ((*cmd_str >= '0') && (*cmd_str <= '9'))
+               goto_line(cmd_str);
+       else if (compare(cmd_str, CHARACTER, FALSE))
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, char_str, *point);
+       }
+       else if (compare(cmd_str, REDRAW, FALSE))
+               redraw();
+       else if (compare(cmd_str, RESEQUENCE, FALSE))
+       {
+               tmp_line = first_line->next_line;
+               while (tmp_line != NULL)
+               {
+               tmp_line->line_number = tmp_line->prev_line->line_number + 1;
+                       tmp_line = tmp_line->next_line;
+               }
+       }
+       else if (compare(cmd_str, AUTHOR, FALSE))
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, "written by Hugh Mahon");
+       }
+       else if (compare(cmd_str, ee_VERSION, FALSE))
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, "%s", version);
+       }
+       else if (compare(cmd_str, CASE, FALSE))
+               case_sen = TRUE;
+       else if (compare(cmd_str, NOCASE, FALSE))
+               case_sen = FALSE;
+       else if (compare(cmd_str, EXPAND, FALSE))
+               expand_tabs = TRUE;
+       else if (compare(cmd_str, NOEXPAND, FALSE))
+               expand_tabs = FALSE;
+       else if (compare(cmd_str, Exit_string, FALSE))
+               ee_finish();
+       else if (compare(cmd_str, chinese_cmd, FALSE))
+       {
+               ee_chinese = TRUE;
+#ifdef NCURSE
+               nc_setattrib(A_NC_BIG5);
+#endif /* NCURSE */
+       }
+       else if (compare(cmd_str, nochinese_cmd, FALSE))
+       {
+               ee_chinese = FALSE;
+#ifdef NCURSE
+               nc_clearattrib(A_NC_BIG5);
+#endif /* NCURSE */
+       }
+       else if (compare(cmd_str, QUIT_string, FALSE))
+               quit(0);
+       else if ((*cmd_str == '<') && (!in_pipe))
+       {
+               in_pipe = TRUE;
+               cmd_str++;
+               if ((*cmd_str == ' ') || (*cmd_str == '\t'))
+                       cmd_str = next_word(cmd_str);
+               command(cmd_str);
+               in_pipe = FALSE;
+       }
+       else if ((*cmd_str == '>') && (!out_pipe))
+       {
+               out_pipe = TRUE;
+               cmd_str++;
+               if ((*cmd_str == ' ') || (*cmd_str == '\t'))
+                       cmd_str = next_word(cmd_str);
+               command(cmd_str);
+               out_pipe = FALSE;
+       }
+       else
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, unkn_cmd_str, cmd_str);
+       }
+       if (cmd_str2 != NULL)
+               free(cmd_str2);
+}
+
+int 
+scan(line, offset, column)     /* determine horizontal position for get_string */
+char *line;
+int offset;
+int column;
+{
+       char *stemp;
+       int i;
+       int j;
+
+       stemp = line;
+       i = 0;
+       j = column;
+       while (i < offset)
+       {
+               i++;
+               j += len_char(*stemp, j);
+               stemp++;
+       }
+       return(j);
+}
+
+char *
+get_string(prompt, advance)    /* read string from input on command line */
+char *prompt;          /* string containing user prompt message        */
+int advance;           /* if true, skip leading spaces and tabs        */
+{
+       char *string;
+       char *tmp_string;
+       char *nam_str;
+       char *g_point;
+       int tmp_int;
+       int g_horz, g_position, g_pos;
+       int esc_flag;
+
+       g_point = tmp_string = malloc(512);
+       wmove(com_win,0,0);
+       wclrtoeol(com_win);
+       waddstr(com_win, prompt);
+       wrefresh(com_win);
+       nam_str = tmp_string;
+       clear_com_win = TRUE;
+       g_horz = g_position = scan(prompt, strlen(prompt), 0);
+       g_pos = 0;
+       do
+       {
+               esc_flag = FALSE;
+               in = wgetch(com_win);
+               if (in == -1)
+                       exit(0);
+               if (((in == 8) || (in == 127) || (in == KEY_BACKSPACE)) && (g_pos > 0))
+               {
+                       tmp_int = g_horz;
+                       g_pos--;
+                       g_horz = scan(g_point, g_pos, g_position);
+                       tmp_int = tmp_int - g_horz;
+                       for (; 0 < tmp_int; tmp_int--)
+                       {
+                               if ((g_horz+tmp_int) < (last_col - 1))
+                               {
+                                       waddch(com_win, '\010');
+                                       waddch(com_win, ' ');
+                                       waddch(com_win, '\010');
+                               }
+                       }
+                       nam_str--;
+               }
+               else if ((in != 8) && (in != 127) && (in != '\n') && (in != '\r') && (in < 256))
+               {
+                       if (in == '\026')       /* control-v, accept next character verbatim    */
+                       {                       /* allows entry of ^m, ^j, and ^h       */
+                               esc_flag = TRUE;
+                               in = wgetch(com_win);
+                               if (in == -1)
+                                       exit(0);
+                       }
+                       *nam_str = in;
+                       g_pos++;
+                       if (((in < ' ') || (in > 126)) && (g_horz < (last_col - 1)))
+                               g_horz += out_char(com_win, in, g_horz);
+                       else
+                       {
+                               g_horz++;
+                               if (g_horz < (last_col - 1))
+                                       waddch(com_win, in);
+                       }
+                       nam_str++;
+               }
+               wrefresh(com_win);
+               if (esc_flag)
+                       in = (char) NULL;
+       } while ((in != '\n') && (in != '\r'));
+       *nam_str = (char) NULL;
+       nam_str = tmp_string;
+       if (((*nam_str == ' ') || (*nam_str == 9)) && (advance))
+               nam_str = next_word(nam_str);
+       string = malloc(strlen(nam_str) + 1);
+       strcpy(string, nam_str);
+       free(tmp_string);
+       wrefresh(com_win);
+       return(string);
+}
+
+int 
+compare(string1, string2, sensitive)   /* compare two strings  */
+char *string1;
+char *string2;
+int sensitive;
+{
+       char *strng1;
+       char *strng2;
+       int tmp;
+       int equal;
+
+       strng1 = string1;
+       strng2 = string2;
+       tmp = 0;
+       if ((strng1 == NULL) || (strng2 == NULL) || (*strng1 == (char) NULL) || (*strng2 == (char) NULL))
+               return(FALSE);
+       equal = TRUE;
+       while (equal)
+       {
+               if (sensitive)
+               {
+                       if (*strng1 != *strng2)
+                               equal = FALSE;
+               }
+               else
+               {
+                       if (toupper(*strng1) != toupper(*strng2))
+                               equal = FALSE;
+               }
+               strng1++;
+               strng2++;
+               if ((*strng1 == (char) NULL) || (*strng2 == (char) NULL) || (*strng1 == ' ') || (*strng2 == ' '))
+                       break;
+               tmp++;
+       }
+       return(equal);
+}
+
+void 
+goto_line(cmd_str)
+char *cmd_str;
+{
+       int number;
+       int i;
+       char *ptr;
+       char *direction;
+       struct text *t_line;
+
+       ptr = cmd_str;
+       i= 0;
+       while ((*ptr >='0') && (*ptr <= '9'))
+       {
+               i= i * 10 + (*ptr - '0');
+               ptr++;
+       }
+       number = i;
+       i = 0;
+       t_line = curr_line;
+       while ((t_line->line_number > number) && (t_line->prev_line != NULL))
+       {
+               i++;
+               t_line = t_line->prev_line;
+               direction = "u";
+       }
+       while ((t_line->line_number < number) && (t_line->next_line != NULL))
+       {
+               i++;
+               direction = "d";
+               t_line = t_line->next_line;
+       }
+       if ((i < 30) && (i > 0))
+       {
+               move_rel(direction, i);
+       }
+       else
+       {
+               curr_line = t_line;
+               point = curr_line->line;
+               position = 1;
+               midscreen((last_line / 2), point);
+               scr_pos = scr_horz;
+       }
+       wmove(com_win, 0, 0);
+       wclrtoeol(com_win);
+       wprintw(com_win, line_num_str, curr_line->line_number);
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void 
+midscreen(line, pnt)   /* put current line in middle of screen */
+int line;
+unsigned char *pnt;
+{
+       struct text *mid_line;
+       int i;
+
+       line = min(line, last_line);
+       mid_line = curr_line;
+       for (i = 0; ((i < line) && (curr_line->prev_line != NULL)); i++)
+               curr_line = curr_line->prev_line;
+       scr_vert = scr_horz = 0;
+       wmove(text_win, 0, 0);
+       draw_screen();
+       scr_vert = i;
+       curr_line = mid_line;
+       scanline(pnt);
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void 
+get_options(numargs, arguments)        /* get arguments from command line      */
+int numargs;
+char *arguments[];
+{
+       char *buff;
+       int count;
+       struct files *temp_names;
+       char *name;
+       char *ptr;
+
+       /*
+        |      see if editor was invoked as 'ree' (restricted mode)
+        */
+
+       if (!(name = strrchr(arguments[0], '/')))
+               name = arguments[0];
+       else
+               name++;
+       if (!strcmp(name, "ree"))
+               restricted = TRUE;
+
+       top_of_stack = NULL;
+       input_file = FALSE;
+       recv_file = FALSE;
+       count = 1;
+       while (count < numargs)
+       {
+               buff = arguments[count];
+               if (!strcmp("-i", buff))
+               {
+                       info_window = FALSE;
+               }
+               else if (!strcmp("-e", buff))
+               {
+                       expand_tabs = FALSE;
+               }
+               else if (!strcmp("-h", buff))
+               {
+                       nohighlight = TRUE;
+               }
+               else if (!strcmp("-?", buff))
+               {
+                       fprintf(stderr, usage0, arguments[0]);
+                       fprintf(stderr, usage1);
+                       fprintf(stderr, usage2);
+                       fprintf(stderr, usage3);
+                       fprintf(stderr, usage4);
+                       exit(1);
+               }
+               else if (*buff == '+')
+               {
+                       buff++;
+                       start_at_line = buff;
+               }
+
+               else
+               {
+                       if (top_of_stack == NULL)
+                       {
+                               temp_names = top_of_stack = name_alloc();
+                       }
+                       else
+                       {
+                               temp_names->next_name = name_alloc();
+                               temp_names = temp_names->next_name;
+                       }
+                       ptr = temp_names->name = malloc(strlen(buff) + 1);
+                       while (*buff != (char) NULL)
+                       {
+                               *ptr = *buff;
+                               buff++;
+                               ptr++;
+                       }
+                       *ptr = (char) NULL;
+                       temp_names->next_name = NULL;
+                       input_file = TRUE;
+                       recv_file = TRUE;
+               }
+               count++;
+       }
+}
+
+void 
+check_fp()             /* open or close files according to flags */
+{
+       int line_num;
+       int temp;
+       struct stat buf;
+
+       clear_com_win = TRUE;
+       tmp_vert = scr_vert;
+       tmp_horz = scr_horz;
+       tmp_line = curr_line;
+       if (input_file)
+       {
+               in_file_name = tmp_file = top_of_stack->name;
+               top_of_stack = top_of_stack->next_name;
+       }
+       temp = stat(tmp_file, &buf);
+       buf.st_mode &= ~07777;
+       if ((temp != -1) && (buf.st_mode != 0100000) && (buf.st_mode != 0))
+       {
+               wprintw(com_win, file_is_dir_msg, tmp_file);
+               wrefresh(com_win);
+               if (input_file)
+               {
+                       quit(0);
+                       return;
+               }
+               else
+                       return;
+       }
+       if ((get_fd = open(tmp_file, O_RDONLY)) == -1)
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               if (input_file)
+                       wprintw(com_win, new_file_msg, tmp_file);
+               else
+                       wprintw(com_win, cant_open_msg, tmp_file);
+               wrefresh(com_win);
+               wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+               wrefresh(text_win);
+               recv_file = FALSE;
+               input_file = FALSE;
+               return;
+       }
+       else
+               get_file(tmp_file);
+
+       recv_file = FALSE;
+       line_num = curr_line->line_number;
+       scr_vert = tmp_vert;
+       scr_horz = tmp_horz;
+       if (input_file)
+               curr_line= first_line;
+       else
+               curr_line = tmp_line;
+       point = curr_line->line;
+       draw_screen();
+       if (input_file)
+       {
+               input_file = FALSE;
+               if (start_at_line != NULL)
+               {
+                       line_num = atoi(start_at_line) - 1;
+                       move_rel("d", line_num);
+                       line_num = 0;
+                       start_at_line = NULL;
+               }
+       }
+       else
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               text_changes = TRUE;
+               if ((tmp_file != NULL) && (*tmp_file != (char) NULL))
+                       wprintw(com_win, file_read_fin_msg, tmp_file);
+       }
+       wrefresh(com_win);
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+       wrefresh(text_win);
+}
+
+void 
+get_file(file_name)    /* read specified file into current buffer      */
+char *file_name;
+{
+       int can_read;           /* file has at least one character      */
+       int length;             /* length of line read by read          */
+       int append;             /* should text be appended to current line */
+       struct text *temp_line;
+       char ro_flag = FALSE;
+
+       if (recv_file)          /* if reading a file                    */
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, reading_file_msg, file_name);
+               if (access(file_name, 2))       /* check permission to write */
+               {
+                       if ((errno == ENOTDIR) || (errno == EACCES) || (errno == EROFS) || (errno == ETXTBSY) || (errno == EFAULT))
+                       {
+                               wprintw(com_win, read_only_msg);
+                               ro_flag = TRUE;
+                       }
+               }
+               wrefresh(com_win);
+       }
+       if (curr_line->line_length > 1) /* if current line is not blank */
+       {
+               insert_line(FALSE);
+               left(FALSE);
+               append = FALSE;
+       }
+       else
+               append = TRUE;
+       can_read = FALSE;               /* test if file has any characters  */
+       while (((length = read(get_fd, in_string, 512)) != 0) && (length != -1))
+       {
+               can_read = TRUE;  /* if set file has at least 1 character   */
+               get_line(length, in_string, &append);
+       }
+       if ((can_read) && (curr_line->line_length == 1))
+       {
+               temp_line = curr_line->prev_line;
+               temp_line->next_line = curr_line->next_line;
+               if (temp_line->next_line != NULL)
+                       temp_line->next_line->prev_line = temp_line;
+               if (curr_line->line != NULL)
+                       free(curr_line->line);
+               free(curr_line);
+               curr_line = temp_line;
+       }
+       if (input_file) /* if this is the file to be edited display number of lines     */
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, file_read_lines_msg, in_file_name, curr_line->line_number);
+               if (ro_flag)
+                       wprintw(com_win, read_only_msg);
+               wrefresh(com_win);
+       }
+       else if (can_read)      /* not input_file and file is non-zero size */
+               text_changes = TRUE;
+
+       if (recv_file)          /* if reading a file                    */
+       {
+               in = EOF;
+       }
+}
+
+void 
+get_line(length, in_string, append)    /* read string and split into lines */
+int length;            /* length of string read by read                */
+unsigned char *in_string;      /* string read by read                          */
+int *append;   /* TRUE if must append more text to end of current line */
+{
+       unsigned char *str1;
+       unsigned char *str2;
+       int num;                /* offset from start of string          */
+       int char_count;         /* length of new line (or added portion */
+       int temp_counter;       /* temporary counter value              */
+       struct text *tline;     /* temporary pointer to new line        */
+       int first_time;         /* if TRUE, the first time through the loop */
+
+       str2 = in_string;
+       num = 0;
+       first_time = TRUE;
+       while (num < length)
+       {
+               if (!first_time)
+               {
+                       if (num < length)
+                       {
+                               str2++;
+                               num++;
+                       }
+               }
+               else
+                       first_time = FALSE;
+               str1 = str2;
+               char_count = 1;
+               /* find end of line     */
+               while ((*str2 != '\n') && (num < length))
+               {
+                       str2++;
+                       num++;
+                       char_count++;
+               }
+               if (!(*append)) /* if not append to current line, insert new one */
+               {
+                       tline = txtalloc();     /* allocate data structure for next line */
+                       tline->line_number = curr_line->line_number + 1;
+                       tline->next_line = curr_line->next_line;
+                       tline->prev_line = curr_line;
+                       curr_line->next_line = tline;
+                       if (tline->next_line != NULL)
+                               tline->next_line->prev_line = tline;
+                       curr_line = tline;
+                       curr_line->line = point = (unsigned char *) malloc(char_count);
+                       curr_line->line_length = char_count;
+                       curr_line->max_length = char_count;
+               }
+               else
+               {
+                       point = resiz_line(char_count, curr_line, curr_line->line_length); 
+                       curr_line->line_length += (char_count - 1);
+               }
+               for (temp_counter = 1; temp_counter < char_count; temp_counter++)
+               {
+                       *point = *str1;
+                       point++;
+                       str1++;
+               }
+               *point = (char) NULL;
+               *append = FALSE;
+               if ((num == length) && (*str2 != '\n'))
+                       *append = TRUE;
+       }
+}
+
+void 
+draw_screen()          /* redraw the screen from current postion       */
+{
+       struct text *temp_line;
+       unsigned char *line_out;
+       int temp_vert;
+
+       temp_line = curr_line;
+       temp_vert = scr_vert;
+       wclrtobot(text_win);
+       while ((temp_line != NULL) && (temp_vert <= last_line))
+       {
+               line_out = temp_line->line;
+               draw_line(temp_vert, 0, line_out, 1, temp_line->line_length);
+               temp_vert++;
+               temp_line = temp_line->next_line;
+       }
+       wmove(text_win, temp_vert, 0);
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void 
+ee_finish()    /* prepare to exit edit session */
+{
+       char *file_name = in_file_name;
+
+       /*
+        |      changes made here should be reflected in the 'save' 
+        |      portion of file_op()
+        */
+
+       if ((file_name == NULL) || (*file_name == (char) NULL))
+               file_name = get_string(save_file_name_prompt, TRUE);
+
+       if ((file_name == NULL) || (*file_name == (char) NULL))
+       {
+               wmove(com_win, 0, 0);
+               wprintw(com_win, file_not_saved_msg);
+               wclrtoeol(com_win);
+               wrefresh(com_win);
+               clear_com_win = TRUE;
+               return;
+       }
+
+       tmp_file = resolve_name(file_name);
+       if (tmp_file != file_name)
+       {
+               free(file_name);
+               file_name = tmp_file;
+       }
+
+       if (write_file(file_name, -1))
+       {
+               text_changes = FALSE;
+               quit(0);
+       }
+}
+
+int 
+quit(noverify)         /* exit editor                  */
+int noverify;
+{
+       char *ans;
+
+       touchwin(text_win);
+       wrefresh(text_win);
+       if ((text_changes) && (!noverify))
+       {
+               ans = get_string(changes_made_prompt, TRUE);
+               if (toupper(*ans) == toupper(*yes_char))
+                       text_changes = FALSE;
+               else
+                       return(0);
+               free(ans);
+       }
+       if (top_of_stack == NULL)
+       {
+               if (info_window)
+                       wrefresh(info_win);
+               wrefresh(com_win);
+               resetty();
+               endwin();
+               putchar('\n');
+               exit(0);
+       }
+       else
+       {
+               delete_text();
+               recv_file = TRUE;
+               input_file = TRUE;
+               check_fp();
+       }
+       return(0);
+}
+
+void 
+edit_abort(arg)
+int arg;
+{
+       wrefresh(com_win);
+       resetty();
+       endwin();
+       putchar('\n');
+       exit(1);
+}
+
+void 
+delete_text()
+{
+       while (curr_line->next_line != NULL)
+               curr_line = curr_line->next_line;
+       while (curr_line != first_line)
+       {
+               free(curr_line->line);
+               curr_line = curr_line->prev_line;
+               free(curr_line->next_line);
+       }
+       curr_line->next_line = NULL;
+       *curr_line->line = (char) NULL;
+       curr_line->line_length = 1;
+       curr_line->line_number = 1;
+       point = curr_line->line;
+       scr_pos = scr_vert = scr_horz = 0;
+       position = 1;
+}
+
+/* If fd >= 0, then use the previously opened file. This is a 
+   hack to get safe tempfile handling in ispell.*/
+int 
+write_file(file_name, fd)
+char *file_name;
+int fd;
+{
+       char cr;
+       char *tmp_point;
+       struct text *out_line;
+       int lines, charac;
+       int temp_pos;
+       int write_flag = TRUE;
+
+       charac = lines = 0;
+       if ((fd < 0) &&
+            ((in_file_name == NULL) || strcmp(in_file_name, file_name)))
+       {
+               if ((temp_fp = fopen(file_name, "r")))
+               {
+                       tmp_point = get_string(file_exists_prompt, TRUE);
+                       if (toupper(*tmp_point) == toupper(*yes_char))
+                               write_flag = TRUE;
+                       else 
+                               write_flag = FALSE;
+                       fclose(temp_fp);
+                       free(tmp_point);
+               }
+       }
+
+       clear_com_win = TRUE;
+
+       if (write_flag)
+       {
+                if (fd < 0) 
+                {
+                        temp_fp = fopen(file_name, "w");
+                }
+                else
+                {
+                        temp_fp = fdopen(fd, "w");
+                }
+
+               if (temp_fp == NULL)
+               {
+                       clear_com_win = TRUE;
+                       wmove(com_win,0,0);
+                       wclrtoeol(com_win);
+                       wprintw(com_win, create_file_fail_msg, file_name);
+                       wrefresh(com_win);
+                       return(FALSE);
+               }
+               else
+               {
+                       wmove(com_win,0,0);
+                       wclrtoeol(com_win);
+                       wprintw(com_win, writing_file_msg, file_name);
+                       wrefresh(com_win);
+                       cr = '\n';
+                       out_line = first_line;
+                       while (out_line != NULL)
+                       {
+                               temp_pos = 1;
+                               tmp_point= out_line->line;
+                               while (temp_pos < out_line->line_length)
+                               {
+                                       putc(*tmp_point, temp_fp);
+                                       tmp_point++;
+                                       temp_pos++;
+                               }
+                               charac += out_line->line_length;
+                               out_line = out_line->next_line;
+                               putc(cr, temp_fp);
+                               lines++;
+                       }
+                       fclose(temp_fp);
+                       wmove(com_win,0,0);
+                       wclrtoeol(com_win);
+                       wprintw(com_win, file_written_msg, file_name, lines, charac);
+                       wrefresh(com_win);
+                       return(TRUE);
+               }
+       }
+       else
+               return(FALSE);
+}
+
+int 
+search(display_message)                /* search for string in srch_str        */
+int display_message;
+{
+       int lines_moved;
+       int iter;
+       int found;
+
+       if ((srch_str == NULL) || (*srch_str == (char) NULL))
+               return(FALSE);
+       if (display_message)
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, searching_msg);
+               wrefresh(com_win);
+               clear_com_win = TRUE;
+       }
+       lines_moved = 0;
+       found = FALSE;
+       srch_line = curr_line;
+       srch_1 = point;
+       if (position < curr_line->line_length)
+               srch_1++;
+       iter = position + 1;
+       while ((!found) && (srch_line != NULL))
+       {
+               while ((iter < srch_line->line_length) && (!found))
+               {
+                       srch_2 = srch_1;
+                       if (case_sen)   /* if case sensitive            */
+                       {
+                               srch_3 = srch_str;
+                       while ((*srch_2 == *srch_3) && (*srch_3 != (char) NULL))
+                               {
+                                       found = TRUE;
+                                       srch_2++;
+                                       srch_3++;
+                               }       /* end while    */
+                       }
+                       else            /* if not case sensitive        */
+                       {
+                               srch_3 = u_srch_str;
+                       while ((toupper(*srch_2) == *srch_3) && (*srch_3 != (char) NULL))
+                               {
+                                       found = TRUE;
+                                       srch_2++;
+                                       srch_3++;
+                               }
+                       }       /* end else     */
+                       if (!((*srch_3 == (char) NULL) && (found)))
+                       {
+                               found = FALSE;
+                               if (iter < srch_line->line_length)
+                                       srch_1++;
+                               iter++;
+                       }
+               }
+               if (!found)
+               {
+                       srch_line = srch_line->next_line;
+                       if (srch_line != NULL)
+                               srch_1 = srch_line->line;
+                       iter = 1;
+                       lines_moved++;
+               }
+       }
+       if (found)
+       {
+               if (display_message)
+               {
+                       wmove(com_win, 0, 0);
+                       wclrtoeol(com_win);
+                       wrefresh(com_win);
+               }
+               if (lines_moved == 0)
+               {
+                       while (position < iter)
+                               right(TRUE);
+               }
+               else
+               {
+                       if (lines_moved < 30)
+                       {
+                               move_rel("d", lines_moved);
+                               while (position < iter)
+                                       right(TRUE);
+                       }
+                       else 
+                       {
+                               curr_line = srch_line;
+                               point = srch_1;
+                               position = iter;
+                               scanline(point);
+                               scr_pos = scr_horz;
+                               midscreen((last_line / 2), point);
+                       }
+               }
+       }
+       else
+       {
+               if (display_message)
+               {
+                       wmove(com_win, 0, 0);
+                       wclrtoeol(com_win);
+                       wprintw(com_win, str_not_found_msg, srch_str);
+                       wrefresh(com_win);
+               }
+               wmove(text_win, scr_vert,(scr_horz - horiz_offset));
+       }
+       return(found);
+}
+
+void 
+search_prompt()                /* prompt and read search string (srch_str)     */
+{
+       if (srch_str != NULL)
+               free(srch_str);
+       if ((u_srch_str != NULL) && (*u_srch_str != (char) NULL))
+               free(u_srch_str);
+       srch_str = get_string(search_prompt_str, FALSE);
+       gold = FALSE;
+       srch_3 = srch_str;
+       srch_1 = u_srch_str = malloc(strlen(srch_str) + 1);
+       while (*srch_3 != (char) NULL)
+       {
+               *srch_1 = toupper(*srch_3);
+               srch_1++;
+               srch_3++;
+       }
+       *srch_1 = (char) NULL;
+       search(TRUE);
+}
+
+void 
+del_char()                     /* delete current character     */
+{
+       in = 8;  /* backspace */
+       if (position < curr_line->line_length)  /* if not end of line   */
+       {
+               if ((ee_chinese) && (*point > 127) && 
+                   ((curr_line->line_length - position) >= 2))
+               {
+                       point++;
+                       position++;
+               }
+               position++;
+               point++;
+               scanline(point);
+               delete(TRUE);
+       }
+       else
+       {
+               right(FALSE);
+               delete(FALSE);
+       }
+}
+
+void 
+undel_char()                   /* undelete last deleted character      */
+{
+       if (d_char[0] == '\n')  /* insert line if last del_char deleted eol */
+               insert_line(TRUE);
+       else
+       {
+               in = d_char[0];
+               insert(in);
+               if (d_char[1] != (unsigned char) NULL)
+               {
+                       in = d_char[1];
+                       insert(in);
+               }
+       }
+}
+
+void 
+del_word()                     /* delete word in front of cursor       */
+{
+       int tposit;
+       int difference;
+       unsigned char *d_word2;
+       unsigned char *d_word3;
+       unsigned char tmp_char[3];
+
+       if (d_word != NULL)
+               free(d_word);
+       d_word = malloc(curr_line->line_length);
+       tmp_char[0] = d_char[0];
+       tmp_char[1] = d_char[1];
+       tmp_char[2] = d_char[2];
+       d_word3 = point;
+       d_word2 = d_word;
+       tposit = position;
+       while ((tposit < curr_line->line_length) && 
+                               ((*d_word3 != ' ') && (*d_word3 != '\t')))
+       {
+               tposit++;
+               *d_word2 = *d_word3;
+               d_word2++;
+               d_word3++;
+       }
+       while ((tposit < curr_line->line_length) && 
+                               ((*d_word3 == ' ') || (*d_word3 == '\t')))
+       {
+               tposit++;
+               *d_word2 = *d_word3;
+               d_word2++;
+               d_word3++;
+       }
+       *d_word2 = (char) NULL;
+       d_wrd_len = difference = d_word2 - d_word;
+       d_word2 = point;
+       while (tposit < curr_line->line_length)
+       {
+               tposit++;
+               *d_word2 = *d_word3;
+               d_word2++;
+               d_word3++;
+       }
+       curr_line->line_length -= difference;
+       *d_word2 = (char) NULL;
+       draw_line(scr_vert, scr_horz,point,position,curr_line->line_length);
+       d_char[0] = tmp_char[0];
+       d_char[1] = tmp_char[1];
+       d_char[2] = tmp_char[2];
+       text_changes = TRUE;
+       formatted = FALSE;
+}
+
+void 
+undel_word()           /* undelete last deleted word           */
+{
+       int temp;
+       int tposit;
+       unsigned char *tmp_old_ptr;
+       unsigned char *tmp_space;
+       unsigned char *tmp_ptr;
+       unsigned char *d_word_ptr;
+
+       /*
+        |      resize line to handle undeleted word
+        */
+       if ((curr_line->max_length - (curr_line->line_length + d_wrd_len)) < 5)
+               point = resiz_line(d_wrd_len, curr_line, position);
+       tmp_ptr = tmp_space = malloc(curr_line->line_length + d_wrd_len);
+       d_word_ptr = d_word;
+       temp = 1;
+       /*
+        |      copy d_word contents into temp space
+        */
+       while (temp <= d_wrd_len)
+       {
+               temp++;
+               *tmp_ptr = *d_word_ptr;
+               tmp_ptr++;
+               d_word_ptr++;
+       }
+       tmp_old_ptr = point;
+       tposit = position;
+       /*
+        |      copy contents of line from curent position to eol into 
+        |      temp space
+        */
+       while (tposit < curr_line->line_length)
+       {
+               temp++;
+               tposit++;
+               *tmp_ptr = *tmp_old_ptr;
+               tmp_ptr++;
+               tmp_old_ptr++;
+       }
+       curr_line->line_length += d_wrd_len;
+       tmp_old_ptr = point;
+       *tmp_ptr = (char) NULL;
+       tmp_ptr = tmp_space;
+       tposit = 1;
+       /*
+        |      now copy contents from temp space back to original line
+        */
+       while (tposit < temp)
+       {
+               tposit++;
+               *tmp_old_ptr = *tmp_ptr;
+               tmp_ptr++;
+               tmp_old_ptr++;
+       }
+       *tmp_old_ptr = (char) NULL;
+       free(tmp_space);
+       draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
+}
+
+void 
+del_line()                     /* delete from cursor to end of line    */
+{
+       unsigned char *dl1;
+       unsigned char *dl2;
+       int tposit;
+
+       if (d_line != NULL)
+               free(d_line);
+       d_line = malloc(curr_line->line_length);
+       dl1 = d_line;
+       dl2 = point;
+       tposit = position;
+       while (tposit < curr_line->line_length)
+       {
+               *dl1 = *dl2;
+               dl1++;
+               dl2++;
+               tposit++;
+       }
+       dlt_line->line_length = 1 + tposit - position;
+       *dl1 = (char) NULL;
+       *point = (char) NULL;
+       curr_line->line_length = position;
+       wclrtoeol(text_win);
+       if (curr_line->next_line != NULL)
+       {
+               right(FALSE);
+               delete(FALSE);
+       }
+       text_changes = TRUE;
+}
+
+void 
+undel_line()                   /* undelete last deleted line           */
+{
+       unsigned char *ud1;
+       unsigned char *ud2;
+       int tposit;
+
+       if (dlt_line->line_length == 0)
+               return;
+
+       insert_line(TRUE);
+       left(TRUE);
+       point = resiz_line(dlt_line->line_length, curr_line, position);
+       curr_line->line_length += dlt_line->line_length - 1;
+       ud1 = point;
+       ud2 = d_line;
+       tposit = 1;
+       while (tposit < dlt_line->line_length)
+       {
+               tposit++;
+               *ud1 = *ud2;
+               ud1++;
+               ud2++;
+       }
+       *ud1 = (char) NULL;
+       draw_line(scr_vert, scr_horz,point,position,curr_line->line_length);
+}
+
+void 
+adv_word()                     /* advance to next word         */
+{
+while ((position < curr_line->line_length) && ((*point != 32) && (*point != 9)))
+               right(TRUE);
+while ((position < curr_line->line_length) && ((*point == 32) || (*point == 9)))
+               right(TRUE);
+}
+
+void 
+move_rel(direction, lines)     /* move relative to current line        */
+char *direction;
+int lines;
+{
+       int i;
+       char *tmp;
+
+       if (*direction == 'u')
+       {
+               scr_pos = 0;
+               while (position > 1)
+                       left(TRUE);
+               for (i = 0; i < lines; i++)
+               {
+                       up();
+               }
+               if ((last_line > 5) && ( scr_vert < 4))
+               {
+                       tmp = point;
+                       tmp_line = curr_line;
+                       for (i= 0;(i<5)&&(curr_line->prev_line != NULL); i++)
+                       {
+                               up();
+                       }
+                       scr_vert = scr_vert + i;
+                       curr_line = tmp_line;
+                       point = tmp;
+                       scanline(point);
+               }
+       }
+       else
+       {
+               if ((position != 1) && (curr_line->next_line != NULL))
+               {
+                       nextline();
+                       scr_pos = scr_horz = 0;
+                       if (horiz_offset)
+                       {
+                               horiz_offset = 0;
+                               midscreen(scr_vert, point);
+                       }
+               }
+               else
+                       adv_line();
+               for (i = 1; i < lines; i++)
+               {
+                       down();
+               }
+               if ((last_line > 10) && (scr_vert > (last_line - 5)))
+               {
+                       tmp = point;
+                       tmp_line = curr_line;
+                       for (i=0; (i<5) && (curr_line->next_line != NULL); i++)
+                       {
+                               down();
+                       }
+                       scr_vert = scr_vert - i;
+                       curr_line = tmp_line;
+                       point = tmp;
+                       scanline(point);
+               }
+       }
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void 
+eol()                          /* go to end of line                    */
+{
+       if (position < curr_line->line_length)
+       {
+               while (position < curr_line->line_length)
+                       right(TRUE);
+       }
+       else if (curr_line->next_line != NULL)
+       {
+               right(TRUE);
+               while (position < curr_line->line_length)
+                       right(TRUE);
+       }
+}
+
+void 
+bol()                          /* move to beginning of line    */
+{
+       if (point != curr_line->line)
+       {
+               while (point != curr_line->line)
+                       left(TRUE);
+       }
+       else if (curr_line->prev_line != NULL)
+       {
+               scr_pos = 0;
+               up();
+       }
+}
+
+void 
+adv_line()     /* advance to beginning of next line    */
+{
+       if ((point != curr_line->line) || (scr_pos > 0))
+       {
+               while (position < curr_line->line_length)
+                       right(TRUE);
+               right(TRUE);
+       }
+       else if (curr_line->next_line != NULL)
+       {
+               scr_pos = 0;
+               down();
+       }
+}
+
+void 
+set_up_term()          /* set up the terminal for operating with ae    */
+{
+       if (!curses_initialized)
+       {
+               initscr();
+               savetty();
+               noecho();
+               raw();
+               nonl();
+               curses_initialized = TRUE;
+       }
+
+       if (((LINES > 15) && (COLS >= 80)) && info_window)
+               last_line = LINES - 8;
+       else
+       {
+               info_window = FALSE;
+               last_line = LINES - 2;
+       }
+
+       idlok(stdscr, TRUE);
+       com_win = newwin(1, COLS, (LINES - 1), 0);
+       keypad(com_win, TRUE);
+       idlok(com_win, TRUE);
+       wrefresh(com_win);
+       if (!info_window)
+               text_win = newwin((LINES - 1), COLS, 0, 0);
+       else
+               text_win = newwin((LINES - 7), COLS, 6, 0);
+       keypad(text_win, TRUE);
+       idlok(text_win, TRUE);
+       wrefresh(text_win);
+       help_win = newwin((LINES - 1), COLS, 0, 0);
+       keypad(help_win, TRUE);
+       idlok(help_win, TRUE);
+       if (info_window)
+       {
+               info_type = CONTROL_KEYS;
+               info_win = newwin(6, COLS, 0, 0);
+               werase(info_win);
+               paint_info_win();
+       }
+
+       last_col = COLS - 1;
+       local_LINES = LINES;
+       local_COLS = COLS;
+
+#ifdef NCURSE
+       if (ee_chinese)
+               nc_setattrib(A_NC_BIG5);
+#endif /* NCURSE */
+
+}
+
+void 
+resize_check()
+{
+       if ((LINES == local_LINES) && (COLS == local_COLS))
+               return;
+
+       if (info_window)
+               delwin(info_win);
+       delwin(text_win);
+       delwin(com_win);
+       delwin(help_win);
+       set_up_term();
+       redraw();
+       wrefresh(text_win);
+}
+
+static char item_alpha[] = "abcdefghijklmnopqrstuvwxyz0123456789 ";
+
+int 
+menu_op(menu_list)
+struct menu_entries menu_list[];
+{
+       WINDOW *temp_win;
+       int max_width, max_height;
+       int x_off, y_off;
+       int counter;
+       int length;
+       int input;
+       int temp;
+       int list_size;
+       int top_offset;         /* offset from top where menu items start */
+       int vert_pos;           /* vertical position                      */
+       int vert_size;          /* vertical size for menu list item display */
+       int off_start = 1;      /* offset from start of menu items to start display */
+
+
+       /*
+        |      determine number and width of menu items
+        */
+
+       list_size = 1;
+       while (menu_list[list_size + 1].item_string != NULL)
+               list_size++;
+       max_width = 0;
+       for (counter = 0; counter <= list_size; counter++)
+       {
+               if ((length = strlen(menu_list[counter].item_string)) > max_width)
+                       max_width = length;
+       }
+       max_width += 3;
+       max_width = max(max_width, strlen(menu_cancel_msg));
+       max_width = max(max_width, max(strlen(more_above_str), strlen(more_below_str)));
+       max_width += 6;
+
+       /*
+        |      make sure that window is large enough to handle menu
+        |      if not, print error message and return to calling function
+        */
+
+       if (max_width > COLS)
+       {
+               wmove(com_win, 0, 0);
+               werase(com_win);
+               wprintw(com_win, menu_too_lrg_msg);
+               wrefresh(com_win);
+               clear_com_win = TRUE;
+               return(0);
+       }
+
+       top_offset = 0;
+
+       if (list_size > LINES)
+       {
+               max_height = LINES;
+               if (max_height > 11)
+                       vert_size = max_height - 8;
+               else
+                       vert_size = max_height;
+       }
+       else
+       {
+               vert_size = list_size;
+               max_height = list_size;
+       }
+
+       if (LINES >= (vert_size + 8))
+       {
+               if (menu_list[0].argument != MENU_WARN)
+                       max_height = vert_size + 8;
+               else
+                       max_height = vert_size + 7;
+               top_offset = 4;
+       }
+       x_off = (COLS - max_width) / 2;
+       y_off = (LINES - max_height - 1) / 2;
+       temp_win = newwin(max_height, max_width, y_off, x_off);
+       keypad(temp_win, TRUE);
+
+       paint_menu(menu_list, max_width, max_height, list_size, top_offset, temp_win, off_start, vert_size);
+
+       counter = 1;
+       vert_pos = 0;
+       do
+       {
+               if (off_start > 2)
+                       wmove(temp_win, (1 + counter + top_offset - off_start), 3);
+               else
+                       wmove(temp_win, (counter + top_offset - off_start), 3);
+
+               wrefresh(temp_win);
+               in = wgetch(temp_win);
+               input = in;
+               if (input == -1)
+                       exit(0);
+
+               if (((tolower(input) >= 'a') && (tolower(input) <= 'z')) || 
+                   ((input >= '0') && (input <= '9')))
+               {
+                       if ((tolower(input) >= 'a') && (tolower(input) <= 'z'))
+                       {
+                               temp = 1 + tolower(input) - 'a';
+                       }
+                       else if ((input >= '0') && (input <= '9'))
+                       {
+                               temp = (2 + 'z' - 'a') + (input - '0');
+                       }
+
+                       if (temp <= list_size)
+                       {
+                               input = '\n';
+                               counter = temp;
+                       }
+               }
+               else
+               {               
+                       switch (input)
+                       {
+                               case ' ':       /* space        */
+                               case '\004':    /* ^d, down     */
+                               case KEY_RIGHT:
+                               case KEY_DOWN:
+                                       counter++;
+                                       if (counter > list_size)
+                                               counter = 1;
+                                       break;
+                               case '\010':    /* ^h, backspace*/
+                               case '\025':    /* ^u, up       */
+                               case 127:       /* ^?, delete   */
+                               case KEY_BACKSPACE:
+                               case KEY_LEFT:
+                               case KEY_UP:
+                                       counter--;
+                                       if (counter == 0)
+                                               counter = list_size;
+                                       break;
+                               case '\033':    /* escape key   */
+                                       if (menu_list[0].argument != MENU_WARN)
+                                               counter = 0;
+                                       break;
+                               case '\014':    /* ^l           */
+                               case '\022':    /* ^r, redraw   */
+                                       paint_menu(menu_list, max_width, max_height, 
+                                               list_size, top_offset, temp_win, 
+                                               off_start, vert_size);
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+       
+               if (((list_size - off_start) >= (vert_size - 1)) && 
+                       (counter > (off_start + vert_size - 3)) && 
+                               (off_start > 1))
+               {
+                       if (counter == list_size)
+                               off_start = (list_size - vert_size) + 2;
+                       else
+                               off_start++;
+
+                       paint_menu(menu_list, max_width, max_height, 
+                                  list_size, top_offset, temp_win, off_start, 
+                                  vert_size);
+               }
+               else if ((list_size != vert_size) && 
+                               (counter > (off_start + vert_size - 2)))
+               {
+                       if (counter == list_size)
+                               off_start = 2 + (list_size - vert_size);
+                       else if (off_start == 1)
+                               off_start = 3;
+                       else
+                               off_start++;
+
+                       paint_menu(menu_list, max_width, max_height, 
+                                  list_size, top_offset, temp_win, off_start, 
+                                  vert_size);
+               }
+               else if (counter < off_start)
+               {
+                       if (counter <= 2)
+                               off_start = 1;
+                       else
+                               off_start = counter;
+
+                       paint_menu(menu_list, max_width, max_height, 
+                                  list_size, top_offset, temp_win, off_start, 
+                                  vert_size);
+               }
+       }
+       while ((input != '\r') && (input != '\n') && (counter != 0));
+
+       werase(temp_win);
+       wrefresh(temp_win);
+       delwin(temp_win);
+
+       if ((menu_list[counter].procedure != NULL) || 
+           (menu_list[counter].iprocedure != NULL) || 
+           (menu_list[counter].nprocedure != NULL))
+       {
+               if (menu_list[counter].argument != -1)
+                       (*menu_list[counter].iprocedure)(menu_list[counter].argument);
+               else if (menu_list[counter].ptr_argument != NULL)
+                       (*menu_list[counter].procedure)(menu_list[counter].ptr_argument);
+               else
+                       (*menu_list[counter].nprocedure)();
+       }
+
+       if (info_window)
+               paint_info_win();
+       redraw();
+
+       return(counter);
+}
+
+void 
+paint_menu(menu_list, max_width, max_height, list_size, top_offset, menu_win, 
+          off_start, vert_size)
+struct menu_entries menu_list[];
+int max_width, max_height, list_size, top_offset;
+WINDOW *menu_win;
+int off_start, vert_size;
+{
+       int counter, temp_int;
+
+       werase(menu_win);
+
+       /*
+        |      output top and bottom portions of menu box only if window 
+        |      large enough 
+        */
+
+       if (max_height > vert_size)
+       {
+               wmove(menu_win, 1, 1);
+               if (!nohighlight)
+                       wstandout(menu_win);
+               waddch(menu_win, '+');
+               for (counter = 0; counter < (max_width - 4); counter++)
+                       waddch(menu_win, '-');
+               waddch(menu_win, '+');
+
+               wmove(menu_win, (max_height - 2), 1);
+               waddch(menu_win, '+');
+               for (counter = 0; counter < (max_width - 4); counter++)
+                       waddch(menu_win, '-');
+               waddch(menu_win, '+');
+               wstandend(menu_win);
+               wmove(menu_win, 2, 3);
+               waddstr(menu_win, menu_list[0].item_string);
+               wmove(menu_win, (max_height - 3), 3);
+               if (menu_list[0].argument != MENU_WARN)
+                       waddstr(menu_win, menu_cancel_msg);
+       }
+       if (!nohighlight)
+               wstandout(menu_win);
+
+       for (counter = 0; counter < (vert_size + top_offset); counter++)
+       {
+               if (top_offset == 4)
+               {
+                       temp_int = counter + 2;
+               }
+               else
+                       temp_int = counter;
+
+               wmove(menu_win, temp_int, 1);
+               waddch(menu_win, '|');
+               wmove(menu_win, temp_int, (max_width - 2));
+               waddch(menu_win, '|');
+       }
+       wstandend(menu_win);
+
+       if (list_size > vert_size)
+       {
+               if (off_start >= 3)
+               {
+                       temp_int = 1;
+                       wmove(menu_win, top_offset, 3);
+                       waddstr(menu_win, more_above_str);
+               }
+               else
+                       temp_int = 0;
+
+               for (counter = off_start; 
+                       ((temp_int + counter - off_start) < (vert_size - 1));
+                               counter++)
+               {
+                       wmove(menu_win, (top_offset + temp_int + 
+                                               (counter - off_start)), 3);
+                       if (list_size > 1)
+                               wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
+                       waddstr(menu_win, menu_list[counter].item_string);
+               }
+
+               wmove(menu_win, (top_offset + (vert_size - 1)), 3);
+
+               if (counter == list_size)
+               {
+                       if (list_size > 1)
+                               wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
+                       wprintw(menu_win, menu_list[counter].item_string);
+               }
+               else
+                       wprintw(menu_win, more_below_str);
+       }
+       else
+       {
+               for (counter = 1; counter <= list_size; counter++)
+               {
+                       wmove(menu_win, (top_offset + counter - 1), 3);
+                       if (list_size > 1)
+                               wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
+                       waddstr(menu_win, menu_list[counter].item_string);
+               }
+       }
+}
+
+void 
+help()
+{
+       int counter;
+
+       werase(help_win);
+       clearok(help_win, TRUE);
+       for (counter = 0; counter < 22; counter++)
+       {
+               wmove(help_win, counter, 0);
+               waddstr(help_win, (emacs_keys_mode) ? 
+                       emacs_help_text[counter] : help_text[counter]);
+       }
+       wrefresh(help_win);
+       werase(com_win);
+       wmove(com_win, 0, 0);
+       wprintw(com_win, press_any_key_msg);
+       wrefresh(com_win);
+       counter = wgetch(com_win);
+       if (counter == -1)
+               exit(0);
+       werase(com_win);
+       wmove(com_win, 0, 0);
+       werase(help_win);
+       wrefresh(help_win);
+       wrefresh(com_win);
+       redraw();
+}
+
+void 
+paint_info_win()
+{
+       int counter;
+
+       if (!info_window)
+               return;
+
+       werase(info_win);
+       for (counter = 0; counter < 5; counter++)
+       {
+               wmove(info_win, counter, 0);
+               wclrtoeol(info_win);
+               if (info_type == CONTROL_KEYS)
+                       waddstr(info_win, (emacs_keys_mode) ? 
+                         emacs_control_keys[counter] : control_keys[counter]);
+               else if (info_type == COMMANDS)
+                       waddstr(info_win, command_strings[counter]);
+       }
+       wmove(info_win, 5, 0);
+       if (!nohighlight)
+               wstandout(info_win);
+       waddstr(info_win, "===============================================================================");
+       wstandend(info_win);
+       wrefresh(info_win);
+}
+
+void 
+no_info_window()
+{
+       if (!info_window)
+               return;
+       delwin(info_win);
+       delwin(text_win);
+       info_window = FALSE;
+       last_line = LINES - 2;
+       text_win = newwin((LINES - 1), COLS, 0, 0);
+       keypad(text_win, TRUE);
+       idlok(text_win, TRUE);
+       clearok(text_win, TRUE);
+       midscreen(scr_vert, point);
+       wrefresh(text_win);
+       clear_com_win = TRUE;
+}
+
+void 
+create_info_window()
+{
+       if (info_window)
+               return;
+       last_line = LINES - 8;
+       delwin(text_win);
+       text_win = newwin((LINES - 7), COLS, 6, 0);
+       keypad(text_win, TRUE);
+       idlok(text_win, TRUE);
+       werase(text_win);
+       info_window = TRUE;
+       info_win = newwin(6, COLS, 0, 0);
+       werase(info_win);
+       info_type = CONTROL_KEYS;
+       midscreen(min(scr_vert, last_line), point);
+       clearok(info_win, TRUE);
+       paint_info_win();
+       wrefresh(text_win);
+       clear_com_win = TRUE;
+}
+
+int 
+file_op(arg)
+int arg;
+{
+       char *string;
+       int flag;
+
+       if (restrict_mode())
+       {
+               return(0);
+       }
+
+       if (arg == READ_FILE)
+       {
+               string = get_string(file_read_prompt_str, TRUE);
+               recv_file = TRUE;
+               tmp_file = resolve_name(string);
+               check_fp();
+               if (tmp_file != string)
+                       free(tmp_file);
+               free(string);
+       }
+       else if (arg == WRITE_FILE)
+       {
+               string = get_string(file_write_prompt_str, TRUE);
+               tmp_file = resolve_name(string);
+               write_file(tmp_file, -1);
+               if (tmp_file != string)
+                       free(tmp_file);
+               free(string);
+       }
+       else if (arg == SAVE_FILE)
+       {
+       /*
+        |      changes made here should be reflected in ee_finish()
+        */
+
+               if (in_file_name)
+                       flag = TRUE;
+               else
+                       flag = FALSE;
+
+               string = in_file_name;
+               if ((string == NULL) || (*string == (char) NULL))
+                       string = get_string(save_file_name_prompt, TRUE);
+               if ((string == NULL) || (*string == (char) NULL))
+               {
+                       wmove(com_win, 0, 0);
+                       wprintw(com_win, file_not_saved_msg);
+                       wclrtoeol(com_win);
+                       wrefresh(com_win);
+                       clear_com_win = TRUE;
+                       return(0);
+               }
+               if (!flag)
+               {
+                       tmp_file = resolve_name(string);
+                       if (tmp_file != string)
+                       {
+                               free(string);
+                               string = tmp_file;
+                       }
+               }
+               if (write_file(string, -1))
+               {
+                       in_file_name = string;
+                       text_changes = FALSE;
+               }
+               else if (!flag)
+                       free(string);
+       }
+       return(0);
+}
+
+void 
+leave_op()
+{
+       if (text_changes)
+       {
+               menu_op(leave_menu);
+       }
+       else
+               quit(TRUE);
+}
+
+void 
+redraw()
+{
+       if (info_window)
+        {
+                clearok(info_win, TRUE);
+               paint_info_win();
+        }
+        else
+               clearok(text_win, TRUE);
+       midscreen(scr_vert, point);
+}
+
+/*
+ |     The following routines will "format" a paragraph (as defined by a 
+ |     block of text with blank lines before and after the block).
+ */
+
+int 
+Blank_Line(test_line)  /* test if line has any non-space characters    */
+struct text *test_line;
+{
+       unsigned char *line;
+       int length;
+       
+       if (test_line == NULL)
+               return(TRUE);
+
+       length = 1;
+       line = test_line->line;
+
+       /*
+        |      To handle troff/nroff documents, consider a line with a 
+        |      period ('.') in the first column to be blank.  To handle mail 
+        |      messages with included text, consider a line with a '>' blank.
+        */
+
+       if ((*line == '.') || (*line == '>'))
+               return(TRUE);
+
+       while (((*line == ' ') || (*line == '\t')) && (length < test_line->line_length))
+       {
+               length++;
+               line++;
+       }
+       if (length != test_line->line_length)
+               return(FALSE);
+       else
+               return(TRUE);
+}
+
+void 
+Format()       /* format the paragraph according to set margins        */
+{
+       int string_count;
+       int offset;
+       int temp_case;
+       int status;
+       int tmp_af;
+       int counter;
+       unsigned char *line;
+       unsigned char *tmp_srchstr;
+       unsigned char *temp1, *temp2;
+       unsigned char *temp_dword;
+       unsigned char temp_d_char[3];
+
+       temp_d_char[0] = d_char[0];
+       temp_d_char[1] = d_char[1];
+       temp_d_char[2] = d_char[2];
+
+/*
+ |     if observ_margins is not set, or the current line is blank, 
+ |     do not format the current paragraph
+ */
+
+       if ((!observ_margins) || (Blank_Line(curr_line)))
+               return;
+
+/*
+ |     save the currently set flags, and clear them
+ */
+
+       wmove(com_win, 0, 0);
+       wclrtoeol(com_win);
+       wprintw(com_win, formatting_msg);
+       wrefresh(com_win);
+
+/*
+ |     get current position in paragraph, so after formatting, the cursor 
+ |     will be in the same relative position
+ */
+
+       tmp_af = auto_format;
+       auto_format = FALSE;
+       offset = position;
+       if (position != 1)
+               prev_word();
+       temp_dword = d_word;
+       d_word = NULL;
+       temp_case = case_sen;
+       case_sen = TRUE;
+       tmp_srchstr = srch_str;
+       temp2 = srch_str = (unsigned char *) malloc(1 + curr_line->line_length - position);
+       if ((*point == ' ') || (*point == '\t'))
+               adv_word();
+       offset -= position;
+       counter = position;
+       line = temp1 = point;
+       while ((*temp1 != (char) NULL) && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length))
+       {
+               *temp2 = *temp1;
+               temp2++;
+               temp1++;
+               counter++;
+       }
+       *temp2 = (char) NULL;
+       if (position != 1)
+               bol();
+       while (!Blank_Line(curr_line->prev_line))
+               bol();
+       string_count = 0;
+       status = TRUE;
+       while ((line != point) && (status))
+       {
+               status = search(FALSE);
+               string_count++;
+       }
+
+       wmove(com_win, 0, 0);
+       wclrtoeol(com_win);
+       wprintw(com_win, formatting_msg);
+       wrefresh(com_win);
+
+/*
+ |     now get back to the start of the paragraph to start formatting
+ */
+
+       if (position != 1)
+               bol();
+       while (!Blank_Line(curr_line->prev_line))
+               bol();
+
+       observ_margins = FALSE;
+
+/*
+ |     Start going through lines, putting spaces at end of lines if they do 
+ |     not already exist.  Append lines together to get one long line, and 
+ |     eliminate spacing at begin of lines.
+ */
+
+       while (!Blank_Line(curr_line->next_line))
+       {
+               eol();
+               left(TRUE);
+               if (*point != ' ')
+               {
+                       right(TRUE);
+                       insert(' ');
+               }
+               else
+                       right(TRUE);
+               del_char();
+               if ((*point == ' ') || (*point == '\t'))
+                       del_word();
+       }
+
+/*
+ |     Now there is one long line.  Eliminate extra spaces within the line
+ |     after the first word (so as not to blow away any indenting the user 
+ |     may have put in).
+ */
+
+       bol();
+       adv_word();
+       while (position < curr_line->line_length)
+       {
+               if ((*point == ' ') && (*(point + 1) == ' '))
+                       del_char();
+               else
+                       right(TRUE);
+       }
+
+/*
+ |     Now make sure there are two spaces after a '.'.
+ */
+
+       bol();
+       while (position < curr_line->line_length)
+       {
+               if ((*point == '.') && (*(point + 1) == ' '))
+               {
+                       right(TRUE);
+                       insert(' ');
+                       insert(' ');
+                       while (*point == ' ')
+                               del_char();
+               }
+               right(TRUE);
+       }
+
+       observ_margins = TRUE;
+       bol();
+
+       wmove(com_win, 0, 0);
+       wclrtoeol(com_win);
+       wprintw(com_win, formatting_msg);
+       wrefresh(com_win);
+
+/*
+ |     create lines between margins
+ */
+
+       while (position < curr_line->line_length)
+       {
+               while ((scr_pos < right_margin) && (position < curr_line->line_length))
+                       right(TRUE);
+               if (position < curr_line->line_length)
+               {
+                       prev_word();
+                       if (position == 1)
+                               adv_word();
+                       insert_line(TRUE);
+               }
+       }
+
+/*
+ |     go back to begin of paragraph, put cursor back to original position
+ */
+
+       bol();
+       while (!Blank_Line(curr_line->prev_line))
+               bol();
+
+/*
+ |     find word cursor was in
+ */
+
+       while ((status) && (string_count > 0))
+       {
+               search(FALSE);
+               string_count--;
+       }
+
+/*
+ |     offset the cursor to where it was before from the start of the word
+ */
+
+       while (offset > 0)
+       {
+               offset--;
+               right(TRUE);
+       }
+
+/*
+ |     reset flags and strings to what they were before formatting
+ */
+
+       if (d_word != NULL)
+               free(d_word);
+       d_word = temp_dword;
+       case_sen = temp_case;
+       free(srch_str);
+       srch_str = tmp_srchstr;
+       d_char[0] = temp_d_char[0];
+       d_char[1] = temp_d_char[1];
+       d_char[2] = temp_d_char[2];
+       auto_format = tmp_af;
+
+       midscreen(scr_vert, point);
+       werase(com_win);
+       wrefresh(com_win);
+}
+
+unsigned char *init_name[3] = {
+       "/usr/local/lib/init.ee", 
+       NULL, 
+       ".init.ee"
+       };
+
+void 
+ee_init()      /* check for init file and read it if it exists */
+{
+       FILE *init_file;
+       unsigned char *string;
+       unsigned char *str1;
+       unsigned char *str2;
+       char *home;
+       int counter;
+       int temp_int;
+
+       string = getenv("HOME");
+       str1 = home = malloc(strlen(string)+10);
+       strcpy(home, string);
+       strcat(home, "/.init.ee");
+       init_name[1] = home;
+       string = malloc(512);
+
+       for (counter = 0; counter < 3; counter++)
+       {
+               if (!(access(init_name[counter], 4)))
+               {
+                       init_file = fopen(init_name[counter], "r");
+                       while ((str2 = fgets(string, 512, init_file)) != NULL)
+                       {
+                               str1 = str2 = string;
+                               while (*str2 != '\n')
+                                       str2++;
+                               *str2 = (char) NULL;
+
+                               if (unique_test(string, init_strings) != 1)
+                                       continue;
+
+                               if (compare(str1, CASE, FALSE))
+                                       case_sen = TRUE;
+                               else if (compare(str1, NOCASE, FALSE))
+                                       case_sen = FALSE;
+                               else if (compare(str1, EXPAND, FALSE))
+                                       expand_tabs = TRUE;
+                               else if (compare(str1, NOEXPAND, FALSE))
+                                       expand_tabs = FALSE;
+                               else if (compare(str1, INFO, FALSE))
+                                       info_window = TRUE;
+                               else if (compare(str1, NOINFO, FALSE))
+                                       info_window = FALSE;   
+                               else if (compare(str1, MARGINS, FALSE))
+                                       observ_margins = TRUE;
+                               else if (compare(str1, NOMARGINS, FALSE))
+                                       observ_margins = FALSE;
+                               else if (compare(str1, AUTOFORMAT, FALSE))
+                               {
+                                       auto_format = TRUE;
+                                       observ_margins = TRUE;
+                               }
+                               else if (compare(str1, NOAUTOFORMAT, FALSE))
+                                       auto_format = FALSE;
+                               else if (compare(str1, Echo, FALSE))
+                               {
+                                       str1 = next_word(str1);
+                                       if (*str1 != (char) NULL)
+                                               echo_string(str1);
+                               }
+                               else if (compare(str1, RIGHTMARGIN, FALSE))
+                               {
+                                       str1 = next_word(str1);
+                                       if ((*str1 >= '0') && (*str1 <= '9'))
+                                       {
+                                               temp_int = atoi(str1);
+                                               if (temp_int > 0)
+                                                       right_margin = temp_int;
+                                       }
+                               }
+                               else if (compare(str1, HIGHLIGHT, FALSE))
+                                       nohighlight = FALSE;
+                               else if (compare(str1, NOHIGHLIGHT, FALSE))
+                                       nohighlight = TRUE;
+                               else if (compare(str1, EIGHTBIT, FALSE))
+                                       eightbit = TRUE;
+                               else if (compare(str1, NOEIGHTBIT, FALSE))
+                               {
+                                       eightbit = FALSE;
+                                       ee_chinese = FALSE;
+                               }
+                               else if (compare(str1, EMACS_string, FALSE))
+                                       emacs_keys_mode = TRUE;
+                               else if (compare(str1, NOEMACS_string, FALSE))
+                                       emacs_keys_mode = FALSE;
+                               else if (compare(str1, chinese_cmd, FALSE))
+                               {
+                                       ee_chinese = TRUE;
+                                       eightbit = TRUE;
+                               }
+                               else if (compare(str1, nochinese_cmd, FALSE))
+                                       ee_chinese = FALSE;
+                       }
+                       fclose(init_file);
+               }
+       }
+       free(string);
+       free(home);
+
+       string = getenv("LANG");
+       if (string != NULL)
+       {
+               if (strcmp(string, "zh_TW.big5") == 0)
+               {
+                       ee_chinese = TRUE;
+                       eightbit = TRUE;
+               }
+       }
+}
+
+void 
+echo_string(string)    /* echo the given string        */
+char *string;
+{
+       char *temp;
+       int Counter;
+
+               temp = string;
+               while (*temp != (char) NULL)
+               {
+                       if (*temp == '\\')
+                       {
+                               temp++;
+                               if (*temp == 'n')
+                                       putchar('\n');
+                               else if (*temp == 't')
+                                       putchar('\t');
+                               else if (*temp == 'b')
+                                       putchar('\b');
+                               else if (*temp == 'r')
+                                       putchar('\r');
+                               else if (*temp == 'f')
+                                       putchar('\f');
+                               else if ((*temp == 'e') || (*temp == 'E'))
+                                       putchar('\033');        /* escape */
+                               else if (*temp == '\\')
+                                       putchar('\\');
+                               else if (*temp == '\'')
+                                       putchar('\'');
+                               else if ((*temp >= '0') && (*temp <= '9'))
+                               {
+                                       Counter = 0;
+                                       while ((*temp >= '0') && (*temp <= '9'))
+                                       {
+                                               Counter = (8 * Counter) + (*temp - '0');
+                                               temp++;
+                                       }
+                                       putchar(Counter);
+                                       temp--;
+                               }
+                               temp++;
+                       }
+                       else
+                       {
+                               putchar(*temp);
+                               temp++;
+                       }
+               }
+
+       fflush(stdout);
+}
+
+int
+first_word_len(test_line)
+struct text *test_line;
+{
+       int counter;
+       unsigned char *pnt;
+
+       if (test_line == NULL)
+               return(0);
+
+       pnt = test_line->line;
+       if ((pnt == NULL) || (*pnt == (char) NULL) || 
+           (*pnt == '.') || (*pnt == '>'))
+               return(0);
+
+       if ((*pnt == ' ') || (*pnt == '\t'))
+       {
+               pnt = next_word(pnt);
+       }
+
+       if (*pnt == (char) NULL)
+               return(0);
+
+       counter = 0;
+       while ((*pnt != (char) NULL) && ((*pnt != ' ') && (*pnt != '\t')))
+       {
+               pnt++;
+               counter++;
+       }
+       while ((*pnt != (char) NULL) && ((*pnt == ' ') || (*pnt == '\t')))
+       {
+               pnt++;
+               counter++;
+       }
+       return(counter);
+}
+
+void 
+Auto_Format()  /* format the paragraph according to set margins        */
+{
+       int string_count;
+       int offset;
+       int temp_case;
+       int word_len;
+       int temp_dwl;
+       int tmp_d_line_length;
+       int leave_loop = FALSE;
+       int status;
+       int counter;
+       char not_blank;
+       unsigned char *line;
+       unsigned char *tmp_srchstr;
+       unsigned char *temp1, *temp2;
+       unsigned char *temp_dword;
+       unsigned char temp_d_char[3];
+       unsigned char *tmp_d_line;
+
+
+       temp_d_char[0] = d_char[0];
+       temp_d_char[1] = d_char[1];
+       temp_d_char[2] = d_char[2];
+
+/*
+ |     if observ_margins is not set, or the current line is blank, 
+ |     do not format the current paragraph
+ */
+
+       if ((!observ_margins) || (Blank_Line(curr_line)))
+               return;
+
+/*
+ |     get current position in paragraph, so after formatting, the cursor 
+ |     will be in the same relative position
+ */
+
+       tmp_d_line = d_line;
+       tmp_d_line_length = dlt_line->line_length;
+       d_line = NULL;
+       auto_format = FALSE;
+       offset = position;
+       if ((position != 1) && ((*point == ' ') || (*point == '\t') || (position == curr_line->line_length) || (*point == (char) NULL)))
+               prev_word();
+       temp_dword = d_word;
+       temp_dwl = d_wrd_len;
+       d_wrd_len = 0;
+       d_word = NULL;
+       temp_case = case_sen;
+       case_sen = TRUE;
+       tmp_srchstr = srch_str;
+       temp2 = srch_str = (unsigned char *) malloc(1 + curr_line->line_length - position);
+       if ((*point == ' ') || (*point == '\t'))
+               adv_word();
+       offset -= position;
+       counter = position;
+       line = temp1 = point;
+       while ((*temp1 != (char) NULL) && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length))
+       {
+               *temp2 = *temp1;
+               temp2++;
+               temp1++;
+               counter++;
+       }
+       *temp2 = (char) NULL;
+       if (position != 1)
+               bol();
+       while (!Blank_Line(curr_line->prev_line))
+               bol();
+       string_count = 0;
+       status = TRUE;
+       while ((line != point) && (status))
+       {
+               status = search(FALSE);
+               string_count++;
+       }
+
+/*
+ |     now get back to the start of the paragraph to start checking
+ */
+
+       if (position != 1)
+               bol();
+       while (!Blank_Line(curr_line->prev_line))
+               bol();
+
+/*
+ |     Start going through lines, putting spaces at end of lines if they do 
+ |     not already exist.  Check line length, and move words to the next line 
+ |     if they cross the margin.  Then get words from the next line if they 
+ |     will fit in before the margin.  
+ */
+
+       counter = 0;
+
+       while (!leave_loop)
+       {
+               if (position != curr_line->line_length)
+                       eol();
+               left(TRUE);
+               if (*point != ' ')
+               {
+                       right(TRUE);
+                       insert(' ');
+               }
+               else
+                       right(TRUE);
+
+               not_blank = FALSE;
+
+               /*
+                |      fill line if first word on next line will fit 
+                |      in the line without crossing the margin
+                */
+
+               while ((curr_line->next_line != NULL) && 
+                      ((word_len = first_word_len(curr_line->next_line)) > 0) 
+                       && ((scr_pos + word_len) < right_margin))
+               {
+                       adv_line();
+                       if ((*point == ' ') || (*point == '\t'))
+                               adv_word();
+                       del_word();
+                       if (position != 1)
+                               bol();
+
+                       /*
+                        |      We know this line was not blank before, so 
+                        |      make sure that it doesn't have one of the 
+                        |      leading characters that indicate the line 
+                        |      should not be modified.
+                        |
+                        |      We also know that this character should not 
+                        |      be left as the first character of this line.
+                        */
+
+                       if ((Blank_Line(curr_line)) && 
+                           (curr_line->line[0] != '.') && 
+                           (curr_line->line[0] != '>'))
+                       {
+                               del_line();
+                               not_blank = FALSE;
+                       }
+                       else
+                               not_blank = TRUE;
+
+                       /*
+                        |   go to end of previous line
+                        */
+                       left(TRUE);
+                       undel_word();
+                       eol();
+                       /*
+                        |   make sure there's a space at the end of the line
+                        */
+                       left(TRUE);
+                       if (*point != ' ')
+                       {
+                               right(TRUE);
+                               insert(' ');
+                       }
+                       else
+                               right(TRUE);
+               }
+
+               /*
+                |      make sure line does not cross right margin
+                */
+
+               while (right_margin <= scr_pos)
+               {
+                       prev_word();
+                       if (position != 1)
+                       {
+                               del_word();
+                               if (Blank_Line(curr_line->next_line))
+                                       insert_line(TRUE);
+                               else
+                                       adv_line();
+                               if ((*point == ' ') || (*point == '\t'))
+                                       adv_word();
+                               undel_word();
+                               not_blank = TRUE;
+                               if (position != 1)
+                                       bol();
+                               left(TRUE);
+                       }
+               }
+
+               if ((!Blank_Line(curr_line->next_line)) || (not_blank))
+               {
+                       adv_line();
+                       counter++;
+               }
+               else
+                       leave_loop = TRUE;
+       }
+
+/*
+ |     go back to begin of paragraph, put cursor back to original position
+ */
+
+       if (position != 1)
+               bol();
+       while ((counter-- > 0) || (!Blank_Line(curr_line->prev_line)))
+               bol();
+
+/*
+ |     find word cursor was in
+ */
+
+       status = TRUE;
+       while ((status) && (string_count > 0))
+       {
+               status = search(FALSE);
+               string_count--;
+       }
+
+/*
+ |     offset the cursor to where it was before from the start of the word
+ */
+
+       while (offset > 0)
+       {
+               offset--;
+               right(TRUE);
+       }
+
+       if ((string_count > 0) && (offset < 0))
+       {
+               while (offset < 0)
+               {
+                       offset++;
+                       left(TRUE);
+               }
+       }
+
+/*
+ |     reset flags and strings to what they were before formatting
+ */
+
+       if (d_word != NULL)
+               free(d_word);
+       d_word = temp_dword;
+       d_wrd_len = temp_dwl;
+       case_sen = temp_case;
+       free(srch_str);
+       srch_str = tmp_srchstr;
+       d_char[0] = temp_d_char[0];
+       d_char[1] = temp_d_char[1];
+       d_char[2] = temp_d_char[2];
+       auto_format = TRUE;
+       dlt_line->line_length = tmp_d_line_length;
+       d_line = tmp_d_line;
+
+       formatted = TRUE;
+       midscreen(scr_vert, point);
+}
+
+void 
+modes_op()
+{
+       int ret_value;
+       int counter;
+       char *string;
+
+       do
+       {
+               sprintf(modes_menu[1].item_string, "%s %s", mode_strings[1], 
+                                       (expand_tabs ? ON : OFF));
+               sprintf(modes_menu[2].item_string, "%s %s", mode_strings[2], 
+                                       (case_sen ? ON : OFF));
+               sprintf(modes_menu[3].item_string, "%s %s", mode_strings[3], 
+                                       (observ_margins ? ON : OFF));
+               sprintf(modes_menu[4].item_string, "%s %s", mode_strings[4], 
+                                       (auto_format ? ON : OFF));
+               sprintf(modes_menu[5].item_string, "%s %s", mode_strings[5], 
+                                       (eightbit ? ON : OFF));
+               sprintf(modes_menu[6].item_string, "%s %s", mode_strings[6], 
+                                       (info_window ? ON : OFF));
+               sprintf(modes_menu[7].item_string, "%s %s", mode_strings[7], 
+                                       (emacs_keys_mode ? ON : OFF));
+               sprintf(modes_menu[8].item_string, "%s %d", mode_strings[8], 
+                                       right_margin);
+               sprintf(modes_menu[9].item_string, "%s %s", mode_strings[9], 
+                                       (ee_chinese ? ON : OFF));
+
+               ret_value = menu_op(modes_menu);
+
+               switch (ret_value) 
+               {
+                       case 1:
+                               expand_tabs = !expand_tabs;
+                               break;
+                       case 2:
+                               case_sen = !case_sen;
+                               break;
+                       case 3:
+                               observ_margins = !observ_margins;
+                               break;
+                       case 4:
+                               auto_format = !auto_format;
+                               if (auto_format)
+                                       observ_margins = TRUE;
+                               break;
+                       case 5:
+                               eightbit = !eightbit;
+                               if (!eightbit)
+                                       ee_chinese = FALSE;
+#ifdef NCURSE
+                               if (ee_chinese)
+                                       nc_setattrib(A_NC_BIG5);
+                               else
+                                       nc_clearattrib(A_NC_BIG5);
+#endif /* NCURSE */
+
+                               redraw();
+                               wnoutrefresh(text_win);
+                               break;
+                       case 6:
+                               if (info_window)
+                                       no_info_window();
+                               else
+                                       create_info_window();
+                               break;
+                       case 7:
+                               emacs_keys_mode = !emacs_keys_mode;
+                               if (info_window)
+                                       paint_info_win();
+                               break;
+                       case 8:
+                               string = get_string(margin_prompt, TRUE);
+                               if (string != NULL)
+                               {
+                                       counter = atoi(string);
+                                       if (counter > 0)
+                                               right_margin = counter;
+                                       free(string);
+                               }
+                               break;
+                       case 9:
+                               ee_chinese = !ee_chinese;
+                               if (ee_chinese != FALSE)
+                                       eightbit = TRUE;
+#ifdef NCURSE
+                               if (ee_chinese)
+                                       nc_setattrib(A_NC_BIG5);
+                               else
+                                       nc_clearattrib(A_NC_BIG5);
+#endif /* NCURSE */
+                               redraw();
+                               break;
+                       default:
+                               break;
+               }
+       }
+       while (ret_value != 0);
+}
+
+char *
+is_in_string(string, substring)        /* a strchr() look-alike for systems without
+                                  strchr() */
+char * string, *substring;
+{
+       char *full, *sub;
+
+       for (sub = substring; (sub != NULL) && (*sub != (char)NULL); sub++)
+       {
+               for (full = string; (full != NULL) && (*full != (char)NULL); 
+                               full++)
+               {
+                       if (*sub == *full)
+                               return(full);
+               }
+       }
+       return(NULL);
+}
+
+/*
+ |     handle names of the form "~/file", "~user/file", 
+ |     "$HOME/foo", "~/$FOO", etc.
+ */
+
+char *
+resolve_name(name)
+char *name;
+{
+       char long_buffer[1024];
+       char short_buffer[128];
+       char *buffer;
+       char *slash;
+       char *tmp;
+       char *start_of_var;
+       int offset;
+       int index;
+       int counter;
+       struct passwd *user;
+
+       if (name[0] == '~') 
+       {
+               if (name[1] == '/')
+               {
+                       index = getuid();
+                       user = (struct passwd *) getpwuid(index);
+                       slash = name + 1;
+               }
+               else
+               {
+                       slash = strchr(name, '/');
+                       if (slash == NULL) 
+                               return(name);
+                       *slash = (char) NULL;
+                       user = (struct passwd *) getpwnam((name + 1));
+                       *slash = '/';
+               }
+               if (user == NULL) 
+               {
+                       return(name);
+               }
+               buffer = malloc(strlen(user->pw_dir) + strlen(slash) + 1);
+               strcpy(buffer, user->pw_dir);
+               strcat(buffer, slash);
+       }
+       else
+               buffer = name;
+
+       if (is_in_string(buffer, "$"))
+       {
+               tmp = buffer;
+               index = 0;
+               
+               while ((*tmp != (char) NULL) && (index < 1024))
+               {
+
+                       while ((*tmp != (char) NULL) && (*tmp != '$') && 
+                               (index < 1024))
+                       {
+                               long_buffer[index] = *tmp;
+                               tmp++;
+                               index++;
+                       }
+
+                       if ((*tmp == '$') && (index < 1024))
+                       {
+                               counter = 0;
+                               start_of_var = tmp;
+                               tmp++;
+                               if (*tmp == '{') /* } */        /* bracketed variable name */
+                               {
+                                       tmp++;                          /* { */
+                                       while ((*tmp != (char) NULL) && 
+                                               (*tmp != '}') && 
+                                               (counter < 128))
+                                       {
+                                               short_buffer[counter] = *tmp;
+                                               counter++;
+                                               tmp++;
+                                       }                       /* { */
+                                       if (*tmp == '}')
+                                               tmp++;
+                               }
+                               else
+                               {
+                                       while ((*tmp != (char) NULL) && 
+                                              (*tmp != '/') && 
+                                              (*tmp != '$') && 
+                                              (counter < 128))
+                                       {
+                                               short_buffer[counter] = *tmp;
+                                               counter++;
+                                               tmp++;
+                                       }
+                               }
+                               short_buffer[counter] = (char) NULL;
+                               if ((slash = getenv(short_buffer)) != NULL)
+                               {
+                                       offset = strlen(slash);
+                                       if ((offset + index) < 1024)
+                                               strcpy(&long_buffer[index], slash);
+                                       index += offset;
+                               }
+                               else
+                               {
+                                       while ((start_of_var != tmp) && (index < 1024))
+                                       {
+                                               long_buffer[index] = *start_of_var;
+                                               start_of_var++;
+                                               index++;
+                                       }
+                               }
+                       }
+               }
+
+               if (index == 1024)
+                       return(buffer);
+               else
+                       long_buffer[index] = (char) NULL;
+
+               if (name != buffer)
+                       free(buffer);
+               buffer = malloc(index + 1);
+               strcpy(buffer, long_buffer);
+       }
+
+       return(buffer);
+}
+
+int
+restrict_mode()
+{
+       if (!restricted)
+               return(FALSE);
+
+       wmove(com_win, 0, 0);
+       wprintw(com_win, restricted_msg);
+       wclrtoeol(com_win);
+       wrefresh(com_win);
+       clear_com_win = TRUE;
+       return(TRUE);
+}
+
+/*
+ |     The following routine tests the input string against the list of 
+ |     strings, to determine if the string is a unique match with one of the 
+ |     valid values.
+ */
+
+int 
+unique_test(string, list)
+char *string;
+char *list[];
+{
+       int counter;
+       int num_match;
+       int result;
+
+       num_match = 0;
+       counter = 0;
+       while (list[counter] != NULL)
+       {
+               result = compare(string, list[counter], FALSE);
+               if (result)
+                       num_match++;
+               counter++;
+       }
+       return(num_match);
+}
+
+/*
+ |     The following is to allow for using message catalogs which allow 
+ |     the software to be 'localized', that is, to use different languages 
+ |     all with the same binary.  For more information, see your system 
+ |     documentation, or the X/Open Internationalization Guide.
+ */
+
+void 
+strings_init()
+{
+       int counter;
+
+       modes_menu[0].item_string = catgetlocal( 1, "modes menu");
+       mode_strings[1]  = catgetlocal( 2, "tabs to spaces       "); 
+       mode_strings[2]  = catgetlocal( 3, "case sensitive search"); 
+       mode_strings[3]  = catgetlocal( 4, "margins observed     "); 
+       mode_strings[4]  = catgetlocal( 5, "auto-paragraph format"); 
+       mode_strings[5]  = catgetlocal( 6, "eightbit characters  "); 
+       mode_strings[6]  = catgetlocal( 7, "info window          "); 
+       mode_strings[8]  = catgetlocal( 8, "right margin         ");
+       leave_menu[0].item_string  = catgetlocal( 9, "leave menu");
+       leave_menu[1].item_string  = catgetlocal( 10, "save changes");
+       leave_menu[2].item_string  = catgetlocal( 11, "no save");
+       file_menu[0].item_string  = catgetlocal( 12, "file menu");
+       file_menu[1].item_string  = catgetlocal( 13, "read a file");
+       file_menu[2].item_string  = catgetlocal( 14, "write a file");
+       file_menu[3].item_string  = catgetlocal( 15, "save file");
+       file_menu[4].item_string  = catgetlocal( 16, "print (disabled)");
+       search_menu[0].item_string = catgetlocal( 17, "search menu");
+       search_menu[1].item_string = catgetlocal( 18, "search for ...");
+       search_menu[2].item_string = catgetlocal( 19, "search");
+       main_menu[0].item_string  = catgetlocal( 27, "main menu");
+       main_menu[1].item_string  = catgetlocal( 28, "leave editor");
+       main_menu[2].item_string  = catgetlocal( 29, "help");
+       main_menu[3].item_string  = catgetlocal( 30, "file operations");
+       main_menu[4].item_string  = catgetlocal( 31, "redraw screen");
+       main_menu[5].item_string  = catgetlocal( 32, "settings");
+       main_menu[6].item_string  = catgetlocal( 33, "search");
+       help_text[0] = catgetlocal( 35, "Control keys:                                                              "); 
+       help_text[1] = catgetlocal( 36, "^a ascii code           ^i tab                  ^r right                   ");
+       help_text[2] = catgetlocal( 37, "^b bottom of text       ^j newline              ^t top of text             ");
+       help_text[3] = catgetlocal( 38, "^c command              ^k delete char          ^u up                      ");
+       help_text[4] = catgetlocal( 39, "^d down                 ^l left                 ^v undelete word           ");
+       help_text[5] = catgetlocal( 40, "^e search prompt        ^m newline              ^w delete word             ");
+       help_text[6] = catgetlocal( 41, "^f undelete char        ^n next page            ^x search                  ");
+       help_text[7] = catgetlocal( 42, "^g begin of line        ^o end of line          ^y delete line             ");
+       help_text[8] = catgetlocal( 43, "^h backspace            ^p prev page            ^z undelete line           ");
+       help_text[9] = catgetlocal( 44, "^[ (escape) menu                                                           ");
+       help_text[10] = catgetlocal( 45, "                                                                           ");
+       help_text[11] = catgetlocal( 46, "Commands:                                                                  ");
+       help_text[12] = catgetlocal( 47, "help    : get this info                 file    : print file name          ");
+       help_text[13] = catgetlocal( 48, "read    : read a file                   char    : ascii code of char       ");
+       help_text[14] = catgetlocal( 49, "write   : write a file                  case    : case sensitive search    ");
+       help_text[15] = catgetlocal( 50, "exit    : leave and save                nocase  : case insensitive search  ");
+       help_text[16] = catgetlocal( 51, "quit    : leave, no save                !cmd    : (disabled)               ");
+       help_text[17] = catgetlocal( 52, "line    : display line #                0-9     : go to line \"#\"           ");
+       help_text[18] = catgetlocal( 53, "expand  : expand tabs                   noexpand: do not expand tabs         ");
+       help_text[19] = catgetlocal( 54, "                                                                             ");
+       help_text[20] = catgetlocal( 55, "  ee [+#] [-i] [-e] [-h] [file(s)]                                            ");
+       help_text[21] = catgetlocal( 56, "+# :go to line #  -i :no info window  -e : don't expand tabs  -h :no highlight");
+       control_keys[0] = catgetlocal( 57, "^[ (escape) menu  ^e search prompt  ^y delete line    ^u up     ^p prev page  ");
+       control_keys[1] = catgetlocal( 58, "^a ascii code     ^x search         ^z undelete line  ^d down   ^n next page  ");
+       control_keys[2] = catgetlocal( 59, "^b bottom of text ^g begin of line  ^w delete word    ^l left                 ");
+       control_keys[3] = catgetlocal( 60, "^t top of text    ^o end of line    ^v undelete word  ^r right                ");
+       control_keys[4] = catgetlocal( 61, "^c command        ^k delete char    ^f undelete char                          ");
+       command_strings[0] = catgetlocal( 62, "help : get help info  |file  : print file name         |line : print line # ");
+       command_strings[1] = catgetlocal( 63, "read : read a file    |char  : ascii code of char      |0-9 : go to line \"#\"");
+       command_strings[2] = catgetlocal( 64, "write: write a file   |case  : case sensitive search   |exit : leave and save ");
+       command_strings[3] = catgetlocal( 65, "!cmd : (disabled)     |nocase: ignore case in search   |quit : leave, no save");
+       command_strings[4] = catgetlocal( 66, "expand: expand tabs   |noexpand: do not expand tabs                           ");
+       com_win_message = catgetlocal( 67, "    press Escape (^[) for menu");
+       no_file_string = catgetlocal( 68, "no file");
+       ascii_code_str = catgetlocal( 69, "ascii code: ");
+       command_str = catgetlocal( 71, "command: ");
+       file_write_prompt_str = catgetlocal( 72, "name of file to write: ");
+       file_read_prompt_str = catgetlocal( 73, "name of file to read: ");
+       char_str = catgetlocal( 74, "character = %d");
+       unkn_cmd_str = catgetlocal( 75, "unknown command \"%s\"");
+       non_unique_cmd_msg = catgetlocal( 76, "entered command is not unique");
+       line_num_str = catgetlocal( 77, "line %d  ");
+       line_len_str = catgetlocal( 78, "length = %d");
+       current_file_str = catgetlocal( 79, "current file is \"%s\" ");
+       usage0 = catgetlocal( 80, "usage: %s [-i] [-e] [-h] [+line_number] [file(s)]\n");
+       usage1 = catgetlocal( 81, "       -i   turn off info window\n");
+       usage2 = catgetlocal( 82, "       -e   do not convert tabs to spaces\n");
+       usage3 = catgetlocal( 83, "       -h   do not use highlighting\n");
+       file_is_dir_msg = catgetlocal( 84, "file \"%s\" is a directory");
+       new_file_msg = catgetlocal( 85, "new file \"%s\"");
+       cant_open_msg = catgetlocal( 86, "can't open \"%s\"");
+       open_file_msg = catgetlocal( 87, "file \"%s\", %d lines");
+       file_read_fin_msg = catgetlocal( 88, "finished reading file \"%s\"");
+       reading_file_msg = catgetlocal( 89, "reading file \"%s\"");
+       read_only_msg = catgetlocal( 90, ", read only");
+       file_read_lines_msg = catgetlocal( 91, "file \"%s\", %d lines");
+       save_file_name_prompt = catgetlocal( 92, "enter name of file: ");
+       file_not_saved_msg = catgetlocal( 93, "no filename entered: file not saved");
+       changes_made_prompt = catgetlocal( 94, "changes have been made, are you sure? (y/n [n]) ");
+       yes_char = catgetlocal( 95, "y");
+       file_exists_prompt = catgetlocal( 96, "file already exists, overwrite? (y/n) [n] ");
+       create_file_fail_msg = catgetlocal( 97, "unable to create file \"%s\"");
+       writing_file_msg = catgetlocal( 98, "writing file \"%s\"");
+       file_written_msg = catgetlocal( 99, "\"%s\" %d lines, %d characters");
+       searching_msg = catgetlocal( 100, "           ...searching");
+       str_not_found_msg = catgetlocal( 101, "string \"%s\" not found");
+       search_prompt_str = catgetlocal( 102, "search for: ");
+       continue_msg = catgetlocal( 104, "press return to continue ");
+       menu_cancel_msg = catgetlocal( 105, "press Esc to cancel");
+       menu_size_err_msg = catgetlocal( 106, "menu too large for window");
+       press_any_key_msg = catgetlocal( 107, "press any key to continue ");
+       shell_prompt = catgetlocal( 108, "shell command: ");
+       formatting_msg = catgetlocal( 109, "...formatting paragraph...");
+       shell_echo_msg = catgetlocal( 110, "<!echo 'list of unrecognized words'; echo -=-=-=-=-=-");
+       margin_prompt = catgetlocal( 112, "right margin is: ");
+       restricted_msg = catgetlocal( 113, "restricted mode: unable to perform requested operation");
+       ON = catgetlocal( 114, "ON");
+       OFF = catgetlocal( 115, "OFF");
+       HELP = catgetlocal( 116, "HELP");
+       WRITE = catgetlocal( 117, "WRITE");
+       READ = catgetlocal( 118, "READ");
+       LINE = catgetlocal( 119, "LINE");
+       FILE_str = catgetlocal( 120, "FILE");
+       CHARACTER = catgetlocal( 121, "CHARACTER");
+       REDRAW = catgetlocal( 122, "REDRAW");
+       RESEQUENCE = catgetlocal( 123, "RESEQUENCE");
+       AUTHOR = catgetlocal( 124, "AUTHOR");
+       ee_VERSION = catgetlocal( 125, "ee_VERSION");
+       CASE = catgetlocal( 126, "CASE");
+       NOCASE = catgetlocal( 127, "NOCASE");
+       EXPAND = catgetlocal( 128, "EXPAND");
+       NOEXPAND = catgetlocal( 129, "NOEXPAND");
+       Exit_string = catgetlocal( 130, "EXIT");
+       QUIT_string = catgetlocal( 131, "QUIT");
+       INFO = catgetlocal( 132, "INFO");
+       NOINFO = catgetlocal( 133, "NOINFO");
+       MARGINS = catgetlocal( 134, "MARGINS");
+       NOMARGINS = catgetlocal( 135, "NOMARGINS");
+       AUTOFORMAT = catgetlocal( 136, "AUTOFORMAT");
+       NOAUTOFORMAT = catgetlocal( 137, "NOAUTOFORMAT");
+       Echo = catgetlocal( 138, "ECHO");
+       PRINTCOMMAND = catgetlocal( 139, "PRINTCOMMAND");
+       RIGHTMARGIN = catgetlocal( 140, "RIGHTMARGIN");
+       HIGHLIGHT = catgetlocal( 141, "HIGHLIGHT");
+       NOHIGHLIGHT = catgetlocal( 142, "NOHIGHLIGHT");
+       EIGHTBIT = catgetlocal( 143, "EIGHTBIT");
+       NOEIGHTBIT = catgetlocal( 144, "NOEIGHTBIT");
+       /*
+        |      additions
+        */
+       mode_strings[7] = catgetlocal( 145, "emacs key bindings   ");
+       emacs_help_text[0] = help_text[0];
+       emacs_help_text[1] = catgetlocal( 146, "^a beginning of line    ^i tab                  ^r restore word            ");
+       emacs_help_text[2] = catgetlocal( 147, "^b back 1 char          ^j undel char           ^t top of text             ");
+       emacs_help_text[3] = catgetlocal( 148, "^c command              ^k delete line          ^u bottom of text          ");
+       emacs_help_text[4] = catgetlocal( 149, "^d delete char          ^l undelete line        ^v next page               ");
+       emacs_help_text[5] = catgetlocal( 150, "^e end of line          ^m newline              ^w delete word             ");
+       emacs_help_text[6] = catgetlocal( 151, "^f forward 1 char       ^n next line            ^x search                  ");
+       emacs_help_text[7] = catgetlocal( 152, "^g go back 1 page       ^o ascii char insert    ^y search prompt           ");
+       emacs_help_text[8] = catgetlocal( 153, "^h backspace            ^p prev line            ^z next word               ");
+       emacs_help_text[9] = help_text[9];
+       emacs_help_text[10] = help_text[10];
+       emacs_help_text[11] = help_text[11];
+       emacs_help_text[12] = help_text[12];
+       emacs_help_text[13] = help_text[13];
+       emacs_help_text[14] = help_text[14];
+       emacs_help_text[15] = help_text[15];
+       emacs_help_text[16] = help_text[16];
+       emacs_help_text[17] = help_text[17];
+       emacs_help_text[18] = help_text[18];
+       emacs_help_text[19] = help_text[19];
+       emacs_help_text[20] = help_text[20];
+       emacs_help_text[21] = help_text[21];
+       emacs_control_keys[0] = catgetlocal( 154, "^[ (escape) menu  ^y search prompt  ^k delete line   ^p prev li   ^g prev page");
+       emacs_control_keys[1] = catgetlocal( 155, "^o ascii code     ^x search         ^l undelete line ^n next li   ^v next page");
+       emacs_control_keys[2] = catgetlocal( 156, "^u end of file    ^a begin of line  ^w delete word   ^b back 1 char           ");
+       emacs_control_keys[3] = catgetlocal( 157, "^t top of text    ^e end of line    ^r restore word  ^f forward 1 char        ");
+       emacs_control_keys[4] = catgetlocal( 158, "^c command        ^d delete char    ^j undelete char ^z next word              ");
+       EMACS_string = catgetlocal( 159, "EMACS");
+       NOEMACS_string = catgetlocal( 160, "NOEMACS");
+       usage4 = catgetlocal( 161, "       +#   put cursor at line #\n");
+       modes_menu[10].item_string = catgetlocal( 164, "dump configuration (disabled)");
+       config_dump_menu[0].item_string = catgetlocal( 165, "save ee configuration");
+       config_dump_menu[1].item_string = catgetlocal( 166, "save in current directory");
+       config_dump_menu[2].item_string = catgetlocal( 167, "save in home directory");
+       conf_not_saved_msg = catgetlocal( 168, "ee configuration not saved");
+       ree_no_file_msg = catgetlocal( 169, "must specify a file when invoking ree");
+       menu_too_lrg_msg = catgetlocal( 180, "menu too large for window");
+       more_above_str = catgetlocal( 181, "^^more^^");
+       more_below_str = catgetlocal( 182, "VVmoreVV");
+       mode_strings[9] = catgetlocal( 183, "16 bit characters    ");
+       chinese_cmd = catgetlocal( 184, "16BIT");
+       nochinese_cmd = catgetlocal( 185, "NO16BIT");
+
+       commands[0] = HELP;
+       commands[1] = WRITE;
+       commands[2] = READ;
+       commands[3] = LINE;
+       commands[4] = FILE_str;
+       commands[5] = REDRAW;
+       commands[6] = RESEQUENCE;
+       commands[7] = AUTHOR;
+       commands[8] = ee_VERSION;
+       commands[9] = CASE;
+       commands[10] = NOCASE;
+       commands[11] = EXPAND;
+       commands[12] = NOEXPAND;
+       commands[13] = Exit_string;
+       commands[14] = QUIT_string;
+       commands[15] = "<";
+       commands[16] = ">";
+       commands[17] = "!";
+       commands[18] = "0";
+       commands[19] = "1";
+       commands[20] = "2";
+       commands[21] = "3";
+       commands[22] = "4";
+       commands[23] = "5";
+       commands[24] = "6";
+       commands[25] = "7";
+       commands[26] = "8";
+       commands[27] = "9";
+       commands[28] = CHARACTER;
+       commands[29] = chinese_cmd;
+       commands[30] = nochinese_cmd;
+       commands[31] = NULL;
+       init_strings[0] = CASE;
+       init_strings[1] = NOCASE;
+       init_strings[2] = EXPAND;
+       init_strings[3] = NOEXPAND;
+       init_strings[4] = INFO;
+       init_strings[5] = NOINFO;
+       init_strings[6] = MARGINS;
+       init_strings[7] = NOMARGINS;
+       init_strings[8] = AUTOFORMAT;
+       init_strings[9] = NOAUTOFORMAT;
+       init_strings[10] = Echo;
+       init_strings[11] = PRINTCOMMAND;
+       init_strings[12] = RIGHTMARGIN;
+       init_strings[13] = HIGHLIGHT;
+       init_strings[14] = NOHIGHLIGHT;
+       init_strings[15] = EIGHTBIT;
+       init_strings[16] = NOEIGHTBIT;
+       init_strings[17] = EMACS_string;
+       init_strings[18] = NOEMACS_string;
+       init_strings[19] = chinese_cmd;
+       init_strings[20] = nochinese_cmd;
+       init_strings[21] = NULL;
+
+       /*
+        |      allocate space for strings here for settings menu
+        */
+
+       for (counter = 1; counter < NUM_MODES_ITEMS; counter++)
+       {
+               modes_menu[counter].item_string = malloc(80);
+       }
+}
+
diff --git a/virus.c b/virus.c
deleted file mode 100644 (file)
index 713ed47..0000000
--- a/virus.c
+++ /dev/null
@@ -1,4487 +0,0 @@
-/* vi: set sw=8 ts=8: */
-/*
- * virus - vi resembling utility skeleton - based on 
- * tiny vi.c: A small 'vi' clone (from busybox 0.52)
- *
- * Copyright (C) 2001, 2002 Stefan Koerner <ripclaw@rocklinux.org>
- * Copyright (C) 2000, 2001 Sterling Huxley <sterling@europa.com>
- *
- *  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.
- */
-
-char *vi_Version = "0.0.2+dgamelaunch 1.1.2";
-
-/*
- * To compile:
- *     gcc -Wall -Os -s -o vi virus.c
- *     strip vi
- */
-
-/*
- * Things To Do:
- *     EXINIT
- *     $HOME/.exrc  and  ./.exrc
- *     add magic to search     /foo.*bar
- *     add :help command
- *     :map macros
- *     how about mode lines:   vi: set sw=8 ts=8:
- *     if mark[] values were line numbers rather than pointers
- *        it would be easier to change the mark when add/delete lines
- *     More intelligence in refresh()
- *     ":r !cmd"  and  "!cmd"  to filter text through an external command
- *     A true "undo" facility
- *     An "ex" line oriented mode- maybe using "cmdedit"
- */
-
-//----  Feature --------------  Bytes to immplement
-#define vi_main                        vi_main
-#define BB_FEATURE_VI_COLON     // 4288
-#define BB_FEATURE_VI_YANKMARK  // 1408
-#define BB_FEATURE_VI_SEARCH    // 1088
-// #define BB_FEATURE_VI_USE_SIGNALS    // 1056
-#define BB_FEATURE_VI_DOT_CMD   //  576
-#define BB_FEATURE_VI_READONLY  //  128
-#define BB_FEATURE_VI_SETOPTS   //  576
-#define BB_FEATURE_VI_SET       //  224
-#define BB_FEATURE_VI_WIN_RESIZE  //  256  WIN_RESIZE
-// To test editor using CRASHME:
-//    vi -C filename
-// To stop testing, wait until all to text[] is deleted, or
-//    Ctrl-Z and kill -9 %1
-// while in the editor Ctrl-T will toggle the crashme function on and off.
-//#define BB_FEATURE_VI_CRASHME         // randomly pick commands to execute
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <setjmp.h>
-#include <regex.h>
-#include <ctype.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdarg.h>
-
-#include "last_char_is.c"
-
-#ifndef TRUE
-#define TRUE                   ((int)1)
-#define FALSE                  ((int)0)
-#endif /* TRUE */
-#define MAX_SCR_COLS           BUFSIZ
-
-// Misc. non-Ascii keys that report an escape sequence
-#define VI_K_UP                        128         // cursor key Up
-#define VI_K_DOWN              129         // cursor key Down
-#define VI_K_RIGHT             130       // Cursor Key Right
-#define VI_K_LEFT              131         // cursor key Left
-#define VI_K_HOME              132         // Cursor Key Home
-#define VI_K_END               133         // Cursor Key End
-#define VI_K_INSERT            134       // Cursor Key Insert
-#define VI_K_PAGEUP            135       // Cursor Key Page Up
-#define VI_K_PAGEDOWN          136     // Cursor Key Page Down
-#define VI_K_FUN1              137         // Function Key F1
-#define VI_K_FUN2              138         // Function Key F2
-#define VI_K_FUN3              139         // Function Key F3
-#define VI_K_FUN4              140         // Function Key F4
-#define VI_K_FUN5              141         // Function Key F5
-#define VI_K_FUN6              142         // Function Key F6
-#define VI_K_FUN7              143         // Function Key F7
-#define VI_K_FUN8              144         // Function Key F8
-#define VI_K_FUN9              145         // Function Key F9
-#define VI_K_FUN10             146       // Function Key F10
-#define VI_K_FUN11             147       // Function Key F11
-#define VI_K_FUN12             148       // Function Key F12
-
-static const int YANKONLY = FALSE;
-static const int YANKDEL = TRUE;
-static const int FORWARD = 1;   // code depends on "1"  for array index
-static const int BACK = -1;     // code depends on "-1" for array index
-static const int LIMITED = 0;   // how much of text[] in char_search
-static const int FULL = 1;      // how much of text[] in char_search
-
-static const int S_BEFORE_WS = 1; // used in skip_thing() for moving "dot"
-static const int S_TO_WS = 2;   // used in skip_thing() for moving "dot"
-static const int S_OVER_WS = 3; // used in skip_thing() for moving "dot"
-static const int S_END_PUNCT = 4; // used in skip_thing() for moving "dot"
-static const int S_END_ALNUM = 5; // used in skip_thing() for moving "dot"
-
-typedef unsigned char Byte;
-
-
-static int editing;             // >0 while we are editing a file
-static int cmd_mode;            // 0=command  1=insert
-static int file_modified;       // buffer contents changed
-static int err_method;          // indicate error with beep or flash
-static int fn_start;            // index of first cmd line file name
-static int save_argc;           // how many file names on cmd line
-static int cmdcnt;              // repetition count
-static fd_set rfds;             // use select() for small sleeps
-static struct timeval tv;       // use select() for small sleeps
-static char erase_char;         // the users erase character
-static int rows, columns;       // the terminal screen is this size
-static int crow, ccol, offset;  // cursor is on Crow x Ccol with Horz Ofset
-static char *SOs, *SOn;         // terminal standout start/normal ESC sequence
-static char *bell;              // terminal bell sequence
-static char *Ceol, *Ceos;       // Clear-end-of-line and Clear-end-of-screen ESC sequence
-static char *CMrc;              // Cursor motion arbitrary destination ESC sequence
-static char *CMup, *CMdown;     // Cursor motion up and down ESC sequence
-static Byte *status_buffer;     // mesages to the user
-static Byte last_input_char;    // last char read from user
-static Byte last_forward_char;  // last char searched for with 'f'
-static Byte *cfn;               // previous, current, and next file name
-static Byte *text, *end, *textend;  // pointers to the user data in memory
-static Byte *screen;            // pointer to the virtual screen buffer
-static int screensize;          //            and its size
-static Byte *screenbegin;       // index into text[], of top line on the screen
-static Byte *dot;               // where all the action takes place
-static int tabstop;
-static struct termios term_orig, term_vi; // remember what the cooked mode was
-
-#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR
-static int last_row;            // where the cursor was last moved to
-#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */
-#ifdef BB_FEATURE_VI_USE_SIGNALS
-static jmp_buf restart;         // catch_sig()
-#endif /* BB_FEATURE_VI_USE_SIGNALS */
-#ifdef BB_FEATURE_VI_WIN_RESIZE
-static struct winsize winsize;  // remember the window size
-#endif /* BB_FEATURE_VI_WIN_RESIZE */
-#ifdef BB_FEATURE_VI_DOT_CMD
-static int adding2q;            // are we currently adding user input to q
-static Byte *last_modifying_cmd;  // last modifying cmd for "."
-static Byte *ioq, *ioq_start;   // pointer to string for get_one_char to "read"
-#endif /* BB_FEATURE_VI_DOT_CMD */
-#if    defined(BB_FEATURE_VI_DOT_CMD) || defined(BB_FEATURE_VI_YANKMARK)
-static Byte *modifying_cmds;    // cmds that modify text[]
-#endif /* BB_FEATURE_VI_DOT_CMD || BB_FEATURE_VI_YANKMARK */
-#ifdef BB_FEATURE_VI_READONLY
-static int vi_readonly, readonly;
-#endif /* BB_FEATURE_VI_READONLY */
-#ifdef BB_FEATURE_VI_SETOPTS
-static int autoindent;
-static int showmatch;
-static int ignorecase;
-#endif /* BB_FEATURE_VI_SETOPTS */
-#ifdef BB_FEATURE_VI_YANKMARK
-static Byte *reg[28];           // named register a-z, "D", and "U" 0-25,26,27
-static int YDreg, Ureg;         // default delete register and orig line for "U"
-static Byte *mark[28];          // user marks points somewhere in text[]-  a-z and previous context ''
-static Byte *context_start, *context_end;
-#endif /* BB_FEATURE_VI_YANKMARK */
-#ifdef BB_FEATURE_VI_SEARCH
-static Byte *last_search_pattern; // last pattern from a '/' or '?' search
-#endif /* BB_FEATURE_VI_SEARCH */
-
-
-static void edit_file (Byte *); // edit one file
-static void do_cmd (Byte);      // execute a command
-static void sync_cursor (Byte *, int *, int *); // synchronize the screen cursor to dot
-static Byte *begin_line (Byte *); // return pointer to cur line B-o-l
-static Byte *end_line (Byte *); // return pointer to cur line E-o-l
-static Byte *dollar_line (Byte *);  // return pointer to just before NL
-static Byte *prev_line (Byte *);  // return pointer to prev line B-o-l
-static Byte *next_line (Byte *);  // return pointer to next line B-o-l
-static Byte *end_screen (void); // get pointer to last char on screen
-static int count_lines (Byte *, Byte *);  // count line from start to stop
-static Byte *find_line (int);   // find begining of line #li
-static Byte *move_to_col (Byte *, int); // move "p" to column l
-static int isblnk (Byte);       // is the char a blank or tab
-static void dot_left (void);    // move dot left- dont leave line
-static void dot_right (void);   // move dot right- dont leave line
-static void dot_begin (void);   // move dot to B-o-l
-static void dot_end (void);     // move dot to E-o-l
-static void dot_next (void);    // move dot to next line B-o-l
-static void dot_prev (void);    // move dot to prev line B-o-l
-static void dot_scroll (int, int);  // move the screen up or down
-static void dot_skip_over_ws (void);  // move dot pat WS
-static void dot_delete (void);  // delete the char at 'dot'
-static Byte *bound_dot (Byte *);  // make sure  text[0] <= P < "end"
-static Byte *new_screen (int, int); // malloc virtual screen memory
-static Byte *new_text (int);    // malloc memory for text[] buffer
-static Byte *char_insert (Byte *, Byte);  // insert the char c at 'p'
-static Byte *stupid_insert (Byte *, Byte);  // stupidly insert the char c at 'p'
-static Byte find_range (Byte **, Byte **, Byte);  // return pointers for an object
-static int st_test (Byte *, int, int, Byte *);  // helper for skip_thing()
-static Byte *skip_thing (Byte *, int, int, int);  // skip some object
-static Byte *find_pair (Byte *, Byte);  // find matching pair ()  []  {}
-static Byte *text_hole_delete (Byte *, Byte *); // at "p", delete a 'size' byte hole
-static Byte *text_hole_make (Byte *, int);  // at "p", make a 'size' byte hole
-static Byte *yank_delete (Byte *, Byte *, int, int);  // yank text[] into register then delete
-static void show_help (void);   // display some help info
-static void print_literal (Byte *, Byte *); // copy s to buf, convert unprintable
-static void rawmode (void);     // set "raw" mode on tty
-static void cookmode (void);    // return to "cooked" mode on tty
-static int mysleep (int);       // sleep for 'h' 1/100 seconds
-static Byte readit (void);      // read (maybe cursor) key from stdin
-static Byte get_one_char (void);  // read 1 char from stdin
-static int file_size (Byte *);  // what is the byte size of "fn"
-static int file_insert (Byte *, Byte *, int);
-static int file_write (Byte *, Byte *, Byte *);
-static void place_cursor (int, int, int);
-static void screen_erase ();
-static void clear_to_eol (void);
-static void clear_to_eos (void);
-static void standout_start (void);  // send "start reverse video" sequence
-static void standout_end (void);  // send "end reverse video" sequence
-static void flash (int);        // flash the terminal screen
-static void beep (void);        // beep the terminal
-static void indicate_error (char);  // use flash or beep to indicate error
-static void show_status_line (void);  // put a message on the bottom line
-static void psb (char *, ...);  // Print Status Buf
-static void psbs (char *, ...); // Print Status Buf in standout mode
-static void ni (Byte *);        // display messages
-static void edit_status (void); // show file status on status line
-static void redraw (int);       // force a full screen refresh
-static void format_line (Byte *, Byte *, int);
-static void refresh (int);      // update the terminal from screen[]
-
-#ifdef BB_FEATURE_VI_SEARCH
-static Byte *char_search (Byte *, Byte *, int, int);  // search for pattern starting at p
-static int mycmp (Byte *, Byte *, int); // string cmp based in "ignorecase"
-#endif /* BB_FEATURE_VI_SEARCH */
-#ifdef BB_FEATURE_VI_COLON
-static void Hit_Return (void);
-static Byte *get_one_address (Byte *, int *); // get colon addr, if present
-static Byte *get_address (Byte *, int *, int *);  // get two colon addrs, if present
-static void colon (Byte *);     // execute the "colon" mode cmds
-#endif /* BB_FEATURE_VI_COLON */
-static Byte *get_input_line (Byte *); // get input line- use "status line"
-#ifdef BB_FEATURE_VI_USE_SIGNALS
-static void winch_sig (int);    // catch window size changes
-static void suspend_sig (int);  // catch ctrl-Z
-static void alarm_sig (int);    // catch alarm time-outs
-static void catch_sig (int);    // catch ctrl-C
-static void core_sig (int);     // catch a core dump signal
-#endif /* BB_FEATURE_VI_USE_SIGNALS */
-#ifdef BB_FEATURE_VI_DOT_CMD
-static void start_new_cmd_q (Byte); // new queue for command
-static void end_cmd_q ();       // stop saving input chars
-#else /* BB_FEATURE_VI_DOT_CMD */
-#define end_cmd_q()
-#endif /* BB_FEATURE_VI_DOT_CMD */
-#ifdef BB_FEATURE_VI_WIN_RESIZE
-static void window_size_get (int);  // find out what size the window is
-#endif /* BB_FEATURE_VI_WIN_RESIZE */
-#ifdef BB_FEATURE_VI_SETOPTS
-static void showmatching (Byte *);  // show the matching pair ()  []  {}
-#endif /* BB_FEATURE_VI_SETOPTS */
-#if defined(BB_FEATURE_VI_YANKMARK) || defined(BB_FEATURE_VI_COLON) || defined(BB_FEATURE_VI_CRASHME)
-static Byte *string_insert (Byte *, Byte *);  // insert the string at 'p'
-#endif /* BB_FEATURE_VI_YANKMARK || BB_FEATURE_VI_COLON || BB_FEATURE_VI_CRASHME */
-#ifdef BB_FEATURE_VI_YANKMARK
-static Byte *text_yank (Byte *, Byte *, int); // save copy of "p" into a register
-static Byte what_reg (void);    // what is letter of current YDreg
-static void check_context (Byte); // remember context for '' command
-static Byte *swap_context (Byte *); // goto new context for '' command
-#endif /* BB_FEATURE_VI_YANKMARK */
-#ifdef BB_FEATURE_VI_CRASHME
-static void crash_dummy ();
-static void crash_test ();
-static int crashme = 0;
-#endif /* BB_FEATURE_VI_CRASHME */
-
-
-extern int
-vi_main (int argc, char **argv)
-{
-#ifdef BB_FEATURE_VI_YANKMARK
-  int i;
-#endif /* BB_FEATURE_VI_YANKMARK */
-
-  CMrc = "\033[%d;%dH";         // Terminal Crusor motion ESC sequence
-  CMup = "\033[A";              // move cursor up one line, same col
-  CMdown = "\n";                // move cursor down one line, same col
-  Ceol = "\033[0K";             // Clear from cursor to end of line
-  Ceos = "\033[0J";             // Clear from cursor to end of screen
-  SOs = "\033[7m";              // Terminal standout mode on
-  SOn = "\033[0m";              // Terminal standout mode off
-  bell = "\007";                // Terminal bell sequence
-#ifdef BB_FEATURE_VI_CRASHME
-  (void) srand ((long) getpid ());
-#endif /* BB_FEATURE_VI_CRASHME */
-  status_buffer = (Byte *) malloc (200);  // hold messages to user
-#ifdef BB_FEATURE_VI_READONLY
-  vi_readonly = readonly = FALSE;
-  if (strncmp (argv[0], "view", 4) == 0)
-    {
-      readonly = TRUE;
-      vi_readonly = TRUE;
-    }
-#endif /* BB_FEATURE_VI_READONLY */
-#ifdef BB_FEATURE_VI_SETOPTS
-  autoindent = 1;
-  ignorecase = 1;
-  showmatch = 1;
-#endif /* BB_FEATURE_VI_SETOPTS */
-#ifdef BB_FEATURE_VI_YANKMARK
-  for (i = 0; i < 28; i++)
-    {
-      reg[i] = 0;
-    }                           // init the yank regs
-#endif /* BB_FEATURE_VI_YANKMARK */
-#ifdef BB_FEATURE_VI_DOT_CMD
-  modifying_cmds = (Byte *) "aAcCdDiIJoOpPrRsxX<>~";  // cmds modifying text[]
-#endif /* BB_FEATURE_VI_DOT_CMD */
-
-  if (argc >= 2)
-    {
-      cfn = (Byte *) strdup (argv[1]);
-      edit_file (cfn);
-    }
-  else
-    {
-      fprintf (stderr, "%s: no file to edit, bailing out\n", argv[0]);
-      exit (-20);
-    }
-
-  //-----------------------------------------------------------
-
-
-  /* set these back to defaults. this was the infamous screen resize crash bug */
-  signal (SIGWINCH, SIG_DFL);
-  signal (SIGTSTP, SIG_DFL);
-
-  return (0);
-}
-
-static void
-edit_file (Byte * fn)
-{
-  char c;
-  int cnt, size, ch;
-
-#ifdef BB_FEATURE_VI_USE_SIGNALS
-  char *msg;
-  int sig;
-#endif /* BB_FEATURE_VI_USE_SIGNALS */
-#ifdef BB_FEATURE_VI_YANKMARK
-  static Byte *cur_line;
-#endif /* BB_FEATURE_VI_YANKMARK */
-
-  rawmode ();
-  rows = 24;
-  columns = 80;
-  ch = -1;
-#ifdef BB_FEATURE_VI_WIN_RESIZE
-  window_size_get (0);
-#endif /* BB_FEATURE_VI_WIN_RESIZE */
-  new_screen (rows, columns);   // get memory for virtual screen
-
-  cnt = file_size (fn);         // file size
-  size = 2 * cnt;               // 200% of file size
-  new_text (size);              // get a text[] buffer
-  screenbegin = dot = end = text;
-  if (fn != 0)
-    {
-      ch = file_insert (fn, text, cnt);
-    }
-  if (ch < 1)
-    {
-      (void) char_insert (text, '\n');  // start empty buf with dummy line
-    }
-  file_modified = FALSE;
-#ifdef BB_FEATURE_VI_YANKMARK
-  YDreg = 26;                   // default Yank/Delete reg
-  Ureg = 27;                    // hold orig line for "U" cmd
-  for (cnt = 0; cnt < 28; cnt++)
-    {
-      mark[cnt] = 0;
-    }                           // init the marks
-  mark[26] = mark[27] = text;   // init "previous context"
-#endif /* BB_FEATURE_VI_YANKMARK */
-
-  err_method = 1;               // flash
-  last_forward_char = last_input_char = '\0';
-  crow = 0;
-  ccol = 0;
-  edit_status ();
-
-#ifdef BB_FEATURE_VI_USE_SIGNALS
-  signal (SIGHUP, catch_sig);
-  signal (SIGINT, catch_sig);
-  signal (SIGALRM, alarm_sig);
-  signal (SIGTERM, catch_sig);
-  signal (SIGQUIT, core_sig);
-  signal (SIGILL, core_sig);
-  signal (SIGTRAP, core_sig);
-  signal (SIGIOT, core_sig);
-  signal (SIGABRT, core_sig);
-  signal (SIGFPE, core_sig);
-  signal (SIGBUS, core_sig);
-  signal (SIGSEGV, core_sig);
-#ifdef SIGSYS
-  signal (SIGSYS, core_sig);
-#endif
-  signal (SIGWINCH, winch_sig);
-  signal (SIGTSTP, suspend_sig);
-  sig = setjmp (restart);
-  if (sig != 0)
-    {
-      msg = "";
-      if (sig == SIGWINCH)
-        msg = "(window resize)";
-      if (sig == SIGHUP)
-        msg = "(hangup)";
-      if (sig == SIGINT)
-        msg = "(interrupt)";
-      if (sig == SIGTERM)
-        msg = "(terminate)";
-      if (sig == SIGBUS)
-        msg = "(bus error)";
-      if (sig == SIGSEGV)
-        msg = "(I tried to touch invalid memory)";
-      if (sig == SIGALRM)
-        msg = "(alarm)";
-
-      psbs ("-- caught signal %d %s--", sig, msg);
-      screenbegin = dot = text;
-    }
-#endif /* BB_FEATURE_VI_USE_SIGNALS */
-
-  editing = 1;
-  cmd_mode = 0;                 // 0=command  1=insert  2='R'eplace
-  cmdcnt = 0;
-  tabstop = 8;
-  offset = 0;                   // no horizontal offset
-  c = '\0';
-#ifdef BB_FEATURE_VI_DOT_CMD
-  if (last_modifying_cmd != 0)
-    free (last_modifying_cmd);
-  if (ioq_start != NULL)
-    free (ioq_start);
-  ioq = ioq_start = last_modifying_cmd = 0;
-  adding2q = 0;
-#endif /* BB_FEATURE_VI_DOT_CMD */
-  redraw (FALSE);               // dont force every col re-draw
-  show_status_line ();
-
-  //------This is the main Vi cmd handling loop -----------------------
-  while (editing > 0)
-    {
-#ifdef BB_FEATURE_VI_CRASHME
-      if (crashme > 0)
-        {
-          if ((end - text) > 1)
-            {
-              crash_dummy ();   // generate a random command
-            }
-          else
-            {
-              crashme = 0;
-              dot = string_insert (text, (Byte *) "\n\n#####  Ran out of text to work on.  #####\n\n"); // insert the string
-              refresh (FALSE);
-            }
-        }
-#endif /* BB_FEATURE_VI_CRASHME */
-      last_input_char = c = get_one_char ();  // get a cmd from user
-#ifdef BB_FEATURE_VI_YANKMARK
-      // save a copy of the current line- for the 'U" command
-      if (begin_line (dot) != cur_line)
-        {
-          cur_line = begin_line (dot);
-          text_yank (begin_line (dot), end_line (dot), Ureg);
-        }
-#endif /* BB_FEATURE_VI_YANKMARK */
-#ifdef BB_FEATURE_VI_DOT_CMD
-      // These are commands that change text[].
-      // Remember the input for the "." command
-      if (!adding2q && ioq_start == 0
-          && strchr ((char *) modifying_cmds, c) != NULL)
-        {
-          start_new_cmd_q (c);
-        }
-#endif /* BB_FEATURE_VI_DOT_CMD */
-      do_cmd (c);               // execute the user command
-      //
-      // poll to see if there is input already waiting. if we are
-      // not able to display output fast enough to keep up, skip
-      // the display update until we catch up with input.
-      if (mysleep (0) == 0)
-        {
-          // no input pending- so update output
-          refresh (FALSE);
-          show_status_line ();
-        }
-#ifdef BB_FEATURE_VI_CRASHME
-      if (crashme > 0)
-        crash_test ();          // test editor variables
-#endif /* BB_FEATURE_VI_CRASHME */
-    }
-  //-------------------------------------------------------------------
-
-  place_cursor (rows, 0, FALSE);  // go to bottom of screen
-  clear_to_eol ();              // Erase to end of line
-  cookmode ();
-}
-
-static Byte readbuffer[BUFSIZ];
-
-#ifdef BB_FEATURE_VI_CRASHME
-static int totalcmds = 0;
-static int Mp = 85;             // Movement command Probability
-static int Np = 90;             // Non-movement command Probability
-static int Dp = 96;             // Delete command Probability
-static int Ip = 97;             // Insert command Probability
-static int Yp = 98;             // Yank command Probability
-static int Pp = 99;             // Put command Probability
-static int M = 0, N = 0, I = 0, D = 0, Y = 0, P = 0, U = 0;
-char chars[20] = "\t012345 abcdABCD-=.$";
-char *words[20] = { "this", "is", "a", "test",
-  "broadcast", "the", "emergency", "of",
-  "system", "quick", "brown", "fox",
-  "jumped", "over", "lazy", "dogs",
-  "back", "January", "Febuary", "March"
-};
-char *lines[20] = {
-  "You should have received a copy of the GNU General Public License\n",
-  "char c, cm, *cmd, *cmd1;\n",
-  "generate a command by percentages\n",
-  "Numbers may be typed as a prefix to some commands.\n",
-  "Quit, discarding changes!\n",
-  "Forced write, if permission originally not valid.\n",
-  "In general, any ex or ed command (such as substitute or delete).\n",
-  "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n",
-  "Please get w/ me and I will go over it with you.\n",
-  "The following is a list of scheduled, committed changes.\n",
-  "1.   Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n",
-  "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n",
-  "Any question about transactions please contact Sterling Huxley.\n",
-  "I will try to get back to you by Friday, December 31.\n",
-  "This Change will be implemented on Friday.\n",
-  "Let me know if you have problems accessing this;\n",
-  "Sterling Huxley recently added you to the access list.\n",
-  "Would you like to go to lunch?\n",
-  "The last command will be automatically run.\n",
-  "This is too much english for a computer geek.\n",
-};
-char *multilines[20] = {
-  "You should have received a copy of the GNU General Public License\n",
-  "char c, cm, *cmd, *cmd1;\n",
-  "generate a command by percentages\n",
-  "Numbers may be typed as a prefix to some commands.\n",
-  "Quit, discarding changes!\n",
-  "Forced write, if permission originally not valid.\n",
-  "In general, any ex or ed command (such as substitute or delete).\n",
-  "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n",
-  "Please get w/ me and I will go over it with you.\n",
-  "The following is a list of scheduled, committed changes.\n",
-  "1.   Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n",
-  "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n",
-  "Any question about transactions please contact Sterling Huxley.\n",
-  "I will try to get back to you by Friday, December 31.\n",
-  "This Change will be implemented on Friday.\n",
-  "Let me know if you have problems accessing this;\n",
-  "Sterling Huxley recently added you to the access list.\n",
-  "Would you like to go to lunch?\n",
-  "The last command will be automatically run.\n",
-  "This is too much english for a computer geek.\n",
-};
-
-// create a random command to execute
-static void
-crash_dummy ()
-{
-  static int sleeptime;         // how long to pause between commands
-  char c, cm, *cmd, *cmd1;
-  int i, cnt, thing, rbi, startrbi, percent;
-
-  // "dot" movement commands
-  cmd1 = " \n\r\002\004\005\006\025\0310^$-+wWeEbBhjklHL";
-
-  // is there already a command running?
-  if (strlen ((char *) readbuffer) > 0)
-    goto cd1;
-cd0:
-  startrbi = rbi = 0;
-  sleeptime = 0;                // how long to pause between commands
-  memset (readbuffer, '\0', BUFSIZ - 1);  // clear the read buffer
-  // generate a command by percentages
-  percent = (int) lrand48 () % 100; // get a number from 0-99
-  if (percent < Mp)
-    {                           //  Movement commands
-      // available commands
-      cmd = cmd1;
-      M++;
-    }
-  else if (percent < Np)
-    {                           //  non-movement commands
-      cmd = "mz<>\'\"";         // available commands
-      N++;
-    }
-  else if (percent < Dp)
-    {                           //  Delete commands
-      cmd = "dx";               // available commands
-      D++;
-    }
-  else if (percent < Ip)
-    {                           //  Inset commands
-      cmd = "iIaAsrJ";          // available commands
-      I++;
-    }
-  else if (percent < Yp)
-    {                           //  Yank commands
-      cmd = "yY";               // available commands
-      Y++;
-    }
-  else if (percent < Pp)
-    {                           //  Put commands
-      cmd = "pP";               // available commands
-      P++;
-    }
-  else
-    {
-      // We do not know how to handle this command, try again
-      U++;
-      goto cd0;
-    }
-  // randomly pick one of the available cmds from "cmd[]"
-  i = (int) lrand48 () % strlen (cmd);
-  cm = cmd[i];
-  if (strchr (":\024", cm))
-    goto cd0;                   // dont allow colon or ctrl-T commands
-  readbuffer[rbi++] = cm;       // put cmd into input buffer
-
-  // now we have the command-
-  // there are 1, 2, and multi char commands
-  // find out which and generate the rest of command as necessary
-  if (strchr ("dmryz<>\'\"", cm))
-    {                           // 2-char commands
-      cmd1 = " \n\r0$^-+wWeEbBhjklHL";
-      if (cm == 'm' || cm == '\'' || cm == '\"')
-        {                       // pick a reg[]
-          cmd1 = "abcdefghijklmnopqrstuvwxyz";
-        }
-      thing = (int) lrand48 () % strlen (cmd1); // pick a movement command
-      c = cmd1[thing];
-      readbuffer[rbi++] = c;    // add movement to input buffer
-    }
-  if (strchr ("iIaAsc", cm))
-    {                           // multi-char commands
-      if (cm == 'c')
-        {
-          // change some thing
-          thing = (int) lrand48 () % strlen (cmd1); // pick a movement command
-          c = cmd1[thing];
-          readbuffer[rbi++] = c;  // add movement to input buffer
-        }
-      thing = (int) lrand48 () % 4; // what thing to insert
-      cnt = (int) lrand48 () % 10;  // how many to insert
-      for (i = 0; i < cnt; i++)
-        {
-          if (thing == 0)
-            {                   // insert chars
-              readbuffer[rbi++] = chars[((int) lrand48 () % strlen (chars))];
-            }
-          else if (thing == 1)
-            {                   // insert words
-              strcat ((char *) readbuffer, words[(int) lrand48 () % 20]);
-              strcat ((char *) readbuffer, " ");
-              sleeptime = 0;    // how fast to type
-            }
-          else if (thing == 2)
-            {                   // insert lines
-              strcat ((char *) readbuffer, lines[(int) lrand48 () % 20]);
-              sleeptime = 0;    // how fast to type
-            }
-          else
-            {                   // insert multi-lines
-              strcat ((char *) readbuffer, multilines[(int) lrand48 () % 20]);
-              sleeptime = 0;    // how fast to type
-            }
-        }
-      strcat ((char *) readbuffer, "\033");
-    }
-cd1:
-  totalcmds++;
-  if (sleeptime > 0)
-    (void) mysleep (sleeptime); // sleep 1/100 sec
-}
-
-// test to see if there are any errors
-static void
-crash_test ()
-{
-  static time_t oldtim;
-  time_t tim;
-  char d[2], buf[BUFSIZ], msg[BUFSIZ];
-
-  msg[0] = '\0';
-  if (end < text)
-    {
-      strcat ((char *) msg, "end<text ");
-    }
-  if (end > textend)
-    {
-      strcat ((char *) msg, "end>textend ");
-    }
-  if (dot < text)
-    {
-      strcat ((char *) msg, "dot<text ");
-    }
-  if (dot > end)
-    {
-      strcat ((char *) msg, "dot>end ");
-    }
-  if (screenbegin < text)
-    {
-      strcat ((char *) msg, "screenbegin<text ");
-    }
-  if (screenbegin > end - 1)
-    {
-      strcat ((char *) msg, "screenbegin>end-1 ");
-    }
-
-  if (strlen (msg) > 0)
-    {
-      // alarm(0);
-      sprintf (buf, "\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s",
-               totalcmds, last_input_char, msg, SOs, SOn);
-      write (1, buf, strlen (buf));
-      while (read (0, d, 1) > 0)
-        {
-          if (d[0] == '\n' || d[0] == '\r')
-            break;
-        }
-      // alarm(3);
-    }
-  tim = (time_t) time ((time_t *) 0);
-  if (tim >= (oldtim + 3))
-    {
-      sprintf ((char *) status_buffer,
-               "Tot=%d: M=%d N=%d I=%d D=%d Y=%d P=%d U=%d size=%d",
-               totalcmds, M, N, I, D, Y, P, U, end - text + 1);
-      oldtim = tim;
-    }
-  return;
-}
-#endif /* BB_FEATURE_VI_CRASHME */
-
-//---------------------------------------------------------------------
-//----- the Ascii Chart -----------------------------------------------
-//
-//  00 nul   01 soh   02 stx   03 etx   04 eot   05 enq   06 ack   07 bel
-//  08 bs    09 ht    0a nl    0b vt    0c np    0d cr    0e so    0f si
-//  10 dle   11 dc1   12 dc2   13 dc3   14 dc4   15 nak   16 syn   17 etb
-//  18 can   19 em    1a sub   1b esc   1c fs    1d gs    1e rs    1f us
-//  20 sp    21 !     22 "     23 #     24 $     25 %     26 &     27 '
-//  28 (     29 )     2a *     2b +     2c ,     2d -     2e .     2f /
-//  30 0     31 1     32 2     33 3     34 4     35 5     36 6     37 7
-//  38 8     39 9     3a :     3b ;     3c <     3d =     3e >     3f ?
-//  40 @     41 A     42 B     43 C     44 D     45 E     46 F     47 G
-//  48 H     49 I     4a J     4b K     4c L     4d M     4e N     4f O
-//  50 P     51 Q     52 R     53 S     54 T     55 U     56 V     57 W
-//  58 X     59 Y     5a Z     5b [     5c \     5d ]     5e ^     5f _
-//  60 `     61 a     62 b     63 c     64 d     65 e     66 f     67 g
-//  68 h     69 i     6a j     6b k     6c l     6d m     6e n     6f o
-//  70 p     71 q     72 r     73 s     74 t     75 u     76 v     77 w
-//  78 x     79 y     7a z     7b {     7c |     7d }     7e ~     7f del
-//---------------------------------------------------------------------
-
-//----- Execute a Vi Command -----------------------------------
-static void
-do_cmd (Byte c)
-{
-  Byte c1, *p, *q, *msg, buf[9], *save_dot;
-  int cnt, i, j, dir, yf;
-
-  c1 = c;                       // quiet the compiler
-  cnt = yf = dir = 0;           // quiet the compiler
-  p = q = save_dot = msg = buf; // quiet the compiler
-  memset (buf, '\0', 9);        // clear buf
-  if (cmd_mode == 2)
-    {
-      // we are 'R'eplacing the current *dot with new char
-      if (*dot == '\n')
-        {
-          // don't Replace past E-o-l
-          cmd_mode = 1;         // convert to insert
-        }
-      else
-        {
-          if (1 <= c && c <= 127)
-            {                   // only ASCII chars
-              if (c != 27)
-                dot = yank_delete (dot, dot, 0, YANKDEL); // delete char
-              dot = char_insert (dot, c); // insert new char
-            }
-          goto dc1;
-        }
-    }
-  if (cmd_mode == 1)
-    {
-      //  hitting "Insert" twice means "R" replace mode
-      if (c == VI_K_INSERT)
-        goto dc5;
-      // insert the char c at "dot"
-      if (1 <= c && c <= 127)
-        {
-          dot = char_insert (dot, c); // only ASCII chars
-        }
-      goto dc1;
-    }
-
-  switch (c)
-    {
-      //case 0x01:    // soh
-      //case 0x09:    // ht
-      //case 0x0b:    // vt
-      //case 0x0e:    // so
-      //case 0x0f:    // si
-      //case 0x10:    // dle
-      //case 0x11:    // dc1
-      //case 0x13:    // dc3
-#ifdef BB_FEATURE_VI_CRASHME
-    case 0x14:                 // dc4  ctrl-T
-      crashme = (crashme == 0) ? 1 : 0;
-      break;
-#endif /* BB_FEATURE_VI_CRASHME */
-      //case 0x16:    // syn
-      //case 0x17:    // etb
-      //case 0x18:    // can
-      //case 0x1c:    // fs
-      //case 0x1d:    // gs
-      //case 0x1e:    // rs
-      //case 0x1f:    // us
-      //case '!':     // !- 
-      //case '#':     // #- 
-      //case '&':     // &- 
-      //case '(':     // (- 
-      //case ')':     // )- 
-      //case '*':     // *- 
-      //case ',':     // ,- 
-      //case '=':     // =- 
-      //case '@':     // @- 
-      //case 'F':     // F- 
-      //case 'K':     // K- 
-      //case 'Q':     // Q- 
-      //case 'S':     // S- 
-      //case 'T':     // T- 
-      //case 'V':     // V- 
-      //case '[':     // [- 
-      //case '\\':    // \- 
-      //case ']':     // ]- 
-      //case '_':     // _- 
-      //case '`':     // `- 
-      //case 'g':     // g- 
-      //case 'u':     // u- FIXME- there is no undo
-      //case 'v':     // v- 
-    default:                   // unrecognised command
-      buf[0] = c;
-      buf[1] = '\0';
-      if (c <= ' ')
-        {
-          buf[0] = '^';
-          buf[1] = c + '@';
-          buf[2] = '\0';
-        }
-      ni ((Byte *) buf);
-      end_cmd_q ();             // stop adding to q
-    case 0x00:                 // nul- ignore
-      break;
-    case 2:                    // ctrl-B  scroll up   full screen
-    case VI_K_PAGEUP:          // Cursor Key Page Up
-      dot_scroll (rows - 2, -1);
-      break;
-#ifdef BB_FEATURE_VI_USE_SIGNALS
-    case 0x03:                 // ctrl-C   interrupt
-      longjmp (restart, 1);
-      break;
-    case 26:                   // ctrl-Z suspend
-      suspend_sig (SIGTSTP);
-      break;
-#endif /* BB_FEATURE_VI_USE_SIGNALS */
-    case 4:                    // ctrl-D  scroll down half screen
-      dot_scroll ((rows - 2) / 2, 1);
-      break;
-    case 5:                    // ctrl-E  scroll down one line
-      dot_scroll (1, 1);
-      break;
-    case 6:                    // ctrl-F  scroll down full screen
-    case VI_K_PAGEDOWN:        // Cursor Key Page Down
-      dot_scroll (rows - 2, 1);
-      break;
-    case 7:                    // ctrl-G  show current status
-      edit_status ();
-      break;
-    case 'h':                  // h- move left
-    case VI_K_LEFT:            // cursor key Left
-    case 8:                    // ctrl-H- move left    (This may be ERASE char)
-    case 127:                  // DEL- move left   (This may be ERASE char)
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dot_left ();
-      break;
-    case 10:                   // Newline ^J
-    case 'j':                  // j- goto next line, same col
-    case VI_K_DOWN:            // cursor key Down
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dot_next ();              // go to next B-o-l
-      dot = move_to_col (dot, ccol + offset); // try stay in same col
-      break;
-    case 12:                   // ctrl-L  force redraw whole screen
-    case 18:                   // ctrl-R  force redraw
-      place_cursor (0, 0, FALSE); // put cursor in correct place
-      clear_to_eos ();          // tel terminal to erase display
-      (void) mysleep (10);
-      screen_erase ();          // erase the internal screen buffer
-      refresh (TRUE);           // this will redraw the entire display
-      break;
-    case 13:                   // Carriage Return ^M
-    case '+':                  // +- goto next line
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dot_next ();
-      dot_skip_over_ws ();
-      break;
-    case 21:                   // ctrl-U  scroll up   half screen
-      dot_scroll ((rows - 2) / 2, -1);
-      break;
-    case 25:                   // ctrl-Y  scroll up one line
-      dot_scroll (1, -1);
-      break;
-    case 27:                   // esc
-      if (cmd_mode == 0)
-        indicate_error (c);
-      cmd_mode = 0;             // stop insrting
-      end_cmd_q ();
-      *status_buffer = '\0';    // clear status buffer
-      break;
-    case ' ':                  // move right
-    case 'l':                  // move right
-    case VI_K_RIGHT:           // Cursor Key Right
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dot_right ();
-      break;
-#ifdef BB_FEATURE_VI_YANKMARK
-    case '"':                  // "- name a register to use for Delete/Yank
-      c1 = get_one_char ();
-      c1 = tolower (c1);
-      if (islower (c1))
-        {
-          YDreg = c1 - 'a';
-        }
-      else
-        {
-          indicate_error (c);
-        }
-      break;
-    case '\'':                 // '- goto a specific mark
-      c1 = get_one_char ();
-      c1 = tolower (c1);
-      if (islower (c1))
-        {
-          c1 = c1 - 'a';
-          // get the b-o-l
-          q = mark[(int) c1];
-          if (text <= q && q < end)
-            {
-              dot = q;
-              dot_begin ();     // go to B-o-l
-              dot_skip_over_ws ();
-            }
-        }
-      else if (c1 == '\'')
-        {                       // goto previous context
-          dot = swap_context (dot); // swap current and previous context
-          dot_begin ();         // go to B-o-l
-          dot_skip_over_ws ();
-        }
-      else
-        {
-          indicate_error (c);
-        }
-      break;
-    case 'm':                  // m- Mark a line
-      // this is really stupid.  If there are any inserts or deletes
-      // between text[0] and dot then this mark will not point to the
-      // correct location! It could be off by many lines!
-      // Well..., at least its quick and dirty.
-      c1 = get_one_char ();
-      c1 = tolower (c1);
-      if (islower (c1))
-        {
-          c1 = c1 - 'a';
-          // remember the line
-          mark[(int) c1] = dot;
-        }
-      else
-        {
-          indicate_error (c);
-        }
-      break;
-    case 'P':                  // P- Put register before
-    case 'p':                  // p- put register after
-      p = reg[YDreg];
-      if (p == 0)
-        {
-          psbs ("Nothing in register %c", what_reg ());
-          break;
-        }
-      // are we putting whole lines or strings
-      if (strchr ((char *) p, '\n') != NULL)
-        {
-          if (c == 'P')
-            {
-              dot_begin ();     // putting lines- Put above
-            }
-          if (c == 'p')
-            {
-              // are we putting after very last line?
-              if (end_line (dot) == (end - 1))
-                {
-                  dot = end;    // force dot to end of text[]
-                }
-              else
-                {
-                  dot_next ();  // next line, then put before
-                }
-            }
-        }
-      else
-        {
-          if (c == 'p')
-            dot_right ();       // move to right, can move to NL
-        }
-      dot = string_insert (dot, p); // insert the string
-      end_cmd_q ();             // stop adding to q
-      break;
-    case 'U':                  // U- Undo; replace current line with original version
-      if (reg[Ureg] != 0)
-        {
-          p = begin_line (dot);
-          q = end_line (dot);
-          p = text_hole_delete (p, q);  // delete cur line
-          p = string_insert (p, reg[Ureg]); // insert orig line
-          dot = p;
-          dot_skip_over_ws ();
-        }
-      break;
-#endif /* BB_FEATURE_VI_YANKMARK */
-    case '$':                  // $- goto end of line
-    case VI_K_END:             // Cursor Key End
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dot = end_line (dot + 1);
-      break;
-    case '%':                  // %- find matching char of pair () [] {}
-      for (q = dot; q < end && *q != '\n'; q++)
-        {
-          if (strchr ("()[]{}", *q) != NULL)
-            {
-              // we found half of a pair
-              p = find_pair (q, *q);
-              if (p == NULL)
-                {
-                  indicate_error (c);
-                }
-              else
-                {
-                  dot = p;
-                }
-              break;
-            }
-        }
-      if (*q == '\n')
-        indicate_error (c);
-      break;
-    case 'f':                  // f- forward to a user specified char
-      last_forward_char = get_one_char ();  // get the search char
-      //
-      // dont seperate these two commands. 'f' depends on ';'
-      //
-      //**** fall thru to ... 'i'
-    case ';':                  // ;- look at rest of line for last forward char
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (';');
-        }                       // repeat cnt
-      if (last_forward_char == 0)
-        break;
-      q = dot + 1;
-      while (q < end - 1 && *q != '\n' && *q != last_forward_char)
-        {
-          q++;
-        }
-      if (*q == last_forward_char)
-        dot = q;
-      break;
-    case '-':                  // -- goto prev line
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dot_prev ();
-      dot_skip_over_ws ();
-      break;
-#ifdef BB_FEATURE_VI_DOT_CMD
-    case '.':                  // .- repeat the last modifying command
-      // Stuff the last_modifying_cmd back into stdin
-      // and let it be re-executed.
-      if (last_modifying_cmd != 0)
-        {
-          ioq = ioq_start = (Byte *) strdup ((char *) last_modifying_cmd);
-        }
-      break;
-#endif /* BB_FEATURE_VI_DOT_CMD */
-#ifdef BB_FEATURE_VI_SEARCH
-    case '?':                  // /- search for a pattern
-    case '/':                  // /- search for a pattern
-      buf[0] = c;
-      buf[1] = '\0';
-      q = get_input_line (buf); // get input line- use "status line"
-      if (strlen ((char *) q) == 1)
-        goto dc3;               // if no pat re-use old pat
-      if (strlen ((char *) q) > 1)
-        {                       // new pat- save it and find
-          // there is a new pat
-          if (last_search_pattern != 0)
-            {
-              free (last_search_pattern);
-            }
-          last_search_pattern = (Byte *) strdup ((char *) q);
-          goto dc3;             // now find the pattern
-        }
-      // user changed mind and erased the "/"-  do nothing
-      break;
-    case 'N':                  // N- backward search for last pattern
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dir = BACK;               // assume BACKWARD search
-      p = dot - 1;
-      if (last_search_pattern[0] == '?')
-        {
-          dir = FORWARD;
-          p = dot + 1;
-        }
-      goto dc4;                 // now search for pattern
-      break;
-    case 'n':                  // n- repeat search for last pattern
-      // search rest of text[] starting at next char
-      // if search fails return orignal "p" not the "p+1" address
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-    dc3:
-      if (last_search_pattern == 0)
-        {
-          msg = (Byte *) "No previous regular expression";
-          goto dc2;
-        }
-      if (last_search_pattern[0] == '/')
-        {
-          dir = FORWARD;        // assume FORWARD search
-          p = dot + 1;
-        }
-      if (last_search_pattern[0] == '?')
-        {
-          dir = BACK;
-          p = dot - 1;
-        }
-    dc4:
-      q = char_search (p, last_search_pattern + 1, dir, FULL);
-      if (q != NULL)
-        {
-          dot = q;              // good search, update "dot"
-          msg = (Byte *) "";
-          goto dc2;
-        }
-      // no pattern found between "dot" and "end"- continue at top
-      p = text;
-      if (dir == BACK)
-        {
-          p = end - 1;
-        }
-      q = char_search (p, last_search_pattern + 1, dir, FULL);
-      if (q != NULL)
-        {                       // found something
-          dot = q;              // found new pattern- goto it
-          msg = (Byte *) "search hit BOTTOM, continuing at TOP";
-          if (dir == BACK)
-            {
-              msg = (Byte *) "search hit TOP, continuing at BOTTOM";
-            }
-        }
-      else
-        {
-          msg = (Byte *) "Pattern not found";
-        }
-    dc2:
-      psbs ("%s", msg);
-      break;
-    case '{':                  // {- move backward paragraph
-      q = char_search (dot, (Byte *) "\n\n", BACK, FULL);
-      if (q != NULL)
-        {                       // found blank line
-          dot = next_line (q);  // move to next blank line
-        }
-      break;
-    case '}':                  // }- move forward paragraph
-      q = char_search (dot, (Byte *) "\n\n", FORWARD, FULL);
-      if (q != NULL)
-        {                       // found blank line
-          dot = next_line (q);  // move to next blank line
-        }
-      break;
-#endif /* BB_FEATURE_VI_SEARCH */
-    case '0':                  // 0- goto begining of line
-    case '1':                  // 1- 
-    case '2':                  // 2- 
-    case '3':                  // 3- 
-    case '4':                  // 4- 
-    case '5':                  // 5- 
-    case '6':                  // 6- 
-    case '7':                  // 7- 
-    case '8':                  // 8- 
-    case '9':                  // 9- 
-      if (c == '0' && cmdcnt < 1)
-        {
-          dot_begin ();         // this was a standalone zero
-        }
-      else
-        {
-          cmdcnt = cmdcnt * 10 + (c - '0'); // this 0 is part of a number
-        }
-      break;
-    case ':':                  // :- the colon mode commands
-      p = get_input_line ((Byte *) ":");  // get input line- use "status line"
-#ifdef BB_FEATURE_VI_COLON
-      colon (p);                // execute the command
-#else /* BB_FEATURE_VI_COLON */
-      if (*p == ':')
-        p++;                    // move past the ':'
-      cnt = strlen ((char *) p);
-      if (cnt <= 0)
-        break;
-      if (strncasecmp ((char *) p, "quit", cnt) == 0 ||
-          strncasecmp ((char *) p, "q!", cnt) == 0)
-        {                       // delete lines
-          if (file_modified == TRUE && p[1] != '!')
-            {
-              psbs ("No write since last change (:quit! overrides)");
-            }
-          else
-            {
-              editing = 0;
-            }
-        }
-      else if (strncasecmp ((char *) p, "write", cnt) == 0 ||
-               strncasecmp ((char *) p, "wq", cnt) == 0)
-        {
-          cnt = file_write (cfn, text, end - 1);
-          file_modified = FALSE;
-          psb ("\"%s\" %dL, %dC", cfn, count_lines (text, end - 1), cnt);
-          if (p[1] == 'q')
-            {
-              editing = 0;
-            }
-        }
-      else if (strncasecmp ((char *) p, "file", cnt) == 0)
-        {
-          edit_status ();       // show current file status
-        }
-      else if (sscanf ((char *) p, "%d", &j) > 0)
-        {
-          dot = find_line (j);  // go to line # j
-          dot_skip_over_ws ();
-        }
-      else
-        {                       // unrecognised cmd
-          ni ((Byte *) p);
-        }
-#endif /* BB_FEATURE_VI_COLON */
-      break;
-    case '<':                  // <- Left  shift something
-    case '>':                  // >- Right shift something
-      cnt = count_lines (text, dot);  // remember what line we are on
-      c1 = get_one_char ();     // get the type of thing to delete
-      find_range (&p, &q, c1);
-      (void) yank_delete (p, q, 1, YANKONLY); // save copy before change
-      p = begin_line (p);
-      q = end_line (q);
-      i = count_lines (p, q);   // # of lines we are shifting
-      for (; i > 0; i--, p = next_line (p))
-        {
-          if (c == '<')
-            {
-              // shift left- remove tab or 8 spaces
-              if (*p == '\t')
-                {
-                  // shrink buffer 1 char
-                  (void) text_hole_delete (p, p);
-                }
-              else if (*p == ' ')
-                {
-                  // we should be calculating columns, not just SPACE
-                  for (j = 0; *p == ' ' && j < tabstop; j++)
-                    {
-                      (void) text_hole_delete (p, p);
-                    }
-                }
-            }
-          else if (c == '>')
-            {
-              // shift right -- add tab or 8 spaces
-              (void) char_insert (p, '\t');
-            }
-        }
-      dot = find_line (cnt);    // what line were we on
-      dot_skip_over_ws ();
-      end_cmd_q ();             // stop adding to q
-      break;
-    case 'A':                  // A- append at e-o-l
-      dot_end ();               // go to e-o-l
-      //**** fall thru to ... 'a'
-    case 'a':                  // a- append after current char
-      if (*dot != '\n')
-        dot++;
-      goto dc_i;
-      break;
-    case 'B':                  // B- back a blank-delimited Word
-    case 'E':                  // E- end of a blank-delimited word
-    case 'W':                  // W- forward a blank-delimited word
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dir = FORWARD;
-      if (c == 'B')
-        dir = BACK;
-      if (c == 'W' || isspace (dot[dir]))
-        {
-          dot = skip_thing (dot, 1, dir, S_TO_WS);
-          dot = skip_thing (dot, 2, dir, S_OVER_WS);
-        }
-      if (c != 'W')
-        dot = skip_thing (dot, 1, dir, S_BEFORE_WS);
-      break;
-    case 'C':                  // C- Change to e-o-l
-    case 'D':                  // D- delete to e-o-l
-      save_dot = dot;
-      dot = dollar_line (dot);  // move to before NL
-      // copy text into a register and delete
-      dot = yank_delete (save_dot, dot, 0, YANKDEL);  // delete to e-o-l
-      if (c == 'C')
-        goto dc_i;              // start inserting
-#ifdef BB_FEATURE_VI_DOT_CMD
-      if (c == 'D')
-        end_cmd_q ();           // stop adding to q
-#endif /* BB_FEATURE_VI_DOT_CMD */
-      break;
-    case 'G':                  // G- goto to a line number (default= E-O-F)
-      dot = end - 1;            // assume E-O-F
-      if (cmdcnt > 0)
-        {
-          dot = find_line (cmdcnt); // what line is #cmdcnt
-        }
-      dot_skip_over_ws ();
-      break;
-    case 'H':                  // H- goto top line on screen
-      dot = screenbegin;
-      if (cmdcnt > (rows - 1))
-        {
-          cmdcnt = (rows - 1);
-        }
-      if (cmdcnt-- > 1)
-        {
-          do_cmd ('+');
-        }                       // repeat cnt
-      dot_skip_over_ws ();
-      break;
-    case 'I':                  // I- insert before first non-blank
-      dot_begin ();             // 0
-      dot_skip_over_ws ();
-      //**** fall thru to ... 'i'
-    case 'i':                  // i- insert before current char
-    case VI_K_INSERT:          // Cursor Key Insert
-    dc_i:
-      cmd_mode = 1;             // start insrting
-      psb ("-- Insert --");
-      break;
-    case 'J':                  // J- join current and next lines together
-      if (cmdcnt-- > 2)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dot_end ();               // move to NL
-      if (dot < end - 1)
-        {                       // make sure not last char in text[]
-          *dot++ = ' ';         // replace NL with space
-          while (isblnk (*dot))
-            {                   // delete leading WS
-              dot_delete ();
-            }
-        }
-      end_cmd_q ();             // stop adding to q
-      break;
-    case 'L':                  // L- goto bottom line on screen
-      dot = end_screen ();
-      if (cmdcnt > (rows - 1))
-        {
-          cmdcnt = (rows - 1);
-        }
-      if (cmdcnt-- > 1)
-        {
-          do_cmd ('-');
-        }                       // repeat cnt
-      dot_begin ();
-      dot_skip_over_ws ();
-      break;
-    case 'M':                  // M- goto middle line on screen
-      dot = screenbegin;
-      for (cnt = 0; cnt < (rows - 1) / 2; cnt++)
-        dot = next_line (dot);
-      break;
-    case 'O':                  // O- open a empty line above
-      //    0i\n ESC -i
-      p = begin_line (dot);
-      if (p[-1] == '\n')
-        {
-          dot_prev ();
-    case 'o':                  // o- open a empty line below; Yes, I know it is in the middle of the "if (..."
-          dot_end ();
-          dot = char_insert (dot, '\n');
-        }
-      else
-        {
-          dot_begin ();         // 0
-          dot = char_insert (dot, '\n');  // i\n ESC
-          dot_prev ();          // -
-        }
-      goto dc_i;
-      break;
-    case 'R':                  // R- continuous Replace char
-    dc5:
-      cmd_mode = 2;
-      psb ("-- Replace --");
-      break;
-    case 'X':                  // X- delete char before dot
-    case 'x':                  // x- delete the current char
-    case 's':                  // s- substitute the current char
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dir = 0;
-      if (c == 'X')
-        dir = -1;
-      if (dot[dir] != '\n')
-        {
-          if (c == 'X')
-            dot--;              // delete prev char
-          dot = yank_delete (dot, dot, 0, YANKDEL); // delete char
-        }
-      if (c == 's')
-        goto dc_i;              // start insrting
-      end_cmd_q ();             // stop adding to q
-      break;
-    case 'Z':                  // Z- if modified, {write}; exit
-      // ZZ means to save file (if necessary), then exit
-      c1 = get_one_char ();
-      if (c1 != 'Z')
-        {
-          indicate_error (c);
-          break;
-        }
-      if (file_modified == TRUE
-#ifdef BB_FEATURE_VI_READONLY
-          && vi_readonly == FALSE && readonly == FALSE
-#endif /* BB_FEATURE_VI_READONLY */
-        )
-        {
-          cnt = file_write (cfn, text, end - 1);
-          if (cnt == (end - 1 - text + 1))
-            {
-              editing = 0;
-            }
-        }
-      else
-        {
-          editing = 0;
-        }
-      break;
-    case '^':                  // ^- move to first non-blank on line
-      dot_begin ();
-      dot_skip_over_ws ();
-      break;
-    case 'b':                  // b- back a word
-    case 'e':                  // e- end of word
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dir = FORWARD;
-      if (c == 'b')
-        dir = BACK;
-      if ((dot + dir) < text || (dot + dir) > end - 1)
-        break;
-      dot += dir;
-      if (isspace (*dot))
-        {
-          dot = skip_thing (dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS);
-        }
-      if (isalnum (*dot) || *dot == '_')
-        {
-          dot = skip_thing (dot, 1, dir, S_END_ALNUM);
-        }
-      else if (ispunct (*dot))
-        {
-          dot = skip_thing (dot, 1, dir, S_END_PUNCT);
-        }
-      break;
-    case 'c':                  // c- change something
-    case 'd':                  // d- delete something
-#ifdef BB_FEATURE_VI_YANKMARK
-    case 'y':                  // y- yank   something
-    case 'Y':                  // Y- Yank a line
-#endif /* BB_FEATURE_VI_YANKMARK */
-      yf = YANKDEL;             // assume either "c" or "d"
-#ifdef BB_FEATURE_VI_YANKMARK
-      if (c == 'y' || c == 'Y')
-        yf = YANKONLY;
-#endif /* BB_FEATURE_VI_YANKMARK */
-      c1 = 'y';
-      if (c != 'Y')
-        c1 = get_one_char ();   // get the type of thing to delete
-      find_range (&p, &q, c1);
-      if (c1 == 27)
-        {                       // ESC- user changed mind and wants out
-          c = c1 = 27;          // Escape- do nothing
-        }
-      else if (strchr ("wW", c1))
-        {
-          if (c == 'c')
-            {
-              // don't include trailing WS as part of word
-              while (isblnk (*q))
-                {
-                  if (q <= text || q[-1] == '\n')
-                    break;
-                  q--;
-                }
-            }
-          dot = yank_delete (p, q, 0, yf);  // delete word
-        }
-      else if (strchr ("^0bBeEft$", c1))
-        {
-          // single line copy text into a register and delete
-          dot = yank_delete (p, q, 0, yf);  // delete word
-        }
-      else if (strchr ("cdykjHL%+-{}\r\n", c1))
-        {
-          // multiple line copy text into a register and delete
-          dot = yank_delete (p, q, 1, yf);  // delete lines
-          if (c == 'c')
-            {
-              dot = char_insert (dot, '\n');
-              // on the last line of file don't move to prev line
-              if (dot != (end - 1))
-                {
-                  dot_prev ();
-                }
-            }
-          else if (c == 'd')
-            {
-              dot_begin ();
-              dot_skip_over_ws ();
-            }
-        }
-      else
-        {
-          // could not recognize object
-          c = c1 = 27;          // error-
-          indicate_error (c);
-        }
-      if (c1 != 27)
-        {
-          // if CHANGING, not deleting, start inserting after the delete
-          if (c == 'c')
-            {
-              strcpy ((char *) buf, "Change");
-              goto dc_i;        // start inserting
-            }
-          if (c == 'd')
-            {
-              strcpy ((char *) buf, "Delete");
-            }
-#ifdef BB_FEATURE_VI_YANKMARK
-          if (c == 'y' || c == 'Y')
-            {
-              strcpy ((char *) buf, "Yank");
-            }
-          p = reg[YDreg];
-          q = p + strlen ((char *) p);
-          for (cnt = 0; p <= q; p++)
-            {
-              if (*p == '\n')
-                cnt++;
-            }
-          psb ("%s %d lines (%d chars) using [%c]",
-               buf, cnt, strlen ((char *) reg[YDreg]), what_reg ());
-#endif /* BB_FEATURE_VI_YANKMARK */
-          end_cmd_q ();         // stop adding to q
-        }
-      break;
-    case 'k':                  // k- goto prev line, same col
-    case VI_K_UP:              // cursor key Up
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      dot_prev ();
-      dot = move_to_col (dot, ccol + offset); // try stay in same col
-      break;
-    case 'r':                  // r- replace the current char with user input
-      c1 = get_one_char ();     // get the replacement char
-      if (*dot != '\n')
-        {
-          *dot = c1;
-          file_modified = TRUE; // has the file been modified
-        }
-      end_cmd_q ();             // stop adding to q
-      break;
-    case 't':                  // t- move to char prior to next x
-      last_forward_char = get_one_char ();
-      do_cmd (';');
-      if (*dot == last_forward_char)
-        dot_left ();
-      last_forward_char = 0;
-      break;
-    case 'w':                  // w- forward a word
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      if (isalnum (*dot) || *dot == '_')
-        {                       // we are on ALNUM
-          dot = skip_thing (dot, 1, FORWARD, S_END_ALNUM);
-        }
-      else if (ispunct (*dot))
-        {                       // we are on PUNCT
-          dot = skip_thing (dot, 1, FORWARD, S_END_PUNCT);
-        }
-      if (dot < end - 1)
-        dot++;                  // move over word
-      if (isspace (*dot))
-        {
-          dot = skip_thing (dot, 2, FORWARD, S_OVER_WS);
-        }
-      break;
-    case 'z':                  // z-
-      c1 = get_one_char ();     // get the replacement char
-      cnt = 0;
-      if (c1 == '.')
-        cnt = (rows - 2) / 2;   // put dot at center
-      if (c1 == '-')
-        cnt = rows - 2;         // put dot at bottom
-      screenbegin = begin_line (dot); // start dot at top
-      dot_scroll (cnt, -1);
-      break;
-    case '|':                  // |- move to column "cmdcnt"
-      dot = move_to_col (dot, cmdcnt - 1);  // try to move to column
-      break;
-    case '~':                  // ~- flip the case of letters   a-z -> A-Z
-      if (cmdcnt-- > 1)
-        {
-          do_cmd (c);
-        }                       // repeat cnt
-      if (islower (*dot))
-        {
-          *dot = toupper (*dot);
-          file_modified = TRUE; // has the file been modified
-        }
-      else if (isupper (*dot))
-        {
-          *dot = tolower (*dot);
-          file_modified = TRUE; // has the file been modified
-        }
-      dot_right ();
-      end_cmd_q ();             // stop adding to q
-      break;
-      //----- The Cursor and Function Keys -----------------------------
-    case VI_K_HOME:            // Cursor Key Home
-      dot_begin ();
-      break;
-      // The Fn keys could point to do_macro which could translate them
-    case VI_K_FUN1:            // Function Key F1
-    case VI_K_FUN2:            // Function Key F2
-    case VI_K_FUN3:            // Function Key F3
-    case VI_K_FUN4:            // Function Key F4
-    case VI_K_FUN5:            // Function Key F5
-    case VI_K_FUN6:            // Function Key F6
-    case VI_K_FUN7:            // Function Key F7
-    case VI_K_FUN8:            // Function Key F8
-    case VI_K_FUN9:            // Function Key F9
-    case VI_K_FUN10:           // Function Key F10
-    case VI_K_FUN11:           // Function Key F11
-    case VI_K_FUN12:           // Function Key F12
-      break;
-    }
-
-dc1:
-  // if text[] just became empty, add back an empty line
-  if (end == text)
-    {
-      (void) char_insert (text, '\n');  // start empty buf with dummy line
-      dot = text;
-    }
-  // it is OK for dot to exactly equal to end, otherwise check dot validity
-  if (dot != end)
-    {
-      dot = bound_dot (dot);    // make sure "dot" is valid
-    }
-#ifdef BB_FEATURE_VI_YANKMARK
-  check_context (c);            // update the current context
-#endif /* BB_FEATURE_VI_YANKMARK */
-
-  if (!isdigit (c))
-    cmdcnt = 0;                 // cmd was not a number, reset cmdcnt
-  cnt = dot - begin_line (dot);
-  // Try to stay off of the Newline
-  if (*dot == '\n' && cnt > 0 && cmd_mode == 0)
-    dot--;
-}
-
-//----- The Colon commands -------------------------------------
-#ifdef BB_FEATURE_VI_COLON
-static Byte *
-get_one_address (Byte * p, int *addr) // get colon addr, if present
-{
-  int st;
-  Byte *q;
-
-#ifdef BB_FEATURE_VI_YANKMARK
-  Byte c;
-#endif /* BB_FEATURE_VI_YANKMARK */
-#ifdef BB_FEATURE_VI_SEARCH
-  Byte *pat, buf[BUFSIZ];
-#endif /* BB_FEATURE_VI_SEARCH */
-
-  *addr = -1;                   // assume no addr
-  if (*p == '.')
-    {                           // the current line
-      p++;
-      q = begin_line (dot);
-      *addr = count_lines (text, q);
-#ifdef BB_FEATURE_VI_YANKMARK
-    }
-  else if (*p == '\'')
-    {                           // is this a mark addr
-      p++;
-      c = tolower (*p);
-      p++;
-      if (c >= 'a' && c <= 'z')
-        {
-          // we have a mark
-          c = c - 'a';
-          q = mark[(int) c];
-          if (q != NULL)
-            {                   // is mark valid
-              *addr = count_lines (text, q);  // count lines
-            }
-        }
-#endif /* BB_FEATURE_VI_YANKMARK */
-#ifdef BB_FEATURE_VI_SEARCH
-    }
-  else if (*p == '/')
-    {                           // a search pattern
-      q = buf;
-      for (p++; *p; p++)
-        {
-          if (*p == '/')
-            break;
-          *q++ = *p;
-          *q = '\0';
-        }
-      pat = (Byte *) strdup ((char *) buf); // save copy of pattern
-      if (*p == '/')
-        p++;
-      q = char_search (dot, pat, FORWARD, FULL);
-      if (q != NULL)
-        {
-          *addr = count_lines (text, q);
-        }
-      free (pat);
-#endif /* BB_FEATURE_VI_SEARCH */
-    }
-  else if (*p == '$')
-    {                           // the last line in file
-      p++;
-      q = begin_line (end - 1);
-      *addr = count_lines (text, q);
-    }
-  else if (isdigit (*p))
-    {                           // specific line number
-      sscanf ((char *) p, "%d%n", addr, &st);
-      p += st;
-    }
-  else
-    {                           // I don't reconise this
-      // unrecognised address- assume -1
-      *addr = -1;
-    }
-  return (p);
-}
-
-static Byte *
-get_address (Byte * p, int *b, int *e)  // get two colon addrs, if present
-{
-  //----- get the address' i.e., 1,3   'a,'b  -----
-  // get FIRST addr, if present
-  while (isblnk (*p))
-    p++;                        // skip over leading spaces
-  if (*p == '%')
-    {                           // alias for 1,$
-      p++;
-      *b = 1;
-      *e = count_lines (text, end - 1);
-      goto ga0;
-    }
-  p = get_one_address (p, b);
-  while (isblnk (*p))
-    p++;
-  if (*p == ',')
-    {                           // is there a address seperator
-      p++;
-      while (isblnk (*p))
-        p++;
-      // get SECOND addr, if present
-      p = get_one_address (p, e);
-    }
-ga0:
-  while (isblnk (*p))
-    p++;                        // skip over trailing spaces
-  return (p);
-}
-
-static void
-colon (Byte * buf)
-{
-  Byte c, *orig_buf, *buf1, *q, *r;
-  Byte *fn, cmd[BUFSIZ], args[BUFSIZ];
-  int i, l, li, ch, st, b, e;
-  int useforce, forced;
-  struct stat st_buf;
-
-  // :3154        // if (-e line 3154) goto it  else stay put
-  // :4,33w! foo  // write a portion of buffer to file "foo"
-  // :w           // write all of buffer to current file
-  // :q           // quit
-  // :q!          // quit- dont care about modified file
-  // :'a,'z!sort -u   // filter block through sort
-  // :'f          // goto mark "f"
-  // :'fl         // list literal the mark "f" line
-  // :.r bar      // read file "bar" into buffer before dot
-  // :/123/,/abc/d    // delete lines from "123" line to "abc" line
-  // :/xyz/       // goto the "xyz" line
-  // :s/find/replace/ // substitute pattern "find" with "replace"
-  // :!<cmd>      // run <cmd> then return
-  //
-  if (strlen ((char *) buf) <= 0)
-    goto vc1;
-  if (*buf == ':')
-    buf++;                      // move past the ':'
-
-  forced = useforce = FALSE;
-  li = st = ch = i = 0;
-  b = e = -1;
-  q = text;                     // assume 1,$ for the range
-  r = end - 1;
-  li = count_lines (text, end - 1);
-  fn = cfn;                     // default to current file
-  memset (cmd, '\0', BUFSIZ);   // clear cmd[]
-  memset (args, '\0', BUFSIZ);  // clear args[]
-
-  // look for optional address(es)  :.  :1  :1,9   :'q,'a   :%
-  buf = get_address (buf, &b, &e);
-
-  // remember orig command line
-  orig_buf = buf;
-
-  // get the COMMAND into cmd[]
-  buf1 = cmd;
-  while (*buf != '\0')
-    {
-      if (isspace (*buf))
-        break;
-      *buf1++ = *buf++;
-    }
-  // get any ARGuments
-  while (isblnk (*buf))
-    buf++;
-  strcpy ((char *) args, (char *) buf);
-  buf1 = last_char_is ((char *) cmd, '!');
-  if (buf1)
-    {
-      useforce = TRUE;
-      *buf1 = '\0';             // get rid of !
-    }
-  if (b >= 0)
-    {
-      // if there is only one addr, then the addr
-      // is the line number of the single line the
-      // user wants. So, reset the end
-      // pointer to point at end of the "b" line
-      q = find_line (b);        // what line is #b
-      r = end_line (q);
-      li = 1;
-    }
-  if (e >= 0)
-    {
-      // we were given two addrs.  change the
-      // end pointer to the addr given by user.
-      r = find_line (e);        // what line is #e
-      r = end_line (r);
-      li = e - b + 1;
-    }
-  // ------------ now look for the command ------------
-  i = strlen ((char *) cmd);
-  if (i == 0)
-    {                           // :123CR goto line #123
-      if (b >= 0)
-        {
-          dot = find_line (b);  // what line is #b
-          dot_skip_over_ws ();
-        }
-    }
-  else if (0)
-    {
-      // } else if (strncmp((char *) cmd, "!", 1) == 0) {     // run a cmd
-      // :!ls   run the <cmd>
-      // (void) alarm(0);             // wait for input- no alarms
-      place_cursor (rows - 1, 0, FALSE);  // go to Status line
-      clear_to_eol ();          // clear the line
-      cookmode ();
-      system (orig_buf + 1);    // run the cmd
-      rawmode ();
-      Hit_Return ();            // let user see results
-      // (void) alarm(3);             // done waiting for input
-    }
-  else if (strncmp ((char *) cmd, "=", i) == 0)
-    {                           // where is the address
-      if (b < 0)
-        {                       // no addr given- use defaults
-          b = e = count_lines (text, dot);
-        }
-      psb ("%d", b);
-    }
-  else if (strncasecmp ((char *) cmd, "delete", i) == 0)
-    {                           // delete lines
-      if (b < 0)
-        {                       // no addr given- use defaults
-          q = begin_line (dot); // assume .,. for the range
-          r = end_line (dot);
-        }
-      dot = yank_delete (q, r, 1, YANKDEL); // save, then delete lines
-      dot_skip_over_ws ();
-    }
-  else if (0)
-    {
-      // } else if (strncasecmp((char *) cmd, "edit", i) == 0) {      // Edit a file
-      int sr;
-      sr = 0;
-      // don't edit, if the current file has been modified
-      if (file_modified == TRUE && useforce != TRUE)
-        {
-          psbs ("No write since last change (:edit! overrides)");
-          goto vc1;
-        }
-      if (strlen (args) > 0)
-        {
-          // the user supplied a file name
-          fn = args;
-        }
-      else if (cfn != 0 && strlen (cfn) > 0)
-        {
-          // no user supplied name- use the current filename
-          fn = cfn;
-          goto vc5;
-        }
-      else
-        {
-          // no user file name, no current name- punt
-          psbs ("No current filename");
-          goto vc1;
-        }
-
-      // see if file exists- if not, its just a new file request
-      if ((sr = stat ((char *) fn, &st_buf)) < 0)
-        {
-          // This is just a request for a new file creation.
-          // The file_insert below will fail but we get
-          // an empty buffer with a file name.  Then the "write"
-          // command can do the create.
-        }
-      else
-        {
-          if ((st_buf.st_mode & (S_IFREG)) == 0)
-            {
-              // This is not a regular file
-              psbs ("\"%s\" is not a regular file", fn);
-              goto vc1;
-            }
-          if ((st_buf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0)
-            {
-              // dont have any read permissions
-              psbs ("\"%s\" is not readable", fn);
-              goto vc1;
-            }
-        }
-
-      // There is a read-able regular file
-      // make this the current file
-      q = (Byte *) strdup ((char *) fn);  // save the cfn
-      if (cfn != 0)
-        free (cfn);             // free the old name
-      cfn = q;                  // remember new cfn
-
-    vc5:
-      // delete all the contents of text[]
-      new_text (2 * file_size (fn));
-      screenbegin = dot = end = text;
-
-      // insert new file
-      ch = file_insert (fn, text, file_size (fn));
-
-      if (ch < 1)
-        {
-          // start empty buf with dummy line
-          (void) char_insert (text, '\n');
-          ch = 1;
-        }
-      file_modified = FALSE;
-#ifdef BB_FEATURE_VI_YANKMARK
-      if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0)
-        {
-          free (reg[Ureg]);     //   free orig line reg- for 'U'
-          reg[Ureg] = 0;
-        }
-      if (YDreg >= 0 && YDreg < 28 && reg[YDreg] != 0)
-        {
-          free (reg[YDreg]);    //   free default yank/delete register
-          reg[YDreg] = 0;
-        }
-      for (li = 0; li < 28; li++)
-        {
-          mark[li] = 0;
-        }                       // init the marks
-#endif /* BB_FEATURE_VI_YANKMARK */
-      // how many lines in text[]?
-      li = count_lines (text, end - 1);
-      psb ("\"%s\"%s"
-#ifdef BB_FEATURE_VI_READONLY
-           "%s"
-#endif /* BB_FEATURE_VI_READONLY */
-           " %dL, %dC", cfn, (sr < 0 ? " [New file]" : ""),
-#ifdef BB_FEATURE_VI_READONLY
-           ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""),
-#endif /* BB_FEATURE_VI_READONLY */
-           li, ch);
-    }
-  else if (0)
-    {
-      // } else if (strncasecmp((char *) cmd, "file", i) == 0) {      // what File is this
-      if (b != -1 || e != -1)
-        {
-          ni ((Byte *) "No address allowed on this command");
-          goto vc1;
-        }
-      if (strlen ((char *) args) > 0)
-        {
-          // user wants a new filename
-          if (cfn != NULL)
-            free (cfn);
-          cfn = (Byte *) strdup ((char *) args);
-        }
-      else
-        {
-          // user wants file status info
-          edit_status ();
-        }
-    }
-  else if (strncasecmp ((char *) cmd, "features", i) == 0)
-    {                           // what features are available
-      // print out values of all features
-      place_cursor (rows - 1, 0, FALSE);  // go to Status line, bottom of screen
-      clear_to_eol ();          // clear the line
-      cookmode ();
-      show_help ();
-      rawmode ();
-      Hit_Return ();
-    }
-  else if (strncasecmp ((char *) cmd, "list", i) == 0)
-    {                           // literal print line
-      if (b < 0)
-        {                       // no addr given- use defaults
-          q = begin_line (dot); // assume .,. for the range
-          r = end_line (dot);
-        }
-      place_cursor (rows - 1, 0, FALSE);  // go to Status line, bottom of screen
-      clear_to_eol ();          // clear the line
-      write (1, "\r\n", 2);
-      for (; q <= r; q++)
-        {
-          c = *q;
-          if (c > '~')
-            standout_start ();
-          if (c == '\n')
-            {
-              write (1, "$\r", 2);
-            }
-          else if (*q < ' ')
-            {
-              write (1, "^", 1);
-              c += '@';
-            }
-          write (1, &c, 1);
-          if (c > '~')
-            standout_end ();
-        }
-#ifdef BB_FEATURE_VI_SET
-    vc2:
-#endif /* BB_FEATURE_VI_SET */
-      Hit_Return ();
-    }
-  else if ((strncasecmp ((char *) cmd, "quit", i) == 0) ||  // Quit
-           (strncasecmp ((char *) cmd, "next", i) == 0))
-    {                           // edit next file
-      if (useforce == TRUE)
-        {
-          // force end of argv list
-          if (*cmd == 'q')
-            {
-              optind = save_argc;
-            }
-          editing = 0;
-          goto vc1;
-        }
-      // don't exit if the file been modified
-      if (file_modified == TRUE)
-        {
-          psbs ("No write since last change (:%s! overrides)",
-                (*cmd == 'q' ? "quit" : "next"));
-          goto vc1;
-        }
-      // are there other file to edit
-      /* if (*cmd == 'q' && optind < save_argc - 1) {
-         psbs("%d more file to edit", (save_argc - optind - 1));
-         goto vc1;
-         }
-         if (*cmd == 'n' && optind >= save_argc - 1) {
-         psbs("No more files to edit");
-         goto vc1;
-         } */
-      editing = 0;
-    }
-  else if (0)
-    {
-      // } else if (strncasecmp((char *) cmd, "read", i) == 0) {      // read file into text[]
-      fn = args;
-      if (strlen ((char *) fn) <= 0)
-        {
-          psbs ("No filename given");
-          goto vc1;
-        }
-      if (b < 0)
-        {                       // no addr given- use defaults
-          q = begin_line (dot); // assume "dot"
-        }
-      // read after current line- unless user said ":0r foo"
-      if (b != 0)
-        q = next_line (q);
-#ifdef BB_FEATURE_VI_READONLY
-      l = readonly;             // remember current files' status
-#endif
-      ch = file_insert (fn, q, file_size (fn));
-#ifdef BB_FEATURE_VI_READONLY
-      readonly = l;
-#endif
-      if (ch < 0)
-        goto vc1;               // nothing was inserted
-      // how many lines in text[]?
-      li = count_lines (q, q + ch - 1);
-      psb ("\"%s\""
-#ifdef BB_FEATURE_VI_READONLY
-           "%s"
-#endif /* BB_FEATURE_VI_READONLY */
-           " %dL, %dC", fn,
-#ifdef BB_FEATURE_VI_READONLY
-           ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""),
-#endif /* BB_FEATURE_VI_READONLY */
-           li, ch);
-      if (ch > 0)
-        {
-          // if the insert is before "dot" then we need to update
-          if (q <= dot)
-            dot += ch;
-          file_modified = TRUE;
-        }
-    }
-  else if (strncasecmp ((char *) cmd, "rewind", i) == 0)
-    {                           // rewind cmd line args
-      if (file_modified == TRUE && useforce != TRUE)
-        {
-          psbs ("No write since last change (:rewind! overrides)");
-        }
-      else
-        {
-          // reset the filenames to edit
-          optind = fn_start - 1;
-          editing = 0;
-        }
-#ifdef BB_FEATURE_VI_SET
-    }
-  else if (strncasecmp ((char *) cmd, "set", i) == 0)
-    {                           // set or clear features
-      i = 0;                    // offset into args
-      if (strlen ((char *) args) == 0)
-        {
-          // print out values of all options
-          place_cursor (rows - 1, 0, FALSE);  // go to Status line, bottom of screen
-          clear_to_eol ();      // clear the line
-          printf ("----------------------------------------\r\n");
-#ifdef BB_FEATURE_VI_SETOPTS
-          if (!autoindent)
-            printf ("no");
-          printf ("autoindent ");
-          if (!err_method)
-            printf ("no");
-          printf ("flash ");
-          if (!ignorecase)
-            printf ("no");
-          printf ("ignorecase ");
-          if (!showmatch)
-            printf ("no");
-          printf ("showmatch ");
-          printf ("tabstop=%d ", tabstop);
-#endif /* BB_FEATURE_VI_SETOPTS */
-          printf ("\r\n");
-          goto vc2;
-        }
-      if (strncasecmp ((char *) args, "no", 2) == 0)
-        i = 2;                  // ":set noautoindent"
-#ifdef BB_FEATURE_VI_SETOPTS
-      if (strncasecmp ((char *) args + i, "autoindent", 10) == 0 ||
-          strncasecmp ((char *) args + i, "ai", 2) == 0)
-        {
-          autoindent = (i == 2) ? 0 : 1;
-        }
-      if (strncasecmp ((char *) args + i, "flash", 5) == 0 ||
-          strncasecmp ((char *) args + i, "fl", 2) == 0)
-        {
-          err_method = (i == 2) ? 0 : 1;
-        }
-      if (strncasecmp ((char *) args + i, "ignorecase", 10) == 0 ||
-          strncasecmp ((char *) args + i, "ic", 2) == 0)
-        {
-          ignorecase = (i == 2) ? 0 : 1;
-        }
-      if (strncasecmp ((char *) args + i, "showmatch", 9) == 0 ||
-          strncasecmp ((char *) args + i, "sm", 2) == 0)
-        {
-          showmatch = (i == 2) ? 0 : 1;
-        }
-      if (strncasecmp ((char *) args + i, "tabstop", 7) == 0)
-        {
-          sscanf (strchr ((char *) args + i, '='), "=%d", &ch);
-          if (ch > 0 && ch < columns - 1)
-            tabstop = ch;
-        }
-#endif /* BB_FEATURE_VI_SETOPTS */
-#endif /* BB_FEATURE_VI_SET */
-#ifdef BB_FEATURE_VI_SEARCH
-    }
-  else if (strncasecmp ((char *) cmd, "s", 1) == 0)
-    {                           // substitute a pattern with a replacement pattern
-      Byte *ls, *F, *R;
-      int gflag;
-
-      // F points to the "find" pattern
-      // R points to the "replace" pattern
-      // replace the cmd line delimiters "/" with NULLs
-      gflag = 0;                // global replace flag
-      c = orig_buf[1];          // what is the delimiter
-      F = orig_buf + 2;         // start of "find"
-      R = (Byte *) strchr ((char *) F, c);  // middle delimiter
-      if (!R)
-        goto colon_s_fail;
-      *R++ = '\0';              // terminate "find"
-      buf1 = (Byte *) strchr ((char *) R, c);
-      if (!buf1)
-        goto colon_s_fail;
-      *buf1++ = '\0';           // terminate "replace"
-      if (*buf1 == 'g')
-        {                       // :s/foo/bar/g
-          buf1++;
-          gflag++;              // turn on gflag
-        }
-      q = begin_line (q);
-      if (b < 0)
-        {                       // maybe :s/foo/bar/
-          q = begin_line (dot); // start with cur line
-          b = count_lines (text, q);  // cur line number
-        }
-      if (e < 0)
-        e = b;                  // maybe :.s/foo/bar/
-      for (i = b; i <= e; i++)
-        {                       // so, :20,23 s \0 find \0 replace \0
-          ls = q;               // orig line start
-        vc4:
-          buf1 = char_search (q, F, FORWARD, LIMITED);  // search cur line only for "find"
-          if (buf1 != NULL)
-            {
-              // we found the "find" pattern- delete it
-              (void) text_hole_delete (buf1, buf1 + strlen ((char *) F) - 1);
-              // inset the "replace" patern
-              (void) string_insert (buf1, R); // insert the string
-              // check for "global"  :s/foo/bar/g
-              if (gflag == 1)
-                {
-                  if ((buf1 + strlen ((char *) R)) < end_line (ls))
-                    {
-                      q = buf1 + strlen ((char *) R);
-                      goto vc4; // don't let q move past cur line
-                    }
-                }
-            }
-          q = next_line (ls);
-        }
-#endif /* BB_FEATURE_VI_SEARCH */
-    }
-  else if (strncasecmp ((char *) cmd, "version", i) == 0)
-    {                           // show software version
-      psb ("%s", vi_Version);
-    }
-  else if ((strncasecmp ((char *) cmd, "write", i) == 0) || // write text to file
-           (strncasecmp ((char *) cmd, "wq", i) == 0))
-    {                           // write text to file
-      // is there a file name to write to?
-      /* if (strlen((char *) args) > 0) {
-         fn = args;
-         } */
-#ifdef BB_FEATURE_VI_READONLY
-      if ((vi_readonly == TRUE || readonly == TRUE) && useforce == FALSE)
-        {
-          psbs ("\"%s\" File is read only", fn);
-          goto vc3;
-        }
-#endif /* BB_FEATURE_VI_READONLY */
-      // how many lines in text[]?
-      li = count_lines (q, r);
-      ch = r - q + 1;
-      // see if file exists- if not, its just a new file request
-      if (useforce == TRUE)
-        {
-          // if "fn" is not write-able, chmod u+w
-          // sprintf(syscmd, "chmod u+w %s", fn);
-          // system(syscmd);
-          forced = TRUE;
-        }
-      l = file_write (fn, q, r);
-      if (useforce == TRUE && forced == TRUE)
-        {
-          // chmod u-w
-          // sprintf(syscmd, "chmod u-w %s", fn);
-          // system(syscmd);
-          forced = FALSE;
-        }
-      psb ("\"%s\" %dL, %dC", fn, li, l);
-      if (q == text && r == end - 1 && l == ch)
-        file_modified = FALSE;
-      if (cmd[1] == 'q' && l == ch)
-        {
-          editing = 0;
-        }
-#ifdef BB_FEATURE_VI_READONLY
-    vc3:;
-#endif /* BB_FEATURE_VI_READONLY */
-#ifdef BB_FEATURE_VI_YANKMARK
-    }
-  else if (strncasecmp ((char *) cmd, "yank", i) == 0)
-    {                           // yank lines
-      if (b < 0)
-        {                       // no addr given- use defaults
-          q = begin_line (dot); // assume .,. for the range
-          r = end_line (dot);
-        }
-      text_yank (q, r, YDreg);
-      li = count_lines (q, r);
-      psb ("Yank %d lines (%d chars) into [%c]",
-           li, strlen ((char *) reg[YDreg]), what_reg ());
-#endif /* BB_FEATURE_VI_YANKMARK */
-    }
-  else
-    {
-      // cmd unknown
-      ni ((Byte *) cmd);
-    }
-vc1:
-  dot = bound_dot (dot);        // make sure "dot" is valid
-  return;
-#ifdef BB_FEATURE_VI_SEARCH
-colon_s_fail:
-  psb (":s expression missing delimiters");
-  return;
-#endif
-
-}
-
-static void
-Hit_Return (void)
-{
-  char c;
-
-  standout_start ();            // start reverse video
-  write (1, "[Hit return to continue]", 24);
-  standout_end ();              // end reverse video
-  while ((c = get_one_char ()) != '\n' && c != '\r')  /*do nothing */
-    ;
-  redraw (TRUE);                // force redraw all
-}
-#endif /* BB_FEATURE_VI_COLON */
-
-//----- Synchronize the cursor to Dot --------------------------
-static void
-sync_cursor (Byte * d, int *row, int *col)
-{
-  Byte *beg_cur, *end_cur;      // begin and end of "d" line
-  Byte *beg_scr, *end_scr;      // begin and end of screen
-  Byte *tp;
-  int cnt, ro, co;
-
-  beg_cur = begin_line (d);     // first char of cur line
-  end_cur = end_line (d);       // last char of cur line
-
-  beg_scr = end_scr = screenbegin;  // first char of screen
-  end_scr = end_screen ();      // last char of screen
-
-  if (beg_cur < screenbegin)
-    {
-      // "d" is before  top line on screen
-      // how many lines do we have to move
-      cnt = count_lines (beg_cur, screenbegin);
-    sc1:
-      screenbegin = beg_cur;
-      if (cnt > (rows - 1) / 2)
-        {
-          // we moved too many lines. put "dot" in middle of screen
-          for (cnt = 0; cnt < (rows - 1) / 2; cnt++)
-            {
-              screenbegin = prev_line (screenbegin);
-            }
-        }
-    }
-  else if (beg_cur > end_scr)
-    {
-      // "d" is after bottom line on screen
-      // how many lines do we have to move
-      cnt = count_lines (end_scr, beg_cur);
-      if (cnt > (rows - 1) / 2)
-        goto sc1;               // too many lines
-      for (ro = 0; ro < cnt - 1; ro++)
-        {
-          // move screen begin the same amount
-          screenbegin = next_line (screenbegin);
-          // now, move the end of screen
-          end_scr = next_line (end_scr);
-          end_scr = end_line (end_scr);
-        }
-    }
-  // "d" is on screen- find out which row
-  tp = screenbegin;
-  for (ro = 0; ro < rows - 1; ro++)
-    {                           // drive "ro" to correct row
-      if (tp == beg_cur)
-        break;
-      tp = next_line (tp);
-    }
-
-  // find out what col "d" is on
-  co = 0;
-  do
-    {                           // drive "co" to correct column
-      if (*tp == '\n' || *tp == '\0')
-        break;
-      if (*tp == '\t')
-        {
-          //         7       - (co %    8  )
-          co += ((tabstop - 1) - (co % tabstop));
-        }
-      else if (*tp < ' ')
-        {
-          co++;                 // display as ^X, use 2 columns
-        }
-    }
-  while (tp++ < d && ++co);
-
-  // "co" is the column where "dot" is.
-  // The screen has "columns" columns.
-  // The currently displayed columns are  0+offset -- columns+ofset
-  // |-------------------------------------------------------------|
-  //               ^ ^                                ^
-  //        offset | |------- columns ----------------|
-  //
-  // If "co" is already in this range then we do not have to adjust offset
-  //      but, we do have to subtract the "offset" bias from "co".
-  // If "co" is outside this range then we have to change "offset".
-  // If the first char of a line is a tab the cursor will try to stay
-  //  in column 7, but we have to set offset to 0.
-
-  if (co < 0 + offset)
-    {
-      offset = co;
-    }
-  if (co >= columns + offset)
-    {
-      offset = co - columns + 1;
-    }
-  // if the first char of the line is a tab, and "dot" is sitting on it
-  //  force offset to 0.
-  if (d == beg_cur && *d == '\t')
-    {
-      offset = 0;
-    }
-  co -= offset;
-
-  *row = ro;
-  *col = co;
-}
-
-//----- Text Movement Routines ---------------------------------
-static Byte *
-begin_line (Byte * p)           // return pointer to first char cur line
-{
-  while (p > text && p[-1] != '\n')
-    p--;                        // go to cur line B-o-l
-  return (p);
-}
-
-static Byte *
-end_line (Byte * p)             // return pointer to NL of cur line line
-{
-  while (p < end - 1 && *p != '\n')
-    p++;                        // go to cur line E-o-l
-  return (p);
-}
-
-static Byte *
-dollar_line (Byte * p)          // return pointer to just before NL line
-{
-  while (p < end - 1 && *p != '\n')
-    p++;                        // go to cur line E-o-l
-  // Try to stay off of the Newline
-  if (*p == '\n' && (p - begin_line (p)) > 0)
-    p--;
-  return (p);
-}
-
-static Byte *
-prev_line (Byte * p)            // return pointer first char prev line
-{
-  p = begin_line (p);           // goto begining of cur line
-  if (p[-1] == '\n' && p > text)
-    p--;                        // step to prev line
-  p = begin_line (p);           // goto begining of prev line
-  return (p);
-}
-
-static Byte *
-next_line (Byte * p)            // return pointer first char next line
-{
-  p = end_line (p);
-  if (*p == '\n' && p < end - 1)
-    p++;                        // step to next line
-  return (p);
-}
-
-//----- Text Information Routines ------------------------------
-static Byte *
-end_screen (void)
-{
-  Byte *q;
-  int cnt;
-
-  // find new bottom line
-  q = screenbegin;
-  for (cnt = 0; cnt < rows - 2; cnt++)
-    q = next_line (q);
-  q = end_line (q);
-  return (q);
-}
-
-static int
-count_lines (Byte * start, Byte * stop) // count line from start to stop
-{
-  Byte *q;
-  int cnt;
-
-  if (stop < start)
-    {                           // start and stop are backwards- reverse them
-      q = start;
-      start = stop;
-      stop = q;
-    }
-  cnt = 0;
-  stop = end_line (stop);       // get to end of this line
-  for (q = start; q <= stop && q <= end - 1; q++)
-    {
-      if (*q == '\n')
-        cnt++;
-    }
-  return (cnt);
-}
-
-static Byte *
-find_line (int li)              // find begining of line #li
-{
-  Byte *q;
-
-  for (q = text; li > 1; li--)
-    {
-      q = next_line (q);
-    }
-  return (q);
-}
-
-//----- Dot Movement Routines ----------------------------------
-static void
-dot_left (void)
-{
-  if (dot > text && dot[-1] != '\n')
-    dot--;
-}
-
-static void
-dot_right (void)
-{
-  if (dot < end - 1 && *dot != '\n')
-    dot++;
-}
-
-static void
-dot_begin (void)
-{
-  dot = begin_line (dot);       // return pointer to first char cur line
-}
-
-static void
-dot_end (void)
-{
-  dot = end_line (dot);         // return pointer to last char cur line
-}
-
-static Byte *
-move_to_col (Byte * p, int l)
-{
-  int co;
-
-  p = begin_line (p);
-  co = 0;
-  do
-    {
-      if (*p == '\n' || *p == '\0')
-        break;
-      if (*p == '\t')
-        {
-          //         7       - (co %    8  )
-          co += ((tabstop - 1) - (co % tabstop));
-        }
-      else if (*p < ' ')
-        {
-          co++;                 // display as ^X, use 2 columns
-        }
-    }
-  while (++co <= l && p++ < end);
-  return (p);
-}
-
-static void
-dot_next (void)
-{
-  dot = next_line (dot);
-}
-
-static void
-dot_prev (void)
-{
-  dot = prev_line (dot);
-}
-
-static void
-dot_scroll (int cnt, int dir)
-{
-  Byte *q;
-
-  for (; cnt > 0; cnt--)
-    {
-      if (dir < 0)
-        {
-          // scroll Backwards
-          // ctrl-Y  scroll up one line
-          screenbegin = prev_line (screenbegin);
-        }
-      else
-        {
-          // scroll Forwards
-          // ctrl-E  scroll down one line
-          screenbegin = next_line (screenbegin);
-        }
-    }
-  // make sure "dot" stays on the screen so we dont scroll off
-  if (dot < screenbegin)
-    dot = screenbegin;
-  q = end_screen ();            // find new bottom line
-  if (dot > q)
-    dot = begin_line (q);       // is dot is below bottom line?
-  dot_skip_over_ws ();
-}
-
-static void
-dot_skip_over_ws (void)
-{
-  // skip WS
-  while (isspace (*dot) && *dot != '\n' && dot < end - 1)
-    dot++;
-}
-
-static void
-dot_delete (void)               // delete the char at 'dot'
-{
-  (void) text_hole_delete (dot, dot);
-}
-
-static Byte *
-bound_dot (Byte * p)            // make sure  text[0] <= P < "end"
-{
-  if (p >= end && end > text)
-    {
-      p = end - 1;
-      indicate_error ('1');
-    }
-  if (p < text)
-    {
-      p = text;
-      indicate_error ('2');
-    }
-  return (p);
-}
-
-//----- Helper Utility Routines --------------------------------
-
-//----------------------------------------------------------------
-//----- Char Routines --------------------------------------------
-/* Chars that are part of a word-
- *    0123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
- * Chars that are Not part of a word (stoppers)
- *    !"#$%&'()*+,-./:;<=>?@[\]^`{|}~
- * Chars that are WhiteSpace
- *    TAB NEWLINE VT FF RETURN SPACE
- * DO NOT COUNT NEWLINE AS WHITESPACE
- */
-
-static Byte *
-new_screen (int ro, int co)
-{
-  int li;
-
-  if (screen != 0)
-    free (screen);
-  screensize = ro * co + 8;
-  screen = (Byte *) malloc (screensize);
-  // initialize the new screen. assume this will be a empty file.
-  screen_erase ();
-  //   non-existant text[] lines start with a tilde (~).
-  for (li = 1; li < ro - 1; li++)
-    {
-      screen[(li * co) + 0] = '~';
-    }
-  return (screen);
-}
-
-static Byte *
-new_text (int size)
-{
-  if (size < 10240)
-    size = 10240;               // have a minimum size for new files
-  if (text != 0)
-    {
-      //text -= 4;
-      free (text);
-    }
-  text = (Byte *) malloc (size + 8);
-  memset (text, '\0', size);    // clear new text[]
-  //text += 4;            // leave some room for "oops"
-  textend = text + size - 1;
-  //textend -= 4;         // leave some root for "oops"
-  return (text);
-}
-
-#ifdef BB_FEATURE_VI_SEARCH
-static int
-mycmp (Byte * s1, Byte * s2, int len)
-{
-  int i;
-
-  i = strncmp ((char *) s1, (char *) s2, len);
-#ifdef BB_FEATURE_VI_SETOPTS
-  if (ignorecase)
-    {
-      i = strncasecmp ((char *) s1, (char *) s2, len);
-    }
-#endif /* BB_FEATURE_VI_SETOPTS */
-  return (i);
-}
-
-static Byte *
-char_search (Byte * p, Byte * pat, int dir, int range)  // search for pattern starting at p
-{
-#ifndef REGEX_SEARCH
-  Byte *start, *stop;
-  int len;
-
-  len = strlen ((char *) pat);
-  if (dir == FORWARD)
-    {
-      stop = end - 1;           // assume range is p - end-1
-      if (range == LIMITED)
-        stop = next_line (p);   // range is to next line
-      for (start = p; start < stop; start++)
-        {
-          if (mycmp (start, pat, len) == 0)
-            {
-              return (start);
-            }
-        }
-    }
-  else if (dir == BACK)
-    {
-      stop = text;              // assume range is text - p
-      if (range == LIMITED)
-        stop = prev_line (p);   // range is to prev line
-      for (start = p - len; start >= stop; start--)
-        {
-          if (mycmp (start, pat, len) == 0)
-            {
-              return (start);
-            }
-        }
-    }
-  // pattern not found
-  return (NULL);
-#else /*REGEX_SEARCH */
-  char *q;
-  struct re_pattern_buffer preg;
-  int i;
-  int size, range;
-
-  re_syntax_options = RE_SYNTAX_POSIX_EXTENDED;
-  preg.translate = 0;
-  preg.fastmap = 0;
-  preg.buffer = 0;
-  preg.allocated = 0;
-
-  // assume a LIMITED forward search
-  q = next_line (p);
-  q = end_line (q);
-  q = end - 1;
-  if (dir == BACK)
-    {
-      q = prev_line (p);
-      q = text;
-    }
-  // count the number of chars to search over, forward or backward
-  size = q - p;
-  if (size < 0)
-    size = p - q;
-  // RANGE could be negative if we are searching backwards
-  range = q - p;
-
-  q = (char *) re_compile_pattern (pat, strlen ((char *) pat), &preg);
-  if (q != 0)
-    {
-      // The pattern was not compiled
-      psbs ("bad search pattern: \"%s\": %s", pat, q);
-      i = 0;                    // return p if pattern not compiled
-      goto cs1;
-    }
-
-  q = p;
-  if (range < 0)
-    {
-      q = p - size;
-      if (q < text)
-        q = text;
-    }
-  // search for the compiled pattern, preg, in p[]
-  // range < 0-  search backward
-  // range > 0-  search forward
-  // 0 < start < size
-  // re_search() < 0  not found or error
-  // re_search() > 0  index of found pattern
-  //            struct pattern    char     int    int    int     struct reg
-  // re_search (*pattern_buffer,  *string, size,  start, range,  *regs)
-  i = re_search (&preg, q, size, 0, range, 0);
-  if (i == -1)
-    {
-      p = 0;
-      i = 0;                    // return NULL if pattern not found
-    }
-cs1:
-  if (dir == FORWARD)
-    {
-      p = p + i;
-    }
-  else
-    {
-      p = p - i;
-    }
-  return (p);
-#endif /*REGEX_SEARCH */
-}
-#endif /* BB_FEATURE_VI_SEARCH */
-
-static Byte *
-char_insert (Byte * p, Byte c)  // insert the char c at 'p'
-{
-  if (c == 22)
-    {                           // Is this an ctrl-V?
-      p = stupid_insert (p, '^'); // use ^ to indicate literal next
-      p--;                      // backup onto ^
-      refresh (FALSE);          // show the ^
-      c = get_one_char ();
-      *p = c;
-      p++;
-      file_modified = TRUE;     // has the file been modified
-    }
-  else if (c == 27)
-    {                           // Is this an ESC?
-      cmd_mode = 0;
-      cmdcnt = 0;
-      end_cmd_q ();             // stop adding to q
-      strcpy ((char *) status_buffer, " "); // clear the status buffer
-      if ((p[-1] != '\n') && (dot > text))
-        {
-          p--;
-        }
-    }
-  else if (c == erase_char)
-    {                           // Is this a BS
-      //     123456789
-      if ((p[-1] != '\n') && (dot > text))
-        {
-          p--;
-          p = text_hole_delete (p, p);  // shrink buffer 1 char
-#ifdef BB_FEATURE_VI_DOT_CMD
-          // also rmove char from last_modifying_cmd
-          if (strlen ((char *) last_modifying_cmd) > 0)
-            {
-              Byte *q;
-
-              q = last_modifying_cmd;
-              q[strlen ((char *) q) - 1] = '\0';  // erase BS
-              q[strlen ((char *) q) - 1] = '\0';  // erase prev char
-            }
-#endif /* BB_FEATURE_VI_DOT_CMD */
-        }
-    }
-  else
-    {
-      // insert a char into text[]
-      Byte *sp;                 // "save p"
-
-      if (c == 13)
-        c = '\n';               // translate \r to \n
-      sp = p;                   // remember addr of insert
-      p = stupid_insert (p, c); // insert the char
-#ifdef BB_FEATURE_VI_SETOPTS
-      if (showmatch && strchr (")]}", *sp) != NULL)
-        {
-          showmatching (sp);
-        }
-      if (autoindent && c == '\n')
-        {                       // auto indent the new line
-          Byte *q;
-
-          q = prev_line (p);    // use prev line as templet
-          for (; isblnk (*q); q++)
-            {
-              p = stupid_insert (p, *q);  // insert the char
-            }
-        }
-#endif /* BB_FEATURE_VI_SETOPTS */
-    }
-  return (p);
-}
-
-static Byte *
-stupid_insert (Byte * p, Byte c)  // stupidly insert the char c at 'p'
-{
-  p = text_hole_make (p, 1);
-  if (p != 0)
-    {
-      *p = c;
-      file_modified = TRUE;     // has the file been modified
-      p++;
-    }
-  return (p);
-}
-
-static Byte
-find_range (Byte ** start, Byte ** stop, Byte c)
-{
-  Byte *save_dot, *p, *q;
-  int cnt;
-
-  save_dot = dot;
-  p = q = dot;
-
-  if (strchr ("cdy><", c))
-    {
-      // these cmds operate on whole lines
-      p = q = begin_line (p);
-      for (cnt = 1; cnt < cmdcnt; cnt++)
-        {
-          q = next_line (q);
-        }
-      q = end_line (q);
-    }
-  else if (strchr ("^%$0bBeEft", c))
-    {
-      // These cmds operate on char positions
-      do_cmd (c);               // execute movement cmd
-      q = dot;
-    }
-  else if (strchr ("wW", c))
-    {
-      do_cmd (c);               // execute movement cmd
-      if (dot > text)
-        dot--;                  // move back off of next word
-      if (dot > text && *dot == '\n')
-        dot--;                  // stay off NL
-      q = dot;
-    }
-  else if (strchr ("H-k{", c))
-    {
-      // these operate on multi-lines backwards
-      q = end_line (dot);       // find NL
-      do_cmd (c);               // execute movement cmd
-      dot_begin ();
-      p = dot;
-    }
-  else if (strchr ("L+j}\r\n", c))
-    {
-      // these operate on multi-lines forwards
-      p = begin_line (dot);
-      do_cmd (c);               // execute movement cmd
-      dot_end ();               // find NL
-      q = dot;
-    }
-  else
-    {
-      c = 27;                   // error- return an ESC char
-      //break;
-    }
-  *start = p;
-  *stop = q;
-  if (q < p)
-    {
-      *start = q;
-      *stop = p;
-    }
-  dot = save_dot;
-  return (c);
-}
-
-static int
-st_test (Byte * p, int type, int dir, Byte * tested)
-{
-  Byte c, c0, ci;
-  int test, inc;
-
-  inc = dir;
-  c = c0 = p[0];
-  ci = p[inc];
-  test = 0;
-
-  if (type == S_BEFORE_WS)
-    {
-      c = ci;
-      test = ((!isspace (c)) || c == '\n');
-    }
-  if (type == S_TO_WS)
-    {
-      c = c0;
-      test = ((!isspace (c)) || c == '\n');
-    }
-  if (type == S_OVER_WS)
-    {
-      c = c0;
-      test = ((isspace (c)));
-    }
-  if (type == S_END_PUNCT)
-    {
-      c = ci;
-      test = ((ispunct (c)));
-    }
-  if (type == S_END_ALNUM)
-    {
-      c = ci;
-      test = ((isalnum (c)) || c == '_');
-    }
-  *tested = c;
-  return (test);
-}
-
-static Byte *
-skip_thing (Byte * p, int linecnt, int dir, int type)
-{
-  Byte c;
-
-  while (st_test (p, type, dir, &c))
-    {
-      // make sure we limit search to correct number of lines
-      if (c == '\n' && --linecnt < 1)
-        break;
-      if (dir >= 0 && p >= end - 1)
-        break;
-      if (dir < 0 && p <= text)
-        break;
-      p += dir;                 // move to next char
-    }
-  return (p);
-}
-
-// find matching char of pair  ()  []  {}
-static Byte *
-find_pair (Byte * p, Byte c)
-{
-  Byte match, *q;
-  int dir, level;
-
-  match = ')';
-  level = 1;
-  dir = 1;                      // assume forward
-  switch (c)
-    {
-    case '(':
-      match = ')';
-      break;
-    case '[':
-      match = ']';
-      break;
-    case '{':
-      match = '}';
-      break;
-    case ')':
-      match = '(';
-      dir = -1;
-      break;
-    case ']':
-      match = '[';
-      dir = -1;
-      break;
-    case '}':
-      match = '{';
-      dir = -1;
-      break;
-    }
-  for (q = p + dir; text <= q && q < end; q += dir)
-    {
-      // look for match, count levels of pairs  (( ))
-      if (*q == c)
-        level++;                // increase pair levels
-      if (*q == match)
-        level--;                // reduce pair level
-      if (level == 0)
-        break;                  // found matching pair
-    }
-  if (level != 0)
-    q = NULL;                   // indicate no match
-  return (q);
-}
-
-#ifdef BB_FEATURE_VI_SETOPTS
-// show the matching char of a pair,  ()  []  {}
-static void
-showmatching (Byte * p)
-{
-  Byte *q, *save_dot;
-
-  // we found half of a pair
-  q = find_pair (p, *p);        // get loc of matching char
-  if (q == NULL)
-    {
-      indicate_error ('3');     // no matching char
-    }
-  else
-    {
-      // "q" now points to matching pair
-      save_dot = dot;           // remember where we are
-      dot = q;                  // go to new loc
-      refresh (FALSE);          // let the user see it
-      (void) mysleep (40);      // give user some time
-      dot = save_dot;           // go back to old loc
-      refresh (FALSE);
-    }
-}
-#endif /* BB_FEATURE_VI_SETOPTS */
-
-//  open a hole in text[]
-static Byte *
-text_hole_make (Byte * p, int size) // at "p", make a 'size' byte hole
-{
-  Byte *src, *dest;
-  int cnt;
-
-  if (size <= 0)
-    goto thm0;
-  src = p;
-  dest = p + size;
-  cnt = end - src;              // the rest of buffer
-  if (memmove (dest, src, cnt) != dest)
-    {
-      psbs ("can't create room for new characters");
-    }
-  memset (p, ' ', size);        // clear new hole
-  end = end + size;             // adjust the new END
-  file_modified = TRUE;         // has the file been modified
-thm0:
-  return (p);
-}
-
-//  close a hole in text[]
-static Byte *
-text_hole_delete (Byte * p, Byte * q) // delete "p" thru "q", inclusive
-{
-  Byte *src, *dest;
-  int cnt, hole_size;
-
-  // move forwards, from beginning
-  // assume p <= q
-  src = q + 1;
-  dest = p;
-  if (q < p)
-    {                           // they are backward- swap them
-      src = p + 1;
-      dest = q;
-    }
-  hole_size = q - p + 1;
-  cnt = end - src;
-  if (src < text || src > end)
-    goto thd0;
-  if (dest < text || dest >= end)
-    goto thd0;
-  if (src >= end)
-    goto thd_atend;             // just delete the end of the buffer
-  if (memmove (dest, src, cnt) != dest)
-    {
-      psbs ("can't delete the character");
-    }
-thd_atend:
-  end = end - hole_size;        // adjust the new END
-  if (dest >= end)
-    dest = end - 1;             // make sure dest in below end-1
-  if (end <= text)
-    dest = end = text;          // keep pointers valid
-  file_modified = TRUE;         // has the file been modified
-thd0:
-  return (dest);
-}
-
-// copy text into register, then delete text.
-// if dist <= 0, do not include, or go past, a NewLine
-//
-static Byte *
-yank_delete (Byte * start, Byte * stop, int dist, int yf)
-{
-  Byte *p;
-
-  // make sure start <= stop
-  if (start > stop)
-    {
-      // they are backwards, reverse them
-      p = start;
-      start = stop;
-      stop = p;
-    }
-  if (dist <= 0)
-    {
-      // we can not cross NL boundaries
-      p = start;
-      if (*p == '\n')
-        return (p);
-      // dont go past a NewLine
-      for (; p + 1 <= stop; p++)
-        {
-          if (p[1] == '\n')
-            {
-              stop = p;         // "stop" just before NewLine
-              break;
-            }
-        }
-    }
-  p = start;
-#ifdef BB_FEATURE_VI_YANKMARK
-  text_yank (start, stop, YDreg);
-#endif /* BB_FEATURE_VI_YANKMARK */
-  if (yf == YANKDEL)
-    {
-      p = text_hole_delete (start, stop);
-    }                           // delete lines
-  return (p);
-}
-
-static void
-show_help (void)
-{
-  fprintf (stderr, "version: %s\n", vi_Version);
-  puts ("These features are available:"
-#ifdef BB_FEATURE_VI_SEARCH
-        "\n\tPattern searches with / and ?"
-#endif /* BB_FEATURE_VI_SEARCH */
-#ifdef BB_FEATURE_VI_DOT_CMD
-        "\n\tLast command repeat with \'.\'"
-#endif /* BB_FEATURE_VI_DOT_CMD */
-#ifdef BB_FEATURE_VI_YANKMARK
-        "\n\tLine marking with  'x" "\n\tNamed buffers with  \"x"
-#endif /* BB_FEATURE_VI_YANKMARK */
-#ifdef BB_FEATURE_VI_READONLY
-        "\n\tReadonly if vi is called as \"view\""
-        "\n\tReadonly with -R command line arg"
-#endif /* BB_FEATURE_VI_READONLY */
-#ifdef BB_FEATURE_VI_SET
-        "\n\tSome colon mode commands with \':\'"
-#endif /* BB_FEATURE_VI_SET */
-#ifdef BB_FEATURE_VI_SETOPTS
-        "\n\tSettable options with \":set\""
-#endif /* BB_FEATURE_VI_SETOPTS */
-#ifdef BB_FEATURE_VI_USE_SIGNALS
-        "\n\tSignal catching- ^C" "\n\tJob suspend and resume with ^Z"
-#endif /* BB_FEATURE_VI_USE_SIGNALS */
-#ifdef BB_FEATURE_VI_WIN_RESIZE
-        "\n\tAdapt to window re-sizes"
-#endif /* BB_FEATURE_VI_WIN_RESIZE */
-    );
-}
-
-static void
-print_literal (Byte * buf, Byte * s)  // copy s to buf, convert unprintable
-{
-  Byte c, b[2];
-
-  b[1] = '\0';
-  strcpy ((char *) buf, "");    // init buf
-  if (strlen ((char *) s) <= 0)
-    s = (Byte *) "(NULL)";
-  for (; *s > '\0'; s++)
-    {
-      c = *s;
-      if (*s > '~')
-        {
-          strcat ((char *) buf, SOs);
-          c = *s - 128;
-        }
-      if (*s < ' ')
-        {
-          strcat ((char *) buf, "^");
-          c += '@';
-        }
-      b[0] = c;
-      strcat ((char *) buf, (char *) b);
-      if (*s > '~')
-        strcat ((char *) buf, SOn);
-      if (*s == '\n')
-        {
-          strcat ((char *) buf, "$");
-        }
-    }
-}
-
-#ifdef BB_FEATURE_VI_DOT_CMD
-static void
-start_new_cmd_q (Byte c)
-{
-  // release old cmd
-  if (last_modifying_cmd != 0)
-    free (last_modifying_cmd);
-  // get buffer for new cmd
-  last_modifying_cmd = (Byte *) malloc (BUFSIZ);
-  memset (last_modifying_cmd, '\0', BUFSIZ);  // clear new cmd queue
-  // if there is a current cmd count put it in the buffer first
-  if (cmdcnt > 0)
-    sprintf ((char *) last_modifying_cmd, "%d", cmdcnt);
-  // save char c onto queue
-  last_modifying_cmd[strlen ((char *) last_modifying_cmd)] = c;
-  adding2q = 1;
-  return;
-}
-
-static void
-end_cmd_q ()
-{
-#ifdef BB_FEATURE_VI_YANKMARK
-  YDreg = 26;                   // go back to default Yank/Delete reg
-#endif /* BB_FEATURE_VI_YANKMARK */
-  adding2q = 0;
-  return;
-}
-#endif /* BB_FEATURE_VI_DOT_CMD */
-
-#if defined(BB_FEATURE_VI_YANKMARK) || defined(BB_FEATURE_VI_COLON) || defined(BB_FEATURE_VI_CRASHME)
-static Byte *
-string_insert (Byte * p, Byte * s)  // insert the string at 'p'
-{
-  int cnt, i;
-
-  i = strlen ((char *) s);
-  p = text_hole_make (p, i);
-  strncpy ((char *) p, (char *) s, i);
-  for (cnt = 0; *s != '\0'; s++)
-    {
-      if (*s == '\n')
-        cnt++;
-    }
-#ifdef BB_FEATURE_VI_YANKMARK
-  psb ("Put %d lines (%d chars) from [%c]", cnt, i, what_reg ());
-#endif /* BB_FEATURE_VI_YANKMARK */
-  return (p);
-}
-#endif /* BB_FEATURE_VI_YANKMARK || BB_FEATURE_VI_COLON || BB_FEATURE_VI_CRASHME */
-
-#ifdef BB_FEATURE_VI_YANKMARK
-static Byte *
-text_yank (Byte * p, Byte * q, int dest)  // copy text into a register
-{
-  Byte *t;
-  int cnt;
-
-  if (q < p)
-    {                           // they are backwards- reverse them
-      t = q;
-      q = p;
-      p = t;
-    }
-  cnt = q - p + 1;
-  t = reg[dest];
-  if (t != 0)
-    {                           // if already a yank register
-      free (t);                 //   free it
-    }
-  t = (Byte *) malloc (cnt + 1);  // get a new register
-  memset (t, '\0', cnt + 1);    // clear new text[]
-  strncpy ((char *) t, (char *) p, cnt);  // copy text[] into bufer
-  reg[dest] = t;
-  return (p);
-}
-
-static Byte
-what_reg (void)
-{
-  Byte c;
-  int i;
-
-  i = 0;
-  c = 'D';                      // default to D-reg
-  if (0 <= YDreg && YDreg <= 25)
-    c = 'a' + (Byte) YDreg;
-  if (YDreg == 26)
-    c = 'D';
-  if (YDreg == 27)
-    c = 'U';
-  return (c);
-}
-
-static void
-check_context (Byte cmd)
-{
-  // A context is defined to be "modifying text"
-  // Any modifying command establishes a new context.
-
-  if (dot < context_start || dot > context_end)
-    {
-      if (strchr ((char *) modifying_cmds, cmd) != NULL)
-        {
-          // we are trying to modify text[]- make this the current context
-          mark[27] = mark[26];  // move cur to prev
-          mark[26] = dot;       // move local to cur
-          context_start = prev_line (prev_line (dot));
-          context_end = next_line (next_line (dot));
-          //loiter= start_loiter= now;
-        }
-    }
-  return;
-}
-
-static Byte *
-swap_context (Byte * p)         // goto new context for '' command make this the current context
-{
-  Byte *tmp;
-
-  // the current context is in mark[26]
-  // the previous context is in mark[27]
-  // only swap context if other context is valid
-  if (text <= mark[27] && mark[27] <= end - 1)
-    {
-      tmp = mark[27];
-      mark[27] = mark[26];
-      mark[26] = tmp;
-      p = mark[26];             // where we are going- previous context
-      context_start = prev_line (prev_line (prev_line (p)));
-      context_end = next_line (next_line (next_line (p)));
-    }
-  return (p);
-}
-#endif /* BB_FEATURE_VI_YANKMARK */
-
-static int
-isblnk (Byte c)                 // is the char a blank or tab
-{
-  return (c == ' ' || c == '\t');
-}
-
-//----- Set terminal attributes --------------------------------
-static void
-rawmode (void)
-{
-  tcgetattr (0, &term_orig);
-  term_vi = term_orig;
-  term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG ON- allow intr's
-  term_vi.c_iflag &= (~IXON & ~ICRNL);
-  term_vi.c_oflag &= (~ONLCR);
-#ifndef linux
-  term_vi.c_cc[VMIN] = 1;
-  term_vi.c_cc[VTIME] = 0;
-#endif
-  erase_char = term_vi.c_cc[VERASE];
-  tcsetattr (0, TCSANOW, &term_vi);
-}
-
-static void
-cookmode (void)
-{
-  tcsetattr (0, TCSANOW, &term_orig);
-}
-
-#ifdef BB_FEATURE_VI_WIN_RESIZE
-//----- See what the window size currently is --------------------
-static void
-window_size_get (int sig)
-{
-  int i;
-
-  i = ioctl (0, TIOCGWINSZ, &winsize);
-  if (i != 0)
-    {
-      // force 24x80
-      winsize.ws_row = 24;
-      winsize.ws_col = 80;
-    }
-  if (winsize.ws_row <= 1)
-    {
-      winsize.ws_row = 24;
-    }
-  if (winsize.ws_col <= 1)
-    {
-      winsize.ws_col = 80;
-    }
-  rows = (int) winsize.ws_row;
-  columns = (int) winsize.ws_col;
-}
-#endif /* BB_FEATURE_VI_WIN_RESIZE */
-
-//----- Come here when we get a window resize signal ---------
-#ifdef BB_FEATURE_VI_USE_SIGNALS
-static void
-winch_sig (int sig)
-{
-  signal (SIGWINCH, winch_sig);
-#ifdef BB_FEATURE_VI_WIN_RESIZE
-  window_size_get (0);
-#endif /* BB_FEATURE_VI_WIN_RESIZE */
-  new_screen (rows, columns);   // get memory for virtual screen
-  redraw (TRUE);                // re-draw the screen
-}
-
-//----- Come here when we get a continue signal -------------------
-static void
-cont_sig (int sig)
-{
-  rawmode ();                   // terminal to "raw"
-  *status_buffer = '\0';        // clear the status buffer
-  redraw (TRUE);                // re-draw the screen
-
-  signal (SIGTSTP, suspend_sig);
-  signal (SIGCONT, SIG_DFL);
-  kill (getpid (), SIGCONT);
-}
-
-//----- Come here when we get a Suspend signal -------------------
-static void
-suspend_sig (int sig)
-{
-  place_cursor (rows - 1, 0, FALSE);  // go to bottom of screen
-  clear_to_eol ();              // Erase to end of line
-  cookmode ();                  // terminal to "cooked"
-
-  signal (SIGCONT, cont_sig);
-  signal (SIGTSTP, SIG_DFL);
-  kill (getpid (), SIGTSTP);
-}
-
-//----- Come here when we get a signal ---------------------------
-static void
-catch_sig (int sig)
-{
-  signal (SIGHUP, catch_sig);
-  signal (SIGINT, catch_sig);
-  signal (SIGTERM, catch_sig);
-  longjmp (restart, sig);
-}
-
-static void
-alarm_sig (int sig)
-{
-  signal (SIGALRM, catch_sig);
-  longjmp (restart, sig);
-}
-
-//----- Come here when we get a core dump signal -----------------
-static void
-core_sig (int sig)
-{
-  signal (SIGQUIT, core_sig);
-  signal (SIGILL, core_sig);
-  signal (SIGTRAP, core_sig);
-  signal (SIGIOT, core_sig);
-  signal (SIGABRT, core_sig);
-  signal (SIGFPE, core_sig);
-  signal (SIGBUS, core_sig);
-  signal (SIGSEGV, core_sig);
-#ifdef SIGSYS
-  signal (SIGSYS, core_sig);
-#endif
-
-  dot = bound_dot (dot);        // make sure "dot" is valid
-
-  longjmp (restart, sig);
-}
-#endif /* BB_FEATURE_VI_USE_SIGNALS */
-
-static int
-mysleep (int hund)              // sleep for 'h' 1/100 seconds
-{
-  // Don't hang- Wait 5/100 seconds-  1 Sec= 1000000
-  FD_ZERO (&rfds);
-  FD_SET (0, &rfds);
-  tv.tv_sec = 0;
-  tv.tv_usec = hund * 10000;
-  select (1, &rfds, NULL, NULL, &tv);
-  return (FD_ISSET (0, &rfds));
-}
-
-//----- IO Routines --------------------------------------------
-static Byte
-readit (void)                   // read (maybe cursor) key from stdin
-{
-  Byte c;
-  int i, bufsiz, cnt;
-  unsigned int cmdindex;
-  struct esc_cmds
-  {
-    Byte *seq;
-    Byte val;
-  };
-
-  static struct esc_cmds esccmds[] = {
-    {(Byte *) "\eOA", (Byte) VI_K_UP}, // cursor key Up
-    {(Byte *) "\eOB", (Byte) VI_K_DOWN}, // cursor key Down
-    {(Byte *) "\eOC", (Byte) VI_K_RIGHT},  // Cursor Key Right
-    {(Byte *) "\eOD", (Byte) VI_K_LEFT}, // cursor key Left
-    {(Byte *) "\eOH", (Byte) VI_K_HOME}, // Cursor Key Home
-    {(Byte *) "\eOF", (Byte) VI_K_END},  // Cursor Key End
-    {(Byte *) "\e[A", (Byte) VI_K_UP}, // cursor key Up
-    {(Byte *) "\e[B", (Byte) VI_K_DOWN}, // cursor key Down
-    {(Byte *) "\e[C", (Byte) VI_K_RIGHT},  // Cursor Key Right
-    {(Byte *) "\e[D", (Byte) VI_K_LEFT}, // cursor key Left
-    {(Byte *) "\e[H", (Byte) VI_K_HOME}, // Cursor Key Home
-    {(Byte *) "\e[F", (Byte) VI_K_END},  // Cursor Key End
-    {(Byte *) "\e[2~", (Byte) VI_K_INSERT},  // Cursor Key Insert
-    {(Byte *) "\e[5~", (Byte) VI_K_PAGEUP},  // Cursor Key Page Up
-    {(Byte *) "\e[6~", (Byte) VI_K_PAGEDOWN},  // Cursor Key Page Down
-    {(Byte *) "\eOP", (Byte) VI_K_FUN1}, // Function Key F1
-    {(Byte *) "\eOQ", (Byte) VI_K_FUN2}, // Function Key F2
-    {(Byte *) "\eOR", (Byte) VI_K_FUN3}, // Function Key F3
-    {(Byte *) "\eOS", (Byte) VI_K_FUN4}, // Function Key F4
-    {(Byte *) "\e[15~", (Byte) VI_K_FUN5}, // Function Key F5
-    {(Byte *) "\e[17~", (Byte) VI_K_FUN6}, // Function Key F6
-    {(Byte *) "\e[18~", (Byte) VI_K_FUN7}, // Function Key F7
-    {(Byte *) "\e[19~", (Byte) VI_K_FUN8}, // Function Key F8
-    {(Byte *) "\e[20~", (Byte) VI_K_FUN9}, // Function Key F9
-    {(Byte *) "\e[21~", (Byte) VI_K_FUN10},  // Function Key F10
-    {(Byte *) "\e[23~", (Byte) VI_K_FUN11},  // Function Key F11
-    {(Byte *) "\e[24~", (Byte) VI_K_FUN12},  // Function Key F12
-    {(Byte *) "\e[11~", (Byte) VI_K_FUN1}, // Function Key F1
-    {(Byte *) "\e[12~", (Byte) VI_K_FUN2}, // Function Key F2
-    {(Byte *) "\e[13~", (Byte) VI_K_FUN3}, // Function Key F3
-    {(Byte *) "\e[14~", (Byte) VI_K_FUN4}, // Function Key F4
-  };
-
-#define ESCCMDS_COUNT (sizeof(esccmds)/sizeof(struct esc_cmds))
-
-  // (void) alarm(0);     // turn alarm OFF while we wait for input
-  // get input from User- are there already input chars in Q?
-  bufsiz = strlen ((char *) readbuffer);
-  if (bufsiz <= 0)
-    {
-    ri0:
-      // the Q is empty, wait for a typed char
-      bufsiz = read (0, readbuffer, BUFSIZ - 1);
-      if (bufsiz < 0)
-        {
-          if (errno == EINTR)
-            goto ri0;           // interrupted sys call
-          if (errno == EBADF)
-            editing = 0;
-          if (errno == EFAULT)
-            editing = 0;
-          if (errno == EINVAL)
-            editing = 0;
-          if (errno == EIO)
-            editing = 0;
-          errno = 0;
-          bufsiz = 0;
-        }
-      readbuffer[bufsiz] = '\0';
-    }
-  // return char if it is not part of ESC sequence
-  if (readbuffer[0] != 27)
-    goto ri1;
-
-  // This is an ESC char. Is this Esc sequence?
-  // Could be bare Esc key. See if there are any
-  // more chars to read after the ESC. This would
-  // be a Function or Cursor Key sequence.
-  FD_ZERO (&rfds);
-  FD_SET (0, &rfds);
-  tv.tv_sec = 0;
-  tv.tv_usec = 50000;           // Wait 5/100 seconds- 1 Sec=1000000
-
-  // keep reading while there are input chars and room in buffer
-  while (select (1, &rfds, NULL, NULL, &tv) > 0 && bufsiz <= (BUFSIZ - 5))
-    {
-      // read the rest of the ESC string
-      i = read (0, (void *) (readbuffer + bufsiz), BUFSIZ - bufsiz);
-      if (i > 0)
-        {
-          bufsiz += i;
-          readbuffer[bufsiz] = '\0';  // Terminate the string
-        }
-    }
-  // Maybe cursor or function key?
-  for (cmdindex = 0; cmdindex < ESCCMDS_COUNT; cmdindex++)
-    {
-      cnt = strlen ((char *) esccmds[cmdindex].seq);
-      i = strncmp ((char *) esccmds[cmdindex].seq, (char *) readbuffer, cnt);
-      if (i == 0)
-        {
-          // is a Cursor key- put derived value back into Q
-          readbuffer[0] = esccmds[cmdindex].val;
-          // squeeze out the ESC sequence
-          for (i = 1; i < cnt; i++)
-            {
-              memmove (readbuffer + 1, readbuffer + 2, BUFSIZ - 2);
-              readbuffer[BUFSIZ - 1] = '\0';
-            }
-          break;
-        }
-    }
-ri1:
-  c = readbuffer[0];
-  // remove one char from Q
-  memmove (readbuffer, readbuffer + 1, BUFSIZ - 1);
-  readbuffer[BUFSIZ - 1] = '\0';
-  // (void) alarm(3);     // we are done waiting for input, turn alarm ON
-  return (c);
-}
-
-//----- IO Routines --------------------------------------------
-static Byte
-get_one_char ()
-{
-  static Byte c;
-
-#ifdef BB_FEATURE_VI_DOT_CMD
-  // ! adding2q  && ioq == 0  read()
-  // ! adding2q  && ioq != 0  *ioq
-  // adding2q         *last_modifying_cmd= read()
-  if (!adding2q)
-    {
-      // we are not adding to the q.
-      // but, we may be reading from a q
-      if (ioq == 0)
-        {
-          // there is no current q, read from STDIN
-          c = readit ();        // get the users input
-        }
-      else
-        {
-          // there is a queue to get chars from first
-          c = *ioq++;
-          if (c == '\0')
-            {
-              // the end of the q, read from STDIN
-              free (ioq_start);
-              ioq_start = ioq = 0;
-              c = readit ();    // get the users input
-            }
-        }
-    }
-  else
-    {
-      // adding STDIN chars to q
-      c = readit ();            // get the users input
-      if (last_modifying_cmd != 0)
-        {
-          // add new char to q
-          last_modifying_cmd[strlen ((char *) last_modifying_cmd)] = c;
-        }
-    }
-#else /* BB_FEATURE_VI_DOT_CMD */
-  c = readit ();                // get the users input
-#endif /* BB_FEATURE_VI_DOT_CMD */
-  return (c);                   // return the char, where ever it came from
-}
-
-static Byte *
-get_input_line (Byte * prompt)  // get input line- use "status line"
-{
-  Byte buf[BUFSIZ];
-  Byte c;
-  int i;
-  static Byte *obufp = NULL;
-
-  strcpy ((char *) buf, (char *) prompt);
-  *status_buffer = '\0';        // clear the status buffer
-  place_cursor (rows - 1, 0, FALSE);  // go to Status line, bottom of screen
-  clear_to_eol ();              // clear the line
-  write (1, prompt, strlen ((char *) prompt));  // write out the :, /, or ? prompt
-
-  for (i = strlen ((char *) buf); i < BUFSIZ;)
-    {
-      c = get_one_char ();      // read user input
-      if (c == '\n' || c == '\r' || c == 27)
-        break;                  // is this end of input
-      if (c == erase_char)
-        {                       // user wants to erase prev char
-          i--;                  // backup to prev char
-          buf[i] = '\0';        // erase the char
-          buf[i + 1] = '\0';    // null terminate buffer
-          write (1, "\b \b", 3);      // erase char on screen
-          if (i <= 0)
-            {                   // user backs up before b-o-l, exit
-              break;
-            }
-        }
-      else
-        {
-          buf[i] = c;           // save char in buffer
-          buf[i + 1] = '\0';    // make sure buffer is null terminated
-          write (1, buf + i, 1);  // echo the char back to user
-          i++;
-        }
-    }
-  refresh (FALSE);
-  if (obufp != NULL)
-    free (obufp);
-  obufp = (Byte *) strdup ((char *) buf);
-  return (obufp);
-}
-
-static int
-file_size (Byte * fn)           // what is the byte size of "fn"
-{
-  struct stat st_buf;
-  int cnt, sr;
-
-  if (fn == 0 || strlen (fn) <= 0)
-    return (-1);
-  cnt = -1;
-  sr = stat ((char *) fn, &st_buf); // see if file exists
-  if (sr >= 0)
-    {
-      cnt = (int) st_buf.st_size;
-    }
-  return (cnt);
-}
-
-static int
-file_insert (Byte * fn, Byte * p, int size)
-{
-  int fd, cnt;
-
-  cnt = -1;
-#ifdef BB_FEATURE_VI_READONLY
-  readonly = FALSE;
-#endif /* BB_FEATURE_VI_READONLY */
-  if (fn == 0 || strlen ((char *) fn) <= 0)
-    {
-      psbs ("No filename given");
-      goto fi0;
-    }
-  if (size == 0)
-    {
-      // OK- this is just a no-op
-      cnt = 0;
-      goto fi0;
-    }
-  if (size < 0)
-    {
-      psbs ("Trying to insert a negative number (%d) of characters", size);
-      goto fi0;
-    }
-  if (p < text || p > end)
-    {
-      psbs ("Trying to insert file outside of memory");
-      goto fi0;
-    }
-
-  // see if we can open the file
-#ifdef BB_FEATURE_VI_READONLY
-  if (vi_readonly == TRUE)
-    goto fi1;                   // do not try write-mode
-#endif
-  fd = open ((char *) fn, O_RDWR);  // assume read & write
-  if (fd < 0)
-    {
-      // could not open for writing- maybe file is read only
-#ifdef BB_FEATURE_VI_READONLY
-    fi1:
-#endif
-      fd = open ((char *) fn, O_RDONLY);  // try read-only
-      if (fd < 0)
-        {
-          psbs ("\"%s\" %s", fn, "could not open file");
-          goto fi0;
-        }
-#ifdef BB_FEATURE_VI_READONLY
-      // got the file- read-only
-      readonly = TRUE;
-#endif /* BB_FEATURE_VI_READONLY */
-    }
-  p = text_hole_make (p, size);
-  cnt = read (fd, p, size);
-  close (fd);
-  if (cnt < 0)
-    {
-      cnt = -1;
-      p = text_hole_delete (p, p + size - 1); // un-do buffer insert
-      psbs ("could not read file \"%s\"", fn);
-    }
-  else if (cnt < size)
-    {
-      // There was a partial read, shrink unused space text[]
-      p = text_hole_delete (p + cnt, p + (size - cnt) - 1); // un-do buffer insert
-      psbs ("could not read all of file \"%s\"", fn);
-    }
-  if (cnt >= size)
-    file_modified = TRUE;
-fi0:
-  return (cnt);
-}
-
-static int
-file_write (Byte * fn, Byte * first, Byte * last)
-{
-  int fd, cnt, charcnt;
-
-  if (fn == 0)
-    {
-      psbs ("No current filename");
-      return (-1);
-    }
-  charcnt = 0;
-  // FIXIT- use the correct umask()
-  fd = open ((char *) fn, (O_WRONLY | O_CREAT | O_TRUNC), 0664);
-  if (fd < 0)
-    return (-1);
-  cnt = last - first + 1;
-  charcnt = write (fd, first, cnt);
-  if (charcnt == cnt)
-    {
-      // good write
-      //file_modified= FALSE; // the file has not been modified
-    }
-  else
-    {
-      charcnt = 0;
-    }
-  close (fd);
-  return (charcnt);
-}
-
-//----- Terminal Drawing ---------------------------------------
-// The terminal is made up of 'rows' line of 'columns' columns.
-// classicly this would be 24 x 80.
-//  screen coordinates
-//  0,0     ...     0,79
-//  1,0     ...     1,79
-//  .       ...     .
-//  .       ...     .
-//  22,0    ...     22,79
-//  23,0    ...     23,79   status line
-//
-
-//----- Move the cursor to row x col (count from 0, not 1) -------
-static void
-place_cursor (int row, int col, int opti)
-{
-  char cm1[BUFSIZ];
-  char *cm;
-  int l;
-#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR
-  char cm2[BUFSIZ];
-  Byte *screenp;
-  // char cm3[BUFSIZ];
-  int Rrow = last_row;
-#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */
-
-  memset (cm1, '\0', BUFSIZ - 1); // clear the buffer
-
-  if (row < 0)
-    row = 0;
-  if (row >= rows)
-    row = rows - 1;
-  if (col < 0)
-    col = 0;
-  if (col >= columns)
-    col = columns - 1;
-
-  //----- 1.  Try the standard terminal ESC sequence
-  sprintf ((char *) cm1, CMrc, row + 1, col + 1);
-  cm = cm1;
-  if (opti == FALSE)
-    goto pc0;
-
-#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR
-  //----- find the minimum # of chars to move cursor -------------
-  //----- 2.  Try moving with discreet chars (Newline, [back]space, ...)
-  memset (cm2, '\0', BUFSIZ - 1); // clear the buffer
-
-  // move to the correct row
-  while (row < Rrow)
-    {
-      // the cursor has to move up
-      strcat (cm2, CMup);
-      Rrow--;
-    }
-  while (row > Rrow)
-    {
-      // the cursor has to move down
-      strcat (cm2, CMdown);
-      Rrow++;
-    }
-
-  // now move to the correct column
-  strcat (cm2, "\r");           // start at col 0
-  // just send out orignal source char to get to correct place
-  screenp = &screen[row * columns]; // start of screen line
-  strncat (cm2, screenp, col);
-
-  //----- 3.  Try some other way of moving cursor
-  //---------------------------------------------
-
-  // pick the shortest cursor motion to send out
-  cm = cm1;
-  if (strlen (cm2) < strlen (cm))
-    {
-      cm = cm2;
-    }                           /* else if (strlen(cm3) < strlen(cm)) {
-                                   cm= cm3;
-                                   } */
-#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */
-pc0:
-  l = strlen (cm);
-  if (l)
-    write (1, cm, l);           // move the cursor
-}
-
-//----- Erase from cursor to end of line -----------------------
-static void
-clear_to_eol ()
-{
-  write (1, Ceol, strlen (Ceol)); // Erase from cursor to end of line
-}
-
-//----- Erase from cursor to end of screen -----------------------
-static void
-clear_to_eos ()
-{
-  write (1, Ceos, strlen (Ceos)); // Erase from cursor to end of screen
-}
-
-//----- Start standout mode ------------------------------------
-static void
-standout_start ()               // send "start reverse video" sequence
-{
-  write (1, SOs, strlen (SOs)); // Start reverse video mode
-}
-
-//----- End standout mode --------------------------------------
-static void
-standout_end ()                 // send "end reverse video" sequence
-{
-  write (1, SOn, strlen (SOn)); // End reverse video mode
-}
-
-//----- Flash the screen  --------------------------------------
-static void
-flash (int h)
-{
-  standout_start ();            // send "start reverse video" sequence
-  redraw (TRUE);
-  (void) mysleep (h);
-  standout_end ();              // send "end reverse video" sequence
-  redraw (TRUE);
-}
-
-static void
-beep ()
-{
-  write (1, bell, strlen (bell)); // send out a bell character
-}
-
-static void
-indicate_error (char c)
-{
-#ifdef BB_FEATURE_VI_CRASHME
-  if (crashme > 0)
-    return;                     // generate a random command
-#endif /* BB_FEATURE_VI_CRASHME */
-  if (err_method == 0)
-    {
-      beep ();
-    }
-  else
-    {
-      flash (10);
-    }
-}
-
-//----- Screen[] Routines --------------------------------------
-//----- Erase the Screen[] memory ------------------------------
-static void
-screen_erase ()
-{
-  memset (screen, ' ', screensize); // clear new screen
-}
-
-//----- Draw the status line at bottom of the screen -------------
-static void
-show_status_line (void)
-{
-  static int last_cksum;
-  int l, cnt, cksum;
-
-  cnt = strlen ((char *) status_buffer);
-  for (cksum = l = 0; l < cnt; l++)
-    {
-      cksum += (int) (status_buffer[l]);
-    }
-  // don't write the status line unless it changes
-  if (cnt > 0 && last_cksum != cksum)
-    {
-      last_cksum = cksum;       // remember if we have seen this line
-      place_cursor (rows - 1, 0, FALSE);  // put cursor on status line
-      write (1, status_buffer, cnt);
-      clear_to_eol ();
-      place_cursor (crow, ccol, FALSE); // put cursor back in correct place
-    }
-}
-
-//----- format the status buffer, the bottom line of screen ------
-// print status buffer, with STANDOUT mode
-static void
-psbs (char *format, ...)
-{
-  va_list args;
-
-  va_start (args, format);
-  strcpy ((char *) status_buffer, SOs); // Terminal standout mode on
-  vsprintf ((char *) status_buffer + strlen ((char *) status_buffer), format,
-            args);
-  strcat ((char *) status_buffer, SOn); // Terminal standout mode off
-  va_end (args);
-
-  return;
-}
-
-// print status buffer
-static void
-psb (char *format, ...)
-{
-  va_list args;
-
-  va_start (args, format);
-  vsprintf ((char *) status_buffer, format, args);
-  va_end (args);
-  return;
-}
-
-static void
-ni (Byte * s)                   // display messages
-{
-  Byte buf[BUFSIZ];
-
-  print_literal (buf, s);
-  psbs ("\'%s\' is not implemented", buf);
-}
-
-static void
-edit_status (void)              // show file status on status line
-{
-  int cur, tot, percent;
-
-  cur = count_lines (text, dot);
-  tot = count_lines (text, end - 1);
-  //    current line         percent
-  //   -------------    ~~ ----------
-  //    total lines            100
-  if (tot > 0)
-    {
-      percent = (100 * cur) / tot;
-    }
-  else
-    {
-      cur = tot = 0;
-      percent = 100;
-    }
-  psb ("\"%s\""
-#ifdef BB_FEATURE_VI_READONLY
-       "%s"
-#endif /* BB_FEATURE_VI_READONLY */
-       "%s line %d of %d --%d%%--", (cfn != 0 ? (char *) cfn : "No file"),
-#ifdef BB_FEATURE_VI_READONLY
-       ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""),
-#endif /* BB_FEATURE_VI_READONLY */
-       (file_modified == TRUE ? " [modified]" : ""), cur, tot, percent);
-}
-
-//----- Force refresh of all Lines -----------------------------
-static void
-redraw (int full_screen)
-{
-  place_cursor (0, 0, FALSE);   // put cursor in correct place
-  clear_to_eos ();              // tel terminal to erase display
-  screen_erase ();              // erase the internal screen buffer
-  refresh (full_screen);        // this will redraw the entire display
-}
-
-//----- Format a text[] line into a buffer ---------------------
-static void
-format_line (Byte * dest, Byte * src, int li)
-{
-  int co;
-  Byte c;
-
-  for (co = 0; co < MAX_SCR_COLS; co++)
-    {
-      c = ' ';                  // assume blank
-      if (li > 0 && co == 0)
-        {
-          c = '~';              // not first line, assume Tilde
-        }
-      // are there chars in text[] and have we gone past the end
-      if (text < end && src < end)
-        {
-          c = *src++;
-        }
-      if (c == '\n')
-        break;
-      if (c < ' ' || c > '~')
-        {
-          if (c == '\t')
-            {
-              c = ' ';
-              //       co %    8     !=     7
-              for (; (co % tabstop) != (tabstop - 1); co++)
-                {
-                  dest[co] = c;
-                }
-            }
-          else
-            {
-              dest[co++] = '^';
-              c |= '@';         // make it visible
-              c &= 0x7f;        // get rid of hi bit
-            }
-        }
-      // the co++ is done here so that the column will
-      // not be overwritten when we blank-out the rest of line
-      dest[co] = c;
-      if (src >= end)
-        break;
-    }
-}
-
-//----- Refresh the changed screen lines -----------------------
-// Copy the source line from text[] into the buffer and note
-// if the current screenline is different from the new buffer.
-// If they differ then that line needs redrawing on the terminal.
-//
-static void
-refresh (int full_screen)
-{
-  static int old_offset;
-  int li, changed;
-  Byte buf[MAX_SCR_COLS];
-  Byte *tp, *sp;                // pointer into text[] and screen[]
-#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR
-  int last_li = -2;             // last line that changed- for optimizing cursor movement
-#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */
-
-#ifdef BB_FEATURE_VI_WIN_RESIZE
-  window_size_get (0);
-#endif /* BB_FEATURE_VI_WIN_RESIZE */
-  sync_cursor (dot, &crow, &ccol);  // where cursor will be (on "dot")
-  tp = screenbegin;             // index into text[] of top line
-
-  // compare text[] to screen[] and mark screen[] lines that need updating
-  for (li = 0; li < rows - 1; li++)
-    {
-      int cs, ce;               // column start & end
-      memset (buf, ' ', MAX_SCR_COLS);  // blank-out the buffer
-      buf[MAX_SCR_COLS - 1] = 0;  // NULL terminate the buffer
-      // format current text line into buf
-      format_line (buf, tp, li);
-
-      // skip to the end of the current text[] line
-      while (tp < end && *tp++ != '\n') /*no-op */ ;
-
-      // see if there are any changes between vitual screen and buf
-      changed = FALSE;          // assume no change
-      cs = 0;
-      ce = columns - 1;
-      sp = &screen[li * columns]; // start of screen line
-      if (full_screen == TRUE)
-        {
-          // force re-draw of every single column from 0 - columns-1
-          goto re0;
-        }
-      // compare newly formatted buffer with virtual screen
-      // look forward for first difference between buf and screen
-      for (; cs <= ce; cs++)
-        {
-          if (buf[cs + offset] != sp[cs])
-            {
-              changed = TRUE;   // mark for redraw
-              break;
-            }
-        }
-
-      // look backward for last difference between buf and screen
-      for (; ce >= cs; ce--)
-        {
-          if (buf[ce + offset] != sp[ce])
-            {
-              changed = TRUE;   // mark for redraw
-              break;
-            }
-        }
-      // now, cs is index of first diff, and ce is index of last diff
-
-      // if horz offset has changed, force a redraw
-      if (offset != old_offset)
-        {
-        re0:
-          changed = TRUE;
-        }
-
-      // make a sanity check of columns indexes
-      if (cs < 0)
-        cs = 0;
-      if (ce > columns - 1)
-        ce = columns - 1;
-      if (cs > ce)
-        {
-          cs = 0;
-          ce = columns - 1;
-        }
-      // is there a change between vitual screen and buf
-      if (changed == TRUE)
-        {
-          //  copy changed part of buffer to virtual screen
-          memmove (sp + cs, buf + (cs + offset), ce - cs + 1);
-
-          // move cursor to column of first change
-          if (offset != old_offset)
-            {
-              // opti_cur_move is still too stupid
-              // to handle offsets correctly
-              place_cursor (li, cs, FALSE);
-            }
-          else
-            {
-#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR
-              // if this just the next line
-              //  try to optimize cursor movement
-              //  otherwise, use standard ESC sequence
-              place_cursor (li, cs, li == (last_li + 1) ? TRUE : FALSE);
-              last_li = li;
-#else /* BB_FEATURE_VI_OPTIMIZE_CURSOR */
-              place_cursor (li, cs, FALSE); // use standard ESC sequence
-#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */
-            }
-
-          // write line out to terminal
-          write (1, sp + cs, ce - cs + 1);
-#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR
-          last_row = li;
-#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */
-        }
-    }
-
-#ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR
-  place_cursor (crow, ccol, (crow == last_row) ? TRUE : FALSE);
-  last_row = crow;
-#else
-  place_cursor (crow, ccol, FALSE);
-#endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */
-
-  if (offset != old_offset)
-    old_offset = offset;
-}