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 (¯o_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 (¯o_stack, cp->cell_str, 1 + strlen (cp->cell_str));
230 rmac->mac_start = rmac->mac_exe =
231 (unsigned char *) obstack_finish (¯o_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 (¯o_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 (¯o_stack, rmac);
298 rmac = old;
299 }
300 else
301 {
302 obstack_grow (¯o_stack, cp->cell_str, 1 + strlen (cp->cell_str));
303 rmac->mac_exe
304 = (unsigned char *) obstack_finish (¯o_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