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