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