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