stat.1 - Remove unsupported %B
[dragonfly.git] / usr.bin / ee / ee.c
1 /*
2  |      ee (easy editor)
3  |
4  |      An easy to use, simple screen oriented editor.
5  |
6  |      written by Hugh Mahon
7  |
8  |      THIS MATERIAL IS PROVIDED "AS IS".  THERE ARE
9  |      NO WARRANTIES OF ANY KIND WITH REGARD TO THIS
10  |      MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE
11  |      IMPLIED WARRANTIES OF MERCHANTABILITY AND
12  |      FITNESS FOR A PARTICULAR PURPOSE.  Neither
13  |      Hewlett-Packard nor Hugh Mahon shall be liable
14  |      for errors contained herein, nor for
15  |      incidental or consequential damages in
16  |      connection with the furnishing, performance or
17  |      use of this material.  Neither Hewlett-Packard
18  |      nor Hugh Mahon assumes any responsibility for
19  |      the use or reliability of this software or
20  |      documentation.  This software and
21  |      documentation is totally UNSUPPORTED.  There
22  |      is no support contract available.  Hewlett-
23  |      Packard has done NO Quality Assurance on ANY
24  |      of the program or documentation.  You may find
25  |      the quality of the materials inferior to
26  |      supported materials.
27  |
28  |      This software is not a product of Hewlett-Packard, Co., or any 
29  |      other company.  No support is implied or offered with this software.
30  |      You've got the source, and you're on your own.
31  |
32  |      This software may be distributed under the terms of Larry Wall's 
33  |      Artistic license, a copy of which is included in this distribution. 
34  |
35  |      This notice must be included with this software and any derivatives.
36  |
37  |      This editor was purposely developed to be simple, both in 
38  |      interface and implementation.  This editor was developed to 
39  |      address a specific audience: the user who is new to computers 
40  |      (especially UNIX).
41  |      
42  |      ee is not aimed at technical users; for that reason more 
43  |      complex features were intentionally left out.  In addition, 
44  |      ee is intended to be compiled by people with little computer 
45  |      experience, which means that it needs to be small, relatively 
46  |      simple in implementation, and portable.
47  |
48  |      This software and documentation contains
49  |      proprietary information which is protected by
50  |      copyright.  All rights are reserved.
51  *
52  * $FreeBSD: src/usr.bin/ee/ee.c,v 1.16.2.6 2002/05/11 16:33:06 mp Exp $
53  */
54
55 char *ee_copyright_message = 
56 "Copyright (c) 1986, 1990, 1991, 1992, 1993, 1994, 1995, 1996 Hugh Mahon ";
57
58 char *ee_long_notice[] = {
59         "This software and documentation contains", 
60         "proprietary information which is protected by", 
61         "copyright.  All rights are reserved."
62         };
63
64 char *version = "@(#) ee, version 1.4.1";
65
66 #include <ncurses.h>
67
68 #ifdef HAS_CTYPE
69 #include <ctype.h>
70 #endif
71 #include <err.h>
72 #include <errno.h>
73 #include <fcntl.h>
74 #include <paths.h>
75 #include <pwd.h>
76 #include <signal.h>
77 #include <sys/types.h>
78 #include <sys/stat.h>
79 #ifdef HAS_SYS_WAIT
80 #include <sys/wait.h>
81 #endif
82 #ifdef HAS_STDARG
83 #include <stdarg.h>
84 #endif
85 #ifdef HAS_STDLIB
86 #include <stdlib.h>
87 #endif
88 #include <string.h>
89 #ifdef HAS_UNISTD
90 #include <unistd.h>
91 #endif
92
93 #ifndef NO_CATGETS
94 #include <locale.h>
95 #include <nl_types.h>
96
97 nl_catd catalog;
98 #else
99 #define catgetlocal(a, b) (b)
100 #endif /* NO_CATGETS */
101
102 #ifndef SIGCHLD
103 #define SIGCHLD SIGCLD
104 #endif
105
106 #define TAB 9
107 #define max(a, b)       (a > b ? a : b)
108 #define min(a, b)       (a < b ? a : b)
109
110 /*
111  |      defines for type of data to show in info window
112  */
113
114 #define CONTROL_KEYS 1
115 #define COMMANDS     2
116
117 struct text {
118         unsigned char *line;            /* line of characters           */
119         int line_number;                /* line number                  */
120         int line_length;        /* actual number of characters in the line */
121         int max_length; /* maximum number of characters the line handles */
122         struct text *next_line;         /* next line of text            */
123         struct text *prev_line;         /* previous line of text        */
124         };
125
126 struct text *first_line;        /* first line of current buffer         */
127 struct text *dlt_line;          /* structure for info on deleted line   */
128 struct text *curr_line;         /* current line cursor is on            */
129 struct text *tmp_line;          /* temporary line pointer               */
130 struct text *srch_line;         /* temporary pointer for search routine */
131
132 struct files {          /* structure to store names of files to be edited*/
133         unsigned char *name;            /* name of file                         */
134         struct files *next_name;
135         };
136
137 struct files *top_of_stack = NULL;
138
139 int d_wrd_len;                  /* length of deleted word               */
140 int position;                   /* offset in bytes from begin of line   */
141 int scr_pos;                    /* horizontal position                  */
142 int scr_vert;                   /* vertical position on screen          */
143 int scr_horz;                   /* horizontal position on screen        */
144 int tmp_vert, tmp_horz;
145 int input_file;                 /* indicate to read input file          */
146 int recv_file;                  /* indicate reading a file              */
147 int edit;                       /* continue executing while true        */
148 int gold;                       /* 'gold' function key pressed          */
149 int fildes;                     /* file descriptor                      */
150 int case_sen;                   /* case sensitive search flag           */
151 int last_line;                  /* last line for text display           */
152 int last_col;                   /* last column for text display         */
153 int horiz_offset = 0;           /* offset from left edge of text        */
154 int clear_com_win;              /* flag to indicate com_win needs clearing */
155 int text_changes = FALSE;       /* indicate changes have been made to text */
156 int get_fd;                     /* file descriptor for reading a file   */
157 int info_window = TRUE;         /* flag to indicate if help window visible */
158 int info_type = CONTROL_KEYS;   /* flag to indicate type of info to display */
159 int expand_tabs = TRUE;         /* flag for expanding tabs              */
160 int right_margin = 0;           /* the right margin                     */
161 int observ_margins = TRUE;      /* flag for whether margins are observed */
162 int shell_fork;
163 int temp_stdin;                 /* temporary storage for stdin          */
164 int temp_stdout;                /* temp storage for stdout descriptor   */
165 int temp_stderr;                /* temp storage for stderr descriptor   */
166 int pipe_out[2];                /* pipe file desc for output            */
167 int pipe_in[2];                 /* pipe file descriptors for input      */
168 int out_pipe;                   /* flag that info is piped out          */
169 int in_pipe;                    /* flag that info is piped in           */
170 int formatted = FALSE;          /* flag indicating paragraph formatted  */
171 int auto_format = FALSE;        /* flag for auto_format mode            */
172 int restricted = FALSE;         /* flag to indicate restricted mode     */
173 int nohighlight = FALSE;        /* turns off highlighting               */
174 int eightbit = TRUE;            /* eight bit character flag             */
175 int local_LINES = 0;            /* copy of LINES, to detect when win resizes */
176 int local_COLS = 0;             /* copy of COLS, to detect when win resizes  */
177 int curses_initialized = FALSE; /* flag indicating if curses has been started*/
178 int emacs_keys_mode = FALSE;    /* mode for if emacs key binings are used    */
179 int ee_chinese = FALSE;         /* allows handling of multi-byte characters  */
180                                 /* by checking for high bit in a byte the    */
181                                 /* code recognizes a two-byte character      */
182                                 /* sequence                                  */
183
184 unsigned char *point;           /* points to current position in line   */
185 unsigned char *srch_str;        /* pointer for search string            */
186 unsigned char *u_srch_str;      /* pointer to non-case sensitive search */
187 unsigned char *srch_1;          /* pointer to start of suspect string   */
188 unsigned char *srch_2;          /* pointer to next character of string  */
189 unsigned char *srch_3;
190 unsigned char *in_file_name = NULL;     /* name of input file           */
191 char *tmp_file; /* temporary file name                  */
192 unsigned char *d_char;          /* deleted character                    */
193 unsigned char *d_word;          /* deleted word                         */
194 unsigned char *d_line;          /* deleted line                         */
195 char in_string[513];    /* buffer for reading a file            */
196 unsigned char *print_command = "lpr";   /* string to use for the print command  */
197 unsigned char *start_at_line = NULL;    /* move to this line at start of session*/
198 const char count_text_default[] = "===============================================================================";
199 int count_text_len = sizeof(count_text_default);        /* length of the line above     */
200 char count_text[sizeof(count_text_default)];    /* buffer for current position display  */
201 int in;                         /* input character                      */
202
203 FILE *temp_fp;                  /* temporary file pointer               */
204 FILE *bit_bucket;               /* file pointer to /dev/null            */
205
206 char *table[] = { 
207         "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "\t", "^J", 
208         "^K", "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", 
209         "^V", "^W", "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_"
210         };
211
212 WINDOW *com_win;
213 WINDOW *text_win;
214 WINDOW *help_win;
215 WINDOW *info_win;
216 WINDOW *count_win;
217
218 /*
219  |      The following structure allows menu items to be flexibly declared.
220  |      The first item is the string describing the selection, the second 
221  |      is the address of the procedure to call when the item is selected,
222  |      and the third is the argument for the procedure.
223  |
224  |      For those systems with i18n, the string should be accompanied by a
225  |      catalog number.  The 'int *' should be replaced with 'void *' on 
226  |      systems with that type.
227  |
228  |      The first menu item will be the title of the menu, with NULL 
229  |      parameters for the procedure and argument, followed by the menu items.
230  |
231  |      If the procedure value is NULL, the menu item is displayed, but no 
232  |      procedure is called when the item is selected.  The number of the 
233  |      item will be returned.  If the third (argument) parameter is -1, no 
234  |      argument is given to the procedure when it is called.
235  */
236
237 struct menu_entries {
238         char *item_string;
239         int (*procedure)(struct menu_entries *);
240         struct menu_entries *ptr_argument;
241         int (*iprocedure)(int);
242         void (*nprocedure)(void);
243         int argument;
244         };
245
246 int main(int argc, char *argv[]);
247 unsigned char *resiz_line(int factor, struct text *rline, int rpos);
248 void insert(int character);
249 void delete(int disp);
250 void scanline(unsigned char *pos);
251 int tabshift(int temp_int);
252 int out_char(WINDOW *window, int character, int column);
253 int len_char(int character, int column);
254 void draw_line(int vertical, int horiz, unsigned char *ptr, int t_pos, int length);
255 void insert_line(int disp);
256 struct text *txtalloc(void);
257 struct files *name_alloc(void);
258 unsigned char *next_word(unsigned char *string);
259 void prev_word(void);
260 void control(void);
261 void emacs_control(void);
262 void bottom(void);
263 void top(void);
264 void nextline(void);
265 void prevline(void);
266 void left(int disp);
267 void right(int disp);
268 void find_pos(void);
269 void up(void);
270 void down(void);
271 void function_key(void);
272 void print_buffer(void);
273 void command_prompt(void);
274 void command(char *cmd_str1);
275 int scan(char *line, int offset, int column);
276 char *get_string(char *prompt, int advance);
277 int compare(char *string1, char *string2, int sensitive);
278 void goto_line(char *cmd_str);
279 void midscreen(int line, unsigned char *pnt);
280 void get_options(int numargs, char *arguments[]);
281 void check_fp(void);
282 void get_file(char *file_name);
283 void get_line(int length, unsigned char *in_string, int *append);
284 void draw_screen(void);
285 void finish(void);
286 int quit(int noverify);
287 void edit_abort(int arg);
288 void delete_text(void);
289 int write_file(char *file_name, int warn_if_exists);
290 int search(int display_message);
291 void search_prompt(void);
292 void del_char(void);
293 void undel_char(void);
294 void del_word(void);
295 void undel_word(void);
296 void del_line(void);
297 void undel_line(void);
298 void adv_word(void);
299 void move_rel(char *direction, int lines);
300 void eol(void);
301 void bol(void);
302 void adv_line(void);
303 void sh_command(char *string);
304 void set_up_term(void);
305 void resize_check(void);
306 int menu_op(struct menu_entries *);
307 void paint_menu(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);
308 void help(void);
309 void paint_info_win(void);
310 void no_info_window(void);
311 void create_info_window(void);
312 int file_op(int arg);
313 void shell_op(void);
314 void leave_op(void);
315 void redraw(void);
316 int Blank_Line(struct text *test_line);
317 void Format(void);
318 void ee_init(void);
319 void dump_ee_conf(void);
320 void echo_string(char *string);
321 void spell_op(void);
322 void ispell_op(void);
323 int first_word_len(struct text *test_line);
324 void Auto_Format(void);
325 void modes_op(void);
326 char *is_in_string(char *string, char *substring);
327 char *resolve_name(char *name);
328 int restrict_mode(void);
329 int unique_test(char *string, char *list[]);
330 void renumber_lines(struct text *firstline, int startnumber);
331 void strings_init(void);
332
333 /*
334  |      allocate space here for the strings that will be in the menu
335  */
336
337 struct menu_entries modes_menu[] = {
338         {"", NULL, NULL, NULL, NULL, 0},        /* title                */
339         {"", NULL, NULL, NULL, NULL, -1},       /* 1. tabs to spaces    */
340         {"", NULL, NULL, NULL, NULL, -1},       /* 2. case sensitive search*/
341         {"", NULL, NULL, NULL, NULL, -1},       /* 3. margins observed  */
342         {"", NULL, NULL, NULL, NULL, -1},       /* 4. auto-paragraph    */
343         {"", NULL, NULL, NULL, NULL, -1},       /* 5. eightbit characters*/
344         {"", NULL, NULL, NULL, NULL, -1},       /* 6. info window       */
345         {"", NULL, NULL, NULL, NULL, -1},       /* 7. emacs key bindings*/
346         {"", NULL, NULL, NULL, NULL, -1},       /* 8. right margin      */
347         {"", NULL, NULL, NULL, NULL, -1},       /* 9. chinese text      */
348         {"", NULL, NULL, NULL, dump_ee_conf, -1}, /* 10. save editor config */
349         {NULL, NULL, NULL, NULL, NULL, -1}      /* terminator           */
350         };
351
352 char *mode_strings[11]; 
353
354 #define NUM_MODES_ITEMS 10
355
356 struct menu_entries config_dump_menu[] = {
357         {"", NULL, NULL, NULL, NULL, 0}, 
358         {"", NULL, NULL, NULL, NULL, -1},
359         {"", NULL, NULL, NULL, NULL, -1},
360         {NULL, NULL, NULL, NULL, NULL, -1}
361         };
362
363 struct menu_entries leave_menu[] = {
364         {"", NULL, NULL, NULL, NULL, -1}, 
365         {"", NULL, NULL, NULL, finish, -1}, 
366         {"", NULL, NULL, quit, NULL, TRUE}, 
367         {NULL, NULL, NULL, NULL, NULL, -1}
368         };
369
370 #define READ_FILE 1
371 #define WRITE_FILE 2
372 #define SAVE_FILE 3
373
374 struct menu_entries file_menu[] = {
375         {"", NULL, NULL, NULL, NULL, -1},
376         {"", NULL, NULL, file_op, NULL, READ_FILE},
377         {"", NULL, NULL, file_op, NULL, WRITE_FILE},
378         {"", NULL, NULL, file_op, NULL, SAVE_FILE},
379         {"", NULL, NULL, NULL, print_buffer, -1},
380         {NULL, NULL, NULL, NULL, NULL, -1}
381         };
382
383 struct menu_entries search_menu[] = {
384         {"", NULL, NULL, NULL, NULL, 0}, 
385         {"", NULL, NULL, NULL, search_prompt, -1},
386         {"", NULL, NULL, search, NULL, TRUE},
387         {NULL, NULL, NULL, NULL, NULL, -1}
388         };
389
390 struct menu_entries spell_menu[] = {
391         {"", NULL, NULL, NULL, NULL, -1}, 
392         {"", NULL, NULL, NULL, spell_op, -1},
393         {"", NULL, NULL, NULL, ispell_op, -1},
394         {NULL, NULL, NULL, NULL, NULL, -1}
395         };
396
397 struct menu_entries misc_menu[] = {
398         {"", NULL, NULL, NULL, NULL, -1}, 
399         {"", NULL, NULL, NULL, Format, -1},
400         {"", NULL, NULL, NULL, shell_op, -1}, 
401         {"", menu_op, spell_menu, NULL, NULL, -1}, 
402         {NULL, NULL, NULL, NULL, NULL, -1}
403         };
404
405 struct menu_entries main_menu[] = {
406         {"", NULL, NULL, NULL, NULL, -1}, 
407         {"", NULL, NULL, NULL, leave_op, -1}, 
408         {"", NULL, NULL, NULL, help, -1},
409         {"", menu_op, file_menu, NULL, NULL, -1}, 
410         {"", NULL, NULL, NULL, redraw, -1}, 
411         {"", NULL, NULL, NULL, modes_op, -1}, 
412         {"", menu_op, search_menu, NULL, NULL, -1}, 
413         {"", menu_op, misc_menu, NULL, NULL, -1}, 
414         {NULL, NULL, NULL, NULL, NULL, -1}
415         };
416
417 char *help_text[23];
418 char *control_keys[5];
419
420 char *emacs_help_text[22];
421 char *emacs_control_keys[5];
422
423 char *command_strings[5];
424 char *commands[32];
425 char *init_strings[22];
426
427 #define MENU_WARN 1
428
429 #define max_alpha_char 36
430
431 /*
432  |      Declarations for strings for localization
433  */
434
435 char *com_win_message;          /* to be shown in com_win if no info window */
436 char *no_file_string;
437 char *ascii_code_str;
438 char *printer_msg_str;
439 char *command_str;
440 char *file_write_prompt_str;
441 char *file_read_prompt_str;
442 char *char_str;
443 char *unkn_cmd_str;
444 char *non_unique_cmd_msg;
445 char *line_num_str;
446 char *line_len_str;
447 char *current_file_str;
448 char *usage0;
449 char *usage1;
450 char *usage2;
451 char *usage3;
452 char *usage4;
453 char *file_is_dir_msg;
454 char *new_file_msg;
455 char *cant_open_msg;
456 char *open_file_msg;
457 char *file_read_fin_msg;
458 char *reading_file_msg;
459 char *read_only_msg;
460 char *file_read_lines_msg;
461 char *save_file_name_prompt;
462 char *file_not_saved_msg;
463 char *changes_made_prompt;
464 char *yes_char;
465 char *file_exists_prompt;
466 char *create_file_fail_msg;
467 char *writing_file_msg;
468 char *file_written_msg;
469 char *searching_msg;
470 char *str_not_found_msg;
471 char *search_prompt_str;
472 char *exec_err_msg;
473 char *continue_msg;
474 char *menu_cancel_msg;
475 char *menu_size_err_msg;
476 char *press_any_key_msg;
477 char *shell_prompt;
478 char *formatting_msg;
479 char *shell_echo_msg;
480 char *spell_in_prog_msg;
481 char *margin_prompt;
482 char *restricted_msg;
483 char *ON;
484 char *OFF;
485 char *HELP;
486 char *WRITE;
487 char *READ;
488 char *LINE;
489 char *FILE_str;
490 char *CHARACTER;
491 char *REDRAW;
492 char *RESEQUENCE;
493 char *AUTHOR;
494 char *VERSION;
495 char *CASE;
496 char *NOCASE;
497 char *EXPAND;
498 char *NOEXPAND;
499 char *Exit_string;
500 char *QUIT_string;
501 char *INFO;
502 char *NOINFO;
503 char *MARGINS;
504 char *NOMARGINS;
505 char *AUTOFORMAT;
506 char *NOAUTOFORMAT;
507 char *Echo;
508 char *PRINTCOMMAND;
509 char *RIGHTMARGIN;
510 char *HIGHLIGHT;
511 char *NOHIGHLIGHT;
512 char *EIGHTBIT;
513 char *NOEIGHTBIT;
514 char *EMACS_string;
515 char *NOEMACS_string;
516 char *conf_dump_err_msg;
517 char *conf_dump_success_msg;
518 char *conf_not_saved_msg;
519 char *ree_no_file_msg;
520 char *cancel_string;
521 char *menu_too_lrg_msg;
522 char *more_above_str, *more_below_str;
523
524 char *chinese_cmd, *nochinese_cmd;
525
526 #ifndef __STDC__
527 #ifndef HAS_STDLIB
528 extern char *malloc();
529 extern char *realloc();
530 extern char *getenv();
531 FILE *fopen();                  /* declaration for open function        */
532 #endif /* HAS_STDLIB */
533 #endif /* __STDC__ */
534
535 int
536 main(int argc, char **argv)             /* beginning of main program            */
537 {
538         int counter;
539
540         for (counter = 1; counter < 24; counter++)
541                 signal(counter, SIG_IGN);
542
543         signal(SIGCHLD, SIG_DFL);
544         signal(SIGSEGV, SIG_DFL);
545         signal(SIGINT, edit_abort);
546         signal(SIGHUP, edit_abort);
547
548         d_char = malloc(3);     /* provide a buffer for multi-byte chars */
549         d_word = malloc(150);
550         *d_word = 0;
551         d_line = NULL;
552         dlt_line = txtalloc();
553         dlt_line->line = d_line;
554         dlt_line->line_length = 0;
555         curr_line = first_line = txtalloc();
556         curr_line->line = point = malloc(10);
557         curr_line->line_length = 1;
558         curr_line->max_length = 10;
559         curr_line->prev_line = NULL;
560         curr_line->next_line = NULL;
561         curr_line->line_number  = 1;
562         srch_str = NULL;
563         u_srch_str = NULL;
564         position = 1;
565         scr_pos =0;
566         scr_vert = 0;
567         scr_horz = 0;
568         bit_bucket = fopen(_PATH_DEVNULL, "w");
569         edit = TRUE;
570         gold = case_sen = FALSE;
571         shell_fork = TRUE;
572         strings_init();
573         ee_init();
574         if (argc > 0 )
575                 get_options(argc, argv);
576         set_up_term();
577         if (right_margin == 0)
578                 right_margin = COLS - 1;
579         if (top_of_stack == NULL)
580         {
581                 if (restrict_mode())
582                 {
583                         wmove(com_win, 0, 0);
584                         werase(com_win);
585                         wprintw(com_win, ree_no_file_msg);
586                         wrefresh(com_win);
587                         edit_abort(0);
588                 }
589                 wprintw(com_win, no_file_string);
590                 wrefresh(com_win);
591         }
592         else
593                 check_fp();
594
595         clear_com_win = TRUE;
596
597         while(edit) 
598         {
599                 if (info_window)
600                 {
601                         snprintf(count_text, count_text_len, "L: %d C: %d %s", \
602                                 curr_line->line_number, scr_horz + 1, count_text_default);
603                         wmove(count_win, 0, 0);
604                         if (!nohighlight)
605                                 wstandout(count_win);
606                         wprintw(count_win, count_text);
607                         wstandend(count_win);
608                         wnoutrefresh(count_win);
609                 }
610
611                 wnoutrefresh(text_win);
612                 doupdate();
613                 in = wgetch(text_win);
614                 if (in == -1)
615                         continue;
616
617                 resize_check();
618
619                 if (clear_com_win)
620                 {
621                         clear_com_win = FALSE;
622                         wmove(com_win, 0, 0);
623                         werase(com_win);
624                         if (!info_window)
625                         {
626                                 wprintw(com_win, "%s", com_win_message);
627                         }
628                         wrefresh(com_win);
629                 }
630
631                 if (in > 255)
632                         function_key();
633                 else if ((in == '\10') || (in == 127))
634                 {
635                         in = 8;         /* make sure key is set to backspace */
636                         delete(TRUE);
637                 }
638                 else if ((in > 31) || (in == 9))
639                         insert(in);
640                 else if ((in >= 0) && (in <= 31))
641                 {
642                         if (emacs_keys_mode)
643                                 emacs_control();
644                         else
645                                 control();
646                 }
647         }
648         return(0);
649 }
650
651 /* factor: resize factor */
652 /* rline: position in line */
653 unsigned char *
654 resiz_line(int factor, struct text *rline, int rpos)
655 /* resize the line to length + factor*/
656 {
657         unsigned char *rpoint;
658         int resiz_var;
659  
660         rline->max_length += factor;
661         rpoint = rline->line = realloc(rline->line, rline->max_length );
662         for (resiz_var = 1 ; (resiz_var < rpos) ; resiz_var++)
663                 rpoint++;
664         return(rpoint);
665 }
666
667 void 
668 insert(int character)           /* insert character into line           */
669 {
670         int counter;
671         int value;
672         unsigned char *temp;    /* temporary pointer                    */
673         unsigned char *temp2;   /* temporary pointer                    */
674
675         if ((character == '\011') && (expand_tabs))
676         {
677                 counter = len_char('\011', scr_horz);
678                 for (; counter > 0; counter--)
679                         insert(' ');
680                 if (auto_format)
681                         Auto_Format();
682                 return;
683         }
684         text_changes = TRUE;
685         if ((curr_line->max_length - curr_line->line_length) < 5)
686                 point = resiz_line(10, curr_line, position);
687         curr_line->line_length++;
688         temp = point;
689         counter = position;
690         while (counter < curr_line->line_length)        /* find end of line */
691         {
692                 counter++;
693                 temp++;
694         }
695         temp++;                 /* increase length of line by one       */
696         while (point < temp)
697         {
698                 temp2=temp - 1;
699                 *temp= *temp2;  /* shift characters over by one         */
700                 temp--;
701         }
702         *point = character;     /* insert new character                 */
703         wclrtoeol(text_win);
704         if (((character >= 0) && (character < ' ')) || (character >= 127)) /* check for TAB character*/
705         {
706                 scr_pos = scr_horz += out_char(text_win, character, scr_horz);
707                 point++;
708                 position++;
709         }
710         else
711         {
712                 waddch(text_win, character);
713                 scr_pos = ++scr_horz;
714                 point++;
715                 position ++;
716         }
717
718         if ((observ_margins) && (right_margin < scr_pos))
719         {
720                 counter = position;
721                 while (scr_pos > right_margin)
722                         prev_word();
723                 if (scr_pos == 0)
724                 {
725                         while (position < counter)
726                                 right(TRUE);
727                 }
728                 else
729                 {
730                         counter -= position;
731                         insert_line(TRUE);
732                         for (value = 0; value < counter; value++)
733                                 right(TRUE);
734                 }
735         }
736
737         if ((scr_horz - horiz_offset) > last_col)
738         {
739                 horiz_offset += 8;
740                 midscreen(scr_vert, point);
741         }
742
743         if ((auto_format) && (character == ' ') && (!formatted))
744                 Auto_Format();
745         else if ((character != ' ') && (character != '\t'))
746                 formatted = FALSE;
747
748         draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
749 }
750
751 void 
752 delete(int disp)                        /* delete character             */
753 {
754         unsigned char *tp;
755         unsigned char *temp2;
756         struct text *temp_buff;
757         int temp_vert;
758         int temp_pos;
759         int del_width = 1;
760
761         if (point != curr_line->line)   /* if not at beginning of line  */
762         {
763                 text_changes = TRUE;
764                 temp2 = tp = point;
765                 if ((ee_chinese) && (position >= 2) && (*(point - 2) > 127))
766                 {
767                         del_width = 2;
768                 }
769                 tp -= del_width;
770                 point -= del_width;
771                 position -= del_width;
772                 temp_pos = position;
773                 curr_line->line_length -= del_width;
774                 if ((*tp < ' ') || (*tp >= 127))        /* check for TAB */
775                         scanline(tp);
776                 else
777                         scr_horz -= del_width;
778                 scr_pos = scr_horz;
779                 if (in == 8)
780                 {
781                         if (del_width == 1)
782                                 *d_char = *point; /* save deleted character  */
783                         else
784                         {
785                                 d_char[0] = *point;
786                                 d_char[1] = *(point + 1);
787                         }
788                         d_char[del_width] = 0;
789                 }
790                 while (temp_pos <= curr_line->line_length)
791                 {
792                         temp_pos++;
793                         *tp = *temp2;
794                         tp++;
795                         temp2++;
796                 }
797                 if (scr_horz < horiz_offset)
798                 {
799                         horiz_offset -= 8;
800                         midscreen(scr_vert, point);
801                 }
802         }
803         else if (curr_line->prev_line != NULL)
804         {
805                 text_changes = TRUE;
806                 left(disp);                     /* go to previous line  */
807                 temp_buff = curr_line->next_line;
808                 point = resiz_line(temp_buff->line_length, curr_line, position);
809                 if (temp_buff->next_line != NULL)
810                         temp_buff->next_line->prev_line = curr_line;
811                 curr_line->next_line = temp_buff->next_line;
812                 renumber_lines(curr_line->next_line, curr_line->line_number + 1);
813                 temp2 = temp_buff->line;
814                 if (in == 8)
815                 {
816                         d_char[0] = '\n';
817                         d_char[1] = 0;
818                 }
819                 tp = point;
820                 temp_pos = 1;
821                 while (temp_pos < temp_buff->line_length)
822                 {
823                         curr_line->line_length++;
824                         temp_pos++;
825                         *tp = *temp2;
826                         tp++;
827                         temp2++;
828                 }
829                 *tp = 0;
830                 free(temp_buff->line);
831                 free(temp_buff);
832                 temp_buff = curr_line;
833                 temp_vert = scr_vert;
834                 scr_pos = scr_horz;
835                 if (scr_vert < last_line)
836                 {
837                         wmove(text_win, scr_vert + 1, 0);
838                         wdeleteln(text_win);
839                 }
840                 while ((temp_buff != NULL) && (temp_vert < last_line))
841                 {
842                         temp_buff = temp_buff->next_line;
843                         temp_vert++;
844                 }
845                 if ((temp_vert == last_line) && (temp_buff != NULL))
846                 {
847                         tp = temp_buff->line;
848                         wmove(text_win, last_line,0);
849                         wclrtobot(text_win);
850                         draw_line(last_line, 0, tp, 1, temp_buff->line_length);
851                         wmove(text_win, scr_vert, (scr_horz - horiz_offset));
852                 }
853         }
854         draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
855         formatted = FALSE;
856 }
857
858 void 
859 scanline(unsigned char *pos)    /* find the proper horizontal position for the pointer  */
860 {
861         int temp;
862         unsigned char *ptr;
863
864         ptr = curr_line->line;
865         temp = 0;
866         while (ptr < pos)
867         {
868                 if (*ptr <= 8)
869                         temp += 2;
870                 else if (*ptr == 9)
871                         temp += tabshift(temp);
872                 else if ((*ptr >= 10) && (*ptr <= 31))
873                         temp += 2;
874                 else if ((*ptr >= 32) && (*ptr < 127))
875                         temp++;
876                 else if (*ptr == 127)
877                         temp += 2;
878                 else if (!eightbit)
879                         temp += 5;
880                 else
881                         temp++;
882                 ptr++;
883         }
884         scr_horz = temp;
885         if ((scr_horz - horiz_offset) > last_col)
886         {
887                 horiz_offset = (scr_horz - (scr_horz % 8)) - (COLS - 8);
888                 midscreen(scr_vert, point);
889         }
890         else if (scr_horz < horiz_offset)
891         {
892                 horiz_offset = max(0, (scr_horz - (scr_horz % 8)));
893                 midscreen(scr_vert, point);
894         }
895 }
896
897 int 
898 tabshift(int temp_int)          /* give the number of spaces to shift   */
899 {
900         int leftover;
901
902         leftover = ((temp_int + 1) % 8);
903         if (leftover == 0)
904                 return (1);
905         else
906                 return (9 - leftover);
907 }
908
909 int 
910 out_char(WINDOW *window, int character, int column)
911 /* output non-printing character */
912 {
913         int i1, i2;
914         unsigned char *string;
915         char string2[8];
916
917         if (character == TAB)
918         {
919                 i1 = tabshift(column);
920                 for (i2 = 0; 
921                   (i2 < i1) && (((column+i2+1)-horiz_offset) < last_col); i2++)
922                 {
923                         waddch(window, ' ');
924                 }
925                 return(i1);
926         }
927         else if ((character >= '\0') && (character < ' '))
928         {
929                 string = table[(int) character];
930         }
931         else if ((character < 0) || (character >= 127))
932         {
933                 if (character == 127)
934                         string = "^?";
935                 else if (!eightbit)
936                 {
937                         sprintf(string2, "<%d>", (character < 0) ? (character + 256) : character);
938                         string = string2;
939                 }
940                 else
941                 {
942                         waddch(window, (unsigned char)character );
943                         return(1);
944                 }
945         }
946         else
947         {
948                 waddch(window, (unsigned char)character);
949                 return(1);
950         }
951         for (i2 = 0; (string[i2] != 0) && (((column+i2+1)-horiz_offset) < last_col); i2++)
952                 waddch(window, string[i2]);
953         return(strlen(string));
954 }
955
956 /* column: the column must be known to provide spacing for tabs */
957 int
958 len_char(int character, int column)     /* return the length of the character   */
959 {
960         int length;
961
962         if (character == '\t')
963                 length = tabshift(column);
964         else if ((character >= 0) && (character < 32))
965                 length = 2;
966         else if ((character >= 32) && (character <= 126))
967                 length = 1;
968         else if (character == 127)
969                 length = 2;
970         else if (((character > 126) || (character < 0)) && (!eightbit))
971                 length = 5;
972         else
973                 length = 1;
974
975         return(length);
976 }
977
978 /*
979 vertical: current vertical position on screen
980 horiz:  current horizontal position on screen
981 ptr:    pointer to line
982 t_pos:  current position (offset in bytes) from bol
983 length: length (in bytes) of line
984 */
985 void
986 draw_line(int vertical, int horiz, unsigned char *ptr, int t_pos, int length)
987 /* redraw line from current position */
988 {
989         int d;          /* partial length of special or tab char to display  */
990         unsigned char *temp;    /* temporary pointer to position in line             */
991         int abs_column; /* offset in screen units from begin of line         */
992         int column;     /* horizontal position on screen                     */
993         int row;        /* vertical position on screen                       */
994         int posit;      /* temporary position indicator within line          */
995
996         abs_column = horiz;
997         column = horiz - horiz_offset;
998         row = vertical;
999         temp = ptr;
1000         d = 0;
1001         posit = t_pos;
1002         if (column < 0)
1003         {
1004                 wmove(text_win, row, 0);
1005                 wclrtoeol(text_win);
1006         }
1007         while (column < 0)
1008         {
1009                 d = len_char(*temp, abs_column);
1010                 abs_column += d;
1011                 column += d;
1012                 posit++;
1013                 temp++;
1014         }
1015         wmove(text_win, row, column);
1016         wclrtoeol(text_win);
1017         while ((posit < length) && (column <= last_col))
1018         {
1019                 if ((*temp < 32) || (*temp >= 127))
1020                 {
1021                         column += len_char(*temp, abs_column);
1022                         abs_column += out_char(text_win, *temp, abs_column);
1023                 }
1024                 else
1025                 {
1026                         abs_column++;
1027                         column++;
1028                         waddch(text_win, *temp);
1029                 }
1030                 posit++;
1031                 temp++;
1032         }
1033         if (column < last_col)
1034                 wclrtoeol(text_win);
1035         wmove(text_win, vertical, (horiz - horiz_offset));
1036 }
1037
1038 void 
1039 insert_line(int disp)                   /* insert new line              */
1040 {
1041         int temp_pos;
1042         int temp_pos2;
1043         unsigned char *temp;
1044         unsigned char *extra;
1045         struct text *temp_nod;
1046
1047         text_changes = TRUE;
1048         wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1049         wclrtoeol(text_win);
1050         temp_nod= txtalloc();
1051         temp_nod->line = extra= malloc(10);
1052         temp_nod->line_length = 1;
1053         temp_nod->max_length = 10;
1054         temp_nod->next_line = curr_line->next_line;
1055         renumber_lines(temp_nod, curr_line->line_number + 1);
1056         if (temp_nod->next_line != NULL)
1057                 temp_nod->next_line->prev_line = temp_nod;
1058         temp_nod->prev_line = curr_line;
1059         curr_line->next_line = temp_nod;
1060         temp_pos2 = position;
1061         temp = point;
1062         if (temp_pos2 < curr_line->line_length)
1063         {
1064                 temp_pos = 1;
1065                 while (temp_pos2 < curr_line->line_length)
1066                 {
1067                         if ((temp_nod->max_length - temp_nod->line_length)< 5)
1068                                 extra = resiz_line(10, temp_nod, temp_pos);
1069                         temp_nod->line_length++;
1070                         temp_pos++;
1071                         temp_pos2++;
1072                         *extra= *temp;
1073                         extra++;
1074                         temp++;
1075                 }
1076                 temp=point;
1077                 *temp = 0;
1078                 temp = resiz_line((1 - temp_nod->line_length), curr_line, position);
1079                 curr_line->line_length = 1 + temp - curr_line->line;
1080         }
1081         curr_line->line_length = position;
1082         curr_line = temp_nod;
1083         *extra = 0;
1084         position = 1;
1085         point= curr_line->line;
1086         if (disp)
1087         {
1088                 if (scr_vert < last_line)
1089                 {
1090                         scr_vert++;
1091                         wclrtoeol(text_win);
1092                         wmove(text_win, scr_vert, 0);
1093                         winsertln(text_win);
1094                 }
1095                 else
1096                 {
1097                         wmove(text_win, 0,0);
1098                         wdeleteln(text_win);
1099                         wmove(text_win, last_line,0);
1100                         wclrtobot(text_win);
1101                 }
1102                 scr_pos = scr_horz = 0;
1103                 if (horiz_offset)
1104                 {
1105                         horiz_offset = 0;
1106                         midscreen(scr_vert, point);
1107                 }
1108                 draw_line(scr_vert, scr_horz, point, position,
1109                         curr_line->line_length);
1110         }
1111 }
1112
1113 struct text *txtalloc(void)             /* allocate space for line structure    */
1114 {
1115         return((struct text *) malloc(sizeof( struct text)));
1116 }
1117
1118 struct files *name_alloc(void)  /* allocate space for file name list node */
1119 {
1120         return((struct files *) malloc(sizeof( struct files)));
1121 }
1122
1123 unsigned char *next_word(unsigned char *string)
1124 /* move to next word in string */
1125 {
1126         while ((*string != 0) && ((*string != 32) && (*string != 9)))
1127                 string++;
1128         while ((*string != 0) && ((*string == 32) || (*string == 9)))
1129                 string++;
1130         return(string);
1131 }
1132
1133 void 
1134 prev_word(void) /* move to start of previous word in text       */
1135 {
1136         if (position != 1)
1137         {
1138                 if ((position != 1) && ((point[-1] == ' ') || (point[-1] == '\t')))
1139                 {       /* if at the start of a word    */
1140                         while ((position != 1) && ((*point != ' ') && (*point != '\t')))
1141                                 left(TRUE);
1142                 }
1143                 while ((position != 1) && ((*point == ' ') || (*point == '\t')))
1144                         left(TRUE);
1145                 while ((position != 1) && ((*point != ' ') && (*point != '\t')))
1146                         left(TRUE);
1147                 if ((position != 1) && ((*point == ' ') || (*point == '\t')))
1148                         right(TRUE);
1149         }
1150         else
1151                 left(TRUE);
1152 }
1153
1154 void 
1155 control(void)                   /* use control for commands             */
1156 {
1157         char *string;
1158
1159         if (in == 1)            /* control a    */
1160         {
1161                 string = get_string(ascii_code_str, TRUE);
1162                 if (*string != 0)
1163                 {
1164                         in = atoi(string);
1165                         wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1166                         insert(in);
1167                 }
1168                 free(string);
1169         }
1170         else if (in == 2)       /* control b    */
1171                 bottom();
1172         else if (in == 3)       /* control c    */
1173         {
1174                 command_prompt();
1175         }
1176         else if (in == 4)       /* control d    */
1177                 down();
1178         else if (in == 5)       /* control e    */
1179                 search_prompt();
1180         else if (in == 6)       /* control f    */
1181                 undel_char();
1182         else if (in == 7)       /* control g    */
1183                 bol();
1184         else if (in == 8)       /* control h    */
1185                 delete(TRUE);
1186         else if (in == 9)       /* control i    */
1187                 ;
1188         else if (in == 10)      /* control j    */
1189                 insert_line(TRUE);
1190         else if (in == 11)      /* control k    */
1191                 del_char();
1192         else if (in == 12)      /* control l    */
1193                 left(TRUE);
1194         else if (in == 13)      /* control m    */
1195                 insert_line(TRUE);
1196         else if (in == 14)      /* control n    */
1197                 move_rel("d", max(5, (last_line - 5)));
1198         else if (in == 15)      /* control o    */
1199                 eol();
1200         else if (in == 16)      /* control p    */
1201                 move_rel("u", max(5, (last_line - 5)));
1202         else if (in == 17)      /* control q    */
1203                 ;
1204         else if (in == 18)      /* control r    */
1205                 right(TRUE);
1206         else if (in == 19)      /* control s    */
1207                 ;
1208         else if (in == 20)      /* control t    */
1209                 top();
1210         else if (in == 21)      /* control u    */
1211                 up();
1212         else if (in == 22)      /* control v    */
1213                 undel_word();
1214         else if (in == 23)      /* control w    */
1215                 del_word();
1216         else if (in == 24)      /* control x    */
1217                 search(TRUE);
1218         else if (in == 25)      /* control y    */
1219                 del_line();
1220         else if (in == 26)      /* control z    */
1221                 undel_line();
1222         else if (in == 27)      /* control [ (escape)   */
1223         {
1224                 menu_op(main_menu);
1225         }       
1226 }
1227
1228 /*
1229  |      Emacs control-key bindings
1230  */
1231
1232 void 
1233 emacs_control(void)
1234 {
1235         char *string;
1236
1237         if (in == 1)            /* control a    */
1238                 bol();
1239         else if (in == 2)       /* control b    */
1240                 left(TRUE);
1241         else if (in == 3)       /* control c    */
1242         {
1243                 command_prompt();
1244         }
1245         else if (in == 4)       /* control d    */
1246                 del_char();
1247         else if (in == 5)       /* control e    */
1248                 eol();
1249         else if (in == 6)       /* control f    */
1250                 right(TRUE);
1251         else if (in == 7)       /* control g    */
1252                 move_rel("u", max(5, (last_line - 5)));
1253         else if (in == 8)       /* control h    */
1254                 delete(TRUE);
1255         else if (in == 9)       /* control i    */
1256                 ;
1257         else if (in == 10)      /* control j    */
1258                 undel_char();
1259         else if (in == 11)      /* control k    */
1260                 del_line();
1261         else if (in == 12)      /* control l    */
1262                 undel_line();
1263         else if (in == 13)      /* control m    */
1264                 insert_line(TRUE);
1265         else if (in == 14)      /* control n    */
1266                 down();
1267         else if (in == 15)      /* control o    */
1268         {
1269                 string = get_string(ascii_code_str, TRUE);
1270                 if (*string != 0)
1271                 {
1272                         in = atoi(string);
1273                         wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1274                         insert(in);
1275                 }
1276                 free(string);
1277         }
1278         else if (in == 16)      /* control p    */
1279                 up();
1280         else if (in == 17)      /* control q    */
1281                 ;
1282         else if (in == 18)      /* control r    */
1283                 undel_word();
1284         else if (in == 19)      /* control s    */
1285                 ;
1286         else if (in == 20)      /* control t    */
1287                 top();
1288         else if (in == 21)      /* control u    */
1289                 bottom();
1290         else if (in == 22)      /* control v    */
1291                 move_rel("d", max(5, (last_line - 5)));
1292         else if (in == 23)      /* control w    */
1293                 del_word();
1294         else if (in == 24)      /* control x    */
1295                 search(TRUE);
1296         else if (in == 25)      /* control y    */
1297                 search_prompt();
1298         else if (in == 26)      /* control z    */
1299                 adv_word();
1300         else if (in == 27)      /* control [ (escape)   */
1301         {
1302                 menu_op(main_menu);
1303         }       
1304 }
1305
1306 void 
1307 bottom(void)                    /* go to bottom of file                 */
1308 {
1309         while (curr_line->next_line != NULL)
1310                 curr_line = curr_line->next_line;
1311         point = curr_line->line;
1312         if (horiz_offset)
1313                 horiz_offset = 0;
1314         position = 1;
1315         midscreen(last_line, point);
1316         scr_pos = scr_horz;
1317 }
1318
1319 void 
1320 top(void)                               /* go to top of file                    */
1321 {
1322         while (curr_line->prev_line != NULL)
1323                 curr_line = curr_line->prev_line;
1324         point = curr_line->line;
1325         if (horiz_offset)
1326                 horiz_offset = 0;
1327         position = 1;
1328         midscreen(0, point);
1329         scr_pos = scr_horz;
1330 }
1331
1332 void 
1333 nextline(void)                  /* move pointers to start of next line  */
1334 {
1335         curr_line = curr_line->next_line;
1336         point = curr_line->line;
1337         position = 1;
1338         if (scr_vert == last_line)
1339         {
1340                 wmove(text_win, 0,0);
1341                 wdeleteln(text_win);
1342                 wmove(text_win, last_line,0);
1343                 wclrtobot(text_win);
1344                 draw_line(last_line,0,point,1,curr_line->line_length);
1345         }
1346         else
1347                 scr_vert++;
1348 }
1349
1350 void 
1351 prevline(void)                  /* move pointers to start of previous line*/
1352 {
1353         curr_line = curr_line->prev_line;
1354         point = curr_line->line;
1355         position = 1;
1356         if (scr_vert == 0)
1357         {
1358                 winsertln(text_win);
1359                 draw_line(0,0,point,1,curr_line->line_length);
1360         }
1361         else
1362                 scr_vert--;
1363         while (position < curr_line->line_length)
1364         {
1365                 position++;
1366                 point++;
1367         }
1368 }
1369
1370 void 
1371 left(int disp)                          /* move left one character      */
1372 {
1373         if (point != curr_line->line)   /* if not at begin of line      */
1374         {
1375                 if ((ee_chinese) && (position >= 2) && (*(point - 2) > 127))
1376                 {
1377                         point--;
1378                         position--;
1379                 }
1380                 point--;
1381                 position--;
1382                 scanline(point);
1383                 wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1384                 scr_pos = scr_horz;
1385         }
1386         else if (curr_line->prev_line != NULL)
1387         {
1388                 if (!disp)
1389                 {
1390                         curr_line = curr_line->prev_line;
1391                         point = curr_line->line + curr_line->line_length;
1392                         position = curr_line->line_length;
1393                         return;
1394                 }
1395                 position = 1;
1396                 prevline();
1397                 scanline(point);
1398                 scr_pos = scr_horz;
1399                 wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1400         }
1401 }
1402
1403 void 
1404 right(int disp)                         /* move right one character     */
1405 {
1406         if (position < curr_line->line_length)
1407         {
1408                 if ((ee_chinese) && (*point > 127) && 
1409                     ((curr_line->line_length - position) >= 2))
1410                 {
1411                         point++;
1412                         position++;
1413                 }
1414                 point++;
1415                 position++;
1416                 scanline(point);
1417                 wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1418                 scr_pos = scr_horz;
1419         }
1420         else if (curr_line->next_line != NULL)
1421         {
1422                 if (!disp)
1423                 {
1424                         curr_line = curr_line->next_line;
1425                         point = curr_line->line;
1426                         position = 1;
1427                         return;
1428                 }
1429                 nextline();
1430                 scr_pos = scr_horz = 0;
1431                 if (horiz_offset)
1432                 {
1433                         horiz_offset = 0;
1434                         midscreen(scr_vert, point);
1435                 }
1436                 wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1437                 position = 1;   
1438         }
1439 }
1440
1441 void 
1442 find_pos(void)          /* move to the same column as on other line     */
1443 {
1444         scr_horz = 0;
1445         position = 1;
1446         while ((scr_horz < scr_pos) && (position < curr_line->line_length))
1447         {
1448                 if (*point == 9)
1449                         scr_horz += tabshift(scr_horz);
1450                 else if (*point < ' ')
1451                         scr_horz += 2;
1452                 else if ((ee_chinese) && (*point > 127) && 
1453                     ((curr_line->line_length - position) >= 2))
1454                 {
1455                         scr_horz += 2;
1456                         point++;
1457                         position++;
1458                 }
1459                 else
1460                         scr_horz++;
1461                 position++;
1462                 point++;
1463         }
1464         if ((scr_horz - horiz_offset) > last_col)
1465         {
1466                 horiz_offset = (scr_horz - (scr_horz % 8)) - (COLS - 8);
1467                 midscreen(scr_vert, point);
1468         }
1469         else if (scr_horz < horiz_offset)
1470         {
1471                 horiz_offset = max(0, (scr_horz - (scr_horz % 8)));
1472                 midscreen(scr_vert, point);
1473         }
1474         wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1475 }
1476
1477 void 
1478 up(void)                                        /* move up one line             */
1479 {
1480         if (curr_line->prev_line != NULL)
1481         {
1482                 prevline();
1483                 point = curr_line->line;
1484                 find_pos();
1485         }
1486 }
1487
1488 void 
1489 down(void)                                      /* move down one line           */
1490 {
1491         if (curr_line->next_line != NULL)
1492         {
1493                 nextline();
1494                 find_pos();
1495         }
1496 }
1497
1498 void 
1499 function_key(void)                              /* process function key         */
1500 {
1501         if (in == KEY_LEFT)
1502                 left(TRUE);
1503         else if (in == KEY_RIGHT)
1504                 right(TRUE);
1505         else if (in == KEY_HOME)
1506                 bol();
1507         else if (in == KEY_END)
1508                 eol();
1509         else if ( in == KEY_UP)
1510                 up();
1511         else if (in == KEY_DOWN)
1512                 down();
1513         else if (in == KEY_NPAGE)
1514                 move_rel("d", max( 5, (last_line - 5)));
1515         else if (in == KEY_PPAGE)
1516                 move_rel("u", max(5, (last_line - 5)));
1517         else if (in == KEY_DL)
1518                 del_line();
1519         else if (in == KEY_DC)
1520                 del_char();
1521         else if (in == KEY_BACKSPACE)
1522                 delete(TRUE);
1523         else if (in == KEY_IL)
1524         {               /* insert a line before current line    */
1525                 insert_line(TRUE);
1526                 left(TRUE);
1527         }
1528         else if (in == KEY_F(1))
1529                 gold = !gold;
1530         else if (in == KEY_F(2))
1531         {
1532                 if (gold)
1533                 {
1534                         gold = FALSE;
1535                         undel_line();
1536                 }
1537                 else
1538                         undel_char();
1539         }
1540         else if (in == KEY_F(3))
1541         {
1542                 if (gold)
1543                 {
1544                         gold = FALSE;
1545                         undel_word();
1546                 }
1547                 else
1548                         del_word();
1549         }
1550         else if (in == KEY_F(4))
1551         {
1552                 if (gold)
1553                 {
1554                         gold = FALSE;
1555                         paint_info_win();
1556                         midscreen(scr_vert, point);
1557                 }
1558                 else
1559                         adv_word();
1560         }
1561         else if (in == KEY_F(5))
1562         {
1563                 if (gold)
1564                 {
1565                         gold = FALSE;
1566                         search_prompt();
1567                 }
1568                 else
1569                         search(TRUE);
1570         }
1571         else if (in == KEY_F(6))
1572         {
1573                 if (gold)
1574                 {
1575                         gold = FALSE;
1576                         bottom();
1577                 }
1578                 else
1579                         top();
1580         }
1581         else if (in == KEY_F(7))
1582         {
1583                 if (gold)
1584                 {
1585                         gold = FALSE;
1586                         eol();
1587                 }
1588                 else
1589                         bol();
1590         }
1591         else if (in == KEY_F(8))
1592         {
1593                 if (gold)
1594                 {
1595                         gold = FALSE;
1596                         command_prompt();
1597                 } 
1598                 else
1599                         adv_line();
1600         }
1601 }
1602
1603 void 
1604 print_buffer(void)
1605 {
1606         char buffer[256];
1607
1608         sprintf(buffer, ">!%s", print_command);
1609         wmove(com_win, 0, 0);
1610         wclrtoeol(com_win);
1611         wprintw(com_win, printer_msg_str, print_command);
1612         wrefresh(com_win);
1613         command(buffer);
1614 }
1615
1616 void 
1617 command_prompt(void)
1618 {
1619         char *cmd_str;
1620         int result;
1621
1622         info_type = COMMANDS;
1623         paint_info_win();
1624         cmd_str = get_string(command_str, TRUE);
1625         if ((result = unique_test(cmd_str, commands)) != 1)
1626         {
1627                 werase(com_win);
1628                 wmove(com_win, 0, 0);
1629                 if (result == 0)
1630                         wprintw(com_win, unkn_cmd_str, cmd_str);
1631                 else
1632                         wprintw(com_win, non_unique_cmd_msg);
1633
1634                 wrefresh(com_win);
1635
1636                 info_type = CONTROL_KEYS;
1637                 paint_info_win();
1638
1639                 if (cmd_str != NULL)
1640                         free(cmd_str);
1641                 return;
1642         }
1643         command(cmd_str);
1644         wrefresh(com_win);
1645         wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1646         info_type = CONTROL_KEYS;
1647         paint_info_win();
1648         if (cmd_str != NULL)
1649                 free(cmd_str);
1650 }
1651
1652 void 
1653 command(char *cmd_str1)         /* process commands from keyboard       */
1654 {
1655         char *cmd_str2 = NULL;
1656         char *cmd_str = cmd_str1;
1657
1658         clear_com_win = TRUE;
1659         if (compare(cmd_str, HELP, FALSE))
1660                 help();
1661         else if (compare(cmd_str, WRITE, FALSE))
1662         {
1663                 if (restrict_mode())
1664                 {
1665                         return;
1666                 }
1667                 cmd_str = next_word(cmd_str);
1668                 if (*cmd_str == 0)
1669                 {
1670                         cmd_str = cmd_str2 = get_string(file_write_prompt_str, TRUE);
1671                 }
1672                 tmp_file = resolve_name(cmd_str);
1673                 write_file(tmp_file, 1);
1674                 if (tmp_file != cmd_str)
1675                         free(tmp_file);
1676         }
1677         else if (compare(cmd_str, READ, FALSE))
1678         {
1679                 if (restrict_mode())
1680                 {
1681                         return;
1682                 }
1683                 cmd_str = next_word(cmd_str);
1684                 if (*cmd_str == 0)
1685                 {
1686                         cmd_str = cmd_str2 = get_string(file_read_prompt_str, TRUE);
1687                 }
1688                 tmp_file = cmd_str;
1689                 recv_file = TRUE;
1690                 tmp_file = resolve_name(cmd_str);
1691                 check_fp();
1692                 if (tmp_file != cmd_str)
1693                         free(tmp_file);
1694         }
1695         else if (compare(cmd_str, LINE, FALSE))
1696         {
1697                 wmove(com_win, 0, 0);
1698                 wclrtoeol(com_win);
1699                 wprintw(com_win, line_num_str, curr_line->line_number);
1700                 wprintw(com_win, line_len_str, curr_line->line_length);
1701         }
1702         else if (compare(cmd_str, FILE_str, FALSE))
1703         {
1704                 wmove(com_win, 0, 0);
1705                 wclrtoeol(com_win);
1706                 if (in_file_name == NULL)
1707                         wprintw(com_win, no_file_string);
1708                 else
1709                         wprintw(com_win, current_file_str, in_file_name);
1710         }
1711         else if ((*cmd_str >= '0') && (*cmd_str <= '9'))
1712                 goto_line(cmd_str);
1713         else if (compare(cmd_str, CHARACTER, FALSE))
1714         {
1715                 wmove(com_win, 0, 0);
1716                 wclrtoeol(com_win);
1717                 wprintw(com_win, char_str, *point);
1718         }
1719         else if (compare(cmd_str, REDRAW, FALSE))
1720                 redraw();
1721         else if (compare(cmd_str, RESEQUENCE, FALSE))
1722         {
1723                 tmp_line = first_line->next_line;
1724                 while (tmp_line != NULL)
1725                 {
1726                 tmp_line->line_number = tmp_line->prev_line->line_number + 1;
1727                         tmp_line = tmp_line->next_line;
1728                 }
1729         }
1730         else if (compare(cmd_str, AUTHOR, FALSE))
1731         {
1732                 wmove(com_win, 0, 0);
1733                 wclrtoeol(com_win);
1734                 wprintw(com_win, "written by Hugh Mahon");
1735         }
1736         else if (compare(cmd_str, VERSION, FALSE))
1737         {
1738                 wmove(com_win, 0, 0);
1739                 wclrtoeol(com_win);
1740                 wprintw(com_win, "%s", version);
1741         }
1742         else if (compare(cmd_str, CASE, FALSE))
1743                 case_sen = TRUE;
1744         else if (compare(cmd_str, NOCASE, FALSE))
1745                 case_sen = FALSE;
1746         else if (compare(cmd_str, EXPAND, FALSE))
1747                 expand_tabs = TRUE;
1748         else if (compare(cmd_str, NOEXPAND, FALSE))
1749                 expand_tabs = FALSE;
1750         else if (compare(cmd_str, Exit_string, FALSE))
1751                 finish();
1752         else if (compare(cmd_str, chinese_cmd, FALSE))
1753         {
1754                 ee_chinese = TRUE;
1755 #ifdef NCURSE
1756                 nc_setattrib(A_NC_BIG5);
1757 #endif /* NCURSE */
1758         }
1759         else if (compare(cmd_str, nochinese_cmd, FALSE))
1760         {
1761                 ee_chinese = FALSE;
1762 #ifdef NCURSE
1763                 nc_clearattrib(A_NC_BIG5);
1764 #endif /* NCURSE */
1765         }
1766         else if (compare(cmd_str, QUIT_string, FALSE))
1767                 quit(0);
1768         else if (*cmd_str == '!')
1769         {
1770                 cmd_str++;
1771                 if ((*cmd_str == ' ') || (*cmd_str == 9))
1772                         cmd_str = next_word(cmd_str);
1773                 sh_command(cmd_str);
1774         }
1775         else if ((*cmd_str == '<') && (!in_pipe))
1776         {
1777                 in_pipe = TRUE;
1778                 shell_fork = FALSE;
1779                 cmd_str++;
1780                 if ((*cmd_str == ' ') || (*cmd_str == '\t'))
1781                         cmd_str = next_word(cmd_str);
1782                 command(cmd_str);
1783                 in_pipe = FALSE;
1784                 shell_fork = TRUE;
1785         }
1786         else if ((*cmd_str == '>') && (!out_pipe))
1787         {
1788                 out_pipe = TRUE;
1789                 cmd_str++;
1790                 if ((*cmd_str == ' ') || (*cmd_str == '\t'))
1791                         cmd_str = next_word(cmd_str);
1792                 command(cmd_str);
1793                 out_pipe = FALSE;
1794         }
1795         else
1796         {
1797                 wmove(com_win, 0, 0);
1798                 wclrtoeol(com_win);
1799                 wprintw(com_win, unkn_cmd_str, cmd_str);
1800         }
1801         if (cmd_str2 != NULL)
1802                 free(cmd_str2);
1803 }
1804
1805 int 
1806 scan(char *line, int offset, int column)
1807 /* determine horizontal position for get_string */
1808 {
1809         char *stemp;
1810         int i;
1811         int j;
1812
1813         stemp = line;
1814         i = 0;
1815         j = column;
1816         while (i < offset)
1817         {
1818                 i++;
1819                 j += len_char(*stemp, j);
1820                 stemp++;
1821         }
1822         return(j);
1823 }
1824
1825 /*
1826 prompt: string containing user prompt message
1827 advance: if true, skip leading spaces and tabs
1828 */
1829 char *
1830 get_string(char *prompt, int advance)
1831 /* read string from input on command line */
1832 {
1833         char *string;
1834         char *tmp_string;
1835         char *nam_str;
1836         char *g_point;
1837         int tmp_int;
1838         int g_horz, g_position, g_pos;
1839         int esc_flag;
1840
1841         g_point = tmp_string = malloc(512);
1842         wmove(com_win,0,0);
1843         wclrtoeol(com_win);
1844         waddstr(com_win, prompt);
1845         wrefresh(com_win);
1846         nam_str = tmp_string;
1847         clear_com_win = TRUE;
1848         g_horz = g_position = scan(prompt, strlen(prompt), 0);
1849         g_pos = 0;
1850         do
1851         {
1852                 esc_flag = FALSE;
1853                 in = wgetch(com_win);
1854                 if (in == -1)
1855                         continue;
1856                 if (((in == 8) || (in == 127) || (in == KEY_BACKSPACE)) && (g_pos > 0))
1857                 {
1858                         tmp_int = g_horz;
1859                         g_pos--;
1860                         g_horz = scan(g_point, g_pos, g_position);
1861                         tmp_int = tmp_int - g_horz;
1862                         for (; 0 < tmp_int; tmp_int--)
1863                         {
1864                                 if ((g_horz+tmp_int) < (last_col - 1))
1865                                 {
1866                                         waddch(com_win, '\010');
1867                                         waddch(com_win, ' ');
1868                                         waddch(com_win, '\010');
1869                                 }
1870                         }
1871                         nam_str--;
1872                 }
1873                 else if ((in != 8) && (in != 127) && (in != '\n') && (in != '\r') && (in < 256))
1874                 {
1875                         if (in == '\026')       /* control-v, accept next character verbatim    */
1876                         {                       /* allows entry of ^m, ^j, and ^h       */
1877                                 esc_flag = TRUE;
1878                                 in = wgetch(com_win);
1879                                 if (in == -1)
1880                                         continue;
1881                         }
1882                         *nam_str = in;
1883                         g_pos++;
1884                         if (((in < ' ') || (in > 126)) && (g_horz < (last_col - 1)))
1885                                 g_horz += out_char(com_win, in, g_horz);
1886                         else
1887                         {
1888                                 g_horz++;
1889                                 if (g_horz < (last_col - 1))
1890                                         waddch(com_win, in);
1891                         }
1892                         nam_str++;
1893                 }
1894                 wrefresh(com_win);
1895                 if (esc_flag)
1896                         in = 0;
1897         } while ((in != '\n') && (in != '\r'));
1898         *nam_str = 0;
1899         nam_str = tmp_string;
1900         if (((*nam_str == ' ') || (*nam_str == 9)) && (advance))
1901                 nam_str = next_word(nam_str);
1902         string = malloc(strlen(nam_str) + 1);
1903         strcpy(string, nam_str);
1904         free(tmp_string);
1905         wrefresh(com_win);
1906         return(string);
1907 }
1908
1909 int 
1910 compare(char *string1, char *string2, int sensitive) /* compare two strings */
1911 {
1912         char *strng1;
1913         char *strng2;
1914         int tmp;
1915         int equal;
1916
1917         strng1 = string1;
1918         strng2 = string2;
1919         tmp = 0;
1920         if ((strng1 == NULL) || (strng2 == NULL) || (*strng1 == 0) || (*strng2 == 0))
1921                 return(FALSE);
1922         equal = TRUE;
1923         while (equal)
1924         {
1925                 if (sensitive)
1926                 {
1927                         if (*strng1 != *strng2)
1928                                 equal = FALSE;
1929                 }
1930                 else
1931                 {
1932                         if (toupper(*strng1) != toupper(*strng2))
1933                                 equal = FALSE;
1934                 }
1935                 strng1++;
1936                 strng2++;
1937                 if ((*strng1 == 0) || (*strng2 == 0) || (*strng1 == ' ') || (*strng2 == ' '))
1938                         break;
1939                 tmp++;
1940         }
1941         return(equal);
1942 }
1943
1944 void 
1945 goto_line(char *cmd_str)
1946 {
1947         int number;
1948         int i;
1949         char *ptr;
1950         char *direction = NULL;
1951         struct text *t_line;
1952
1953         ptr = cmd_str;
1954         i= 0;
1955         while ((*ptr >='0') && (*ptr <= '9'))
1956         {
1957                 i= i * 10 + (*ptr - '0');
1958                 ptr++;
1959         }
1960         number = i;
1961         i = 0;
1962         t_line = curr_line;
1963         while ((t_line->line_number > number) && (t_line->prev_line != NULL))
1964         {
1965                 i++;
1966                 t_line = t_line->prev_line;
1967                 direction = "u";
1968         }
1969         while ((t_line->line_number < number) && (t_line->next_line != NULL))
1970         {
1971                 i++;
1972                 direction = "d";
1973                 t_line = t_line->next_line;
1974         }
1975         if ((i < 30) && (i > 0))
1976         {
1977                 move_rel(direction, i);
1978         }
1979         else
1980         {
1981                 curr_line = t_line;
1982                 point = curr_line->line;
1983                 position = 1;
1984                 midscreen((last_line / 2), point);
1985                 scr_pos = scr_horz;
1986         }
1987         wmove(com_win, 0, 0);
1988         wclrtoeol(com_win);
1989         wprintw(com_win, line_num_str, curr_line->line_number);
1990         wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1991 }
1992
1993 void 
1994 midscreen(int line, unsigned char *pnt)
1995 /* put current line in middle of screen */
1996 {
1997         struct text *mid_line;
1998         int i;
1999
2000         line = min(line, last_line);
2001         mid_line = curr_line;
2002         for (i = 0; ((i < line) && (curr_line->prev_line != NULL)); i++)
2003                 curr_line = curr_line->prev_line;
2004         scr_vert = scr_horz = 0;
2005         wmove(text_win, 0, 0);
2006         draw_screen();
2007         scr_vert = i;
2008         curr_line = mid_line;
2009         scanline(pnt);
2010         wmove(text_win, scr_vert, (scr_horz - horiz_offset));
2011 }
2012
2013 void 
2014 get_options(int numargs, char **arguments)
2015 /* get arguments from command line */
2016 {
2017         char *buff;
2018         int count;
2019         struct files *temp_names = NULL;
2020         char *name;
2021         char *ptr;
2022
2023         /*
2024          |      see if editor was invoked as 'ree' (restricted mode)
2025          */
2026
2027         if (!(name = strrchr(arguments[0], '/')))
2028                 name = arguments[0];
2029         else
2030                 name++;
2031         if (!strcmp(name, "ree"))
2032                 restricted = TRUE;
2033
2034         top_of_stack = NULL;
2035         input_file = FALSE;
2036         recv_file = FALSE;
2037         count = 1;
2038         while (count < numargs)
2039         {
2040                 buff = arguments[count];
2041                 if (!strcmp("-i", buff))
2042                 {
2043                         info_window = FALSE;
2044                 }
2045                 else if (!strcmp("-e", buff))
2046                 {
2047                         expand_tabs = FALSE;
2048                 }
2049                 else if (!strcmp("-h", buff))
2050                 {
2051                         nohighlight = TRUE;
2052                 }
2053                 else if (!strcmp("-?", buff))
2054                 {
2055                         fprintf(stderr, usage0, arguments[0]);
2056                         fprintf(stderr, usage1);
2057                         fprintf(stderr, usage2);
2058                         fprintf(stderr, usage3);
2059                         fprintf(stderr, usage4);
2060                         exit(1);
2061                 }
2062                 else if (*buff == '+')
2063                 {
2064                         buff++;
2065                         start_at_line = buff;
2066                 }
2067
2068                 else
2069                 {
2070                         if (top_of_stack == NULL)
2071                         {
2072                                 temp_names = top_of_stack = name_alloc();
2073                         }
2074                         else
2075                         {
2076                                 temp_names->next_name = name_alloc();
2077                                 temp_names = temp_names->next_name;
2078                         }
2079                         ptr = temp_names->name = malloc(strlen(buff) + 1);
2080                         while (*buff != 0)
2081                         {
2082                                 *ptr = *buff;
2083                                 buff++;
2084                                 ptr++;
2085                         }
2086                         *ptr = 0;
2087                         temp_names->next_name = NULL;
2088                         input_file = TRUE;
2089                         recv_file = TRUE;
2090                 }
2091                 count++;
2092         }
2093 }
2094
2095 void 
2096 check_fp(void)          /* open or close files according to flags */
2097 {
2098         int line_num;
2099         int temp;
2100         struct stat buf;
2101
2102         clear_com_win = TRUE;
2103         tmp_vert = scr_vert;
2104         tmp_horz = scr_horz;
2105         tmp_line = curr_line;
2106         if (input_file)
2107         {
2108                 in_file_name = tmp_file = top_of_stack->name;
2109                 top_of_stack = top_of_stack->next_name;
2110         }
2111         temp = stat(tmp_file, &buf);
2112         buf.st_mode &= ~07777;
2113         if ((temp != -1) && (buf.st_mode != 0100000) && (buf.st_mode != 0))
2114         {
2115                 wprintw(com_win, file_is_dir_msg, tmp_file);
2116                 wrefresh(com_win);
2117                 if (input_file)
2118                 {
2119                         quit(0);
2120                         return;
2121                 }
2122                 else
2123                         return;
2124         }
2125         if ((get_fd = open(tmp_file, O_RDONLY)) == -1)
2126         {
2127                 wmove(com_win, 0, 0);
2128                 wclrtoeol(com_win);
2129                 if (input_file)
2130                         wprintw(com_win, new_file_msg, tmp_file);
2131                 else
2132                         wprintw(com_win, cant_open_msg, tmp_file);
2133                 wrefresh(com_win);
2134                 wmove(text_win, scr_vert, (scr_horz - horiz_offset));
2135                 wrefresh(text_win);
2136                 recv_file = FALSE;
2137                 input_file = FALSE;
2138                 return;
2139         }
2140         else
2141                 get_file(tmp_file);
2142
2143         recv_file = FALSE;
2144         line_num = curr_line->line_number;
2145         scr_vert = tmp_vert;
2146         scr_horz = tmp_horz;
2147         if (input_file)
2148                 curr_line= first_line;
2149         else
2150                 curr_line = tmp_line;
2151         point = curr_line->line;
2152         draw_screen();
2153         if (input_file)
2154         {
2155                 input_file = FALSE;
2156                 if (start_at_line != NULL)
2157                 {
2158                         line_num = atoi(start_at_line) - 1;
2159                         move_rel("d", line_num);
2160                         line_num = 0;
2161                         start_at_line = NULL;
2162                 }
2163         }
2164         else
2165         {
2166                 wmove(com_win, 0, 0);
2167                 wclrtoeol(com_win);
2168                 text_changes = TRUE;
2169                 if ((tmp_file != NULL) && (*tmp_file != 0))
2170                         wprintw(com_win, file_read_fin_msg, tmp_file);
2171         }
2172         wrefresh(com_win);
2173         wmove(text_win, scr_vert, (scr_horz - horiz_offset));
2174         wrefresh(text_win);
2175 }
2176
2177 void 
2178 get_file(char *file_name) /* read specified file into current buffer */
2179 {
2180         int can_read;           /* file has at least one character      */
2181         int length;             /* length of line read by read          */
2182         int append;             /* should text be appended to current line */
2183         struct text *temp_line;
2184         char ro_flag = FALSE;
2185
2186         if (recv_file)          /* if reading a file                    */
2187         {
2188                 wmove(com_win, 0, 0);
2189                 wclrtoeol(com_win);
2190                 wprintw(com_win, reading_file_msg, file_name);
2191                 if (access(file_name, 2))       /* check permission to write */
2192                 {
2193                         if ((errno == ENOTDIR) || (errno == EACCES) || (errno == EROFS) || (errno == ETXTBSY) || (errno == EFAULT))
2194                         {
2195                                 wprintw(com_win, read_only_msg);
2196                                 ro_flag = TRUE;
2197                         }
2198                 }
2199                 wrefresh(com_win);
2200         }
2201         if (curr_line->line_length > 1) /* if current line is not blank */
2202         {
2203                 insert_line(FALSE);
2204                 left(FALSE);
2205                 append = FALSE;
2206         }
2207         else
2208                 append = TRUE;
2209         can_read = FALSE;               /* test if file has any characters  */
2210         while (((length = read(get_fd, in_string, 512)) != 0) && (length != -1))
2211         {
2212                 can_read = TRUE;  /* if set file has at least 1 character   */
2213                 get_line(length, in_string, &append);
2214         }
2215         if ((can_read) && (curr_line->line_length == 1))
2216         {
2217                 temp_line = curr_line->prev_line;
2218                 temp_line->next_line = curr_line->next_line;
2219                 if (temp_line->next_line != NULL)
2220                         temp_line->next_line->prev_line = temp_line;
2221                 if (curr_line->line != NULL)
2222                         free(curr_line->line);
2223                 free(curr_line);
2224                 curr_line = temp_line;
2225         }
2226         if (input_file) /* if this is the file to be edited display number of lines     */
2227         {
2228                 wmove(com_win, 0, 0);
2229                 wclrtoeol(com_win);
2230                 wprintw(com_win, file_read_lines_msg, in_file_name, curr_line->line_number);
2231                 if (ro_flag)
2232                         wprintw(com_win, read_only_msg);
2233                 wrefresh(com_win);
2234         }
2235         else if (can_read)      /* not input_file and file is non-zero size */
2236                 text_changes = TRUE;
2237
2238         if (recv_file)          /* if reading a file                    */
2239         {
2240                 in = EOF;
2241         }
2242 }
2243
2244 /*
2245 length: length of string read by read
2246 in_string: string read by read
2247 append: TRUE if must append more text to end of current line
2248 */
2249 void
2250 get_line(int length, unsigned char *in_string, int *append)
2251 /* read string and split into lines */
2252 {
2253         unsigned char *str1;
2254         unsigned char *str2;
2255         int num;                /* offset from start of string          */
2256         int char_count;         /* length of new line (or added portion */
2257         int temp_counter;       /* temporary counter value              */
2258         struct text *tline;     /* temporary pointer to new line        */
2259         int first_time;         /* if TRUE, the first time through the loop */
2260
2261         str2 = in_string;
2262         num = 0;
2263         first_time = TRUE;
2264         while (num < length)
2265         {
2266                 if (!first_time)
2267                 {
2268                         if (num < length)
2269                         {
2270                                 str2++;
2271                                 num++;
2272                         }
2273                 }
2274                 else
2275                         first_time = FALSE;
2276                 str1 = str2;
2277                 char_count = 1;
2278                 /* find end of line     */
2279                 while ((*str2 != '\n') && (num < length))
2280                 {
2281                         str2++;
2282                         num++;
2283                         char_count++;
2284                 }
2285                 if (!(*append)) /* if not append to current line, insert new one */
2286                 {
2287                         tline = txtalloc();     /* allocate data structure for next line */
2288                         tline->next_line = curr_line->next_line;
2289                         renumber_lines(tline, curr_line->line_number + 1);
2290                         tline->prev_line = curr_line;
2291                         curr_line->next_line = tline;
2292                         if (tline->next_line != NULL)
2293                                 tline->next_line->prev_line = tline;
2294                         curr_line = tline;
2295                         curr_line->line = point = (unsigned char *) malloc(char_count);
2296                         curr_line->line_length = char_count;
2297                         curr_line->max_length = char_count;
2298                 }
2299                 else
2300                 {
2301                         point = resiz_line(char_count, curr_line, curr_line->line_length); 
2302                         curr_line->line_length += (char_count - 1);
2303                 }
2304                 for (temp_counter = 1; temp_counter < char_count; temp_counter++)
2305                 {
2306                         *point = *str1;
2307                         point++;
2308                         str1++;
2309                 }
2310                 *point = 0;
2311                 *append = FALSE;
2312                 if ((num == length) && (*str2 != '\n'))
2313                         *append = TRUE;
2314         }
2315 }
2316
2317 void 
2318 draw_screen(void)               /* redraw the screen from current postion       */
2319 {
2320         struct text *temp_line;
2321         unsigned char *line_out;
2322         int temp_vert;
2323
2324         temp_line = curr_line;
2325         temp_vert = scr_vert;
2326         wclrtobot(text_win);
2327         while ((temp_line != NULL) && (temp_vert <= last_line))
2328         {
2329                 line_out = temp_line->line;
2330                 draw_line(temp_vert, 0, line_out, 1, temp_line->line_length);
2331                 temp_vert++;
2332                 temp_line = temp_line->next_line;
2333         }
2334         wmove(text_win, temp_vert, 0);
2335         wmove(text_win, scr_vert, (scr_horz - horiz_offset));
2336 }
2337
2338 void 
2339 finish(void)    /* prepare to exit edit session */
2340 {
2341         char *file_name = in_file_name;
2342
2343         /*
2344          |      changes made here should be reflected in the 'save' 
2345          |      portion of file_op()
2346          */
2347
2348         if ((file_name == NULL) || (*file_name == 0))
2349                 file_name = get_string(save_file_name_prompt, TRUE);
2350
2351         if ((file_name == NULL) || (*file_name == 0))
2352         {
2353                 wmove(com_win, 0, 0);
2354                 wprintw(com_win, file_not_saved_msg);
2355                 wclrtoeol(com_win);
2356                 wrefresh(com_win);
2357                 clear_com_win = TRUE;
2358                 return;
2359         }
2360
2361         tmp_file = resolve_name(file_name);
2362         if (tmp_file != file_name)
2363         {
2364                 free(file_name);
2365                 file_name = tmp_file;
2366         }
2367
2368         if (write_file(file_name, 1))
2369         {
2370                 text_changes = FALSE;
2371                 quit(0);
2372         }
2373 }
2374
2375 int 
2376 quit(int noverify)              /* exit editor                  */
2377 {
2378         char *ans;
2379
2380         touchwin(text_win);
2381         wrefresh(text_win);
2382         if ((text_changes) && (!noverify))
2383         {
2384                 ans = get_string(changes_made_prompt, TRUE);
2385                 if (toupper(*ans) == toupper(*yes_char))
2386                         text_changes = FALSE;
2387                 else
2388                         return(0);
2389                 free(ans);
2390         }
2391         if (top_of_stack == NULL)
2392         {
2393                 if (info_window)
2394                         wrefresh(info_win);
2395                 wrefresh(com_win);
2396                 resetty();
2397                 endwin();
2398                 putchar('\n');
2399                 exit(0);
2400         }
2401         else
2402         {
2403                 delete_text();
2404                 recv_file = TRUE;
2405                 input_file = TRUE;
2406                 check_fp();
2407                 text_changes = FALSE;
2408         }
2409         return(0);
2410 }
2411
2412 void 
2413 edit_abort(int arg)
2414 {
2415         wrefresh(com_win);
2416         resetty();
2417         endwin();
2418         putchar('\n');
2419         exit(1);
2420 }
2421
2422 void 
2423 delete_text(void)
2424 {
2425         while (curr_line->next_line != NULL)
2426                 curr_line = curr_line->next_line;
2427         while (curr_line != first_line)
2428         {
2429                 free(curr_line->line);
2430                 curr_line = curr_line->prev_line;
2431                 free(curr_line->next_line);
2432         }
2433         curr_line->next_line = NULL;
2434         *curr_line->line = 0;
2435         curr_line->line_length = 1;
2436         curr_line->line_number = 1;
2437         point = curr_line->line;
2438         scr_pos = scr_vert = scr_horz = 0;
2439         position = 1;
2440 }
2441
2442 int 
2443 write_file(char *file_name, int warn_if_exists)
2444 {
2445         char cr;
2446         char *tmp_point;
2447         struct text *out_line;
2448         int lines, charac;
2449         int temp_pos;
2450         int write_flag = TRUE;
2451
2452         charac = lines = 0;
2453         if (warn_if_exists &&
2454             ((in_file_name == NULL) || strcmp(in_file_name, file_name)))
2455         {
2456                 if ((temp_fp = fopen(file_name, "r")))
2457                 {
2458                         tmp_point = get_string(file_exists_prompt, TRUE);
2459                         if (toupper(*tmp_point) == toupper(*yes_char))
2460                                 write_flag = TRUE;
2461                         else 
2462                                 write_flag = FALSE;
2463                         fclose(temp_fp);
2464                         free(tmp_point);
2465                 }
2466         }
2467
2468         clear_com_win = TRUE;
2469
2470         if (write_flag)
2471         {
2472                 if ((temp_fp = fopen(file_name, "w")) == NULL)
2473                 {
2474                         clear_com_win = TRUE;
2475                         wmove(com_win,0,0);
2476                         wclrtoeol(com_win);
2477                         wprintw(com_win, create_file_fail_msg, file_name);
2478                         wrefresh(com_win);
2479                         return(FALSE);
2480                 }
2481                 else
2482                 {
2483                         wmove(com_win,0,0);
2484                         wclrtoeol(com_win);
2485                         wprintw(com_win, writing_file_msg, file_name);
2486                         wrefresh(com_win);
2487                         cr = '\n';
2488                         out_line = first_line;
2489                         while (out_line != NULL)
2490                         {
2491                                 temp_pos = 1;
2492                                 tmp_point= out_line->line;
2493                                 while (temp_pos < out_line->line_length)
2494                                 {
2495                                         putc(*tmp_point, temp_fp);
2496                                         tmp_point++;
2497                                         temp_pos++;
2498                                 }
2499                                 charac += out_line->line_length;
2500                                 out_line = out_line->next_line;
2501                                 putc(cr, temp_fp);
2502                                 lines++;
2503                         }
2504                         fclose(temp_fp);
2505                         wmove(com_win,0,0);
2506                         wclrtoeol(com_win);
2507                         wprintw(com_win, file_written_msg, file_name, lines, charac);
2508                         wrefresh(com_win);
2509                         return(TRUE);
2510                 }
2511         }
2512         else
2513                 return(FALSE);
2514 }
2515
2516 int 
2517 search(int display_message) /* search for string in srch_str */
2518 {
2519         int lines_moved;
2520         int iter;
2521         int found;
2522
2523         if ((srch_str == NULL) || (*srch_str == 0))
2524                 return(FALSE);
2525         if (display_message)
2526         {
2527                 wmove(com_win, 0, 0);
2528                 wclrtoeol(com_win);
2529                 wprintw(com_win, searching_msg);
2530                 wrefresh(com_win);
2531                 clear_com_win = TRUE;
2532         }
2533         lines_moved = 0;
2534         found = FALSE;
2535         srch_line = curr_line;
2536         srch_1 = point;
2537         if (position < curr_line->line_length)
2538                 srch_1++;
2539         iter = position + 1;
2540         while ((!found) && (srch_line != NULL))
2541         {
2542                 while ((iter < srch_line->line_length) && (!found))
2543                 {
2544                         srch_2 = srch_1;
2545                         if (case_sen)   /* if case sensitive            */
2546                         {
2547                                 srch_3 = srch_str;
2548                         while ((*srch_2 == *srch_3) && (*srch_3 != 0))
2549                                 {
2550                                         found = TRUE;
2551                                         srch_2++;
2552                                         srch_3++;
2553                                 }       /* end while    */
2554                         }
2555                         else            /* if not case sensitive        */
2556                         {
2557                                 srch_3 = u_srch_str;
2558                         while ((toupper(*srch_2) == *srch_3) && (*srch_3 != 0))
2559                                 {
2560                                         found = TRUE;
2561                                         srch_2++;
2562                                         srch_3++;
2563                                 }
2564                         }       /* end else     */
2565                         if (!((*srch_3 == 0) && (found)))
2566                         {
2567                                 found = FALSE;
2568                                 if (iter < srch_line->line_length)
2569                                         srch_1++;
2570                                 iter++;
2571                         }
2572                 }
2573                 if (!found)
2574                 {
2575                         srch_line = srch_line->next_line;
2576                         if (srch_line != NULL)
2577                                 srch_1 = srch_line->line;
2578                         iter = 1;
2579                         lines_moved++;
2580                 }
2581         }
2582         if (found)
2583         {
2584                 if (display_message)
2585                 {
2586                         wmove(com_win, 0, 0);
2587                         wclrtoeol(com_win);
2588                         wrefresh(com_win);
2589                 }
2590                 if (lines_moved == 0)
2591                 {
2592                         while (position < iter)
2593                                 right(TRUE);
2594                 }
2595                 else
2596                 {
2597                         if (lines_moved < 30)
2598                         {
2599                                 move_rel("d", lines_moved);
2600                                 while (position < iter)
2601                                         right(TRUE);
2602                         }
2603                         else 
2604                         {
2605                                 curr_line = srch_line;
2606                                 point = srch_1;
2607                                 position = iter;
2608                                 scanline(point);
2609                                 scr_pos = scr_horz;
2610                                 midscreen((last_line / 2), point);
2611                         }
2612                 }
2613         }
2614         else
2615         {
2616                 if (display_message)
2617                 {
2618                         wmove(com_win, 0, 0);
2619                         wclrtoeol(com_win);
2620                         wprintw(com_win, str_not_found_msg, srch_str);
2621                         wrefresh(com_win);
2622                 }
2623                 wmove(text_win, scr_vert,(scr_horz - horiz_offset));
2624         }
2625         return(found);
2626 }
2627
2628 void 
2629 search_prompt(void) /* prompt and read search string (srch_str) */
2630 {
2631         if (srch_str != NULL)
2632                 free(srch_str);
2633         if ((u_srch_str != NULL) && (*u_srch_str != 0))
2634                 free(u_srch_str);
2635         srch_str = get_string(search_prompt_str, FALSE);
2636         gold = FALSE;
2637         srch_3 = srch_str;
2638         srch_1 = u_srch_str = malloc(strlen(srch_str) + 1);
2639         while (*srch_3 != 0)
2640         {
2641                 *srch_1 = toupper(*srch_3);
2642                 srch_1++;
2643                 srch_3++;
2644         }
2645         *srch_1 = 0;
2646         search(TRUE);
2647 }
2648
2649 void 
2650 del_char(void) /* delete current character */
2651 {
2652         in = 8;  /* backspace */
2653         if (position < curr_line->line_length)  /* if not end of line   */
2654         {
2655                 if ((ee_chinese) && (*point > 127) && 
2656                     ((curr_line->line_length - position) >= 2))
2657                 {
2658                         point++;
2659                         position++;
2660                 }
2661                 position++;
2662                 point++;
2663                 scanline(point);
2664                 delete(TRUE);
2665         }
2666         else
2667         {
2668                 right(FALSE);
2669                 delete(FALSE);
2670         }
2671 }
2672
2673 void 
2674 undel_char(void) /* undelete last deleted character */
2675 {
2676         if (d_char[0] == '\n')  /* insert line if last del_char deleted eol */
2677                 insert_line(TRUE);
2678         else
2679         {
2680                 in = d_char[0];
2681                 insert(in);
2682                 if (d_char[1] != 0)
2683                 {
2684                         in = d_char[1];
2685                         insert(in);
2686                 }
2687         }
2688 }
2689
2690 void 
2691 del_word(void) /* delete word in front of cursor */
2692 {
2693         int tposit;
2694         int difference;
2695         unsigned char *d_word2;
2696         unsigned char *d_word3;
2697         unsigned char tmp_char[3];
2698
2699         if (d_word != NULL)
2700                 free(d_word);
2701         d_word = malloc(curr_line->line_length);
2702         tmp_char[0] = d_char[0];
2703         tmp_char[1] = d_char[1];
2704         tmp_char[2] = d_char[2];
2705         d_word3 = point;
2706         d_word2 = d_word;
2707         tposit = position;
2708         while ((tposit < curr_line->line_length) && 
2709                                 ((*d_word3 != ' ') && (*d_word3 != '\t')))
2710         {
2711                 tposit++;
2712                 *d_word2 = *d_word3;
2713                 d_word2++;
2714                 d_word3++;
2715         }
2716         while ((tposit < curr_line->line_length) && 
2717                                 ((*d_word3 == ' ') || (*d_word3 == '\t')))
2718         {
2719                 tposit++;
2720                 *d_word2 = *d_word3;
2721                 d_word2++;
2722                 d_word3++;
2723         }
2724         *d_word2 = 0;
2725         d_wrd_len = difference = d_word2 - d_word;
2726         d_word2 = point;
2727         while (tposit < curr_line->line_length)
2728         {
2729                 tposit++;
2730                 *d_word2 = *d_word3;
2731                 d_word2++;
2732                 d_word3++;
2733         }
2734         curr_line->line_length -= difference;
2735         *d_word2 = 0;
2736         draw_line(scr_vert, scr_horz,point,position,curr_line->line_length);
2737         d_char[0] = tmp_char[0];
2738         d_char[1] = tmp_char[1];
2739         d_char[2] = tmp_char[2];
2740         text_changes = TRUE;
2741         formatted = FALSE;
2742 }
2743
2744 void 
2745 undel_word(void) /* undelete last deleted word */
2746 {
2747         int temp;
2748         int tposit;
2749         unsigned char *tmp_old_ptr;
2750         unsigned char *tmp_space;
2751         unsigned char *tmp_ptr;
2752         unsigned char *d_word_ptr;
2753
2754         /*
2755          |      resize line to handle undeleted word
2756          */
2757         if ((curr_line->max_length - (curr_line->line_length + d_wrd_len)) < 5)
2758                 point = resiz_line(d_wrd_len, curr_line, position);
2759         tmp_ptr = tmp_space = malloc(curr_line->line_length + d_wrd_len);
2760         d_word_ptr = d_word;
2761         temp = 1;
2762         /*
2763          |      copy d_word contents into temp space
2764          */
2765         while (temp <= d_wrd_len)
2766         {
2767                 temp++;
2768                 *tmp_ptr = *d_word_ptr;
2769                 tmp_ptr++;
2770                 d_word_ptr++;
2771         }
2772         tmp_old_ptr = point;
2773         tposit = position;
2774         /*
2775          |      copy contents of line from curent position to eol into 
2776          |      temp space
2777          */
2778         while (tposit < curr_line->line_length)
2779         {
2780                 temp++;
2781                 tposit++;
2782                 *tmp_ptr = *tmp_old_ptr;
2783                 tmp_ptr++;
2784                 tmp_old_ptr++;
2785         }
2786         curr_line->line_length += d_wrd_len;
2787         tmp_old_ptr = point;
2788         *tmp_ptr = 0;
2789         tmp_ptr = tmp_space;
2790         tposit = 1;
2791         /*
2792          |      now copy contents from temp space back to original line
2793          */
2794         while (tposit < temp)
2795         {
2796                 tposit++;
2797                 *tmp_old_ptr = *tmp_ptr;
2798                 tmp_ptr++;
2799                 tmp_old_ptr++;
2800         }
2801         *tmp_old_ptr = 0;
2802         free(tmp_space);
2803         draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
2804 }
2805
2806 void 
2807 del_line(void) /* delete from cursor to end of line */
2808 {
2809         unsigned char *dl1;
2810         unsigned char *dl2;
2811         int tposit;
2812
2813         if (d_line != NULL)
2814                 free(d_line);
2815         d_line = malloc(curr_line->line_length);
2816         dl1 = d_line;
2817         dl2 = point;
2818         tposit = position;
2819         while (tposit < curr_line->line_length)
2820         {
2821                 *dl1 = *dl2;
2822                 dl1++;
2823                 dl2++;
2824                 tposit++;
2825         }
2826         dlt_line->line_length = 1 + tposit - position;
2827         *dl1 = 0;
2828         *point = 0;
2829         curr_line->line_length = position;
2830         wclrtoeol(text_win);
2831         if (curr_line->next_line != NULL)
2832         {
2833                 right(FALSE);
2834                 delete(FALSE);
2835         }
2836         text_changes = TRUE;
2837 }
2838
2839 void 
2840 undel_line(void) /* undelete last deleted line */
2841 {
2842         unsigned char *ud1;
2843         unsigned char *ud2;
2844         int tposit;
2845
2846         if (dlt_line->line_length == 0)
2847                 return;
2848
2849         insert_line(TRUE);
2850         left(TRUE);
2851         point = resiz_line(dlt_line->line_length, curr_line, position);
2852         curr_line->line_length += dlt_line->line_length - 1;
2853         ud1 = point;
2854         ud2 = d_line;
2855         tposit = 1;
2856         while (tposit < dlt_line->line_length)
2857         {
2858                 tposit++;
2859                 *ud1 = *ud2;
2860                 ud1++;
2861                 ud2++;
2862         }
2863         *ud1 = 0;
2864         draw_line(scr_vert, scr_horz,point,position,curr_line->line_length);
2865 }
2866
2867 void 
2868 adv_word(void) /* advance to next word */
2869 {
2870 while ((position < curr_line->line_length) && ((*point != 32) && (*point != 9)))
2871                 right(TRUE);
2872 while ((position < curr_line->line_length) && ((*point == 32) || (*point == 9)))
2873                 right(TRUE);
2874 }
2875
2876 void 
2877 move_rel(char *direction, int lines)    /* move relative to current line        */
2878 {
2879         int i;
2880         char *tmp;
2881
2882         if (*direction == 'u')
2883         {
2884                 scr_pos = 0;
2885                 while (position > 1)
2886                         left(TRUE);
2887                 for (i = 0; i < lines; i++)
2888                 {
2889                         up();
2890                 }
2891                 if ((last_line > 5) && ( scr_vert < 4))
2892                 {
2893                         tmp = point;
2894                         tmp_line = curr_line;
2895                         for (i= 0;(i<5)&&(curr_line->prev_line != NULL); i++)
2896                         {
2897                                 up();
2898                         }
2899                         scr_vert = scr_vert + i;
2900                         curr_line = tmp_line;
2901                         point = tmp;
2902                         scanline(point);
2903                 }
2904         }
2905         else
2906         {
2907                 if ((position != 1) && (curr_line->next_line != NULL))
2908                 {
2909                         nextline();
2910                         scr_pos = scr_horz = 0;
2911                         if (horiz_offset)
2912                         {
2913                                 horiz_offset = 0;
2914                                 midscreen(scr_vert, point);
2915                         }
2916                 }
2917                 else
2918                         adv_line();
2919                 for (i = 1; i < lines; i++)
2920                 {
2921                         down();
2922                 }
2923                 if ((last_line > 10) && (scr_vert > (last_line - 5)))
2924                 {
2925                         tmp = point;
2926                         tmp_line = curr_line;
2927                         for (i=0; (i<5) && (curr_line->next_line != NULL); i++)
2928                         {
2929                                 down();
2930                         }
2931                         scr_vert = scr_vert - i;
2932                         curr_line = tmp_line;
2933                         point = tmp;
2934                         scanline(point);
2935                 }
2936         }
2937         wmove(text_win, scr_vert, (scr_horz - horiz_offset));
2938 }
2939
2940 void 
2941 eol(void)                               /* go to end of line                    */
2942 {
2943         if (position < curr_line->line_length)
2944         {
2945                 while (position < curr_line->line_length)
2946                         right(TRUE);
2947         }
2948         else if (curr_line->next_line != NULL)
2949         {
2950                 right(TRUE);
2951                 while (position < curr_line->line_length)
2952                         right(TRUE);
2953         }
2954 }
2955
2956 void 
2957 bol(void)                               /* move to beginning of line    */
2958 {
2959         if (point != curr_line->line)
2960         {
2961                 while (point != curr_line->line)
2962                         left(TRUE);
2963         }
2964         else if (curr_line->prev_line != NULL)
2965         {
2966                 scr_pos = 0;
2967                 up();
2968         }
2969 }
2970
2971 void 
2972 adv_line(void)  /* advance to beginning of next line    */
2973 {
2974         if ((point != curr_line->line) || (scr_pos > 0))
2975         {
2976                 while (position < curr_line->line_length)
2977                         right(TRUE);
2978                 right(TRUE);
2979         }
2980         else if (curr_line->next_line != NULL)
2981         {
2982                 scr_pos = 0;
2983                 down();
2984         }
2985 }
2986
2987 /* string: string containing user command */
2988 void 
2989 sh_command(char *string)        /* execute shell command                        */
2990 {
2991         char *temp_point;
2992         char *last_slash;
2993         char *path;             /* directory path to executable         */
2994         int parent;             /* zero if child, child's pid if parent */
2995         int value;
2996         int return_val;
2997         struct text *line_holder;
2998
2999         if (restrict_mode())
3000         {
3001                 return;
3002         }
3003
3004         if (!(path = getenv("SHELL")))
3005                 path = "/bin/sh";
3006         last_slash = temp_point = path;
3007         while (*temp_point != 0)
3008         {
3009                 if (*temp_point == '/')
3010                         last_slash = ++temp_point;
3011                 else
3012                         temp_point++;
3013         }
3014
3015         /*
3016          |      if in_pipe is true, then output of the shell operation will be 
3017          |      read by the editor, and curses doesn't need to be turned off
3018          */
3019
3020         if (!in_pipe)
3021         {
3022                 keypad(com_win, FALSE);
3023                 keypad(text_win, FALSE);
3024                 echo();
3025                 nl();
3026                 noraw();
3027                 resetty();
3028
3029 #ifndef NCURSE
3030                 endwin();
3031 #endif
3032         }
3033
3034         if (in_pipe)
3035         {
3036                 pipe(pipe_in);          /* create a pipe        */
3037                 parent = fork();
3038                 if (!parent)            /* if the child         */
3039                 {
3040 /*
3041  |  child process which will fork and exec shell command (if shell output is
3042  |  to be read by editor)
3043  */
3044                         in_pipe = FALSE;
3045 /*
3046  |  redirect stdout to pipe
3047  */
3048                         temp_stdout = dup(1);
3049                         close(1);
3050                         dup(pipe_in[1]);
3051 /*
3052  |  redirect stderr to pipe
3053  */
3054                         temp_stderr = dup(2);
3055                         close(2);
3056                         dup(pipe_in[1]);
3057                         close(pipe_in[1]);
3058                         /*
3059                          |      child will now continue down 'if (!in_pipe)' 
3060                          |      path below
3061                          */
3062                 }
3063                 else  /* if the parent  */
3064                 {
3065 /*
3066  |  prepare editor to read from the pipe
3067  */
3068                         signal(SIGCHLD, SIG_IGN);
3069                         line_holder = curr_line;
3070                         tmp_vert = scr_vert;
3071                         close(pipe_in[1]);
3072                         get_fd = pipe_in[0];
3073                         get_file("");
3074                         close(pipe_in[0]);
3075                         scr_vert = tmp_vert;
3076                         scr_horz = scr_pos = 0;
3077                         position = 1;
3078                         curr_line = line_holder;
3079                         point = curr_line->line;
3080                         out_pipe = FALSE;
3081                         signal(SIGCHLD, SIG_DFL);
3082 /*
3083  |  since flag "in_pipe" is still TRUE, the path which waits for the child 
3084  |  process to die will be avoided.
3085  |  (the pipe is closed, no more output can be expected)
3086  */
3087                 }
3088         }
3089         if (!in_pipe)
3090         {
3091                 signal(SIGINT, SIG_IGN);
3092                 if (out_pipe)
3093                 {
3094                         pipe(pipe_out);
3095                 }
3096 /*
3097  |  fork process which will exec command
3098  */
3099                 parent = fork();   
3100                 if (!parent)            /* if the child */
3101                 {
3102                         if (shell_fork)
3103                                 putchar('\n');
3104                         if (out_pipe)
3105                         {
3106 /*
3107  |  prepare the child process (soon to exec a shell command) to read from the 
3108  |  pipe (which will be output from the editor's buffer)
3109  */
3110                                 close(0);
3111                                 dup(pipe_out[0]);
3112                                 close(pipe_out[0]);
3113                                 close(pipe_out[1]);
3114                         }
3115                         for (value = 1; value < 24; value++)
3116                                 signal(value, SIG_DFL);
3117                         execl(path, last_slash, "-c", string, NULL);
3118                         errx(1, exec_err_msg, path);
3119                 }
3120                 else    /* if the parent        */
3121                 {
3122                         if (out_pipe)
3123                         {
3124 /*
3125  |  output the contents of the buffer to the pipe (to be read by the 
3126  |  process forked and exec'd above as stdin)
3127  */
3128                                 close(pipe_out[0]);
3129                                 line_holder = first_line;
3130                                 while (line_holder != NULL)
3131                                 {
3132                                         write(pipe_out[1], line_holder->line, (line_holder->line_length-1));
3133                                         write(pipe_out[1], "\n", 1);
3134                                         line_holder = line_holder->next_line;
3135                                 }
3136                                 close(pipe_out[1]);
3137                                 out_pipe = FALSE;
3138                         }
3139                         do
3140                         {
3141                                 return_val = wait(NULL);
3142                         }
3143                         while ((return_val != parent) && (return_val != -1));
3144 /*
3145  |  if this process is actually the child of the editor, exit.  Here's how it 
3146  |  works:
3147  |  The editor forks a process.  If output must be sent to the command to be 
3148  |  exec'd another process is forked, and that process (the child's child) 
3149  |  will exec the command.  In this case, "shell_fork" will be FALSE.  If no 
3150  |  output is to be performed to the shell command, "shell_fork" will be TRUE.
3151  |  If this is the editor process, shell_fork will be true, otherwise this is 
3152  |  the child of the edit process.
3153  */
3154                         if (!shell_fork)
3155                                 exit(0);
3156                 }
3157                 signal(SIGINT, edit_abort);
3158         }
3159         if (shell_fork)
3160         {
3161                 printf("%s", continue_msg);
3162                 fflush(stdout);
3163                 while ((in = getchar()) != '\n')
3164                         ;
3165         }
3166
3167         if (!in_pipe)
3168         {
3169                 fixterm();
3170                 noecho();
3171                 nonl();
3172                 raw();
3173                 keypad(text_win, TRUE);
3174                 keypad(com_win, TRUE);
3175                 if (info_window)
3176                         clearok(info_win, TRUE);
3177         }
3178
3179         redraw();
3180 }
3181
3182 void 
3183 set_up_term(void)               /* set up the terminal for operating with ae    */
3184 {
3185         if (!curses_initialized)
3186         {
3187                 initscr();
3188                 savetty();
3189                 noecho();
3190                 raw();
3191                 nonl();
3192                 curses_initialized = TRUE;
3193         }
3194
3195         if (((LINES > 15) && (COLS >= 80)) && info_window)
3196                 last_line = LINES - 8;
3197         else
3198         {
3199                 info_window = FALSE;
3200                 last_line = LINES - 2;
3201         }
3202
3203         idlok(stdscr, TRUE);
3204         com_win = newwin(1, COLS, (LINES - 1), 0);
3205         keypad(com_win, TRUE);
3206         idlok(com_win, TRUE);
3207         wrefresh(com_win);
3208         if (!info_window)
3209                 text_win = newwin((LINES - 1), COLS, 0, 0);
3210         else
3211                 text_win = newwin((LINES - 7), COLS, 6, 0);
3212         keypad(text_win, TRUE);
3213         idlok(text_win, TRUE);
3214         wrefresh(text_win);
3215         help_win = newwin((LINES - 1), COLS, 0, 0);
3216         keypad(help_win, TRUE);
3217         idlok(help_win, TRUE);
3218         if (info_window)
3219         {
3220                 info_type = CONTROL_KEYS;
3221                 info_win = newwin(5, COLS, 0, 0);
3222                 werase(info_win);
3223                 paint_info_win();
3224                 count_win = newwin(1, COLS, 5, 0);
3225                 leaveok(count_win, TRUE);
3226                 wrefresh(count_win);
3227         }
3228
3229         last_col = COLS - 1;
3230         local_LINES = LINES;
3231         local_COLS = COLS;
3232
3233 #ifdef NCURSE
3234         if (ee_chinese)
3235                 nc_setattrib(A_NC_BIG5);
3236 #endif /* NCURSE */
3237
3238 }
3239
3240 void 
3241 resize_check(void)
3242 {
3243         if ((LINES == local_LINES) && (COLS == local_COLS))
3244                 return;
3245
3246         if (info_window)
3247                 delwin(info_win);
3248         delwin(text_win);
3249         delwin(com_win);
3250         delwin(help_win);
3251         delwin(count_win);
3252         set_up_term();
3253         redraw();
3254         wrefresh(text_win);
3255 }
3256
3257 static char item_alpha[] = "abcdefghijklmnopqrstuvwxyz0123456789 ";
3258
3259 int 
3260 menu_op(struct menu_entries *menu_list)
3261 {
3262         WINDOW *temp_win;
3263         int max_width, max_height;
3264         int x_off, y_off;
3265         int counter;
3266         int length;
3267         int input;
3268         int temp = 0;
3269         int list_size;
3270         int top_offset;         /* offset from top where menu items start */
3271         int vert_size;          /* vertical size for menu list item display */
3272         int off_start = 1;      /* offset from start of menu items to start display */
3273
3274
3275         /*
3276          |      determine number and width of menu items
3277          */
3278
3279         list_size = 1;
3280         while (menu_list[list_size + 1].item_string != NULL)
3281                 list_size++;
3282         max_width = 0;
3283         for (counter = 0; counter <= list_size; counter++)
3284         {
3285                 if ((length = strlen(menu_list[counter].item_string)) > max_width)
3286                         max_width = length;
3287         }
3288         max_width += 3;
3289         max_width = max(max_width, strlen(menu_cancel_msg));
3290         max_width = max(max_width, max(strlen(more_above_str), strlen(more_below_str)));
3291         max_width += 6;
3292
3293         /*
3294          |      make sure that window is large enough to handle menu
3295          |      if not, print error message and return to calling function
3296          */
3297
3298         if (max_width > COLS)
3299         {
3300                 wmove(com_win, 0, 0);
3301                 werase(com_win);
3302                 wprintw(com_win, menu_too_lrg_msg);
3303                 wrefresh(com_win);
3304                 clear_com_win = TRUE;
3305                 return(0);
3306         }
3307
3308         top_offset = 0;
3309
3310         if (list_size > LINES)
3311         {
3312                 max_height = LINES;
3313                 if (max_height > 11)
3314                         vert_size = max_height - 8;
3315                 else
3316                         vert_size = max_height;
3317         }
3318         else
3319         {
3320                 vert_size = list_size;
3321                 max_height = list_size;
3322         }
3323
3324         if (LINES >= (vert_size + 8))
3325         {
3326                 if (menu_list[0].argument != MENU_WARN)
3327                         max_height = vert_size + 8;
3328                 else
3329                         max_height = vert_size + 7;
3330                 top_offset = 4;
3331         }
3332         x_off = (COLS - max_width) / 2;
3333         y_off = (LINES - max_height - 1) / 2;
3334         temp_win = newwin(max_height, max_width, y_off, x_off);
3335         keypad(temp_win, TRUE);
3336
3337         paint_menu(menu_list, max_width, max_height, list_size, top_offset, temp_win, off_start, vert_size);
3338
3339         counter = 1;
3340         do
3341         {
3342                 if (off_start > 2)
3343                         wmove(temp_win, (1 + counter + top_offset - off_start), 3);
3344                 else
3345                         wmove(temp_win, (counter + top_offset - off_start), 3);
3346
3347                 wrefresh(temp_win);
3348                 input = wgetch(temp_win);
3349
3350                 if (((tolower(input) >= 'a') && (tolower(input) <= 'z')) || 
3351                     ((input >= '0') && (input <= '9')))
3352                 {
3353                         if ((tolower(input) >= 'a') && (tolower(input) <= 'z'))
3354                         {
3355                                 temp = 1 + tolower(input) - 'a';
3356                         }
3357                         else if ((input >= '0') && (input <= '9'))
3358                         {
3359                                 temp = (2 + 'z' - 'a') + (input - '0');
3360                         }
3361
3362                         if (temp <= list_size)
3363                         {
3364                                 input = '\n';
3365                                 counter = temp;
3366                         }
3367                 }
3368                 else
3369                 {               
3370                         switch (input)
3371                         {
3372                                 case ' ':       /* space        */
3373                                 case '\004':    /* ^d, down     */
3374                                 case KEY_RIGHT:
3375                                 case KEY_DOWN:
3376                                         counter++;
3377                                         if (counter > list_size)
3378                                                 counter = 1;
3379                                         break;
3380                                 case '\010':    /* ^h, backspace*/
3381                                 case '\025':    /* ^u, up       */
3382                                 case 127:       /* ^?, delete   */
3383                                 case KEY_BACKSPACE:
3384                                 case KEY_LEFT:
3385                                 case KEY_UP:
3386                                         counter--;
3387                                         if (counter == 0)
3388                                                 counter = list_size;
3389                                         break;
3390                                 case '\033':    /* escape key   */
3391                                         if (menu_list[0].argument != MENU_WARN)
3392                                                 counter = 0;
3393                                         break;
3394                                 case '\014':    /* ^l           */
3395                                 case '\022':    /* ^r, redraw   */
3396                                         paint_menu(menu_list, max_width, max_height, 
3397                                                 list_size, top_offset, temp_win, 
3398                                                 off_start, vert_size);
3399                                         break;
3400                                 default:
3401                                         break;
3402                         }
3403                 }
3404         
3405                 if (((list_size - off_start) >= (vert_size - 1)) && 
3406                         (counter > (off_start + vert_size - 3)) && 
3407                                 (off_start > 1))
3408                 {
3409                         if (counter == list_size)
3410                                 off_start = (list_size - vert_size) + 2;
3411                         else
3412                                 off_start++;
3413
3414                         paint_menu(menu_list, max_width, max_height, 
3415                                    list_size, top_offset, temp_win, off_start, 
3416                                    vert_size);
3417                 }
3418                 else if ((list_size != vert_size) && 
3419                                 (counter > (off_start + vert_size - 2)))
3420                 {
3421                         if (counter == list_size)
3422                                 off_start = 2 + (list_size - vert_size);
3423                         else if (off_start == 1)
3424                                 off_start = 3;
3425                         else
3426                                 off_start++;
3427
3428                         paint_menu(menu_list, max_width, max_height, 
3429                                    list_size, top_offset, temp_win, off_start, 
3430                                    vert_size);
3431                 }
3432                 else if (counter < off_start)
3433                 {
3434                         if (counter <= 2)
3435                                 off_start = 1;
3436                         else
3437                                 off_start = counter;
3438
3439                         paint_menu(menu_list, max_width, max_height, 
3440                                    list_size, top_offset, temp_win, off_start, 
3441                                    vert_size);
3442                 }
3443         }
3444         while ((input != '\r') && (input != '\n') && (counter != 0));
3445
3446         werase(temp_win);
3447         wrefresh(temp_win);
3448         delwin(temp_win);
3449
3450         if ((menu_list[counter].procedure != NULL) || 
3451             (menu_list[counter].iprocedure != NULL) || 
3452             (menu_list[counter].nprocedure != NULL))
3453         {
3454                 if (menu_list[counter].argument != -1)
3455                         (*menu_list[counter].iprocedure)(menu_list[counter].argument);
3456                 else if (menu_list[counter].ptr_argument != NULL)
3457                         (*menu_list[counter].procedure)(menu_list[counter].ptr_argument);
3458                 else
3459                         (*menu_list[counter].nprocedure)();
3460         }
3461
3462         if (info_window)
3463                 paint_info_win();
3464         redraw();
3465
3466         return(counter);
3467 }
3468
3469 void 
3470 paint_menu(struct menu_entries *menu_list, int max_width, int max_height,
3471            int list_size, int top_offset, WINDOW *menu_win, int off_start,
3472            int vert_size)
3473 {
3474         int counter, temp_int;
3475
3476         werase(menu_win);
3477
3478         /*
3479          |      output top and bottom portions of menu box only if window 
3480          |      large enough 
3481          */
3482
3483         if (max_height > vert_size)
3484         {
3485                 wmove(menu_win, 1, 1);
3486                 if (!nohighlight)
3487                         wstandout(menu_win);
3488                 waddch(menu_win, '+');
3489                 for (counter = 0; counter < (max_width - 4); counter++)
3490                         waddch(menu_win, '-');
3491                 waddch(menu_win, '+');
3492
3493                 wmove(menu_win, (max_height - 2), 1);
3494                 waddch(menu_win, '+');
3495                 for (counter = 0; counter < (max_width - 4); counter++)
3496                         waddch(menu_win, '-');
3497                 waddch(menu_win, '+');
3498                 wstandend(menu_win);
3499                 wmove(menu_win, 2, 3);
3500                 waddstr(menu_win, menu_list[0].item_string);
3501                 wmove(menu_win, (max_height - 3), 3);
3502                 if (menu_list[0].argument != MENU_WARN)
3503                         waddstr(menu_win, menu_cancel_msg);
3504         }
3505         if (!nohighlight)
3506                 wstandout(menu_win);
3507
3508         for (counter = 0; counter < (vert_size + top_offset); counter++)
3509         {
3510                 if (top_offset == 4)
3511                 {
3512                         temp_int = counter + 2;
3513                 }
3514                 else
3515                         temp_int = counter;
3516
3517                 wmove(menu_win, temp_int, 1);
3518                 waddch(menu_win, '|');
3519                 wmove(menu_win, temp_int, (max_width - 2));
3520                 waddch(menu_win, '|');
3521         }
3522         wstandend(menu_win);
3523
3524         if (list_size > vert_size)
3525         {
3526                 if (off_start >= 3)
3527                 {
3528                         temp_int = 1;
3529                         wmove(menu_win, top_offset, 3);
3530                         waddstr(menu_win, more_above_str);
3531                 }
3532                 else
3533                         temp_int = 0;
3534
3535                 for (counter = off_start; 
3536                         ((temp_int + counter - off_start) < (vert_size - 1));
3537                                 counter++)
3538                 {
3539                         wmove(menu_win, (top_offset + temp_int + 
3540                                                 (counter - off_start)), 3);
3541                         if (list_size > 1)
3542                                 wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
3543                         waddstr(menu_win, menu_list[counter].item_string);
3544                 }
3545
3546                 wmove(menu_win, (top_offset + (vert_size - 1)), 3);
3547
3548                 if (counter == list_size)
3549                 {
3550                         if (list_size > 1)
3551                                 wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
3552                         wprintw(menu_win, menu_list[counter].item_string);
3553                 }
3554                 else
3555                         wprintw(menu_win, more_below_str);
3556         }
3557         else
3558         {
3559                 for (counter = 1; counter <= list_size; counter++)
3560                 {
3561                         wmove(menu_win, (top_offset + counter - 1), 3);
3562                         if (list_size > 1)
3563                                 wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
3564                         waddstr(menu_win, menu_list[counter].item_string);
3565                 }
3566         }
3567 }
3568
3569 void 
3570 help(void)
3571 {
3572         int counter;
3573
3574         werase(help_win);
3575         clearok(help_win, TRUE);
3576         for (counter = 0; counter < 22; counter++)
3577         {
3578                 wmove(help_win, counter, 0);
3579                 waddstr(help_win, (emacs_keys_mode) ? 
3580                         emacs_help_text[counter] : help_text[counter]);
3581         }
3582         wrefresh(help_win);
3583         werase(com_win);
3584         wmove(com_win, 0, 0);
3585         wprintw(com_win, press_any_key_msg);
3586         wrefresh(com_win);
3587         counter = wgetch(com_win);
3588         werase(com_win);
3589         wmove(com_win, 0, 0);
3590         werase(help_win);
3591         wrefresh(help_win);
3592         wrefresh(com_win);
3593         redraw();
3594 }
3595
3596 void 
3597 paint_info_win(void)
3598 {
3599         int counter;
3600
3601         if (!info_window)
3602                 return;
3603
3604         werase(info_win);
3605         for (counter = 0; counter < 5; counter++)
3606         {
3607                 wmove(info_win, counter, 0);
3608                 wclrtoeol(info_win);
3609                 if (info_type == CONTROL_KEYS)
3610                         waddstr(info_win, (emacs_keys_mode) ? 
3611                           emacs_control_keys[counter] : control_keys[counter]);
3612                 else if (info_type == COMMANDS)
3613                         waddstr(info_win, command_strings[counter]);
3614         }
3615         wrefresh(info_win);
3616 }
3617
3618 void 
3619 no_info_window(void)
3620 {
3621         if (!info_window)
3622                 return;
3623         delwin(info_win);
3624         delwin(text_win);
3625         info_window = FALSE;
3626         last_line = LINES - 2;
3627         text_win = newwin((LINES - 1), COLS, 0, 0);
3628         keypad(text_win, TRUE);
3629         idlok(text_win, TRUE);
3630         clearok(text_win, TRUE);
3631         midscreen(scr_vert, point);
3632         wrefresh(text_win);
3633         clear_com_win = TRUE;
3634 }
3635
3636 void 
3637 create_info_window(void)
3638 {
3639         if (info_window)
3640                 return;
3641         last_line = LINES - 8;
3642         delwin(text_win);
3643         text_win = newwin((LINES - 7), COLS, 6, 0);
3644         keypad(text_win, TRUE);
3645         idlok(text_win, TRUE);
3646         werase(text_win);
3647         info_window = TRUE;
3648         info_win = newwin(5, COLS, 0, 0);
3649         werase(info_win);
3650         info_type = CONTROL_KEYS;
3651         midscreen(min(scr_vert, last_line), point);
3652         clearok(info_win, TRUE);
3653         paint_info_win();
3654         count_win = newwin(1, COLS, 5, 0);
3655         leaveok(count_win, TRUE);
3656         wrefresh(count_win);
3657         wrefresh(text_win);
3658         clear_com_win = TRUE;
3659 }
3660
3661 int 
3662 file_op(int arg)
3663 {
3664         char *string;
3665         int flag;
3666
3667         if (restrict_mode())
3668         {
3669                 return(0);
3670         }
3671
3672         if (arg == READ_FILE)
3673         {
3674                 string = get_string(file_read_prompt_str, TRUE);
3675                 recv_file = TRUE;
3676                 tmp_file = resolve_name(string);
3677                 check_fp();
3678                 if (tmp_file != string)
3679                         free(tmp_file);
3680                 free(string);
3681         }
3682         else if (arg == WRITE_FILE)
3683         {
3684                 string = get_string(file_write_prompt_str, TRUE);
3685                 tmp_file = resolve_name(string);
3686                 write_file(tmp_file, 1);
3687                 if (tmp_file != string)
3688                         free(tmp_file);
3689                 free(string);
3690         }
3691         else if (arg == SAVE_FILE)
3692         {
3693         /*
3694          |      changes made here should be reflected in finish()
3695          */
3696
3697                 if (in_file_name)
3698                         flag = TRUE;
3699                 else
3700                         flag = FALSE;
3701
3702                 string = in_file_name;
3703                 if ((string == NULL) || (*string == 0))
3704                         string = get_string(save_file_name_prompt, TRUE);
3705                 if ((string == NULL) || (*string == 0))
3706                 {
3707                         wmove(com_win, 0, 0);
3708                         wprintw(com_win, file_not_saved_msg);
3709                         wclrtoeol(com_win);
3710                         wrefresh(com_win);
3711                         clear_com_win = TRUE;
3712                         return(0);
3713                 }
3714                 if (!flag)
3715                 {
3716                         tmp_file = resolve_name(string);
3717                         if (tmp_file != string)
3718                         {
3719                                 free(string);
3720                                 string = tmp_file;
3721                         }
3722                 }
3723                 if (write_file(string, 1))
3724                 {
3725                         in_file_name = string;
3726                         text_changes = FALSE;
3727                 }
3728                 else if (!flag)
3729                         free(string);
3730         }
3731         return(0);
3732 }
3733
3734 void 
3735 shell_op(void)
3736 {
3737         char *string;
3738
3739         if (((string = get_string(shell_prompt, TRUE)) != NULL) && 
3740                         (*string != 0))
3741         {
3742                 sh_command(string);
3743                 free(string);
3744         }
3745 }
3746
3747 void 
3748 leave_op(void)
3749 {
3750         if (text_changes)
3751         {
3752                 menu_op(leave_menu);
3753         }
3754         else
3755                 quit(TRUE);
3756 }
3757
3758 void 
3759 redraw(void)
3760 {
3761         if (info_window)
3762         {
3763                 clearok(info_win, TRUE);
3764                 paint_info_win();
3765         }
3766         else
3767                 clearok(text_win, TRUE);
3768         midscreen(scr_vert, point);
3769 }
3770
3771 /*
3772  |      The following routines will "format" a paragraph (as defined by a 
3773  |      block of text with blank lines before and after the block).
3774  */
3775
3776 int 
3777 Blank_Line(struct text *test_line)
3778 /* test if line has any non-space characters */
3779 {
3780         unsigned char *line;
3781         int length;
3782         
3783         if (test_line == NULL)
3784                 return(TRUE);
3785
3786         length = 1;
3787         line = test_line->line;
3788
3789         /*
3790          |      To handle troff/nroff documents, consider a line with a 
3791          |      period ('.') in the first column to be blank.  To handle mail 
3792          |      messages with included text, consider a line with a '>' blank.
3793          */
3794
3795         if ((*line == '.') || (*line == '>'))
3796                 return(TRUE);
3797
3798         while (((*line == ' ') || (*line == '\t')) && (length < test_line->line_length))
3799         {
3800                 length++;
3801                 line++;
3802         }
3803         if (length != test_line->line_length)
3804                 return(FALSE);
3805         else
3806                 return(TRUE);
3807 }
3808
3809 void 
3810 Format(void)    /* format the paragraph according to set margins        */
3811 {
3812         int string_count;
3813         int offset;
3814         int temp_case;
3815         int status;
3816         int tmp_af;
3817         int counter;
3818         unsigned char *line;
3819         unsigned char *tmp_srchstr;
3820         unsigned char *temp1, *temp2;
3821         unsigned char *temp_dword;
3822         unsigned char temp_d_char[3];
3823
3824         temp_d_char[0] = d_char[0];
3825         temp_d_char[1] = d_char[1];
3826         temp_d_char[2] = d_char[2];
3827
3828 /*
3829  |      if observ_margins is not set, or the current line is blank, 
3830  |      do not format the current paragraph
3831  */
3832
3833         if ((!observ_margins) || (Blank_Line(curr_line)))
3834                 return;
3835
3836 /*
3837  |      save the currently set flags, and clear them
3838  */
3839
3840         wmove(com_win, 0, 0);
3841         wclrtoeol(com_win);
3842         wprintw(com_win, formatting_msg);
3843         wrefresh(com_win);
3844
3845 /*
3846  |      get current position in paragraph, so after formatting, the cursor 
3847  |      will be in the same relative position
3848  */
3849
3850         tmp_af = auto_format;
3851         auto_format = FALSE;
3852         offset = position;
3853         if (position != 1)
3854                 prev_word();
3855         temp_dword = d_word;
3856         d_word = NULL;
3857         temp_case = case_sen;
3858         case_sen = TRUE;
3859         tmp_srchstr = srch_str;
3860         temp2 = srch_str = (unsigned char *) malloc(1 + curr_line->line_length - position);
3861         if ((*point == ' ') || (*point == '\t'))
3862                 adv_word();
3863         offset -= position;
3864         counter = position;
3865         line = temp1 = point;
3866         while ((*temp1 != 0) && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length))
3867         {
3868                 *temp2 = *temp1;
3869                 temp2++;
3870                 temp1++;
3871                 counter++;
3872         }
3873         *temp2 = 0;
3874         if (position != 1)
3875                 bol();
3876         while (!Blank_Line(curr_line->prev_line))
3877                 bol();
3878         string_count = 0;
3879         status = TRUE;
3880         while ((line != point) && (status))
3881         {
3882                 status = search(FALSE);
3883                 string_count++;
3884         }
3885
3886         wmove(com_win, 0, 0);
3887         wclrtoeol(com_win);
3888         wprintw(com_win, formatting_msg);
3889         wrefresh(com_win);
3890
3891 /*
3892  |      now get back to the start of the paragraph to start formatting
3893  */
3894
3895         if (position != 1)
3896                 bol();
3897         while (!Blank_Line(curr_line->prev_line))
3898                 bol();
3899
3900         observ_margins = FALSE;
3901
3902 /*
3903  |      Start going through lines, putting spaces at end of lines if they do 
3904  |      not already exist.  Append lines together to get one long line, and 
3905  |      eliminate spacing at begin of lines.
3906  */
3907
3908         while (!Blank_Line(curr_line->next_line))
3909         {
3910                 eol();
3911                 left(TRUE);
3912                 if (*point != ' ')
3913                 {
3914                         right(TRUE);
3915                         insert(' ');
3916                 }
3917                 else
3918                         right(TRUE);
3919                 del_char();
3920                 if ((*point == ' ') || (*point == '\t'))
3921                         del_word();
3922         }
3923
3924 /*
3925  |      Now there is one long line.  Eliminate extra spaces within the line
3926  |      after the first word (so as not to blow away any indenting the user 
3927  |      may have put in).
3928  */
3929
3930         bol();
3931         adv_word();
3932         while (position < curr_line->line_length)
3933         {
3934                 if ((*point == ' ') && (*(point + 1) == ' '))
3935                         del_char();
3936                 else
3937                         right(TRUE);
3938         }
3939
3940 /*
3941  |      Now make sure there are two spaces after a '.'.
3942  */
3943
3944         bol();
3945         while (position < curr_line->line_length)
3946         {
3947                 if ((*point == '.') && (*(point + 1) == ' '))
3948                 {
3949                         right(TRUE);
3950                         insert(' ');
3951                         insert(' ');
3952                         while (*point == ' ')
3953                                 del_char();
3954                 }
3955                 right(TRUE);
3956         }
3957
3958         observ_margins = TRUE;
3959         bol();
3960
3961         wmove(com_win, 0, 0);
3962         wclrtoeol(com_win);
3963         wprintw(com_win, formatting_msg);
3964         wrefresh(com_win);
3965
3966 /*
3967  |      create lines between margins
3968  */
3969
3970         while (position < curr_line->line_length)
3971         {
3972                 while ((scr_pos < right_margin) && (position < curr_line->line_length))
3973                         right(TRUE);
3974                 if (position < curr_line->line_length)
3975                 {
3976                         prev_word();
3977                         if (position == 1)
3978                                 adv_word();
3979                         insert_line(TRUE);
3980                 }
3981         }
3982
3983 /*
3984  |      go back to begin of paragraph, put cursor back to original position
3985  */
3986
3987         bol();
3988         while (!Blank_Line(curr_line->prev_line))
3989                 bol();
3990
3991 /*
3992  |      find word cursor was in
3993  */
3994
3995         while ((status) && (string_count > 0))
3996         {
3997                 search(FALSE);
3998                 string_count--;
3999         }
4000
4001 /*
4002  |      offset the cursor to where it was before from the start of the word
4003  */
4004
4005         while (offset > 0)
4006         {
4007                 offset--;
4008                 right(TRUE);
4009         }
4010
4011 /*
4012  |      reset flags and strings to what they were before formatting
4013  */
4014
4015         if (d_word != NULL)
4016                 free(d_word);
4017         d_word = temp_dword;
4018         case_sen = temp_case;
4019         free(srch_str);
4020         srch_str = tmp_srchstr;
4021         d_char[0] = temp_d_char[0];
4022         d_char[1] = temp_d_char[1];
4023         d_char[2] = temp_d_char[2];
4024         auto_format = tmp_af;
4025
4026         midscreen(scr_vert, point);
4027         werase(com_win);
4028         wrefresh(com_win);
4029 }
4030
4031 unsigned char *init_name[3] = {
4032         "/usr/share/misc/init.ee", 
4033         NULL, 
4034         ".init.ee"
4035         };
4036
4037 void 
4038 ee_init(void)   /* check for init file and read it if it exists */
4039 {
4040         FILE *init_file;
4041         unsigned char *string;
4042         unsigned char *str1;
4043         unsigned char *str2;
4044         char *home;
4045         int counter;
4046         int temp_int;
4047
4048         string = getenv("HOME");
4049         if (!string)
4050             string = "/root"; /* Set to reasonable default so we don't crash */
4051         str1 = home = malloc(strlen(string)+10);
4052         strcpy(home, string);
4053         strcat(home, "/.init.ee");
4054         init_name[1] = home;
4055         string = malloc(512);
4056
4057         for (counter = 0; counter < 3; counter++)
4058         {
4059                 if (!(access(init_name[counter], 4)))
4060                 {
4061                         init_file = fopen(init_name[counter], "r");
4062                         while ((str2 = fgets(string, 512, init_file)) != NULL)
4063                         {
4064                                 str1 = str2 = string;
4065                                 while (*str2 != '\n')
4066                                         str2++;
4067                                 *str2 = 0;
4068
4069                                 if (unique_test(string, init_strings) != 1)
4070                                         continue;
4071
4072                                 if (compare(str1, CASE, FALSE))
4073                                         case_sen = TRUE;
4074                                 else if (compare(str1, NOCASE, FALSE))
4075                                         case_sen = FALSE;
4076                                 else if (compare(str1, EXPAND, FALSE))
4077                                         expand_tabs = TRUE;
4078                                 else if (compare(str1, NOEXPAND, FALSE))
4079                                         expand_tabs = FALSE;
4080                                 else if (compare(str1, INFO, FALSE))
4081                                         info_window = TRUE;
4082                                 else if (compare(str1, NOINFO, FALSE))
4083                                         info_window = FALSE;   
4084                                 else if (compare(str1, MARGINS, FALSE))
4085                                         observ_margins = TRUE;
4086                                 else if (compare(str1, NOMARGINS, FALSE))
4087                                         observ_margins = FALSE;
4088                                 else if (compare(str1, AUTOFORMAT, FALSE))
4089                                 {
4090                                         auto_format = TRUE;
4091                                         observ_margins = TRUE;
4092                                 }
4093                                 else if (compare(str1, NOAUTOFORMAT, FALSE))
4094                                         auto_format = FALSE;
4095                                 else if (compare(str1, Echo, FALSE))
4096                                 {
4097                                         str1 = next_word(str1);
4098                                         if (*str1 != 0)
4099                                                 echo_string(str1);
4100                                 }
4101                                 else if (compare(str1, PRINTCOMMAND, FALSE))
4102                                 {
4103                                         str1 = next_word(str1);
4104                                         print_command = malloc(strlen(str1)+1);
4105                                         strcpy(print_command, str1);
4106                                 }
4107                                 else if (compare(str1, RIGHTMARGIN, FALSE))
4108                                 {
4109                                         str1 = next_word(str1);
4110                                         if ((*str1 >= '0') && (*str1 <= '9'))
4111                                         {
4112                                                 temp_int = atoi(str1);
4113                                                 if (temp_int > 0)
4114                                                         right_margin = temp_int;
4115                                         }
4116                                 }
4117                                 else if (compare(str1, HIGHLIGHT, FALSE))
4118                                         nohighlight = FALSE;
4119                                 else if (compare(str1, NOHIGHLIGHT, FALSE))
4120                                         nohighlight = TRUE;
4121                                 else if (compare(str1, EIGHTBIT, FALSE))
4122                                         eightbit = TRUE;
4123                                 else if (compare(str1, NOEIGHTBIT, FALSE))
4124                                 {
4125                                         eightbit = FALSE;
4126                                         ee_chinese = FALSE;
4127                                 }
4128                                 else if (compare(str1, EMACS_string, FALSE))
4129                                         emacs_keys_mode = TRUE;
4130                                 else if (compare(str1, NOEMACS_string, FALSE))
4131                                         emacs_keys_mode = FALSE;
4132                                 else if (compare(str1, chinese_cmd, FALSE))
4133                                 {
4134                                         ee_chinese = TRUE;
4135                                         eightbit = TRUE;
4136                                 }
4137                                 else if (compare(str1, nochinese_cmd, FALSE))
4138                                         ee_chinese = FALSE;
4139                         }
4140                         fclose(init_file);
4141                 }
4142         }
4143         free(string);
4144         free(home);
4145
4146         string = getenv("LANG");
4147         if (string != NULL)
4148         {
4149                 if (strcmp(string, "zh_TW.big5") == 0)
4150                 {
4151                         ee_chinese = TRUE;
4152                         eightbit = TRUE;
4153                 }
4154         }
4155 }
4156
4157 /*
4158  |      Save current configuration to .init.ee file in the current directory.
4159  */
4160
4161 void 
4162 dump_ee_conf(void)
4163 {
4164         FILE *init_file;
4165         FILE *old_init_file = NULL;
4166         char *file_name = ".init.ee";
4167         char *home_dir =  "~/.init.ee";
4168         char buffer[512];
4169         struct stat buf;
4170         char *string;
4171         int length;
4172         int option = 0;
4173
4174         if (restrict_mode())
4175         {
4176                 return;
4177         }
4178
4179         option = menu_op(config_dump_menu);
4180
4181         werase(com_win);
4182         wmove(com_win, 0, 0);
4183
4184         if (option == 0)
4185         {
4186                 wprintw(com_win, conf_not_saved_msg);
4187                 wrefresh(com_win);
4188                 return;
4189         }
4190         else if (option == 2)
4191                 file_name = resolve_name(home_dir);
4192
4193         /*
4194          |      If a .init.ee file exists, move it to .init.ee.old.
4195          */
4196
4197         if (stat(file_name, &buf) != -1)
4198         {
4199                 sprintf(buffer, "%s.old", file_name);
4200                 unlink(buffer);
4201                 link(file_name, buffer);
4202                 unlink(file_name);
4203                 old_init_file = fopen(buffer, "r");
4204         }
4205
4206         init_file = fopen(file_name, "w");
4207         if (init_file == NULL)
4208         {
4209                 wprintw(com_win, conf_dump_err_msg);
4210                 wrefresh(com_win);
4211                 return;
4212         }
4213
4214         if (old_init_file != NULL)
4215         {
4216                 /*
4217                  |      Copy non-configuration info into new .init.ee file.
4218                  */
4219                 while ((string = fgets(buffer, 512, old_init_file)) != NULL)
4220                 {
4221                         length = strlen(string);
4222                         string[length - 1] = 0;
4223
4224                         if (unique_test(string, init_strings) == 1)
4225                         {
4226                                 if (compare(string, Echo, FALSE))
4227                                 {
4228                                         fprintf(init_file, "%s\n", string);
4229                                 }
4230                         }
4231                         else
4232                                 fprintf(init_file, "%s\n", string);
4233                 }
4234
4235                 fclose(old_init_file);
4236         }
4237
4238         fprintf(init_file, "%s\n", case_sen ? CASE : NOCASE);
4239         fprintf(init_file, "%s\n", expand_tabs ? EXPAND : NOEXPAND);
4240         fprintf(init_file, "%s\n", info_window ? INFO : NOINFO );
4241         fprintf(init_file, "%s\n", observ_margins ? MARGINS : NOMARGINS );
4242         fprintf(init_file, "%s\n", auto_format ? AUTOFORMAT : NOAUTOFORMAT );
4243         fprintf(init_file, "%s %s\n", PRINTCOMMAND, print_command);
4244         fprintf(init_file, "%s %d\n", RIGHTMARGIN, right_margin);
4245         fprintf(init_file, "%s\n", nohighlight ? NOHIGHLIGHT : HIGHLIGHT );
4246         fprintf(init_file, "%s\n", eightbit ? EIGHTBIT : NOEIGHTBIT );
4247         fprintf(init_file, "%s\n", emacs_keys_mode ? EMACS_string : NOEMACS_string );
4248         fprintf(init_file, "%s\n", ee_chinese ? chinese_cmd : nochinese_cmd );
4249
4250         fclose(init_file);
4251
4252         wprintw(com_win, conf_dump_success_msg, file_name);
4253         wrefresh(com_win);
4254
4255         if ((option == 2) && (file_name != home_dir))
4256         {
4257                 free(file_name);
4258         }
4259 }
4260
4261 void 
4262 echo_string(char *string)       /* echo the given string        */
4263 {
4264         char *temp;
4265         int Counter;
4266
4267                 temp = string;
4268                 while (*temp != 0)
4269                 {
4270                         if (*temp == '\\')
4271                         {
4272                                 temp++;
4273                                 if (*temp == 'n')
4274                                         putchar('\n');
4275                                 else if (*temp == 't')
4276                                         putchar('\t');
4277                                 else if (*temp == 'b')
4278                                         putchar('\b');
4279                                 else if (*temp == 'r')
4280                                         putchar('\r');
4281                                 else if (*temp == 'f')
4282                                         putchar('\f');
4283                                 else if ((*temp == 'e') || (*temp == 'E'))
4284                                         putchar('\033');        /* escape */
4285                                 else if (*temp == '\\')
4286                                         putchar('\\');
4287                                 else if (*temp == '\'')
4288                                         putchar('\'');
4289                                 else if ((*temp >= '0') && (*temp <= '9'))
4290                                 {
4291                                         Counter = 0;
4292                                         while ((*temp >= '0') && (*temp <= '9'))
4293                                         {
4294                                                 Counter = (8 * Counter) + (*temp - '0');
4295                                                 temp++;
4296                                         }
4297                                         putchar(Counter);
4298                                         temp--;
4299                                 }
4300                                 temp++;
4301                         }
4302                         else
4303                         {
4304                                 putchar(*temp);
4305                                 temp++;
4306                         }
4307                 }
4308
4309         fflush(stdout);
4310 }
4311
4312 void 
4313 spell_op(void)  /* check spelling of words in the editor        */
4314 {
4315         if (restrict_mode())
4316         {
4317                 return;
4318         }
4319         top();                  /* go to top of file            */
4320         insert_line(FALSE);     /* create two blank lines       */
4321         insert_line(FALSE);
4322         top();
4323         command(shell_echo_msg);
4324         adv_line();
4325         wmove(com_win, 0, 0);
4326         wprintw(com_win, spell_in_prog_msg);
4327         wrefresh(com_win);
4328         command("<>!spell");    /* send contents of buffer to command 'spell' 
4329                                    and read the results back into the editor */
4330 }
4331
4332 void 
4333 ispell_op(void)
4334 {
4335         char template[128], *name;
4336         char string[256];
4337         int fd;
4338
4339         if (restrict_mode())
4340         {
4341                 return;
4342         }
4343         (void)sprintf(template, "/tmp/ee.XXXXXXXX");
4344         name = mktemp(&template[0]);
4345         fd = open(name, O_CREAT | O_EXCL | O_RDWR, 0600);
4346         if (fd < 0) {
4347                 wmove(com_win, 0, 0);
4348                 wprintw(com_win, create_file_fail_msg, name);
4349                 wrefresh(com_win);
4350                 return;
4351         }
4352         close(fd);
4353         if (write_file(name, 0))
4354         {
4355                 sprintf(string, "ispell %s", name);
4356                 sh_command(string);
4357                 delete_text();
4358                 tmp_file = name;
4359                 recv_file = TRUE;
4360                 check_fp();
4361                 unlink(name);
4362         }
4363 }
4364
4365 int
4366 first_word_len(struct text *test_line)
4367 {
4368         int counter;
4369         unsigned char *pnt;
4370
4371         if (test_line == NULL)
4372                 return(0);
4373
4374         pnt = test_line->line;
4375         if ((pnt == NULL) || (*pnt == 0) ||
4376             (*pnt == '.') || (*pnt == '>'))
4377                 return(0);
4378
4379         if ((*pnt == ' ') || (*pnt == '\t'))
4380         {
4381                 pnt = next_word(pnt);
4382         }
4383
4384         if (*pnt == 0)
4385                 return(0);
4386
4387         counter = 0;
4388         while ((*pnt != 0) && ((*pnt != ' ') && (*pnt != '\t')))
4389         {
4390                 pnt++;
4391                 counter++;
4392         }
4393         while ((*pnt != 0) && ((*pnt == ' ') || (*pnt == '\t')))
4394         {
4395                 pnt++;
4396                 counter++;
4397         }
4398         return(counter);
4399 }
4400
4401 void 
4402 Auto_Format(void)       /* format the paragraph according to set margins */
4403 {
4404         int string_count;
4405         int offset;
4406         int temp_case;
4407         int word_len;
4408         int temp_dwl;
4409         int tmp_d_line_length;
4410         int leave_loop = FALSE;
4411         int status;
4412         int counter;
4413         char not_blank;
4414         unsigned char *line;
4415         unsigned char *tmp_srchstr;
4416         unsigned char *temp1, *temp2;
4417         unsigned char *temp_dword;
4418         unsigned char temp_d_char[3];
4419         unsigned char *tmp_d_line;
4420
4421
4422         temp_d_char[0] = d_char[0];
4423         temp_d_char[1] = d_char[1];
4424         temp_d_char[2] = d_char[2];
4425
4426 /*
4427  |      if observ_margins is not set, or the current line is blank, 
4428  |      do not format the current paragraph
4429  */
4430
4431         if ((!observ_margins) || (Blank_Line(curr_line)))
4432                 return;
4433
4434 /*
4435  |      get current position in paragraph, so after formatting, the cursor 
4436  |      will be in the same relative position
4437  */
4438
4439         tmp_d_line = d_line;
4440         tmp_d_line_length = dlt_line->line_length;
4441         d_line = NULL;
4442         auto_format = FALSE;
4443         offset = position;
4444         if ((position != 1) && ((*point == ' ') || (*point == '\t') || (position == curr_line->line_length) || (*point == 0)))
4445                 prev_word();
4446         temp_dword = d_word;
4447         temp_dwl = d_wrd_len;
4448         d_wrd_len = 0;
4449         d_word = NULL;
4450         temp_case = case_sen;
4451         case_sen = TRUE;
4452         tmp_srchstr = srch_str;
4453         temp2 = srch_str = (unsigned char *) malloc(1 + curr_line->line_length - position);
4454         if ((*point == ' ') || (*point == '\t'))
4455                 adv_word();
4456         offset -= position;
4457         counter = position;
4458         line = temp1 = point;
4459         while ((*temp1 != 0) && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length))
4460         {
4461                 *temp2 = *temp1;
4462                 temp2++;
4463                 temp1++;
4464                 counter++;
4465         }
4466         *temp2 = 0;
4467         if (position != 1)
4468                 bol();
4469         while (!Blank_Line(curr_line->prev_line))
4470                 bol();
4471         string_count = 0;
4472         status = TRUE;
4473         while ((line != point) && (status))
4474         {
4475                 status = search(FALSE);
4476                 string_count++;
4477         }
4478
4479 /*
4480  |      now get back to the start of the paragraph to start checking
4481  */
4482
4483         if (position != 1)
4484                 bol();
4485         while (!Blank_Line(curr_line->prev_line))
4486                 bol();
4487
4488 /*
4489  |      Start going through lines, putting spaces at end of lines if they do 
4490  |      not already exist.  Check line length, and move words to the next line 
4491  |      if they cross the margin.  Then get words from the next line if they 
4492  |      will fit in before the margin.  
4493  */
4494
4495         counter = 0;
4496
4497         while (!leave_loop)
4498         {
4499                 if (position != curr_line->line_length)
4500                         eol();
4501                 left(TRUE);
4502                 if (*point != ' ')
4503                 {
4504                         right(TRUE);
4505                         insert(' ');
4506                 }
4507                 else
4508                         right(TRUE);
4509
4510                 not_blank = FALSE;
4511
4512                 /*
4513                  |      fill line if first word on next line will fit 
4514                  |      in the line without crossing the margin
4515                  */
4516
4517                 while ((curr_line->next_line != NULL) && 
4518                        ((word_len = first_word_len(curr_line->next_line)) > 0) 
4519                         && ((scr_pos + word_len) < right_margin))
4520                 {
4521                         adv_line();
4522                         if ((*point == ' ') || (*point == '\t'))
4523                                 adv_word();
4524                         del_word();
4525                         if (position != 1)
4526                                 bol();
4527
4528                         /*
4529                          |      We know this line was not blank before, so 
4530                          |      make sure that it doesn't have one of the 
4531                          |      leading characters that indicate the line 
4532                          |      should not be modified.
4533                          |
4534                          |      We also know that this character should not 
4535                          |      be left as the first character of this line.
4536                          */
4537
4538                         if ((Blank_Line(curr_line)) && 
4539                             (curr_line->line[0] != '.') && 
4540                             (curr_line->line[0] != '>'))
4541                         {
4542                                 del_line();
4543                                 not_blank = FALSE;
4544                         }
4545                         else
4546                                 not_blank = TRUE;
4547
4548                         /*
4549                          |   go to end of previous line
4550                          */
4551                         left(TRUE);
4552                         undel_word();
4553                         eol();
4554                         /*
4555                          |   make sure there's a space at the end of the line
4556                          */
4557                         left(TRUE);
4558                         if (*point != ' ')
4559                         {
4560                                 right(TRUE);
4561                                 insert(' ');
4562                         }
4563                         else
4564                                 right(TRUE);
4565                 }
4566
4567                 /*
4568                  |      make sure line does not cross right margin
4569                  */
4570
4571                 while (right_margin <= scr_pos)
4572                 {
4573                         prev_word();
4574                         if (position != 1)
4575                         {
4576                                 del_word();
4577                                 if (Blank_Line(curr_line->next_line))
4578                                         insert_line(TRUE);
4579                                 else
4580                                         adv_line();
4581                                 if ((*point == ' ') || (*point == '\t'))
4582                                         adv_word();
4583                                 undel_word();
4584                                 not_blank = TRUE;
4585                                 if (position != 1)
4586                                         bol();
4587                                 left(TRUE);
4588                         }
4589                 }
4590
4591                 if ((!Blank_Line(curr_line->next_line)) || (not_blank))
4592                 {
4593                         adv_line();
4594                         counter++;
4595                 }
4596                 else
4597                         leave_loop = TRUE;
4598         }
4599
4600 /*
4601  |      go back to begin of paragraph, put cursor back to original position
4602  */
4603
4604         if (position != 1)
4605                 bol();
4606         while ((counter-- > 0) || (!Blank_Line(curr_line->prev_line)))
4607                 bol();
4608
4609 /*
4610  |      find word cursor was in
4611  */
4612
4613         status = TRUE;
4614         while ((status) && (string_count > 0))
4615         {
4616                 status = search(FALSE);
4617                 string_count--;
4618         }
4619
4620 /*
4621  |      offset the cursor to where it was before from the start of the word
4622  */
4623
4624         while (offset > 0)
4625         {
4626                 offset--;
4627                 right(TRUE);
4628         }
4629
4630         if ((string_count > 0) && (offset < 0))
4631         {
4632                 while (offset < 0)
4633                 {
4634                         offset++;
4635                         left(TRUE);
4636                 }
4637         }
4638
4639 /*
4640  |      reset flags and strings to what they were before formatting
4641  */
4642
4643         if (d_word != NULL)
4644                 free(d_word);
4645         d_word = temp_dword;
4646         d_wrd_len = temp_dwl;
4647         case_sen = temp_case;
4648         free(srch_str);
4649         srch_str = tmp_srchstr;
4650         d_char[0] = temp_d_char[0];
4651         d_char[1] = temp_d_char[1];
4652         d_char[2] = temp_d_char[2];
4653         auto_format = TRUE;
4654         dlt_line->line_length = tmp_d_line_length;
4655         d_line = tmp_d_line;
4656
4657         formatted = TRUE;
4658         midscreen(scr_vert, point);
4659 }
4660
4661 void 
4662 modes_op(void)
4663 {
4664         int ret_value;
4665         int counter;
4666         char *string;
4667
4668         do
4669         {
4670                 sprintf(modes_menu[1].item_string, "%s %s", mode_strings[1], 
4671                                         (expand_tabs ? ON : OFF));
4672                 sprintf(modes_menu[2].item_string, "%s %s", mode_strings[2], 
4673                                         (case_sen ? ON : OFF));
4674                 sprintf(modes_menu[3].item_string, "%s %s", mode_strings[3], 
4675                                         (observ_margins ? ON : OFF));
4676                 sprintf(modes_menu[4].item_string, "%s %s", mode_strings[4], 
4677                                         (auto_format ? ON : OFF));
4678                 sprintf(modes_menu[5].item_string, "%s %s", mode_strings[5], 
4679                                         (eightbit ? ON : OFF));
4680                 sprintf(modes_menu[6].item_string, "%s %s", mode_strings[6], 
4681                                         (info_window ? ON : OFF));
4682                 sprintf(modes_menu[7].item_string, "%s %s", mode_strings[7], 
4683                                         (emacs_keys_mode ? ON : OFF));
4684                 sprintf(modes_menu[8].item_string, "%s %d", mode_strings[8], 
4685                                         right_margin);
4686                 sprintf(modes_menu[9].item_string, "%s %s", mode_strings[9], 
4687                                         (ee_chinese ? ON : OFF));
4688
4689                 ret_value = menu_op(modes_menu);
4690
4691                 switch (ret_value) 
4692                 {
4693                         case 1:
4694                                 expand_tabs = !expand_tabs;
4695                                 break;
4696                         case 2:
4697                                 case_sen = !case_sen;
4698                                 break;
4699                         case 3:
4700                                 observ_margins = !observ_margins;
4701                                 break;
4702                         case 4:
4703                                 auto_format = !auto_format;
4704                                 if (auto_format)
4705                                         observ_margins = TRUE;
4706                                 break;
4707                         case 5:
4708                                 eightbit = !eightbit;
4709                                 if (!eightbit)
4710                                         ee_chinese = FALSE;
4711 #ifdef NCURSE
4712                                 if (ee_chinese)
4713                                         nc_setattrib(A_NC_BIG5);
4714                                 else
4715                                         nc_clearattrib(A_NC_BIG5);
4716 #endif /* NCURSE */
4717
4718                                 redraw();
4719                                 wnoutrefresh(text_win);
4720                                 break;
4721                         case 6:
4722                                 if (info_window)
4723                                         no_info_window();
4724                                 else
4725                                         create_info_window();
4726                                 break;
4727                         case 7:
4728                                 emacs_keys_mode = !emacs_keys_mode;
4729                                 if (info_window)
4730                                         paint_info_win();
4731                                 break;
4732                         case 8:
4733                                 string = get_string(margin_prompt, TRUE);
4734                                 if (string != NULL)
4735                                 {
4736                                         counter = atoi(string);
4737                                         if (counter > 0)
4738                                                 right_margin = counter;
4739                                         free(string);
4740                                 }
4741                                 break;
4742                         case 9:
4743                                 ee_chinese = !ee_chinese;
4744                                 if (ee_chinese != FALSE)
4745                                         eightbit = TRUE;
4746 #ifdef NCURSE
4747                                 if (ee_chinese)
4748                                         nc_setattrib(A_NC_BIG5);
4749                                 else
4750                                         nc_clearattrib(A_NC_BIG5);
4751 #endif /* NCURSE */
4752                                 redraw();
4753                                 break;
4754                         default:
4755                                 break;
4756                 }
4757         }
4758         while (ret_value != 0);
4759 }
4760
4761 char *
4762 is_in_string(char *string, char *substring)
4763 /* a strchr() look-alike for systems without strchr() */
4764 {
4765         char *full, *sub;
4766
4767         for (sub = substring; (sub != NULL) && (*sub != 0); sub++)
4768         {
4769                 for (full = string; (full != NULL) && (*full != 0);
4770                                 full++)
4771                 {
4772                         if (*sub == *full)
4773                                 return(full);
4774                 }
4775         }
4776         return(NULL);
4777 }
4778
4779 /*
4780  |      handle names of the form "~/file", "~user/file", 
4781  |      "$HOME/foo", "~/$FOO", etc.
4782  */
4783
4784 char *
4785 resolve_name(char *name)
4786 {
4787         char long_buffer[1024];
4788         char short_buffer[128];
4789         char *buffer;
4790         char *slash;
4791         char *tmp;
4792         char *start_of_var;
4793         int offset;
4794         int index;
4795         int counter;
4796         struct passwd *user;
4797
4798         if (name[0] == '~') 
4799         {
4800                 if (name[1] == '/')
4801                 {
4802                         index = getuid();
4803                         user = (struct passwd *) getpwuid(index);
4804                         slash = name + 1;
4805                 }
4806                 else
4807                 {
4808                         slash = strchr(name, '/');
4809                         if (slash == NULL) 
4810                                 return(name);
4811                         *slash = 0;
4812                         user = (struct passwd *) getpwnam((name + 1));
4813                         *slash = '/';
4814                 }
4815                 if (user == NULL) 
4816                 {
4817                         return(name);
4818                 }
4819                 buffer = malloc(strlen(user->pw_dir) + strlen(slash) + 1);
4820                 strcpy(buffer, user->pw_dir);
4821                 strcat(buffer, slash);
4822         }
4823         else
4824                 buffer = name;
4825
4826         if (is_in_string(buffer, "$"))
4827         {
4828                 tmp = buffer;
4829                 index = 0;
4830                 
4831                 while ((*tmp != 0) && (index < 1024))
4832                 {
4833
4834                         while ((*tmp != 0) && (*tmp != '$') &&
4835                                 (index < 1024))
4836                         {
4837                                 long_buffer[index] = *tmp;
4838                                 tmp++;
4839                                 index++;
4840                         }
4841
4842                         if ((*tmp == '$') && (index < 1024))
4843                         {
4844                                 counter = 0;
4845                                 start_of_var = tmp;
4846                                 tmp++;
4847                                 if (*tmp == '{') /* } */        /* bracketed variable name */
4848                                 {
4849                                         tmp++;                          /* { */
4850                                         while ((*tmp != 0) &&
4851                                                 (*tmp != '}') && 
4852                                                 (counter < 128))
4853                                         {
4854                                                 short_buffer[counter] = *tmp;
4855                                                 counter++;
4856                                                 tmp++;
4857                                         }                       /* { */
4858                                         if (*tmp == '}')
4859                                                 tmp++;
4860                                 }
4861                                 else
4862                                 {
4863                                         while ((*tmp != 0) &&
4864                                                (*tmp != '/') && 
4865                                                (*tmp != '$') && 
4866                                                (counter < 128))
4867                                         {
4868                                                 short_buffer[counter] = *tmp;
4869                                                 counter++;
4870                                                 tmp++;
4871                                         }
4872                                 }
4873                                 short_buffer[counter] = 0;
4874                                 if ((slash = getenv(short_buffer)) != NULL)
4875                                 {
4876                                         offset = strlen(slash);
4877                                         if ((offset + index) < 1024)
4878                                                 strcpy(&long_buffer[index], slash);
4879                                         index += offset;
4880                                 }
4881                                 else
4882                                 {
4883                                         while ((start_of_var != tmp) && (index < 1024))
4884                                         {
4885                                                 long_buffer[index] = *start_of_var;
4886                                                 start_of_var++;
4887                                                 index++;
4888                                         }
4889                                 }
4890                         }
4891                 }
4892
4893                 if (index == 1024)
4894                         return(buffer);
4895                 else
4896                         long_buffer[index] = 0;
4897
4898                 if (name != buffer)
4899                         free(buffer);
4900                 buffer = malloc(index + 1);
4901                 strcpy(buffer, long_buffer);
4902         }
4903
4904         return(buffer);
4905 }
4906
4907 int
4908 restrict_mode(void)
4909 {
4910         if (!restricted)
4911                 return(FALSE);
4912
4913         wmove(com_win, 0, 0);
4914         wprintw(com_win, restricted_msg);
4915         wclrtoeol(com_win);
4916         wrefresh(com_win);
4917         clear_com_win = TRUE;
4918         return(TRUE);
4919 }
4920
4921 /*
4922  |      The following routine tests the input string against the list of 
4923  |      strings, to determine if the string is a unique match with one of the 
4924  |      valid values.
4925  */
4926
4927 int 
4928 unique_test(char *string, char **list)
4929 {
4930         int counter;
4931         int num_match;
4932         int result;
4933
4934         num_match = 0;
4935         counter = 0;
4936         while (list[counter] != NULL)
4937         {
4938                 result = compare(string, list[counter], FALSE);
4939                 if (result)
4940                         num_match++;
4941                 counter++;
4942         }
4943         return(num_match);
4944 }
4945
4946 void
4947 renumber_lines(struct text *firstline, int startnumber)
4948 {
4949         struct text *lineptr;
4950         int i;
4951         
4952         i = startnumber;
4953         for (lineptr = firstline; lineptr != NULL; lineptr = lineptr->next_line)
4954                 lineptr->line_number = i++;
4955 }
4956
4957 #ifndef NO_CATGETS
4958 /*
4959  |      Get the catalog entry, and if it got it from the catalog, 
4960  |      make a copy, since the buffer will be overwritten by the 
4961  |      next call to catgets().
4962  */
4963
4964 char *
4965 catgetlocal(int number, char *string)
4966 {
4967         char *temp1;
4968         char *temp2;
4969
4970         temp1 = catgets(catalog, 1, number, string);
4971         if (temp1 != string)
4972         {
4973                 temp2 = malloc(strlen(temp1) + 1);
4974                 strcpy(temp2, temp1);
4975                 temp1 = temp2;
4976         }
4977         return(temp1);
4978 }
4979 #endif /* NO_CATGETS */
4980
4981 /*
4982  |      The following is to allow for using message catalogs which allow 
4983  |      the software to be 'localized', that is, to use different languages 
4984  |      all with the same binary.  For more information, see your system 
4985  |      documentation, or the X/Open Internationalization Guide.
4986  */
4987
4988 void 
4989 strings_init(void)
4990 {
4991         int counter;
4992
4993 #ifndef NO_CATGETS
4994         setlocale(LC_ALL, "");
4995         catalog = catopen("ee", NL_CAT_LOCALE);
4996 #endif /* NO_CATGETS */
4997
4998         modes_menu[0].item_string = catgetlocal( 1, "modes menu");
4999         mode_strings[1]  = catgetlocal( 2, "tabs to spaces       "); 
5000         mode_strings[2]  = catgetlocal( 3, "case sensitive search"); 
5001         mode_strings[3]  = catgetlocal( 4, "margins observed     "); 
5002         mode_strings[4]  = catgetlocal( 5, "auto-paragraph format"); 
5003         mode_strings[5]  = catgetlocal( 6, "eightbit characters  "); 
5004         mode_strings[6]  = catgetlocal( 7, "info window          "); 
5005         mode_strings[8]  = catgetlocal( 8, "right margin         ");
5006         leave_menu[0].item_string  = catgetlocal( 9, "leave menu");
5007         leave_menu[1].item_string  = catgetlocal( 10, "save changes");
5008         leave_menu[2].item_string  = catgetlocal( 11, "no save");
5009         file_menu[0].item_string  = catgetlocal( 12, "file menu");
5010         file_menu[1].item_string  = catgetlocal( 13, "read a file");
5011         file_menu[2].item_string  = catgetlocal( 14, "write a file");
5012         file_menu[3].item_string  = catgetlocal( 15, "save file");
5013         file_menu[4].item_string  = catgetlocal( 16, "print editor contents");
5014         search_menu[0].item_string = catgetlocal( 17, "search menu");
5015         search_menu[1].item_string = catgetlocal( 18, "search for ...");
5016         search_menu[2].item_string = catgetlocal( 19, "search");
5017         spell_menu[0].item_string = catgetlocal( 20, "spell menu");
5018         spell_menu[1].item_string = catgetlocal( 21, "use 'spell'");
5019         spell_menu[2].item_string = catgetlocal( 22, "use 'ispell'");
5020         misc_menu[0].item_string = catgetlocal( 23, "miscellaneous menu");
5021         misc_menu[1].item_string = catgetlocal( 24, "format paragraph");
5022         misc_menu[2].item_string = catgetlocal( 25, "shell command");
5023         misc_menu[3].item_string = catgetlocal( 26, "check spelling");
5024         main_menu[0].item_string  = catgetlocal( 27, "main menu");
5025         main_menu[1].item_string  = catgetlocal( 28, "leave editor");
5026         main_menu[2].item_string  = catgetlocal( 29, "help");
5027         main_menu[3].item_string  = catgetlocal( 30, "file operations");
5028         main_menu[4].item_string  = catgetlocal( 31, "redraw screen");
5029         main_menu[5].item_string  = catgetlocal( 32, "settings");
5030         main_menu[6].item_string  = catgetlocal( 33, "search");
5031         main_menu[7].item_string  = catgetlocal( 34, "miscellaneous");
5032         help_text[0] = catgetlocal( 35, "Control keys:                                                              "); 
5033         help_text[1] = catgetlocal( 36, "^a ascii code           ^i tab                  ^r right                   ");
5034         help_text[2] = catgetlocal( 37, "^b bottom of text       ^j newline              ^t top of text             ");
5035         help_text[3] = catgetlocal( 38, "^c command              ^k delete char          ^u up                      ");
5036         help_text[4] = catgetlocal( 39, "^d down                 ^l left                 ^v undelete word           ");
5037         help_text[5] = catgetlocal( 40, "^e search prompt        ^m newline              ^w delete word             ");
5038         help_text[6] = catgetlocal( 41, "^f undelete char        ^n next page            ^x search                  ");
5039         help_text[7] = catgetlocal( 42, "^g begin of line        ^o end of line          ^y delete line             ");
5040         help_text[8] = catgetlocal( 43, "^h backspace            ^p prev page            ^z undelete line           ");
5041         help_text[9] = catgetlocal( 44, "^[ (escape) menu        ESC-Enter: exit ee                                 ");
5042         help_text[10] = catgetlocal( 45, "                                                                           ");
5043         help_text[11] = catgetlocal( 46, "Commands:                                                                  ");
5044         help_text[12] = catgetlocal( 47, "help    : get this info                 file    : print file name          ");
5045         help_text[13] = catgetlocal( 48, "read    : read a file                   char    : ascii code of char       ");
5046         help_text[14] = catgetlocal( 49, "write   : write a file                  case    : case sensitive search    ");
5047         help_text[15] = catgetlocal( 50, "exit    : leave and save                nocase  : case insensitive search  ");
5048         help_text[16] = catgetlocal( 51, "quit    : leave, no save                !cmd    : execute \"cmd\" in shell   ");
5049         help_text[17] = catgetlocal( 52, "line    : display line #                0-9     : go to line \"#\"           ");
5050         help_text[18] = catgetlocal( 53, "expand  : expand tabs                   noexpand: do not expand tabs         ");
5051         help_text[19] = catgetlocal( 54, "                                                                             ");
5052         help_text[20] = catgetlocal( 55, "  ee [+#] [-i] [-e] [-h] [file(s)]                                            ");
5053         help_text[21] = catgetlocal( 56, "+# :go to line #  -i :no info window  -e : don't expand tabs  -h :no highlight");
5054         control_keys[0] = catgetlocal( 57, "^[ (escape) menu  ^e search prompt  ^y delete line    ^u up     ^p prev page  ");
5055         control_keys[1] = catgetlocal( 58, "^a ascii code     ^x search         ^z undelete line  ^d down   ^n next page  ");
5056         control_keys[2] = catgetlocal( 59, "^b bottom of text ^g begin of line  ^w delete word    ^l left                 ");
5057         control_keys[3] = catgetlocal( 60, "^t top of text    ^o end of line    ^v undelete word  ^r right                ");
5058         control_keys[4] = catgetlocal( 61, "^c command        ^k delete char    ^f undelete char      ESC-Enter: exit ee  ");
5059         command_strings[0] = catgetlocal( 62, "help : get help info  |file  : print file name         |line : print line # ");
5060         command_strings[1] = catgetlocal( 63, "read : read a file    |char  : ascii code of char      |0-9 : go to line \"#\"");
5061         command_strings[2] = catgetlocal( 64, "write: write a file   |case  : case sensitive search   |exit : leave and save ");
5062         command_strings[3] = catgetlocal( 65, "!cmd : shell \"cmd\"    |nocase: ignore case in search   |quit : leave, no save");
5063         command_strings[4] = catgetlocal( 66, "expand: expand tabs   |noexpand: do not expand tabs                           ");
5064         com_win_message = catgetlocal( 67, "    press Escape (^[) for menu");
5065         no_file_string = catgetlocal( 68, "no file");
5066         ascii_code_str = catgetlocal( 69, "ascii code: ");
5067         printer_msg_str = catgetlocal( 70, "sending contents of buffer to \"%s\" ");
5068         command_str = catgetlocal( 71, "command: ");
5069         file_write_prompt_str = catgetlocal( 72, "name of file to write: ");
5070         file_read_prompt_str = catgetlocal( 73, "name of file to read: ");
5071         char_str = catgetlocal( 74, "character = %d");
5072         unkn_cmd_str = catgetlocal( 75, "unknown command \"%s\"");
5073         non_unique_cmd_msg = catgetlocal( 76, "entered command is not unique");
5074         line_num_str = catgetlocal( 77, "line %d  ");
5075         line_len_str = catgetlocal( 78, "length = %d");
5076         current_file_str = catgetlocal( 79, "current file is \"%s\" ");
5077         usage0 = catgetlocal( 80, "usage: %s [-i] [-e] [-h] [+line_number] [file(s)]\n");
5078         usage1 = catgetlocal( 81, "       -i   turn off info window\n");
5079         usage2 = catgetlocal( 82, "       -e   do not convert tabs to spaces\n");
5080         usage3 = catgetlocal( 83, "       -h   do not use highlighting\n");
5081         file_is_dir_msg = catgetlocal( 84, "file \"%s\" is a directory");
5082         new_file_msg = catgetlocal( 85, "new file \"%s\"");
5083         cant_open_msg = catgetlocal( 86, "can't open \"%s\"");
5084         open_file_msg = catgetlocal( 87, "file \"%s\", %d lines");
5085         file_read_fin_msg = catgetlocal( 88, "finished reading file \"%s\"");
5086         reading_file_msg = catgetlocal( 89, "reading file \"%s\"");
5087         read_only_msg = catgetlocal( 90, ", read only");
5088         file_read_lines_msg = catgetlocal( 91, "file \"%s\", %d lines");
5089         save_file_name_prompt = catgetlocal( 92, "enter name of file: ");
5090         file_not_saved_msg = catgetlocal( 93, "no filename entered: file not saved");
5091         changes_made_prompt = catgetlocal( 94, "changes have been made, are you sure? (y/n [n]) ");
5092         yes_char = catgetlocal( 95, "y");
5093         file_exists_prompt = catgetlocal( 96, "file already exists, overwrite? (y/n) [n] ");
5094         create_file_fail_msg = catgetlocal( 97, "unable to create file \"%s\"");
5095         writing_file_msg = catgetlocal( 98, "writing file \"%s\"");
5096         file_written_msg = catgetlocal( 99, "\"%s\" %d lines, %d characters");
5097         searching_msg = catgetlocal( 100, "           ...searching");
5098         str_not_found_msg = catgetlocal( 101, "string \"%s\" not found");
5099         search_prompt_str = catgetlocal( 102, "search for: ");
5100         exec_err_msg = catgetlocal( 103, "could not exec %s");
5101         continue_msg = catgetlocal( 104, "press return to continue ");
5102         menu_cancel_msg = catgetlocal( 105, "press Esc to cancel");
5103         menu_size_err_msg = catgetlocal( 106, "menu too large for window");
5104         press_any_key_msg = catgetlocal( 107, "press any key to continue ");
5105         shell_prompt = catgetlocal( 108, "shell command: ");
5106         formatting_msg = catgetlocal( 109, "...formatting paragraph...");
5107         shell_echo_msg = catgetlocal( 110, "<!echo 'list of unrecognized words'; echo -=-=-=-=-=-");
5108         spell_in_prog_msg = catgetlocal( 111, "sending contents of edit buffer to 'spell'");
5109         margin_prompt = catgetlocal( 112, "right margin is: ");
5110         restricted_msg = catgetlocal( 113, "restricted mode: unable to perform requested operation");
5111         ON = catgetlocal( 114, "ON");
5112         OFF = catgetlocal( 115, "OFF");
5113         HELP = catgetlocal( 116, "HELP");
5114         WRITE = catgetlocal( 117, "WRITE");
5115         READ = catgetlocal( 118, "READ");
5116         LINE = catgetlocal( 119, "LINE");
5117         FILE_str = catgetlocal( 120, "FILE");
5118         CHARACTER = catgetlocal( 121, "CHARACTER");
5119         REDRAW = catgetlocal( 122, "REDRAW");
5120         RESEQUENCE = catgetlocal( 123, "RESEQUENCE");
5121         AUTHOR = catgetlocal( 124, "AUTHOR");
5122         VERSION = catgetlocal( 125, "VERSION");
5123         CASE = catgetlocal( 126, "CASE");
5124         NOCASE = catgetlocal( 127, "NOCASE");
5125         EXPAND = catgetlocal( 128, "EXPAND");
5126         NOEXPAND = catgetlocal( 129, "NOEXPAND");
5127         Exit_string = catgetlocal( 130, "EXIT");
5128         QUIT_string = catgetlocal( 131, "QUIT");
5129         INFO = catgetlocal( 132, "INFO");
5130         NOINFO = catgetlocal( 133, "NOINFO");
5131         MARGINS = catgetlocal( 134, "MARGINS");
5132         NOMARGINS = catgetlocal( 135, "NOMARGINS");
5133         AUTOFORMAT = catgetlocal( 136, "AUTOFORMAT");
5134         NOAUTOFORMAT = catgetlocal( 137, "NOAUTOFORMAT");
5135         Echo = catgetlocal( 138, "ECHO");
5136         PRINTCOMMAND = catgetlocal( 139, "PRINTCOMMAND");
5137         RIGHTMARGIN = catgetlocal( 140, "RIGHTMARGIN");
5138         HIGHLIGHT = catgetlocal( 141, "HIGHLIGHT");
5139         NOHIGHLIGHT = catgetlocal( 142, "NOHIGHLIGHT");
5140         EIGHTBIT = catgetlocal( 143, "EIGHTBIT");
5141         NOEIGHTBIT = catgetlocal( 144, "NOEIGHTBIT");
5142         /*
5143          |      additions
5144          */
5145         mode_strings[7] = catgetlocal( 145, "emacs key bindings   ");
5146         emacs_help_text[0] = help_text[0];
5147         emacs_help_text[1] = catgetlocal( 146, "^a beginning of line    ^i tab                  ^r restore word            ");
5148         emacs_help_text[2] = catgetlocal( 147, "^b back 1 char          ^j undel char           ^t begin of file           ");
5149         emacs_help_text[3] = catgetlocal( 148, "^c command              ^k delete line          ^u end of file             ");
5150         emacs_help_text[4] = catgetlocal( 149, "^d delete char          ^l undelete line        ^v next page               ");
5151         emacs_help_text[5] = catgetlocal( 150, "^e end of line          ^m newline              ^w delete word             ");
5152         emacs_help_text[6] = catgetlocal( 151, "^f forward 1 char       ^n next line            ^x search                  ");
5153         emacs_help_text[7] = catgetlocal( 152, "^g go back 1 page       ^o ascii char insert    ^y search prompt           ");
5154         emacs_help_text[8] = catgetlocal( 153, "^h backspace            ^p prev line            ^z next word               ");
5155         emacs_help_text[9] = help_text[9];
5156         emacs_help_text[10] = help_text[10];
5157         emacs_help_text[11] = help_text[11];
5158         emacs_help_text[12] = help_text[12];
5159         emacs_help_text[13] = help_text[13];
5160         emacs_help_text[14] = help_text[14];
5161         emacs_help_text[15] = help_text[15];
5162         emacs_help_text[16] = help_text[16];
5163         emacs_help_text[17] = help_text[17];
5164         emacs_help_text[18] = help_text[18];
5165         emacs_help_text[19] = help_text[19];
5166         emacs_help_text[20] = help_text[20];
5167         emacs_help_text[21] = help_text[21];
5168         emacs_control_keys[0] = catgetlocal( 154, "^[ (escape) menu ^y search prompt ^k delete line    ^p prev line  ^g prev page");
5169         emacs_control_keys[1] = catgetlocal( 155, "^o ascii code    ^x search        ^l undelete line  ^n next line  ^v next page");
5170         emacs_control_keys[2] = catgetlocal( 156, "^u end of file   ^a begin of line ^w delete word    ^b back char  ^z next word");
5171         emacs_control_keys[3] = catgetlocal( 157, "^t begin of file ^e end of line   ^r restore word   ^f forward char           ");
5172         emacs_control_keys[4] = catgetlocal( 158, "^c command       ^d delete char   ^j undelete char              ESC-Enter: exit");
5173         EMACS_string = catgetlocal( 159, "EMACS");
5174         NOEMACS_string = catgetlocal( 160, "NOEMACS");
5175         usage4 = catgetlocal( 161, "       +#   put cursor at line #\n");
5176         conf_dump_err_msg = catgetlocal( 162, "unable to open .init.ee for writing, no configuration saved!");
5177         conf_dump_success_msg = catgetlocal( 163, "ee configuration saved in file %s");
5178         modes_menu[10].item_string = catgetlocal( 164, "save editor configuration");
5179         config_dump_menu[0].item_string = catgetlocal( 165, "save ee configuration");
5180         config_dump_menu[1].item_string = catgetlocal( 166, "save in current directory");
5181         config_dump_menu[2].item_string = catgetlocal( 167, "save in home directory");
5182         conf_not_saved_msg = catgetlocal( 168, "ee configuration not saved");
5183         ree_no_file_msg = catgetlocal( 169, "must specify a file when invoking ree");
5184         menu_too_lrg_msg = catgetlocal( 180, "menu too large for window");
5185         more_above_str = catgetlocal( 181, "^^more^^");
5186         more_below_str = catgetlocal( 182, "VVmoreVV");
5187         mode_strings[9] = catgetlocal( 183, "16 bit characters    ");
5188         chinese_cmd = catgetlocal( 184, "16BIT");
5189         nochinese_cmd = catgetlocal( 185, "NO16BIT");
5190
5191         commands[0] = HELP;
5192         commands[1] = WRITE;
5193         commands[2] = READ;
5194         commands[3] = LINE;
5195         commands[4] = FILE_str;
5196         commands[5] = REDRAW;
5197         commands[6] = RESEQUENCE;
5198         commands[7] = AUTHOR;
5199         commands[8] = VERSION;
5200         commands[9] = CASE;
5201         commands[10] = NOCASE;
5202         commands[11] = EXPAND;
5203         commands[12] = NOEXPAND;
5204         commands[13] = Exit_string;
5205         commands[14] = QUIT_string;
5206         commands[15] = "<";
5207         commands[16] = ">";
5208         commands[17] = "!";
5209         commands[18] = "0";
5210         commands[19] = "1";
5211         commands[20] = "2";
5212         commands[21] = "3";
5213         commands[22] = "4";
5214         commands[23] = "5";
5215         commands[24] = "6";
5216         commands[25] = "7";
5217         commands[26] = "8";
5218         commands[27] = "9";
5219         commands[28] = CHARACTER;
5220         commands[29] = chinese_cmd;
5221         commands[30] = nochinese_cmd;
5222         commands[31] = NULL;
5223         init_strings[0] = CASE;
5224         init_strings[1] = NOCASE;
5225         init_strings[2] = EXPAND;
5226         init_strings[3] = NOEXPAND;
5227         init_strings[4] = INFO;
5228         init_strings[5] = NOINFO;
5229         init_strings[6] = MARGINS;
5230         init_strings[7] = NOMARGINS;
5231         init_strings[8] = AUTOFORMAT;
5232         init_strings[9] = NOAUTOFORMAT;
5233         init_strings[10] = Echo;
5234         init_strings[11] = PRINTCOMMAND;
5235         init_strings[12] = RIGHTMARGIN;
5236         init_strings[13] = HIGHLIGHT;
5237         init_strings[14] = NOHIGHLIGHT;
5238         init_strings[15] = EIGHTBIT;
5239         init_strings[16] = NOEIGHTBIT;
5240         init_strings[17] = EMACS_string;
5241         init_strings[18] = NOEMACS_string;
5242         init_strings[19] = chinese_cmd;
5243         init_strings[20] = nochinese_cmd;
5244         init_strings[21] = NULL;
5245
5246         /*
5247          |      allocate space for strings here for settings menu
5248          */
5249
5250         for (counter = 1; counter < NUM_MODES_ITEMS; counter++)
5251         {
5252                 modes_menu[counter].item_string = malloc(80);
5253         }
5254
5255 #ifndef NO_CATGETS
5256         catclose(catalog);
5257 #endif /* NO_CATGETS */
5258 }
5259