This source file includes following definitions.
- DEFUN
- quotify_arg
- quotify_args
- check_mark
- fix_command
- read_file_name
- DEFUN
- syms_of_callint
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <config.h>
22
23 #include "lisp.h"
24 #include "character.h"
25 #include "buffer.h"
26 #include "keyboard.h"
27 #include "window.h"
28
29 static Lisp_Object preserved_fns;
30
31
32 static Lisp_Object point_marker;
33
34
35 static Lisp_Object callint_message;
36
37 DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0,
38 doc:
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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 attributes: const)
118 (Lisp_Object args)
119 {
120 return Qnil;
121 }
122
123
124
125 static Lisp_Object
126 quotify_arg (register Lisp_Object exp)
127 {
128 if (CONSP (exp)
129 || (SYMBOLP (exp)
130 && !NILP (exp) && !EQ (exp, Qt)))
131 return list2 (Qquote, exp);
132
133 return exp;
134 }
135
136
137 static Lisp_Object
138 quotify_args (Lisp_Object exp)
139 {
140 register Lisp_Object tail;
141 Lisp_Object next;
142 for (tail = exp; CONSP (tail); tail = next)
143 {
144 next = XCDR (tail);
145 XSETCAR (tail, quotify_arg (XCAR (tail)));
146 }
147 return exp;
148 }
149
150 static const char *callint_argfuns[]
151 = {"", "point", "mark", "region-beginning", "region-end"};
152
153 static void
154 check_mark (bool for_region)
155 {
156 Lisp_Object tem;
157 tem = Fmarker_buffer (BVAR (current_buffer, mark));
158 if (NILP (tem) || (XBUFFER (tem) != current_buffer))
159 error (for_region ? "The mark is not set now, so there is no region"
160 : "The mark is not set now");
161 if (!NILP (Vtransient_mark_mode) && NILP (Vmark_even_if_inactive)
162 && NILP (BVAR (current_buffer, mark_active)))
163 xsignal0 (Qmark_inactive);
164 }
165
166
167
168
169
170
171
172 static void
173 fix_command (Lisp_Object function, Lisp_Object values)
174 {
175
176 if (!CONSP (values) || !SYMBOLP (function))
177 return;
178
179 Lisp_Object reps = Fget (function, Qinteractive_args);
180
181 if (CONSP (reps))
182 {
183 int i = 0;
184 Lisp_Object vals = values;
185
186 while (!NILP (vals))
187 {
188 Lisp_Object rep = Fassq (make_fixnum (i), reps);
189 if (!NILP (rep))
190 Fsetcar (vals, XCDR (rep));
191 vals = XCDR (vals);
192 ++i;
193 }
194 }
195
196
197
198
199
200 Lisp_Object arity = Ffunc_arity (function);
201
202
203
204 if (FIXNUMP (XCAR (arity)) && FIXNUMP (XCDR (arity)))
205 {
206 Lisp_Object final = Qnil;
207 ptrdiff_t final_i = 0, i = 0;
208 for (Lisp_Object tail = values;
209 CONSP (tail);
210 tail = XCDR (tail), ++i)
211 {
212 if (!NILP (XCAR (tail)))
213 {
214 final = tail;
215 final_i = i;
216 }
217 }
218
219
220 if (final_i > 0 && final_i >= XFIXNUM (XCAR (arity)) - 1)
221 XSETCDR (final, Qnil);
222 }
223 }
224
225
226
227 static Lisp_Object
228 read_file_name (Lisp_Object default_filename, Lisp_Object mustmatch,
229 Lisp_Object initial, Lisp_Object predicate)
230 {
231 return CALLN (Ffuncall, intern ("read-file-name"),
232 callint_message, Qnil, default_filename,
233 mustmatch, initial, predicate);
234 }
235
236
237 DEFUN ("funcall-interactively", Ffuncall_interactively, Sfuncall_interactively,
238 1, MANY, 0, doc:
239
240
241 )
242 (ptrdiff_t nargs, Lisp_Object *args)
243 {
244 specpdl_ref speccount = SPECPDL_INDEX ();
245 temporarily_switch_to_single_kboard (NULL);
246
247
248
249
250 return unbind_to (speccount, Ffuncall (nargs, args));
251 }
252
253 DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 3, 0,
254 doc:
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269 )
270 (Lisp_Object function, Lisp_Object record_flag, Lisp_Object keys)
271 {
272 specpdl_ref speccount = SPECPDL_INDEX ();
273
274 bool arg_from_tty = false;
275 ptrdiff_t key_count;
276 bool record_then_fail = false;
277
278 Lisp_Object save_this_command = Vthis_command;
279 Lisp_Object save_this_original_command = Vthis_original_command;
280 Lisp_Object save_real_this_command = Vreal_this_command;
281 Lisp_Object save_last_command = KVAR (current_kboard, Vlast_command);
282
283
284
285
286 specbind (Qcurrent_minibuffer_command, Vthis_command);
287
288 if (NILP (keys))
289 keys = this_command_keys, key_count = this_command_key_count;
290 else
291 {
292 CHECK_VECTOR (keys);
293 key_count = ASIZE (keys);
294 }
295
296
297 Lisp_Object prefix_arg = Vcurrent_prefix_arg;
298
299 Lisp_Object enable = (SYMBOLP (function)
300 ? Fget (function, Qenable_recursive_minibuffers)
301 : Qnil);
302
303
304
305 Lisp_Object up_event = Qnil;
306
307
308 Lisp_Object form = call1 (Qinteractive_form, function);
309 if (! CONSP (form))
310 wrong_type_argument (Qcommandp, function);
311 Lisp_Object specs = Fcar (XCDR (form));
312
313
314
315
316
317
318 if (! STRINGP (specs))
319 {
320 Lisp_Object funval = Findirect_function (function, Qt);
321 uintmax_t events = num_input_events;
322
323 specs = Feval (specs,
324 CONSP (funval) && EQ (Qclosure, XCAR (funval))
325 ? CAR_SAFE (XCDR (funval)) : Qnil);
326 if (events != num_input_events || !NILP (record_flag))
327 {
328
329
330
331 Lisp_Object values = quotify_args (Fcopy_sequence (specs));
332 fix_command (function, values);
333 call4 (intern ("add-to-history"), intern ("command-history"),
334 Fcons (function, values), Qnil, Qt);
335 }
336
337 Vthis_command = save_this_command;
338 Vthis_original_command = save_this_original_command;
339 Vreal_this_command = save_real_this_command;
340 kset_last_command (current_kboard, save_last_command);
341
342 return unbind_to (speccount, CALLN (Fapply, Qfuncall_interactively,
343 function, specs));
344 }
345
346
347
348 USE_SAFE_ALLOCA;
349 ptrdiff_t string_len = SBYTES (specs);
350 char *string = SAFE_ALLOCA (string_len + 1);
351 memcpy (string, SDATA (specs), string_len + 1);
352 char *string_end = string + string_len;
353
354
355
356
357
358
359 ptrdiff_t next_event = 0;
360 if (!inhibit_mouse_event_check)
361 for (; next_event < key_count; next_event++)
362 if (EVENT_HAS_PARAMETERS (AREF (keys, next_event)))
363 break;
364
365
366
367 for (;; string++)
368 {
369 if (*string == '+')
370 error ("`+' is not used in `interactive' for ordinary commands");
371 else if (*string == '*')
372 {
373 if (!NILP (BVAR (current_buffer, read_only)))
374 {
375 if (!NILP (record_flag))
376 {
377 for (char *p = string + 1; p < string_end; p++)
378 if (! (*p == 'r' || *p == 'p' || *p == 'P' || *p == '\n'))
379 Fbarf_if_buffer_read_only (Qnil);
380 record_then_fail = true;
381 }
382 else
383 Fbarf_if_buffer_read_only (Qnil);
384 }
385 }
386
387 else if (*string == '-')
388 ;
389 else if (*string == '@')
390 {
391 Lisp_Object w, event = (next_event < key_count
392 ? AREF (keys, next_event)
393 : Qnil);
394 if (EVENT_HAS_PARAMETERS (event)
395 && (w = XCDR (event), CONSP (w))
396 && (w = XCAR (w), CONSP (w))
397 && (w = XCAR (w), WINDOWP (w)))
398 {
399 if (MINI_WINDOW_P (XWINDOW (w))
400 && ! (minibuf_level > 0 && BASE_EQ (w, minibuf_window)))
401 error ("Attempt to select inactive minibuffer window");
402
403
404 run_hook (Qmouse_leave_buffer_hook);
405
406 Fselect_window (w, Qnil);
407 }
408 }
409 else if (*string == '^')
410 call0 (Qhandle_shift_selection);
411 else break;
412 }
413
414
415
416
417 ptrdiff_t nargs = 2;
418 for (char const *tem = string; tem < string_end; tem++)
419 {
420
421
422 nargs += 1 + (*tem == 'r');
423 tem = memchr (tem, '\n', string_len - (tem - string));
424 if (!tem)
425 break;
426 }
427
428 if (MOST_POSITIVE_FIXNUM < min (PTRDIFF_MAX, SIZE_MAX) / word_size
429 && MOST_POSITIVE_FIXNUM < nargs)
430 memory_full (SIZE_MAX);
431
432
433
434
435
436
437 Lisp_Object *args;
438 SAFE_NALLOCA (args, 3, nargs);
439 Lisp_Object *visargs = args + nargs;
440
441
442
443 signed char *varies = (signed char *) (visargs + nargs);
444
445 memclear (args, nargs * (2 * word_size + 1));
446
447 if (!NILP (enable))
448 specbind (Qenable_recursive_minibuffers, Qt);
449
450 char const *tem = string;
451 for (ptrdiff_t i = 2; tem < string_end; i++)
452 {
453 char *pnl = memchr (tem + 1, '\n', string_len - (tem + 1 - string));
454 ptrdiff_t sz = pnl ? pnl - (tem + 1) : string_end - (tem + 1);
455
456 visargs[1] = make_string (tem + 1, sz);
457 callint_message = Fformat_message (i - 1, visargs + 1);
458
459 switch (*tem)
460 {
461 case 'a':
462 visargs[i] = Fcompleting_read (callint_message,
463 Vobarray, Qfboundp, Qt,
464 Qnil, Qnil, Qnil, Qnil);
465 args[i] = Fintern (visargs[i], Qnil);
466 break;
467
468 case 'b':
469 args[i] = Fcurrent_buffer ();
470 if (BASE_EQ (selected_window, minibuf_window))
471 args[i] = Fother_buffer (args[i], Qnil, Qnil);
472 args[i] = Fread_buffer (callint_message, args[i], Qt, Qnil);
473 break;
474
475 case 'B':
476 args[i] = Fread_buffer (callint_message,
477 Fother_buffer (Fcurrent_buffer (),
478 Qnil, Qnil),
479 Qnil, Qnil);
480 break;
481
482 case 'c':
483
484 Fput_text_property (make_fixnum (0),
485 make_fixnum (SCHARS (callint_message)),
486 Qface, Qminibuffer_prompt, callint_message);
487 args[i] = Fread_char (callint_message, Qnil, Qnil);
488 message1_nolog (0);
489
490 if (! CHARACTERP (args[i]))
491 error ("Non-character input-event");
492 visargs[i] = Fchar_to_string (args[i]);
493 break;
494
495 case 'C':
496 visargs[i] = Fcompleting_read (callint_message,
497 Vobarray, Qcommandp,
498 Qt, Qnil, Qnil, Qnil, Qnil);
499 args[i] = Fintern (visargs[i], Qnil);
500 break;
501
502 case 'd':
503 set_marker_both (point_marker, Qnil, PT, PT_BYTE);
504 args[i] = point_marker;
505
506 varies[i] = 1;
507 break;
508
509 case 'D':
510 args[i] = read_file_name (BVAR (current_buffer, directory), Qlambda,
511 Qnil, Qfile_directory_p);
512 break;
513
514 case 'f':
515 args[i] = read_file_name (Qnil, Qlambda, Qnil, Qnil);
516 break;
517
518 case 'F':
519 args[i] = read_file_name (Qnil, Qnil, Qnil, Qnil);
520 break;
521
522 case 'G':
523
524 args[i] = read_file_name (Qnil, Qnil, empty_unibyte_string, Qnil);
525 break;
526
527 case 'i':
528 varies[i] = -1;
529 break;
530
531 case 'k':
532 {
533 specpdl_ref speccount1 = SPECPDL_INDEX ();
534 specbind (Qcursor_in_echo_area, Qt);
535
536 Fput_text_property (make_fixnum (0),
537 make_fixnum (SCHARS (callint_message)),
538 Qface, Qminibuffer_prompt, callint_message);
539 args[i] = Fread_key_sequence (callint_message,
540 Qnil, Qnil, Qnil, Qnil);
541 unbind_to (speccount1, Qnil);
542 visargs[i] = Fkey_description (args[i], Qnil);
543
544
545
546 Lisp_Object teml
547 = Faref (args[i], make_fixnum (XFIXNUM (Flength (args[i])) - 1));
548 if (CONSP (teml))
549 teml = XCAR (teml);
550 if (SYMBOLP (teml))
551 {
552 teml = Fget (teml, Qevent_symbol_elements);
553
554 Lisp_Object tem2 = Fmemq (Qdown, Fcdr (teml));
555 if (! NILP (tem2))
556 up_event = Fread_event (Qnil, Qnil, Qnil);
557 }
558 }
559 break;
560
561 case 'K':
562 {
563 specpdl_ref speccount1 = SPECPDL_INDEX ();
564 specbind (Qcursor_in_echo_area, Qt);
565
566 Fput_text_property (make_fixnum (0),
567 make_fixnum (SCHARS (callint_message)),
568 Qface, Qminibuffer_prompt, callint_message);
569 args[i] = Fread_key_sequence_vector (callint_message,
570 Qnil, Qt, Qnil, Qnil);
571 visargs[i] = Fkey_description (args[i], Qnil);
572 unbind_to (speccount1, Qnil);
573
574
575
576 Lisp_Object teml
577 = Faref (args[i], make_fixnum (ASIZE (args[i]) - 1));
578 if (CONSP (teml))
579 teml = XCAR (teml);
580 if (SYMBOLP (teml))
581 {
582 teml = Fget (teml, Qevent_symbol_elements);
583
584 Lisp_Object tem2 = Fmemq (Qdown, Fcdr (teml));
585 if (! NILP (tem2))
586 up_event = Fread_event (Qnil, Qnil, Qnil);
587 }
588 }
589 break;
590
591 case 'U':
592 if (!NILP (up_event))
593 {
594 args[i] = make_vector (1, up_event);
595 up_event = Qnil;
596 visargs[i] = Fkey_description (args[i], Qnil);
597 }
598 break;
599
600 case 'e':
601 if (next_event >= key_count)
602 error ("%s must be bound to an event with parameters",
603 (SYMBOLP (function)
604 ? SSDATA (SYMBOL_NAME (function))
605 : "command"));
606 args[i] = AREF (keys, next_event);
607 varies[i] = -1;
608
609
610 if (inhibit_mouse_event_check)
611 next_event++;
612 else
613
614 do
615 next_event++;
616 while (next_event < key_count
617 && ! EVENT_HAS_PARAMETERS (AREF (keys, next_event)));
618
619 break;
620
621 case 'm':
622 check_mark (false);
623
624 args[i] = BVAR (current_buffer, mark);
625 varies[i] = 2;
626 break;
627
628 case 'M':
629
630 args[i] = Fread_string (callint_message,
631 Qnil, Qnil, Qnil, Qt);
632 break;
633
634 case 'N':
635 if (!NILP (prefix_arg))
636 goto have_prefix_arg;
637 FALLTHROUGH;
638 case 'n':
639 args[i] = call1 (Qread_number, callint_message);
640 visargs[i] = Fnumber_to_string (args[i]);
641 break;
642
643 case 'P':
644 args[i] = prefix_arg;
645
646 varies[i] = -1;
647 break;
648
649 case 'p':
650 have_prefix_arg:
651 args[i] = Fprefix_numeric_value (prefix_arg);
652
653 varies[i] = -1;
654 break;
655
656 case 'r':
657 {
658 check_mark (true);
659 set_marker_both (point_marker, Qnil, PT, PT_BYTE);
660 ptrdiff_t mark = marker_position (BVAR (current_buffer, mark));
661
662 args[i] = PT < mark ? point_marker : BVAR (current_buffer, mark);
663 varies[i] = 3;
664 args[++i] = PT > mark ? point_marker : BVAR (current_buffer, mark);
665 varies[i] = 4;
666 }
667 break;
668
669 case 's':
670
671 args[i] = Fread_string (callint_message,
672 Qnil, Qnil, Qnil, Qnil);
673 break;
674
675 case 'S':
676 visargs[i] = Fread_string (callint_message,
677 Qnil, Qnil, Qnil, Qnil);
678 args[i] = Fintern (visargs[i], Qnil);
679 break;
680
681 case 'v':
682
683 args[i] = Fread_variable (callint_message, Qnil);
684 visargs[i] = last_minibuf_string;
685 break;
686
687 case 'x':
688 args[i] = call1 (intern ("read-minibuffer"), callint_message);
689 visargs[i] = last_minibuf_string;
690 break;
691
692 case 'X':
693 args[i] = call1 (intern ("eval-minibuffer"), callint_message);
694 visargs[i] = last_minibuf_string;
695 break;
696
697 case 'Z':
698
699 if (NILP (prefix_arg))
700 {
701
702 varies[i] = -1;
703 }
704 else
705 {
706 args[i]
707 = Fread_non_nil_coding_system (callint_message);
708 visargs[i] = last_minibuf_string;
709 }
710 break;
711
712 case 'z':
713 args[i] = Fread_coding_system (callint_message, Qnil);
714 visargs[i] = last_minibuf_string;
715 break;
716
717
718
719 case '+':
720 default:
721 {
722
723
724 ptrdiff_t bytes_left = string_len - (tem - string);
725 unsigned letter;
726
727
728
729
730 if (bytes_left >= BYTES_BY_CHAR_HEAD (*((unsigned char *) tem)))
731 letter = STRING_CHAR ((unsigned char *) tem);
732 else
733 letter = *((unsigned char *) tem);
734
735 error (("Invalid control letter `%c' (#o%03o, #x%04x)"
736 " in interactive calling string"),
737 (int) letter, letter, letter);
738 }
739 }
740
741 if (varies[i] == 0)
742 arg_from_tty = true;
743
744 if (NILP (visargs[i]) && STRINGP (args[i]))
745 visargs[i] = args[i];
746
747 tem = memchr (tem, '\n', string_len - (tem - string));
748 if (tem) tem++;
749 else tem = string_end;
750 }
751 unbind_to (speccount, Qnil);
752
753 maybe_quit ();
754
755 args[0] = Qfuncall_interactively;
756 args[1] = function;
757
758 if (arg_from_tty || !NILP (record_flag))
759 {
760
761
762 visargs[1] = function;
763 for (ptrdiff_t i = 2; i < nargs; i++)
764 visargs[i] = (varies[i] > 0
765 ? list1 (intern (callint_argfuns[varies[i]]))
766 : quotify_arg (args[i]));
767 call4 (intern ("add-to-history"), intern ("command-history"),
768 Flist (nargs - 1, visargs + 1), Qnil, Qt);
769 }
770
771
772
773 for (ptrdiff_t i = 2; i < nargs; i++)
774 if (varies[i] >= 1 && varies[i] <= 4)
775 XSETINT (args[i], marker_position (args[i]));
776
777 if (record_then_fail)
778 Fbarf_if_buffer_read_only (Qnil);
779
780 Vthis_command = save_this_command;
781 Vthis_original_command = save_this_original_command;
782 Vreal_this_command = save_real_this_command;
783 kset_last_command (current_kboard, save_last_command);
784
785 specbind (Qcommand_debug_status, Qnil);
786
787 Lisp_Object val = Ffuncall (nargs, args);
788 return SAFE_FREE_UNBIND_TO (speccount, val);
789 }
790
791 DEFUN ("prefix-numeric-value", Fprefix_numeric_value, Sprefix_numeric_value,
792 1, 1, 0,
793 doc:
794
795 )
796 (Lisp_Object raw)
797 {
798 Lisp_Object val;
799
800 if (NILP (raw))
801 XSETFASTINT (val, 1);
802 else if (EQ (raw, Qminus))
803 XSETINT (val, -1);
804 else if (CONSP (raw) && FIXNUMP (XCAR (raw)))
805 val = XCAR (raw);
806 else if (FIXNUMP (raw))
807 val = raw;
808 else
809 XSETFASTINT (val, 1);
810
811 return val;
812 }
813
814 void
815 syms_of_callint (void)
816 {
817 point_marker = Fmake_marker ();
818 staticpro (&point_marker);
819
820 callint_message = Qnil;
821 staticpro (&callint_message);
822
823 preserved_fns = pure_list (intern_c_string ("region-beginning"),
824 intern_c_string ("region-end"),
825 intern_c_string ("point"),
826 intern_c_string ("mark"));
827 staticpro (&preserved_fns);
828
829 DEFSYM (Qlist, "list");
830 DEFSYM (Qlet, "let");
831 DEFSYM (Qif, "if");
832 DEFSYM (Qwhen, "when");
833 DEFSYM (Qletx, "let*");
834 DEFSYM (Qsave_excursion, "save-excursion");
835 DEFSYM (Qprogn, "progn");
836 DEFSYM (Qminus, "-");
837 DEFSYM (Qplus, "+");
838 DEFSYM (Qhandle_shift_selection, "handle-shift-selection");
839 DEFSYM (Qread_number, "read-number");
840 DEFSYM (Qfuncall_interactively, "funcall-interactively");
841 DEFSYM (Qcommand_debug_status, "command-debug-status");
842 DEFSYM (Qenable_recursive_minibuffers, "enable-recursive-minibuffers");
843 DEFSYM (Qmouse_leave_buffer_hook, "mouse-leave-buffer-hook");
844
845 DEFVAR_KBOARD ("prefix-arg", Vprefix_arg,
846 doc:
847
848
849
850
851
852
853
854 );
855
856 DEFVAR_KBOARD ("last-prefix-arg", Vlast_prefix_arg,
857 doc:
858 );
859
860 DEFVAR_LISP ("current-prefix-arg", Vcurrent_prefix_arg,
861 doc:
862
863
864
865 );
866 Vcurrent_prefix_arg = Qnil;
867
868 DEFVAR_LISP ("command-history", Vcommand_history,
869 doc:
870
871
872
873 );
874 Vcommand_history = Qnil;
875
876 DEFVAR_LISP ("command-debug-status", Vcommand_debug_status,
877 doc:
878
879 );
880 Vcommand_debug_status = Qnil;
881
882 DEFVAR_LISP ("mark-even-if-inactive", Vmark_even_if_inactive,
883 doc:
884
885
886
887 );
888 Vmark_even_if_inactive = Qt;
889
890 DEFVAR_LISP ("mouse-leave-buffer-hook", Vmouse_leave_buffer_hook,
891 doc:
892
893
894
895
896 );
897 Vmouse_leave_buffer_hook = Qnil;
898
899 DEFVAR_BOOL ("inhibit-mouse-event-check", inhibit_mouse_event_check,
900 doc:
901
902
903
904 );
905 inhibit_mouse_event_check = false;
906
907 defsubr (&Sinteractive);
908 defsubr (&Scall_interactively);
909 defsubr (&Sfuncall_interactively);
910 defsubr (&Sprefix_numeric_value);
911
912 DEFSYM (Qinteractive_args, "interactive-args");
913 }