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