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