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