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