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