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