home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / OLEO130S.ZIP / oleo130s.tar / oleo-1.3 / cmd.c < prev    next >
C/C++ Source or Header  |  1993-03-31  |  54KB  |  2,347 lines

  1. /*    Copyright (C) 1993 Free Software Foundation, Inc.
  2.  
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2, or (at your option)
  6. any later version.
  7.  
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU General Public License for more details.
  12.  
  13. You should have received a copy of the GNU General Public License
  14. along with this software; see the file COPYING.  If not, write to
  15. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17.  
  18.  
  19. #include <ctype.h>
  20. #include "errno.h"
  21. #define obstack_chunk_alloc ck_malloc
  22. #define obstack_chunk_free free
  23. #include "obstack.h"
  24. #include "global.h"
  25. #include "cmd.h"
  26. #include "io-term.h"
  27. #include "io-abstract.h"
  28. #include "io-generic.h"
  29. #include "io-utils.h"
  30. #include "io-edit.h"
  31. #include "stub.h"
  32. #include "ref.h"
  33.  
  34. #undef MIN
  35. #undef MAX
  36. #define MIN(A,B) ((A) < (B) ? (A) : (B))
  37. #define MAX(A,B) ((A) > (B) ? (A) : (B))
  38.  
  39. /* Bogus mapping from KEY->CODE to ranges.  This is how bound
  40.  * macros are represented.
  41.  * This is bogus because the ranges will not be adjusted in 
  42.  * the ways they should.  Variables should be used instead. 
  43.  */
  44. int n_bound_macros;
  45. struct rng *bound_macros;
  46. int bound_macro_vec;
  47.  
  48.  
  49.  
  50. /* Flow of control centers around a select loop.  These are the 
  51.  * fd's selected on.
  52.  */
  53. SELECT_TYPE read_fd_set;
  54. SELECT_TYPE exception_fd_set;
  55. SELECT_TYPE write_fd_set;
  56.  
  57. /* These are fd's returned by the last call to select.
  58.  */
  59. SELECT_TYPE read_pending_fd_set;
  60. SELECT_TYPE exception_pending_fd_set;
  61. SELECT_TYPE write_pending_fd_set;
  62.  
  63. /* Hooks for asynchronos i/o
  64.  */
  65.  
  66. struct select_hook file_read_hooks[SELECT_SET_SIZE] = {0};
  67. struct select_hook file_exception_hooks[SELECT_SET_SIZE] = {0};
  68. struct select_hook file_write_hooks[SELECT_SET_SIZE] = {0};
  69.  
  70.  
  71. /* The current stream from which commands are being read. */
  72. struct input_stream * the_input_stream = 0;
  73.  
  74.  
  75.  
  76.  
  77. #ifdef __STDC__
  78. static struct input_stream *
  79. default_input_stream (void)
  80. #else
  81. static struct input_stream *
  82. default_input_stream ()
  83. #endif
  84. {
  85.   if (!the_input_stream)
  86.     {
  87.       the_input_stream =
  88.     (struct input_stream *)ck_malloc (sizeof (struct input_stream));
  89.       the_input_stream->_rmac = 0;
  90.       the_input_stream->_func_arg = 0;
  91.       obstack_init (&the_input_stream->_macro_stack);
  92.       the_input_stream->_macro = 0;
  93.       the_input_stream->_macro_start = 0;
  94.       the_input_stream->_macro_size = 0;
  95.       the_input_stream->prev_stream = 0;
  96.       the_input_stream->_last_macro = 0;
  97.       the_input_stream->_pushed_back_char = -1;
  98.     }
  99.   return the_input_stream;
  100. }
  101.  
  102.  
  103. /* This constructs an input stream that reads from a macro but never
  104.  * from a keyboard.  EXECUTE_CMD uses this.
  105.  */
  106.  
  107.  
  108. #ifdef __STDC__
  109. static struct input_stream *
  110. macro_only_input_stream (struct rng * rng, char * first_line, int len,
  111.              struct command_frame * frame)
  112. #else
  113. static struct input_stream *
  114. macro_only_input_stream (rng, first_line, len, frame)
  115.      struct rng * rng;
  116.      char * first_line;
  117.      int len;
  118.      struct command_frame * frame;
  119. #endif
  120. {
  121.   struct input_stream * ret;
  122.   ret = (struct input_stream *)ck_malloc (sizeof (struct input_stream));
  123.   ret->_func_arg = 0;
  124.   obstack_init (&ret->_macro_stack);
  125.   ret->_rmac =
  126.     (struct macro *) obstack_alloc (&ret->_macro_stack, sizeof (struct macro));
  127.   ret->_rmac->mac_prev = 0;
  128.   ret->_rmac->mac_rng = *rng;
  129.   ret->_rmac->mac_row = rng->lr;
  130.   ret->_rmac->mac_col = rng->lc;
  131.   (void) obstack_grow (&ret->_macro_stack, first_line, len);
  132.   (void) obstack_grow (&ret->_macro_stack, "", 1);
  133.   ret->_rmac->mac_start = ret->_rmac->mac_exe
  134.     = (unsigned char *) obstack_finish (&ret->_macro_stack);
  135.   ret->_macro = 0;
  136.   ret->_macro_start = 0;
  137.   ret->_macro_size = 0;
  138.   ret->_last_macro = 0;
  139.   ret->prev_stream = frame->input;
  140.   {
  141.     struct input_stream * key = frame->input;
  142.     while (frame->input == key)
  143.       {
  144.     frame->input = ret;
  145.     frame = frame->prev;
  146.       }
  147.   }
  148.   ret->_pushed_back_char = -1;
  149.   return ret;
  150. }
  151.  
  152. #ifdef __STDC__
  153. void
  154. free_input_stream (struct input_stream * stream)
  155. #else
  156. void
  157. free_input_stream (stream)
  158.      struct input_stream * stream;
  159. #endif
  160. {
  161.   if (stream->_macro_start)
  162.     free (stream->_macro_start);
  163.   if (stream->_last_macro)
  164.     free (stream->_last_macro);
  165.   obstack_free (&stream->_macro_stack, 0);
  166.   free (stream);
  167. }
  168.  
  169. /* This gets rid of an input stream created by macro_only_input_stream.
  170.  * It fixes the INPUT fields of pending command frames.
  171.  */
  172.  
  173. #ifdef __STDC__
  174. void
  175. pop_input_stream (void)
  176. #else
  177. void
  178. pop_input_stream ()
  179. #endif
  180. {
  181.   if (the_cmd_frame->input->prev_stream)
  182.     {
  183.       struct command_frame * fr = the_cmd_frame;
  184.       struct input_stream * key = the_cmd_frame->input;
  185.       while (fr->input == key)
  186.     {
  187.       fr->input = key->prev_stream;
  188.       fr = fr->prev;
  189.     }
  190.       free_input_stream (key);
  191.       return;
  192.     }
  193. }
  194.  
  195.  
  196. /* Macros 
  197.  * These are the commands the user has to interact with macros.
  198.  */
  199.  
  200. #ifdef __STDC__
  201. void
  202. start_entering_macro (void)
  203. #else
  204. void
  205. start_entering_macro ()
  206. #endif
  207. {
  208.   if (making_macro)
  209.     {
  210.       io_error_msg ("Can't define two macros at once");
  211.       return;
  212.     }
  213.   making_macro_size = 20;
  214.   making_macro = making_macro_start = ck_malloc (5 + making_macro_size);
  215. }
  216.  
  217. #ifdef __STDC__
  218. void
  219. bound_macro (int num)
  220. #else
  221. void
  222. bound_macro (num)
  223.      int num;
  224. #endif
  225. {
  226.   struct macro *old;
  227.   CELL *cp;
  228.  
  229.   cp = find_cell (bound_macros[num].lr, bound_macros[num].lc);
  230.   if (!cp || GET_TYP (cp) != TYP_STR || cp->cell_str[0] == '\0')
  231.     return;
  232.   old = rmac;
  233.   rmac =
  234.     (struct macro *) obstack_alloc (¯o_stack, sizeof (struct macro));
  235.   rmac->mac_prev = old;
  236.   rmac->mac_rng = bound_macros[num];
  237.   rmac->mac_row = bound_macros[num].lr;
  238.   rmac->mac_col = bound_macros[num].lc;
  239.   obstack_grow (¯o_stack, cp->cell_str, 1 + strlen (cp->cell_str));
  240.   rmac->mac_start = rmac->mac_exe =
  241.     (unsigned char *) obstack_finish (¯o_stack);
  242. }
  243.  
  244. #ifdef __STDC__
  245. void
  246. run_string_as_macro (char * macro, int count)
  247. #else
  248. void
  249. run_string_as_macro (macro, count)
  250.      char * macro;
  251.      int count;
  252. #endif
  253. {
  254.   struct rng rng;
  255.   while (count--)
  256.     {
  257.       rng.lr = rng.hr = rng.lc = rng.hc = MIN_ROW;
  258.       macro_only_input_stream (&rng, macro, strlen (macro), the_cmd_frame);
  259.       command_loop (1);
  260.     }
  261. }
  262.  
  263. #ifdef __STDC__
  264. void
  265. call_last_kbd_macro (int count)
  266. #else
  267. void
  268. call_last_kbd_macro (count)
  269.      int count;
  270. #endif
  271. {
  272.   if (!last_macro)
  273.     io_error_msg ("No keyboard macro entered.");
  274.   run_string_as_macro ((char *)last_macro, count);
  275. }
  276.  
  277. /* This command is automaticly inserted into the command stream
  278.  * when the end of a macro is reached.  
  279.  */
  280. #ifdef __STDC__
  281. void
  282. end_macro (void)
  283. #else
  284. void
  285. end_macro ()
  286. #endif
  287. {
  288.   CELL *cp;
  289.   struct macro *old;
  290.  
  291.   if (!rmac)
  292.     {
  293.       io_error_msg ("Not executing a macro!");
  294.       return;
  295.     }
  296.   if ((rmac->mac_row == rmac->mac_rng.hr)
  297.       && (rmac->mac_col == rmac->mac_rng.hc))
  298.     {
  299.       old = rmac->mac_prev;
  300.       obstack_free (¯o_stack, rmac);
  301.       rmac = old;
  302.     }
  303.   else
  304.     {
  305.       if (rmac->mac_row == rmac->mac_rng.hr)
  306.     {
  307.       rmac->mac_row = rmac->mac_rng.lr; 
  308.       rmac->mac_col++;
  309.     }
  310.       else
  311.     rmac->mac_row++;
  312.       
  313.       cp = find_cell (rmac->mac_row, rmac->mac_col);
  314.       
  315.       if (!cp || GET_TYP (cp) != TYP_STR || cp->cell_str[0] == '\0') 
  316.     {
  317.       old = rmac->mac_prev;
  318.       obstack_free (¯o_stack, rmac); 
  319.       rmac = old;
  320.     }
  321.       else
  322.     {
  323.       obstack_grow (¯o_stack, cp->cell_str, 1 + strlen (cp->cell_str));
  324.       rmac->mac_exe
  325.         = (unsigned char *) obstack_finish (¯o_stack);
  326.     }
  327.     }
  328. }
  329.  
  330.  
  331. /* This command is executed by the user to stop entering a macro.
  332.  */
  333. #ifdef __STDC__
  334. void
  335. stop_entering_macro (void)
  336. #else
  337. void
  338. stop_entering_macro ()
  339. #endif
  340. {
  341.   if (!making_macro)
  342.     {
  343.       if (rmac)
  344.     return;
  345.       io_error_msg ("Not defining a macro!");
  346.       return;
  347.     }
  348.  
  349.   making_macro[0] = '\0';
  350.   making_macro = 0;
  351.   if (last_macro)
  352.     ck_free (last_macro);
  353.   last_macro = making_macro_start;
  354.   making_macro_start = 0;
  355.   free (making_macro_start);
  356. }
  357.  
  358. #ifdef __STDC__
  359. void
  360. store_last_macro (struct rng * rng)
  361. #else
  362. void
  363. store_last_macro (rng)
  364.      struct rng * rng;
  365. #endif
  366. {
  367.   union vals z;
  368.   z.c_s = (char *)last_macro;
  369.   set_new_value (rng->lr, rng->lc, TYP_STR, &z);
  370. }
  371.  
  372.  
  373.  
  374. /* Scheduling 
  375.  *
  376.  * Scheduling is centered around the function real_get_chr
  377.  * which is allowed to block until an input event has occured.
  378.  * Before blocking, real_get_chr may evaluate cells and/or update 
  379.  * the display.
  380.  */
  381.  
  382.  
  383. /* Error messages are delivered to the user by invoking a command 
  384.  * that prompts with the error message, and waits for the user's next
  385.  * keypress.  This command shouldn't wait indefinitely.  After a short time,
  386.  * the error message should disappear.  This is accomplished by counting down
  387.  * a timer, then destorying the error message command frame and throwing an
  388.  * error.  The error is thrown directly rather than with io_error_msg in order
  389.  * to avoid circularity.
  390.  */
  391.  
  392. static void
  393. error_alarm ()
  394. {
  395.   if (the_cmd_frame->cmd && the_cmd_arg.timeout_seconds)
  396.     {
  397.       --the_cmd_arg.timeout_seconds;
  398.       if (!the_cmd_arg.timeout_seconds)
  399.     {
  400.       pop_unfinished_command ();
  401.       alarm_table[2].freq = 0;
  402.       longjmp (error_exception, 1);
  403.     }
  404.     }
  405.   else
  406.     alarm_table[2].freq = 0;
  407. }
  408.  
  409. struct alarm_entry alarm_table [3] = 
  410. {
  411.   {cell_alarm, 1, 0},
  412.   {error_alarm, 0, 0},
  413.   {0, 0}
  414. };
  415.  
  416. /* Function that get called whenever blocking times out. */
  417.  
  418. #ifdef __STDC__
  419. static void
  420. alarm_hooks (void)
  421. #else
  422. static void
  423. alarm_hooks ()
  424. #endif
  425. {
  426.   int x;
  427.   time_t now = time(0);
  428.   for (x = 0; alarm_table[x].fn; ++x)
  429.     if (alarm_table[x].freq
  430.     && ((now - alarm_table[x].last_time) >= alarm_table[x].freq))
  431.       {
  432.     alarm_table[x].last_time = now;
  433.     alarm_table[x].fn ();
  434.       }
  435. }
  436.  
  437.  
  438. #ifdef __STDC__
  439. static void
  440. select_hooks (void)
  441. #else
  442. static void
  443. select_hooks ()
  444. #endif
  445. {
  446.   int x;
  447.   for (x = 0; x < SELECT_SET_SIZE; ++x)
  448.     {
  449.       if (file_read_hooks[x].hook_fn && FD_ISSET (x, &read_pending_fd_set))
  450.     file_read_hooks[x].hook_fn (x);
  451.       FD_CLR (x, &read_pending_fd_set);
  452.       if (file_write_hooks[x].hook_fn && FD_ISSET (x, &write_pending_fd_set))
  453.     file_write_hooks[x].hook_fn (x);
  454.       FD_CLR (x, &write_pending_fd_set);
  455.       if (file_exception_hooks[x].hook_fn
  456.       && FD_ISSET (x, &exception_pending_fd_set))
  457.     file_exception_hooks[x].hook_fn (x);
  458.       FD_CLR (x, &exception_pending_fd_set);
  459.     }
  460. }
  461.  
  462. /* Block until we get a signal (unless system calls restart), 
  463.  * can do i/o or, until we timeout (timeout is specified in seconds,
  464.  * 0 means block indefinately).  (Front end to select)
  465.  */
  466. #ifdef __STDC__
  467. static void
  468. block_until_excitment (int timeout_seconds)
  469. #else
  470. static void
  471. block_until_excitment (timeout_seconds)
  472.      int timeout_seconds;
  473. #endif
  474. {
  475.   int ret;
  476.   struct timeval timeout;
  477.   struct timeval * time_p = 0;
  478.  
  479.   if (timeout_seconds)
  480.     {
  481.       timeout.tv_sec = timeout_seconds;
  482.       timeout.tv_usec = 0;
  483.       time_p = &timeout;
  484.     }
  485.   bcopy ((char *)&read_fd_set, (char *)&read_pending_fd_set,
  486.      sizeof (SELECT_TYPE)) ;
  487.   bcopy ((char *)&exception_fd_set,
  488.      (char *)&exception_pending_fd_set, sizeof (SELECT_TYPE));
  489.   bcopy ((char *)&write_fd_set,
  490.      (char *)&write_pending_fd_set, sizeof (SELECT_TYPE));
  491.   ret = select (SELECT_SET_SIZE,
  492.         &read_pending_fd_set, &write_pending_fd_set,
  493.         &exception_pending_fd_set, time_p);
  494.   if (ret < 0)
  495.     {
  496.       FD_ZERO (&read_pending_fd_set);
  497.       FD_ZERO (&write_pending_fd_set);
  498.       FD_ZERO (&exception_pending_fd_set);
  499.     }
  500. }
  501.  
  502. /* This is the main interact loop.  As quickly as possible
  503.  * it returns a character from the keyboard.  While waiting,
  504.  * it updates cells and the display.  If a macro is being defined,
  505.  * this function save characters in the macro.
  506.  */
  507.  
  508. #ifdef __STDC__
  509. int 
  510. real_get_chr (void)
  511. #else
  512. int 
  513. real_get_chr ()
  514. #endif
  515. {
  516.   int ch;            /* The char that will be returned. */
  517.  
  518.   /* Characters with the meta bit set are returned as
  519.    * two characters: ESC and a non-meta character.
  520.    * This buffers the non-meta character between calls.
  521.    * The value is 0 if no character is buffered, C+1 if
  522.    * C is buffered.
  523.    */
  524.   static int saved_char;
  525.  
  526.   /* A buffer of characters read in one burst from the kbd. */
  527.   static char ibuf[256];
  528.   static int i_in;        /* chars buffered */
  529.   static int i_cnt;        /* buffer position */
  530.  
  531.   alarm_hooks ();
  532.   if (saved_char)
  533.     {
  534.       ch = saved_char - 1;
  535.       saved_char = 0;
  536.       goto fini;
  537.     }
  538.  
  539.   if (i_cnt)
  540.     {
  541.       ch = ibuf[i_cnt++];
  542.       if (i_cnt == i_in)
  543.     i_cnt = i_in = 0;
  544.       goto fini;
  545.     }
  546.  
  547.   /* This loop until a character can be read. */
  548.   while (!io_input_avail ())
  549.     {
  550.       alarm_hooks ();
  551.       select_hooks ();
  552.       io_scan_for_input (0);
  553.       if (!io_input_avail ())
  554.     {
  555.       ++current_cycle;
  556.       if (auto_recalc && eval_next_cell ())
  557.         {
  558.           if (bkgrnd_recalc)
  559.         while (!io_input_avail () && eval_next_cell ())
  560.           io_scan_for_input (0);
  561.           else
  562.         while (eval_next_cell ())
  563.           ;
  564.           io_scan_for_input (0);
  565.           if (!io_input_avail ())
  566.         io_redisp ();
  567.           io_flush ();
  568.           io_scan_for_input (0);
  569.         }
  570.       else
  571.         {
  572.           int timeout = (alarm_active
  573.                  ? (alarm_seconds == 1
  574.                 ? 1
  575.                 : (alarm_seconds / 2))
  576.                  : 0);
  577.                  
  578.           --current_cycle;
  579.           io_redisp ();
  580.           io_flush ();
  581.           io_scan_for_input (0);
  582.           if (!io_input_avail ())
  583.         block_until_excitment (timeout);
  584.         }
  585.     }
  586.     }
  587.  
  588.   {
  589.     int ret;
  590.     ret = io_read_kbd (ibuf, sizeof (ibuf));
  591.     if (ret == 1)
  592.       {
  593.     ch = ibuf[0];
  594.     goto fini;
  595.       }
  596.     if (ret > 1)
  597.       {
  598.     i_cnt = 1;
  599.     i_in = ret;
  600.     ch = ibuf[0];
  601.     goto fini;
  602.       }
  603.     if (ret == 0 || errno != EINTR)
  604.       return EOF;
  605.   }
  606.  
  607. fini:
  608.  
  609.   if (ch & 0x80)
  610.     {
  611.       saved_char = 1 + (ch & 0x7f);
  612.       ch = CTRL ('[');
  613.     }
  614.  
  615.   if (making_macro)
  616.     {
  617.       /* This is stoopid and should be fixed.
  618.        * Macros (and other cell strings) should be 
  619.        * `struct line' and not c-strings.   -tl
  620.        */
  621.       if (ch == 0)
  622.     *making_macro++ = 0x80 | 'a';
  623.       else if (ch == '{')
  624.     *making_macro++ = 0x80 | 'b';
  625.       else
  626.     *making_macro++ = ch;
  627.       if (making_macro >= (making_macro_start + making_macro_size))
  628.     {
  629.       making_macro_start = ck_realloc (making_macro_start, 5
  630.                        + making_macro_size * 2);
  631.       making_macro = (making_macro_start + making_macro_size);
  632.       making_macro_size *= 2;
  633.     }
  634.     }
  635.   return ch;
  636. }
  637.  
  638.  
  639.  
  640.  
  641. /*****************************************************************
  642.  * 
  643.  * Command loops
  644.  *
  645.  * The basic cycle is that the user or a macro selects a function
  646.  * (while oleo updates the display and evaluates cells).
  647.  * A new command_frame is allocated in which to evaluate the selected 
  648.  * function.   Arguments to the function will be stored in this frame.
  649.  * The command loop interprets the FUNC_ARGS string of the selected function
  650.  * and builds an argument list.  If the FUNC_ARGS string specifies that
  651.  * the user must be prompted for an argument, an editting mode is entered
  652.  * and the command loop restarts.  The queue of command_frames form
  653.  * a stack of recursively invoked editting modes.
  654.  *
  655.  * When all of the arguments are ready, the command loop executes
  656.  * the function and discards its frame.
  657.  *
  658.  * In principle, any number of command_frames can be created and they
  659.  * could be evaluated in any order.  It is assumed in the code though that
  660.  * the frame the_cmd_frame->prev is the frame the user was in when
  661.  * the_cmd_frame was created (call it the `parent' frame).  Some arguments, 
  662.  * for example the prefix argument and the current row/col, are taken from the
  663.  * parent frame.  This is because those values may have changed in
  664.  * the_cmd_frame as the user editted arguments to the function being called.
  665.  */
  666.  
  667. /* The active command frame. This is the head of a queue which is used as a
  668.  * stack. 
  669.  */ 
  670. struct command_frame * the_cmd_frame = 0;
  671.  
  672. /* This is a list (next field) of frames that are currently running (their 
  673.  * commands are active on the c stack below the error_exception jump buffer).
  674.  */
  675. struct command_frame * running_frames = 0;
  676.  
  677.  
  678. /* This is called when the current frame has keymapped
  679.  * down to some function (stored in the_cmd_frame->_cur_cmd.
  680.  * This pushes a new frame in which the arguments to that
  681.  * command will be stored.
  682.  *
  683.  * This can also be called when the_cmd_frame is 0.  In that case,
  684.  * it will create a top-level frame.
  685.  *
  686.  */
  687.  
  688. #ifdef __STDC__
  689. void
  690. push_command_frame (struct rng * rng, char * first_line, int len)
  691. #else
  692. void
  693. push_command_frame (rng, first_line, len)
  694.      struct rng * rng;
  695.      struct line * first_line;
  696.      int len;
  697. #endif
  698. {
  699.   struct command_frame * new_cf =
  700.     (struct command_frame *)ck_malloc (sizeof (*new_cf));
  701.  
  702.   new_cf->next = new_cf;
  703.   new_cf->prev = new_cf;
  704.  
  705.   new_cf->input = (rng
  706.            ? macro_only_input_stream (rng, first_line, len, new_cf)
  707.            : default_input_stream ());
  708.  
  709.   new_cf->_setrow = NON_ROW;
  710.   new_cf->_setcol = NON_COL;
  711.   new_cf->_curow = MIN_ROW;
  712.   new_cf->_cucol = MIN_COL;
  713.   new_cf->_mkrow = NON_ROW;
  714.   new_cf->_mkcol = NON_COL;
  715.   new_cf->_input_active = 0;
  716.   new_cf->_window_after_input = -1;
  717.  
  718.   /* These may be reset later. */
  719.   new_cf->top_keymap = map_id ("main");
  720.   if (new_cf->top_keymap < 0)
  721.     new_cf->top_keymap = map_id ("universal");
  722.   new_cf->saved_cur_keymap = -1;
  723.   new_cf->_cur_keymap = map_id ("main");
  724.   new_cf->_how_many = 1;
  725.   new_cf->_cur_cmd = 0;
  726.   new_cf->_cur_vector = 0;
  727.   new_cf->_cur_chr = the_cmd_frame ? cur_chr : 0;
  728.  
  729.   init_line (&new_cf->_raw_prefix);
  730.   new_cf->_cmd_argc = 0;
  731.   new_cf->complex_to_user = 0;
  732.  
  733.   if (!the_cmd_frame)
  734.     {
  735.       /* This is a new top-level frame. */
  736.       the_cmd_frame = new_cf;
  737.       new_cf->cmd = 0;
  738.       new_cf->top_keymap =  map_id ("main");
  739.       if (new_cf->top_keymap < 0)
  740.     new_cf->top_keymap = map_id ("universal");
  741.     }
  742.   else if (cur_cmd)
  743.     {
  744.       new_cf->_cur_arg = 0;
  745.       new_cf->cmd = cur_cmd;
  746.       {
  747.     int argc = 0;
  748.     char ** prompt = new_cf->cmd->func_args;
  749.     while (prompt && *prompt)
  750.       {
  751.         new_cf->argv[argc].do_prompt = 0;
  752.         new_cf->argv[argc].is_set = 0;
  753.         new_cf->argv[argc].style = 0;
  754.         new_cf->argv[argc].arg_desc = *prompt;
  755.         new_cf->argv[argc].prompt = 0;
  756.         new_cf->argv[argc].expanded_prompt = 0;
  757.         new_cf->argv[argc].prompt_info = 0;
  758.         new_cf->argv[argc].info_line = 0;
  759.         init_line (&new_cf->argv[argc].text);
  760.         set_line (&new_cf->argv[argc].text, "");
  761.         new_cf->argv[argc].cursor = 0;
  762.         new_cf->argv[argc].overwrite = 0;
  763.         new_cf->argv[argc].inc_cmd = 0;
  764.         new_cf->argv[argc].timeout_seconds = 0;
  765.         bzero (&new_cf->argv[argc].val, sizeof (union command_arg_val));
  766.         ++argc;
  767.         ++prompt;
  768.       }
  769.     if (argc && new_cf->argv[0].arg_desc[0] == '+')
  770.       ++new_cf->argv[0].arg_desc;
  771.     new_cf->_cmd_argc = argc;
  772.     new_cf->_curow = curow;
  773.     new_cf->_cucol = cucol;
  774.     new_cf->_mkrow = mkrow;
  775.     new_cf->_mkcol = mkcol;
  776.     new_cf->_setrow = setrow;
  777.     new_cf->_setcol = setcol;
  778.     if (!rng)
  779.       new_cf->input = the_cmd_frame->input;
  780.       }
  781.     }
  782.  
  783.   new_cf->prev = the_cmd_frame;
  784.   new_cf->next = the_cmd_frame->next;
  785.   new_cf->prev->next = new_cf;
  786.   new_cf->next->prev = new_cf;
  787.   the_cmd_frame = new_cf;
  788. }
  789.  
  790. /* Remove a frame from the queue/stack. */
  791. #ifdef __STDC__
  792. void
  793. remove_cmd_frame (struct command_frame * frame)
  794. #else
  795. void
  796. remove_cmd_frame (frame)
  797.      struct command_frame * frame;
  798. #endif
  799. {
  800.   frame->next->prev = frame->prev;
  801.   frame->prev->next = frame->next;
  802.   if (the_cmd_frame == frame)
  803.     the_cmd_frame = frame->prev;
  804.   if (the_cmd_frame == frame)
  805.     {
  806.       the_cmd_frame = 0;
  807.       push_command_frame (0, 0, 0);
  808.     }
  809.   frame->next = frame->prev = 0;
  810. }
  811.  
  812.  
  813. /* This frees all of the memory allocated to FRAME (including
  814.  * the frame itself. 
  815.  */
  816. #ifdef __STDC__
  817. void
  818. free_cmd_frame (struct command_frame * frame)
  819. #else
  820. void
  821. free_cmd_frame (frame)
  822.      struct command_frame * frame;
  823. #endif
  824. {
  825.   if (frame->next)
  826.     remove_cmd_frame (frame);
  827.  
  828.   free_line (&frame->_raw_prefix);
  829.   if (frame->cmd)
  830.     {
  831.       int argc;
  832.       for (argc = 0; argc < frame->_cmd_argc; ++argc)
  833.     {
  834.       if (frame->argv[argc].is_set && frame->argv[argc].style->destroy)
  835.         frame->argv[argc].style->destroy (&frame->argv[argc]);
  836.       free_line (&frame->argv[argc].text);
  837.       if (frame->argv[argc].expanded_prompt &&
  838.           (frame->argv[argc].expanded_prompt != frame->argv[argc].prompt))
  839.         free (frame->argv[argc].expanded_prompt);
  840.     }
  841.     }
  842.   ck_free (frame);
  843. }
  844.  
  845.  
  846. /* Discard the current frame if it contains an unexecuted commnand. 
  847.  * This is used, for example, to handle break.
  848.  */
  849. #ifdef __STDC__
  850. void
  851. pop_unfinished_command (void)
  852. #else
  853. void
  854. pop_unfinished_command ()
  855. #endif
  856. {
  857.   if (the_cmd_frame->cmd)
  858.     {
  859.       int move_cursor = 0;
  860.       struct command_frame * frame = the_cmd_frame;
  861.       if (   frame->_curow != frame->prev->_curow
  862.       || frame->_cucol != frame->prev->_cucol)
  863.     {
  864.       io_hide_cell_cursor ();
  865.       move_cursor = 1;
  866.     }
  867.       remove_cmd_frame (frame);
  868.       if (move_cursor)
  869.     io_display_cell_cursor ();
  870.       free_cmd_frame (frame);
  871.     }
  872. }
  873.  
  874. /* This is called if an error has been signaled with io_error_msg.
  875.  * It discards any frames that the user has never interacted with
  876.  * and cancels all pending macros.  This is properly followed by 
  877.  * generating an error message for the user and longjmp to error_exception.
  878.  */
  879.  
  880. #ifdef __STDC__
  881. void
  882. recover_from_error (void)
  883. #else
  884. void
  885. recover_from_error ()
  886. #endif
  887. {
  888.   /* pop input streams until the bottom is reached. */
  889.   while (the_cmd_frame->input->prev_stream)
  890.     pop_input_stream ();
  891.  
  892.   /* cancel the current macros */
  893.   {
  894.     struct input_stream * stream = the_cmd_frame->input;
  895.     if (stream->_macro_start)
  896.       free (stream->_macro_start);
  897.     if (stream->_last_macro)
  898.       free (stream->_last_macro);
  899.     obstack_free (&stream->_macro_stack, 0);
  900.     obstack_init (&stream->_macro_stack);
  901.     stream->_rmac = 0;
  902.     stream->_func_arg = 0;
  903.     stream->_macro = stream->_macro_start = 0;
  904.     stream->_macro_size = 0;
  905.     stream->_pushed_back_char = -1;
  906.   }
  907.  
  908.   /* pop command frames until an interactive one is reached. */
  909.   while (the_cmd_frame->prev != the_cmd_frame
  910.      && !the_cmd_frame->complex_to_user)
  911.     {
  912.       struct command_frame * fr = the_cmd_frame;
  913.       the_cmd_frame = the_cmd_frame->prev;
  914.       free_cmd_frame (fr);
  915.     }
  916.  
  917.   /* Discard any frames that were executing */
  918.   while (running_frames)
  919.     {
  920.       struct command_frame * f = running_frames;
  921.       running_frames = running_frames->next;
  922.       f->next = 0;
  923.       free_cmd_frame (f);
  924.     }
  925. }
  926.  
  927.  
  928.  
  929. /* When we begin editting a new argument, this function sets up the
  930.  * appropriate keymap, and then resets the state of the editting commands.
  931.  *
  932.  * The return value is 1 if the user must be prompted, 0 otherwise.
  933.  */
  934. #ifdef __STDC__
  935. static int
  936. get_argument (char * prompt, struct prompt_style * style)
  937. #else
  938. static int
  939. get_argument (prompt, style)
  940.      char * prompt;
  941.      struct prompt_style * style;
  942. #endif
  943. {
  944.   the_cmd_arg.style = style;
  945.   the_cmd_arg.prompt = prompt;
  946.   if (!the_cmd_arg.expanded_prompt)
  947.     the_cmd_arg.expanded_prompt = expand_prompt (prompt);
  948.   the_cmd_frame->top_keymap = map_id (the_cmd_arg.style->keymap);
  949.   the_cmd_arg.is_set = 0;
  950.   the_cmd_arg.do_prompt = 1;
  951.   if (the_cmd_frame->top_keymap < 0)
  952.     the_cmd_frame->top_keymap = map_id ("universal");
  953.   if (macro_func_arg)
  954.     {
  955.       set_line (&the_cmd_arg.text, macro_func_arg);
  956.       {
  957.     char * arg_ptr;
  958.     char * error;
  959.     arg_ptr = the_cmd_arg.text.buf;
  960.     error = the_cmd_arg.style->verify (&arg_ptr, &the_cmd_arg);
  961.     if (error)
  962.       {
  963.         macro_func_arg = 0;
  964.         io_error_msg ("%s", error);
  965.       }
  966.     else
  967.       {
  968.         the_cmd_arg.is_set = 1;
  969.         if (arg_ptr)
  970.           while (isspace (*arg_ptr))
  971.         ++arg_ptr;
  972.         if (arg_ptr && *arg_ptr)
  973.           macro_func_arg = arg_ptr;
  974.         else
  975.           macro_func_arg = 0;
  976.         return 0;
  977.       }
  978.       }
  979.     }
  980.   input_active = 1;
  981.   begin_edit ();
  982.  
  983.   /* Functions can come with macros that initialize arguments for the user. 
  984.    * As for the call to expand_prompt -- hehehehehe
  985.    */
  986.   if (the_cmd_frame->cmd->init_code && the_cmd_frame->cmd->init_code[cur_arg])
  987.     {
  988.       char * init_code = expand_prompt(the_cmd_frame->cmd->init_code[cur_arg]);
  989.       struct rng rng;
  990.       rng.lr = rng.hr = rng.lc = rng.hc = 1;
  991.       macro_only_input_stream (&rng, init_code, strlen (init_code),
  992.                    the_cmd_frame);
  993.       command_loop (1);
  994.     }
  995.  
  996.   return 1;
  997. }
  998.  
  999. #ifdef __STDC__
  1000. void
  1001. exit_minibuffer (void)
  1002. #else
  1003. void
  1004. exit_minibuffer ()
  1005. #endif
  1006. {
  1007.   if (check_editting_mode ())
  1008.     return;
  1009.   else
  1010.     {
  1011.       char * extra = the_cmd_arg.text.buf;
  1012.       char * error = the_cmd_arg.style->verify (&extra, &the_cmd_arg);
  1013.       if (error)
  1014.     {
  1015.       if (*error)
  1016.         io_error_msg ("%s", error);
  1017.     }
  1018.       else
  1019.     {
  1020.       if (extra)
  1021.         {
  1022.           while (isspace (*extra))
  1023.         ++extra;
  1024.           if (*extra)
  1025.         io_error_msg ("%s: extra characters in argument (%s)",
  1026.                   the_cmd_frame->cmd->func_name, extra);
  1027.         }
  1028.       the_cmd_arg.is_set = 1;
  1029.       input_active = 0;
  1030.       window_after_input = -1;
  1031.       topclear = 2;
  1032.     }
  1033.     }
  1034. }
  1035.  
  1036.  
  1037.  
  1038.  
  1039. #ifdef __STDC__
  1040. void
  1041. setn_arg_text (struct command_arg * arg, char * text, int len)
  1042. #else
  1043. void
  1044. setn_arg_text (arg, text, len)
  1045.      struct command_arg * arg;
  1046.      char * text;
  1047.      int len;
  1048. #endif
  1049. {
  1050.   setn_line (&arg->text, text, len);
  1051.   arg->cursor = len;
  1052. }
  1053.  
  1054. #ifdef __STDC__
  1055. void
  1056. init_arg_text (struct command_arg * arg, char * text)
  1057. #else
  1058. void
  1059. init_arg_text (arg, text)
  1060.      struct command_arg * arg;
  1061.      char * text;
  1062. #endif
  1063. {
  1064.   setn_arg_text (arg, text, strlen (text));
  1065. }
  1066.  
  1067. /* This apparently useless alias is here because
  1068.  * sometime in the future i want to handle defaults
  1069.  * differently.  
  1070.  */
  1071.  
  1072. #ifdef __STDC__
  1073. void
  1074. set_default_arg (struct command_arg * arg, char * text, int len)
  1075. #else
  1076. void
  1077. set_default_arg (arg, text, len)
  1078.      struct command_arg * arg;
  1079.      char * text;
  1080.      int len;
  1081. #endif
  1082. {
  1083.   setn_arg_text (arg, text, len);
  1084. }
  1085.  
  1086. /* This is the main loop of oleo.   It reads commands and their arguments, and
  1087.  * evaluates them.  It (via real_get_chr) udpates the display and performs
  1088.  * background recomputation.
  1089.  *
  1090.  * This function can also be used to evaluate a function without doing any
  1091.  * interaction.  This is done by pushing a macro_only command frame
  1092.  *  (see execute_command).
  1093.  */
  1094.  
  1095. #ifdef __STDC__
  1096. void
  1097. command_loop (int prefix)
  1098. #else
  1099. void
  1100. command_loop (prefix)
  1101.      int prefix;
  1102. #endif
  1103. {
  1104.  
  1105.   /* We might be re-entering after a longjmp caused by an error.
  1106.    * In that case, we use an alternate entry point:
  1107.    */
  1108.   if (the_cmd_frame->cmd)
  1109.     goto resume_getting_arguments;
  1110.  
  1111.   /* Commands (notably execute_command) just tweek the command_frame
  1112.    * state for some other command.  To accomplish this, there is an 
  1113.    * entry point that avoid reinitializing the command_frame.\
  1114.    */
  1115.   if (prefix)
  1116.     {
  1117.       prefix = 0;
  1118.       goto prefix_cmd_continuation;
  1119.     }
  1120.   
  1121.   while (1)
  1122.     {
  1123.       int ch;            /* The next character to be keymapped. */
  1124.  
  1125.     new_cycle:
  1126.  
  1127.       if (!the_cmd_frame)
  1128.     push_command_frame (0, 0, 0);
  1129.  
  1130.       /* Reset the prefix argument. */
  1131.  
  1132.       how_many = 1;
  1133.       set_line (&raw_prefix, "");
  1134.       io_update_status ();
  1135.  
  1136.       /* Reset the keystate. */
  1137.       cur_keymap = the_cmd_frame->top_keymap;
  1138.  
  1139.       /* If the input area holds a prompt from the last command,
  1140.        * erase it. 
  1141.        */
  1142.       io_clear_input_before ();
  1143.  
  1144.  
  1145.       /* Some commands are prefix commands: they effect the 
  1146.        * user's state without beginnging a new command cyle.
  1147.        * Those commands return here:
  1148.        */
  1149.  
  1150.     prefix_cmd_continuation:
  1151.  
  1152.       /* In this loop, we look for the next command to
  1153.        * execute.  This may involve reading from a macro, 
  1154.        * or the keyboard.  If there is time to kill, updates
  1155.        * and evalutations are done.
  1156.        *
  1157.        * This loop is exited by `goto got_command'.
  1158.        */
  1159.  
  1160.       while (1)
  1161.     {
  1162.       /* Get the next character.
  1163.        * However, if we are in a macro, and the next character
  1164.        * is '{', then the macro contains a function name
  1165.        * and keymapping is circumvented. 
  1166.        */
  1167.  
  1168.     get_next_char:
  1169.  
  1170.       if (pushed_back_char >= 0)
  1171.         {
  1172.           ch = pushed_back_char;
  1173.           pushed_back_char = -1;
  1174.         }
  1175.       else if (!rmac)
  1176.         {
  1177.           io_fix_input ();
  1178.           ch = real_get_chr ();
  1179.         }
  1180.       else
  1181.         {
  1182.           int len;
  1183.           unsigned char *ptr;
  1184.           
  1185.         tryagain:
  1186.           alarm_hooks ();
  1187.           ch = *(rmac->mac_exe++);
  1188.           switch (ch)
  1189.         {
  1190.         case '\0':
  1191.           cur_vector = 0;
  1192.           cur_cmd = end_macro_cmd;
  1193.           cur_chr = 0;
  1194.           goto got_command;
  1195.           
  1196.         case 0x80 | 'a':
  1197.           ch = '\0';
  1198.           break;
  1199.           
  1200.         case 0x80 | 'b':
  1201.           ch = '{';
  1202.           break;
  1203.         case 0x80 | 'c':
  1204.           ch = '}';
  1205.           break;
  1206.           
  1207.         case '{':
  1208.           for (ptr = rmac->mac_exe;
  1209.                *ptr && *ptr != ' ' && *ptr != '}';
  1210.                ptr++);
  1211.           len = ptr - rmac->mac_exe;
  1212.           for (cur_vector = 0;
  1213.                cur_vector < num_funcs;
  1214.                cur_vector++)
  1215.             for (cur_cmd =
  1216.              &the_funcs[cur_vector][0];
  1217.              cur_cmd->func_name;
  1218.              cur_cmd++)
  1219.               if (!strincmp ((char *) (rmac->mac_exe),
  1220.                      cur_cmd->func_name, len)
  1221.               && cur_cmd->func_name[len] == '\0')
  1222.             {
  1223.               cur_chr = '\0';
  1224.               goto out;
  1225.             }
  1226.           io_error_msg ("Ignoring unknown function '%.*s' in macro",
  1227.                 len, rmac->mac_exe);
  1228.           while (*ptr != '\0' && *ptr != '}')
  1229.             ptr++;
  1230.           if (*ptr == '}')
  1231.             ptr++;
  1232.           rmac->mac_exe = ptr;
  1233.           goto tryagain;
  1234.           
  1235.         out:
  1236.           if (*ptr == ' ')
  1237.             {
  1238.               /* ... add argument support here ... */
  1239.               if (!cur_cmd->func_args)
  1240.             {
  1241.               io_error_msg ("Ignoring extra operand to %s",
  1242.                     cur_cmd->func_name);
  1243.               while (*ptr && *ptr != '}')
  1244.                 ptr++;
  1245.               if (*ptr == '}')
  1246.                 ptr++;
  1247.             }
  1248.               else if (cur_cmd->func_args[0][0] == '+')
  1249.             {
  1250.               unsigned char * start = ptr;
  1251.               how_many = astol ((char **) (&ptr));
  1252.               setn_line (&raw_prefix, (char *)start,
  1253.                      ptr - start);
  1254.               if (*ptr == '}')
  1255.                 ptr++;
  1256.             }
  1257.               else
  1258.             {
  1259.               while (isspace(*ptr))
  1260.                 ++ptr;
  1261.               macro_func_arg = (char *) ptr;
  1262.               while (*ptr && *ptr != '}')
  1263.                 {
  1264.                   switch (*ptr)
  1265.                 {
  1266.                 case 0x80 | 'b':
  1267.                   *ptr = '{';
  1268.                   break;
  1269.                 case 0x80 | 'c':
  1270.                   *ptr = '}';
  1271.                   break;
  1272.                 }
  1273.                   ptr++;
  1274.                 }
  1275.               if (*ptr == '}')
  1276.                 *ptr++ = '\0';
  1277.             }
  1278.               rmac->mac_exe = ptr;
  1279.             }
  1280.           else
  1281.             rmac->mac_exe += len + 1;
  1282.           goto got_command;
  1283.         }
  1284.         }
  1285.  
  1286.       /* When control comes here, adjust the keystate according 
  1287.        * to the cur_keymap and `ch';
  1288.        */
  1289.     have_character:
  1290.  
  1291.       /* This is how keymaps are searched for a binding. */ 
  1292.       while (1)
  1293.         {
  1294.           struct key * key;
  1295.           key = &(the_maps[cur_keymap]->keys[ch]);
  1296.           if (key->vector < 0)
  1297.         {
  1298.           if (key->code >= 0)
  1299.             {
  1300.               cur_keymap = key->code;
  1301.               goto get_next_char;
  1302.             }
  1303.           else if (the_maps[cur_keymap]->map_next)
  1304.             cur_keymap =
  1305.               the_maps[cur_keymap]->map_next->id;
  1306.           else
  1307.             {
  1308.               cur_vector = 0;
  1309.               cur_cmd = 0;
  1310.               cur_chr = ch;
  1311.               goto got_command;
  1312.             }
  1313.         }
  1314.           else
  1315.         {
  1316.           cur_vector = key->vector;
  1317.           cur_cmd =
  1318.             &(the_funcs[key->vector][key->code]);
  1319.           cur_chr = ch;
  1320.           goto got_command;
  1321.         }
  1322.         }
  1323.     }
  1324.  
  1325.  
  1326.       /* Now the next command to begin has been read from a macro
  1327.        * or the keyboard.
  1328.        */
  1329.     got_command:
  1330.  
  1331.       /* If there is anything left in the input area (e.g. old error message)
  1332.        * get rid of it (but only if we're not executing a macro).
  1333.        */
  1334.       if (!rmac)
  1335.     io_clear_input_after ();
  1336.  
  1337.       /* There are some commands that are implemented right here. */
  1338.       if (cur_cmd == break_cmd)
  1339.     {
  1340.       io_bell ();
  1341.       set_info (0);
  1342.       if (input_active)
  1343.         pop_unfinished_command ();      /* Abort a complex command.*/
  1344.       goto new_cycle;
  1345.     }
  1346.  
  1347.       /* The binding of all keys associated with the prefix arg. */
  1348.       if (cur_cmd == universal_arg_cmd)
  1349.       {
  1350.       char ch = cur_chr;
  1351.       int prefix_map = map_id ("prefix");
  1352.       /* Make sure the prefix-arg keymap is in place. */
  1353.       if (cur_keymap != prefix_map)
  1354.         {
  1355.           the_cmd_frame->saved_cur_keymap = the_cmd_frame->top_keymap;
  1356.           cur_keymap = prefix_map;
  1357.         }
  1358.       /* Store the last character typed in the raw-prefix.*/
  1359.       catn_line (&raw_prefix, &ch, 1);
  1360.       /* Recompute the numeric value of the prefix. */
  1361.       {
  1362.         int x = 0;
  1363.         int presumed_digits = 0;
  1364.         int sign = 1;
  1365.  
  1366.         how_many = 1;
  1367.         while (raw_prefix.buf[x])
  1368.           {
  1369.         if (isdigit (raw_prefix.buf[x]))
  1370.           {
  1371.             if (presumed_digits)
  1372.               how_many = how_many * 10 + (raw_prefix.buf[x] - '0');
  1373.             else
  1374.               {
  1375.             presumed_digits = 1;
  1376.             how_many = raw_prefix.buf[x] - '0';
  1377.               }
  1378.           }
  1379.         else if (raw_prefix.buf[x] == '-')
  1380.           sign *= -1;
  1381.         else
  1382.           {
  1383.             if (presumed_digits)
  1384.               {
  1385.             presumed_digits = 0;
  1386.             how_many = 1;
  1387.               }
  1388.             how_many *= 4;
  1389.           }
  1390.         ++x;
  1391.           }
  1392.         how_many *= sign;
  1393.         io_update_status ();
  1394.         goto prefix_cmd_continuation; 
  1395.       }
  1396.     }
  1397.  
  1398.       /* Make sure we really mapped to a command. */
  1399.       if (!cur_cmd || !cur_cmd->func_func)
  1400.     {
  1401.       /* If a character is unmapped in the prefix map,
  1402.        * retry mapping in the last-used normal keymap.
  1403.        */
  1404.       if (the_cmd_frame->saved_cur_keymap >= 0)
  1405.         {
  1406.           cur_keymap = the_cmd_frame->saved_cur_keymap;
  1407.           the_cmd_frame->saved_cur_keymap = -1;
  1408.           goto have_character;
  1409.         }
  1410.       /* Otherwise, signal an error and start from the top keymap. */
  1411.       io_bell ();
  1412.       goto new_cycle;
  1413.     }
  1414.       
  1415.  
  1416.  
  1417.       /* The next step is to gather the arguments with which to call
  1418.        * the function interactively.
  1419.        */
  1420.       /* Whever a new command is encountered, we begin by creating a 
  1421.        * frame in which to store it's arguments.
  1422.        * This initializes the new frame on the basis of cur_cmd in 
  1423.        * the_cmd_frame.  
  1424.        */
  1425.       push_command_frame (0, 0, 0);
  1426.  
  1427.       /* After some other command finishes from underneath a complex command,
  1428.        * flow returns here. 
  1429.        */
  1430.       
  1431.     resume_getting_arguments:
  1432.  
  1433.       while (cur_arg < cmd_argc)
  1434.     {
  1435.       if (the_cmd_arg.is_set)
  1436.         goto next_arg;
  1437.       else if (the_cmd_arg.prompt)
  1438.         {
  1439.           begin_edit ();
  1440.           goto new_cycle;
  1441.         }
  1442.       else
  1443.         {
  1444.           /* If we're just starting on this argument, then parse the
  1445.            * FUNC_ARGS string. To continue this loop, use `goto next_arg;'.
  1446.            *
  1447.            * If user interaction is required, the appropriate keymap,
  1448.            * editting area, etc. is set up, and the command loop resumes
  1449.            * (`goto new_cycle').
  1450.            */
  1451.           char * prompt = the_cmd_arg.arg_desc;
  1452.           
  1453.           switch (*prompt)
  1454.         {
  1455.         case 'c':
  1456.           {
  1457.             ++prompt;
  1458.             if (*prompt == '#')
  1459.               {
  1460.             ++prompt;
  1461.             the_cmd_arg.val.integer = *prompt;
  1462.             the_cmd_arg.is_set = 1;
  1463.             the_cmd_arg.do_prompt = 0;
  1464.             the_cmd_arg.style = &int_constant_style;
  1465.             {
  1466.               char c[2];
  1467.               c[0] = cur_chr;
  1468.               c[1] = '\0';
  1469.               init_arg_text (&the_cmd_arg, c);
  1470.             }
  1471.             goto next_arg;
  1472.               }
  1473.             else if (*prompt == '\'')
  1474.               {
  1475.             the_cmd_arg.timeout_seconds = 30;
  1476.             alarm_table[1].freq = 1;
  1477.             ++prompt;
  1478.               }
  1479.             if (get_argument (prompt, &char_style))
  1480.               goto new_cycle;
  1481.             goto next_arg;
  1482.           }
  1483.         case 'C':
  1484.           {
  1485.             ++prompt;
  1486.             if (get_argument (prompt, &command_style))
  1487.               goto new_cycle;
  1488.             goto next_arg;
  1489.           }
  1490.         case 'd':
  1491.           {
  1492.             ++prompt;
  1493.             if (get_argument (prompt, &double_style))
  1494.               goto new_cycle;
  1495.             goto next_arg;
  1496.           }
  1497.         case 'f':
  1498.           {
  1499.             char type;
  1500.             struct prompt_style * style;
  1501.             ++prompt;
  1502.             type = *prompt;
  1503.             ++prompt;
  1504.             switch (type)
  1505.               {
  1506.               case 'r':
  1507.             style = &read_file_style;
  1508.             break;
  1509.               case 'w':
  1510.             style = &write_file_style;
  1511.             break;
  1512.               case 'n':
  1513.             style = &file_name_style;
  1514.             break;
  1515.               default:
  1516.             style = 0; /* shutup gcc -ansi -pendantic -Wall! */
  1517.             io_error_msg ("func_args bug for %s",
  1518.                       the_cmd_frame->cmd->func_name);
  1519.               }
  1520.             if (get_argument (prompt, style))
  1521.               goto new_cycle;
  1522.             goto next_arg;
  1523.           }
  1524.         case 'F':
  1525.           {
  1526.             ++prompt;
  1527.             if (get_argument (prompt, &format_style))
  1528.               goto new_cycle;
  1529.             goto next_arg;
  1530.           }
  1531.         case 'k':
  1532.           {
  1533.             ++prompt;
  1534.             the_cmd_arg.val.key.cmd.vector = -1;
  1535.             the_cmd_arg.val.key.cmd.code
  1536.               = the_cmd_frame->prev->top_keymap;
  1537.             the_cmd_arg.val.key.keys = &the_cmd_arg.text;
  1538.             if (get_argument (prompt, &keyseq_style))
  1539.               goto new_cycle;
  1540.             goto next_arg;
  1541.           }
  1542.         case 'K':
  1543.           {
  1544.             ++prompt;
  1545.             if (get_argument (prompt, &keymap_style))
  1546.               goto new_cycle;
  1547.             goto next_arg;
  1548.           }
  1549.         case 'l':
  1550.           {
  1551.             the_cmd_arg.val.integer = cur_chr;
  1552.             the_cmd_arg.is_set = 1;
  1553.             the_cmd_arg.do_prompt = 0;
  1554.             the_cmd_arg.style = &int_constant_style;
  1555.             {
  1556.               char c[2];
  1557.               c[0] = cur_chr;
  1558.               c[1] = '\0';
  1559.               init_arg_text (&the_cmd_arg, c);
  1560.             }
  1561.             goto next_arg;
  1562.           }
  1563.         case 'm':
  1564.           {
  1565.             int want_keyseq = 0;
  1566.             ++prompt;
  1567.             want_keyseq = (*prompt == '\'');
  1568.             if (want_keyseq)
  1569.               {
  1570.             char * map;
  1571.             ++prompt;
  1572.             map = expand_prompt (prompt);
  1573.             the_cmd_arg.val.key.cmd.vector = -1;
  1574.             the_cmd_arg.val.key.cmd.code = map_id (map);
  1575.             the_cmd_arg.val.key.keys = &the_cmd_arg.text;
  1576.               }
  1577.             else
  1578.               {
  1579.             if (mode_style.keymap)
  1580.               ck_free (mode_style.keymap);
  1581.             mode_style.keymap = expand_prompt (prompt);
  1582.               }
  1583.             if (get_argument (prompt, (want_keyseq
  1584.                            ? &keyseq_style
  1585.                            : &mode_style)))
  1586.               goto new_cycle;
  1587.             goto next_arg;
  1588.           }
  1589.         case 'M':
  1590.           if (modified)
  1591.             {
  1592.               ++prompt;
  1593.               if (get_argument (prompt, &yes_style))
  1594.             goto new_cycle;
  1595.               goto next_arg;
  1596.             }
  1597.           else
  1598.             {
  1599.               the_cmd_arg.is_set = 1;
  1600.               the_cmd_arg.do_prompt = 1;
  1601.               the_cmd_arg.style = &yes_style;
  1602.               init_arg_text (&the_cmd_arg, "yes");
  1603.               goto next_arg;
  1604.             }
  1605.         case 'p':
  1606.           {
  1607.             ++prompt;
  1608.             switch (*prompt)
  1609.               {
  1610.               default:
  1611.             the_cmd_arg.val.integer
  1612.               = the_cmd_frame->prev->_how_many;
  1613.             the_cmd_arg.is_set = 1;
  1614.             the_cmd_arg.do_prompt = 0;
  1615.             the_cmd_arg.style = &int_constant_style;
  1616.             init_arg_text
  1617.               (&the_cmd_arg,
  1618.                long_to_str ((long)the_cmd_arg.val.integer)); 
  1619.             break;
  1620.  
  1621.               case '?':    /* Command wants to know if prefix provided */
  1622.             the_cmd_arg.val.integer =
  1623.               (the_cmd_frame->prev->_raw_prefix.alloc
  1624.                && the_cmd_frame->prev->_raw_prefix.buf[0]);
  1625.             the_cmd_arg.is_set = 1;
  1626.             the_cmd_arg.do_prompt = 0;
  1627.             the_cmd_arg.style = &int_constant_style;
  1628.             init_arg_text (&the_cmd_arg,
  1629.                        the_cmd_arg.val.integer ? "1" : "0");
  1630.             break;
  1631.               }
  1632.             goto next_arg;
  1633.           }
  1634.         case 'N':
  1635.         case 'n':
  1636.           {
  1637.             long low = 0;
  1638.             long high = -1;
  1639.             char type = *prompt;
  1640.             ++prompt;
  1641.             if (*prompt == '[')
  1642.               {
  1643.             ++prompt;
  1644.             low = astol (&prompt);
  1645.             while (isspace (*prompt))  ++prompt;
  1646.             if (*prompt == ',') ++prompt;
  1647.             high = astol (&prompt);
  1648.             while (isspace (*prompt))  ++prompt;
  1649.             if (*prompt == ']') ++prompt;
  1650.               }
  1651.             if (   (type == 'N')
  1652.             && the_cmd_frame->prev->_raw_prefix.alloc
  1653.             && the_cmd_frame->prev->_raw_prefix.buf[0])
  1654.               {
  1655.             the_cmd_arg.val.integer
  1656.               = the_cmd_frame->prev->_how_many;
  1657.             the_cmd_arg.is_set = 1;
  1658.             the_cmd_arg.do_prompt = 1;
  1659.             the_cmd_arg.style = &number_style;
  1660.             if (   (low >= high)
  1661.                 && (   (low > the_cmd_arg.val.integer)
  1662.                 || (high < the_cmd_arg.val.integer)))
  1663.               io_error_msg
  1664.                 ("Out of range %d (should be in [%d-%d]).");
  1665.             else
  1666.               init_arg_text
  1667.                 (&the_cmd_arg,
  1668.                  long_to_str ((long)the_cmd_arg.val.integer));
  1669.               }
  1670.             else
  1671.               {
  1672.             if (get_argument (prompt, &number_style))
  1673.               goto new_cycle;
  1674.               }
  1675.             goto next_arg;
  1676.           }
  1677.         case 'r':
  1678.         case 'R':
  1679.           {
  1680.             if (*prompt != 'R' && mkrow != NON_ROW)
  1681.               {
  1682.             the_cmd_arg.val.range.lr = MIN(mkrow, curow);
  1683.             the_cmd_arg.val.range.hr = MAX(mkrow, curow);
  1684.             the_cmd_arg.val.range.lc = MIN(mkcol, cucol);
  1685.             the_cmd_arg.val.range.hc = MAX(mkcol, cucol);
  1686.             the_cmd_arg.is_set = 1;
  1687.             the_cmd_arg.do_prompt = 1;
  1688.             the_cmd_arg.style = &range_style;
  1689.             mkrow = NON_ROW;
  1690.             mkcol = NON_COL;
  1691.             init_arg_text (&the_cmd_arg,
  1692.                        range_name (&the_cmd_arg.val.range)); 
  1693.             goto next_arg;
  1694.               }
  1695.             else
  1696.               {
  1697.             ++prompt;
  1698.             if (get_argument (prompt, &range_style))
  1699.               goto new_cycle;
  1700.             goto next_arg;
  1701.               }
  1702.           }
  1703.         case 's':
  1704.           {
  1705.             {
  1706.               ++prompt;
  1707.               if (get_argument (prompt, &string_style))
  1708.             goto new_cycle;
  1709.               goto next_arg;
  1710.             }
  1711.           }
  1712.         case 'S':
  1713.           {
  1714.             {
  1715.               ++prompt;
  1716.               if (*prompt == '\'')
  1717.             ++prompt;
  1718.               if (get_argument (prompt, &symbol_style))
  1719.             goto new_cycle;
  1720.               goto next_arg;
  1721.             }
  1722.           }
  1723.         case 'V':
  1724.           {
  1725.             ++prompt;
  1726.             the_cmd_arg.inc_cmd = io_shift_cell_cursor;
  1727.             if (get_argument (prompt, &inc_cmd_style))
  1728.               goto new_cycle;
  1729.             goto next_arg;
  1730.           }
  1731.         case 'w':
  1732.           {
  1733.             {
  1734.               ++prompt;
  1735.               if (*prompt == '\'')
  1736.             ++prompt;
  1737.               if (get_argument (prompt, &word_style))
  1738.             goto new_cycle;
  1739.               goto next_arg;
  1740.             }
  1741.           }
  1742.         case '#':
  1743.           {
  1744.             ++prompt;
  1745.             
  1746.             init_arg_text (&the_cmd_arg, prompt);
  1747.             the_cmd_arg.val.integer = astol(&prompt);
  1748.             the_cmd_arg.is_set = 1;
  1749.             the_cmd_arg.do_prompt = 0;
  1750.             the_cmd_arg.style = &int_constant_style;
  1751.             goto next_arg;
  1752.           }
  1753.         case '=':
  1754.           {
  1755.             ++prompt;
  1756.             the_cmd_arg.expanded_prompt = expand_prompt(prompt);
  1757.             init_arg_text (&the_cmd_arg, the_cmd_arg.expanded_prompt);
  1758.             the_cmd_arg.val.string = the_cmd_arg.expanded_prompt;
  1759.             the_cmd_arg.is_set = 1;
  1760.             the_cmd_arg.do_prompt = 0;
  1761.             the_cmd_arg.style = &string_style;
  1762.             goto next_arg;
  1763.           }
  1764.         case '.':
  1765.           {
  1766.             ++prompt;
  1767.             the_cmd_arg.val.range.lr = curow;
  1768.             the_cmd_arg.val.range.lc = cucol;
  1769.             if (*prompt == '\'')
  1770.               {
  1771.             the_cmd_arg.val.range.hr = curow;
  1772.             the_cmd_arg.val.range.hc = cucol;
  1773.               }
  1774.             else
  1775.               {
  1776.             the_cmd_arg.val.range.hr = mkrow;
  1777.             the_cmd_arg.val.range.hc = mkcol;
  1778.               }
  1779.             the_cmd_arg.is_set = 1;
  1780.             the_cmd_arg.do_prompt = 0;
  1781.             init_arg_text (&the_cmd_arg,
  1782.                    range_name (&the_cmd_arg.val.range));
  1783.             the_cmd_arg.style = &range_constant_style;
  1784.             goto next_arg;
  1785.           }
  1786.         case '[':
  1787.           {
  1788.             ++prompt;
  1789.             while (*prompt && (*prompt != ']'))
  1790.               if (*prompt != '\\')
  1791.             ++prompt;
  1792.               else
  1793.             {
  1794.               ++prompt;
  1795.               if (*prompt)
  1796.                 ++prompt;
  1797.             }
  1798.             if (*prompt == ']')
  1799.               ++prompt;
  1800.             
  1801.             if (get_argument (prompt, &menu_style))
  1802.               goto new_cycle;
  1803.             goto next_arg;
  1804.           }
  1805.         case '$':
  1806.           {
  1807.             /* Edit a cell's formula. */
  1808.             CELL * cp = find_cell (curow, cucol);
  1809.             ++prompt;
  1810.             if (((!cp || GET_LCK (cp) == LCK_DEF)
  1811.              && (default_lock == LCK_LCK))
  1812.             || (cp && GET_LCK (cp) == LCK_LCK))
  1813.               {
  1814.             io_error_msg ("Cell %s is locked",
  1815.                       cell_name (curow, cucol));
  1816.             pop_unfinished_command ();
  1817.             goto new_cycle;
  1818.               }
  1819.             the_cmd_frame->prev->_setrow = curow;
  1820.             the_cmd_frame->prev->_setcol = cucol;
  1821.             if (get_argument (prompt, &formula_style))
  1822.               {
  1823.             init_arg_text (&the_cmd_arg,
  1824.                        decomp (curow, cucol, cp));
  1825.             decomp_free ();
  1826.             goto new_cycle;
  1827.               }
  1828.             goto next_arg;
  1829.           }
  1830.           
  1831.         default:
  1832.           {
  1833.             io_error_msg ("Interaction-string error!!!");
  1834.             pop_unfinished_command ();
  1835.             goto new_cycle;
  1836.           }
  1837.         }
  1838.         }
  1839.     next_arg:
  1840.       ++cur_arg;
  1841.     }
  1842.  
  1843.       /* Make sure that all the args are really there. */
  1844.       for (cur_arg = 0; cur_arg < cmd_argc; ++cur_arg)
  1845.     if (the_cmd_arg.do_prompt && !the_cmd_arg.is_set)
  1846.       goto resume_getting_arguments;
  1847.  
  1848.       /* If this point is reached, call the interactive function,
  1849.        * destroy it's frame, and restart the cycle.
  1850.        */
  1851.       {
  1852.     int move_cursor = 0;
  1853.     struct command_frame * frame = the_cmd_frame;
  1854.     cmd_invoker stub = find_stub ();
  1855.     if (   frame->_curow != frame->prev->_curow
  1856.         || frame->_cucol != frame->prev->_cucol)
  1857.       {
  1858.         move_cursor = 1;
  1859.         io_hide_cell_cursor ();
  1860.       }
  1861.     remove_cmd_frame (frame);
  1862.     /* Add frame to the list of frames to be freed on error. */
  1863.     frame->next = running_frames;
  1864.     running_frames = frame;
  1865.     if (move_cursor)
  1866.       io_display_cell_cursor ();
  1867.     if (!stub)
  1868.       io_error_msg ("Don't know how to invoke %s!!!",
  1869.             frame->cmd->func_name);
  1870.     else
  1871.       stub (frame);
  1872.     running_frames = running_frames->next;
  1873.     frame->next = 0;
  1874.     free_cmd_frame (frame);
  1875.  
  1876.     /* If command_loop was called by execute_command, it should
  1877.      * return as soon as there is no more macro to evaluate.
  1878.       */
  1879.     if (!rmac && the_cmd_frame->input->prev_stream)
  1880.       {
  1881.         pop_input_stream ();
  1882.         return;
  1883.       }
  1884.     if (the_cmd_frame->cmd)
  1885.       goto resume_getting_arguments;
  1886.       }
  1887.     }
  1888. }
  1889.  
  1890. /* Exectute the command called in `string'.
  1891.  * If the string begins with a proper command name,
  1892.  * it is executed as if it were embedded in "{}" in 
  1893.  * a macro.  Otherwise, if the string can be interpreted 
  1894.  * as a range address, the macro at that address is executed.
  1895.  */
  1896.  
  1897. static struct line exec_cmd_line = {0, 0};
  1898.  
  1899. #ifdef __STDC__
  1900. void
  1901. execute_as_macro (char * str)
  1902. #else
  1903. void
  1904. execute_as_macro (str)
  1905.      char * str;
  1906. #endif
  1907. {
  1908.   struct rng fake_rng;
  1909.   fake_rng.lr = fake_rng.lc = fake_rng.hr = fake_rng.hc = 1;
  1910.   macro_only_input_stream (&fake_rng, str, strlen (str), the_cmd_frame);
  1911.   command_loop (1);
  1912. }
  1913.  
  1914.  
  1915. /* execute_command buils a macro expression of the from `{command args}'.
  1916.  * This function quotes the braces in ARGS so that the macro reader knows
  1917.  * they are literal rather than macro syntax.
  1918.  */
  1919. static void
  1920. quote_macro_args (args)
  1921.      char * args;
  1922. {
  1923.   while (*args)
  1924.     {
  1925.       switch (*args)
  1926.     {
  1927.     case '{':
  1928.       *args = 0x80 | 'b';
  1929.       break;
  1930.     case '}':
  1931.       *args = 0x80 | 'c';
  1932.       break;
  1933.     }
  1934.       ++args;
  1935.     }
  1936. }
  1937.  
  1938. #ifdef __STDC__
  1939. void 
  1940. execute_command (char *str, int count)
  1941. #else
  1942. void 
  1943. execute_command (str, count)
  1944.      char *str;
  1945.      int count;
  1946. #endif
  1947. {
  1948.   char *ptr = str;
  1949.   char * run;            /* The first string to execute. */
  1950.   /* The address of the macro to execute.  If the user typed a 
  1951.    * command name and not a range name, then this range will be
  1952.    * set to a one cell region.
  1953.    */
  1954.   struct rng rng;
  1955.  
  1956.   /* Chop off the first word. */
  1957.   while (isspace (*str))
  1958.     ++str;
  1959.   if (!*str || *str == '#')
  1960.     return;
  1961.   for (ptr = str; *ptr && *ptr != ' '; ptr++);
  1962.   
  1963.   if (*ptr)
  1964.     *ptr++ = '\0';
  1965.   else
  1966.     ptr = 0;
  1967.   
  1968.  
  1969.   /* First, look for a command name. */
  1970.   
  1971.   {
  1972.     int vector;
  1973.     struct cmd_func * cmd;
  1974.  
  1975.     if (!find_function (&vector, &cmd, str, strlen(str)))
  1976.       {
  1977.     if (ptr)
  1978.       {
  1979.         quote_macro_args (ptr);
  1980.         sprint_line (&exec_cmd_line, "{%s %s}", str, ptr);
  1981.       }
  1982.     else
  1983.       sprint_line (&exec_cmd_line, "{%s}", str);
  1984.     run = exec_cmd_line.buf;
  1985.     rng.lr = rng.hr = 1;
  1986.     rng.lc = rng.hc = 1;
  1987.     goto found_command;
  1988.       }
  1989.   }
  1990.   
  1991.   {
  1992.     /* Try for a range address. */
  1993.     CELL *cp;
  1994.     if (get_abs_rng (&str, &rng))
  1995.       {
  1996.     io_error_msg ("Unknown command %s", str);
  1997.     return;
  1998.       }
  1999.     if (ptr)
  2000.       {
  2001.     io_error_msg ("Macros can't take arguments");
  2002.     return;
  2003.       }
  2004.  
  2005.     cp = find_cell (rng.lr, rng.lc);
  2006.     if (!cp
  2007.     || GET_TYP (cp) != TYP_STR
  2008.     || cp->cell_str[0] == '\0')
  2009.       {
  2010.     io_error_msg ("No macro found at %s.", range_name (&rng));
  2011.     return;
  2012.       }
  2013.  
  2014.     run = cp->cell_str;
  2015.     count = how_many;
  2016.     how_many = 1;
  2017.     set_line (&raw_prefix, "");
  2018.   }
  2019.  
  2020.  found_command:
  2021.   while (count --)
  2022.     {
  2023.       macro_only_input_stream (&rng, run, strlen (run), the_cmd_frame);
  2024.       command_loop (1);
  2025.     }
  2026. }
  2027.  
  2028.  
  2029.  
  2030.  
  2031. /* Read a character.  If we're in a macro, read from the macro. . . */
  2032. #ifdef __STDC__
  2033. int
  2034. get_chr (void)
  2035. #else
  2036. int
  2037. get_chr ()
  2038. #endif
  2039. {
  2040.   int ch;
  2041.  
  2042.   if (rmac)
  2043.     {
  2044.       ch = *(rmac->mac_exe++);
  2045.       switch (ch)
  2046.     {
  2047.     case '{':        /* What else can we do? */
  2048.     case '\0':
  2049.       --rmac->mac_exe;
  2050.       break;
  2051.  
  2052.     case (0x80 | 'a'):
  2053.       ch = 0;
  2054.       break;
  2055.  
  2056.     case (0x80 | 'b'):
  2057.       ch = '{';
  2058.       break;
  2059.     default:
  2060.       break;
  2061.     }
  2062.     }
  2063.   else
  2064.     ch = real_get_chr ();
  2065.   return ch;
  2066. }
  2067.  
  2068.  
  2069. /* This is an entirely magical function.  All of it's work is done 
  2070.  * by the argument prompting system.  All that remains to be done
  2071.  * when this is called is to push back a character the user may have
  2072.  * typed to cause the error message to go away.
  2073.  */
  2074.  
  2075. #ifdef __STDC__
  2076. void
  2077. display_error_msg (char * msg, int c)
  2078. #else
  2079. void
  2080. display_error_msg (msg, c)
  2081.      char * msg;
  2082.      int c;
  2083. #endif
  2084. {
  2085.   if (c > 0)
  2086.     pushed_back_char = c;
  2087. }
  2088.  
  2089. #ifdef __STDC__
  2090. void
  2091. io_error_msg (char *str,...)
  2092. #else
  2093. void
  2094. io_error_msg (str, va_alist)
  2095.      char *str;
  2096.      va_dcl
  2097. #endif
  2098. {
  2099.   va_list foo;
  2100.   char buf[1000];
  2101.   char buf2[1000];
  2102.  
  2103.   /* This is made robust against errors that occur before
  2104.    * the io hooks have been initialized.
  2105.    */
  2106.   if (display_opened)
  2107.     io_bell ();
  2108.   
  2109.   var_start (foo, str);
  2110.   vsprintf (buf, str, foo);
  2111.   sprintf (buf2, "display-error-msg %s", buf);
  2112.   recover_from_error ();
  2113.   if (display_opened)
  2114.     execute_command (buf2, 1);
  2115.   else
  2116.     fprintf (stderr, "oleo: %s\n", buf);
  2117.   longjmp (error_exception, 1);
  2118. }
  2119.  
  2120.  
  2121. #ifdef __STDC__
  2122. void
  2123. io_info_msg (char *str,...)
  2124. #else
  2125. void
  2126. io_info_msg (str, va_alist)
  2127.      char *str;
  2128.      va_dcl
  2129. #endif
  2130. {
  2131.   va_list foo;
  2132.   char buf[1000];
  2133.   char buf2[1000];
  2134.  
  2135.   var_start (foo, str);
  2136.   vsprintf (buf, str, foo);
  2137.   sprintf (buf2, "display-error-msg %s", buf);
  2138.   execute_command (buf2, 1);
  2139. }
  2140.  
  2141.  
  2142.  
  2143.  
  2144. /* Expands a string that will be used to prompt for an argument.
  2145.  *    %n expands to the text of argument n (if defined -- ??? otherwise).
  2146.  *    %% expands to %
  2147.  *    %c expands to the name of the_cmd_frame->prev->_set{row,col}
  2148.  * If no expansion is needed, the argument is returned.  Otherwise,
  2149.  * malloced memory is returned.
  2150.  */
  2151.  
  2152. #ifdef __STDC__
  2153. char *
  2154. expand_prompt (char * str)
  2155. #else
  2156. char *
  2157. expand_prompt (str)
  2158.      char * str;
  2159. #endif
  2160. {
  2161.   struct line expanded;
  2162.   init_line (&expanded);
  2163.   if (!str || !index (str, '%'))
  2164.     return ck_savestr (str);
  2165.   {
  2166.     char * last_pos = str;
  2167.     char * src_pos;
  2168.  
  2169.     for (src_pos = index (str, '%'); src_pos; src_pos = index (src_pos, '%'))
  2170.       {
  2171.     catn_line (&expanded, last_pos, src_pos - last_pos);
  2172.     ++src_pos;
  2173.     switch (*src_pos)
  2174.       {
  2175.       case '%':
  2176.         catn_line (&expanded, src_pos, 1);
  2177.         ++src_pos;
  2178.         break;
  2179.       case 'c':
  2180.         {
  2181.           struct rng rng;
  2182.           char * str;
  2183.           rng.lr = rng.hr = the_cmd_frame->prev->_setrow;
  2184.           rng.lc = rng.hc = the_cmd_frame->prev->_setcol;
  2185.           str = range_name (&rng);
  2186.           catn_line (&expanded, str, strlen(str));
  2187.           ++src_pos;
  2188.           break;
  2189.         }
  2190.       case '.':
  2191.         {
  2192.           struct rng rng;
  2193.           char * str;
  2194.           rng.lr = rng.hr = the_cmd_frame->prev->_curow;
  2195.           rng.lc = rng.hc = the_cmd_frame->prev->_cucol;
  2196.           str = range_name (&rng);
  2197.           catn_line (&expanded, str, strlen(str));
  2198.           ++src_pos;
  2199.           break;
  2200.         }
  2201.       case '0': case '1': case '2': case '3': case '4':
  2202.       case '5': case '6': case '7': case '8': case '9':
  2203.         {
  2204.           int argn = *src_pos - '0';
  2205.           if (   (cmd_argc > argn)
  2206.           && the_cmd_frame->argv[argn].is_set
  2207.           && the_cmd_frame->argv[argn].text.buf)
  2208.         catn_line (&expanded, the_cmd_frame->argv[argn].text.buf,
  2209.                strlen (the_cmd_frame->argv[argn].text.buf));
  2210.           else
  2211.         catn_line (&expanded, "????", 4);
  2212.           ++src_pos;
  2213.           break;
  2214.         }
  2215.       default:
  2216.         catn_line (&expanded, "%", 1);
  2217.         break;
  2218.       }
  2219.     last_pos = src_pos;
  2220.       }
  2221.     catn_line (&expanded, last_pos, strlen(last_pos));
  2222.   }
  2223.   return expanded.buf;
  2224. }
  2225.  
  2226.  
  2227.  
  2228.  
  2229. /* Info commands */
  2230.  
  2231. #ifdef __STDC__
  2232. void
  2233. set_info (char * name)
  2234. #else
  2235. void
  2236. set_info (name)
  2237.      char * name;
  2238. #endif
  2239. {
  2240.   struct info_buffer * ib = (name ? find_or_make_info (name) : 0);
  2241.   
  2242.   if (the_cmd_frame->cmd && (the_cmd_arg.prompt_info != ib))
  2243.     {
  2244.       the_cmd_arg.info_line = 0;
  2245.       the_cmd_arg.prompt_info = ib;
  2246.     }
  2247.   if (!ib && name && *name)
  2248.     io_error_msg ("No information about %s.", name);
  2249. }
  2250.  
  2251.  
  2252. #ifdef __STDC__
  2253. void
  2254. page_info_backwards (int rep)
  2255. #else
  2256. void
  2257. page_info_backwards (rep)
  2258.      int rep;
  2259. #endif
  2260. {
  2261.   if (rep < 0)
  2262.     page_info (-rep);
  2263.   else if (the_cmd_frame->cmd && the_cmd_arg.prompt_info)
  2264.     {
  2265.       int vis_lines = (scr_lines - input_rows) / info_rows;
  2266.       int next = the_cmd_arg.info_line - vis_lines * rep;
  2267.       the_cmd_arg.info_line = ((next >= 0) ? next : 0);
  2268.     }
  2269.   else
  2270.     io_error_msg ("No info to page.");
  2271. }
  2272.  
  2273. #undef MAX
  2274. #define MAX(A,B) (((A) >= (B)) ? (A) : (B))
  2275.  
  2276. #ifdef __STDC__
  2277. void
  2278. page_info (int rep)
  2279. #else
  2280. void
  2281. page_info (rep)
  2282.      int rep;
  2283. #endif
  2284. {
  2285.   if (rep < 0)
  2286.     page_info_backwards (-rep);
  2287.   else if (the_cmd_frame->cmd && the_cmd_arg.prompt_info)
  2288.     {
  2289.       int vis_lines = (scr_lines - input_rows) / info_rows;
  2290.       int next = the_cmd_arg.info_line + vis_lines * rep;
  2291.       the_cmd_arg.info_line =
  2292.     ((next >= the_cmd_arg.prompt_info->len)
  2293.      ? MAX(0, (the_cmd_arg.prompt_info->len - vis_lines))
  2294.      : next);
  2295.     }
  2296.   else
  2297.     io_error_msg ("No info to page.");
  2298. }
  2299.  
  2300. #ifdef __STDC__
  2301. void
  2302. view_info (char * name, int ignore)
  2303. #else
  2304. void
  2305. view_info (name, ignore)
  2306.      char * name;
  2307.      int ignore;
  2308. #endif
  2309. {}
  2310.  
  2311.  
  2312.  
  2313. /* The C part of this function is uninteresting.  The interesting part
  2314.  * is in defun.h.
  2315.  */
  2316.  
  2317. #ifdef __STDC__
  2318. void
  2319. with_keymap (char * mapname)
  2320. #else
  2321. void
  2322. with_keymap (mapname)
  2323.      char * mapname;
  2324. #endif
  2325. {}
  2326.  
  2327. #ifdef __STDC__
  2328. void
  2329. one_cmd_with_keymap (char * mapname, struct key_sequence * keyseq)
  2330. #else
  2331. void
  2332. one_cmd_with_keymap (mapname, keyseq)
  2333.      char * mapname;
  2334.      struct key_sequence * keyseq;
  2335. #endif
  2336. {
  2337.   if (keyseq->cmd.vector < 0 && keyseq->cmd.code < 0)
  2338.     io_bell ();
  2339.   else if (keyseq->cmd.vector < 0)
  2340.     io_error_msg
  2341.       ("one-command-with-keymap: %s maps to a keymap (%s), not a command.",
  2342.        keyseq->keys->buf, map_names[keyseq->cmd.code]);
  2343.   else
  2344.     execute_command
  2345.       (the_funcs[keyseq->cmd.vector][keyseq->cmd.code].func_name, 1);
  2346. }
  2347.