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