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