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