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. */
36 int info_aborted_echo_area = 0;
37
38 /* Non-zero means that the echo area is being used to read input. */
39 int echo_area_is_active = 0;
40
41 /* The address of the last command executed in the echo area. */
42 VFunction *ea_last_executed_command = (VFunction *)NULL;
43
44 /* Non-zero means that the last command executed while reading input
45 killed some text. */
46 int echo_area_last_command_was_kill = 0;
47
48 /* Variables which hold on to the current state of the input line. */
49 static char input_line[1 + EA_MAX_INPUT];
50 static char *input_line_prompt;
51 static int input_line_point;
52 static int input_line_beg;
53 static int input_line_end;
54 static NODE input_line_node = {
55 (char *)NULL, (char *)NULL, (char *)NULL, input_line,
56 EA_MAX_INPUT, 0, N_IsInternal
57 };
58
59 static void echo_area_initialize_node (void);
60 static void push_echo_area (void), pop_echo_area (void);
61 static int echo_area_stack_contains_completions_p (void);
62
63 static void ea_kill_text (int from, int to);
64
65 /* Non-zero means we force the user to complete. */
66 static int echo_area_must_complete_p = 0;
67 static int completions_window_p (WINDOW *window);
68
69 /* If non-null, this is a window which was specifically created to display
70 possible completions output. We remember it so we can delete it when
71 appropriate. */
72 static WINDOW *echo_area_completions_window = (WINDOW *)NULL;
73
74 /* Variables which keep track of the window which was active prior to
75 entering the echo area. */
76 static WINDOW *calling_window = (WINDOW *)NULL;
77 static NODE *calling_window_node = (NODE *)NULL;
78 static long calling_window_point = 0;
79 static long calling_window_pagetop = 0;
80
81 /* Remember the node and pertinent variables of the calling window. */
82 static void
remember_calling_window(WINDOW * window)83 remember_calling_window (WINDOW *window)
84 {
85 /* Only do this if the calling window is not the completions window, or,
86 if it is the completions window and there is no other window. */
87 if (!completions_window_p (window) ||
88 ((window == windows) && !(window->next)))
89 {
90 calling_window = window;
91 calling_window_node = window->node;
92 calling_window_point = window->point;
93 calling_window_pagetop = window->pagetop;
94 }
95 }
96
97 /* Restore the caller's window so that it shows the node that it was showing
98 on entry to info_read_xxx_echo_area (). */
99 static void
restore_calling_window(void)100 restore_calling_window (void)
101 {
102 register WINDOW *win, *compwin = (WINDOW *)NULL;
103
104 /* If the calling window is still visible, and it is the window that
105 we used for completions output, then restore the calling window. */
106 for (win = windows; win; win = win->next)
107 {
108 if (completions_window_p (win))
109 compwin = win;
110
111 if (win == calling_window && win == compwin)
112 {
113 window_set_node_of_window (calling_window, calling_window_node);
114 calling_window->point = calling_window_point;
115 calling_window->pagetop = calling_window_pagetop;
116 compwin = (WINDOW *)NULL;
117 break;
118 }
119 }
120
121 /* Delete the completions window if it is still present, it isn't the
122 last window on the screen, and there aren't any prior echo area reads
123 pending which created a completions window. */
124 if (compwin)
125 {
126 if ((compwin != windows || windows->next) &&
127 !echo_area_stack_contains_completions_p ())
128 {
129 WINDOW *next;
130 int pagetop = 0;
131 int start = 0;
132 int end = 0;
133 int amount = 0;
134
135 next = compwin->next;
136 if (next)
137 {
138 start = next->first_row;
139 end = start + next->height;
140 amount = - (compwin->height + 1);
141 pagetop = next->pagetop;
142 }
143
144 info_delete_window_internal (compwin);
145
146 /* This is not necessary because info_delete_window_internal ()
147 calls echo_area_inform_of_deleted_window (), which does the
148 right thing. */
149 #if defined (UNNECESSARY)
150 echo_area_completions_window = (WINDOW *)NULL;
151 #endif /* UNNECESSARY */
152
153 if (next)
154 {
155 display_scroll_display (start, end, amount);
156 next->pagetop = pagetop;
157 display_update_display (windows);
158 }
159 }
160 }
161 }
162
163 /* Set up a new input line with PROMPT. */
164 static void
initialize_input_line(char * prompt)165 initialize_input_line (char *prompt)
166 {
167 input_line_prompt = prompt;
168 if (prompt)
169 strcpy (input_line, prompt);
170 else
171 input_line[0] = '\0';
172
173 input_line_beg = input_line_end = input_line_point = strlen (prompt);
174 }
175
176 static char *
echo_area_after_read(void)177 echo_area_after_read (void)
178 {
179 char *return_value;
180
181 if (info_aborted_echo_area)
182 {
183 info_aborted_echo_area = 0;
184 return_value = (char *)NULL;
185 }
186 else
187 {
188 if (input_line_beg == input_line_end)
189 return_value = xstrdup ("");
190 else
191 {
192 int line_len = input_line_end - input_line_beg;
193 return_value = (char *) xmalloc (1 + line_len);
194 strncpy (return_value, &input_line[input_line_beg], line_len);
195 return_value[line_len] = '\0';
196 }
197 }
198 return (return_value);
199 }
200
201 /* Read a line of text in the echo area. Return a malloc ()'ed string,
202 or NULL if the user aborted out of this read. WINDOW is the currently
203 active window, so that we can restore it when we need to. PROMPT, if
204 non-null, is a prompt to print before reading the line. */
205 char *
info_read_in_echo_area(WINDOW * window,char * prompt)206 info_read_in_echo_area (WINDOW *window, char *prompt)
207 {
208 char *line;
209
210 /* If the echo area is already active, remember the current state. */
211 if (echo_area_is_active)
212 push_echo_area ();
213
214 /* Initialize our local variables. */
215 initialize_input_line (prompt);
216
217 /* Initialize the echo area for the first (but maybe not the last) time. */
218 echo_area_initialize_node ();
219
220 /* Save away the original node of this window, and the window itself,
221 so echo area commands can temporarily use this window. */
222 remember_calling_window (window);
223
224 /* Let the rest of Info know that the echo area is active. */
225 echo_area_is_active++;
226 active_window = the_echo_area;
227
228 /* Read characters in the echo area. */
229 info_read_and_dispatch ();
230
231 echo_area_is_active--;
232
233 /* Restore the original active window and show point in it. */
234 active_window = calling_window;
235 restore_calling_window ();
236 display_cursor_at_point (active_window);
237 fflush (stdout);
238
239 /* Get the value of the line. */
240 line = echo_area_after_read ();
241
242 /* If there is a previous loop waiting for us, restore it now. */
243 if (echo_area_is_active)
244 pop_echo_area ();
245
246 /* Return the results to the caller. */
247 return (line);
248 }
249
250 /* (re) Initialize the echo area node. */
251 static void
echo_area_initialize_node(void)252 echo_area_initialize_node (void)
253 {
254 register int i;
255
256 for (i = input_line_end; (unsigned int) i < sizeof (input_line); i++)
257 input_line[i] = ' ';
258
259 input_line[i - 1] = '\n';
260 window_set_node_of_window (the_echo_area, &input_line_node);
261 input_line[input_line_end] = '\n';
262 }
263
264 /* Prepare to read characters in the echo area. This can initialize the
265 echo area node, but its primary purpose is to side effect the input
266 line buffer contents. */
267 void
echo_area_prep_read(void)268 echo_area_prep_read (void)
269 {
270 if (the_echo_area->node != &input_line_node)
271 echo_area_initialize_node ();
272
273 the_echo_area->point = input_line_point;
274 input_line[input_line_end] = '\n';
275 display_update_one_window (the_echo_area);
276 display_cursor_at_point (active_window);
277 }
278
279
280 /* **************************************************************** */
281 /* */
282 /* Echo Area Movement Commands */
283 /* */
284 /* **************************************************************** */
285
286 DECLARE_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
298 DECLARE_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
310 DECLARE_INFO_COMMAND (ea_beg_of_line, _("Move to the start of this line"))
311 {
312 input_line_point = input_line_beg;
313 }
314
315 DECLARE_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. */
323 DECLARE_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
363 DECLARE_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
403 DECLARE_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
433 DECLARE_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
454 DECLARE_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
469 DECLARE_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
474 DECLARE_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
482 DECLARE_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
500 DECLARE_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. */
507 DECLARE_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
550 static char **kill_ring = (char **)NULL;
551 static int kill_ring_index = 0; /* Number of kills appearing in KILL_RING. */
552 static int kill_ring_slots = 0; /* Number of slots allocated to KILL_RING. */
553 static int kill_ring_loc = 0; /* Location of current yank pointer. */
554
555 /* The largest number of kills that we remember at one time. */
556 static int max_retained_kills = 15;
557
558 DECLARE_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. */
578 DECLARE_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. */
611 DECLARE_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. */
623 DECLARE_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. */
636 DECLARE_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. */
654 DECLARE_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. */
675 static void
ea_kill_text(int from,int to)676 ea_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. */
768 static 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. */
773 static REFERENCE **completions_found = (REFERENCE **)NULL;
774 static int completions_found_index = 0;
775 static int completions_found_slots = 0;
776
777 /* The lowest common denominator found while completing. */
778 static REFERENCE *LCD_completion;
779
780 /* Internal functions used by the user calls. */
781 static void build_completions (void), completions_must_be_rebuilt (void);
782
783 /* Variable which holds the output of completions. */
784 static NODE *possible_completions_output_node = (NODE *)NULL;
785
786 static char *compwin_name = "*Completions*";
787
788 /* Return non-zero if WINDOW is a window used for completions output. */
789 static int
completions_window_p(WINDOW * window)790 completions_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. */
803 char *
info_read_completing_internal(WINDOW * window,char * prompt,REFERENCE ** completions,int force)804 info_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. */
897 char *
info_read_completing_in_echo_area(WINDOW * window,char * prompt,REFERENCE ** completions)898 info_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. */
906 char *
info_read_maybe_completing(WINDOW * window,char * prompt,REFERENCE ** completions)907 info_read_maybe_completing (WINDOW *window,
908 char *prompt, REFERENCE **completions)
909 {
910 return (info_read_completing_internal (window, prompt, completions, 0));
911 }
912
913 DECLARE_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
1087 DECLARE_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. */
1151 static REFERENCE LCD_reference = {
1152 (char *)NULL, (char *)NULL, (char *)NULL, 0, 0, 0
1153 };
1154
1155 static void remove_completion_duplicates (void);
1156
1157 /* Variables which remember the state of the most recent call
1158 to build_completions (). */
1159 static char *last_completion_request = (char *)NULL;
1160 static REFERENCE **last_completion_items = (REFERENCE **)NULL;
1161
1162 /* How to tell the completion builder to reset internal state. */
1163 static void
completions_must_be_rebuilt(void)1164 completions_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. */
1173 static void
build_completions(void)1174 build_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. */
1291 static int
compare_references(const void * entry1,const void * entry2)1292 compare_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. */
1301 static void
remove_completion_duplicates(void)1302 remove_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. */
1342 DECLARE_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. */
1361 void
echo_area_inform_of_deleted_window(WINDOW * window)1362 echo_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. */
1386 typedef 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
1396 static PUSHED_EA **pushed_echo_areas = (PUSHED_EA **)NULL;
1397 static int pushed_echo_areas_index = 0;
1398 static int pushed_echo_areas_slots = 0;
1399
1400 /* Pushing the echo_area has a side effect of zeroing the completion_items. */
1401 static void
push_echo_area(void)1402 push_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
1423 static void
pop_echo_area(void)1424 pop_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. */
1461 static int
echo_area_stack_contains_completions_p(void)1462 echo_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
1484 static void
pause_or_input(void)1485 pause_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. */
1504 void
inform_in_echo_area(const char * message)1505 inform_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