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