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