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