1 /* ******************************************** 2 * * 3 * Copyright, (C) Honeywell Bull Inc., 1988 * 4 * * 5 ******************************************** */ 6 7 /* HISTORY COMMENTS: 8 1) change(88-06-13,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel), 9 install(88-10-12,MR12.2-1160): 10 Created. 11 2) change(88-07-22,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel), 12 install(88-10-12,MR12.2-1160): 13 Added support routines to capitalize, uppercase, lowercase 14 and transpose words; added support routine to transpose characters. 15 3) change(88-07-25,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel), 16 install(88-10-12,MR12.2-1160): 17 Documentation additions only. Added header comments to all routines. 18 4) change(88-08-09,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel), 19 install(88-10-12,MR12.2-1160): 20 Fix references to include files; "wstdefs.h" was split into 21 "wstdefs.h" and "wsttype.h" to avoid declaration clash; also, 22 various constants defined to descriptive names. 23 5) change(88-09-16,Lee), approve(88-05-16,MCR7897), audit(88-09-19,Flegel), 24 install(88-10-12,MR12.2-1160): 25 Modified line terminator to be always a linefeed for edit-mode; 26 lfecho and crecho only applies to fullduplex modes. 27 6) change(89-01-18,Lee), approve(89-01-02,MCR8043), audit(89-03-14,Flegel), 28 install(89-04-24,MR12.3-1033): 29 phx21233 - Modified to save only echoed input when items are killed to the 30 kill buffer and when lines are saved to history buffer, kill buffer and 31 audit buffers. 32 END HISTORY COMMENTS */ 33 34 #include <stdio.h> 35 #include <dos.h> 36 #include <ctype.h> 37 #include "wstdefs.h" 38 #include "wstglob.h" 39 #include <wsmincap.h> 40 41 /*^L 42 ********************************************************************** 43 44 Routine: DELETE_CHARS 45 46 Function: 47 This routine will delete a specified number of characters at 48 the logical cursor position on the line and force the line to be 49 updated on the screen. 50 51 Parameters: 52 (input/output) line - pointer to the structure containing the 53 line and information about the line being 54 edited 55 (input) n_chars - specifies the number of characters to 56 delete at the current cursor position 57 (input) save_sw - if TRUE, specifies that the deleted 58 characters are to be put into the kill buffer 59 60 Returns: NONE 61 62 **********************************************************************/ 63 64 delete_chars(line,n_chars,save_sw) 65 EDIT_LINE *line; 66 int n_chars; 67 { 68 int chars_to_eol; 69 int chars_to_del; 70 int i, j; 71 char *echoed_input; 72 int echoed_length; 73 74 /* determine number of characters from logical cursor position */ 75 /* to end of line */ 76 chars_to_eol = line->length - line->index; 77 78 /* make sure number of characters to delete does not exceed */ 79 /* number of characters to the end of line */ 80 if (chars_to_eol < n_chars) 81 chars_to_del = chars_to_eol; 82 else 83 chars_to_del = n_chars; 84 85 /* save item to killbuffer if save switch is on */ 86 if (save_sw && chars_to_del > 0 && kb.echo) { 87 /* phx21233 R.L. - save only echoed input to kill buffer */ 88 get_echoed_input(line,line->index,chars_to_del,&echoed_input, 89 &echoed_length); 90 save_to_killbuff(echoed_input,echoed_length); 91 } 92 93 /* copy rest of line over the deleted part of the line */ 94 for (i = line->index, j = line->index+chars_to_del; 95 j < line->length; i++,j++) { 96 97 /* copy over text in line buffer */ 98 line->line[i] = line->line[j]; 99 100 /* copy over count of display chars for text characters */ 101 line->size[i] = line->size[j]; 102 } 103 104 /* update line length */ 105 line->length -= chars_to_del; 106 107 /* force redraw from logical cursor position to end of line */ 108 redisplay(line,line->index,&(line->max_row),&(line->max_col)); 109 } 110 111 112 113 /*^L 114 ********************************************************************** 115 116 Routine: KILL_TO_BOL 117 118 Function: 119 This routine deletes all text from the current cursor position 120 to the end of the line and then updates the screen. 121 122 Parameters: 123 (input/output) line - pointer to the structure containing the 124 line and information about the line being 125 edited 126 127 Returns: NONE 128 129 **********************************************************************/ 130 131 kill_to_bol(line) 132 EDIT_LINE *line; 133 { 134 int i; 135 int n_chars; 136 137 /* do only if logical cursor not already at beginning of line */ 138 if (line->index > 0) { 139 140 /* number of characters to delete is logical cursor */ 141 /* position */ 142 n_chars = line->index; 143 144 /* check if beginning of line has scrolled off top of */ 145 /* screen */ 146 if (line->scrolled_flag) { 147 148 /* redisplay line from top of the screen */ 149 set_cursor(ss.top,ss.left); 150 151 /* pad over to original display column */ 152 for (i = ss.left; i < line->orig_col; i++) 153 putch(' '); 154 155 /* update line cursor position information */ 156 line->orig_row = ss.top; 157 line->scrolled_flag = FALSE; 158 159 /* move physical and logical cursor to beginning of */ 160 /* line */ 161 line->cur_row = ss.top; 162 line->cur_col = line->orig_col; 163 set_cursor(line->cur_row,line->cur_col); 164 line->index = 0; 165 166 /* delete the characters and force a redraw */ 167 delete_chars(line,n_chars,KILLBUFF_SAVE); 168 } 169 170 /* coordinates for beginning of line on screen */ 171 else { 172 173 /* move logical and physical cursor to beginning of */ 174 /* line */ 175 line->index = 0; 176 line->cur_row = line->orig_row; 177 line->cur_col = line->orig_col; 178 set_cursor(line->cur_row,line->cur_col); 179 180 /* perform the delete and force a screen update */ 181 delete_chars(line,n_chars,KILLBUFF_SAVE); 182 } 183 } 184 } 185 186 187 /*^L 188 ********************************************************************** 189 190 Routine: KILL_TO_EOL 191 192 Function: 193 This routine deletes all text from the current cursor position 194 to the end of the line, updating the screen. 195 196 Parameters: 197 (input/output) line - pointer to the structure containing the 198 line and information about the line being 199 edited 200 201 Returns: NONE 202 203 **********************************************************************/ 204 205 kill_to_eol(line) 206 EDIT_LINE *line; 207 { 208 209 /* if not already at end of the line */ 210 if (line->index < line->length) 211 212 /* delete the number of characters from the end of the */ 213 /* line to the current logical cursor position */ 214 215 delete_chars(line,line->length-line->index,KILLBUFF_SAVE); 216 } 217 218 219 220 /*^L 221 ********************************************************************** 222 223 Routine: ADD_TEXT 224 225 Function: 226 This routine adds text into the line being edited 227 228 Parameters: 229 (input/output) line - pointer to the structure containing the 230 line and information about the line 231 (input) ch - specifies the character to add as text to 232 the line being edited 233 (input) n_times - specifies the number of times that 234 the text character is to be added 235 236 Returns: NONE 237 238 **********************************************************************/ 239 240 add_text(line,ch,n_times) 241 EDIT_LINE *line; 242 int ch; 243 int n_times; 244 { 245 246 /* determine if editing is in replace mode */ 247 if (!line->mode) 248 replace_text(line,ch,n_times); 249 250 /* if not, then is in insert mode */ 251 else 252 insert_text(line,ch,n_times); 253 } 254 255 256 257 /*^L 258 ********************************************************************** 259 260 Routine: INSERT_TEXT 261 262 Function: 263 This routine displays and inserts one or more characters into 264 the edit line buffer and updates the screen. 265 266 Parameters: 267 (input/output) line - pointer to the structure containing the 268 line and information about the line 269 (input) ch - specifies the ASCII character to insert 270 into the line edited as text 271 (input) n_times - specifies the number of times that 272 the specified character is to be inserted 273 274 Returns: TRUE if successful 275 FALSE if unsuccessful 276 277 **********************************************************************/ 278 279 insert_text(line,ch,n_times) 280 EDIT_LINE *line; 281 int ch; 282 int n_times; 283 { 284 CURPOS tpos; 285 int i, j; 286 int actual_times; 287 int chars_to_eol; 288 289 /* determine how much space is available to insert text */ 290 chars_to_eol = MAX_LINE_SIZE - line->length; 291 292 /* check for 0 or less characters to insert */ 293 if (n_times < 1) 294 return(FALSE); 295 296 /* check for no more space in edit line buffer for insert */ 297 if (chars_to_eol < 1) { 298 beep(); 299 return(FALSE); 300 } 301 302 /* make sure number of characters to insert does not exceed */ 303 /* space available for insert */ 304 if (n_times > chars_to_eol) { 305 actual_times = chars_to_eol; 306 beep(); 307 } 308 else 309 actual_times = n_times; 310 311 /* initialize cursor position information */ 312 init_temp_curpos(&tpos,line); 313 314 /* make a gap in the line buffer for the insert */ 315 for (i = line->length+actual_times, j = line->length; 316 j >= line->index; i--, j--) { 317 line->line[i] = line->line[j]; 318 line->size[i] = line->size[j]; 319 } 320 321 /* copy the text into the gap */ 322 for (i = line->index, j = 0; j < actual_times; i++, j++) { 323 line->line[i] = ch; 324 line->size[i] = display_char(&tpos,ch); 325 } 326 327 /* update the line length and logical cursor position */ 328 line->length += actual_times; 329 line->index += actual_times; 330 331 /* update cursor position information */ 332 line->cur_row = tpos.cur_row; 333 line->cur_col = tpos.cur_col; 334 line->orig_row -= tpos.scroll_flag; 335 if (line->orig_row < ss.top) 336 line->scrolled_flag = TRUE; 337 338 /* update the changes to the screen */ 339 redisplay(line,line->index,&(line->max_row),&(line->max_col)); 340 return(TRUE); 341 } 342 343 344 345 /*^L 346 ********************************************************************** 347 348 Routine: REPLACE_TEXT 349 350 Function: 351 This routine replaces the character(s) at the cursor position 352 in the edit line and updates the screen 353 354 Parameters: 355 (input/output) line - specifies the structure containing the 356 line and information about the line being 357 edited 358 (input) key - specifies the ASCII character to replace 359 the current character(s) with 360 (input) n_times - specifies the number of characters to 361 replace with the specified ASCII character 362 363 Returns: FALSE if unsuccessful 364 TRUE if successful 365 366 **********************************************************************/ 367 368 replace_text(line,key,n_times) 369 EDIT_LINE *line; 370 int key; 371 int n_times; 372 { 373 CURPOS tpos; 374 int i; 375 int ch; 376 int actual_times; 377 int chars_to_eol; 378 379 /* determine space available for adding text */ 380 chars_to_eol = MAX_LINE_SIZE - line->index; 381 382 /* do nothing if replacing 0 or less characters */ 383 if (n_times < 1) 384 return(FALSE); 385 386 /* beep and return if no more space available to add text */ 387 if (chars_to_eol < 1) { 388 beep(); 389 return(FALSE); 390 } 391 392 /* make sure number of characters to replace does not exceed */ 393 /* space available; beep if it does */ 394 if (n_times > chars_to_eol) { 395 actual_times = chars_to_eol; 396 beep(); 397 } 398 else 399 actual_times = n_times; 400 401 /* get character to replace */ 402 ch = key; 403 404 /* initialize structure for keeping track of cursor position */ 405 init_temp_curpos(&tpos,line); 406 407 /* perform the replace and display the character(s) being */ 408 /* added */ 409 for (i = 0; i < actual_times; i++) { 410 line->line[line->index] = ch; 411 line->size[line->index] = display_char(&tpos,ch); 412 line->index++; 413 } 414 415 /* update line length if line got extended */ 416 if (line->index > line->length) line->length = line->index; 417 418 /* update cursor position information in line structure */ 419 line->cur_row = tpos.cur_row; 420 line->cur_col = tpos.cur_col; 421 line->orig_row -= tpos.scroll_flag; 422 if (line->orig_row < ss.top) 423 line->scrolled_flag = TRUE; 424 425 /* update the changes to the screen */ 426 redisplay(line,line->index,&(line->max_row),&(line->max_col)); 427 428 return(TRUE); 429 } 430 431 432 433 /*^L 434 ********************************************************************** 435 436 Routine: FORWARD_DELETE_WORD 437 438 Function: 439 This routine deletes text to the right of the cursor up to the 440 end of the next word in the line. The screen is then updated. 441 442 Parameters: 443 (input/output) line - specifies the structure containing the 444 line and information about the line being 445 edited 446 (input) n_times - specifies the number of times to 447 repeat this delete function 448 449 Returns: NONE 450 451 **********************************************************************/ 452 453 forward_delete_word(line,n_times) 454 EDIT_LINE *line; 455 int n_times; 456 { 457 int i; 458 459 /* do nothing if already at end of the line */ 460 if (line->index >= line->length) return; 461 462 /* get current logical cursor position */ 463 i = line->index; 464 465 /* perform for the specified number of times or until end of */ 466 /* line reached */ 467 while (n_times > 0 && i < line->length) { 468 469 /* skip any word delimiters */ 470 while (i < line->length && is_word_delim(line->line[i])) 471 i++; 472 473 /* skip until word delimiter reached */ 474 while (i < line->length && !is_word_delim(line->line[i])) 475 i++; 476 477 /* tally number of times performed */ 478 n_times--; 479 480 } 481 482 /* check if new position is different */ 483 if (i == line->index) 484 return; 485 486 /* delete the difference in positions and update the screen */ 487 delete_chars(line,i-line->index,KILLBUFF_SAVE); 488 } 489 490 491 /*^L 492 ********************************************************************** 493 494 Routine: BACKWARD_DELETE_WORD 495 496 Function: 497 This routine deletes text to the left of the cursor up to the 498 beginning of the previous word. The screen is updated. 499 500 Parameters: 501 (input/output) line - specifies the structure containing the 502 line and information about the line being 503 edited 504 (input) n_times - specifies the number of times to 505 perform this function 506 507 Returns: NONE 508 509 **********************************************************************/ 510 511 backward_delete_word(line,n_times) 512 EDIT_LINE *line; 513 int n_times; 514 { 515 int i; 516 int n_chars; 517 518 /* do only if not at beginning of line */ 519 if (line->index < 1) return; 520 521 /* begin at one position before the cursor */ 522 i = line->index - 1; 523 524 /* do the specified number of times or until beginning of line */ 525 /* reached */ 526 while (n_times > 0 && i >= 0) { 527 528 /* skip word delimiters to the left */ 529 while (i >= 0 && is_word_delim(line->line[i])) 530 i--; 531 532 /* skip word to the left */ 533 while (i >= 0 && !is_word_delim(line->line[i])) 534 i--; 535 536 /* tally the times performed */ 537 n_times--; 538 } 539 540 /* restore cursor position one position to the right */ 541 i++; 542 543 /* determine the number of characters to the left to delete */ 544 n_chars = line->index - i; 545 546 /* move the physical and logical cursor there, updating the */ 547 /* screen */ 548 cursor_left(line,n_chars); 549 550 /* perform the delete and update the screen */ 551 delete_chars(line,n_chars,KILLBUFF_SAVE); 552 } 553 554 555 556 /*^L 557 ********************************************************************** 558 559 Routine: ADD_CHAR 560 561 Function: 562 This routine adds a character into the line being edited and 563 updates the screen without moving the cursor forward. This routine 564 is used for handling literal escaping of characters. 565 566 Parameters: 567 (input/output) line - specifies the structure containing the 568 line and information about the line being 569 edited 570 (input) ch - specifies the ASCII character to add into 571 the line 572 573 Returns: TRUE if successful 574 FALSE if unsuccessful 575 576 **********************************************************************/ 577 578 add_char(line,ch) 579 EDIT_LINE *line; 580 int ch; 581 { 582 int code; 583 584 /* determine if in edit replace mode */ 585 if (!line->mode) 586 code = replace_char(line,ch); 587 588 /* no, in edit insert mode */ 589 else 590 code = insert_char(line,ch); 591 592 /* return the status to caller */ 593 return(code); 594 } 595 596 597 598 /*^L 599 ********************************************************************** 600 601 Routine: REPLACE_CHAR 602 603 Function: 604 This routine will replace the current character of the line 605 being edited. The cursor position is NOT changed. 606 607 Parameters: 608 (input/output) line - specifies the structure containing the 609 line and information about the line being 610 edited 611 (input) key - specifies the ASCII character to replace 612 the current character with 613 614 Returns: FALSE if unsuccessful 615 TRUE if successful 616 617 **********************************************************************/ 618 619 replace_char(line,key) 620 EDIT_LINE *line; 621 int key; 622 { 623 CURPOS tpos; 624 int ch; 625 int chars_to_eol; 626 627 /* determine space available for replacing line buffer text */ 628 chars_to_eol = MAX_LINE_SIZE - line->index; 629 630 /* if no more space left, beep and return */ 631 if (chars_to_eol < 1) { 632 beep(); 633 return(FALSE); 634 } 635 636 /* get character to insert */ 637 ch = key; 638 639 /* initialize cursor positioning information */ 640 init_temp_curpos(&tpos,line); 641 642 /* do the replace and display the new character */ 643 line->line[line->index] = ch; 644 line->size[line->index] = display_char(&tpos,ch); 645 646 /* update the line length if line is extended */ 647 if (line->index+1 > line->length) line->length = line->index+1; 648 649 /* update cursor position */ 650 line->cur_row = tpos.cur_row; 651 line->cur_col = tpos.cur_col; 652 line->orig_row -= tpos.scroll_flag; 653 if (line->orig_row < ss.top) 654 line->scrolled_flag = TRUE; 655 656 /* update the line to the screen */ 657 redisplay(line,line->index+1,&(line->max_row),&(line->max_col)); 658 659 return(TRUE); 660 } 661 662 663 664 /*^L 665 ********************************************************************** 666 667 Routine: INSERT_CHAR 668 669 Function: 670 This routine inserts a character into the line being edited. 671 The cursor position is not moved forward. 672 673 Parameters: 674 (input/output) line - specifies the structure containing the 675 line and information about the line being 676 edited 677 (input) ch - specifies the ASCII character to insert 678 into the line 679 680 Returns: TRUE if successful 681 FALSE if unsuccessful 682 683 **********************************************************************/ 684 685 insert_char(line,ch) 686 EDIT_LINE *line; 687 int ch; 688 { 689 CURPOS tpos; 690 int i, j; 691 692 int chars_to_eol; 693 694 /* determine space available in line for inserting */ 695 chars_to_eol = MAX_LINE_SIZE - line->length; 696 697 /* beep and return if no space for insert */ 698 if (chars_to_eol < 1) { 699 beep(); 700 return(FALSE); 701 } 702 703 /* initialize cursor position information */ 704 init_temp_curpos(&tpos,line); 705 706 /* create gap in line buffer for the character to insert */ 707 for (i = line->length+1, j = line->length; 708 j >= line->index; i--, j--) { 709 line->line[i] = line->line[j]; 710 line->size[i] = line->size[j]; 711 } 712 713 /* copy in the character */ 714 line->line[line->index] = ch; 715 line->size[line->index] = display_char(&tpos,ch); 716 717 /* update the line length */ 718 line->length++; 719 720 /* update the cursor position information */ 721 line->cur_row = tpos.cur_row; 722 line->cur_col = tpos.cur_col; 723 line->orig_row -= tpos.scroll_flag; 724 if (line->orig_row < ss.top) 725 line->scrolled_flag = TRUE; 726 727 /* update the line to the screen */ 728 redisplay(line,line->index+1,&(line->max_row),&(line->max_col)); 729 return(TRUE); 730 } 731 732 733 734 /*^L 735 ********************************************************************** 736 737 Routine: INSERT_DISPLAY_CHAR 738 739 Function: 740 This routine inserts characters on the screen only. It allows 741 partial input of a backslash sequence to be displayed before it is 742 entered into the line being edited. 743 744 Parameters: 745 (input/output) line - specifies the structure containing the 746 line and information about the line being 747 edited 748 (input) ch - specifies the character to insert at the 749 cursor position in the screen 750 751 Returns: NONE 752 753 **********************************************************************/ 754 755 insert_display_char(line,ch) 756 EDIT_LINE *line; 757 int ch; 758 { 759 CURPOS tpos; 760 761 /* initialize cursor position information */ 762 init_temp_curpos(&tpos,line); 763 764 /* store the character in the buffer for handling literal */ 765 /* escaping */ 766 line->literal_buff[line->literal_dex++] = ch; 767 768 /* display the character */ 769 display_char(&tpos,ch); 770 771 /* update the line structure with cursor position information */ 772 line->cur_row = tpos.cur_row; 773 line->cur_col = tpos.cur_col; 774 line->orig_row -= tpos.scroll_flag; 775 if (line->orig_row < ss.top) 776 line->scrolled_flag = TRUE; 777 778 /* update the line to the screen */ 779 redisplay(line,line->index+1,&(line->max_row),&(line->max_col)); 780 } 781 782 783 784 /*^L 785 ********************************************************************** 786 787 Routine: CHANGE_CASE_WORD 788 789 Function: 790 This routine converts all alphabetic characters in the current 791 word of the line being edited (in edit mode) to a specified case. If 792 the cursor is not on a word, the word to the left of the cursor is 793 converted to the specified case. The screen is then updated and the 794 cursor is positioned at the end of the word that has been converted. 795 The cases specified may be upper case, lower case or capitalized. 796 797 Parameters: 798 (input/output) line - pointer to the structure containing the 799 line and information about the line being 800 edited (in edit mode) 801 (input) case_flag - specifies the case to convert the 802 word(s) to: 803 KB_UPPER_CASE for upper case, 804 KB_LOWER_CASE for lower case, 805 KB_CAPITALIZED for first letter of word 806 in upper case, and rest in lower case 807 808 Returns: NONE 809 810 **********************************************************************/ 811 812 change_case_word(line,case_flag) 813 EDIT_LINE *line; 814 int case_flag; 815 { 816 int i; 817 int orig_index; 818 819 /* get copy of keyboard buffer index */ 820 i = line->index; 821 if (i >= line->length) i--; 822 orig_index = i; 823 824 /* cursor on word delimiter or space? */ 825 if (is_word_delim(line->line[i])) { 826 827 /* go left to previous word */ 828 while (i >= 0 && is_word_delim(line->line[i])) i--; 829 830 /* check for no word on left */ 831 if (i < 0) { 832 833 /* no previous word, move right to use next word */ 834 i = orig_index; 835 while (i < line->length && is_word_delim(line->line[i])) i++; 836 837 /* past end of line, is a blank line, do nothing */ 838 if (i >= line->length) 839 return; 840 } 841 } 842 843 /* make sure is at beginning of word */ 844 while (i >= 0 && !is_word_delim(line->line[i])) i--; 845 i++; 846 847 /* move physical cursor to beginning of the word for case change */ 848 if (i < line->index) 849 cursor_left(line,line->index-i); 850 else if (i > line->index) 851 cursor_right(line,i-line->index); 852 853 /* lower case first character if LOWER CASE specified */ 854 if (case_flag == KB_LOWER_CASE) 855 line->line[i] = tolower(line->line[i]); 856 857 /* upper case first character for UPPER CASE or CAPITALIZE */ 858 else 859 line->line[i] = toupper(line->line[i]); 860 i++; 861 862 /* handle rest of word */ 863 while (i < line->length && !is_word_delim(line->line[i])) { 864 865 /* upper case rest of word if UPPER CASE */ 866 if (case_flag == KB_UPPER_CASE) 867 line->line[i] = toupper(line->line[i]); 868 869 /* lower case rest of word if LOWER CASE or CAPITALIZE */ 870 else 871 line->line[i] = tolower(line->line[i]); 872 873 i++; 874 875 } 876 877 /* update the screen */ 878 redisplay(line,line->index,&(line->max_row),&(line->max_col)); 879 880 /* position cursor to end of last word upper cased */ 881 cursor_right(line,i-line->index); 882 } 883 884 885 886 /*^L 887 ********************************************************************** 888 889 Routine: TRANSPOSE_CHARS 890 891 Function: 892 This routine exchanges the positions of the two characters to 893 the left of the cursor. If there isn't two characters to the left 894 of the cursor, the routine will sound a beep and do nothing. The 895 screen is updated and the cursor position is unchanged. 896 897 Parameters: 898 (input/output) line - specifies the structure containing the 899 line and information about the line being 900 edited (in edit mode) 901 902 Returns: NONE 903 904 **********************************************************************/ 905 906 transpose_chars(line) 907 EDIT_LINE *line; 908 { 909 int i; 910 int tmp_ch; 911 912 /* check if two characters exist to left of cursor */ 913 if (line->length < 2 || line->index < 2) { 914 beep(); 915 return; 916 } 917 918 /* position temporary index to two positions before cursor */ 919 i = line->index - 2; 920 921 /* move cursor two characters back */ 922 cursor_left(line,2); 923 924 /* swap the two characters */ 925 tmp_ch = line->line[i]; 926 line->line[i] = line->line[i+1]; 927 line->line[i+1] = tmp_ch; 928 929 /* update the screen */ 930 redisplay(line,line->index,&(line->max_row),&(line->max_col)); 931 932 /* restore cursor position */ 933 cursor_right(line,2); 934 } 935 936 937 938 /*^L 939 ********************************************************************** 940 941 Routine: TRANSPOSE_WORDS 942 943 Function: 944 This routine interchanges the positions of the current word 945 (under the cursor) and the word to its left. If the cursor is not 946 on a word, the two words to the left of the cursor are 947 interchanged. The screen is updated and the cursor is positioned at 948 the end of the interchanged words. If there are no words to 949 interchange (e.g. at beginning of the line), the routine will beep 950 and do nothing. 951 952 Parameters: 953 (input/output) line - specifies the structure containing the 954 line and information about the line being 955 edited (in edit mode) 956 957 Returns: NONE 958 959 **********************************************************************/ 960 961 transpose_words(line) 962 EDIT_LINE *line; 963 { 964 int i; 965 int word1_index, word1_len; 966 int word2_index, word2_len; 967 int delim_len; 968 char *tmp_buff, *malloc(); 969 int tmp_index; 970 int final_index; 971 972 /* get cursor position and make sure it points to valid data */ 973 /* if at end of line */ 974 i = line->index; 975 if (i >= line->length) i--; 976 977 /* check if in middle of a word */ 978 if (!is_word_delim(line->line[i])) 979 /* go to end of word */ 980 while (i < line->length && !is_word_delim(line->line[i])) 981 i++; 982 983 /* go left to right, skip trailing blanks */ 984 i--; 985 while (i >= 0 && is_word_delim(line->line[i])) 986 i--; 987 988 /* save the index to the end of this second word */ 989 final_index = i+1; 990 991 /* determine length and starting position of this second word */ 992 word2_len = 0; 993 while (i >= 0 && !is_word_delim(line->line[i])) { 994 i--; 995 word2_len++; 996 } 997 word2_index = i+1; 998 999 /* no word to transpose with if past beginning of line */ 1000 if (i < 0) { 1001 beep(); 1002 return; 1003 } 1004 1005 /* determine number of delimiter characters to left of second word */ 1006 delim_len = 0; 1007 while (i >= 0 && is_word_delim(line->line[i])) { 1008 delim_len++; 1009 i--; 1010 } 1011 1012 /* no words to transpose with if past beginning of line */ 1013 if (i < 0) { 1014 beep(); 1015 return; 1016 } 1017 1018 /* determine length and position of first word */ 1019 word1_len = 0; 1020 while (i >= 0 && !is_word_delim(line->line[i])) { 1021 i--; 1022 word1_len++; 1023 } 1024 word1_index = i+1; 1025 1026 /* allocate buffer big enough to hold both words and delimiter */ 1027 tmp_buff = malloc(word1_len+delim_len+word2_len+1); 1028 if (tmp_buff == NULL) return; 1029 1030 /* move cursor to beginning of first word */ 1031 i = line->index - word1_index; 1032 cursor_left(line,i); 1033 1034 /* copy the two words and delimiter in between with the word positions 1035 interchanged to temporary buffer 1036 */ 1037 tmp_index = 0; 1038 for (i = 0; i < word2_len; i++) 1039 tmp_buff[tmp_index++] = line->line[word2_index+i]; 1040 for (i = 0; i < delim_len; i++) 1041 tmp_buff[tmp_index++] = line->line[word1_index+word1_len+i]; 1042 for (i = 0; i < word1_len; i++) 1043 tmp_buff[tmp_index++] = line->line[word1_index+i]; 1044 1045 /* copy back from temporary buffer to line buffer */ 1046 for (i = 0; i < tmp_index; i++) 1047 line->line[word1_index+i] = tmp_buff[i]; 1048 1049 /* deallocate temporary buffer */ 1050 free(tmp_buff); 1051 1052 /* update the screen */ 1053 redisplay(line,line->index,&(line->max_row),&(line->max_col)); 1054 1055 /* position cursor at end of words */ 1056 cursor_right(line,final_index-line->index); 1057 } 1058 1059 1060 1061 /*^L 1062 ********************************************************************** 1063 1064 Routine: KB_EDIT_LF_RETURN 1065 1066 Function: 1067 This function passes processes a line in edit-mode when a 1068 linefeed or carriage return is entered, before the line is to 1069 be sent to the host. Processing includes moving the cursor to 1070 the end of the line, saving the line in the history and kill 1071 buffer, file or printer audit the lines if auditing is enabled, 1072 and updating any cursor position variables. The line is then 1073 sent to the host. 1074 1075 Parameters: 1076 (input/output) line - pointer to the structure containing the 1077 line and information about the line to be 1078 saved and sent to the host 1079 (input) key - specifies the line terminator key that 1080 was entered 1081 1082 Returns: NONE 1083 1084 **********************************************************************/ 1085 1086 kb_edit_lf_return(line,key) 1087 EDIT_LINE *line; 1088 int key; 1089 { 1090 char *dptr; 1091 char *echoed_input; 1092 int echoed_length; 1093 1094 /* position cursor to end of line (to prevent incoming messages 1095 from overwriting the input 1096 */ 1097 cursor_eol(line); 1098 1099 /* Handle moving the cursor to the next line. */ 1100 /* Don't move to beginning of next line if CR hit and mowse is */ 1101 /* not active; in glass tty mode, when using edit mode, */ 1102 /* the terminal modes should be ^echoplex,lfecho. A linefeed */ 1103 /* will be echoed from Multics anyways. */ 1104 1105 if (!mowse_active && key == CR) 1106 line->cur_col = ss.left; 1107 1108 else if (line->cur_row >= ss.bottom) { 1109 wst_scroll(); 1110 line->cur_row = ss.bottom; 1111 line->cur_col = ss.left; 1112 } 1113 else { 1114 line->cur_row++; 1115 line->cur_col = ss.left; 1116 } 1117 1118 cursor_move(line->cur_row,line->cur_col); 1119 1120 /* re-initialize screen information */ 1121 screen.curlin = line->cur_row; 1122 screen.curcol = line->cur_col; 1123 screen.EOP_ct = 0; /* input resets page line counter */ 1124 1125 /* phx21233 R.L. - saved only echoed input to history and kill buffers */ 1126 get_echoed_input(line,0,line->length,&echoed_input,&echoed_length); 1127 1128 /* non-empty lines saved to history buffer */ 1129 if (echoed_length > 0) { 1130 save_to_histbuff(echoed_input,echoed_length); 1131 save_to_killbuff(echoed_input,echoed_length); 1132 } 1133 1134 if (mowse_active) 1135 1136 /* terminate line with line delimiter; a linefeed character is */ 1137 /* always used so the line gets interpreted by the host; the */ 1138 /* modes lfecho and crecho do not affect edit-mode since */ 1139 /* characters are echoed locally, and not by the host. The lfecho */ 1140 /* and crecho modes are meaningful in full duplex */ 1141 1142 line->line[line->length++] = LF; 1143 1144 /* otherwise send whatever line terminator was entered */ 1145 else 1146 line->line[line->length++] = key; 1147 1148 /* terminate string */ 1149 line->line[line->length] = NUL_TERMINATOR; 1150 1151 /* phx21233 R.L. - LF terminate echoed input and audit only echoed input */ 1152 echoed_input[echoed_length++] = LF; 1153 1154 /* audit input if necessary */ 1155 if (wst_f_audit) 1156 f_audit_msg(echoed_input,echoed_length); 1157 1158 if (wst_p_audit) 1159 p_audit_msg(echoed_input,echoed_length,NULL); 1160 1161 /* just send the message to host if not in glass tty mode */ 1162 if (mowse_active) 1163 puttdata (FG_TERMINAL_DATA, line->line, line->length); 1164 1165 /* kludge to minimize line overrun for long input lines when */ 1166 /* Multics is echoing; this problems shows up when the user */ 1167 /* is in non-packet (glass tty) mode and long input lines are */ 1168 /* echoed. The echoed input from Multics sometimes causes the PC */ 1169 /* to stall, resulting in a Multics interpreting a QUIT signal. */ 1170 /* This fix slows long input from being sent too quickly so that */ 1171 /* echoed characters are received less quickly. */ 1172 else { 1173 /* send characters out in 4 character chunks, delaying in between */ 1174 dptr = line->line; 1175 while (line->length > 4) { 1176 1177 puttdata(FG_TERMINAL_DATA, dptr, 4); 1178 dptr += 4; 1179 line->length -= 4; 1180 delay(); 1181 } 1182 1183 puttdata(FG_TERMINAL_DATA, dptr, line->length); 1184 } 1185 1186 /* reset edit mode line length and buffer index to indicate 0 length */ 1187 line->length = 0; 1188 line->index = 0; 1189 }