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