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