1 /* $NetBSD: echo-area.c,v 1.2 2016/01/14 00:34:52 christos Exp $ */ 2 3 /* echo-area.c -- how to read a line in the echo area. 4 Id: echo-area.c,v 1.7 2004/12/14 00:15:36 karl Exp 5 6 Copyright (C) 1993, 1997, 1998, 1999, 2001, 2004 Free Software 7 Foundation, Inc. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2, or (at your option) 12 any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 23 Written by Brian Fox (bfox (at) ai.mit.edu). */ 24 25 #include "info.h" 26 27 #if defined (FD_SET) 28 # if defined (hpux) 29 # define fd_set_cast(x) (int *)(x) 30 # else 31 # define fd_set_cast(x) (fd_set *)(x) 32 # endif /* !hpux */ 33 #endif /* FD_SET */ 34 35 /* Non-zero means that C-g was used to quit reading input. */ 36 int info_aborted_echo_area = 0; 37 38 /* Non-zero means that the echo area is being used to read input. */ 39 int echo_area_is_active = 0; 40 41 /* The address of the last command executed in the echo area. */ 42 VFunction *ea_last_executed_command = (VFunction *)NULL; 43 44 /* Non-zero means that the last command executed while reading input 45 killed some text. */ 46 int echo_area_last_command_was_kill = 0; 47 48 /* Variables which hold on to the current state of the input line. */ 49 static char input_line[1 + EA_MAX_INPUT]; 50 static char *input_line_prompt; 51 static int input_line_point; 52 static int input_line_beg; 53 static int input_line_end; 54 static NODE input_line_node = { 55 (char *)NULL, (char *)NULL, (char *)NULL, input_line, 56 EA_MAX_INPUT, 0, N_IsInternal 57 }; 58 59 static void echo_area_initialize_node (void); 60 static void push_echo_area (void), pop_echo_area (void); 61 static int echo_area_stack_contains_completions_p (void); 62 63 static void ea_kill_text (int from, int to); 64 65 /* Non-zero means we force the user to complete. */ 66 static int echo_area_must_complete_p = 0; 67 static int completions_window_p (WINDOW *window); 68 69 /* If non-null, this is a window which was specifically created to display 70 possible completions output. We remember it so we can delete it when 71 appropriate. */ 72 static WINDOW *echo_area_completions_window = (WINDOW *)NULL; 73 74 /* Variables which keep track of the window which was active prior to 75 entering the echo area. */ 76 static WINDOW *calling_window = (WINDOW *)NULL; 77 static NODE *calling_window_node = (NODE *)NULL; 78 static long calling_window_point = 0; 79 static long calling_window_pagetop = 0; 80 81 /* Remember the node and pertinent variables of the calling window. */ 82 static void 83 remember_calling_window (WINDOW *window) 84 { 85 /* Only do this if the calling window is not the completions window, or, 86 if it is the completions window and there is no other window. */ 87 if (!completions_window_p (window) || 88 ((window == windows) && !(window->next))) 89 { 90 calling_window = window; 91 calling_window_node = window->node; 92 calling_window_point = window->point; 93 calling_window_pagetop = window->pagetop; 94 } 95 } 96 97 /* Restore the caller's window so that it shows the node that it was showing 98 on entry to info_read_xxx_echo_area (). */ 99 static void 100 restore_calling_window (void) 101 { 102 register WINDOW *win, *compwin = (WINDOW *)NULL; 103 104 /* If the calling window is still visible, and it is the window that 105 we used for completions output, then restore the calling window. */ 106 for (win = windows; win; win = win->next) 107 { 108 if (completions_window_p (win)) 109 compwin = win; 110 111 if (win == calling_window && win == compwin) 112 { 113 window_set_node_of_window (calling_window, calling_window_node); 114 calling_window->point = calling_window_point; 115 calling_window->pagetop = calling_window_pagetop; 116 compwin = (WINDOW *)NULL; 117 break; 118 } 119 } 120 121 /* Delete the completions window if it is still present, it isn't the 122 last window on the screen, and there aren't any prior echo area reads 123 pending which created a completions window. */ 124 if (compwin) 125 { 126 if ((compwin != windows || windows->next) && 127 !echo_area_stack_contains_completions_p ()) 128 { 129 WINDOW *next; 130 int pagetop = 0; 131 int start = 0; 132 int end = 0; 133 int amount = 0; 134 135 next = compwin->next; 136 if (next) 137 { 138 start = next->first_row; 139 end = start + next->height; 140 amount = - (compwin->height + 1); 141 pagetop = next->pagetop; 142 } 143 144 info_delete_window_internal (compwin); 145 146 /* This is not necessary because info_delete_window_internal () 147 calls echo_area_inform_of_deleted_window (), which does the 148 right thing. */ 149 #if defined (UNNECESSARY) 150 echo_area_completions_window = (WINDOW *)NULL; 151 #endif /* UNNECESSARY */ 152 153 if (next) 154 { 155 display_scroll_display (start, end, amount); 156 next->pagetop = pagetop; 157 display_update_display (windows); 158 } 159 } 160 } 161 } 162 163 /* Set up a new input line with PROMPT. */ 164 static void 165 initialize_input_line (char *prompt) 166 { 167 input_line_prompt = prompt; 168 if (prompt) 169 strcpy (input_line, prompt); 170 else 171 input_line[0] = '\0'; 172 173 input_line_beg = input_line_end = input_line_point = strlen (prompt); 174 } 175 176 static char * 177 echo_area_after_read (void) 178 { 179 char *return_value; 180 181 if (info_aborted_echo_area) 182 { 183 info_aborted_echo_area = 0; 184 return_value = (char *)NULL; 185 } 186 else 187 { 188 if (input_line_beg == input_line_end) 189 return_value = xstrdup (""); 190 else 191 { 192 int line_len = input_line_end - input_line_beg; 193 return_value = (char *) xmalloc (1 + line_len); 194 strncpy (return_value, &input_line[input_line_beg], line_len); 195 return_value[line_len] = '\0'; 196 } 197 } 198 return (return_value); 199 } 200 201 /* Read a line of text in the echo area. Return a malloc ()'ed string, 202 or NULL if the user aborted out of this read. WINDOW is the currently 203 active window, so that we can restore it when we need to. PROMPT, if 204 non-null, is a prompt to print before reading the line. */ 205 char * 206 info_read_in_echo_area (WINDOW *window, char *prompt) 207 { 208 char *line; 209 210 /* If the echo area is already active, remember the current state. */ 211 if (echo_area_is_active) 212 push_echo_area (); 213 214 /* Initialize our local variables. */ 215 initialize_input_line (prompt); 216 217 /* Initialize the echo area for the first (but maybe not the last) time. */ 218 echo_area_initialize_node (); 219 220 /* Save away the original node of this window, and the window itself, 221 so echo area commands can temporarily use this window. */ 222 remember_calling_window (window); 223 224 /* Let the rest of Info know that the echo area is active. */ 225 echo_area_is_active++; 226 active_window = the_echo_area; 227 228 /* Read characters in the echo area. */ 229 info_read_and_dispatch (); 230 231 echo_area_is_active--; 232 233 /* Restore the original active window and show point in it. */ 234 active_window = calling_window; 235 restore_calling_window (); 236 display_cursor_at_point (active_window); 237 fflush (stdout); 238 239 /* Get the value of the line. */ 240 line = echo_area_after_read (); 241 242 /* If there is a previous loop waiting for us, restore it now. */ 243 if (echo_area_is_active) 244 pop_echo_area (); 245 246 /* Return the results to the caller. */ 247 return (line); 248 } 249 250 /* (re) Initialize the echo area node. */ 251 static void 252 echo_area_initialize_node (void) 253 { 254 register int i; 255 256 for (i = input_line_end; (unsigned int) i < sizeof (input_line); i++) 257 input_line[i] = ' '; 258 259 input_line[i - 1] = '\n'; 260 window_set_node_of_window (the_echo_area, &input_line_node); 261 input_line[input_line_end] = '\n'; 262 } 263 264 /* Prepare to read characters in the echo area. This can initialize the 265 echo area node, but its primary purpose is to side effect the input 266 line buffer contents. */ 267 void 268 echo_area_prep_read (void) 269 { 270 if (the_echo_area->node != &input_line_node) 271 echo_area_initialize_node (); 272 273 the_echo_area->point = input_line_point; 274 input_line[input_line_end] = '\n'; 275 display_update_one_window (the_echo_area); 276 display_cursor_at_point (active_window); 277 } 278 279 280 /* **************************************************************** */ 282 /* */ 283 /* Echo Area Movement Commands */ 284 /* */ 285 /* **************************************************************** */ 286 287 DECLARE_INFO_COMMAND (ea_forward, _("Move forward a character")) 288 { 289 if (count < 0) 290 ea_backward (window, -count, key); 291 else 292 { 293 input_line_point += count; 294 if (input_line_point > input_line_end) 295 input_line_point = input_line_end; 296 } 297 } 298 299 DECLARE_INFO_COMMAND (ea_backward, _("Move backward a character")) 300 { 301 if (count < 0) 302 ea_forward (window, -count, key); 303 else 304 { 305 input_line_point -= count; 306 if (input_line_point < input_line_beg) 307 input_line_point = input_line_beg; 308 } 309 } 310 311 DECLARE_INFO_COMMAND (ea_beg_of_line, _("Move to the start of this line")) 312 { 313 input_line_point = input_line_beg; 314 } 315 316 DECLARE_INFO_COMMAND (ea_end_of_line, _("Move to the end of this line")) 317 { 318 input_line_point = input_line_end; 319 } 320 321 #define alphabetic(c) (islower (c) || isupper (c) || isdigit (c)) 322 323 /* Move forward a word in the input line. */ 324 DECLARE_INFO_COMMAND (ea_forward_word, _("Move forward a word")) 325 { 326 int c; 327 328 if (count < 0) 329 ea_backward_word (window, -count, key); 330 else 331 { 332 while (count--) 333 { 334 if (input_line_point == input_line_end) 335 return; 336 337 /* If we are not in a word, move forward until we are in one. 338 Then, move forward until we hit a non-alphabetic character. */ 339 c = input_line[input_line_point]; 340 341 if (!alphabetic (c)) 342 { 343 while (++input_line_point < input_line_end) 344 { 345 c = input_line[input_line_point]; 346 if (alphabetic (c)) 347 break; 348 } 349 } 350 351 if (input_line_point == input_line_end) 352 return; 353 354 while (++input_line_point < input_line_end) 355 { 356 c = input_line[input_line_point]; 357 if (!alphabetic (c)) 358 break; 359 } 360 } 361 } 362 } 363 364 DECLARE_INFO_COMMAND (ea_backward_word, _("Move backward a word")) 365 { 366 int c; 367 368 if (count < 0) 369 ea_forward_word (window, -count, key); 370 else 371 { 372 while (count--) 373 { 374 if (input_line_point == input_line_beg) 375 return; 376 377 /* Like ea_forward_word (), except that we look at the 378 characters just before point. */ 379 380 c = input_line[input_line_point - 1]; 381 382 if (!alphabetic (c)) 383 { 384 while ((--input_line_point) != input_line_beg) 385 { 386 c = input_line[input_line_point - 1]; 387 if (alphabetic (c)) 388 break; 389 } 390 } 391 392 while (input_line_point != input_line_beg) 393 { 394 c = input_line[input_line_point - 1]; 395 if (!alphabetic (c)) 396 break; 397 else 398 --input_line_point; 399 } 400 } 401 } 402 } 403 404 DECLARE_INFO_COMMAND (ea_delete, _("Delete the character under the cursor")) 405 { 406 register int i; 407 408 if (count < 0) 409 ea_rubout (window, -count, key); 410 else 411 { 412 if (input_line_point == input_line_end) 413 return; 414 415 if (info_explicit_arg || count > 1) 416 { 417 int orig_point; 418 419 orig_point = input_line_point; 420 ea_forward (window, count, key); 421 ea_kill_text (orig_point, input_line_point); 422 input_line_point = orig_point; 423 } 424 else 425 { 426 for (i = input_line_point; i < input_line_end; i++) 427 input_line[i] = input_line[i + 1]; 428 429 input_line_end--; 430 } 431 } 432 } 433 434 DECLARE_INFO_COMMAND (ea_rubout, _("Delete the character behind the cursor")) 435 { 436 if (count < 0) 437 ea_delete (window, -count, key); 438 else 439 { 440 int start; 441 442 if (input_line_point == input_line_beg) 443 return; 444 445 start = input_line_point; 446 ea_backward (window, count, key); 447 448 if (info_explicit_arg || count > 1) 449 ea_kill_text (start, input_line_point); 450 else 451 ea_delete (window, count, key); 452 } 453 } 454 455 DECLARE_INFO_COMMAND (ea_abort, _("Cancel or quit operation")) 456 { 457 /* If any text, just discard it, and restore the calling window's node. 458 If no text, quit. */ 459 if (input_line_end != input_line_beg) 460 { 461 terminal_ring_bell (); 462 input_line_end = input_line_point = input_line_beg; 463 if (calling_window->node != calling_window_node) 464 restore_calling_window (); 465 } 466 else 467 info_aborted_echo_area = 1; 468 } 469 470 DECLARE_INFO_COMMAND (ea_newline, _("Accept (or force completion of) this line")) 471 { 472 /* Stub does nothing. Simply here to see if it has been executed. */ 473 } 474 475 DECLARE_INFO_COMMAND (ea_quoted_insert, _("Insert next character verbatim")) 476 { 477 unsigned char character; 478 479 character = info_get_another_input_char (); 480 ea_insert (window, count, character); 481 } 482 483 DECLARE_INFO_COMMAND (ea_insert, _("Insert this character")) 484 { 485 register int i; 486 487 if ((input_line_end + 1) == EA_MAX_INPUT) 488 { 489 terminal_ring_bell (); 490 return; 491 } 492 493 for (i = input_line_end + 1; i != input_line_point; i--) 494 input_line[i] = input_line[i - 1]; 495 496 input_line[input_line_point] = key; 497 input_line_point++; 498 input_line_end++; 499 } 500 501 DECLARE_INFO_COMMAND (ea_tab_insert, _("Insert a TAB character")) 502 { 503 ea_insert (window, count, '\t'); 504 } 505 506 /* Transpose the characters at point. If point is at the end of the line, 507 then transpose the characters before point. */ 508 DECLARE_INFO_COMMAND (ea_transpose_chars, _("Transpose characters at point")) 509 { 510 /* Handle conditions that would make it impossible to transpose 511 characters. */ 512 if (!count || !input_line_point || (input_line_end - input_line_beg) < 2) 513 return; 514 515 while (count) 516 { 517 int t; 518 if (input_line_point == input_line_end) 519 { 520 t = input_line[input_line_point - 1]; 521 522 input_line[input_line_point - 1] = input_line[input_line_point - 2]; 523 input_line[input_line_point - 2] = t; 524 } 525 else 526 { 527 t = input_line[input_line_point]; 528 529 input_line[input_line_point] = input_line[input_line_point - 1]; 530 input_line[input_line_point - 1] = t; 531 532 if (count < 0 && input_line_point != input_line_beg) 533 input_line_point--; 534 else 535 input_line_point++; 536 } 537 538 if (count < 0) 539 count++; 540 else 541 count--; 542 } 543 } 544 545 /* **************************************************************** */ 547 /* */ 548 /* Echo Area Killing and Yanking */ 549 /* */ 550 /* **************************************************************** */ 551 552 static char **kill_ring = (char **)NULL; 553 static int kill_ring_index = 0; /* Number of kills appearing in KILL_RING. */ 554 static int kill_ring_slots = 0; /* Number of slots allocated to KILL_RING. */ 555 static int kill_ring_loc = 0; /* Location of current yank pointer. */ 556 557 /* The largest number of kills that we remember at one time. */ 558 static int max_retained_kills = 15; 559 560 DECLARE_INFO_COMMAND (ea_yank, _("Yank back the contents of the last kill")) 561 { 562 register int i; 563 register char *text; 564 565 if (!kill_ring_index) 566 { 567 inform_in_echo_area ((char *) _("Kill ring is empty")); 568 return; 569 } 570 571 text = kill_ring[kill_ring_loc]; 572 573 for (i = 0; text[i]; i++) 574 ea_insert (window, 1, text[i]); 575 } 576 577 /* If the last command was yank, or yank_pop, and the text just before 578 point is identical to the current kill item, then delete that text 579 from the line, rotate the index down, and yank back some other text. */ 580 DECLARE_INFO_COMMAND (ea_yank_pop, _("Yank back a previous kill")) 581 { 582 register int len; 583 584 if (((ea_last_executed_command != (VFunction *) ea_yank) && 585 (ea_last_executed_command != (VFunction *) ea_yank_pop)) || 586 (kill_ring_index == 0)) 587 return; 588 589 len = strlen (kill_ring[kill_ring_loc]); 590 591 /* Delete the last yanked item from the line. */ 592 { 593 register int i, counter; 594 595 counter = input_line_end - input_line_point; 596 597 for (i = input_line_point - len; counter; i++, counter--) 598 input_line[i] = input_line[i + len]; 599 600 input_line_end -= len; 601 input_line_point -= len; 602 } 603 604 /* Get a previous kill, and yank that. */ 605 kill_ring_loc--; 606 if (kill_ring_loc < 0) 607 kill_ring_loc = kill_ring_index - 1; 608 609 ea_yank (window, count, key); 610 } 611 612 /* Delete the text from point to end of line. */ 613 DECLARE_INFO_COMMAND (ea_kill_line, _("Kill to the end of the line")) 614 { 615 if (count < 0) 616 { 617 ea_kill_text (input_line_point, input_line_beg); 618 input_line_point = input_line_beg; 619 } 620 else 621 ea_kill_text (input_line_point, input_line_end); 622 } 623 624 /* Delete the text from point to beg of line. */ 625 DECLARE_INFO_COMMAND (ea_backward_kill_line, 626 _("Kill to the beginning of the line")) 627 { 628 if (count < 0) 629 ea_kill_text (input_line_point, input_line_end); 630 else 631 { 632 ea_kill_text (input_line_point, input_line_beg); 633 input_line_point = input_line_beg; 634 } 635 } 636 637 /* Delete from point to the end of the current word. */ 638 DECLARE_INFO_COMMAND (ea_kill_word, _("Kill the word following the cursor")) 639 { 640 int orig_point = input_line_point; 641 642 if (count < 0) 643 ea_backward_kill_word (window, -count, key); 644 else 645 { 646 ea_forward_word (window, count, key); 647 648 if (input_line_point != orig_point) 649 ea_kill_text (orig_point, input_line_point); 650 651 input_line_point = orig_point; 652 } 653 } 654 655 /* Delete from point to the start of the current word. */ 656 DECLARE_INFO_COMMAND (ea_backward_kill_word, 657 _("Kill the word preceding the cursor")) 658 { 659 int orig_point = input_line_point; 660 661 if (count < 0) 662 ea_kill_word (window, -count, key); 663 else 664 { 665 ea_backward_word (window, count, key); 666 667 if (input_line_point != orig_point) 668 ea_kill_text (orig_point, input_line_point); 669 } 670 } 671 672 /* The way to kill something. This appends or prepends to the last 673 kill, if the last command was a kill command. If FROM is less 674 than TO, then the killed text is appended to the most recent kill, 675 otherwise it is prepended. If the last command was not a kill command, 676 then a new slot is made for this kill. */ 677 static void 678 ea_kill_text (int from, int to) 679 { 680 register int i, counter, distance; 681 int killing_backwards, slot; 682 char *killed_text; 683 684 killing_backwards = (from > to); 685 686 /* If killing backwards, reverse the values of FROM and TO. */ 687 if (killing_backwards) 688 { 689 int temp = from; 690 from = to; 691 to = temp; 692 } 693 694 /* Remember the text that we are about to delete. */ 695 distance = to - from; 696 killed_text = (char *)xmalloc (1 + distance); 697 strncpy (killed_text, &input_line[from], distance); 698 killed_text[distance] = '\0'; 699 700 /* Actually delete the text from the line. */ 701 counter = input_line_end - to; 702 703 for (i = from; counter; i++, counter--) 704 input_line[i] = input_line[i + distance]; 705 706 input_line_end -= distance; 707 708 /* If the last command was a kill, append or prepend the killed text to 709 the last command's killed text. */ 710 if (echo_area_last_command_was_kill) 711 { 712 char *old, *new; 713 714 slot = kill_ring_loc; 715 old = kill_ring[slot]; 716 new = (char *)xmalloc (1 + strlen (old) + strlen (killed_text)); 717 718 if (killing_backwards) 719 { 720 /* Prepend TEXT to current kill. */ 721 strcpy (new, killed_text); 722 strcat (new, old); 723 } 724 else 725 { 726 /* Append TEXT to current kill. */ 727 strcpy (new, old); 728 strcat (new, killed_text); 729 } 730 731 free (old); 732 free (killed_text); 733 kill_ring[slot] = new; 734 } 735 else 736 { 737 /* Try to store the kill in a new slot, unless that would cause there 738 to be too many remembered kills. */ 739 slot = kill_ring_index; 740 741 if (slot == max_retained_kills) 742 slot = 0; 743 744 if (slot + 1 > kill_ring_slots) 745 kill_ring = (char **) xrealloc 746 (kill_ring, 747 (kill_ring_slots += max_retained_kills) * sizeof (char *)); 748 749 if (slot != kill_ring_index) 750 free (kill_ring[slot]); 751 else 752 kill_ring_index++; 753 754 kill_ring[slot] = killed_text; 755 756 kill_ring_loc = slot; 757 } 758 759 /* Notice that the last command was a kill. */ 760 echo_area_last_command_was_kill++; 761 } 762 763 /* **************************************************************** */ 765 /* */ 766 /* Echo Area Completion */ 767 /* */ 768 /* **************************************************************** */ 769 770 /* Pointer to an array of REFERENCE to complete over. */ 771 static REFERENCE **echo_area_completion_items = (REFERENCE **)NULL; 772 773 /* Sorted array of REFERENCE * which is the possible completions found in 774 the variable echo_area_completion_items. If there is only one element, 775 it is the only possible completion. */ 776 static REFERENCE **completions_found = (REFERENCE **)NULL; 777 static int completions_found_index = 0; 778 static int completions_found_slots = 0; 779 780 /* The lowest common denominator found while completing. */ 781 static REFERENCE *LCD_completion; 782 783 /* Internal functions used by the user calls. */ 784 static void build_completions (void), completions_must_be_rebuilt (void); 785 786 /* Variable which holds the output of completions. */ 787 static NODE *possible_completions_output_node = (NODE *)NULL; 788 789 static char *compwin_name = "*Completions*"; 790 791 /* Return non-zero if WINDOW is a window used for completions output. */ 792 static int 793 completions_window_p (WINDOW *window) 794 { 795 int result = 0; 796 797 if (internal_info_node_p (window->node) && 798 (strcmp (window->node->nodename, compwin_name) == 0)) 799 result = 1; 800 801 return (result); 802 } 803 804 /* Workhorse for completion readers. If FORCE is non-zero, the user cannot 805 exit unless the line read completes, or is empty. */ 806 char * 807 info_read_completing_internal (WINDOW *window, char *prompt, 808 REFERENCE **completions, int force) 809 { 810 char *line; 811 812 /* If the echo area is already active, remember the current state. */ 813 if (echo_area_is_active) 814 push_echo_area (); 815 816 echo_area_must_complete_p = force; 817 818 /* Initialize our local variables. */ 819 initialize_input_line (prompt); 820 821 /* Initialize the echo area for the first (but maybe not the last) time. */ 822 echo_area_initialize_node (); 823 824 /* Save away the original node of this window, and the window itself, 825 so echo area commands can temporarily use this window. */ 826 remember_calling_window (window); 827 828 /* Save away the list of items to complete over. */ 829 echo_area_completion_items = completions; 830 completions_must_be_rebuilt (); 831 832 active_window = the_echo_area; 833 echo_area_is_active++; 834 835 /* Read characters in the echo area. */ 836 while (1) 837 { 838 info_read_and_dispatch (); 839 840 line = echo_area_after_read (); 841 842 /* Force the completion to take place if the user hasn't accepted 843 a default or aborted, and if FORCE is active. */ 844 if (force && line && *line && completions) 845 { 846 register int i; 847 848 build_completions (); 849 850 /* If there is only one completion, then make the line be that 851 completion. */ 852 if (completions_found_index == 1) 853 { 854 free (line); 855 line = xstrdup (completions_found[0]->label); 856 break; 857 } 858 859 /* If one of the completions matches exactly, then that is okay, so 860 return the current line. */ 861 for (i = 0; i < completions_found_index; i++) 862 if (strcasecmp (completions_found[i]->label, line) == 0) 863 { 864 free (line); 865 line = xstrdup (completions_found[i]->label); 866 break; 867 } 868 869 /* If no match, go back and try again. */ 870 if (i == completions_found_index) 871 { 872 if (!completions_found_index) 873 inform_in_echo_area ((char *) _("No completions")); 874 else 875 inform_in_echo_area ((char *) _("Not complete")); 876 continue; 877 } 878 } 879 break; 880 } 881 echo_area_is_active--; 882 883 /* Restore the original active window and show point in it. */ 884 active_window = calling_window; 885 restore_calling_window (); 886 display_cursor_at_point (active_window); 887 fflush (stdout); 888 889 echo_area_completion_items = (REFERENCE **)NULL; 890 completions_must_be_rebuilt (); 891 892 /* If there is a previous loop waiting for us, restore it now. */ 893 if (echo_area_is_active) 894 pop_echo_area (); 895 896 return (line); 897 } 898 899 /* Read a line in the echo area with completion over COMPLETIONS. */ 900 char * 901 info_read_completing_in_echo_area (WINDOW *window, 902 char *prompt, REFERENCE **completions) 903 { 904 return (info_read_completing_internal (window, prompt, completions, 1)); 905 } 906 907 /* Read a line in the echo area allowing completion over COMPLETIONS, but 908 not requiring it. */ 909 char * 910 info_read_maybe_completing (WINDOW *window, 911 char *prompt, REFERENCE **completions) 912 { 913 return (info_read_completing_internal (window, prompt, completions, 0)); 914 } 915 916 DECLARE_INFO_COMMAND (ea_possible_completions, _("List possible completions")) 917 { 918 if (!echo_area_completion_items) 919 { 920 ea_insert (window, count, key); 921 return; 922 } 923 924 build_completions (); 925 926 if (!completions_found_index) 927 { 928 terminal_ring_bell (); 929 inform_in_echo_area ((char *) _("No completions")); 930 } 931 else if ((completions_found_index == 1) && (key != '?')) 932 { 933 inform_in_echo_area ((char *) _("Sole completion")); 934 } 935 else 936 { 937 register int i, l; 938 int limit, iterations, max_label = 0; 939 940 initialize_message_buffer (); 941 printf_to_message_buffer (completions_found_index == 1 942 ? (char *) _("One completion:\n") 943 : (char *) _("%d completions:\n"), 944 (void*)((intptr_t)completions_found_index), 945 NULL, NULL); 946 947 /* Find the maximum length of a label. */ 948 for (i = 0; i < completions_found_index; i++) 949 { 950 int len = strlen (completions_found[i]->label); 951 if (len > max_label) 952 max_label = len; 953 } 954 955 max_label += 4; 956 957 /* Find out how many columns we should print in. */ 958 limit = calling_window->width / max_label; 959 if (limit != 1 && (limit * max_label == calling_window->width)) 960 limit--; 961 962 /* Avoid a possible floating exception. If max_label > width then 963 the limit will be 0 and a divide-by-zero fault will result. */ 964 if (limit == 0) 965 limit = 1; 966 967 /* How many iterations of the printing loop? */ 968 iterations = (completions_found_index + (limit - 1)) / limit; 969 970 /* Watch out for special case. If the number of completions is less 971 than LIMIT, then just do the inner printing loop. */ 972 if (completions_found_index < limit) 973 iterations = 1; 974 975 /* Print the sorted items, up-and-down alphabetically. */ 976 for (i = 0; i < iterations; i++) 977 { 978 register int j; 979 980 for (j = 0, l = i; j < limit; j++) 981 { 982 if (l >= completions_found_index) 983 break; 984 else 985 { 986 char *label; 987 int printed_length, k; 988 989 label = completions_found[l]->label; 990 printed_length = strlen (label); 991 printf_to_message_buffer ("%s", label, NULL, NULL); 992 993 if (j + 1 < limit) 994 { 995 for (k = 0; k < max_label - printed_length; k++) 996 printf_to_message_buffer (" ", NULL, NULL, NULL); 997 } 998 } 999 l += iterations; 1000 } 1001 printf_to_message_buffer ("\n", NULL, NULL, NULL); 1002 } 1003 1004 /* Make a new node to hold onto possible completions. Don't destroy 1005 dangling pointers. */ 1006 { 1007 NODE *temp; 1008 1009 temp = message_buffer_to_node (); 1010 add_gcable_pointer (temp->contents); 1011 name_internal_node (temp, compwin_name); 1012 possible_completions_output_node = temp; 1013 } 1014 1015 /* Find a suitable window for displaying the completions output. 1016 First choice is an existing window showing completions output. 1017 If there is only one window, and it is large, make another 1018 (smaller) window, and use that one. Otherwise, use the caller's 1019 window. */ 1020 { 1021 WINDOW *compwin; 1022 1023 compwin = get_internal_info_window (compwin_name); 1024 1025 if (!compwin) 1026 { 1027 /* If we can split the window to display most of the completion 1028 items, then do so. */ 1029 if (calling_window->height > (iterations * 2) 1030 && calling_window->height / 2 >= WINDOW_MIN_SIZE) 1031 { 1032 int start, pagetop; 1033 #ifdef SPLIT_BEFORE_ACTIVE 1034 int end; 1035 #endif 1036 1037 active_window = calling_window; 1038 1039 /* Perhaps we can scroll this window on redisplay. */ 1040 start = calling_window->first_row; 1041 pagetop = calling_window->pagetop; 1042 1043 compwin = 1044 window_make_window (possible_completions_output_node); 1045 active_window = the_echo_area; 1046 window_change_window_height 1047 (compwin, -(compwin->height - (iterations + 2))); 1048 1049 window_adjust_pagetop (calling_window); 1050 remember_calling_window (calling_window); 1051 1052 #if defined (SPLIT_BEFORE_ACTIVE) 1053 /* If the pagetop hasn't changed, scrolling the calling 1054 window is a reasonable thing to do. */ 1055 if (pagetop == calling_window->pagetop) 1056 { 1057 end = start + calling_window->height; 1058 display_scroll_display 1059 (start, end, calling_window->prev->height + 1); 1060 } 1061 #else /* !SPLIT_BEFORE_ACTIVE */ 1062 /* If the pagetop has changed, set the new pagetop here. */ 1063 if (pagetop != calling_window->pagetop) 1064 { 1065 int newtop = calling_window->pagetop; 1066 calling_window->pagetop = pagetop; 1067 set_window_pagetop (calling_window, newtop); 1068 } 1069 #endif /* !SPLIT_BEFORE_ACTIVE */ 1070 1071 echo_area_completions_window = compwin; 1072 remember_window_and_node (compwin, compwin->node); 1073 } 1074 else 1075 compwin = calling_window; 1076 } 1077 1078 if (compwin->node != possible_completions_output_node) 1079 { 1080 window_set_node_of_window 1081 (compwin, possible_completions_output_node); 1082 remember_window_and_node (compwin, compwin->node); 1083 } 1084 1085 display_update_display (windows); 1086 } 1087 } 1088 } 1089 1090 DECLARE_INFO_COMMAND (ea_complete, _("Insert completion")) 1091 { 1092 if (!echo_area_completion_items) 1093 { 1094 ea_insert (window, count, key); 1095 return; 1096 } 1097 1098 /* If KEY is SPC, and we are not forcing completion to take place, simply 1099 insert the key. */ 1100 if (!echo_area_must_complete_p && key == SPC) 1101 { 1102 ea_insert (window, count, key); 1103 return; 1104 } 1105 1106 if (ea_last_executed_command == (VFunction *) ea_complete) 1107 { 1108 /* If the keypress is a SPC character, and we have already tried 1109 completing once, and there are several completions, then check 1110 the batch of completions to see if any continue with a space. 1111 If there are some, insert the space character and continue. */ 1112 if (key == SPC && completions_found_index > 1) 1113 { 1114 register int i, offset; 1115 1116 offset = input_line_end - input_line_beg; 1117 1118 for (i = 0; i < completions_found_index; i++) 1119 if (completions_found[i]->label[offset] == ' ') 1120 break; 1121 1122 if (completions_found[i]) 1123 ea_insert (window, 1, ' '); 1124 else 1125 { 1126 ea_possible_completions (window, count, key); 1127 return; 1128 } 1129 } 1130 else 1131 { 1132 ea_possible_completions (window, count, key); 1133 return; 1134 } 1135 } 1136 1137 input_line_point = input_line_end; 1138 build_completions (); 1139 1140 if (!completions_found_index) 1141 terminal_ring_bell (); 1142 else if (LCD_completion->label[0] == '\0') 1143 ea_possible_completions (window, count, key); 1144 else 1145 { 1146 register int i; 1147 input_line_point = input_line_end = input_line_beg; 1148 for (i = 0; LCD_completion->label[i]; i++) 1149 ea_insert (window, 1, LCD_completion->label[i]); 1150 } 1151 } 1152 1153 /* Utility REFERENCE used to store possible LCD. */ 1154 static REFERENCE LCD_reference = { 1155 (char *)NULL, (char *)NULL, (char *)NULL, 0, 0, 0 1156 }; 1157 1158 static void remove_completion_duplicates (void); 1159 1160 /* Variables which remember the state of the most recent call 1161 to build_completions (). */ 1162 static char *last_completion_request = (char *)NULL; 1163 static REFERENCE **last_completion_items = (REFERENCE **)NULL; 1164 1165 /* How to tell the completion builder to reset internal state. */ 1166 static void 1167 completions_must_be_rebuilt (void) 1168 { 1169 maybe_free (last_completion_request); 1170 last_completion_request = (char *)NULL; 1171 last_completion_items = (REFERENCE **)NULL; 1172 } 1173 1174 /* Build a list of possible completions from echo_area_completion_items, 1175 and the contents of input_line. */ 1176 static void 1177 build_completions (void) 1178 { 1179 register int i, len; 1180 register REFERENCE *entry; 1181 char *request; 1182 int informed_of_lengthy_job = 0; 1183 1184 /* If there are no items to complete over, exit immediately. */ 1185 if (!echo_area_completion_items) 1186 { 1187 completions_found_index = 0; 1188 LCD_completion = (REFERENCE *)NULL; 1189 return; 1190 } 1191 1192 /* Check to see if this call to build completions is the same as the last 1193 call to build completions. */ 1194 len = input_line_end - input_line_beg; 1195 request = (char *)xmalloc (1 + len); 1196 strncpy (request, &input_line[input_line_beg], len); 1197 request[len] = '\0'; 1198 1199 if (last_completion_request && last_completion_items && 1200 last_completion_items == echo_area_completion_items && 1201 (strcmp (last_completion_request, request) == 0)) 1202 { 1203 free (request); 1204 return; 1205 } 1206 1207 maybe_free (last_completion_request); 1208 last_completion_request = request; 1209 last_completion_items = echo_area_completion_items; 1210 1211 /* Always start at the beginning of the list. */ 1212 completions_found_index = 0; 1213 LCD_completion = (REFERENCE *)NULL; 1214 1215 for (i = 0; (entry = echo_area_completion_items[i]); i++) 1216 { 1217 if (strncasecmp (request, entry->label, len) == 0) 1218 add_pointer_to_array (entry, completions_found_index, 1219 completions_found, completions_found_slots, 1220 20, REFERENCE *); 1221 1222 if (!informed_of_lengthy_job && completions_found_index > 100) 1223 { 1224 informed_of_lengthy_job = 1; 1225 window_message_in_echo_area ((char *) _("Building completions..."), 1226 NULL, NULL); 1227 } 1228 } 1229 1230 if (!completions_found_index) 1231 return; 1232 1233 /* Sort and prune duplicate entries from the completions array. */ 1234 remove_completion_duplicates (); 1235 1236 /* If there is only one completion, just return that. */ 1237 if (completions_found_index == 1) 1238 { 1239 LCD_completion = completions_found[0]; 1240 return; 1241 } 1242 1243 /* Find the least common denominator. */ 1244 { 1245 long shortest = 100000; 1246 1247 for (i = 1; i < completions_found_index; i++) 1248 { 1249 register int j; 1250 int c1, c2; 1251 1252 for (j = 0; 1253 (c1 = info_tolower (completions_found[i - 1]->label[j])) && 1254 (c2 = info_tolower (completions_found[i]->label[j])); 1255 j++) 1256 if (c1 != c2) 1257 break; 1258 1259 if (shortest > j) 1260 shortest = j; 1261 } 1262 1263 maybe_free (LCD_reference.label); 1264 LCD_reference.label = (char *)xmalloc (1 + shortest); 1265 /* Since both the sorting done inside remove_completion_duplicates 1266 and all the comparisons above are case-insensitive, it's 1267 possible that the completion we are going to return is 1268 identical to what the user typed but for the letter-case. This 1269 is confusing, since the user could type FOOBAR<TAB> and get her 1270 string change letter-case for no good reason. So try to find a 1271 possible completion whose letter-case is identical, and if so, 1272 use that. */ 1273 if (completions_found_index > 1) 1274 { 1275 int req_len = strlen (request); 1276 1277 for (i = 0; i < completions_found_index; i++) 1278 if (strncmp (request, completions_found[i]->label, req_len) == 0) 1279 break; 1280 /* If none of the candidates match exactly, use the first one. */ 1281 if (i >= completions_found_index) 1282 i = 0; 1283 } 1284 strncpy (LCD_reference.label, completions_found[i]->label, shortest); 1285 LCD_reference.label[shortest] = '\0'; 1286 LCD_completion = &LCD_reference; 1287 } 1288 1289 if (informed_of_lengthy_job) 1290 echo_area_initialize_node (); 1291 } 1292 1293 /* Function called by qsort. */ 1294 static int 1295 compare_references (const void *entry1, const void *entry2) 1296 { 1297 REFERENCE **e1 = (REFERENCE **) entry1; 1298 REFERENCE **e2 = (REFERENCE **) entry2; 1299 1300 return (strcasecmp ((*e1)->label, (*e2)->label)); 1301 } 1302 1303 /* Prune duplicate entries from COMPLETIONS_FOUND. */ 1304 static void 1305 remove_completion_duplicates (void) 1306 { 1307 register int i, j; 1308 REFERENCE **temp; 1309 int newlen; 1310 1311 if (!completions_found_index) 1312 return; 1313 1314 /* Sort the items. */ 1315 qsort (completions_found, completions_found_index, sizeof (REFERENCE *), 1316 compare_references); 1317 1318 for (i = 0, newlen = 1; i < completions_found_index - 1; i++) 1319 { 1320 if (strcmp (completions_found[i]->label, 1321 completions_found[i + 1]->label) == 0) 1322 completions_found[i] = (REFERENCE *)NULL; 1323 else 1324 newlen++; 1325 } 1326 1327 /* We have marked all the dead slots. It is faster to copy the live slots 1328 twice than to prune the dead slots one by one. */ 1329 temp = (REFERENCE **)xmalloc ((1 + newlen) * sizeof (REFERENCE *)); 1330 for (i = 0, j = 0; i < completions_found_index; i++) 1331 if (completions_found[i]) 1332 temp[j++] = completions_found[i]; 1333 1334 for (i = 0; i < newlen; i++) 1335 completions_found[i] = temp[i]; 1336 1337 completions_found[i] = (REFERENCE *)NULL; 1338 completions_found_index = newlen; 1339 free (temp); 1340 } 1341 1342 /* Scroll the "other" window. If there is a window showing completions, scroll 1343 that one, otherwise scroll the window which was active on entering the read 1344 function. */ 1345 DECLARE_INFO_COMMAND (ea_scroll_completions_window, _("Scroll the completions window")) 1346 { 1347 WINDOW *compwin; 1348 int old_pagetop; 1349 1350 compwin = get_internal_info_window (compwin_name); 1351 1352 if (!compwin) 1353 compwin = calling_window; 1354 1355 old_pagetop = compwin->pagetop; 1356 1357 /* Let info_scroll_forward () do the work, and print any messages that 1358 need to be displayed. */ 1359 info_scroll_forward (compwin, count, key); 1360 } 1361 1362 /* Function which gets called when an Info window is deleted while the 1363 echo area is active. WINDOW is the window which has just been deleted. */ 1364 void 1365 echo_area_inform_of_deleted_window (WINDOW *window) 1366 { 1367 /* If this is the calling_window, forget what we remembered about it. */ 1368 if (window == calling_window) 1369 { 1370 if (active_window != the_echo_area) 1371 remember_calling_window (active_window); 1372 else 1373 remember_calling_window (windows); 1374 } 1375 1376 /* If this window was the echo_area_completions_window, then notice that 1377 the window has been deleted. */ 1378 if (window == echo_area_completions_window) 1379 echo_area_completions_window = (WINDOW *)NULL; 1380 } 1381 1382 /* **************************************************************** */ 1384 /* */ 1385 /* Pushing and Popping the Echo Area */ 1386 /* */ 1387 /* **************************************************************** */ 1388 1389 /* Push and Pop the echo area. */ 1390 typedef struct { 1391 char *line; 1392 char *prompt; 1393 REFERENCE **comp_items; 1394 int point, beg, end; 1395 int must_complete; 1396 NODE node; 1397 WINDOW *compwin; 1398 } PUSHED_EA; 1399 1400 static PUSHED_EA **pushed_echo_areas = (PUSHED_EA **)NULL; 1401 static int pushed_echo_areas_index = 0; 1402 static int pushed_echo_areas_slots = 0; 1403 1404 /* Pushing the echo_area has a side effect of zeroing the completion_items. */ 1405 static void 1406 push_echo_area (void) 1407 { 1408 PUSHED_EA *pushed; 1409 1410 pushed = (PUSHED_EA *)xmalloc (sizeof (PUSHED_EA)); 1411 pushed->line = xstrdup (input_line); 1412 pushed->prompt = input_line_prompt; 1413 pushed->point = input_line_point; 1414 pushed->beg = input_line_beg; 1415 pushed->end = input_line_end; 1416 pushed->node = input_line_node; 1417 pushed->comp_items = echo_area_completion_items; 1418 pushed->must_complete = echo_area_must_complete_p; 1419 pushed->compwin = echo_area_completions_window; 1420 1421 add_pointer_to_array (pushed, pushed_echo_areas_index, pushed_echo_areas, 1422 pushed_echo_areas_slots, 4, PUSHED_EA *); 1423 1424 echo_area_completion_items = (REFERENCE **)NULL; 1425 } 1426 1427 static void 1428 pop_echo_area (void) 1429 { 1430 PUSHED_EA *popped; 1431 1432 popped = pushed_echo_areas[--pushed_echo_areas_index]; 1433 1434 strcpy (input_line, popped->line); 1435 free (popped->line); 1436 input_line_prompt = popped->prompt; 1437 input_line_point = popped->point; 1438 input_line_beg = popped->beg; 1439 input_line_end = popped->end; 1440 input_line_node = popped->node; 1441 echo_area_completion_items = popped->comp_items; 1442 echo_area_must_complete_p = popped->must_complete; 1443 echo_area_completions_window = popped->compwin; 1444 completions_must_be_rebuilt (); 1445 1446 /* If the completion window no longer exists, forget about it. */ 1447 if (echo_area_completions_window) 1448 { 1449 register WINDOW *win; 1450 1451 for (win = windows; win; win = win->next) 1452 if (echo_area_completions_window == win) 1453 break; 1454 1455 /* If the window wasn't found, then it has already been deleted. */ 1456 if (!win) 1457 echo_area_completions_window = (WINDOW *)NULL; 1458 } 1459 1460 free (popped); 1461 } 1462 1463 /* Returns non-zero if any of the prior stacked calls to read in the echo 1464 area produced a completions window. */ 1465 static int 1466 echo_area_stack_contains_completions_p (void) 1467 { 1468 register int i; 1469 1470 for (i = 0; i < pushed_echo_areas_index; i++) 1471 if (pushed_echo_areas[i]->compwin) 1472 return (1); 1473 1474 return (0); 1475 } 1476 1477 /* **************************************************************** */ 1479 /* */ 1480 /* Error Messages While Reading in Echo Area */ 1481 /* */ 1482 /* **************************************************************** */ 1483 1484 #if defined (HAVE_SYS_TIME_H) 1485 # include <sys/time.h> 1486 # define HAVE_STRUCT_TIMEVAL 1487 #endif /* HAVE_SYS_TIME_H */ 1488 1489 static void 1490 pause_or_input (void) 1491 { 1492 #ifdef FD_SET 1493 struct timeval timer; 1494 fd_set readfds; 1495 int ready; 1496 1497 FD_ZERO (&readfds); 1498 FD_SET (fileno (stdin), &readfds); 1499 timer.tv_sec = 2; 1500 timer.tv_usec = 0; 1501 ready = select (fileno (stdin) + 1, &readfds, (fd_set *) NULL, 1502 (fd_set *) NULL, &timer); 1503 #endif /* FD_SET */ 1504 } 1505 1506 /* Print MESSAGE right after the end of the current line, and wait 1507 for input or a couple of seconds, whichever comes first. Then flush the 1508 informational message that was printed. */ 1509 void 1510 inform_in_echo_area (const char *message) 1511 { 1512 int i; 1513 char *text; 1514 int avail = EA_MAX_INPUT + 1 - input_line_end; 1515 1516 text = xstrdup (message); 1517 for (i = 0; text[i] && text[i] != '\n' && i < avail; i++) 1518 ; 1519 text[i] = 0; 1520 1521 echo_area_initialize_node (); 1522 sprintf (&input_line[input_line_end], "%s[%s]\n", 1523 echo_area_is_active ? " ": "", text); 1524 free (text); 1525 the_echo_area->point = input_line_point; 1526 display_update_one_window (the_echo_area); 1527 display_cursor_at_point (active_window); 1528 fflush (stdout); 1529 pause_or_input (); 1530 echo_area_initialize_node (); 1531 } 1532