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