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