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