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. */
34 int info_aborted_echo_area = 0;
35
36 /* Non-zero means that the echo area is being used to read input. */
37 int echo_area_is_active = 0;
38
39 /* The address of the last command executed in the echo area. */
40 VFunction *ea_last_executed_command = (VFunction *)NULL;
41
42 /* Non-zero means that the last command executed while reading input
43 killed some text. */
44 int echo_area_last_command_was_kill = 0;
45
46 /* Variables which hold on to the current state of the input line. */
47 static char input_line[1 + EA_MAX_INPUT];
48 static char *input_line_prompt;
49 static int input_line_point;
50 static int input_line_beg;
51 static int input_line_end;
52 static NODE input_line_node = {
53 (char *)NULL, (char *)NULL, (char *)NULL, input_line,
54 EA_MAX_INPUT, 0, N_IsInternal
55 };
56
57 static void echo_area_initialize_node (void);
58 static void push_echo_area (void), pop_echo_area (void);
59 static int echo_area_stack_contains_completions_p (void);
60
61 static void ea_kill_text (int from, int to);
62
63 /* Non-zero means we force the user to complete. */
64 static int echo_area_must_complete_p = 0;
65 static 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. */
70 static 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. */
74 static WINDOW *calling_window = (WINDOW *)NULL;
75 static NODE *calling_window_node = (NODE *)NULL;
76 static long calling_window_point = 0;
77 static long calling_window_pagetop = 0;
78
79 /* Remember the node and pertinent variables of the calling window. */
80 static void
remember_calling_window(WINDOW * window)81 remember_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 (). */
97 static void
restore_calling_window(void)98 restore_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. */
162 static void
initialize_input_line(char * prompt)163 initialize_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
174 static char *
echo_area_after_read(void)175 echo_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. */
203 char *
info_read_in_echo_area(WINDOW * window,char * prompt)204 info_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. */
249 static void
echo_area_initialize_node(void)250 echo_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. */
265 void
echo_area_prep_read(void)266 echo_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
284 DECLARE_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
296 DECLARE_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
308 DECLARE_INFO_COMMAND (ea_beg_of_line, _("Move to the start of this line"))
309 {
310 input_line_point = input_line_beg;
311 }
312
313 DECLARE_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. */
321 DECLARE_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
361 DECLARE_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
401 DECLARE_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
431 DECLARE_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
452 DECLARE_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
467 DECLARE_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
472 DECLARE_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
480 DECLARE_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
498 DECLARE_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. */
505 DECLARE_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
548 static char **kill_ring = (char **)NULL;
549 static int kill_ring_index = 0; /* Number of kills appearing in KILL_RING. */
550 static int kill_ring_slots = 0; /* Number of slots allocated to KILL_RING. */
551 static int kill_ring_loc = 0; /* Location of current yank pointer. */
552
553 /* The largest number of kills that we remember at one time. */
554 static int max_retained_kills = 15;
555
556 DECLARE_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. */
576 DECLARE_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. */
609 DECLARE_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. */
621 DECLARE_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. */
634 DECLARE_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. */
652 DECLARE_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. */
673 static void
ea_kill_text(int from,int to)674 ea_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. */
766 static 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. */
771 static REFERENCE **completions_found = (REFERENCE **)NULL;
772 static int completions_found_index = 0;
773 static int completions_found_slots = 0;
774
775 /* The lowest common denominator found while completing. */
776 static REFERENCE *LCD_completion;
777
778 /* Internal functions used by the user calls. */
779 static void build_completions (void), completions_must_be_rebuilt (void);
780
781 /* Variable which holds the output of completions. */
782 static NODE *possible_completions_output_node = (NODE *)NULL;
783
784 static char *compwin_name = "*Completions*";
785
786 /* Return non-zero if WINDOW is a window used for completions output. */
787 static int
completions_window_p(WINDOW * window)788 completions_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. */
801 char *
info_read_completing_internal(WINDOW * window,char * prompt,REFERENCE ** completions,int force)802 info_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. */
895 char *
info_read_completing_in_echo_area(WINDOW * window,char * prompt,REFERENCE ** completions)896 info_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. */
904 char *
info_read_maybe_completing(WINDOW * window,char * prompt,REFERENCE ** completions)905 info_read_maybe_completing (WINDOW *window,
906 char *prompt, REFERENCE **completions)
907 {
908 return (info_read_completing_internal (window, prompt, completions, 0));
909 }
910
911 DECLARE_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
1085 DECLARE_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. */
1149 static REFERENCE LCD_reference = {
1150 (char *)NULL, (char *)NULL, (char *)NULL, 0, 0, 0
1151 };
1152
1153 static void remove_completion_duplicates (void);
1154
1155 /* Variables which remember the state of the most recent call
1156 to build_completions (). */
1157 static char *last_completion_request = (char *)NULL;
1158 static REFERENCE **last_completion_items = (REFERENCE **)NULL;
1159
1160 /* How to tell the completion builder to reset internal state. */
1161 static void
completions_must_be_rebuilt(void)1162 completions_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. */
1171 static void
build_completions(void)1172 build_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. */
1289 static int
compare_references(const void * entry1,const void * entry2)1290 compare_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. */
1299 static void
remove_completion_duplicates(void)1300 remove_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. */
1340 DECLARE_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. */
1359 void
echo_area_inform_of_deleted_window(WINDOW * window)1360 echo_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. */
1384 typedef 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
1394 static PUSHED_EA **pushed_echo_areas = (PUSHED_EA **)NULL;
1395 static int pushed_echo_areas_index = 0;
1396 static int pushed_echo_areas_slots = 0;
1397
1398 /* Pushing the echo_area has a side effect of zeroing the completion_items. */
1399 static void
push_echo_area(void)1400 push_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
1421 static void
pop_echo_area(void)1422 pop_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. */
1459 static int
echo_area_stack_contains_completions_p(void)1460 echo_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
1482 static void
pause_or_input(void)1483 pause_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. */
1502 void
inform_in_echo_area(const char * message)1503 inform_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