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