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