ee.c revision 192914
1139826Simp/*
262587Sitojun |	ee (easy editor)
362587Sitojun |
462587Sitojun |	An easy to use, simple screen oriented editor.
562587Sitojun |
662587Sitojun |	written by Hugh Mahon
762587Sitojun |
862587Sitojun |
962587Sitojun |      Copyright (c) 2009, Hugh Mahon
1062587Sitojun |      All rights reserved.
1162587Sitojun |
1262587Sitojun |      Redistribution and use in source and binary forms, with or without
1362587Sitojun |      modification, are permitted provided that the following conditions
1462587Sitojun |      are met:
1562587Sitojun |
1662587Sitojun |          * Redistributions of source code must retain the above copyright
1762587Sitojun |            notice, this list of conditions and the following disclaimer.
1862587Sitojun |          * Redistributions in binary form must reproduce the above
1962587Sitojun |            copyright notice, this list of conditions and the following
2062587Sitojun |            disclaimer in the documentation and/or other materials provided
2162587Sitojun |            with the distribution.
2262587Sitojun |
2362587Sitojun |      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2462587Sitojun |      "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2562587Sitojun |      LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2662587Sitojun |      FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2762587Sitojun |      COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28174510Sobrien |      INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29174510Sobrien |      BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3062587Sitojun |      LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
3162587Sitojun |      CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32139826Simp |      LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3362587Sitojun |      ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3462587Sitojun |      POSSIBILITY OF SUCH DAMAGE.
3562587Sitojun |
3662587Sitojun |     -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
3762587Sitojun |
3862587Sitojun |	This editor was purposely developed to be simple, both in
3962587Sitojun |	interface and implementation.  This editor was developed to
4062587Sitojun |	address a specific audience: the user who is new to computers
4162587Sitojun |	(especially UNIX).
4262587Sitojun |
4362587Sitojun |	ee is not aimed at technical users; for that reason more
4462587Sitojun |	complex features were intentionally left out.  In addition,
4562587Sitojun |	ee is intended to be compiled by people with little computer
4662587Sitojun |	experience, which means that it needs to be small, relatively
4762587Sitojun |	simple in implementation, and portable.
4862587Sitojun |
4962587Sitojun |	This software and documentation contains
5062587Sitojun |	proprietary information which is protected by
5162587Sitojun |	copyright.  All rights are reserved.
5262587Sitojun |
5362587Sitojun |	$Header: /home/hugh/sources/old_ae/RCS/ee.c,v 1.102 2009/02/17 03:22:50 hugh Exp hugh $
5462587Sitojun |
5562587Sitojun */
5662587Sitojun
5762587Sitojun#include <sys/cdefs.h>
5862587Sitojun__FBSDID("$FreeBSD: head/contrib/ee/ee.c 192914 2009-05-27 17:27:03Z ed $");
5962587Sitojun
6062587Sitojunchar *ee_copyright_message =
6162587Sitojun"Copyright (c) 1986, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 2009 Hugh Mahon ";
6262587Sitojun
63174510Sobrien#include "ee_version.h"
64174510Sobrien
65174510Sobrienchar *version = "@(#) ee, version "  EE_VERSION  " $Revision: 1.102 $";
6662587Sitojun
6762587Sitojun#ifdef NCURSE
68178167Sqingli#include "new_curse.h"
6962587Sitojun#elif HAS_NCURSES
7062587Sitojun#include <ncurses.h>
7162587Sitojun#else
72168191Sjhb#include <curses.h>
7378064Sume#endif
7462587Sitojun
75164033Srwatson#ifdef HAS_CTYPE
7662587Sitojun#include <ctype.h>
7762587Sitojun#endif
7862587Sitojun
79121742Sume#include <signal.h>
80121742Sume#include <fcntl.h>
8162587Sitojun#include <sys/types.h>
8262587Sitojun#include <sys/stat.h>
83185435Sbz#include <errno.h>
84122058Sume#include <string.h>
85286001Sae#include <pwd.h>
86149200Sume
8762587Sitojun#ifdef HAS_SYS_WAIT
8862587Sitojun#include <sys/wait.h>
89257176Sglebius#endif
90196864Sqingli
9162587Sitojun#ifdef HAS_STDLIB
92186119Sqingli#include <stdlib.h>
93178167Sqingli#endif
94178167Sqingli
95178167Sqingli#ifdef HAS_STDARG
9662587Sitojun#include <stdarg.h>
9762587Sitojun#endif
9862587Sitojun
9962587Sitojun#ifdef HAS_UNISTD
10062587Sitojun#include <unistd.h>
10162587Sitojun#endif
102184096Sbz
103184096Sbz
104184096Sbz#ifndef NO_CATGETS
105185571Sbz#include <locale.h>
10662587Sitojun#include <nl_types.h>
10762587Sitojun
108292015Smelifaronl_catd catalog;
10962587Sitojun#else
11062587Sitojun#define catgetlocal(a, b) (b)
111148385Sume#endif /* NO_CATGETS */
11262587Sitojun
11362587Sitojun#ifndef SIGCHLD
114121742Sume#define SIGCHLD SIGCLD
115121742Sume#endif
116121742Sume
117121742Sume#define TAB 9
118121742Sume#define max(a, b)	(a > b ? a : b)
119121742Sume#define min(a, b)	(a < b ? a : b)
120149200Sume
121149200Sume/*
122149200Sume |	defines for type of data to show in info window
123149200Sume */
124149200Sume
125149200Sume#define CONTROL_KEYS 1
126149200Sume#define COMMANDS     2
127121742Sume
128215701Sdimstruct text {
129195727Srwatson	unsigned char *line;		/* line of characters		*/
130195699Srwatson	int line_number;		/* line number			*/
131207369Sbz	int line_length;	/* actual number of characters in the line */
132207369Sbz	int max_length;	/* maximum number of characters the line handles */
133241916Sdelphij	struct text *next_line;		/* next line of text		*/
134148385Sume	struct text *prev_line;		/* previous line of text	*/
135241916Sdelphij	};
136241916Sdelphij
137293101Smelifarostruct text *first_line;	/* first line of current buffer		*/
138241916Sdelphijstruct text *dlt_line;		/* structure for info on deleted line	*/
139293633Smelifarostruct text *curr_line;		/* current line cursor is on		*/
140293633Smelifarostruct text *tmp_line;		/* temporary line pointer		*/
141293633Smelifarostruct text *srch_line;		/* temporary pointer for search routine */
142122077Sume
143175162Sobrienstruct files {		/* structure to store names of files to be edited*/
144122077Sume	unsigned char *name;		/* name of file				*/
145175162Sobrien	struct files *next_name;
146175162Sobrien	};
147175162Sobrien
148241916Sdelphijstruct files *top_of_stack = NULL;
149242938Sobrien
150175162Sobrienint d_wrd_len;			/* length of deleted word		*/
151175162Sobrienint position;			/* offset in bytes from begin of line	*/
152121742Sumeint scr_pos;			/* horizontal position			*/
15362587Sitojunint scr_vert;			/* vertical position on screen		*/
15478064Sumeint scr_horz;			/* horizontal position on screen	*/
15562587Sitojunint absolute_lin;		/* number of lines from top		*/
15678064Sumeint tmp_vert, tmp_horz;
15762587Sitojunint input_file;			/* indicate to read input file		*/
15862587Sitojunint recv_file;			/* indicate reading a file		*/
159122077Sumeint edit;			/* continue executing while true	*/
160249546Saeint gold;			/* 'gold' function key pressed		*/
161249528Saeint fildes;			/* file descriptor			*/
162175512Sbzint case_sen;			/* case sensitive search flag		*/
163175512Sbzint last_line;			/* last line for text display		*/
164175512Sbzint last_col;			/* last column for text display		*/
165175512Sbzint horiz_offset = 0;		/* offset from left edge of text	*/
166122077Sumeint clear_com_win;		/* flag to indicate com_win needs clearing */
167122077Sumeint text_changes = FALSE;	/* indicate changes have been made to text */
168122077Sumeint get_fd;			/* file descriptor for reading a file	*/
169175512Sbzint info_window = TRUE;		/* flag to indicate if help window visible */
170175512Sbzint info_type = CONTROL_KEYS;	/* flag to indicate type of info to display */
171175512Sbzint expand_tabs = TRUE;		/* flag for expanding tabs		*/
172175512Sbzint right_margin = 0;		/* the right margin 			*/
173171260Sdelphijint observ_margins = TRUE;	/* flag for whether margins are observed */
174122077Sumeint shell_fork;
175122077Sumeint temp_stdin;			/* temporary storage for stdin		*/
176249546Saeint temp_stdout;		/* temp storage for stdout descriptor	*/
177249528Saeint temp_stderr;		/* temp storage for stderr descriptor	*/
178171260Sdelphijint pipe_out[2];		/* pipe file desc for output		*/
179122077Sumeint pipe_in[2];			/* pipe file descriptors for input	*/
180122077Sumeint out_pipe;			/* flag that info is piped out		*/
181293633Smelifaroint in_pipe;			/* flag that info is piped in		*/
182293633Smelifaroint formatted = FALSE;		/* flag indicating paragraph formatted	*/
183293633Smelifaroint auto_format = FALSE;	/* flag for auto_format mode		*/
184194777Sbzint restricted = FALSE;		/* flag to indicate restricted mode	*/
18562587Sitojunint nohighlight = FALSE;	/* turns off highlighting		*/
186286001Saeint eightbit = TRUE;		/* eight bit character flag		*/
187207276Sbzint local_LINES = 0;		/* copy of LINES, to detect when win resizes */
188231852Sbzint local_COLS = 0;		/* copy of COLS, to detect when win resizes  */
189122077Sumeint curses_initialized = FALSE;	/* flag indicating if curses has been started*/
19062587Sitojunint emacs_keys_mode = FALSE;	/* mode for if emacs key binings are used    */
191122077Sumeint ee_chinese = FALSE;		/* allows handling of multi-byte characters  */
192122077Sume				/* by checking for high bit in a byte the    */
193122077Sume				/* code recognizes a two-byte character      */
194122077Sume				/* sequence				     */
195249528Sae
196180371Sbzunsigned char *point;		/* points to current position in line	*/
19762587Sitojununsigned char *srch_str;	/* pointer for search string		*/
198194777Sbzunsigned char *u_srch_str;	/* pointer to non-case sensitive search	*/
199194777Sbzunsigned char *srch_1;		/* pointer to start of suspect string	*/
200148385Sumeunsigned char *srch_2;		/* pointer to next character of string	*/
201231852Sbzunsigned char *srch_3;
202231852Sbzunsigned char *in_file_name = NULL;	/* name of input file		*/
203231852Sbzchar *tmp_file;	/* temporary file name			*/
204231852Sbzunsigned char *d_char;		/* deleted character			*/
205231852Sbzunsigned char *d_word;		/* deleted word				*/
206231852Sbzunsigned char *d_line;		/* deleted line				*/
207231852Sbzchar in_string[513];	/* buffer for reading a file		*/
208231852Sbzunsigned char *print_command = (unsigned char *)"lpr";	/* string to use for the print command 	*/
209231852Sbzunsigned char *start_at_line = NULL;	/* move to this line at start of session*/
210231852Sbzint in;				/* input character			*/
211148385Sume
212231852SbzFILE *temp_fp;			/* temporary file pointer		*/
21362587SitojunFILE *bit_bucket;		/* file pointer to /dev/null		*/
214180386Sbz
215180386Sbzchar *table[] = {
216180371Sbz	"^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "\t", "^J",
217180386Sbz	"^K", "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U",
218180371Sbz	"^V", "^W", "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_"
219180386Sbz	};
220180371Sbz
22162587SitojunWINDOW *com_win;
22262587SitojunWINDOW *text_win;
223122077SumeWINDOW *help_win;
224122077SumeWINDOW *info_win;
225122077Sume
22662587Sitojun#if defined(__STDC__) || defined(__cplusplus)
22762587Sitojun#define P_(s) s
228122077Sume#else
229122077Sume#define P_(s) ()
230293101Smelifaro#endif
231293633Smelifaro
232231852Sbz
233194777Sbz/*
234125436Sume |	The following structure allows menu items to be flexibly declared.
235122077Sume |	The first item is the string describing the selection, the second
236122077Sume |	is the address of the procedure to call when the item is selected,
237122077Sume |	and the third is the argument for the procedure.
238148385Sume |
239148385Sume |	For those systems with i18n, the string should be accompanied by a
240148385Sume |	catalog number.  The 'int *' should be replaced with 'void *' on
241122077Sume |	systems with that type.
242296986Sae |
243122077Sume |	The first menu item will be the title of the menu, with NULL
244296986Sae |	parameters for the procedure and argument, followed by the menu items.
245194777Sbz |
246194777Sbz |	If the procedure value is NULL, the menu item is displayed, but no
247122077Sume |	procedure is called when the item is selected.  The number of the
248194777Sbz |	item will be returned.  If the third (argument) parameter is -1, no
249296986Sae |	argument is given to the procedure when it is called.
250194777Sbz */
251148385Sume
252296984Saestruct menu_entries {
253296984Sae	char *item_string;
254296984Sae	int (*procedure)P_((struct menu_entries *));
255296984Sae	struct menu_entries *ptr_argument;
256296984Sae	int (*iprocedure)P_((int));
257296984Sae	void (*nprocedure)P_((void));
258297705Sae	int argument;
259296986Sae	};
260296984Sae
261296986Saeint main P_((int argc, char *argv[]));
262296986Saeunsigned char *resiz_line P_((int factor, struct text *rline, int rpos));
263296984Saevoid insert P_((int character));
264296984Saevoid delete P_((int disp));
265296986Saevoid scanline P_((unsigned char *pos));
266296986Saeint tabshift P_((int temp_int));
267296984Saeint out_char P_((WINDOW *window, int character, int column));
268296986Saeint len_char P_((int character, int column));
269296986Saevoid draw_line P_((int vertical, int horiz, unsigned char *ptr, int t_pos, int length));
270148385Sumevoid insert_line P_((int disp));
271148385Sumestruct text *txtalloc P_((void));
272194777Sbzstruct files *name_alloc P_((void));
273122077Sumeunsigned char *next_word P_((unsigned char *string));
274122077Sumevoid prev_word P_((void));
27562587Sitojunvoid control P_((void));
276122077Sumevoid emacs_control P_((void));
27762587Sitojunvoid bottom P_((void));
278180371Sbzvoid top P_((void));
279188144Sjamievoid nextline P_((void));
280194777Sbzvoid prevline P_((void));
281188144Sjamievoid left P_((int disp));
282194777Sbzvoid right P_((int disp));
283194777Sbzvoid find_pos P_((void));
284194777Sbzvoid up P_((void));
285180371Sbzvoid down P_((void));
28662587Sitojunvoid function_key P_((void));
28762587Sitojunvoid print_buffer P_((void));
288202468Sbzvoid command_prompt P_((void));
289202468Sbzvoid command P_((char *cmd_str1));
290202468Sbzint scan P_((char *line, int offset, int column));
291202468Sbzchar *get_string P_((char *prompt, int advance));
292202468Sbzint compare P_((char *string1, char *string2, int sensitive));
293202468Sbzvoid goto_line P_((char *cmd_str));
294202468Sbzvoid midscreen P_((int line, unsigned char *pnt));
295122077Sumevoid get_options P_((int numargs, char *arguments[]));
296122077Sumevoid check_fp P_((void));
29762587Sitojunvoid get_file P_((char *file_name));
298122077Sumevoid get_line P_((int length, unsigned char *in_string, int *append));
299293101Smelifarovoid draw_screen P_((void));
300231852Sbzvoid finish P_((void));
301194777Sbzint quit P_((int noverify));
30262587Sitojunvoid edit_abort P_((int arg));
303122077Sumevoid delete_text P_((void));
304122077Sumeint write_file P_((char *file_name, int warn_if_exists));
305122077Sumeint search P_((int display_message));
306122077Sumevoid search_prompt P_((void));
307194777Sbzvoid del_char P_((void));
308194777Sbzvoid undel_char P_((void));
309194777Sbzvoid del_word P_((void));
310148385Sumevoid undel_word P_((void));
311249528Saevoid del_line P_((void));
312286001Saevoid undel_line P_((void));
313194907Srwatsonvoid adv_word P_((void));
314122077Sumevoid move_rel P_((char *direction, int lines));
315122077Sumevoid eol P_((void));
316122077Sumevoid bol P_((void));
317148385Sumevoid adv_line P_((void));
318122077Sumevoid sh_command P_((char *string));
319122077Sumevoid set_up_term P_((void));
320122077Sumevoid resize_check P_((void));
321122077Sumeint menu_op P_((struct menu_entries *));
322122077Sumevoid 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));
323122077Sumevoid help P_((void));
324122077Sumevoid paint_info_win P_((void));
325122077Sumevoid no_info_window P_((void));
326148385Sumevoid create_info_window P_((void));
327122077Sumeint file_op P_((int arg));
328122077Sumevoid shell_op P_((void));
32962587Sitojunvoid leave_op P_((void));
330148385Sumevoid redraw P_((void));
331148385Sumeint Blank_Line P_((struct text *test_line));
332148385Sumevoid Format P_((void));
333122077Sumevoid ee_init P_((void));
334122077Sumevoid dump_ee_conf P_((void));
335122077Sumevoid echo_string P_((char *string));
33662587Sitojunvoid spell_op P_((void));
337122077Sumevoid ispell_op P_((void));
338122077Sumeint first_word_len P_((struct text *test_line));
339122077Sumevoid Auto_Format P_((void));
340122077Sumevoid modes_op P_((void));
34162587Sitojunchar *is_in_string P_((char *string, char *substring));
342181803Sbzchar *resolve_name P_((char *name));
343122077Sumeint restrict_mode P_((void));
344122077Sumeint unique_test P_((char *string, char *list[]));
345207276Sbzvoid strings_init P_((void));
346185435Sbz
347207276Sbz#undef P_
348185435Sbz/*
349185435Sbz |	allocate space here for the strings that will be in the menu
350122077Sume */
351148385Sume
352122077Sumestruct menu_entries modes_menu[] = {
353122077Sume	{"", NULL, NULL, NULL, NULL, 0}, 	/* title		*/
354122077Sume	{"", NULL, NULL, NULL, NULL, -1}, 	/* 1. tabs to spaces	*/
355122077Sume	{"", NULL, NULL, NULL, NULL, -1}, 	/* 2. case sensitive search*/
356122077Sume	{"", NULL, NULL, NULL, NULL, -1}, 	/* 3. margins observed	*/
357122077Sume	{"", NULL, NULL, NULL, NULL, -1}, 	/* 4. auto-paragraph	*/
358122077Sume	{"", NULL, NULL, NULL, NULL, -1}, 	/* 5. eightbit characters*/
359122077Sume	{"", NULL, NULL, NULL, NULL, -1}, 	/* 6. info window	*/
360122077Sume	{"", NULL, NULL, NULL, NULL, -1}, 	/* 7. emacs key bindings*/
361148385Sume	{"", NULL, NULL, NULL, NULL, -1}, 	/* 8. right margin	*/
362122077Sume	{"", NULL, NULL, NULL, NULL, -1}, 	/* 9. chinese text	*/
363122077Sume	{"", NULL, NULL, NULL, dump_ee_conf, -1}, /* 10. save editor config */
364122077Sume	{NULL, NULL, NULL, NULL, NULL, -1}	/* terminator		*/
365122077Sume	};
366122077Sume
367122077Sumechar *mode_strings[11];
368122077Sume
369122077Sume#define NUM_MODES_ITEMS 10
370122077Sume
371122077Sumestruct menu_entries config_dump_menu[] = {
372122077Sume	{"", NULL, NULL, NULL, NULL, 0},
373122077Sume	{"", NULL, NULL, NULL, NULL, -1},
374122077Sume	{"", NULL, NULL, NULL, NULL, -1},
375122077Sume	{NULL, NULL, NULL, NULL, NULL, -1}
376122077Sume	};
377122077Sume
378122077Sumestruct menu_entries leave_menu[] = {
379122077Sume	{"", NULL, NULL, NULL, NULL, -1},
380122077Sume	{"", NULL, NULL, NULL, finish, -1},
381122077Sume	{"", NULL, NULL, quit, NULL, TRUE},
382122077Sume	{NULL, NULL, NULL, NULL, NULL, -1}
383122077Sume	};
384122077Sume
385122077Sume#define READ_FILE 1
386122077Sume#define WRITE_FILE 2
387122077Sume#define SAVE_FILE 3
388122077Sume
389245230Sumestruct menu_entries file_menu[] = {
390245230Sume	{"", NULL, NULL, NULL, NULL, -1},
391245230Sume	{"", NULL, NULL, file_op, NULL, READ_FILE},
392245230Sume	{"", NULL, NULL, file_op, NULL, WRITE_FILE},
393245230Sume	{"", NULL, NULL, file_op, NULL, SAVE_FILE},
394245230Sume	{"", NULL, NULL, NULL, print_buffer, -1},
395122077Sume	{NULL, NULL, NULL, NULL, NULL, -1}
396122077Sume	};
397122077Sume
398122077Sumestruct menu_entries search_menu[] = {
399122077Sume	{"", NULL, NULL, NULL, NULL, 0},
400122077Sume	{"", NULL, NULL, NULL, search_prompt, -1},
401122077Sume	{"", NULL, NULL, search, NULL, TRUE},
402122077Sume	{NULL, NULL, NULL, NULL, NULL, -1}
403122077Sume	};
404122077Sume
405122077Sumestruct menu_entries spell_menu[] = {
406122077Sume	{"", NULL, NULL, NULL, NULL, -1},
407122077Sume	{"", NULL, NULL, NULL, spell_op, -1},
408122077Sume	{"", NULL, NULL, NULL, ispell_op, -1},
409122077Sume	{NULL, NULL, NULL, NULL, NULL, -1}
410122077Sume	};
411122077Sume
412122077Sumestruct menu_entries misc_menu[] = {
413122077Sume	{"", NULL, NULL, NULL, NULL, -1},
414122077Sume	{"", NULL, NULL, NULL, Format, -1},
415122077Sume	{"", NULL, NULL, NULL, shell_op, -1},
416122077Sume	{"", menu_op, spell_menu, NULL, NULL, -1},
417122077Sume	{NULL, NULL, NULL, NULL, NULL, -1}
418122077Sume	};
419122077Sume
420181803Sbzstruct menu_entries main_menu[] = {
421122077Sume	{"", NULL, NULL, NULL, NULL, -1},
422122077Sume	{"", NULL, NULL, NULL, leave_op, -1},
423122077Sume	{"", NULL, NULL, NULL, help, -1},
424122077Sume	{"", menu_op, file_menu, NULL, NULL, -1},
425122077Sume	{"", NULL, NULL, NULL, redraw, -1},
426122077Sume	{"", NULL, NULL, NULL, modes_op, -1},
427122077Sume	{"", menu_op, search_menu, NULL, NULL, -1},
428122077Sume	{"", menu_op, misc_menu, NULL, NULL, -1},
429122077Sume	{NULL, NULL, NULL, NULL, NULL, -1}
430122077Sume	};
431122077Sume
432122077Sumechar *help_text[23];
433122077Sumechar *control_keys[5];
434122077Sume
435122077Sumechar *emacs_help_text[22];
436122077Sumechar *emacs_control_keys[5];
437122077Sume
438122077Sumechar *command_strings[5];
439122077Sumechar *commands[32];
440122077Sumechar *init_strings[22];
441122077Sume
442122077Sume#define MENU_WARN 1
443122077Sume
444122077Sume#define max_alpha_char 36
445122077Sume
446122077Sume/*
447122077Sume |	Declarations for strings for localization
448122077Sume */
449122077Sume
450122077Sumechar *com_win_message;		/* to be shown in com_win if no info window */
451122077Sumechar *no_file_string;
452122077Sumechar *ascii_code_str;
453269306Saechar *printer_msg_str;
454269306Saechar *command_str;
455269306Saechar *file_write_prompt_str;
456269306Saechar *file_read_prompt_str;
457270927Saechar *char_str;
458270927Saechar *unkn_cmd_str;
459269306Saechar *non_unique_cmd_msg;
460269306Saechar *line_num_str;
461271307Saechar *line_len_str;
462271307Saechar *current_file_str;
463271307Saechar *usage0;
464271307Saechar *usage1;
465271307Saechar *usage2;
466271307Saechar *usage3;
467271307Saechar *usage4;
468271307Saechar *file_is_dir_msg;
469271307Saechar *new_file_msg;
470271307Saechar *cant_open_msg;
471122077Sumechar *open_file_msg;
472122077Sumechar *file_read_fin_msg;
473122077Sumechar *reading_file_msg;
474122077Sumechar *read_only_msg;
475122077Sumechar *file_read_lines_msg;
476122077Sumechar *save_file_name_prompt;
477122077Sumechar *file_not_saved_msg;
478148385Sumechar *changes_made_prompt;
479122077Sumechar *yes_char;
480122077Sumechar *file_exists_prompt;
481122077Sumechar *create_file_fail_msg;
482122077Sumechar *writing_file_msg;
483122077Sumechar *file_written_msg;
484122077Sumechar *searching_msg;
485122077Sumechar *str_not_found_msg;
486122077Sumechar *search_prompt_str;
487122077Sumechar *exec_err_msg;
488122077Sumechar *continue_msg;
489122077Sumechar *menu_cancel_msg;
490122077Sumechar *menu_size_err_msg;
491122077Sumechar *press_any_key_msg;
492122077Sumechar *shell_prompt;
493122077Sumechar *formatting_msg;
494122077Sumechar *shell_echo_msg;
495122077Sumechar *spell_in_prog_msg;
496122077Sumechar *margin_prompt;
497122077Sumechar *restricted_msg;
498122077Sumechar *ON;
499122077Sumechar *OFF;
500148385Sumechar *HELP;
501122077Sumechar *WRITE;
502122077Sumechar *READ;
503122077Sumechar *LINE;
504122077Sumechar *FILE_str;
505122077Sumechar *CHARACTER;
506122077Sumechar *REDRAW;
50762587Sitojunchar *RESEQUENCE;
50862587Sitojunchar *AUTHOR;
509194971Srwatsonchar *VERSION;
510286001Saechar *CASE;
511249528Saechar *NOCASE;
512194777Sbzchar *EXPAND;
513194971Srwatsonchar *NOEXPAND;
514122077Sumechar *Exit_string;
515207276Sbzchar *QUIT_string;
516207276Sbzchar *INFO;
517207276Sbzchar *NOINFO;
518207276Sbzchar *MARGINS;
519207276Sbzchar *NOMARGINS;
520207276Sbzchar *AUTOFORMAT;
521207276Sbzchar *NOAUTOFORMAT;
522207276Sbzchar *Echo;
523207276Sbzchar *PRINTCOMMAND;
524207276Sbzchar *RIGHTMARGIN;
525207276Sbzchar *HIGHLIGHT;
526207276Sbzchar *NOHIGHLIGHT;
527286001Saechar *EIGHTBIT;
528249528Saechar *NOEIGHTBIT;
529207276Sbzchar *EMACS_string;
530207276Sbzchar *NOEMACS_string;
531207276Sbzchar *conf_dump_err_msg;
532148385Sumechar *conf_dump_success_msg;
533148385Sumechar *conf_not_saved_msg;
534148385Sumechar *ree_no_file_msg;
535207276Sbzchar *cancel_string;
536249546Saechar *menu_too_lrg_msg;
537249546Saechar *more_above_str, *more_below_str;
538249546Saechar *separator = "===============================================================================";
539249546Sae
540249546Saechar *chinese_cmd, *nochinese_cmd;
541249546Sae
542249546Sae#ifndef __STDC__
543249546Sae#ifndef HAS_STDLIB
544249546Saeextern char *malloc();
545249546Saeextern char *realloc();
546286001Saeextern char *getenv();
547194777SbzFILE *fopen();			/* declaration for open function	*/
548122077Sume#endif /* HAS_STDLIB */
549122077Sume#endif /* __STDC__ */
550171259Sdelphij
551293633Smelifaroint
552293633Smelifaromain(argc, argv)		/* beginning of main program		*/
553293633Smelifaroint argc;
554293633Smelifarochar *argv[];
555293633Smelifaro{
556293633Smelifaro	int counter;
557293633Smelifaro
558293633Smelifaro	for (counter = 1; counter < 24; counter++)
559293633Smelifaro		signal(counter, SIG_IGN);
560293633Smelifaro
561293633Smelifaro	signal(SIGCHLD, SIG_DFL);
562293633Smelifaro	signal(SIGSEGV, SIG_DFL);
563293633Smelifaro	signal(SIGINT, edit_abort);
564293633Smelifaro	d_char = malloc(3);	/* provide a buffer for multi-byte chars */
565293633Smelifaro	d_word = malloc(150);
566293633Smelifaro	*d_word = '\0';
567293633Smelifaro	d_line = NULL;
568293633Smelifaro	dlt_line = txtalloc();
569293633Smelifaro	dlt_line->line = d_line;
570293633Smelifaro	dlt_line->line_length = 0;
571293633Smelifaro	curr_line = first_line = txtalloc();
572293633Smelifaro	curr_line->line = point = malloc(10);
573293633Smelifaro	curr_line->line_length = 1;
574293633Smelifaro	curr_line->max_length = 10;
575293633Smelifaro	curr_line->prev_line = NULL;
576293633Smelifaro	curr_line->next_line = NULL;
577293633Smelifaro	curr_line->line_number  = 1;
578293633Smelifaro	srch_str = NULL;
579293633Smelifaro	u_srch_str = NULL;
580293633Smelifaro	position = 1;
581293633Smelifaro	scr_pos =0;
582293633Smelifaro	scr_vert = 0;
583293633Smelifaro	scr_horz = 0;
584293633Smelifaro	absolute_lin = 1;
585293633Smelifaro	bit_bucket = fopen("/dev/null", "w");
586293633Smelifaro	edit = TRUE;
587293633Smelifaro	gold = case_sen = FALSE;
588293633Smelifaro	shell_fork = TRUE;
589293633Smelifaro	strings_init();
590293633Smelifaro	ee_init();
591293633Smelifaro	if (argc > 0 )
592293633Smelifaro		get_options(argc, argv);
593293633Smelifaro	set_up_term();
594293633Smelifaro	if (right_margin == 0)
595293633Smelifaro		right_margin = COLS - 1;
596293633Smelifaro	if (top_of_stack == NULL)
597293633Smelifaro	{
598293633Smelifaro		if (restrict_mode())
599293633Smelifaro		{
600293633Smelifaro			wmove(com_win, 0, 0);
601293633Smelifaro			werase(com_win);
602293633Smelifaro			wprintw(com_win, ree_no_file_msg);
603293633Smelifaro			wrefresh(com_win);
604293633Smelifaro			edit_abort(0);
605293633Smelifaro		}
606293633Smelifaro		wprintw(com_win, no_file_string);
607293633Smelifaro		wrefresh(com_win);
608293633Smelifaro	}
609293633Smelifaro	else
610293633Smelifaro		check_fp();
611293633Smelifaro
612293633Smelifaro	clear_com_win = TRUE;
613293633Smelifaro
614293633Smelifaro	counter = 0;
615293633Smelifaro
616293633Smelifaro	while(edit)
617293633Smelifaro	{
618293633Smelifaro		/*
619293633Smelifaro		 |  display line and column information
620293633Smelifaro		 */
621293633Smelifaro		if (info_window)
622293633Smelifaro		{
623293633Smelifaro			if (!nohighlight)
624171259Sdelphij				wstandout(info_win);
625171259Sdelphij			wmove(info_win, 5, 0);
626122077Sume			wprintw(info_win, separator);
627171259Sdelphij			wmove(info_win, 5, 5);
628171259Sdelphij			wprintw(info_win, "line %d col %d lines from top %d ",
629232127Sbz			          curr_line->line_number, scr_horz, absolute_lin);
630122077Sume			wstandend(info_win);
631122077Sume			wrefresh(info_win);
632122077Sume		}
633122077Sume
634122077Sume		wrefresh(text_win);
635122077Sume		in = wgetch(text_win);
636122077Sume		if (in == -1)
637274334Sae			exit(0);  /* without this exit ee will go into an
638165118Sbz			             infinite loop if the network
639165118Sbz			             session detaches */
640122077Sume
641122077Sume		resize_check();
642122077Sume
643122077Sume		if (clear_com_win)
644122077Sume		{
645165118Sbz			clear_com_win = FALSE;
646122077Sume			wmove(com_win, 0, 0);
647122077Sume			werase(com_win);
648165118Sbz			if (!info_window)
649122077Sume			{
650122077Sume				wprintw(com_win, "%s", com_win_message);
651122077Sume			}
652122077Sume			wrefresh(com_win);
653122077Sume		}
654122077Sume
655122077Sume		if (in > 255)
656122077Sume			function_key();
657122077Sume		else if ((in == '\10') || (in == 127))
658148385Sume		{
659148385Sume			in = 8;		/* make sure key is set to backspace */
660122077Sume			delete(TRUE);
661148987Sume		}
662122077Sume		else if ((in > 31) || (in == 9))
663122077Sume			insert(in);
664122077Sume		else if ((in >= 0) && (in <= 31))
665122077Sume		{
666122077Sume			if (emacs_keys_mode)
667122077Sume				emacs_control();
668122077Sume			else
669274342Sae				control();
670274342Sae		}
671274342Sae	}
672274342Sae	return(0);
673274342Sae}
674274342Sae
675274342Saeunsigned char *
676274342Saeresiz_line(factor, rline, rpos)	/* resize the line to length + factor*/
677274334Saeint factor;		/* resize factor				*/
678274334Saestruct text *rline;	/* position in line				*/
679274334Saeint rpos;
680274342Sae{
681274334Sae	unsigned char *rpoint;
682274334Sae	int resiz_var;
683274334Sae
684274334Sae	rline->max_length += factor;
685274334Sae	rpoint = rline->line = realloc(rline->line, rline->max_length );
686274334Sae	for (resiz_var = 1 ; (resiz_var < rpos) ; resiz_var++)
687274334Sae		rpoint++;
688122077Sume	return(rpoint);
689122077Sume}
690122077Sume
691122077Sumevoid
692122077Sumeinsert(character)		/* insert character into line		*/
693122077Sumeint character;			/* new character			*/
694122077Sume{
695122077Sume	int counter;
696286195Sae	int value;
697122077Sume	unsigned char *temp;	/* temporary pointer			*/
698286195Sae	unsigned char *temp2;	/* temporary pointer			*/
699286195Sae
700286195Sae	if ((character == '\011') && (expand_tabs))
701286195Sae	{
702286195Sae		counter = len_char('\011', scr_horz);
703286195Sae		for (; counter > 0; counter--)
704286195Sae			insert(' ');
705286195Sae		if (auto_format)
706186119Sqingli			Auto_Format();
707286194Sae		return;
708186119Sqingli	}
709286195Sae	text_changes = TRUE;
710286195Sae	if ((curr_line->max_length - curr_line->line_length) < 5)
711286195Sae		point = resiz_line(10, curr_line, position);
712286195Sae	curr_line->line_length++;
713286195Sae	temp = point;
714286195Sae	counter = position;
715286195Sae	while (counter < curr_line->line_length)	/* find end of line */
716286195Sae	{
717122077Sume		counter++;
718286195Sae		temp++;
719232127Sbz	}
72062587Sitojun	temp++;			/* increase length of line by one	*/
721122077Sume	while (point < temp)
722286195Sae	{
723286195Sae		temp2=temp - 1;
724122077Sume		*temp= *temp2;	/* shift characters over by one		*/
725286195Sae		temp--;
726286195Sae	}
727286195Sae	*point = character;	/* insert new character			*/
728186119Sqingli	wclrtoeol(text_win);
72962587Sitojun	if (((character >= 0) && (character < ' ')) || (character >= 127)) /* check for TAB character*/
73062587Sitojun	{
73162587Sitojun		scr_pos = scr_horz += out_char(text_win, character, scr_horz);
732122077Sume		point++;
733122077Sume		position++;
734122077Sume	}
73562587Sitojun	else
73662587Sitojun	{
73762587Sitojun		waddch(text_win, character);
73889623Sume		scr_pos = ++scr_horz;
739122077Sume		point++;
74089623Sume		position ++;
741125436Sume	}
74262587Sitojun
743122077Sume	if ((observ_margins) && (right_margin < scr_pos))
74462587Sitojun	{
745122077Sume		counter = position;
74678064Sume		while (scr_pos > right_margin)
74778064Sume			prev_word();
74862587Sitojun		if (scr_pos == 0)
74962587Sitojun		{
75078064Sume			while (position < counter)
751122077Sume				right(TRUE);
752122122Sume		}
753122922Sandre		else
754178167Sqingli		{
755231852Sbz			counter -= position;
756231852Sbz			insert_line(TRUE);
757186119Sqingli			for (value = 0; value < counter; value++)
758231852Sbz				right(TRUE);
759231852Sbz		}
760121445Ssam	}
761121445Ssam
762186119Sqingli	if ((scr_horz - horiz_offset) > last_col)
76362587Sitojun	{
764186119Sqingli		horiz_offset += 8;
76562587Sitojun		midscreen(scr_vert, point);
766122077Sume	}
767122077Sume
76862587Sitojun	if ((auto_format) && (character == ' ') && (!formatted))
769122077Sume		Auto_Format();
770122077Sume	else if ((character != ' ') && (character != '\t'))
77162587Sitojun		formatted = FALSE;
77262587Sitojun
773122077Sume	draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
774122077Sume}
775122077Sume
776122077Sumevoid
777122077Sumedelete(disp)			/* delete character		*/
778122077Sumeint disp;
77962587Sitojun{
780122077Sume	unsigned char *tp;
781122077Sume	unsigned char *temp2;
782122077Sume	struct text *temp_buff;
783122077Sume	int temp_vert;
784122077Sume	int temp_pos;
785122077Sume	int del_width = 1;
786122077Sume
787122077Sume	if (point != curr_line->line)	/* if not at beginning of line	*/
788122077Sume	{
789122077Sume		text_changes = TRUE;
790122077Sume		temp2 = tp = point;
791146228Sgnn		if ((ee_chinese) && (position >= 2) && (*(point - 2) > 127))
792125436Sume		{
793122077Sume			del_width = 2;
794122077Sume		}
795122077Sume		tp -= del_width;
796122077Sume		point -= del_width;
797122077Sume		position -= del_width;
798122077Sume		temp_pos = position;
79962587Sitojun		curr_line->line_length -= del_width;
80062587Sitojun		if ((*tp < ' ') || (*tp >= 127))	/* check for TAB */
80162587Sitojun			scanline(tp);
802122077Sume		else
803122077Sume			scr_horz -= del_width;
804122077Sume		scr_pos = scr_horz;
805122077Sume		if (in == 8)
806122077Sume		{
807122077Sume			if (del_width == 1)
808122077Sume				*d_char = *point; /* save deleted character  */
809122077Sume			else
810122077Sume			{
811249294Sae				d_char[0] = *point;
812122077Sume				d_char[1] = *(point + 1);
813196864Sqingli			}
814122077Sume			d_char[del_width] = '\0';
815196864Sqingli		}
816196864Sqingli		while (temp_pos <= curr_line->line_length)
817196864Sqingli		{
818196864Sqingli			temp_pos++;
819196864Sqingli			*tp = *temp2;
820196864Sqingli			tp++;
821196864Sqingli			temp2++;
822196864Sqingli		}
823196864Sqingli		if (scr_horz < horiz_offset)
824196864Sqingli		{
825196864Sqingli			horiz_offset -= 8;
826196864Sqingli			midscreen(scr_vert, point);
827196864Sqingli		}
828196864Sqingli	}
829196864Sqingli	else if (curr_line->prev_line != NULL)
830196864Sqingli	{
831196864Sqingli		absolute_lin--;
832122077Sume		text_changes = TRUE;
833122077Sume		left(disp);			/* go to previous line	*/
834122077Sume		temp_buff = curr_line->next_line;
835122077Sume		point = resiz_line(temp_buff->line_length, curr_line, position);
83662587Sitojun		if (temp_buff->next_line != NULL)
83762587Sitojun			temp_buff->next_line->prev_line = curr_line;
838148385Sume		curr_line->next_line = temp_buff->next_line;
839171259Sdelphij		temp2 = temp_buff->line;
840293101Smelifaro		if (in == 8)
841232127Sbz		{
842148385Sume			d_char[0] = '\n';
843148385Sume			d_char[1] = '\0';
844148385Sume		}
845148385Sume		tp = point;
846293101Smelifaro		temp_pos = 1;
847148385Sume		while (temp_pos < temp_buff->line_length)
848231852Sbz		{
849231852Sbz			curr_line->line_length++;
850293101Smelifaro			temp_pos++;
851293101Smelifaro			*tp = *temp2;
852148385Sume			tp++;
853293101Smelifaro			temp2++;
854293101Smelifaro		}
855293101Smelifaro		*tp = '\0';
856293101Smelifaro		free(temp_buff->line);
857293101Smelifaro		free(temp_buff);
858293101Smelifaro		temp_buff = curr_line;
859293101Smelifaro		temp_vert = scr_vert;
860293101Smelifaro		scr_pos = scr_horz;
861231852Sbz		if (scr_vert < last_line)
862231852Sbz		{
863231852Sbz			wmove(text_win, scr_vert + 1, 0);
864231852Sbz			wdeleteln(text_win);
865231852Sbz		}
866148385Sume		while ((temp_buff != NULL) && (temp_vert < last_line))
867148385Sume		{
868148385Sume			temp_buff = temp_buff->next_line;
869148385Sume			temp_vert++;
870148385Sume		}
871148385Sume		if ((temp_vert == last_line) && (temp_buff != NULL))
872148385Sume		{
873148385Sume			tp = temp_buff->line;
874148385Sume			wmove(text_win, last_line,0);
875148385Sume			wclrtobot(text_win);
876148385Sume			draw_line(last_line, 0, tp, 1, temp_buff->line_length);
877148385Sume			wmove(text_win, scr_vert, (scr_horz - horiz_offset));
878148385Sume		}
879148385Sume	}
880148385Sume	draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
881148385Sume	formatted = FALSE;
882148385Sume}
883148385Sume
884148385Sumevoid
885148385Sumescanline(pos)	/* find the proper horizontal position for the pointer	*/
886148385Sumeunsigned char *pos;
887293101Smelifaro{
888293101Smelifaro	int temp;
889293101Smelifaro	unsigned char *ptr;
890148385Sume
891148385Sume	ptr = curr_line->line;
892148385Sume	temp = 0;
893148385Sume	while (ptr < pos)
894148385Sume	{
895171259Sdelphij		if (*ptr <= 8)
896231852Sbz			temp += 2;
897231852Sbz		else if (*ptr == 9)
898231852Sbz			temp += tabshift(temp);
899231852Sbz		else if ((*ptr >= 10) && (*ptr <= 31))
900171259Sdelphij			temp += 2;
901148385Sume		else if ((*ptr >= 32) && (*ptr < 127))
902171259Sdelphij			temp++;
903171259Sdelphij		else if (*ptr == 127)
904186119Sqingli			temp += 2;
905148385Sume		else if (!eightbit)
906171259Sdelphij			temp += 5;
907148385Sume		else
908231852Sbz			temp++;
909148385Sume		ptr++;
910148385Sume	}
911231852Sbz	scr_horz = temp;
912231852Sbz	if ((scr_horz - horiz_offset) > last_col)
913231852Sbz	{
914231852Sbz		horiz_offset = (scr_horz - (scr_horz % 8)) - (COLS - 8);
915232127Sbz		midscreen(scr_vert, point);
916231852Sbz	}
917231852Sbz	else if (scr_horz < horiz_offset)
918231852Sbz	{
919231852Sbz		horiz_offset = max(0, (scr_horz - (scr_horz % 8)));
920231852Sbz		midscreen(scr_vert, point);
921231852Sbz	}
922231852Sbz}
92362587Sitojun
92462587Sitojunint
92562587Sitojuntabshift(temp_int)		/* give the number of spaces to shift	*/
92662587Sitojunint temp_int;
92762587Sitojun{
92862587Sitojun	int leftover;
929122922Sandre
93062587Sitojun	leftover = ((temp_int + 1) % 8);
931186141Sbz	if (leftover == 0)
93262587Sitojun		return (1);
933171259Sdelphij	else
93462587Sitojun		return (9 - leftover);
935120856Sume}
93662587Sitojun
937121161Sumeint
938122922Sandreout_char(window, character, column)	/* output non-printing character */
939292015SmelifaroWINDOW *window;
940292015Smelifarochar character;
941292015Smelifaroint column;
942292015Smelifaro{
943122922Sandre	int i1, i2;
944292015Smelifaro	char *string;
945292015Smelifaro	char string2[8];
946292015Smelifaro
947292015Smelifaro	if (character == TAB)
948292015Smelifaro	{
949235955Sbz		i1 = tabshift(column);
950122922Sandre		for (i2 = 0;
951181803Sbz		  (i2 < i1) && (((column+i2+1)-horiz_offset) < last_col); i2++)
95262587Sitojun		{
95362587Sitojun			waddch(window, ' ');
95462587Sitojun		}
95562587Sitojun		return(i1);
95662587Sitojun	}
95762587Sitojun	else if ((character >= '\0') && (character < ' '))
95862587Sitojun	{
959171259Sdelphij		string = table[(int) character];
96062587Sitojun	}
96162587Sitojun	else if ((character < 0) || (character >= 127))
962219579Sbz	{
963222215Srwatson		if (character == 127)
964219579Sbz			string = "^?";
96562587Sitojun		else if (!eightbit)
966219579Sbz		{
96762587Sitojun			sprintf(string2, "<%d>", (character < 0) ? (character + 256) : character);
968178285Srwatson			string = string2;
969222488Srwatson		}
970158011Srwatson		else
971188144Sjamie		{
972188144Sjamie			waddch(window, (char)character );
973188144Sjamie			return(1);
974188144Sjamie		}
975185435Sbz	}
97662587Sitojun	else
97762587Sitojun	{
978222215Srwatson		waddch(window, (char)character);
97962587Sitojun		return(1);
98062587Sitojun	}
98162587Sitojun	for (i2 = 0; (string[i2] != '\0') && (((column+i2+1)-horiz_offset) < last_col); i2++)
982222215Srwatson		waddch(window, string[i2]);
983219579Sbz	return(strlen(string));
984219579Sbz}
985184096Sbz
98662587Sitojunint
98762587Sitojunlen_char(character, column)	/* return the length of the character	*/
98862587Sitojunchar character;
98962587Sitojunint column;	/* the column must be known to provide spacing for tabs	*/
99062587Sitojun{
99162587Sitojun	int length;
99262587Sitojun
993120856Sume	if (character == '\t')
99462587Sitojun		length = tabshift(column);
99562587Sitojun	else if ((character >= 0) && (character < 32))
99678064Sume		length = 2;
997171259Sdelphij	else if ((character >= 32) && (character <= 126))
998121742Sume		length = 1;
999121742Sume	else if (character == 127)
1000121742Sume		length = 2;
1001121742Sume	else if (((character > 126) || (character < 0)) && (!eightbit))
1002121742Sume		length = 5;
1003181803Sbz	else
1004181803Sbz		length = 1;
1005190787Szec
1006190787Szec	return(length);
1007190787Szec}
1008190787Szec
1009190787Szecvoid
1010190787Szecdraw_line(vertical, horiz, ptr, t_pos, length)	/* redraw line from current position */
1011121742Sumeint vertical;	/* current vertical position on screen		*/
1012121742Sumeint horiz;	/* current horizontal position on screen	*/
1013122077Sumeunsigned char *ptr;	/* pointer to line				*/
1014171259Sdelphijint t_pos;	/* current position (offset in bytes) from bol	*/
1015122077Sumeint length;	/* length (in bytes) of line			*/
1016122077Sume{
1017122077Sume	int d;		/* partial length of special or tab char to display  */
1018122077Sume	unsigned char *temp;	/* temporary pointer to position in line	     */
1019122077Sume	int abs_column;	/* offset in screen units from begin of line	     */
1020122077Sume	int column;	/* horizontal position on screen		     */
1021122077Sume	int row;	/* vertical position on screen			     */
1022181803Sbz	int posit;	/* temporary position indicator within line	     */
1023122077Sume
1024122077Sume	abs_column = horiz;
1025122077Sume	column = horiz - horiz_offset;
1026122077Sume	row = vertical;
1027122077Sume	temp = ptr;
1028122077Sume	d = 0;
1029122077Sume	posit = t_pos;
1030121742Sume	if (column < 0)
1031121742Sume	{
1032121742Sume		wmove(text_win, row, 0);
1033121742Sume		wclrtoeol(text_win);
1034121742Sume	}
1035121742Sume	while (column < 0)
1036121742Sume	{
1037121742Sume		d = len_char(*temp, abs_column);
1038121742Sume		abs_column += d;
1039227309Sed		column += d;
1040121742Sume		posit++;
1041121742Sume		temp++;
1042121742Sume	}
1043121742Sume	wmove(text_win, row, column);
1044121742Sume	wclrtoeol(text_win);
1045121742Sume	while ((posit < length) && (column <= last_col))
1046121742Sume	{
1047121742Sume		if ((*temp < 32) || (*temp >= 127))
1048121742Sume		{
1049121742Sume			column += len_char(*temp, abs_column);
1050121742Sume			abs_column += out_char(text_win, *temp, abs_column);
1051121742Sume		}
1052121742Sume		else
1053121742Sume		{
1054121742Sume			abs_column++;
1055121742Sume			column++;
1056121742Sume			waddch(text_win, *temp);
1057171259Sdelphij		}
1058121742Sume		posit++;
1059121742Sume		temp++;
1060121742Sume	}
1061121742Sume	if (column < last_col)
1062121742Sume		wclrtoeol(text_win);
1063121742Sume	wmove(text_win, vertical, (horiz - horiz_offset));
1064121742Sume}
1065121742Sume
1066121742Sumevoid
1067121742Sumeinsert_line(disp)			/* insert new line		*/
1068121742Sumeint disp;
1069121742Sume{
1070121742Sume	int temp_pos;
1071121742Sume	int temp_pos2;
1072260458Smelifaro	unsigned char *temp;
1073121742Sume	unsigned char *extra;
1074121742Sume	struct text *temp_nod;
1075121742Sume
1076121742Sume	text_changes = TRUE;
1077121742Sume	wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1078121742Sume	wclrtoeol(text_win);
1079121742Sume	temp_nod= txtalloc();
1080121742Sume	temp_nod->line = extra= malloc(10);
1081121742Sume	temp_nod->line_length = 1;
1082121742Sume	temp_nod->max_length = 10;
1083121742Sume	temp_nod->line_number = curr_line->line_number + 1;
1084121742Sume	temp_nod->next_line = curr_line->next_line;
1085121742Sume	if (temp_nod->next_line != NULL)
1086121742Sume		temp_nod->next_line->prev_line = temp_nod;
1087121742Sume	temp_nod->prev_line = curr_line;
1088121742Sume	curr_line->next_line = temp_nod;
1089121742Sume	temp_pos2 = position;
1090121742Sume	temp = point;
1091121742Sume	if (temp_pos2 < curr_line->line_length)
1092121742Sume	{
1093121742Sume		temp_pos = 1;
1094121742Sume		while (temp_pos2 < curr_line->line_length)
1095121742Sume		{
1096121742Sume			if ((temp_nod->max_length - temp_nod->line_length)< 5)
1097121742Sume				extra = resiz_line(10, temp_nod, temp_pos);
1098215701Sdim			temp_nod->line_length++;
1099195727Srwatson			temp_pos++;
1100121742Sume			temp_pos2++;
1101121742Sume			*extra= *temp;
1102171259Sdelphij			extra++;
1103121742Sume			temp++;
1104171259Sdelphij		}
1105181803Sbz		temp=point;
1106121742Sume		*temp = '\0';
1107121742Sume		temp = resiz_line((1 - temp_nod->line_length), curr_line, position);
1108121742Sume		curr_line->line_length = 1 + temp - curr_line->line;
1109171259Sdelphij	}
1110121742Sume	curr_line->line_length = position;
1111121742Sume	absolute_lin++;
1112121742Sume	curr_line = temp_nod;
1113184205Sdes	*extra = '\0';
1114121750Sume	position = 1;
1115149200Sume	point= curr_line->line;
1116121742Sume	if (disp)
1117121742Sume	{
1118121742Sume		if (scr_vert < last_line)
1119181803Sbz		{
1120151478Ssuz			scr_vert++;
1121151478Ssuz			wclrtoeol(text_win);
1122151478Ssuz			wmove(text_win, scr_vert, 0);
1123151478Ssuz			winsertln(text_win);
1124121750Sume		}
1125149200Sume		else
1126184205Sdes		{
1127121742Sume			wmove(text_win, 0,0);
1128121742Sume			wdeleteln(text_win);
1129121742Sume			wmove(text_win, last_line,0);
1130121742Sume			wclrtobot(text_win);
1131121742Sume		}
1132121742Sume		scr_pos = scr_horz = 0;
1133121742Sume		if (horiz_offset)
1134121742Sume		{
1135121742Sume			horiz_offset = 0;
1136181803Sbz			midscreen(scr_vert, point);
1137121742Sume		}
1138149200Sume		draw_line(scr_vert, scr_horz, point, position,
1139121742Sume			curr_line->line_length);
1140121742Sume	}
1141121742Sume}
1142121742Sume
1143121742Sumestruct text *txtalloc()		/* allocate space for line structure	*/
1144171259Sdelphij{
1145121742Sume	return((struct text *) malloc(sizeof( struct text)));
1146121742Sume}
1147121742Sume
1148149200Sumestruct files *name_alloc()	/* allocate space for file name list node */
1149121742Sume{
1150121742Sume	return((struct files *) malloc(sizeof( struct files)));
1151121742Sume}
1152181803Sbz
1153151478Ssuzunsigned char *next_word(string)		/* move to next word in string		*/
1154151478Ssuzunsigned char *string;
1155151478Ssuz{
1156151478Ssuz	while ((*string != '\0') && ((*string != 32) && (*string != 9)))
1157121742Sume		string++;
1158121742Sume	while ((*string != '\0') && ((*string == 32) || (*string == 9)))
1159121742Sume		string++;
1160121750Sume	return(string);
1161121750Sume}
1162149200Sume
1163121742Sumevoid
1164121750Sumeprev_word()	/* move to start of previous word in text	*/
1165121742Sume{
1166181803Sbz	if (position != 1)
1167121742Sume	{
1168149200Sume		if ((position != 1) && ((point[-1] == ' ') || (point[-1] == '\t')))
1169249398Sae		{	/* if at the start of a word	*/
1170121742Sume			while ((position != 1) && ((*point != ' ') && (*point != '\t')))
1171121742Sume				left(TRUE);
1172121742Sume		}
1173121742Sume		while ((position != 1) && ((*point == ' ') || (*point == '\t')))
1174121742Sume			left(TRUE);
1175242938Sobrien		while ((position != 1) && ((*point != ' ') && (*point != '\t')))
1176121742Sume			left(TRUE);
1177121742Sume		if ((position != 1) && ((*point == ' ') || (*point == '\t')))
1178121742Sume			right(TRUE);
1179121742Sume	}
1180149200Sume	else
1181181803Sbz		left(TRUE);
1182149200Sume}
1183149200Sume
1184121742Sumevoid
1185149200Sumecontrol()			/* use control for commands		*/
1186121742Sume{
1187149200Sume	char *string;
1188121742Sume
1189121742Sume	if (in == 1)		/* control a	*/
1190121742Sume	{
1191121742Sume		string = get_string(ascii_code_str, TRUE);
1192171259Sdelphij		if (*string != '\0')
1193121742Sume		{
1194121742Sume			in = atoi(string);
1195121742Sume			wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1196121742Sume			insert(in);
1197121742Sume		}
1198121742Sume		free(string);
1199121742Sume	}
1200121742Sume	else if (in == 2)	/* control b	*/
1201122077Sume		bottom();
1202122077Sume	else if (in == 3)	/* control c	*/
1203171259Sdelphij	{
1204122077Sume		command_prompt();
1205122077Sume	}
1206122077Sume	else if (in == 4)	/* control d	*/
1207122077Sume		down();
1208122077Sume	else if (in == 5)	/* control e	*/
1209122077Sume		search_prompt();
1210181803Sbz	else if (in == 6)	/* control f	*/
1211122077Sume		undel_char();
1212122077Sume	else if (in == 7)	/* control g	*/
1213122077Sume		bol();
1214122077Sume	else if (in == 8)	/* control h	*/
1215122077Sume		delete(TRUE);
1216122077Sume	else if (in == 9)	/* control i	*/
1217122077Sume		;
1218122077Sume	else if (in == 10)	/* control j	*/
1219122077Sume		insert_line(TRUE);
1220122077Sume	else if (in == 11)	/* control k	*/
1221122077Sume		del_char();
1222122077Sume	else if (in == 12)	/* control l	*/
1223122077Sume		left(TRUE);
1224122077Sume	else if (in == 13)	/* control m	*/
1225122077Sume		insert_line(TRUE);
1226122077Sume	else if (in == 14)	/* control n	*/
1227122077Sume		move_rel("d", max(5, (last_line - 5)));
1228122077Sume	else if (in == 15)	/* control o	*/
1229122077Sume		eol();
1230122077Sume	else if (in == 16)	/* control p	*/
1231122077Sume		move_rel("u", max(5, (last_line - 5)));
1232122077Sume	else if (in == 17)	/* control q	*/
1233122077Sume		;
1234122077Sume	else if (in == 18)	/* control r	*/
1235122077Sume		right(TRUE);
1236122077Sume	else if (in == 19)	/* control s	*/
1237122077Sume		;
1238122077Sume	else if (in == 20)	/* control t	*/
1239122077Sume		top();
1240122077Sume	else if (in == 21)	/* control u	*/
1241122077Sume		up();
1242122077Sume	else if (in == 22)	/* control v	*/
1243122077Sume		undel_word();
1244122077Sume	else if (in == 23)	/* control w	*/
1245		del_word();
1246	else if (in == 24)	/* control x	*/
1247		search(TRUE);
1248	else if (in == 25)	/* control y	*/
1249		del_line();
1250	else if (in == 26)	/* control z	*/
1251		undel_line();
1252	else if (in == 27)	/* control [ (escape)	*/
1253	{
1254		menu_op(main_menu);
1255	}
1256}
1257
1258/*
1259 |	Emacs control-key bindings
1260 */
1261
1262void
1263emacs_control()
1264{
1265	char *string;
1266
1267	if (in == 1)		/* control a	*/
1268		bol();
1269	else if (in == 2)	/* control b	*/
1270		left(TRUE);
1271	else if (in == 3)	/* control c	*/
1272	{
1273		command_prompt();
1274	}
1275	else if (in == 4)	/* control d	*/
1276		del_char();
1277	else if (in == 5)	/* control e	*/
1278		eol();
1279	else if (in == 6)	/* control f	*/
1280		right(TRUE);
1281	else if (in == 7)	/* control g	*/
1282		move_rel("u", max(5, (last_line - 5)));
1283	else if (in == 8)	/* control h	*/
1284		delete(TRUE);
1285	else if (in == 9)	/* control i	*/
1286		;
1287	else if (in == 10)	/* control j	*/
1288		undel_char();
1289	else if (in == 11)	/* control k	*/
1290		del_line();
1291	else if (in == 12)	/* control l	*/
1292		undel_line();
1293	else if (in == 13)	/* control m	*/
1294		insert_line(TRUE);
1295	else if (in == 14)	/* control n	*/
1296		down();
1297	else if (in == 15)	/* control o	*/
1298	{
1299		string = get_string(ascii_code_str, TRUE);
1300		if (*string != '\0')
1301		{
1302			in = atoi(string);
1303			wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1304			insert(in);
1305		}
1306		free(string);
1307	}
1308	else if (in == 16)	/* control p	*/
1309		up();
1310	else if (in == 17)	/* control q	*/
1311		;
1312	else if (in == 18)	/* control r	*/
1313		undel_word();
1314	else if (in == 19)	/* control s	*/
1315		;
1316	else if (in == 20)	/* control t	*/
1317		top();
1318	else if (in == 21)	/* control u	*/
1319		bottom();
1320	else if (in == 22)	/* control v	*/
1321		move_rel("d", max(5, (last_line - 5)));
1322	else if (in == 23)	/* control w	*/
1323		del_word();
1324	else if (in == 24)	/* control x	*/
1325		search(TRUE);
1326	else if (in == 25)	/* control y	*/
1327		search_prompt();
1328	else if (in == 26)	/* control z	*/
1329		adv_word();
1330	else if (in == 27)	/* control [ (escape)	*/
1331	{
1332		menu_op(main_menu);
1333	}
1334}
1335
1336void
1337bottom()			/* go to bottom of file			*/
1338{
1339	while (curr_line->next_line != NULL)
1340	{
1341		curr_line = curr_line->next_line;
1342		absolute_lin++;
1343	}
1344	point = curr_line->line;
1345	if (horiz_offset)
1346		horiz_offset = 0;
1347	position = 1;
1348	midscreen(last_line, point);
1349	scr_pos = scr_horz;
1350}
1351
1352void
1353top()				/* go to top of file			*/
1354{
1355	while (curr_line->prev_line != NULL)
1356	{
1357		curr_line = curr_line->prev_line;
1358		absolute_lin--;
1359	}
1360	point = curr_line->line;
1361	if (horiz_offset)
1362		horiz_offset = 0;
1363	position = 1;
1364	midscreen(0, point);
1365	scr_pos = scr_horz;
1366}
1367
1368void
1369nextline()			/* move pointers to start of next line	*/
1370{
1371	curr_line = curr_line->next_line;
1372	absolute_lin++;
1373	point = curr_line->line;
1374	position = 1;
1375	if (scr_vert == last_line)
1376	{
1377		wmove(text_win, 0,0);
1378		wdeleteln(text_win);
1379		wmove(text_win, last_line,0);
1380		wclrtobot(text_win);
1381		draw_line(last_line,0,point,1,curr_line->line_length);
1382	}
1383	else
1384		scr_vert++;
1385}
1386
1387void
1388prevline()			/* move pointers to start of previous line*/
1389{
1390	curr_line = curr_line->prev_line;
1391	absolute_lin--;
1392	point = curr_line->line;
1393	position = 1;
1394	if (scr_vert == 0)
1395	{
1396		winsertln(text_win);
1397		draw_line(0,0,point,1,curr_line->line_length);
1398	}
1399	else
1400		scr_vert--;
1401	while (position < curr_line->line_length)
1402	{
1403		position++;
1404		point++;
1405	}
1406}
1407
1408void
1409left(disp)				/* move left one character	*/
1410int disp;
1411{
1412	if (point != curr_line->line)	/* if not at begin of line	*/
1413	{
1414		if ((ee_chinese) && (position >= 2) && (*(point - 2) > 127))
1415		{
1416			point--;
1417			position--;
1418		}
1419		point--;
1420		position--;
1421		scanline(point);
1422		wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1423		scr_pos = scr_horz;
1424	}
1425	else if (curr_line->prev_line != NULL)
1426	{
1427		if (!disp)
1428		{
1429			absolute_lin--;
1430			curr_line = curr_line->prev_line;
1431			point = curr_line->line + curr_line->line_length;
1432			position = curr_line->line_length;
1433			return;
1434		}
1435		position = 1;
1436		prevline();
1437		scanline(point);
1438		scr_pos = scr_horz;
1439		wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1440	}
1441}
1442
1443void
1444right(disp)				/* move right one character	*/
1445int disp;
1446{
1447	if (position < curr_line->line_length)
1448	{
1449		if ((ee_chinese) && (*point > 127) &&
1450		    ((curr_line->line_length - position) >= 2))
1451		{
1452			point++;
1453			position++;
1454		}
1455		point++;
1456		position++;
1457		scanline(point);
1458		wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1459		scr_pos = scr_horz;
1460	}
1461	else if (curr_line->next_line != NULL)
1462	{
1463		if (!disp)
1464		{
1465			absolute_lin++;
1466			curr_line = curr_line->next_line;
1467			point = curr_line->line;
1468			position = 1;
1469			return;
1470		}
1471		nextline();
1472		scr_pos = scr_horz = 0;
1473		if (horiz_offset)
1474		{
1475			horiz_offset = 0;
1476			midscreen(scr_vert, point);
1477		}
1478		wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1479		position = 1;
1480	}
1481}
1482
1483void
1484find_pos()		/* move to the same column as on other line	*/
1485{
1486	scr_horz = 0;
1487	position = 1;
1488	while ((scr_horz < scr_pos) && (position < curr_line->line_length))
1489	{
1490		if (*point == 9)
1491			scr_horz += tabshift(scr_horz);
1492		else if (*point < ' ')
1493			scr_horz += 2;
1494		else if ((ee_chinese) && (*point > 127) &&
1495		    ((curr_line->line_length - position) >= 2))
1496		{
1497			scr_horz += 2;
1498			point++;
1499			position++;
1500		}
1501		else
1502			scr_horz++;
1503		position++;
1504		point++;
1505	}
1506	if ((scr_horz - horiz_offset) > last_col)
1507	{
1508		horiz_offset = (scr_horz - (scr_horz % 8)) - (COLS - 8);
1509		midscreen(scr_vert, point);
1510	}
1511	else if (scr_horz < horiz_offset)
1512	{
1513		horiz_offset = max(0, (scr_horz - (scr_horz % 8)));
1514		midscreen(scr_vert, point);
1515	}
1516	wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1517}
1518
1519void
1520up()					/* move up one line		*/
1521{
1522	if (curr_line->prev_line != NULL)
1523	{
1524		prevline();
1525		point = curr_line->line;
1526		find_pos();
1527	}
1528}
1529
1530void
1531down()					/* move down one line		*/
1532{
1533	if (curr_line->next_line != NULL)
1534	{
1535		nextline();
1536		find_pos();
1537	}
1538}
1539
1540void
1541function_key()				/* process function key		*/
1542{
1543	if (in == KEY_LEFT)
1544		left(TRUE);
1545	else if (in == KEY_RIGHT)
1546		right(TRUE);
1547	else if (in == KEY_HOME)
1548		bol();
1549	else if (in == KEY_END)
1550		eol();
1551	else if (in == KEY_UP)
1552		up();
1553	else if (in == KEY_DOWN)
1554		down();
1555	else if (in == KEY_NPAGE)
1556		move_rel("d", max( 5, (last_line - 5)));
1557	else if (in == KEY_PPAGE)
1558		move_rel("u", max(5, (last_line - 5)));
1559	else if (in == KEY_DL)
1560		del_line();
1561	else if (in == KEY_DC)
1562		del_char();
1563	else if (in == KEY_BACKSPACE)
1564		delete(TRUE);
1565	else if (in == KEY_IL)
1566	{		/* insert a line before current line	*/
1567		insert_line(TRUE);
1568		left(TRUE);
1569	}
1570	else if (in == KEY_F(1))
1571		gold = !gold;
1572	else if (in == KEY_F(2))
1573	{
1574		if (gold)
1575		{
1576			gold = FALSE;
1577			undel_line();
1578		}
1579		else
1580			undel_char();
1581	}
1582	else if (in == KEY_F(3))
1583	{
1584		if (gold)
1585		{
1586			gold = FALSE;
1587			undel_word();
1588		}
1589		else
1590			del_word();
1591	}
1592	else if (in == KEY_F(4))
1593	{
1594		if (gold)
1595		{
1596			gold = FALSE;
1597			paint_info_win();
1598			midscreen(scr_vert, point);
1599		}
1600		else
1601			adv_word();
1602	}
1603	else if (in == KEY_F(5))
1604	{
1605		if (gold)
1606		{
1607			gold = FALSE;
1608			search_prompt();
1609		}
1610		else
1611			search(TRUE);
1612	}
1613	else if (in == KEY_F(6))
1614	{
1615		if (gold)
1616		{
1617			gold = FALSE;
1618			bottom();
1619		}
1620		else
1621			top();
1622	}
1623	else if (in == KEY_F(7))
1624	{
1625		if (gold)
1626		{
1627			gold = FALSE;
1628			eol();
1629		}
1630		else
1631			bol();
1632	}
1633	else if (in == KEY_F(8))
1634	{
1635		if (gold)
1636		{
1637			gold = FALSE;
1638			command_prompt();
1639		}
1640		else
1641			adv_line();
1642	}
1643}
1644
1645void
1646print_buffer()
1647{
1648	char buffer[256];
1649
1650	sprintf(buffer, ">!%s", print_command);
1651	wmove(com_win, 0, 0);
1652	wclrtoeol(com_win);
1653	wprintw(com_win, printer_msg_str, print_command);
1654	wrefresh(com_win);
1655	command(buffer);
1656}
1657
1658void
1659command_prompt()
1660{
1661	char *cmd_str;
1662	int result;
1663
1664	info_type = COMMANDS;
1665	paint_info_win();
1666	cmd_str = get_string(command_str, TRUE);
1667	if ((result = unique_test(cmd_str, commands)) != 1)
1668	{
1669		werase(com_win);
1670		wmove(com_win, 0, 0);
1671		if (result == 0)
1672			wprintw(com_win, unkn_cmd_str, cmd_str);
1673		else
1674			wprintw(com_win, non_unique_cmd_msg);
1675
1676		wrefresh(com_win);
1677
1678		info_type = CONTROL_KEYS;
1679		paint_info_win();
1680
1681		if (cmd_str != NULL)
1682			free(cmd_str);
1683		return;
1684	}
1685	command(cmd_str);
1686	wrefresh(com_win);
1687	wmove(text_win, scr_vert, (scr_horz - horiz_offset));
1688	info_type = CONTROL_KEYS;
1689	paint_info_win();
1690	if (cmd_str != NULL)
1691		free(cmd_str);
1692}
1693
1694void
1695command(cmd_str1)		/* process commands from keyboard	*/
1696char *cmd_str1;
1697{
1698	char *cmd_str2 = NULL;
1699	char *cmd_str = cmd_str1;
1700
1701	clear_com_win = TRUE;
1702	if (compare(cmd_str, HELP, FALSE))
1703		help();
1704	else if (compare(cmd_str, WRITE, FALSE))
1705	{
1706		if (restrict_mode())
1707		{
1708			return;
1709		}
1710		cmd_str = next_word(cmd_str);
1711		if (*cmd_str == '\0')
1712		{
1713			cmd_str = cmd_str2 = get_string(file_write_prompt_str, TRUE);
1714		}
1715		tmp_file = resolve_name(cmd_str);
1716		write_file(tmp_file, 1);
1717		if (tmp_file != cmd_str)
1718			free(tmp_file);
1719	}
1720	else if (compare(cmd_str, READ, FALSE))
1721	{
1722		if (restrict_mode())
1723		{
1724			return;
1725		}
1726		cmd_str = next_word(cmd_str);
1727		if (*cmd_str == '\0')
1728		{
1729			cmd_str = cmd_str2 = get_string(file_read_prompt_str, TRUE);
1730		}
1731		tmp_file = cmd_str;
1732		recv_file = TRUE;
1733		tmp_file = resolve_name(cmd_str);
1734		check_fp();
1735		if (tmp_file != cmd_str)
1736			free(tmp_file);
1737	}
1738	else if (compare(cmd_str, LINE, FALSE))
1739	{
1740		wmove(com_win, 0, 0);
1741		wclrtoeol(com_win);
1742		wprintw(com_win, line_num_str, curr_line->line_number);
1743		wprintw(com_win, line_len_str, curr_line->line_length);
1744	}
1745	else if (compare(cmd_str, FILE_str, FALSE))
1746	{
1747		wmove(com_win, 0, 0);
1748		wclrtoeol(com_win);
1749		if (in_file_name == NULL)
1750			wprintw(com_win, no_file_string);
1751		else
1752			wprintw(com_win, current_file_str, in_file_name);
1753	}
1754	else if ((*cmd_str >= '0') && (*cmd_str <= '9'))
1755		goto_line(cmd_str);
1756	else if (compare(cmd_str, CHARACTER, FALSE))
1757	{
1758		wmove(com_win, 0, 0);
1759		wclrtoeol(com_win);
1760		wprintw(com_win, char_str, *point);
1761	}
1762	else if (compare(cmd_str, REDRAW, FALSE))
1763		redraw();
1764	else if (compare(cmd_str, RESEQUENCE, FALSE))
1765	{
1766		tmp_line = first_line->next_line;
1767		while (tmp_line != NULL)
1768		{
1769		tmp_line->line_number = tmp_line->prev_line->line_number + 1;
1770			tmp_line = tmp_line->next_line;
1771		}
1772	}
1773	else if (compare(cmd_str, AUTHOR, FALSE))
1774	{
1775		wmove(com_win, 0, 0);
1776		wclrtoeol(com_win);
1777		wprintw(com_win, "written by Hugh Mahon");
1778	}
1779	else if (compare(cmd_str, VERSION, FALSE))
1780	{
1781		wmove(com_win, 0, 0);
1782		wclrtoeol(com_win);
1783		wprintw(com_win, "%s", version);
1784	}
1785	else if (compare(cmd_str, CASE, FALSE))
1786		case_sen = TRUE;
1787	else if (compare(cmd_str, NOCASE, FALSE))
1788		case_sen = FALSE;
1789	else if (compare(cmd_str, EXPAND, FALSE))
1790		expand_tabs = TRUE;
1791	else if (compare(cmd_str, NOEXPAND, FALSE))
1792		expand_tabs = FALSE;
1793	else if (compare(cmd_str, Exit_string, FALSE))
1794		finish();
1795	else if (compare(cmd_str, chinese_cmd, FALSE))
1796	{
1797		ee_chinese = TRUE;
1798#ifdef NCURSE
1799		nc_setattrib(A_NC_BIG5);
1800#endif /* NCURSE */
1801	}
1802	else if (compare(cmd_str, nochinese_cmd, FALSE))
1803	{
1804		ee_chinese = FALSE;
1805#ifdef NCURSE
1806		nc_clearattrib(A_NC_BIG5);
1807#endif /* NCURSE */
1808	}
1809	else if (compare(cmd_str, QUIT_string, FALSE))
1810		quit(0);
1811	else if (*cmd_str == '!')
1812	{
1813		cmd_str++;
1814		if ((*cmd_str == ' ') || (*cmd_str == 9))
1815			cmd_str = next_word(cmd_str);
1816		sh_command(cmd_str);
1817	}
1818	else if ((*cmd_str == '<') && (!in_pipe))
1819	{
1820		in_pipe = TRUE;
1821		shell_fork = FALSE;
1822		cmd_str++;
1823		if ((*cmd_str == ' ') || (*cmd_str == '\t'))
1824			cmd_str = next_word(cmd_str);
1825		command(cmd_str);
1826		in_pipe = FALSE;
1827		shell_fork = TRUE;
1828	}
1829	else if ((*cmd_str == '>') && (!out_pipe))
1830	{
1831		out_pipe = TRUE;
1832		cmd_str++;
1833		if ((*cmd_str == ' ') || (*cmd_str == '\t'))
1834			cmd_str = next_word(cmd_str);
1835		command(cmd_str);
1836		out_pipe = FALSE;
1837	}
1838	else
1839	{
1840		wmove(com_win, 0, 0);
1841		wclrtoeol(com_win);
1842		wprintw(com_win, unkn_cmd_str, cmd_str);
1843	}
1844	if (cmd_str2 != NULL)
1845		free(cmd_str2);
1846}
1847
1848int
1849scan(line, offset, column)	/* determine horizontal position for get_string	*/
1850char *line;
1851int offset;
1852int column;
1853{
1854	char *stemp;
1855	int i;
1856	int j;
1857
1858	stemp = line;
1859	i = 0;
1860	j = column;
1861	while (i < offset)
1862	{
1863		i++;
1864		j += len_char(*stemp, j);
1865		stemp++;
1866	}
1867	return(j);
1868}
1869
1870char *
1871get_string(prompt, advance)	/* read string from input on command line */
1872char *prompt;		/* string containing user prompt message	*/
1873int advance;		/* if true, skip leading spaces and tabs	*/
1874{
1875	char *string;
1876	char *tmp_string;
1877	char *nam_str;
1878	char *g_point;
1879	int tmp_int;
1880	int g_horz, g_position, g_pos;
1881	int esc_flag;
1882
1883	g_point = tmp_string = malloc(512);
1884	wmove(com_win,0,0);
1885	wclrtoeol(com_win);
1886	waddstr(com_win, prompt);
1887	wrefresh(com_win);
1888	nam_str = tmp_string;
1889	clear_com_win = TRUE;
1890	g_horz = g_position = scan(prompt, strlen(prompt), 0);
1891	g_pos = 0;
1892	do
1893	{
1894		esc_flag = FALSE;
1895		in = wgetch(com_win);
1896		if (in == -1)
1897			exit(0);
1898		if (((in == 8) || (in == 127) || (in == KEY_BACKSPACE)) && (g_pos > 0))
1899		{
1900			tmp_int = g_horz;
1901			g_pos--;
1902			g_horz = scan(g_point, g_pos, g_position);
1903			tmp_int = tmp_int - g_horz;
1904			for (; 0 < tmp_int; tmp_int--)
1905			{
1906				if ((g_horz+tmp_int) < (last_col - 1))
1907				{
1908					waddch(com_win, '\010');
1909					waddch(com_win, ' ');
1910					waddch(com_win, '\010');
1911				}
1912			}
1913			nam_str--;
1914		}
1915		else if ((in != 8) && (in != 127) && (in != '\n') && (in != '\r') && (in < 256))
1916		{
1917			if (in == '\026')	/* control-v, accept next character verbatim	*/
1918			{			/* allows entry of ^m, ^j, and ^h	*/
1919				esc_flag = TRUE;
1920				in = wgetch(com_win);
1921				if (in == -1)
1922					exit(0);
1923			}
1924			*nam_str = in;
1925			g_pos++;
1926			if (((in < ' ') || (in > 126)) && (g_horz < (last_col - 1)))
1927				g_horz += out_char(com_win, in, g_horz);
1928			else
1929			{
1930				g_horz++;
1931				if (g_horz < (last_col - 1))
1932					waddch(com_win, in);
1933			}
1934			nam_str++;
1935		}
1936		wrefresh(com_win);
1937		if (esc_flag)
1938			in = '\0';
1939	} while ((in != '\n') && (in != '\r'));
1940	*nam_str = '\0';
1941	nam_str = tmp_string;
1942	if (((*nam_str == ' ') || (*nam_str == 9)) && (advance))
1943		nam_str = next_word(nam_str);
1944	string = malloc(strlen(nam_str) + 1);
1945	strcpy(string, nam_str);
1946	free(tmp_string);
1947	wrefresh(com_win);
1948	return(string);
1949}
1950
1951int
1952compare(string1, string2, sensitive)	/* compare two strings	*/
1953char *string1;
1954char *string2;
1955int sensitive;
1956{
1957	char *strng1;
1958	char *strng2;
1959	int tmp;
1960	int equal;
1961
1962	strng1 = string1;
1963	strng2 = string2;
1964	tmp = 0;
1965	if ((strng1 == NULL) || (strng2 == NULL) || (*strng1 == '\0') || (*strng2 == '\0'))
1966		return(FALSE);
1967	equal = TRUE;
1968	while (equal)
1969	{
1970		if (sensitive)
1971		{
1972			if (*strng1 != *strng2)
1973				equal = FALSE;
1974		}
1975		else
1976		{
1977			if (toupper(*strng1) != toupper(*strng2))
1978				equal = FALSE;
1979		}
1980		strng1++;
1981		strng2++;
1982		if ((*strng1 == '\0') || (*strng2 == '\0') || (*strng1 == ' ') || (*strng2 == ' '))
1983			break;
1984		tmp++;
1985	}
1986	return(equal);
1987}
1988
1989void
1990goto_line(cmd_str)
1991char *cmd_str;
1992{
1993	int number;
1994	int i;
1995	char *ptr;
1996	char *direction = NULL;
1997	struct text *t_line;
1998
1999	ptr = cmd_str;
2000	i= 0;
2001	while ((*ptr >='0') && (*ptr <= '9'))
2002	{
2003		i= i * 10 + (*ptr - '0');
2004		ptr++;
2005	}
2006	number = i;
2007	i = 0;
2008	t_line = curr_line;
2009	while ((t_line->line_number > number) && (t_line->prev_line != NULL))
2010	{
2011		i++;
2012		t_line = t_line->prev_line;
2013		direction = "u";
2014	}
2015	while ((t_line->line_number < number) && (t_line->next_line != NULL))
2016	{
2017		i++;
2018		direction = "d";
2019		t_line = t_line->next_line;
2020	}
2021	if ((i < 30) && (i > 0))
2022	{
2023		move_rel(direction, i);
2024	}
2025	else
2026	{
2027		if (!strcmp(direction, "d"))
2028		{
2029			absolute_lin += i;
2030		}
2031		else
2032		{
2033			absolute_lin -= i;
2034		}
2035		curr_line = t_line;
2036		point = curr_line->line;
2037		position = 1;
2038		midscreen((last_line / 2), point);
2039		scr_pos = scr_horz;
2040	}
2041	wmove(com_win, 0, 0);
2042	wclrtoeol(com_win);
2043	wprintw(com_win, line_num_str, curr_line->line_number);
2044	wmove(text_win, scr_vert, (scr_horz - horiz_offset));
2045}
2046
2047void
2048midscreen(line, pnt)	/* put current line in middle of screen	*/
2049int line;
2050unsigned char *pnt;
2051{
2052	struct text *mid_line;
2053	int i;
2054
2055	line = min(line, last_line);
2056	mid_line = curr_line;
2057	for (i = 0; ((i < line) && (curr_line->prev_line != NULL)); i++)
2058		curr_line = curr_line->prev_line;
2059	scr_vert = scr_horz = 0;
2060	wmove(text_win, 0, 0);
2061	draw_screen();
2062	scr_vert = i;
2063	curr_line = mid_line;
2064	scanline(pnt);
2065	wmove(text_win, scr_vert, (scr_horz - horiz_offset));
2066}
2067
2068void
2069get_options(numargs, arguments)	/* get arguments from command line	*/
2070int numargs;
2071char *arguments[];
2072{
2073	char *buff;
2074	int count;
2075	struct files *temp_names = NULL;
2076	char *name;
2077	char *ptr;
2078	int no_more_opts = FALSE;
2079
2080	/*
2081	 |	see if editor was invoked as 'ree' (restricted mode)
2082	 */
2083
2084	if (!(name = strrchr(arguments[0], '/')))
2085		name = arguments[0];
2086	else
2087		name++;
2088	if (!strcmp(name, "ree"))
2089		restricted = TRUE;
2090
2091	top_of_stack = NULL;
2092	input_file = FALSE;
2093	recv_file = FALSE;
2094	count = 1;
2095	while ((count < numargs)&& (!no_more_opts))
2096	{
2097		buff = arguments[count];
2098		if (!strcmp("-i", buff))
2099		{
2100			info_window = FALSE;
2101		}
2102		else if (!strcmp("-e", buff))
2103		{
2104			expand_tabs = FALSE;
2105		}
2106		else if (!strcmp("-h", buff))
2107		{
2108			nohighlight = TRUE;
2109		}
2110		else if (!strcmp("-?", buff))
2111		{
2112			fprintf(stderr, usage0, arguments[0]);
2113			fprintf(stderr, usage1);
2114			fprintf(stderr, usage2);
2115			fprintf(stderr, usage3);
2116			fprintf(stderr, usage4);
2117			exit(1);
2118		}
2119		else if ((*buff == '+') && (start_at_line == NULL))
2120		{
2121			buff++;
2122			start_at_line = buff;
2123		}
2124		else if (!(strcmp("--", buff)))
2125			no_more_opts = TRUE;
2126		else
2127		{
2128			count--;
2129			no_more_opts = TRUE;
2130		}
2131		count++;
2132	}
2133	while (count < numargs)
2134	{
2135		buff = arguments[count];
2136		if (top_of_stack == NULL)
2137		{
2138			temp_names = top_of_stack = name_alloc();
2139		}
2140		else
2141		{
2142			temp_names->next_name = name_alloc();
2143			temp_names = temp_names->next_name;
2144		}
2145		ptr = temp_names->name = malloc(strlen(buff) + 1);
2146		while (*buff != '\0')
2147		{
2148			*ptr = *buff;
2149			buff++;
2150			ptr++;
2151		}
2152		*ptr = '\0';
2153		temp_names->next_name = NULL;
2154		input_file = TRUE;
2155		recv_file = TRUE;
2156		count++;
2157	}
2158}
2159
2160void
2161check_fp()		/* open or close files according to flags */
2162{
2163	int line_num;
2164	int temp;
2165	struct stat buf;
2166
2167	clear_com_win = TRUE;
2168	tmp_vert = scr_vert;
2169	tmp_horz = scr_horz;
2170	tmp_line = curr_line;
2171	if (input_file)
2172	{
2173		in_file_name = tmp_file = top_of_stack->name;
2174		top_of_stack = top_of_stack->next_name;
2175	}
2176	temp = stat(tmp_file, &buf);
2177	buf.st_mode &= ~07777;
2178	if ((temp != -1) && (buf.st_mode != 0100000) && (buf.st_mode != 0))
2179	{
2180		wprintw(com_win, file_is_dir_msg, tmp_file);
2181		wrefresh(com_win);
2182		if (input_file)
2183		{
2184			quit(0);
2185			return;
2186		}
2187		else
2188			return;
2189	}
2190	if ((get_fd = open(tmp_file, O_RDONLY)) == -1)
2191	{
2192		wmove(com_win, 0, 0);
2193		wclrtoeol(com_win);
2194		if (input_file)
2195			wprintw(com_win, new_file_msg, tmp_file);
2196		else
2197			wprintw(com_win, cant_open_msg, tmp_file);
2198		wrefresh(com_win);
2199		wmove(text_win, scr_vert, (scr_horz - horiz_offset));
2200		wrefresh(text_win);
2201		recv_file = FALSE;
2202		input_file = FALSE;
2203		return;
2204	}
2205	else
2206		get_file(tmp_file);
2207
2208	recv_file = FALSE;
2209	line_num = curr_line->line_number;
2210	scr_vert = tmp_vert;
2211	scr_horz = tmp_horz;
2212	if (input_file)
2213		curr_line= first_line;
2214	else
2215		curr_line = tmp_line;
2216	point = curr_line->line;
2217	draw_screen();
2218	if (input_file)
2219	{
2220		input_file = FALSE;
2221		if (start_at_line != NULL)
2222		{
2223			line_num = atoi(start_at_line) - 1;
2224			move_rel("d", line_num);
2225			line_num = 0;
2226			start_at_line = NULL;
2227		}
2228	}
2229	else
2230	{
2231		wmove(com_win, 0, 0);
2232		wclrtoeol(com_win);
2233		text_changes = TRUE;
2234		if ((tmp_file != NULL) && (*tmp_file != '\0'))
2235			wprintw(com_win, file_read_fin_msg, tmp_file);
2236	}
2237	wrefresh(com_win);
2238	wmove(text_win, scr_vert, (scr_horz - horiz_offset));
2239	wrefresh(text_win);
2240}
2241
2242void
2243get_file(file_name)	/* read specified file into current buffer	*/
2244char *file_name;
2245{
2246	int can_read;		/* file has at least one character	*/
2247	int length;		/* length of line read by read		*/
2248	int append;		/* should text be appended to current line */
2249	struct text *temp_line;
2250	char ro_flag = FALSE;
2251
2252	if (recv_file)		/* if reading a file			*/
2253	{
2254		wmove(com_win, 0, 0);
2255		wclrtoeol(com_win);
2256		wprintw(com_win, reading_file_msg, file_name);
2257		if (access(file_name, 2))	/* check permission to write */
2258		{
2259			if ((errno == ENOTDIR) || (errno == EACCES) || (errno == EROFS) || (errno == ETXTBSY) || (errno == EFAULT))
2260			{
2261				wprintw(com_win, read_only_msg);
2262				ro_flag = TRUE;
2263			}
2264		}
2265		wrefresh(com_win);
2266	}
2267	if (curr_line->line_length > 1)	/* if current line is not blank	*/
2268	{
2269		insert_line(FALSE);
2270		left(FALSE);
2271		append = FALSE;
2272	}
2273	else
2274		append = TRUE;
2275	can_read = FALSE;		/* test if file has any characters  */
2276	while (((length = read(get_fd, in_string, 512)) != 0) && (length != -1))
2277	{
2278		can_read = TRUE;  /* if set file has at least 1 character   */
2279		get_line(length, in_string, &append);
2280	}
2281	if ((can_read) && (curr_line->line_length == 1))
2282	{
2283		temp_line = curr_line->prev_line;
2284		temp_line->next_line = curr_line->next_line;
2285		if (temp_line->next_line != NULL)
2286			temp_line->next_line->prev_line = temp_line;
2287		if (curr_line->line != NULL)
2288			free(curr_line->line);
2289		free(curr_line);
2290		curr_line = temp_line;
2291	}
2292	if (input_file)	/* if this is the file to be edited display number of lines	*/
2293	{
2294		wmove(com_win, 0, 0);
2295		wclrtoeol(com_win);
2296		wprintw(com_win, file_read_lines_msg, in_file_name, curr_line->line_number);
2297		if (ro_flag)
2298			wprintw(com_win, read_only_msg);
2299		wrefresh(com_win);
2300	}
2301	else if (can_read)	/* not input_file and file is non-zero size */
2302		text_changes = TRUE;
2303
2304	if (recv_file)		/* if reading a file			*/
2305	{
2306		in = EOF;
2307	}
2308}
2309
2310void
2311get_line(length, in_string, append)	/* read string and split into lines */
2312int length;		/* length of string read by read		*/
2313unsigned char *in_string;	/* string read by read				*/
2314int *append;	/* TRUE if must append more text to end of current line	*/
2315{
2316	unsigned char *str1;
2317	unsigned char *str2;
2318	int num;		/* offset from start of string		*/
2319	int char_count;		/* length of new line (or added portion	*/
2320	int temp_counter;	/* temporary counter value		*/
2321	struct text *tline;	/* temporary pointer to new line	*/
2322	int first_time;		/* if TRUE, the first time through the loop */
2323
2324	str2 = in_string;
2325	num = 0;
2326	first_time = TRUE;
2327	while (num < length)
2328	{
2329		if (!first_time)
2330		{
2331			if (num < length)
2332			{
2333				str2++;
2334				num++;
2335			}
2336		}
2337		else
2338			first_time = FALSE;
2339		str1 = str2;
2340		char_count = 1;
2341		/* find end of line	*/
2342		while ((*str2 != '\n') && (num < length))
2343		{
2344			str2++;
2345			num++;
2346			char_count++;
2347		}
2348		if (!(*append))	/* if not append to current line, insert new one */
2349		{
2350			tline = txtalloc();	/* allocate data structure for next line */
2351			tline->line_number = curr_line->line_number + 1;
2352			tline->next_line = curr_line->next_line;
2353			tline->prev_line = curr_line;
2354			curr_line->next_line = tline;
2355			if (tline->next_line != NULL)
2356				tline->next_line->prev_line = tline;
2357			curr_line = tline;
2358			curr_line->line = point = (unsigned char *) malloc(char_count);
2359			curr_line->line_length = char_count;
2360			curr_line->max_length = char_count;
2361		}
2362		else
2363		{
2364			point = resiz_line(char_count, curr_line, curr_line->line_length);
2365			curr_line->line_length += (char_count - 1);
2366		}
2367		for (temp_counter = 1; temp_counter < char_count; temp_counter++)
2368		{
2369			*point = *str1;
2370			point++;
2371			str1++;
2372		}
2373		*point = '\0';
2374		*append = FALSE;
2375		if ((num == length) && (*str2 != '\n'))
2376			*append = TRUE;
2377	}
2378}
2379
2380void
2381draw_screen()		/* redraw the screen from current postion	*/
2382{
2383	struct text *temp_line;
2384	unsigned char *line_out;
2385	int temp_vert;
2386
2387	temp_line = curr_line;
2388	temp_vert = scr_vert;
2389	wclrtobot(text_win);
2390	while ((temp_line != NULL) && (temp_vert <= last_line))
2391	{
2392		line_out = temp_line->line;
2393		draw_line(temp_vert, 0, line_out, 1, temp_line->line_length);
2394		temp_vert++;
2395		temp_line = temp_line->next_line;
2396	}
2397	wmove(text_win, temp_vert, 0);
2398	wmove(text_win, scr_vert, (scr_horz - horiz_offset));
2399}
2400
2401void
2402finish()	/* prepare to exit edit session	*/
2403{
2404	char *file_name = in_file_name;
2405
2406	/*
2407	 |	changes made here should be reflected in the 'save'
2408	 |	portion of file_op()
2409	 */
2410
2411	if ((file_name == NULL) || (*file_name == '\0'))
2412		file_name = get_string(save_file_name_prompt, TRUE);
2413
2414	if ((file_name == NULL) || (*file_name == '\0'))
2415	{
2416		wmove(com_win, 0, 0);
2417		wprintw(com_win, file_not_saved_msg);
2418		wclrtoeol(com_win);
2419		wrefresh(com_win);
2420		clear_com_win = TRUE;
2421		return;
2422	}
2423
2424	tmp_file = resolve_name(file_name);
2425	if (tmp_file != file_name)
2426	{
2427		free(file_name);
2428		file_name = tmp_file;
2429	}
2430
2431	if (write_file(file_name, 1))
2432	{
2433		text_changes = FALSE;
2434		quit(0);
2435	}
2436}
2437
2438int
2439quit(noverify)		/* exit editor			*/
2440int noverify;
2441{
2442	char *ans;
2443
2444	touchwin(text_win);
2445	wrefresh(text_win);
2446	if ((text_changes) && (!noverify))
2447	{
2448		ans = get_string(changes_made_prompt, TRUE);
2449		if (toupper(*ans) == toupper(*yes_char))
2450			text_changes = FALSE;
2451		else
2452			return(0);
2453		free(ans);
2454	}
2455	if (top_of_stack == NULL)
2456	{
2457		if (info_window)
2458			wrefresh(info_win);
2459		wrefresh(com_win);
2460		resetty();
2461		endwin();
2462		putchar('\n');
2463		exit(0);
2464	}
2465	else
2466	{
2467		delete_text();
2468		recv_file = TRUE;
2469		input_file = TRUE;
2470		check_fp();
2471	}
2472	return(0);
2473}
2474
2475void
2476edit_abort(arg)
2477int arg;
2478{
2479	wrefresh(com_win);
2480	resetty();
2481	endwin();
2482	putchar('\n');
2483	exit(1);
2484}
2485
2486void
2487delete_text()
2488{
2489	while (curr_line->next_line != NULL)
2490		curr_line = curr_line->next_line;
2491	while (curr_line != first_line)
2492	{
2493		free(curr_line->line);
2494		curr_line = curr_line->prev_line;
2495		absolute_lin--;
2496		free(curr_line->next_line);
2497	}
2498	curr_line->next_line = NULL;
2499	*curr_line->line = '\0';
2500	curr_line->line_length = 1;
2501	curr_line->line_number = 1;
2502	point = curr_line->line;
2503	scr_pos = scr_vert = scr_horz = 0;
2504	position = 1;
2505}
2506
2507int
2508write_file(file_name, warn_if_exists)
2509char *file_name;
2510int warn_if_exists;
2511{
2512	char cr;
2513	char *tmp_point;
2514	struct text *out_line;
2515	int lines, charac;
2516	int temp_pos;
2517	int write_flag = TRUE;
2518
2519	charac = lines = 0;
2520	if (warn_if_exists &&
2521	    ((in_file_name == NULL) || strcmp(in_file_name, file_name)))
2522	{
2523		if ((temp_fp = fopen(file_name, "r")))
2524		{
2525			tmp_point = get_string(file_exists_prompt, TRUE);
2526			if (toupper(*tmp_point) == toupper(*yes_char))
2527				write_flag = TRUE;
2528			else
2529				write_flag = FALSE;
2530			fclose(temp_fp);
2531			free(tmp_point);
2532		}
2533	}
2534
2535	clear_com_win = TRUE;
2536
2537	if (write_flag)
2538	{
2539		if ((temp_fp = fopen(file_name, "w")) == NULL)
2540		{
2541			clear_com_win = TRUE;
2542			wmove(com_win,0,0);
2543			wclrtoeol(com_win);
2544			wprintw(com_win, create_file_fail_msg, file_name);
2545			wrefresh(com_win);
2546			return(FALSE);
2547		}
2548		else
2549		{
2550			wmove(com_win,0,0);
2551			wclrtoeol(com_win);
2552			wprintw(com_win, writing_file_msg, file_name);
2553			wrefresh(com_win);
2554			cr = '\n';
2555			out_line = first_line;
2556			while (out_line != NULL)
2557			{
2558				temp_pos = 1;
2559				tmp_point= out_line->line;
2560				while (temp_pos < out_line->line_length)
2561				{
2562					putc(*tmp_point, temp_fp);
2563					tmp_point++;
2564					temp_pos++;
2565				}
2566				charac += out_line->line_length;
2567				out_line = out_line->next_line;
2568				putc(cr, temp_fp);
2569				lines++;
2570			}
2571			fclose(temp_fp);
2572			wmove(com_win,0,0);
2573			wclrtoeol(com_win);
2574			wprintw(com_win, file_written_msg, file_name, lines, charac);
2575			wrefresh(com_win);
2576			return(TRUE);
2577		}
2578	}
2579	else
2580		return(FALSE);
2581}
2582
2583int
2584search(display_message)		/* search for string in srch_str	*/
2585int display_message;
2586{
2587	int lines_moved;
2588	int iter;
2589	int found;
2590
2591	if ((srch_str == NULL) || (*srch_str == '\0'))
2592		return(FALSE);
2593	if (display_message)
2594	{
2595		wmove(com_win, 0, 0);
2596		wclrtoeol(com_win);
2597		wprintw(com_win, searching_msg);
2598		wrefresh(com_win);
2599		clear_com_win = TRUE;
2600	}
2601	lines_moved = 0;
2602	found = FALSE;
2603	srch_line = curr_line;
2604	srch_1 = point;
2605	if (position < curr_line->line_length)
2606		srch_1++;
2607	iter = position + 1;
2608	while ((!found) && (srch_line != NULL))
2609	{
2610		while ((iter < srch_line->line_length) && (!found))
2611		{
2612			srch_2 = srch_1;
2613			if (case_sen)	/* if case sensitive		*/
2614			{
2615				srch_3 = srch_str;
2616			while ((*srch_2 == *srch_3) && (*srch_3 != '\0'))
2617				{
2618					found = TRUE;
2619					srch_2++;
2620					srch_3++;
2621				}	/* end while	*/
2622			}
2623			else		/* if not case sensitive	*/
2624			{
2625				srch_3 = u_srch_str;
2626			while ((toupper(*srch_2) == *srch_3) && (*srch_3 != '\0'))
2627				{
2628					found = TRUE;
2629					srch_2++;
2630					srch_3++;
2631				}
2632			}	/* end else	*/
2633			if (!((*srch_3 == '\0') && (found)))
2634			{
2635				found = FALSE;
2636				if (iter < srch_line->line_length)
2637					srch_1++;
2638				iter++;
2639			}
2640		}
2641		if (!found)
2642		{
2643			srch_line = srch_line->next_line;
2644			if (srch_line != NULL)
2645				srch_1 = srch_line->line;
2646			iter = 1;
2647			lines_moved++;
2648		}
2649	}
2650	if (found)
2651	{
2652		if (display_message)
2653		{
2654			wmove(com_win, 0, 0);
2655			wclrtoeol(com_win);
2656			wrefresh(com_win);
2657		}
2658		if (lines_moved == 0)
2659		{
2660			while (position < iter)
2661				right(TRUE);
2662		}
2663		else
2664		{
2665			if (lines_moved < 30)
2666			{
2667				move_rel("d", lines_moved);
2668				while (position < iter)
2669					right(TRUE);
2670			}
2671			else
2672			{
2673				absolute_lin += lines_moved;
2674				curr_line = srch_line;
2675				point = srch_1;
2676				position = iter;
2677				scanline(point);
2678				scr_pos = scr_horz;
2679				midscreen((last_line / 2), point);
2680			}
2681		}
2682	}
2683	else
2684	{
2685		if (display_message)
2686		{
2687			wmove(com_win, 0, 0);
2688			wclrtoeol(com_win);
2689			wprintw(com_win, str_not_found_msg, srch_str);
2690			wrefresh(com_win);
2691		}
2692		wmove(text_win, scr_vert,(scr_horz - horiz_offset));
2693	}
2694	return(found);
2695}
2696
2697void
2698search_prompt()		/* prompt and read search string (srch_str)	*/
2699{
2700	if (srch_str != NULL)
2701		free(srch_str);
2702	if ((u_srch_str != NULL) && (*u_srch_str != '\0'))
2703		free(u_srch_str);
2704	srch_str = get_string(search_prompt_str, FALSE);
2705	gold = FALSE;
2706	srch_3 = srch_str;
2707	srch_1 = u_srch_str = malloc(strlen(srch_str) + 1);
2708	while (*srch_3 != '\0')
2709	{
2710		*srch_1 = toupper(*srch_3);
2711		srch_1++;
2712		srch_3++;
2713	}
2714	*srch_1 = '\0';
2715	search(TRUE);
2716}
2717
2718void
2719del_char()			/* delete current character	*/
2720{
2721	in = 8;  /* backspace */
2722	if (position < curr_line->line_length)	/* if not end of line	*/
2723	{
2724		if ((ee_chinese) && (*point > 127) &&
2725		    ((curr_line->line_length - position) >= 2))
2726		{
2727			point++;
2728			position++;
2729		}
2730		position++;
2731		point++;
2732		scanline(point);
2733		delete(TRUE);
2734	}
2735	else
2736	{
2737		right(FALSE);
2738		delete(FALSE);
2739	}
2740}
2741
2742void
2743undel_char()			/* undelete last deleted character	*/
2744{
2745	if (d_char[0] == '\n')	/* insert line if last del_char deleted eol */
2746		insert_line(TRUE);
2747	else
2748	{
2749		in = d_char[0];
2750		insert(in);
2751		if (d_char[1] != '\0')
2752		{
2753			in = d_char[1];
2754			insert(in);
2755		}
2756	}
2757}
2758
2759void
2760del_word()			/* delete word in front of cursor	*/
2761{
2762	int tposit;
2763	int difference;
2764	unsigned char *d_word2;
2765	unsigned char *d_word3;
2766	unsigned char tmp_char[3];
2767
2768	if (d_word != NULL)
2769		free(d_word);
2770	d_word = malloc(curr_line->line_length);
2771	tmp_char[0] = d_char[0];
2772	tmp_char[1] = d_char[1];
2773	tmp_char[2] = d_char[2];
2774	d_word3 = point;
2775	d_word2 = d_word;
2776	tposit = position;
2777	while ((tposit < curr_line->line_length) &&
2778				((*d_word3 != ' ') && (*d_word3 != '\t')))
2779	{
2780		tposit++;
2781		*d_word2 = *d_word3;
2782		d_word2++;
2783		d_word3++;
2784	}
2785	while ((tposit < curr_line->line_length) &&
2786				((*d_word3 == ' ') || (*d_word3 == '\t')))
2787	{
2788		tposit++;
2789		*d_word2 = *d_word3;
2790		d_word2++;
2791		d_word3++;
2792	}
2793	*d_word2 = '\0';
2794	d_wrd_len = difference = d_word2 - d_word;
2795	d_word2 = point;
2796	while (tposit < curr_line->line_length)
2797	{
2798		tposit++;
2799		*d_word2 = *d_word3;
2800		d_word2++;
2801		d_word3++;
2802	}
2803	curr_line->line_length -= difference;
2804	*d_word2 = '\0';
2805	draw_line(scr_vert, scr_horz,point,position,curr_line->line_length);
2806	d_char[0] = tmp_char[0];
2807	d_char[1] = tmp_char[1];
2808	d_char[2] = tmp_char[2];
2809	text_changes = TRUE;
2810	formatted = FALSE;
2811}
2812
2813void
2814undel_word()		/* undelete last deleted word		*/
2815{
2816	int temp;
2817	int tposit;
2818	unsigned char *tmp_old_ptr;
2819	unsigned char *tmp_space;
2820	unsigned char *tmp_ptr;
2821	unsigned char *d_word_ptr;
2822
2823	/*
2824	 |	resize line to handle undeleted word
2825	 */
2826	if ((curr_line->max_length - (curr_line->line_length + d_wrd_len)) < 5)
2827		point = resiz_line(d_wrd_len, curr_line, position);
2828	tmp_ptr = tmp_space = malloc(curr_line->line_length + d_wrd_len);
2829	d_word_ptr = d_word;
2830	temp = 1;
2831	/*
2832	 |	copy d_word contents into temp space
2833	 */
2834	while (temp <= d_wrd_len)
2835	{
2836		temp++;
2837		*tmp_ptr = *d_word_ptr;
2838		tmp_ptr++;
2839		d_word_ptr++;
2840	}
2841	tmp_old_ptr = point;
2842	tposit = position;
2843	/*
2844	 |	copy contents of line from curent position to eol into
2845	 |	temp space
2846	 */
2847	while (tposit < curr_line->line_length)
2848	{
2849		temp++;
2850		tposit++;
2851		*tmp_ptr = *tmp_old_ptr;
2852		tmp_ptr++;
2853		tmp_old_ptr++;
2854	}
2855	curr_line->line_length += d_wrd_len;
2856	tmp_old_ptr = point;
2857	*tmp_ptr = '\0';
2858	tmp_ptr = tmp_space;
2859	tposit = 1;
2860	/*
2861	 |	now copy contents from temp space back to original line
2862	 */
2863	while (tposit < temp)
2864	{
2865		tposit++;
2866		*tmp_old_ptr = *tmp_ptr;
2867		tmp_ptr++;
2868		tmp_old_ptr++;
2869	}
2870	*tmp_old_ptr = '\0';
2871	free(tmp_space);
2872	draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
2873}
2874
2875void
2876del_line()			/* delete from cursor to end of line	*/
2877{
2878	unsigned char *dl1;
2879	unsigned char *dl2;
2880	int tposit;
2881
2882	if (d_line != NULL)
2883		free(d_line);
2884	d_line = malloc(curr_line->line_length);
2885	dl1 = d_line;
2886	dl2 = point;
2887	tposit = position;
2888	while (tposit < curr_line->line_length)
2889	{
2890		*dl1 = *dl2;
2891		dl1++;
2892		dl2++;
2893		tposit++;
2894	}
2895	dlt_line->line_length = 1 + tposit - position;
2896	*dl1 = '\0';
2897	*point = '\0';
2898	curr_line->line_length = position;
2899	wclrtoeol(text_win);
2900	if (curr_line->next_line != NULL)
2901	{
2902		right(FALSE);
2903		delete(FALSE);
2904	}
2905	text_changes = TRUE;
2906}
2907
2908void
2909undel_line()			/* undelete last deleted line		*/
2910{
2911	unsigned char *ud1;
2912	unsigned char *ud2;
2913	int tposit;
2914
2915	if (dlt_line->line_length == 0)
2916		return;
2917
2918	insert_line(TRUE);
2919	left(TRUE);
2920	point = resiz_line(dlt_line->line_length, curr_line, position);
2921	curr_line->line_length += dlt_line->line_length - 1;
2922	ud1 = point;
2923	ud2 = d_line;
2924	tposit = 1;
2925	while (tposit < dlt_line->line_length)
2926	{
2927		tposit++;
2928		*ud1 = *ud2;
2929		ud1++;
2930		ud2++;
2931	}
2932	*ud1 = '\0';
2933	draw_line(scr_vert, scr_horz,point,position,curr_line->line_length);
2934}
2935
2936void
2937adv_word()			/* advance to next word		*/
2938{
2939while ((position < curr_line->line_length) && ((*point != 32) && (*point != 9)))
2940		right(TRUE);
2941while ((position < curr_line->line_length) && ((*point == 32) || (*point == 9)))
2942		right(TRUE);
2943}
2944
2945void
2946move_rel(direction, lines)	/* move relative to current line	*/
2947char *direction;
2948int lines;
2949{
2950	int i;
2951	char *tmp;
2952
2953	if (*direction == 'u')
2954	{
2955		scr_pos = 0;
2956		while (position > 1)
2957			left(TRUE);
2958		for (i = 0; i < lines; i++)
2959		{
2960			up();
2961		}
2962		if ((last_line > 5) && ( scr_vert < 4))
2963		{
2964			tmp = point;
2965			tmp_line = curr_line;
2966			for (i= 0;(i<5)&&(curr_line->prev_line != NULL); i++)
2967			{
2968				up();
2969			}
2970			scr_vert = scr_vert + i;
2971			curr_line = tmp_line;
2972			absolute_lin += i;
2973			point = tmp;
2974			scanline(point);
2975		}
2976	}
2977	else
2978	{
2979		if ((position != 1) && (curr_line->next_line != NULL))
2980		{
2981			nextline();
2982			scr_pos = scr_horz = 0;
2983			if (horiz_offset)
2984			{
2985				horiz_offset = 0;
2986				midscreen(scr_vert, point);
2987			}
2988		}
2989		else
2990			adv_line();
2991		for (i = 1; i < lines; i++)
2992		{
2993			down();
2994		}
2995		if ((last_line > 10) && (scr_vert > (last_line - 5)))
2996		{
2997			tmp = point;
2998			tmp_line = curr_line;
2999			for (i=0; (i<5) && (curr_line->next_line != NULL); i++)
3000			{
3001				down();
3002			}
3003			absolute_lin -= i;
3004			scr_vert = scr_vert - i;
3005			curr_line = tmp_line;
3006			point = tmp;
3007			scanline(point);
3008		}
3009	}
3010	wmove(text_win, scr_vert, (scr_horz - horiz_offset));
3011}
3012
3013void
3014eol()				/* go to end of line			*/
3015{
3016	if (position < curr_line->line_length)
3017	{
3018		while (position < curr_line->line_length)
3019			right(TRUE);
3020	}
3021	else if (curr_line->next_line != NULL)
3022	{
3023		right(TRUE);
3024		while (position < curr_line->line_length)
3025			right(TRUE);
3026	}
3027}
3028
3029void
3030bol()				/* move to beginning of line	*/
3031{
3032	if (point != curr_line->line)
3033	{
3034		while (point != curr_line->line)
3035			left(TRUE);
3036	}
3037	else if (curr_line->prev_line != NULL)
3038	{
3039		scr_pos = 0;
3040		up();
3041	}
3042}
3043
3044void
3045adv_line()	/* advance to beginning of next line	*/
3046{
3047	if ((point != curr_line->line) || (scr_pos > 0))
3048	{
3049		while (position < curr_line->line_length)
3050			right(TRUE);
3051		right(TRUE);
3052	}
3053	else if (curr_line->next_line != NULL)
3054	{
3055		scr_pos = 0;
3056		down();
3057	}
3058}
3059
3060void
3061from_top()
3062{
3063	struct text *tmpline = first_line;
3064	int x = 1;
3065
3066	while ((tmpline != NULL) && (tmpline != curr_line))
3067	{
3068		x++;
3069		tmpline = tmpline->next_line;
3070	}
3071	absolute_lin = x;
3072}
3073
3074void
3075sh_command(string)	/* execute shell command			*/
3076char *string;		/* string containing user command		*/
3077{
3078	char *temp_point;
3079	char *last_slash;
3080	char *path;		/* directory path to executable		*/
3081	int parent;		/* zero if child, child's pid if parent	*/
3082	int value;
3083	int return_val;
3084	struct text *line_holder;
3085
3086	if (restrict_mode())
3087	{
3088		return;
3089	}
3090
3091	if (!(path = getenv("SHELL")))
3092		path = "/bin/sh";
3093	last_slash = temp_point = path;
3094	while (*temp_point != '\0')
3095	{
3096		if (*temp_point == '/')
3097			last_slash = ++temp_point;
3098		else
3099			temp_point++;
3100	}
3101
3102	/*
3103	 |	if in_pipe is true, then output of the shell operation will be
3104	 |	read by the editor, and curses doesn't need to be turned off
3105	 */
3106
3107	if (!in_pipe)
3108	{
3109		keypad(com_win, FALSE);
3110		keypad(text_win, FALSE);
3111		echo();
3112		nl();
3113		noraw();
3114		resetty();
3115
3116#ifndef NCURSE
3117		endwin();
3118#endif
3119	}
3120
3121	if (in_pipe)
3122	{
3123		pipe(pipe_in);		/* create a pipe	*/
3124		parent = fork();
3125		if (!parent)		/* if the child		*/
3126		{
3127/*
3128 |  child process which will fork and exec shell command (if shell output is
3129 |  to be read by editor)
3130 */
3131			in_pipe = FALSE;
3132/*
3133 |  redirect stdout to pipe
3134 */
3135			temp_stdout = dup(1);
3136			close(1);
3137			dup(pipe_in[1]);
3138/*
3139 |  redirect stderr to pipe
3140 */
3141			temp_stderr = dup(2);
3142			close(2);
3143			dup(pipe_in[1]);
3144			close(pipe_in[1]);
3145			/*
3146			 |	child will now continue down 'if (!in_pipe)'
3147			 |	path below
3148			 */
3149		}
3150		else  /* if the parent	*/
3151		{
3152/*
3153 |  prepare editor to read from the pipe
3154 */
3155			signal(SIGCHLD, SIG_IGN);
3156			line_holder = curr_line;
3157			tmp_vert = scr_vert;
3158			close(pipe_in[1]);
3159			get_fd = pipe_in[0];
3160			get_file("");
3161			close(pipe_in[0]);
3162			scr_vert = tmp_vert;
3163			scr_horz = scr_pos = 0;
3164			position = 1;
3165			curr_line = line_holder;
3166			from_top();
3167			point = curr_line->line;
3168			out_pipe = FALSE;
3169			signal(SIGCHLD, SIG_DFL);
3170/*
3171 |  since flag "in_pipe" is still TRUE, the path which waits for the child
3172 |  process to die will be avoided.
3173 |  (the pipe is closed, no more output can be expected)
3174 */
3175		}
3176	}
3177	if (!in_pipe)
3178	{
3179		signal(SIGINT, SIG_IGN);
3180		if (out_pipe)
3181		{
3182			pipe(pipe_out);
3183		}
3184/*
3185 |  fork process which will exec command
3186 */
3187		parent = fork();
3188		if (!parent)		/* if the child	*/
3189		{
3190			if (shell_fork)
3191				putchar('\n');
3192			if (out_pipe)
3193			{
3194/*
3195 |  prepare the child process (soon to exec a shell command) to read from the
3196 |  pipe (which will be output from the editor's buffer)
3197 */
3198				close(0);
3199				dup(pipe_out[0]);
3200				close(pipe_out[0]);
3201				close(pipe_out[1]);
3202			}
3203			for (value = 1; value < 24; value++)
3204				signal(value, SIG_DFL);
3205			execl(path, last_slash, "-c", string, NULL);
3206			fprintf(stderr, exec_err_msg, path);
3207			exit(-1);
3208		}
3209		else	/* if the parent	*/
3210		{
3211			if (out_pipe)
3212			{
3213/*
3214 |  output the contents of the buffer to the pipe (to be read by the
3215 |  process forked and exec'd above as stdin)
3216 */
3217				close(pipe_out[0]);
3218				line_holder = first_line;
3219				while (line_holder != NULL)
3220				{
3221					write(pipe_out[1], line_holder->line, (line_holder->line_length-1));
3222					write(pipe_out[1], "\n", 1);
3223					line_holder = line_holder->next_line;
3224				}
3225				close(pipe_out[1]);
3226				out_pipe = FALSE;
3227			}
3228			do
3229			{
3230				return_val = wait((int *) 0);
3231			}
3232			while ((return_val != parent) && (return_val != -1));
3233/*
3234 |  if this process is actually the child of the editor, exit.  Here's how it
3235 |  works:
3236 |  The editor forks a process.  If output must be sent to the command to be
3237 |  exec'd another process is forked, and that process (the child's child)
3238 |  will exec the command.  In this case, "shell_fork" will be FALSE.  If no
3239 |  output is to be performed to the shell command, "shell_fork" will be TRUE.
3240 |  If this is the editor process, shell_fork will be true, otherwise this is
3241 |  the child of the edit process.
3242 */
3243			if (!shell_fork)
3244				exit(0);
3245		}
3246		signal(SIGINT, edit_abort);
3247	}
3248	if (shell_fork)
3249	{
3250		printf(continue_msg);
3251		fflush(stdout);
3252		while ((in = getchar()) != '\n')
3253			;
3254	}
3255
3256	if (!in_pipe)
3257	{
3258		fixterm();
3259		noecho();
3260		nonl();
3261		raw();
3262		keypad(text_win, TRUE);
3263		keypad(com_win, TRUE);
3264		if (info_window)
3265			clearok(info_win, TRUE);
3266	}
3267
3268	redraw();
3269}
3270
3271void
3272set_up_term()		/* set up the terminal for operating with ae	*/
3273{
3274	if (!curses_initialized)
3275	{
3276		initscr();
3277		savetty();
3278		noecho();
3279		raw();
3280		nonl();
3281		curses_initialized = TRUE;
3282	}
3283
3284	if (((LINES > 15) && (COLS >= 80)) && info_window)
3285		last_line = LINES - 8;
3286	else
3287	{
3288		info_window = FALSE;
3289		last_line = LINES - 2;
3290	}
3291
3292	idlok(stdscr, TRUE);
3293	com_win = newwin(1, COLS, (LINES - 1), 0);
3294	keypad(com_win, TRUE);
3295	idlok(com_win, TRUE);
3296	wrefresh(com_win);
3297	if (!info_window)
3298		text_win = newwin((LINES - 1), COLS, 0, 0);
3299	else
3300		text_win = newwin((LINES - 7), COLS, 6, 0);
3301	keypad(text_win, TRUE);
3302	idlok(text_win, TRUE);
3303	wrefresh(text_win);
3304	help_win = newwin((LINES - 1), COLS, 0, 0);
3305	keypad(help_win, TRUE);
3306	idlok(help_win, TRUE);
3307	if (info_window)
3308	{
3309		info_type = CONTROL_KEYS;
3310		info_win = newwin(6, COLS, 0, 0);
3311		werase(info_win);
3312		paint_info_win();
3313	}
3314
3315	last_col = COLS - 1;
3316	local_LINES = LINES;
3317	local_COLS = COLS;
3318
3319#ifdef NCURSE
3320	if (ee_chinese)
3321		nc_setattrib(A_NC_BIG5);
3322#endif /* NCURSE */
3323
3324}
3325
3326void
3327resize_check()
3328{
3329	if ((LINES == local_LINES) && (COLS == local_COLS))
3330		return;
3331
3332	if (info_window)
3333		delwin(info_win);
3334	delwin(text_win);
3335	delwin(com_win);
3336	delwin(help_win);
3337	set_up_term();
3338	redraw();
3339	wrefresh(text_win);
3340}
3341
3342static char item_alpha[] = "abcdefghijklmnopqrstuvwxyz0123456789 ";
3343
3344int
3345menu_op(menu_list)
3346struct menu_entries menu_list[];
3347{
3348	WINDOW *temp_win;
3349	int max_width, max_height;
3350	int x_off, y_off;
3351	int counter;
3352	int length;
3353	int input;
3354	int temp;
3355	int list_size;
3356	int top_offset;		/* offset from top where menu items start */
3357	int vert_pos;		/* vertical position			  */
3358	int vert_size;		/* vertical size for menu list item display */
3359	int off_start = 1;	/* offset from start of menu items to start display */
3360
3361
3362	/*
3363	 |	determine number and width of menu items
3364	 */
3365
3366	list_size = 1;
3367	while (menu_list[list_size + 1].item_string != NULL)
3368		list_size++;
3369	max_width = 0;
3370	for (counter = 0; counter <= list_size; counter++)
3371	{
3372		if ((length = strlen(menu_list[counter].item_string)) > max_width)
3373			max_width = length;
3374	}
3375	max_width += 3;
3376	max_width = max(max_width, strlen(menu_cancel_msg));
3377	max_width = max(max_width, max(strlen(more_above_str), strlen(more_below_str)));
3378	max_width += 6;
3379
3380	/*
3381	 |	make sure that window is large enough to handle menu
3382	 |	if not, print error message and return to calling function
3383	 */
3384
3385	if (max_width > COLS)
3386	{
3387		wmove(com_win, 0, 0);
3388		werase(com_win);
3389		wprintw(com_win, menu_too_lrg_msg);
3390		wrefresh(com_win);
3391		clear_com_win = TRUE;
3392		return(0);
3393	}
3394
3395	top_offset = 0;
3396
3397	if (list_size > LINES)
3398	{
3399		max_height = LINES;
3400		if (max_height > 11)
3401			vert_size = max_height - 8;
3402		else
3403			vert_size = max_height;
3404	}
3405	else
3406	{
3407		vert_size = list_size;
3408		max_height = list_size;
3409	}
3410
3411	if (LINES >= (vert_size + 8))
3412	{
3413		if (menu_list[0].argument != MENU_WARN)
3414			max_height = vert_size + 8;
3415		else
3416			max_height = vert_size + 7;
3417		top_offset = 4;
3418	}
3419	x_off = (COLS - max_width) / 2;
3420	y_off = (LINES - max_height - 1) / 2;
3421	temp_win = newwin(max_height, max_width, y_off, x_off);
3422	keypad(temp_win, TRUE);
3423
3424	paint_menu(menu_list, max_width, max_height, list_size, top_offset, temp_win, off_start, vert_size);
3425
3426	counter = 1;
3427	vert_pos = 0;
3428	do
3429	{
3430		if (off_start > 2)
3431			wmove(temp_win, (1 + counter + top_offset - off_start), 3);
3432		else
3433			wmove(temp_win, (counter + top_offset - off_start), 3);
3434
3435		wrefresh(temp_win);
3436		in = wgetch(temp_win);
3437		input = in;
3438		if (input == -1)
3439			exit(0);
3440
3441		if (((tolower(input) >= 'a') && (tolower(input) <= 'z')) ||
3442		    ((input >= '0') && (input <= '9')))
3443		{
3444			if ((tolower(input) >= 'a') && (tolower(input) <= 'z'))
3445			{
3446				temp = 1 + tolower(input) - 'a';
3447			}
3448			else if ((input >= '0') && (input <= '9'))
3449			{
3450				temp = (2 + 'z' - 'a') + (input - '0');
3451			}
3452
3453			if (temp <= list_size)
3454			{
3455				input = '\n';
3456				counter = temp;
3457			}
3458		}
3459		else
3460		{
3461			switch (input)
3462			{
3463				case ' ':	/* space	*/
3464				case '\004':	/* ^d, down	*/
3465				case KEY_RIGHT:
3466				case KEY_DOWN:
3467					counter++;
3468					if (counter > list_size)
3469						counter = 1;
3470					break;
3471				case '\010':	/* ^h, backspace*/
3472				case '\025':	/* ^u, up	*/
3473				case 127:	/* ^?, delete	*/
3474				case KEY_BACKSPACE:
3475				case KEY_LEFT:
3476				case KEY_UP:
3477					counter--;
3478					if (counter == 0)
3479						counter = list_size;
3480					break;
3481				case '\033':	/* escape key	*/
3482					if (menu_list[0].argument != MENU_WARN)
3483						counter = 0;
3484					break;
3485				case '\014':	/* ^l       	*/
3486				case '\022':	/* ^r, redraw	*/
3487					paint_menu(menu_list, max_width, max_height,
3488						list_size, top_offset, temp_win,
3489						off_start, vert_size);
3490					break;
3491				default:
3492					break;
3493			}
3494		}
3495
3496		if (((list_size - off_start) >= (vert_size - 1)) &&
3497			(counter > (off_start + vert_size - 3)) &&
3498				(off_start > 1))
3499		{
3500			if (counter == list_size)
3501				off_start = (list_size - vert_size) + 2;
3502			else
3503				off_start++;
3504
3505			paint_menu(menu_list, max_width, max_height,
3506				   list_size, top_offset, temp_win, off_start,
3507				   vert_size);
3508		}
3509		else if ((list_size != vert_size) &&
3510				(counter > (off_start + vert_size - 2)))
3511		{
3512			if (counter == list_size)
3513				off_start = 2 + (list_size - vert_size);
3514			else if (off_start == 1)
3515				off_start = 3;
3516			else
3517				off_start++;
3518
3519			paint_menu(menu_list, max_width, max_height,
3520				   list_size, top_offset, temp_win, off_start,
3521				   vert_size);
3522		}
3523		else if (counter < off_start)
3524		{
3525			if (counter <= 2)
3526				off_start = 1;
3527			else
3528				off_start = counter;
3529
3530			paint_menu(menu_list, max_width, max_height,
3531				   list_size, top_offset, temp_win, off_start,
3532				   vert_size);
3533		}
3534	}
3535	while ((input != '\r') && (input != '\n') && (counter != 0));
3536
3537	werase(temp_win);
3538	wrefresh(temp_win);
3539	delwin(temp_win);
3540
3541	if ((menu_list[counter].procedure != NULL) ||
3542	    (menu_list[counter].iprocedure != NULL) ||
3543	    (menu_list[counter].nprocedure != NULL))
3544	{
3545		if (menu_list[counter].argument != -1)
3546			(*menu_list[counter].iprocedure)(menu_list[counter].argument);
3547		else if (menu_list[counter].ptr_argument != NULL)
3548			(*menu_list[counter].procedure)(menu_list[counter].ptr_argument);
3549		else
3550			(*menu_list[counter].nprocedure)();
3551	}
3552
3553	if (info_window)
3554		paint_info_win();
3555	redraw();
3556
3557	return(counter);
3558}
3559
3560void
3561paint_menu(menu_list, max_width, max_height, list_size, top_offset, menu_win,
3562	   off_start, vert_size)
3563struct menu_entries menu_list[];
3564int max_width, max_height, list_size, top_offset;
3565WINDOW *menu_win;
3566int off_start, vert_size;
3567{
3568	int counter, temp_int;
3569
3570	werase(menu_win);
3571
3572	/*
3573	 |	output top and bottom portions of menu box only if window
3574	 |	large enough
3575	 */
3576
3577	if (max_height > vert_size)
3578	{
3579		wmove(menu_win, 1, 1);
3580		if (!nohighlight)
3581			wstandout(menu_win);
3582		waddch(menu_win, '+');
3583		for (counter = 0; counter < (max_width - 4); counter++)
3584			waddch(menu_win, '-');
3585		waddch(menu_win, '+');
3586
3587		wmove(menu_win, (max_height - 2), 1);
3588		waddch(menu_win, '+');
3589		for (counter = 0; counter < (max_width - 4); counter++)
3590			waddch(menu_win, '-');
3591		waddch(menu_win, '+');
3592		wstandend(menu_win);
3593		wmove(menu_win, 2, 3);
3594		waddstr(menu_win, menu_list[0].item_string);
3595		wmove(menu_win, (max_height - 3), 3);
3596		if (menu_list[0].argument != MENU_WARN)
3597			waddstr(menu_win, menu_cancel_msg);
3598	}
3599	if (!nohighlight)
3600		wstandout(menu_win);
3601
3602	for (counter = 0; counter < (vert_size + top_offset); counter++)
3603	{
3604		if (top_offset == 4)
3605		{
3606			temp_int = counter + 2;
3607		}
3608		else
3609			temp_int = counter;
3610
3611		wmove(menu_win, temp_int, 1);
3612		waddch(menu_win, '|');
3613		wmove(menu_win, temp_int, (max_width - 2));
3614		waddch(menu_win, '|');
3615	}
3616	wstandend(menu_win);
3617
3618	if (list_size > vert_size)
3619	{
3620		if (off_start >= 3)
3621		{
3622			temp_int = 1;
3623			wmove(menu_win, top_offset, 3);
3624			waddstr(menu_win, more_above_str);
3625		}
3626		else
3627			temp_int = 0;
3628
3629		for (counter = off_start;
3630			((temp_int + counter - off_start) < (vert_size - 1));
3631				counter++)
3632		{
3633			wmove(menu_win, (top_offset + temp_int +
3634						(counter - off_start)), 3);
3635			if (list_size > 1)
3636				wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
3637			waddstr(menu_win, menu_list[counter].item_string);
3638		}
3639
3640		wmove(menu_win, (top_offset + (vert_size - 1)), 3);
3641
3642		if (counter == list_size)
3643		{
3644			if (list_size > 1)
3645				wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
3646			wprintw(menu_win, menu_list[counter].item_string);
3647		}
3648		else
3649			wprintw(menu_win, more_below_str);
3650	}
3651	else
3652	{
3653		for (counter = 1; counter <= list_size; counter++)
3654		{
3655			wmove(menu_win, (top_offset + counter - 1), 3);
3656			if (list_size > 1)
3657				wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
3658			waddstr(menu_win, menu_list[counter].item_string);
3659		}
3660	}
3661}
3662
3663void
3664help()
3665{
3666	int counter;
3667
3668	werase(help_win);
3669	clearok(help_win, TRUE);
3670	for (counter = 0; counter < 22; counter++)
3671	{
3672		wmove(help_win, counter, 0);
3673		waddstr(help_win, (emacs_keys_mode) ?
3674			emacs_help_text[counter] : help_text[counter]);
3675	}
3676	wrefresh(help_win);
3677	werase(com_win);
3678	wmove(com_win, 0, 0);
3679	wprintw(com_win, press_any_key_msg);
3680	wrefresh(com_win);
3681	counter = wgetch(com_win);
3682	if (counter == -1)
3683		exit(0);
3684	werase(com_win);
3685	wmove(com_win, 0, 0);
3686	werase(help_win);
3687	wrefresh(help_win);
3688	wrefresh(com_win);
3689	redraw();
3690}
3691
3692void
3693paint_info_win()
3694{
3695	int counter;
3696
3697	if (!info_window)
3698		return;
3699
3700	werase(info_win);
3701	for (counter = 0; counter < 5; counter++)
3702	{
3703		wmove(info_win, counter, 0);
3704		wclrtoeol(info_win);
3705		if (info_type == CONTROL_KEYS)
3706			waddstr(info_win, (emacs_keys_mode) ?
3707			  emacs_control_keys[counter] : control_keys[counter]);
3708		else if (info_type == COMMANDS)
3709			waddstr(info_win, command_strings[counter]);
3710	}
3711	wmove(info_win, 5, 0);
3712	if (!nohighlight)
3713		wstandout(info_win);
3714	waddstr(info_win, separator);
3715	wstandend(info_win);
3716	wrefresh(info_win);
3717}
3718
3719void
3720no_info_window()
3721{
3722	if (!info_window)
3723		return;
3724	delwin(info_win);
3725	delwin(text_win);
3726	info_window = FALSE;
3727	last_line = LINES - 2;
3728	text_win = newwin((LINES - 1), COLS, 0, 0);
3729	keypad(text_win, TRUE);
3730	idlok(text_win, TRUE);
3731	clearok(text_win, TRUE);
3732	midscreen(scr_vert, point);
3733	wrefresh(text_win);
3734	clear_com_win = TRUE;
3735}
3736
3737void
3738create_info_window()
3739{
3740	if (info_window)
3741		return;
3742	last_line = LINES - 8;
3743	delwin(text_win);
3744	text_win = newwin((LINES - 7), COLS, 6, 0);
3745	keypad(text_win, TRUE);
3746	idlok(text_win, TRUE);
3747	werase(text_win);
3748	info_window = TRUE;
3749	info_win = newwin(6, COLS, 0, 0);
3750	werase(info_win);
3751	info_type = CONTROL_KEYS;
3752	midscreen(min(scr_vert, last_line), point);
3753	clearok(info_win, TRUE);
3754	paint_info_win();
3755	wrefresh(text_win);
3756	clear_com_win = TRUE;
3757}
3758
3759int
3760file_op(arg)
3761int arg;
3762{
3763	char *string;
3764	int flag;
3765
3766	if (restrict_mode())
3767	{
3768		return(0);
3769	}
3770
3771	if (arg == READ_FILE)
3772	{
3773		string = get_string(file_read_prompt_str, TRUE);
3774		recv_file = TRUE;
3775		tmp_file = resolve_name(string);
3776		check_fp();
3777		if (tmp_file != string)
3778			free(tmp_file);
3779		free(string);
3780	}
3781	else if (arg == WRITE_FILE)
3782	{
3783		string = get_string(file_write_prompt_str, TRUE);
3784		tmp_file = resolve_name(string);
3785		write_file(tmp_file, 1);
3786		if (tmp_file != string)
3787			free(tmp_file);
3788		free(string);
3789	}
3790	else if (arg == SAVE_FILE)
3791	{
3792	/*
3793	 |	changes made here should be reflected in finish()
3794	 */
3795
3796		if (in_file_name)
3797			flag = TRUE;
3798		else
3799			flag = FALSE;
3800
3801		string = in_file_name;
3802		if ((string == NULL) || (*string == '\0'))
3803			string = get_string(save_file_name_prompt, TRUE);
3804		if ((string == NULL) || (*string == '\0'))
3805		{
3806			wmove(com_win, 0, 0);
3807			wprintw(com_win, file_not_saved_msg);
3808			wclrtoeol(com_win);
3809			wrefresh(com_win);
3810			clear_com_win = TRUE;
3811			return(0);
3812		}
3813		if (!flag)
3814		{
3815			tmp_file = resolve_name(string);
3816			if (tmp_file != string)
3817			{
3818				free(string);
3819				string = tmp_file;
3820			}
3821		}
3822		if (write_file(string, 1))
3823		{
3824			in_file_name = string;
3825			text_changes = FALSE;
3826		}
3827		else if (!flag)
3828			free(string);
3829	}
3830	return(0);
3831}
3832
3833void
3834shell_op()
3835{
3836	char *string;
3837
3838	if (((string = get_string(shell_prompt, TRUE)) != NULL) &&
3839			(*string != '\0'))
3840	{
3841		sh_command(string);
3842		free(string);
3843	}
3844}
3845
3846void
3847leave_op()
3848{
3849	if (text_changes)
3850	{
3851		menu_op(leave_menu);
3852	}
3853	else
3854		quit(TRUE);
3855}
3856
3857void
3858redraw()
3859{
3860	if (info_window)
3861        {
3862                clearok(info_win, TRUE);
3863        	paint_info_win();
3864        }
3865        else
3866		clearok(text_win, TRUE);
3867	midscreen(scr_vert, point);
3868}
3869
3870/*
3871 |	The following routines will "format" a paragraph (as defined by a
3872 |	block of text with blank lines before and after the block).
3873 */
3874
3875int
3876Blank_Line(test_line)	/* test if line has any non-space characters	*/
3877struct text *test_line;
3878{
3879	unsigned char *line;
3880	int length;
3881
3882	if (test_line == NULL)
3883		return(TRUE);
3884
3885	length = 1;
3886	line = test_line->line;
3887
3888	/*
3889	 |	To handle troff/nroff documents, consider a line with a
3890	 |	period ('.') in the first column to be blank.  To handle mail
3891	 |	messages with included text, consider a line with a '>' blank.
3892	 */
3893
3894	if ((*line == '.') || (*line == '>'))
3895		return(TRUE);
3896
3897	while (((*line == ' ') || (*line == '\t')) && (length < test_line->line_length))
3898	{
3899		length++;
3900		line++;
3901	}
3902	if (length != test_line->line_length)
3903		return(FALSE);
3904	else
3905		return(TRUE);
3906}
3907
3908void
3909Format()	/* format the paragraph according to set margins	*/
3910{
3911	int string_count;
3912	int offset;
3913	int temp_case;
3914	int status;
3915	int tmp_af;
3916	int counter;
3917	unsigned char *line;
3918	unsigned char *tmp_srchstr;
3919	unsigned char *temp1, *temp2;
3920	unsigned char *temp_dword;
3921	unsigned char temp_d_char[3];
3922
3923	temp_d_char[0] = d_char[0];
3924	temp_d_char[1] = d_char[1];
3925	temp_d_char[2] = d_char[2];
3926
3927/*
3928 |	if observ_margins is not set, or the current line is blank,
3929 |	do not format the current paragraph
3930 */
3931
3932	if ((!observ_margins) || (Blank_Line(curr_line)))
3933		return;
3934
3935/*
3936 |	save the currently set flags, and clear them
3937 */
3938
3939	wmove(com_win, 0, 0);
3940	wclrtoeol(com_win);
3941	wprintw(com_win, formatting_msg);
3942	wrefresh(com_win);
3943
3944/*
3945 |	get current position in paragraph, so after formatting, the cursor
3946 |	will be in the same relative position
3947 */
3948
3949	tmp_af = auto_format;
3950	auto_format = FALSE;
3951	offset = position;
3952	if (position != 1)
3953		prev_word();
3954	temp_dword = d_word;
3955	d_word = NULL;
3956	temp_case = case_sen;
3957	case_sen = TRUE;
3958	tmp_srchstr = srch_str;
3959	temp2 = srch_str = (unsigned char *) malloc(1 + curr_line->line_length - position);
3960	if ((*point == ' ') || (*point == '\t'))
3961		adv_word();
3962	offset -= position;
3963	counter = position;
3964	line = temp1 = point;
3965	while ((*temp1 != '\0') && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length))
3966	{
3967		*temp2 = *temp1;
3968		temp2++;
3969		temp1++;
3970		counter++;
3971	}
3972	*temp2 = '\0';
3973	if (position != 1)
3974		bol();
3975	while (!Blank_Line(curr_line->prev_line))
3976		bol();
3977	string_count = 0;
3978	status = TRUE;
3979	while ((line != point) && (status))
3980	{
3981		status = search(FALSE);
3982		string_count++;
3983	}
3984
3985	wmove(com_win, 0, 0);
3986	wclrtoeol(com_win);
3987	wprintw(com_win, formatting_msg);
3988	wrefresh(com_win);
3989
3990/*
3991 |	now get back to the start of the paragraph to start formatting
3992 */
3993
3994	if (position != 1)
3995		bol();
3996	while (!Blank_Line(curr_line->prev_line))
3997		bol();
3998
3999	observ_margins = FALSE;
4000
4001/*
4002 |	Start going through lines, putting spaces at end of lines if they do
4003 |	not already exist.  Append lines together to get one long line, and
4004 |	eliminate spacing at begin of lines.
4005 */
4006
4007	while (!Blank_Line(curr_line->next_line))
4008	{
4009		eol();
4010		left(TRUE);
4011		if (*point != ' ')
4012		{
4013			right(TRUE);
4014			insert(' ');
4015		}
4016		else
4017			right(TRUE);
4018		del_char();
4019		if ((*point == ' ') || (*point == '\t'))
4020			del_word();
4021	}
4022
4023/*
4024 |	Now there is one long line.  Eliminate extra spaces within the line
4025 |	after the first word (so as not to blow away any indenting the user
4026 |	may have put in).
4027 */
4028
4029	bol();
4030	adv_word();
4031	while (position < curr_line->line_length)
4032	{
4033		if ((*point == ' ') && (*(point + 1) == ' '))
4034			del_char();
4035		else
4036			right(TRUE);
4037	}
4038
4039/*
4040 |	Now make sure there are two spaces after a '.'.
4041 */
4042
4043	bol();
4044	while (position < curr_line->line_length)
4045	{
4046		if ((*point == '.') && (*(point + 1) == ' '))
4047		{
4048			right(TRUE);
4049			insert(' ');
4050			insert(' ');
4051			while (*point == ' ')
4052				del_char();
4053		}
4054		right(TRUE);
4055	}
4056
4057	observ_margins = TRUE;
4058	bol();
4059
4060	wmove(com_win, 0, 0);
4061	wclrtoeol(com_win);
4062	wprintw(com_win, formatting_msg);
4063	wrefresh(com_win);
4064
4065/*
4066 |	create lines between margins
4067 */
4068
4069	while (position < curr_line->line_length)
4070	{
4071		while ((scr_pos < right_margin) && (position < curr_line->line_length))
4072			right(TRUE);
4073		if (position < curr_line->line_length)
4074		{
4075			prev_word();
4076			if (position == 1)
4077				adv_word();
4078			insert_line(TRUE);
4079		}
4080	}
4081
4082/*
4083 |	go back to begin of paragraph, put cursor back to original position
4084 */
4085
4086	bol();
4087	while (!Blank_Line(curr_line->prev_line))
4088		bol();
4089
4090/*
4091 |	find word cursor was in
4092 */
4093
4094	while ((status) && (string_count > 0))
4095	{
4096		search(FALSE);
4097		string_count--;
4098	}
4099
4100/*
4101 |	offset the cursor to where it was before from the start of the word
4102 */
4103
4104	while (offset > 0)
4105	{
4106		offset--;
4107		right(TRUE);
4108	}
4109
4110/*
4111 |	reset flags and strings to what they were before formatting
4112 */
4113
4114	if (d_word != NULL)
4115		free(d_word);
4116	d_word = temp_dword;
4117	case_sen = temp_case;
4118	free(srch_str);
4119	srch_str = tmp_srchstr;
4120	d_char[0] = temp_d_char[0];
4121	d_char[1] = temp_d_char[1];
4122	d_char[2] = temp_d_char[2];
4123	auto_format = tmp_af;
4124
4125	midscreen(scr_vert, point);
4126	werase(com_win);
4127	wrefresh(com_win);
4128}
4129
4130unsigned char *init_name[3] = {
4131	"/usr/share/misc/init.ee",
4132	NULL,
4133	".init.ee"
4134	};
4135
4136void
4137ee_init()	/* check for init file and read it if it exists	*/
4138{
4139	FILE *init_file;
4140	unsigned char *string;
4141	unsigned char *str1;
4142	unsigned char *str2;
4143	char *home;
4144	int counter;
4145	int temp_int;
4146
4147	string = getenv("HOME");
4148	if (string == NULL)
4149		string = "/tmp";
4150	str1 = home = malloc(strlen(string)+10);
4151	strcpy(home, string);
4152	strcat(home, "/.init.ee");
4153	init_name[1] = home;
4154	string = malloc(512);
4155
4156	for (counter = 0; counter < 3; counter++)
4157	{
4158		if (!(access(init_name[counter], 4)))
4159		{
4160			init_file = fopen(init_name[counter], "r");
4161			while ((str2 = fgets(string, 512, init_file)) != NULL)
4162			{
4163				str1 = str2 = string;
4164				while (*str2 != '\n')
4165					str2++;
4166				*str2 = '\0';
4167
4168				if (unique_test(string, init_strings) != 1)
4169					continue;
4170
4171				if (compare(str1, CASE, FALSE))
4172					case_sen = TRUE;
4173				else if (compare(str1, NOCASE, FALSE))
4174					case_sen = FALSE;
4175				else if (compare(str1, EXPAND, FALSE))
4176					expand_tabs = TRUE;
4177				else if (compare(str1, NOEXPAND, FALSE))
4178					expand_tabs = FALSE;
4179				else if (compare(str1, INFO, FALSE))
4180					info_window = TRUE;
4181				else if (compare(str1, NOINFO, FALSE))
4182					info_window = FALSE;
4183				else if (compare(str1, MARGINS, FALSE))
4184					observ_margins = TRUE;
4185				else if (compare(str1, NOMARGINS, FALSE))
4186					observ_margins = FALSE;
4187				else if (compare(str1, AUTOFORMAT, FALSE))
4188				{
4189					auto_format = TRUE;
4190					observ_margins = TRUE;
4191				}
4192				else if (compare(str1, NOAUTOFORMAT, FALSE))
4193					auto_format = FALSE;
4194				else if (compare(str1, Echo, FALSE))
4195				{
4196					str1 = next_word(str1);
4197					if (*str1 != '\0')
4198						echo_string(str1);
4199				}
4200				else if (compare(str1, PRINTCOMMAND, FALSE))
4201				{
4202					str1 = next_word(str1);
4203					print_command = malloc(strlen(str1)+1);
4204					strcpy(print_command, str1);
4205				}
4206				else if (compare(str1, RIGHTMARGIN, FALSE))
4207				{
4208					str1 = next_word(str1);
4209					if ((*str1 >= '0') && (*str1 <= '9'))
4210					{
4211						temp_int = atoi(str1);
4212						if (temp_int > 0)
4213							right_margin = temp_int;
4214					}
4215				}
4216				else if (compare(str1, HIGHLIGHT, FALSE))
4217					nohighlight = FALSE;
4218				else if (compare(str1, NOHIGHLIGHT, FALSE))
4219					nohighlight = TRUE;
4220				else if (compare(str1, EIGHTBIT, FALSE))
4221					eightbit = TRUE;
4222				else if (compare(str1, NOEIGHTBIT, FALSE))
4223				{
4224					eightbit = FALSE;
4225					ee_chinese = FALSE;
4226				}
4227				else if (compare(str1, EMACS_string, FALSE))
4228					emacs_keys_mode = TRUE;
4229				else if (compare(str1, NOEMACS_string, FALSE))
4230					emacs_keys_mode = FALSE;
4231				else if (compare(str1, chinese_cmd, FALSE))
4232				{
4233					ee_chinese = TRUE;
4234					eightbit = TRUE;
4235				}
4236				else if (compare(str1, nochinese_cmd, FALSE))
4237					ee_chinese = FALSE;
4238			}
4239			fclose(init_file);
4240		}
4241	}
4242	free(string);
4243	free(home);
4244
4245	string = getenv("LANG");
4246	if (string != NULL)
4247	{
4248		if (strcmp(string, "zh_TW.big5") == 0)
4249		{
4250			ee_chinese = TRUE;
4251			eightbit = TRUE;
4252		}
4253	}
4254}
4255
4256/*
4257 |	Save current configuration to .init.ee file in the current directory.
4258 */
4259
4260void
4261dump_ee_conf()
4262{
4263	FILE *init_file;
4264	FILE *old_init_file = NULL;
4265	char *file_name = ".init.ee";
4266	char *home_dir =  "~/.init.ee";
4267	char buffer[512];
4268	struct stat buf;
4269	char *string;
4270	int length;
4271	int option = 0;
4272
4273	if (restrict_mode())
4274	{
4275		return;
4276	}
4277
4278	option = menu_op(config_dump_menu);
4279
4280	werase(com_win);
4281	wmove(com_win, 0, 0);
4282
4283	if (option == 0)
4284	{
4285		wprintw(com_win, conf_not_saved_msg);
4286		wrefresh(com_win);
4287		return;
4288	}
4289	else if (option == 2)
4290		file_name = resolve_name(home_dir);
4291
4292	/*
4293	 |	If a .init.ee file exists, move it to .init.ee.old.
4294	 */
4295
4296	if (stat(file_name, &buf) != -1)
4297	{
4298		sprintf(buffer, "%s.old", file_name);
4299		unlink(buffer);
4300		link(file_name, buffer);
4301		unlink(file_name);
4302		old_init_file = fopen(buffer, "r");
4303	}
4304
4305	init_file = fopen(file_name, "w");
4306	if (init_file == NULL)
4307	{
4308		wprintw(com_win, conf_dump_err_msg);
4309		wrefresh(com_win);
4310		return;
4311	}
4312
4313	if (old_init_file != NULL)
4314	{
4315		/*
4316		 |	Copy non-configuration info into new .init.ee file.
4317		 */
4318		while ((string = fgets(buffer, 512, old_init_file)) != NULL)
4319		{
4320			length = strlen(string);
4321			string[length - 1] = '\0';
4322
4323			if (unique_test(string, init_strings) == 1)
4324			{
4325				if (compare(string, Echo, FALSE))
4326				{
4327					fprintf(init_file, "%s\n", string);
4328				}
4329			}
4330			else
4331				fprintf(init_file, "%s\n", string);
4332		}
4333
4334		fclose(old_init_file);
4335	}
4336
4337	fprintf(init_file, "%s\n", case_sen ? CASE : NOCASE);
4338	fprintf(init_file, "%s\n", expand_tabs ? EXPAND : NOEXPAND);
4339	fprintf(init_file, "%s\n", info_window ? INFO : NOINFO );
4340	fprintf(init_file, "%s\n", observ_margins ? MARGINS : NOMARGINS );
4341	fprintf(init_file, "%s\n", auto_format ? AUTOFORMAT : NOAUTOFORMAT );
4342	fprintf(init_file, "%s %s\n", PRINTCOMMAND, print_command);
4343	fprintf(init_file, "%s %d\n", RIGHTMARGIN, right_margin);
4344	fprintf(init_file, "%s\n", nohighlight ? NOHIGHLIGHT : HIGHLIGHT );
4345	fprintf(init_file, "%s\n", eightbit ? EIGHTBIT : NOEIGHTBIT );
4346	fprintf(init_file, "%s\n", emacs_keys_mode ? EMACS_string : NOEMACS_string );
4347	fprintf(init_file, "%s\n", ee_chinese ? chinese_cmd : nochinese_cmd );
4348
4349	fclose(init_file);
4350
4351	wprintw(com_win, conf_dump_success_msg, file_name);
4352	wrefresh(com_win);
4353
4354	if ((option == 2) && (file_name != home_dir))
4355	{
4356		free(file_name);
4357	}
4358}
4359
4360void
4361echo_string(string)	/* echo the given string	*/
4362char *string;
4363{
4364	char *temp;
4365	int Counter;
4366
4367		temp = string;
4368		while (*temp != '\0')
4369		{
4370			if (*temp == '\\')
4371			{
4372				temp++;
4373				if (*temp == 'n')
4374					putchar('\n');
4375				else if (*temp == 't')
4376					putchar('\t');
4377				else if (*temp == 'b')
4378					putchar('\b');
4379				else if (*temp == 'r')
4380					putchar('\r');
4381				else if (*temp == 'f')
4382					putchar('\f');
4383				else if ((*temp == 'e') || (*temp == 'E'))
4384					putchar('\033');	/* escape */
4385				else if (*temp == '\\')
4386					putchar('\\');
4387				else if (*temp == '\'')
4388					putchar('\'');
4389				else if ((*temp >= '0') && (*temp <= '9'))
4390				{
4391					Counter = 0;
4392					while ((*temp >= '0') && (*temp <= '9'))
4393					{
4394						Counter = (8 * Counter) + (*temp - '0');
4395						temp++;
4396					}
4397					putchar(Counter);
4398					temp--;
4399				}
4400				temp++;
4401			}
4402			else
4403			{
4404				putchar(*temp);
4405				temp++;
4406			}
4407		}
4408
4409	fflush(stdout);
4410}
4411
4412void
4413spell_op()	/* check spelling of words in the editor	*/
4414{
4415	if (restrict_mode())
4416	{
4417		return;
4418	}
4419	top();			/* go to top of file		*/
4420	insert_line(FALSE);	/* create two blank lines	*/
4421	insert_line(FALSE);
4422	top();
4423	command(shell_echo_msg);
4424	adv_line();
4425	wmove(com_win, 0, 0);
4426	wprintw(com_win, spell_in_prog_msg);
4427	wrefresh(com_win);
4428	command("<>!spell");	/* send contents of buffer to command 'spell'
4429				   and read the results back into the editor */
4430}
4431
4432void
4433ispell_op()
4434{
4435	char template[128], *name;
4436	char string[256];
4437	int fd;
4438
4439	if (restrict_mode())
4440	{
4441		return;
4442	}
4443	(void)sprintf(template, "/tmp/ee.XXXXXXXX");
4444	fd = mkstemp(template);
4445	if (fd < 0) {
4446		wmove(com_win, 0, 0);
4447		wprintw(com_win, create_file_fail_msg, name);
4448		wrefresh(com_win);
4449		return;
4450	}
4451	close(fd);
4452	if (write_file(name, 0))
4453	{
4454		sprintf(string, "ispell %s", name);
4455		sh_command(string);
4456		delete_text();
4457		tmp_file = name;
4458		recv_file = TRUE;
4459		check_fp();
4460		unlink(name);
4461	}
4462}
4463
4464int
4465first_word_len(test_line)
4466struct text *test_line;
4467{
4468	int counter;
4469	unsigned char *pnt;
4470
4471	if (test_line == NULL)
4472		return(0);
4473
4474	pnt = test_line->line;
4475	if ((pnt == NULL) || (*pnt == '\0') ||
4476	    (*pnt == '.') || (*pnt == '>'))
4477		return(0);
4478
4479	if ((*pnt == ' ') || (*pnt == '\t'))
4480	{
4481		pnt = next_word(pnt);
4482	}
4483
4484	if (*pnt == '\0')
4485		return(0);
4486
4487	counter = 0;
4488	while ((*pnt != '\0') && ((*pnt != ' ') && (*pnt != '\t')))
4489	{
4490		pnt++;
4491		counter++;
4492	}
4493	while ((*pnt != '\0') && ((*pnt == ' ') || (*pnt == '\t')))
4494	{
4495		pnt++;
4496		counter++;
4497	}
4498	return(counter);
4499}
4500
4501void
4502Auto_Format()	/* format the paragraph according to set margins	*/
4503{
4504	int string_count;
4505	int offset;
4506	int temp_case;
4507	int word_len;
4508	int temp_dwl;
4509	int tmp_d_line_length;
4510	int leave_loop = FALSE;
4511	int status;
4512	int counter;
4513	char not_blank;
4514	unsigned char *line;
4515	unsigned char *tmp_srchstr;
4516	unsigned char *temp1, *temp2;
4517	unsigned char *temp_dword;
4518	unsigned char temp_d_char[3];
4519	unsigned char *tmp_d_line;
4520
4521
4522	temp_d_char[0] = d_char[0];
4523	temp_d_char[1] = d_char[1];
4524	temp_d_char[2] = d_char[2];
4525
4526/*
4527 |	if observ_margins is not set, or the current line is blank,
4528 |	do not format the current paragraph
4529 */
4530
4531	if ((!observ_margins) || (Blank_Line(curr_line)))
4532		return;
4533
4534/*
4535 |	get current position in paragraph, so after formatting, the cursor
4536 |	will be in the same relative position
4537 */
4538
4539	tmp_d_line = d_line;
4540	tmp_d_line_length = dlt_line->line_length;
4541	d_line = NULL;
4542	auto_format = FALSE;
4543	offset = position;
4544	if ((position != 1) && ((*point == ' ') || (*point == '\t') || (position == curr_line->line_length) || (*point == '\0')))
4545		prev_word();
4546	temp_dword = d_word;
4547	temp_dwl = d_wrd_len;
4548	d_wrd_len = 0;
4549	d_word = NULL;
4550	temp_case = case_sen;
4551	case_sen = TRUE;
4552	tmp_srchstr = srch_str;
4553	temp2 = srch_str = (unsigned char *) malloc(1 + curr_line->line_length - position);
4554	if ((*point == ' ') || (*point == '\t'))
4555		adv_word();
4556	offset -= position;
4557	counter = position;
4558	line = temp1 = point;
4559	while ((*temp1 != '\0') && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length))
4560	{
4561		*temp2 = *temp1;
4562		temp2++;
4563		temp1++;
4564		counter++;
4565	}
4566	*temp2 = '\0';
4567	if (position != 1)
4568		bol();
4569	while (!Blank_Line(curr_line->prev_line))
4570		bol();
4571	string_count = 0;
4572	status = TRUE;
4573	while ((line != point) && (status))
4574	{
4575		status = search(FALSE);
4576		string_count++;
4577	}
4578
4579/*
4580 |	now get back to the start of the paragraph to start checking
4581 */
4582
4583	if (position != 1)
4584		bol();
4585	while (!Blank_Line(curr_line->prev_line))
4586		bol();
4587
4588/*
4589 |	Start going through lines, putting spaces at end of lines if they do
4590 |	not already exist.  Check line length, and move words to the next line
4591 |	if they cross the margin.  Then get words from the next line if they
4592 |	will fit in before the margin.
4593 */
4594
4595	counter = 0;
4596
4597	while (!leave_loop)
4598	{
4599		if (position != curr_line->line_length)
4600			eol();
4601		left(TRUE);
4602		if (*point != ' ')
4603		{
4604			right(TRUE);
4605			insert(' ');
4606		}
4607		else
4608			right(TRUE);
4609
4610		not_blank = FALSE;
4611
4612		/*
4613		 |	fill line if first word on next line will fit
4614		 |	in the line without crossing the margin
4615		 */
4616
4617		while ((curr_line->next_line != NULL) &&
4618		       ((word_len = first_word_len(curr_line->next_line)) > 0)
4619			&& ((scr_pos + word_len) < right_margin))
4620		{
4621			adv_line();
4622			if ((*point == ' ') || (*point == '\t'))
4623				adv_word();
4624			del_word();
4625			if (position != 1)
4626				bol();
4627
4628			/*
4629			 |	We know this line was not blank before, so
4630			 |	make sure that it doesn't have one of the
4631			 |	leading characters that indicate the line
4632			 |	should not be modified.
4633			 |
4634			 |	We also know that this character should not
4635			 |	be left as the first character of this line.
4636			 */
4637
4638			if ((Blank_Line(curr_line)) &&
4639			    (curr_line->line[0] != '.') &&
4640			    (curr_line->line[0] != '>'))
4641			{
4642				del_line();
4643				not_blank = FALSE;
4644			}
4645			else
4646				not_blank = TRUE;
4647
4648			/*
4649			 |   go to end of previous line
4650			 */
4651			left(TRUE);
4652			undel_word();
4653			eol();
4654			/*
4655			 |   make sure there's a space at the end of the line
4656			 */
4657			left(TRUE);
4658			if (*point != ' ')
4659			{
4660				right(TRUE);
4661				insert(' ');
4662			}
4663			else
4664				right(TRUE);
4665		}
4666
4667		/*
4668		 |	make sure line does not cross right margin
4669		 */
4670
4671		while (right_margin <= scr_pos)
4672		{
4673			prev_word();
4674			if (position != 1)
4675			{
4676				del_word();
4677				if (Blank_Line(curr_line->next_line))
4678					insert_line(TRUE);
4679				else
4680					adv_line();
4681				if ((*point == ' ') || (*point == '\t'))
4682					adv_word();
4683				undel_word();
4684				not_blank = TRUE;
4685				if (position != 1)
4686					bol();
4687				left(TRUE);
4688			}
4689		}
4690
4691		if ((!Blank_Line(curr_line->next_line)) || (not_blank))
4692		{
4693			adv_line();
4694			counter++;
4695		}
4696		else
4697			leave_loop = TRUE;
4698	}
4699
4700/*
4701 |	go back to begin of paragraph, put cursor back to original position
4702 */
4703
4704	if (position != 1)
4705		bol();
4706	while ((counter-- > 0) || (!Blank_Line(curr_line->prev_line)))
4707		bol();
4708
4709/*
4710 |	find word cursor was in
4711 */
4712
4713	status = TRUE;
4714	while ((status) && (string_count > 0))
4715	{
4716		status = search(FALSE);
4717		string_count--;
4718	}
4719
4720/*
4721 |	offset the cursor to where it was before from the start of the word
4722 */
4723
4724	while (offset > 0)
4725	{
4726		offset--;
4727		right(TRUE);
4728	}
4729
4730	if ((string_count > 0) && (offset < 0))
4731	{
4732		while (offset < 0)
4733		{
4734			offset++;
4735			left(TRUE);
4736		}
4737	}
4738
4739/*
4740 |	reset flags and strings to what they were before formatting
4741 */
4742
4743	if (d_word != NULL)
4744		free(d_word);
4745	d_word = temp_dword;
4746	d_wrd_len = temp_dwl;
4747	case_sen = temp_case;
4748	free(srch_str);
4749	srch_str = tmp_srchstr;
4750	d_char[0] = temp_d_char[0];
4751	d_char[1] = temp_d_char[1];
4752	d_char[2] = temp_d_char[2];
4753	auto_format = TRUE;
4754	dlt_line->line_length = tmp_d_line_length;
4755	d_line = tmp_d_line;
4756
4757	formatted = TRUE;
4758	midscreen(scr_vert, point);
4759}
4760
4761void
4762modes_op()
4763{
4764	int ret_value;
4765	int counter;
4766	char *string;
4767
4768	do
4769	{
4770		sprintf(modes_menu[1].item_string, "%s %s", mode_strings[1],
4771					(expand_tabs ? ON : OFF));
4772		sprintf(modes_menu[2].item_string, "%s %s", mode_strings[2],
4773					(case_sen ? ON : OFF));
4774		sprintf(modes_menu[3].item_string, "%s %s", mode_strings[3],
4775					(observ_margins ? ON : OFF));
4776		sprintf(modes_menu[4].item_string, "%s %s", mode_strings[4],
4777					(auto_format ? ON : OFF));
4778		sprintf(modes_menu[5].item_string, "%s %s", mode_strings[5],
4779					(eightbit ? ON : OFF));
4780		sprintf(modes_menu[6].item_string, "%s %s", mode_strings[6],
4781					(info_window ? ON : OFF));
4782		sprintf(modes_menu[7].item_string, "%s %s", mode_strings[7],
4783					(emacs_keys_mode ? ON : OFF));
4784		sprintf(modes_menu[8].item_string, "%s %d", mode_strings[8],
4785					right_margin);
4786		sprintf(modes_menu[9].item_string, "%s %s", mode_strings[9],
4787					(ee_chinese ? ON : OFF));
4788
4789		ret_value = menu_op(modes_menu);
4790
4791		switch (ret_value)
4792		{
4793			case 1:
4794				expand_tabs = !expand_tabs;
4795				break;
4796			case 2:
4797				case_sen = !case_sen;
4798				break;
4799			case 3:
4800				observ_margins = !observ_margins;
4801				break;
4802			case 4:
4803				auto_format = !auto_format;
4804				if (auto_format)
4805					observ_margins = TRUE;
4806				break;
4807			case 5:
4808				eightbit = !eightbit;
4809				if (!eightbit)
4810					ee_chinese = FALSE;
4811#ifdef NCURSE
4812				if (ee_chinese)
4813					nc_setattrib(A_NC_BIG5);
4814				else
4815					nc_clearattrib(A_NC_BIG5);
4816#endif /* NCURSE */
4817
4818				redraw();
4819				wnoutrefresh(text_win);
4820				break;
4821			case 6:
4822				if (info_window)
4823					no_info_window();
4824				else
4825					create_info_window();
4826				break;
4827			case 7:
4828				emacs_keys_mode = !emacs_keys_mode;
4829				if (info_window)
4830					paint_info_win();
4831				break;
4832			case 8:
4833				string = get_string(margin_prompt, TRUE);
4834				if (string != NULL)
4835				{
4836					counter = atoi(string);
4837					if (counter > 0)
4838						right_margin = counter;
4839					free(string);
4840				}
4841				break;
4842			case 9:
4843				ee_chinese = !ee_chinese;
4844				if (ee_chinese != FALSE)
4845					eightbit = TRUE;
4846#ifdef NCURSE
4847				if (ee_chinese)
4848					nc_setattrib(A_NC_BIG5);
4849				else
4850					nc_clearattrib(A_NC_BIG5);
4851#endif /* NCURSE */
4852				redraw();
4853				break;
4854			default:
4855				break;
4856		}
4857	}
4858	while (ret_value != 0);
4859}
4860
4861char *
4862is_in_string(string, substring)	/* a strchr() look-alike for systems without
4863				   strchr() */
4864char * string, *substring;
4865{
4866	char *full, *sub;
4867
4868	for (sub = substring; (sub != NULL) && (*sub != '\0'); sub++)
4869	{
4870		for (full = string; (full != NULL) && (*full != '\0');
4871				full++)
4872		{
4873			if (*sub == *full)
4874				return(full);
4875		}
4876	}
4877	return(NULL);
4878}
4879
4880/*
4881 |	handle names of the form "~/file", "~user/file",
4882 |	"$HOME/foo", "~/$FOO", etc.
4883 */
4884
4885char *
4886resolve_name(name)
4887char *name;
4888{
4889	char long_buffer[1024];
4890	char short_buffer[128];
4891	char *buffer;
4892	char *slash;
4893	char *tmp;
4894	char *start_of_var;
4895	int offset;
4896	int index;
4897	int counter;
4898	struct passwd *user;
4899
4900	if (name[0] == '~')
4901	{
4902		if (name[1] == '/')
4903		{
4904			index = getuid();
4905			user = (struct passwd *) getpwuid(index);
4906			slash = name + 1;
4907		}
4908		else
4909		{
4910			slash = strchr(name, '/');
4911			if (slash == NULL)
4912				return(name);
4913			*slash = '\0';
4914			user = (struct passwd *) getpwnam((name + 1));
4915			*slash = '/';
4916		}
4917		if (user == NULL)
4918		{
4919			return(name);
4920		}
4921		buffer = malloc(strlen(user->pw_dir) + strlen(slash) + 1);
4922		strcpy(buffer, user->pw_dir);
4923		strcat(buffer, slash);
4924	}
4925	else
4926		buffer = name;
4927
4928	if (is_in_string(buffer, "$"))
4929	{
4930		tmp = buffer;
4931		index = 0;
4932
4933		while ((*tmp != '\0') && (index < 1024))
4934		{
4935
4936			while ((*tmp != '\0') && (*tmp != '$') &&
4937				(index < 1024))
4938			{
4939				long_buffer[index] = *tmp;
4940				tmp++;
4941				index++;
4942			}
4943
4944			if ((*tmp == '$') && (index < 1024))
4945			{
4946				counter = 0;
4947				start_of_var = tmp;
4948				tmp++;
4949				if (*tmp == '{') /* } */	/* bracketed variable name */
4950				{
4951					tmp++;				/* { */
4952					while ((*tmp != '\0') &&
4953						(*tmp != '}') &&
4954						(counter < 128))
4955					{
4956						short_buffer[counter] = *tmp;
4957						counter++;
4958						tmp++;
4959					}			/* { */
4960					if (*tmp == '}')
4961						tmp++;
4962				}
4963				else
4964				{
4965					while ((*tmp != '\0') &&
4966					       (*tmp != '/') &&
4967					       (*tmp != '$') &&
4968					       (counter < 128))
4969					{
4970						short_buffer[counter] = *tmp;
4971						counter++;
4972						tmp++;
4973					}
4974				}
4975				short_buffer[counter] = '\0';
4976				if ((slash = getenv(short_buffer)) != NULL)
4977				{
4978					offset = strlen(slash);
4979					if ((offset + index) < 1024)
4980						strcpy(&long_buffer[index], slash);
4981					index += offset;
4982				}
4983				else
4984				{
4985					while ((start_of_var != tmp) && (index < 1024))
4986					{
4987						long_buffer[index] = *start_of_var;
4988						start_of_var++;
4989						index++;
4990					}
4991				}
4992			}
4993		}
4994
4995		if (index == 1024)
4996			return(buffer);
4997		else
4998			long_buffer[index] = '\0';
4999
5000		if (name != buffer)
5001			free(buffer);
5002		buffer = malloc(index + 1);
5003		strcpy(buffer, long_buffer);
5004	}
5005
5006	return(buffer);
5007}
5008
5009int
5010restrict_mode()
5011{
5012	if (!restricted)
5013		return(FALSE);
5014
5015	wmove(com_win, 0, 0);
5016	wprintw(com_win, restricted_msg);
5017	wclrtoeol(com_win);
5018	wrefresh(com_win);
5019	clear_com_win = TRUE;
5020	return(TRUE);
5021}
5022
5023/*
5024 |	The following routine tests the input string against the list of
5025 |	strings, to determine if the string is a unique match with one of the
5026 |	valid values.
5027 */
5028
5029int
5030unique_test(string, list)
5031char *string;
5032char *list[];
5033{
5034	int counter;
5035	int num_match;
5036	int result;
5037
5038	num_match = 0;
5039	counter = 0;
5040	while (list[counter] != NULL)
5041	{
5042		result = compare(string, list[counter], FALSE);
5043		if (result)
5044			num_match++;
5045		counter++;
5046	}
5047	return(num_match);
5048}
5049
5050#ifndef NO_CATGETS
5051/*
5052 |	Get the catalog entry, and if it got it from the catalog,
5053 |	make a copy, since the buffer will be overwritten by the
5054 |	next call to catgets().
5055 */
5056
5057char *
5058catgetlocal(number, string)
5059int number;
5060char *string;
5061{
5062	char *temp1;
5063	char *temp2;
5064
5065	temp1 = catgets(catalog, 1, number, string);
5066	if (temp1 != string)
5067	{
5068		temp2 = malloc(strlen(temp1) + 1);
5069		strcpy(temp2, temp1);
5070		temp1 = temp2;
5071	}
5072	return(temp1);
5073}
5074#endif /* NO_CATGETS */
5075
5076/*
5077 |	The following is to allow for using message catalogs which allow
5078 |	the software to be 'localized', that is, to use different languages
5079 |	all with the same binary.  For more information, see your system
5080 |	documentation, or the X/Open Internationalization Guide.
5081 */
5082
5083void
5084strings_init()
5085{
5086	int counter;
5087
5088#ifndef NO_CATGETS
5089	setlocale(LC_ALL, "");
5090	catalog = catopen("ee", NL_CAT_LOCALE);
5091#endif /* NO_CATGETS */
5092
5093	modes_menu[0].item_string = catgetlocal( 1, "modes menu");
5094	mode_strings[1]  = catgetlocal( 2, "tabs to spaces       ");
5095	mode_strings[2]  = catgetlocal( 3, "case sensitive search");
5096	mode_strings[3]  = catgetlocal( 4, "margins observed     ");
5097	mode_strings[4]  = catgetlocal( 5, "auto-paragraph format");
5098	mode_strings[5]  = catgetlocal( 6, "eightbit characters  ");
5099	mode_strings[6]  = catgetlocal( 7, "info window          ");
5100	mode_strings[8]  = catgetlocal( 8, "right margin         ");
5101	leave_menu[0].item_string  = catgetlocal( 9, "leave menu");
5102	leave_menu[1].item_string  = catgetlocal( 10, "save changes");
5103	leave_menu[2].item_string  = catgetlocal( 11, "no save");
5104	file_menu[0].item_string  = catgetlocal( 12, "file menu");
5105	file_menu[1].item_string  = catgetlocal( 13, "read a file");
5106	file_menu[2].item_string  = catgetlocal( 14, "write a file");
5107	file_menu[3].item_string  = catgetlocal( 15, "save file");
5108	file_menu[4].item_string  = catgetlocal( 16, "print editor contents");
5109	search_menu[0].item_string = catgetlocal( 17, "search menu");
5110	search_menu[1].item_string = catgetlocal( 18, "search for ...");
5111	search_menu[2].item_string = catgetlocal( 19, "search");
5112	spell_menu[0].item_string = catgetlocal( 20, "spell menu");
5113	spell_menu[1].item_string = catgetlocal( 21, "use 'spell'");
5114	spell_menu[2].item_string = catgetlocal( 22, "use 'ispell'");
5115	misc_menu[0].item_string = catgetlocal( 23, "miscellaneous menu");
5116	misc_menu[1].item_string = catgetlocal( 24, "format paragraph");
5117	misc_menu[2].item_string = catgetlocal( 25, "shell command");
5118	misc_menu[3].item_string = catgetlocal( 26, "check spelling");
5119	main_menu[0].item_string  = catgetlocal( 27, "main menu");
5120	main_menu[1].item_string  = catgetlocal( 28, "leave editor");
5121	main_menu[2].item_string  = catgetlocal( 29, "help");
5122	main_menu[3].item_string  = catgetlocal( 30, "file operations");
5123	main_menu[4].item_string  = catgetlocal( 31, "redraw screen");
5124	main_menu[5].item_string  = catgetlocal( 32, "settings");
5125	main_menu[6].item_string  = catgetlocal( 33, "search");
5126	main_menu[7].item_string  = catgetlocal( 34, "miscellaneous");
5127	help_text[0] = catgetlocal( 35, "Control keys:                                                              ");
5128	help_text[1] = catgetlocal( 36, "^a ascii code           ^i tab                  ^r right                   ");
5129	help_text[2] = catgetlocal( 37, "^b bottom of text       ^j newline              ^t top of text             ");
5130	help_text[3] = catgetlocal( 38, "^c command              ^k delete char          ^u up                      ");
5131	help_text[4] = catgetlocal( 39, "^d down                 ^l left                 ^v undelete word           ");
5132	help_text[5] = catgetlocal( 40, "^e search prompt        ^m newline              ^w delete word             ");
5133	help_text[6] = catgetlocal( 41, "^f undelete char        ^n next page            ^x search                  ");
5134	help_text[7] = catgetlocal( 42, "^g begin of line        ^o end of line          ^y delete line             ");
5135	help_text[8] = catgetlocal( 43, "^h backspace            ^p prev page            ^z undelete line           ");
5136	help_text[9] = catgetlocal( 44, "^[ (escape) menu        ESC-Enter: exit ee                                 ");
5137	help_text[10] = catgetlocal( 45, "                                                                           ");
5138	help_text[11] = catgetlocal( 46, "Commands:                                                                  ");
5139	help_text[12] = catgetlocal( 47, "help    : get this info                 file    : print file name          ");
5140	help_text[13] = catgetlocal( 48, "read    : read a file                   char    : ascii code of char       ");
5141	help_text[14] = catgetlocal( 49, "write   : write a file                  case    : case sensitive search    ");
5142	help_text[15] = catgetlocal( 50, "exit    : leave and save                nocase  : case insensitive search  ");
5143	help_text[16] = catgetlocal( 51, "quit    : leave, no save                !cmd    : execute \"cmd\" in shell   ");
5144	help_text[17] = catgetlocal( 52, "line    : display line #                0-9     : go to line \"#\"           ");
5145	help_text[18] = catgetlocal( 53, "expand  : expand tabs                   noexpand: do not expand tabs         ");
5146	help_text[19] = catgetlocal( 54, "                                                                             ");
5147	help_text[20] = catgetlocal( 55, "  ee [+#] [-i] [-e] [-h] [file(s)]                                            ");
5148	help_text[21] = catgetlocal( 56, "+# :go to line #  -i :no info window  -e : don't expand tabs  -h :no highlight");
5149	control_keys[0] = catgetlocal( 57, "^[ (escape) menu  ^e search prompt  ^y delete line    ^u up     ^p prev page  ");
5150	control_keys[1] = catgetlocal( 58, "^a ascii code     ^x search         ^z undelete line  ^d down   ^n next page  ");
5151	control_keys[2] = catgetlocal( 59, "^b bottom of text ^g begin of line  ^w delete word    ^l left                 ");
5152	control_keys[3] = catgetlocal( 60, "^t top of text    ^o end of line    ^v undelete word  ^r right                ");
5153	control_keys[4] = catgetlocal( 61, "^c command        ^k delete char    ^f undelete char      ESC-Enter: exit ee  ");
5154	command_strings[0] = catgetlocal( 62, "help : get help info  |file  : print file name         |line : print line # ");
5155	command_strings[1] = catgetlocal( 63, "read : read a file    |char  : ascii code of char      |0-9 : go to line \"#\"");
5156	command_strings[2] = catgetlocal( 64, "write: write a file   |case  : case sensitive search   |exit : leave and save ");
5157	command_strings[3] = catgetlocal( 65, "!cmd : shell \"cmd\"    |nocase: ignore case in search   |quit : leave, no save");
5158	command_strings[4] = catgetlocal( 66, "expand: expand tabs   |noexpand: do not expand tabs                           ");
5159	com_win_message = catgetlocal( 67, "    press Escape (^[) for menu");
5160	no_file_string = catgetlocal( 68, "no file");
5161	ascii_code_str = catgetlocal( 69, "ascii code: ");
5162	printer_msg_str = catgetlocal( 70, "sending contents of buffer to \"%s\" ");
5163	command_str = catgetlocal( 71, "command: ");
5164	file_write_prompt_str = catgetlocal( 72, "name of file to write: ");
5165	file_read_prompt_str = catgetlocal( 73, "name of file to read: ");
5166	char_str = catgetlocal( 74, "character = %d");
5167	unkn_cmd_str = catgetlocal( 75, "unknown command \"%s\"");
5168	non_unique_cmd_msg = catgetlocal( 76, "entered command is not unique");
5169	line_num_str = catgetlocal( 77, "line %d  ");
5170	line_len_str = catgetlocal( 78, "length = %d");
5171	current_file_str = catgetlocal( 79, "current file is \"%s\" ");
5172	usage0 = catgetlocal( 80, "usage: %s [-i] [-e] [-h] [+line_number] [file(s)]\n");
5173	usage1 = catgetlocal( 81, "       -i   turn off info window\n");
5174	usage2 = catgetlocal( 82, "       -e   do not convert tabs to spaces\n");
5175	usage3 = catgetlocal( 83, "       -h   do not use highlighting\n");
5176	file_is_dir_msg = catgetlocal( 84, "file \"%s\" is a directory");
5177	new_file_msg = catgetlocal( 85, "new file \"%s\"");
5178	cant_open_msg = catgetlocal( 86, "can't open \"%s\"");
5179	open_file_msg = catgetlocal( 87, "file \"%s\", %d lines");
5180	file_read_fin_msg = catgetlocal( 88, "finished reading file \"%s\"");
5181	reading_file_msg = catgetlocal( 89, "reading file \"%s\"");
5182	read_only_msg = catgetlocal( 90, ", read only");
5183	file_read_lines_msg = catgetlocal( 91, "file \"%s\", %d lines");
5184	save_file_name_prompt = catgetlocal( 92, "enter name of file: ");
5185	file_not_saved_msg = catgetlocal( 93, "no filename entered: file not saved");
5186	changes_made_prompt = catgetlocal( 94, "changes have been made, are you sure? (y/n [n]) ");
5187	yes_char = catgetlocal( 95, "y");
5188	file_exists_prompt = catgetlocal( 96, "file already exists, overwrite? (y/n) [n] ");
5189	create_file_fail_msg = catgetlocal( 97, "unable to create file \"%s\"");
5190	writing_file_msg = catgetlocal( 98, "writing file \"%s\"");
5191	file_written_msg = catgetlocal( 99, "\"%s\" %d lines, %d characters");
5192	searching_msg = catgetlocal( 100, "           ...searching");
5193	str_not_found_msg = catgetlocal( 101, "string \"%s\" not found");
5194	search_prompt_str = catgetlocal( 102, "search for: ");
5195	exec_err_msg = catgetlocal( 103, "could not exec %s\n");
5196	continue_msg = catgetlocal( 104, "press return to continue ");
5197	menu_cancel_msg = catgetlocal( 105, "press Esc to cancel");
5198	menu_size_err_msg = catgetlocal( 106, "menu too large for window");
5199	press_any_key_msg = catgetlocal( 107, "press any key to continue ");
5200	shell_prompt = catgetlocal( 108, "shell command: ");
5201	formatting_msg = catgetlocal( 109, "...formatting paragraph...");
5202	shell_echo_msg = catgetlocal( 110, "<!echo 'list of unrecognized words'; echo -=-=-=-=-=-");
5203	spell_in_prog_msg = catgetlocal( 111, "sending contents of edit buffer to 'spell'");
5204	margin_prompt = catgetlocal( 112, "right margin is: ");
5205	restricted_msg = catgetlocal( 113, "restricted mode: unable to perform requested operation");
5206	ON = catgetlocal( 114, "ON");
5207	OFF = catgetlocal( 115, "OFF");
5208	HELP = catgetlocal( 116, "HELP");
5209	WRITE = catgetlocal( 117, "WRITE");
5210	READ = catgetlocal( 118, "READ");
5211	LINE = catgetlocal( 119, "LINE");
5212	FILE_str = catgetlocal( 120, "FILE");
5213	CHARACTER = catgetlocal( 121, "CHARACTER");
5214	REDRAW = catgetlocal( 122, "REDRAW");
5215	RESEQUENCE = catgetlocal( 123, "RESEQUENCE");
5216	AUTHOR = catgetlocal( 124, "AUTHOR");
5217	VERSION = catgetlocal( 125, "VERSION");
5218	CASE = catgetlocal( 126, "CASE");
5219	NOCASE = catgetlocal( 127, "NOCASE");
5220	EXPAND = catgetlocal( 128, "EXPAND");
5221	NOEXPAND = catgetlocal( 129, "NOEXPAND");
5222	Exit_string = catgetlocal( 130, "EXIT");
5223	QUIT_string = catgetlocal( 131, "QUIT");
5224	INFO = catgetlocal( 132, "INFO");
5225	NOINFO = catgetlocal( 133, "NOINFO");
5226	MARGINS = catgetlocal( 134, "MARGINS");
5227	NOMARGINS = catgetlocal( 135, "NOMARGINS");
5228	AUTOFORMAT = catgetlocal( 136, "AUTOFORMAT");
5229	NOAUTOFORMAT = catgetlocal( 137, "NOAUTOFORMAT");
5230	Echo = catgetlocal( 138, "ECHO");
5231	PRINTCOMMAND = catgetlocal( 139, "PRINTCOMMAND");
5232	RIGHTMARGIN = catgetlocal( 140, "RIGHTMARGIN");
5233	HIGHLIGHT = catgetlocal( 141, "HIGHLIGHT");
5234	NOHIGHLIGHT = catgetlocal( 142, "NOHIGHLIGHT");
5235	EIGHTBIT = catgetlocal( 143, "EIGHTBIT");
5236	NOEIGHTBIT = catgetlocal( 144, "NOEIGHTBIT");
5237	/*
5238	 |	additions
5239	 */
5240	mode_strings[7] = catgetlocal( 145, "emacs key bindings   ");
5241	emacs_help_text[0] = help_text[0];
5242	emacs_help_text[1] = catgetlocal( 146, "^a beginning of line    ^i tab                  ^r restore word            ");
5243	emacs_help_text[2] = catgetlocal( 147, "^b back 1 char          ^j undel char           ^t top of text             ");
5244	emacs_help_text[3] = catgetlocal( 148, "^c command              ^k delete line          ^u bottom of text          ");
5245	emacs_help_text[4] = catgetlocal( 149, "^d delete char          ^l undelete line        ^v next page               ");
5246	emacs_help_text[5] = catgetlocal( 150, "^e end of line          ^m newline              ^w delete word             ");
5247	emacs_help_text[6] = catgetlocal( 151, "^f forward 1 char       ^n next line            ^x search                  ");
5248	emacs_help_text[7] = catgetlocal( 152, "^g go back 1 page       ^o ascii char insert    ^y search prompt           ");
5249	emacs_help_text[8] = catgetlocal( 153, "^h backspace            ^p prev line            ^z next word               ");
5250	emacs_help_text[9] = help_text[9];
5251	emacs_help_text[10] = help_text[10];
5252	emacs_help_text[11] = help_text[11];
5253	emacs_help_text[12] = help_text[12];
5254	emacs_help_text[13] = help_text[13];
5255	emacs_help_text[14] = help_text[14];
5256	emacs_help_text[15] = help_text[15];
5257	emacs_help_text[16] = help_text[16];
5258	emacs_help_text[17] = help_text[17];
5259	emacs_help_text[18] = help_text[18];
5260	emacs_help_text[19] = help_text[19];
5261	emacs_help_text[20] = help_text[20];
5262	emacs_help_text[21] = help_text[21];
5263	emacs_control_keys[0] = catgetlocal( 154, "^[ (escape) menu ^y search prompt ^k delete line   ^p prev li     ^g prev page");
5264	emacs_control_keys[1] = catgetlocal( 155, "^o ascii code    ^x search        ^l undelete line ^n next li     ^v next page");
5265	emacs_control_keys[2] = catgetlocal( 156, "^u end of file   ^a begin of line ^w delete word   ^b back 1 char ^z next word");
5266	emacs_control_keys[3] = catgetlocal( 157, "^t top of text   ^e end of line   ^r restore word  ^f forward char            ");
5267	emacs_control_keys[4] = catgetlocal( 158, "^c command       ^d delete char   ^j undelete char              ESC-Enter: exit");
5268	EMACS_string = catgetlocal( 159, "EMACS");
5269	NOEMACS_string = catgetlocal( 160, "NOEMACS");
5270	usage4 = catgetlocal( 161, "       +#   put cursor at line #\n");
5271	conf_dump_err_msg = catgetlocal( 162, "unable to open .init.ee for writing, no configuration saved!");
5272	conf_dump_success_msg = catgetlocal( 163, "ee configuration saved in file %s");
5273	modes_menu[10].item_string = catgetlocal( 164, "save editor configuration");
5274	config_dump_menu[0].item_string = catgetlocal( 165, "save ee configuration");
5275	config_dump_menu[1].item_string = catgetlocal( 166, "save in current directory");
5276	config_dump_menu[2].item_string = catgetlocal( 167, "save in home directory");
5277	conf_not_saved_msg = catgetlocal( 168, "ee configuration not saved");
5278	ree_no_file_msg = catgetlocal( 169, "must specify a file when invoking ree");
5279	menu_too_lrg_msg = catgetlocal( 180, "menu too large for window");
5280	more_above_str = catgetlocal( 181, "^^more^^");
5281	more_below_str = catgetlocal( 182, "VVmoreVV");
5282	mode_strings[9] = catgetlocal( 183, "16 bit characters    ");
5283	chinese_cmd = catgetlocal( 184, "16BIT");
5284	nochinese_cmd = catgetlocal( 185, "NO16BIT");
5285
5286	commands[0] = HELP;
5287	commands[1] = WRITE;
5288	commands[2] = READ;
5289	commands[3] = LINE;
5290	commands[4] = FILE_str;
5291	commands[5] = REDRAW;
5292	commands[6] = RESEQUENCE;
5293	commands[7] = AUTHOR;
5294	commands[8] = VERSION;
5295	commands[9] = CASE;
5296	commands[10] = NOCASE;
5297	commands[11] = EXPAND;
5298	commands[12] = NOEXPAND;
5299	commands[13] = Exit_string;
5300	commands[14] = QUIT_string;
5301	commands[15] = "<";
5302	commands[16] = ">";
5303	commands[17] = "!";
5304	commands[18] = "0";
5305	commands[19] = "1";
5306	commands[20] = "2";
5307	commands[21] = "3";
5308	commands[22] = "4";
5309	commands[23] = "5";
5310	commands[24] = "6";
5311	commands[25] = "7";
5312	commands[26] = "8";
5313	commands[27] = "9";
5314	commands[28] = CHARACTER;
5315	commands[29] = chinese_cmd;
5316	commands[30] = nochinese_cmd;
5317	commands[31] = NULL;
5318	init_strings[0] = CASE;
5319	init_strings[1] = NOCASE;
5320	init_strings[2] = EXPAND;
5321	init_strings[3] = NOEXPAND;
5322	init_strings[4] = INFO;
5323	init_strings[5] = NOINFO;
5324	init_strings[6] = MARGINS;
5325	init_strings[7] = NOMARGINS;
5326	init_strings[8] = AUTOFORMAT;
5327	init_strings[9] = NOAUTOFORMAT;
5328	init_strings[10] = Echo;
5329	init_strings[11] = PRINTCOMMAND;
5330	init_strings[12] = RIGHTMARGIN;
5331	init_strings[13] = HIGHLIGHT;
5332	init_strings[14] = NOHIGHLIGHT;
5333	init_strings[15] = EIGHTBIT;
5334	init_strings[16] = NOEIGHTBIT;
5335	init_strings[17] = EMACS_string;
5336	init_strings[18] = NOEMACS_string;
5337	init_strings[19] = chinese_cmd;
5338	init_strings[20] = nochinese_cmd;
5339	init_strings[21] = NULL;
5340
5341	/*
5342	 |	allocate space for strings here for settings menu
5343	 */
5344
5345	for (counter = 1; counter < NUM_MODES_ITEMS; counter++)
5346	{
5347		modes_menu[counter].item_string = malloc(80);
5348	}
5349
5350#ifndef NO_CATGETS
5351	catclose(catalog);
5352#endif /* NO_CATGETS */
5353}
5354
5355