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