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