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