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