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