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