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