1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23: #include <config.h>
24:
25: #include "lisp.h"
26: #include "buffer.h"
27: #include "commands.h"
28: #include "keyboard.h"
29: #include "window.h"
30: #include "keymap.h"
31:
32: #ifdef HAVE_INDEX
33: extern char *index P_ ((const char *, int));
34: #endif
35:
36: extern Lisp_Object Qcursor_in_echo_area;
37: extern Lisp_Object Qfile_directory_p;
38:
39: Lisp_Object Vcurrent_prefix_arg, Qminus, Qplus;
40: Lisp_Object Qcall_interactively;
41: Lisp_Object Vcommand_history;
42:
43: extern Lisp_Object Vhistory_length;
44: extern Lisp_Object Vthis_original_command, real_this_command;
45:
46: Lisp_Object Vcommand_debug_status, Qcommand_debug_status;
47: Lisp_Object Qenable_recursive_minibuffers;
48:
49:
50:
51: Lisp_Object Vmark_even_if_inactive;
52:
53: Lisp_Object Vmouse_leave_buffer_hook, Qmouse_leave_buffer_hook;
54:
55: Lisp_Object Qlist, Qlet, Qletx, Qsave_excursion, Qprogn, Qif, Qwhen;
56: static Lisp_Object preserved_fns;
57:
58:
59: static Lisp_Object point_marker;
60:
61:
62: static Lisp_Object callint_message;
63: ^L
64:
65: DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0,
66: doc:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125: )
126: (args)
127: Lisp_Object args;
128: {
129: return Qnil;
130: }
131:
132:
133:
134: Lisp_Object
135: quotify_arg (exp)
136: register Lisp_Object exp;
137: {
138: if (!INTEGERP (exp) && !STRINGP (exp)
139: && !NILP (exp) && !EQ (exp, Qt))
140: return Fcons (Qquote, Fcons (exp, Qnil));
141:
142: return exp;
143: }
144:
145:
146: Lisp_Object
147: quotify_args (exp)
148: Lisp_Object exp;
149: {
150: register Lisp_Object tail;
151: Lisp_Object next;
152: for (tail = exp; CONSP (tail); tail = next)
153: {
154: next = XCDR (tail);
155: XSETCAR (tail, quotify_arg (XCAR (tail)));
156: }
157: return exp;
158: }
159:
160: char *callint_argfuns[]
161: = {"", "point", "mark", "region-beginning", "region-end"};
162:
163: static void
164: check_mark (for_region)
165: int for_region;
166: {
167: Lisp_Object tem;
168: tem = Fmarker_buffer (current_buffer->mark);
169: if (NILP (tem) || (XBUFFER (tem) != current_buffer))
170: error (for_region ? "The mark is not set now, so there is no region"
171: : "The mark is not set now");
172: if (!NILP (Vtransient_mark_mode) && NILP (Vmark_even_if_inactive)
173: && NILP (current_buffer->mark_active))
174: xsignal0 (Qmark_inactive);
175: }
176:
177:
178:
179:
180:
181:
182:
183:
184:
185: static void
186: fix_command (input, values)
187: Lisp_Object input, values;
188: {
189: if (CONSP (input))
190: {
191: Lisp_Object car;
192:
193: car = XCAR (input);
194:
195: while (EQ (car, Qlet) || EQ (car, Qletx)
196: || EQ (car, Qsave_excursion)
197: || EQ (car, Qprogn))
198: {
199: while (CONSP (XCDR (input)))
200: input = XCDR (input);
201: input = XCAR (input);
202: if (!CONSP (input))
203: break;
204: car = XCAR (input);
205: }
206: if (EQ (car, Qlist))
207: {
208: Lisp_Object intail, valtail;
209: for (intail = Fcdr (input), valtail = values;
210: CONSP (valtail);
211: intail = Fcdr (intail), valtail = XCDR (valtail))
212: {
213: Lisp_Object elt;
214: elt = Fcar (intail);
215: if (CONSP (elt))
216: {
217: Lisp_Object presflag, carelt;
218: carelt = Fcar (elt);
219:
220: if (EQ (carelt, Qif)
221: && EQ (Fnthcdr (make_number (3), elt), Qnil))
222: elt = Fnth (make_number (2), elt);
223:
224: else if (EQ (carelt, Qwhen))
225: {
226: while (CONSP (XCDR (elt)))
227: elt = XCDR (elt);
228: elt = Fcar (elt);
229: }
230:
231:
232:
233:
234: if (CONSP (elt))
235: {
236: presflag = Fmemq (Fcar (elt), preserved_fns);
237: if (!NILP (presflag))
238: Fsetcar (valtail, Fcar (intail));
239: }
240: }
241: }
242: }
243: }
244: }
245:
246: DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 3, 0,
247: doc:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261: )
262: (function, record_flag, keys)
263: Lisp_Object function, record_flag, keys;
264: {
265: Lisp_Object *args, *visargs;
266: Lisp_Object fun;
267: Lisp_Object specs;
268: Lisp_Object filter_specs;
269: Lisp_Object teml;
270: Lisp_Object up_event;
271: Lisp_Object enable;
272: int speccount = SPECPDL_INDEX ();
273:
274:
275:
276: int next_event;
277:
278: Lisp_Object prefix_arg;
279: unsigned char *string;
280: unsigned char *tem;
281:
282:
283:
284:
285: int *varies;
286:
287: register int i, j;
288: int count, foo;
289: char prompt1[100];
290: char *tem1;
291: int arg_from_tty = 0;
292: struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
293: int key_count;
294: int record_then_fail = 0;
295:
296: Lisp_Object save_this_command, save_last_command;
297: Lisp_Object save_this_original_command, save_real_this_command;
298:
299: save_this_command = Vthis_command;
300: save_this_original_command = Vthis_original_command;
301: save_real_this_command = real_this_command;
302: save_last_command = current_kboard->Vlast_command;
303:
304: if (NILP (keys))
305: keys = this_command_keys, key_count = this_command_key_count;
306: else
307: {
308: CHECK_VECTOR (keys);
309: key_count = XVECTOR (keys)->size;
310: }
311:
312:
313: prefix_arg = Vcurrent_prefix_arg;
314:
315: if (SYMBOLP (function))
316: enable = Fget (function, Qenable_recursive_minibuffers);
317: else
318: enable = Qnil;
319:
320: fun = indirect_function (function);
321:
322: specs = Qnil;
323: string = 0;
324:
325:
326:
327: filter_specs = Qnil;
328:
329:
330: up_event = Qnil;
331:
332:
333:
334:
335: if (SUBRP (fun))
336: {
337: string = (unsigned char *) XSUBR (fun)->prompt;
338: if (!string)
339: {
340: lose:
341: wrong_type_argument (Qcommandp, function);
342: }
343: }
344: else if (COMPILEDP (fun))
345: {
346: if ((XVECTOR (fun)->size & PSEUDOVECTOR_SIZE_MASK) <= COMPILED_INTERACTIVE)
347: goto lose;
348: specs = XVECTOR (fun)->contents[COMPILED_INTERACTIVE];
349: }
350: else
351: {
352: Lisp_Object form;
353: GCPRO2 (function, prefix_arg);
354: form = Finteractive_form (function);
355: UNGCPRO;
356: if (CONSP (form))
357: specs = filter_specs = Fcar (XCDR (form));
358: else
359: goto lose;
360: }
361:
362:
363: if (STRINGP (specs))
364: {
365:
366:
367: string = (unsigned char *) alloca (SBYTES (specs) + 1);
368: bcopy (SDATA (specs), string,
369: SBYTES (specs) + 1);
370: }
371: else if (string == 0)
372: {
373: Lisp_Object input;
374: i = num_input_events;
375: input = specs;
376:
377: GCPRO2 (input, filter_specs);
378: specs = Feval (specs);
379: UNGCPRO;
380: if (i != num_input_events || !NILP (record_flag))
381: {
382:
383: Lisp_Object values;
384:
385:
386: values = quotify_args (Fcopy_sequence (specs));
387: fix_command (input, values);
388: Vcommand_history
389: = Fcons (Fcons (function, values), Vcommand_history);
390:
391:
392: if (INTEGERP (Vhistory_length) && XINT (Vhistory_length) > 0)
393: {
394: teml = Fnthcdr (Vhistory_length, Vcommand_history);
395: if (CONSP (teml))
396: XSETCDR (teml, Qnil);
397: }
398: }
399:
400: Vthis_command = save_this_command;
401: Vthis_original_command = save_this_original_command;
402: real_this_command= save_real_this_command;
403: current_kboard->Vlast_command = save_last_command;
404:
405: single_kboard_state ();
406: return apply1 (function, specs);
407: }
408:
409:
410:
411:
412: for (next_event = 0; next_event < key_count; next_event++)
413: if (EVENT_HAS_PARAMETERS (XVECTOR (keys)->contents[next_event]))
414: break;
415:
416:
417:
418: while (1)
419: {
420: if (*string == '+')
421: error ("`+' is not used in `interactive' for ordinary commands");
422: else if (*string == '*')
423: {
424: string++;
425: if (!NILP (current_buffer->read_only))
426: {
427: if (!NILP (record_flag))
428: {
429: unsigned char *p = string;
430: while (*p)
431: {
432: if (! (*p == 'r' || *p == 'p' || *p == 'P'
433: || *p == '\n'))
434: Fbarf_if_buffer_read_only ();
435: p++;
436: }
437: record_then_fail = 1;
438: }
439: else
440: Fbarf_if_buffer_read_only ();
441: }
442: }
443:
444: else if (*string == '-')
445: string++;
446: else if (*string == '@')
447: {
448: Lisp_Object event, tem;
449:
450: event = (next_event < key_count
451: ? XVECTOR (keys)->contents[next_event]
452: : Qnil);
453: if (EVENT_HAS_PARAMETERS (event)
454: && (tem = XCDR (event), CONSP (tem))
455: && (tem = XCAR (tem), CONSP (tem))
456: && (tem = XCAR (tem), WINDOWP (tem)))
457: {
458: if (MINI_WINDOW_P (XWINDOW (tem))
459: && ! (minibuf_level > 0 && EQ (tem, minibuf_window)))
460: error ("Attempt to select inactive minibuffer window");
461:
462:
463: if (!NILP (Vmouse_leave_buffer_hook))
464: call1 (Vrun_hooks, Qmouse_leave_buffer_hook);
465:
466: Fselect_window (tem, Qnil);
467: }
468: string++;
469: }
470: else break;
471: }
472:
473:
474:
475: tem = string;
476: for (j = 0; *tem; j++)
477: {
478:
479:
480: if (*tem == 'r') j++;
481: tem = (unsigned char *) index (tem, '\n');
482: if (tem)
483: tem++;
484: else
485: tem = (unsigned char *) "";
486: }
487: count = j;
488:
489: args = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
490: visargs = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object));
491: varies = (int *) alloca ((count + 1) * sizeof (int));
492:
493: for (i = 0; i < (count + 1); i++)
494: {
495: args[i] = Qnil;
496: visargs[i] = Qnil;
497: varies[i] = 0;
498: }
499:
500: GCPRO5 (prefix_arg, function, *args, *visargs, up_event);
501: gcpro3.nvars = (count + 1);
502: gcpro4.nvars = (count + 1);
503:
504: if (!NILP (enable))
505: specbind (Qenable_recursive_minibuffers, Qt);
506:
507: tem = string;
508: for (i = 1; *tem; i++)
509: {
510: strncpy (prompt1, tem + 1, sizeof prompt1 - 1);
511: prompt1[sizeof prompt1 - 1] = 0;
512: tem1 = (char *) index (prompt1, '\n');
513: if (tem1) *tem1 = 0;
514:
515: visargs[0] = build_string (prompt1);
516: if (index (prompt1, '%'))
517: callint_message = Fformat (i, visargs);
518: else
519: callint_message = visargs[0];
520:
521: switch (*tem)
522: {
523: case 'a':
524: visargs[i] = Fcompleting_read (callint_message,
525: Vobarray, Qfboundp, Qt,
526: Qnil, Qnil, Qnil, Qnil);
527:
528: teml = visargs[i];
529: args[i] = Fintern (teml, Qnil);
530: break;
531:
532: case 'b':
533: args[i] = Fcurrent_buffer ();
534: if (EQ (selected_window, minibuf_window))
535: args[i] = Fother_buffer (args[i], Qnil, Qnil);
536: args[i] = Fread_buffer (callint_message, args[i], Qt);
537: break;
538:
539: case 'B':
540: args[i] = Fread_buffer (callint_message,
541: Fother_buffer (Fcurrent_buffer (), Qnil, Qnil),
542: Qnil);
543: break;
544:
545: case 'c':
546: args[i] = Fread_char (callint_message, Qnil, Qnil);
547: message1_nolog ((char *) 0);
548:
549: teml = args[i];
550: visargs[i] = Fchar_to_string (teml);
551: break;
552:
553: case 'C':
554: visargs[i] = Fcompleting_read (callint_message,
555: Vobarray, Qcommandp,
556: Qt, Qnil, Qnil, Qnil, Qnil);
557:
558: teml = visargs[i];
559: args[i] = Fintern (teml, Qnil);
560: break;
561:
562: case 'd':
563: set_marker_both (point_marker, Qnil, PT, PT_BYTE);
564: args[i] = point_marker;
565:
566: varies[i] = 1;
567: break;
568:
569: case 'D':
570: args[i] = Fread_file_name (callint_message, Qnil,
571: current_buffer->directory, Qlambda, Qnil,
572: Qfile_directory_p);
573: break;
574:
575: case 'f':
576: args[i] = Fread_file_name (callint_message,
577: Qnil, Qnil, Qlambda, Qnil, Qnil);
578: break;
579:
580: case 'F':
581: args[i] = Fread_file_name (callint_message,
582: Qnil, Qnil, Qnil, Qnil, Qnil);
583: break;
584:
585: case 'G':
586:
587: args[i] = Fread_file_name (callint_message,
588: Qnil, Qnil, Qnil, build_string (""), Qnil);
589: break;
590:
591: case 'i':
592: varies[i] = -1;