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