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