Mercurial > hg > xemacs-beta
diff src/callint.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/callint.c Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,1008 @@ +/* Call a Lisp function interactively. + Copyright (C) 1985, 1986, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1995, 1996 Ben Wing. + +This file is part of XEmacs. + +XEmacs is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +XEmacs is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with XEmacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Synched up with: FSF 19.30, Mule 2.0. */ + +/* Authorship: + + FSF: long ago. + Mly or JWZ: various changes. + */ + +#include <config.h> +#include "lisp.h" + +#include "buffer.h" +#include "bytecode.h" +#include "commands.h" +#include "events.h" +#include "insdel.h" +#include "window.h" + +extern int num_input_chars; + +Lisp_Object Vcurrent_prefix_arg; +Lisp_Object Qcall_interactively; +Lisp_Object Vcommand_history; + +Lisp_Object Vcommand_debug_status, Qcommand_debug_status; +Lisp_Object Qenable_recursive_minibuffers; + +#if 0 /* FSFmacs */ +/* Non-nil means treat the mark as active + even if mark_active is 0. */ +Lisp_Object Vmark_even_if_inactive; +#endif + +#if 0 /* ill-conceived */ +Lisp_Object Vmouse_leave_buffer_hook, Qmouse_leave_buffer_hook; +#endif + +Lisp_Object Qlet, QletX, Qsave_excursion; + +Lisp_Object Qcurrent_prefix_arg; + +Lisp_Object Quser_variable_p; +Lisp_Object Qread_from_minibuffer; +Lisp_Object Qread_file_name; +Lisp_Object Qread_directory_name; +Lisp_Object Qcompleting_read; +Lisp_Object Qread_buffer; +Lisp_Object Qread_function; +Lisp_Object Qread_variable; +Lisp_Object Qread_expression; +Lisp_Object Qread_command; +Lisp_Object Qread_number; +Lisp_Object Qread_string; +Lisp_Object Qevents_to_keys; + +/* ARGSUSED */ +DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0 /* +Specify a way of parsing arguments for interactive use of a function. +For example, write + (defun foo (arg) \"Doc string\" (interactive \"p\") ...use arg...) +to make ARG be the prefix argument when `foo' is called as a command. +The \"call\" to `interactive' is actually a declaration rather than a function; + it tells `call-interactively' how to read arguments + to pass to the function. +When actually called, `interactive' just returns nil. + +The argument of `interactive' is usually a string containing a code letter + followed by a prompt. (Some code letters do not use I/O to get + the argument and do not need prompts.) To prompt for multiple arguments, + give a code letter, its prompt, a newline, and another code letter, etc. + Prompts are passed to format, and may use % escapes to print the + arguments that have already been read. +If the argument is not a string, it is evaluated to get a list of + arguments to pass to the function. +Just `(interactive)' means pass no args when calling interactively. + +Code letters available are: +a -- Function name: symbol with a function definition. +b -- Name of existing buffer. +B -- Name of buffer, possibly nonexistent. +c -- Character. +C -- Command name: symbol with interactive function definition. +d -- Value of point as number. Does not do I/O. +D -- Directory name. +e -- Last mouse-button or misc-user event that invoked this command. + If used more than once, the Nth `e' returns the Nth such event. + Does not do I/O. +f -- Existing file name. +F -- Possibly nonexistent file name. +k -- Key sequence (a vector of events). +K -- Key sequence to be redefined (do not automatically down-case). +m -- Value of mark as number. Does not do I/O. +n -- Number read using minibuffer. +N -- Prefix arg converted to number, or if none, do like code `n'. +p -- Prefix arg converted to number. Does not do I/O. +P -- Prefix arg in raw form. Does not do I/O. +r -- Region: point and mark as 2 numeric args, smallest first. Does no I/O. +s -- Any string. +S -- Any symbol. +v -- Variable name: symbol that is user-variable-p. +x -- Lisp expression read but not evaluated. +X -- Lisp expression read and evaluated. +In addition, if the string begins with `*' + then an error is signaled if the buffer is read-only. + This happens before reading any arguments. +If the string begins with `@', then the window the mouse is over is selected + before anything else is done. +If the string begins with `_', then this command will not cause the region + to be deactivated when it completes; that is, `zmacs-region-stays' will be + set to t when the command exits successfully. +You may use any of `@', `*' and `_' at the beginning of the string; + they are processed in the order that they appear. +*/ ) + (args) + Lisp_Object args; +{ + return Qnil; +} + +/* Quotify EXP: if EXP is constant, return it. + If EXP is not constant, return (quote EXP). */ +static Lisp_Object +quotify_arg (Lisp_Object exp) +{ + if (!INTP (exp) && !CHARP (exp) && !STRINGP (exp) + && !NILP (exp) && !EQ (exp, Qt)) + return Fcons (Qquote, Fcons (exp, Qnil)); + + return exp; +} + +/* Modify EXP by quotifying each element (except the first). */ +static Lisp_Object +quotify_args (Lisp_Object exp) +{ + REGISTER Lisp_Object tail; + REGISTER struct Lisp_Cons *ptr; + for (tail = exp; CONSP (tail); tail = ptr->cdr) + { + ptr = XCONS (tail); + ptr->car = quotify_arg (ptr->car); + } + return exp; +} + +static Bufpos +check_mark (void) +{ + Lisp_Object tem; + + if (zmacs_regions && !zmacs_region_active_p) + error ("The region is not active now"); + + tem = Fmarker_buffer (current_buffer->mark); + if (NILP (tem) || (XBUFFER (tem) != current_buffer)) + error ("The mark is not set now"); + + return (marker_position (current_buffer->mark)); +} + +static Lisp_Object +callint_prompt (CONST Bufbyte *prompt_start, Bytecount prompt_length, + CONST Lisp_Object *args, int nargs) +{ + Lisp_Object s = make_string (prompt_start, prompt_length); + struct gcpro gcpro1; + + /* Fformat no longer smashes its arg vector, so no need to copy it. */ + + if (!strchr ((char *) string_data (XSTRING (s)), '%')) + return (s); + GCPRO1 (s); + RETURN_UNGCPRO (emacs_doprnt_string_lisp (0, s, 0, nargs, args)); +} + +/* `lambda' for RECORD-FLAG is an XEmacs addition. */ + +DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, + 1, 3, 0 /* +Call FUNCTION, reading args according to its interactive calling specs. +Return the value FUNCTION returns. +The function contains a specification of how to do the argument reading. +In the case of user-defined functions, this is specified by placing a call +to the function `interactive' at the top level of the function body. +See `interactive'. + +If optional second arg RECORD-FLAG is the symbol `lambda', the interactive +calling arguments for FUNCTION are read and returned as a list, +but the function is not called on them. + +If RECORD-FLAG is `t' then unconditionally put this command in the +command-history. Otherwise, this is done only if an arg is read using +the minibuffer. + +The argument KEYS specifies the value to use instead of (this-command-keys) +when reading the arguments. +*/ ) + (function, record_flag, keys) + Lisp_Object function, record_flag, keys; +{ + /* This function can GC */ + int speccount = specpdl_depth (); + Lisp_Object prefix; + + Lisp_Object fun; + Lisp_Object specs = Qnil; +#ifdef IT_SEEMS_THAT_MLY_DOESNT_LIKE_THIS + Lisp_Object enable; +#endif + /* If SPECS is a string, we reset prompt_data to string_data + * (XSTRING (specs)) every time a GC might have occurred */ + CONST char *prompt_data = 0; + int prompt_index = 0; + int argcount; + int set_zmacs_region_stays = 0; + int mouse_event_count = 0; + + if (!NILP (keys)) + { + int i; + + CHECK_VECTOR (keys); + for (i = 0; i < vector_length (XVECTOR (keys)); i++) + CHECK_LIVE_EVENT (vector_data (XVECTOR (keys))[i]); + } + + /* Save this now, since use of minibuffer will clobber it. */ + prefix = Vcurrent_prefix_arg; + + retry: + +#ifdef IT_SEEMS_THAT_MLY_DOESNT_LIKE_THIS + /* Marginal kludge. Use an evaluated interactive spec instead of this! */ + if (SYMBOLP (function)) + enable = Fget (function, Qenable_recursive_minibuffers, Qnil); +#endif + + fun = indirect_function (function, 1); + + /* Decode the kind of function. Either handle it and return, + or go to `lose' if not interactive, or go to `retry' + to specify a different function, or set either PROMPT_DATA or SPECS. */ + + if (SUBRP (fun)) + { + prompt_data = XSUBR (fun)->prompt; + if (!prompt_data) + { + lose: + function = wrong_type_argument (Qcommandp, function); + goto retry; + } +#if 0 /* FSFmacs */ /* Huh? Where is this used? */ + if ((EMACS_INT) prompt_data == 1) + /* Let SPECS (which is nil) be used as the args. */ + prompt_data = 0; +#endif + } + else if (COMPILED_FUNCTIONP (fun)) + { + struct Lisp_Compiled_Function *b = XCOMPILED_FUNCTION (fun); + if (!(b->flags.interactivep)) + goto lose; + specs = compiled_function_interactive (b); + } + else if (!CONSP (fun)) + goto lose; + else + { + Lisp_Object funcar = Fcar (fun); + + if (EQ (funcar, Qautoload)) + { + struct gcpro gcpro1, gcpro2; + GCPRO2 (function, prefix); + do_autoload (fun, function); + UNGCPRO; + goto retry; + } + else if (EQ (funcar, Qlambda)) + { + specs = Fassq (Qinteractive, Fcdr (Fcdr (fun))); + if (NILP (specs)) + goto lose; + specs = Fcar (Fcdr (specs)); + } +#ifdef MOCKLISP_SUPPORT + else if (EQ (funcar, Qmocklisp)) + { + single_console_state (); + return ml_apply (fun, Qinteractive); + } +#endif + else + goto lose; + } + + /* FSFmacs makes an alloca() copy of prompt_data here. + We're more intelligent about this and just reset prompt_data + as necessary. */ + /* If either specs or prompt_data is set to a string, use it. */ + if (!STRINGP (specs) && prompt_data == 0) + { + struct gcpro gcpro1, gcpro2, gcpro3; + int i = num_input_chars; + Lisp_Object input = specs; + + GCPRO3 (function, specs, input); + /* Compute the arg values using the user's expression. */ + specs = Feval (specs); + if (EQ (record_flag, Qlambda)) /* XEmacs addition */ + { + UNGCPRO; + return (specs); + } + if (!NILP (record_flag) || i != num_input_chars) + { + /* We should record this command on the command history. */ + /* #### The following is too specific; should have general + mechanism for doing this. */ + Lisp_Object values, car; + /* Make a copy of the list of values, for the command history, + and turn them into things we can eval. */ + values = quotify_args (Fcopy_sequence (specs)); + /* If the list of args was produced with an explicit call to `list', + look for elements that were computed with (region-beginning) + or (region-end), and put those expressions into VALUES + instead of the present values. */ + if (CONSP (input)) + { + car = XCAR (input); + /* Skip through certain special forms. */ + while (EQ (car, Qlet) || EQ (car, QletX) + || EQ (car, Qsave_excursion)) + { + while (CONSP (XCDR (input))) + input = XCDR (input); + input = XCAR (input); + if (!CONSP (input)) + break; + car = XCAR (input); + } + if (EQ (car, Qlist)) + { + Lisp_Object intail, valtail; + for (intail = Fcdr (input), valtail = values; + CONSP (valtail); + intail = Fcdr (intail), valtail = Fcdr (valtail)) + { + Lisp_Object elt; + elt = Fcar (intail); + if (CONSP (elt)) + { + Lisp_Object eltcar = Fcar (elt); + if (EQ (eltcar, Qpoint) + || EQ (eltcar, Qmark) + || EQ (eltcar, Qregion_beginning) + || EQ (eltcar, Qregion_end)) + Fsetcar (valtail, Fcar (intail)); + } + } + } + } + Vcommand_history + = Fcons (Fcons (function, values), Vcommand_history); + } + single_console_state (); + RETURN_UNGCPRO (apply1 (fun, specs)); + } + + /* Here if function specifies a string to control parsing the defaults */ + +#ifdef I18N3 + /* Translate interactive prompt. */ + if (STRINGP (specs)) + { + Lisp_Object domain = Qnil; + if (COMPILED_FUNCTIONP (fun)) + domain = Fcompiled_function_domain (fun); + if (NILP (domain)) + specs = Fgettext (specs); + else + specs = Fdgettext (domain, specs); + } + else if (prompt_data) + /* We do not have to worry about domains in this case because + prompt_data is non-nil only for built-in functions, which + always use the default domain. */ + prompt_data = gettext (prompt_data); +#endif + + /* Handle special starting chars `*' and `@' and `_'. */ + /* Note that `+' is reserved for user extensions. */ + prompt_index = 0; + { + struct gcpro gcpro1, gcpro2; + GCPRO2 (function, specs); + + for (;;) + { + if (STRINGP (specs)) + prompt_data = (CONST char *) string_data (XSTRING (specs)); + + if (prompt_data[prompt_index] == '+') + error ("`+' is not used in `interactive' for ordinary commands"); + else if (prompt_data[prompt_index] == '*') + { + prompt_index++; + if (!NILP (current_buffer->read_only)) + barf_if_buffer_read_only (current_buffer, -1, -1); + } + else if (prompt_data[prompt_index] == '@') + { + Lisp_Object event; + prompt_index++; + + if (!NILP (keys)) + event = extract_vector_nth_mouse_event (keys, 0); + else +#if 0 + event = extract_this_command_keys_nth_mouse_event (0); +#else + /* Doesn't work; see below */ + event = Vcurrent_mouse_event; +#endif + if (! NILP (event)) + { + Lisp_Object window = Fevent_window (event); + if (!NILP (window)) + { + if (MINI_WINDOW_P (XWINDOW (window)) + && ! (minibuf_level > 0 && EQ (window, + minibuf_window))) + error ("Attempt to select inactive minibuffer window"); + +#if 0 /* unclean! see event-stream.c */ + /* If the current buffer wants to clean up, let it. */ + if (!NILP (Vmouse_leave_buffer_hook)) + run_hook (Qmouse_leave_buffer_hook); +#endif + + Fselect_window (window); + } + } + } + else if (prompt_data[prompt_index] == '_') + { + prompt_index++; + set_zmacs_region_stays = 1; + } + else + { + UNGCPRO; + break; + } + } + } + + /* Count the number of arguments the interactive spec would have + us give to the function. */ + argcount = 0; + { + CONST char *tem; + for (tem = prompt_data + prompt_index; *tem; ) + { + /* 'r' specifications ("point and mark as 2 numeric args") + produce *two* arguments. */ + if (*tem == 'r') + argcount += 2; + else + argcount += 1; + tem = (CONST char *) strchr (tem + 1, '\n'); + if (!tem) + break; + tem++; + } + } + +#ifdef IT_SEEMS_THAT_MLY_DOESNT_LIKE_THIS + if (!NILP (enable)) + specbind (Qenable_recursive_minibuffers, Qt); +#endif + + if (argcount == 0) + { + /* Interactive function or no arguments; just call it */ + if (EQ (record_flag, Qlambda)) + return (Qnil); + if (!NILP (record_flag)) + { + Vcommand_history = Fcons (list1 (function), Vcommand_history); + } + specbind (Qcommand_debug_status, Qnil); + /* XEmacs: was fun = call0 (fun), but that's backtraced wrong */ + { + struct gcpro gcpro1; + + GCPRO1 (fun); + fun = funcall_recording_as (function, 1, &fun); + UNGCPRO; + } + if (set_zmacs_region_stays) + zmacs_region_stays = 1; + return (unbind_to (speccount, fun)); + } + + /* Read interactive arguments */ + { + /* args[-1] is the function to call */ + /* args[n] is the n'th argument to the function */ + int alloca_size = (1 /* function to call */ + + argcount /* actual arguments */ + + argcount /* visargs */ + + argcount /* varies */ + ); + Lisp_Object *args + = (((Lisp_Object *) alloca (sizeof (Lisp_Object) * alloca_size)) + + 1); + /* visargs is an array of either Qnil or user-friendlier versions (often + * strings) of previous arguments, to use in prompts for succesive + * arguments. ("Often strings" because emacs didn't used to have + * format %S and prin1-to-string.) */ + Lisp_Object *visargs = args + argcount; + /* If varies[i] is non-null, the i'th argument shouldn't just have + its value in this call quoted in the command history. It should be + recorded as a call to the function named varies[i]]. */ + Lisp_Object *varies = visargs + argcount; + int arg_from_tty = 0; + REGISTER int argnum; + struct gcpro gcpro1, gcpro2; + + args[-1] = function; + for (argnum = 0; argnum < alloca_size - 1; argnum++) + args[argnum] = Qnil; + + /* Must GC-protect args[-1] (ie function) because Ffuncall doesn't */ + /* `function' itself isn't GC-protected -- use args[-1] from here + (actually, doesn't matter since Emacs GC doesn't relocate, sigh) */ + GCPRO2 (prefix, args[-1]); + gcpro2.nvars = alloca_size; + + for (argnum = 0; ; argnum++) + { + CONST char *prompt_start = prompt_data + prompt_index + 1; + CONST char *prompt_limit = (CONST char *) strchr (prompt_start, '\n'); + int prompt_length; + prompt_length = ((prompt_limit) + ? (prompt_limit - prompt_start) + : strlen (prompt_start)); + if (prompt_limit && prompt_limit[1] == 0) + { + prompt_limit = 0; /* "sfoo:\n" -- strip tailing return */ + prompt_length -= 1; + } + /* This uses `visargs' instead of `args' so that global-set-key + prompts with "Set key C-x C-f to command: "instead of printing + event objects in there. + */ +#define PROMPT() callint_prompt ((CONST Bufbyte *) prompt_start, prompt_length, visargs, argnum) + switch (prompt_data[prompt_index]) + { + case 'a': /* Symbol defined as a function */ + { + Lisp_Object tem = call1 (Qread_function, PROMPT ()); + args[argnum] = tem; + arg_from_tty = 1; + break; + } + case 'b': /* Name of existing buffer */ + { + Lisp_Object def = Fcurrent_buffer (); + if (EQ (Fselected_window (Qnil), minibuf_window)) + def = Fother_buffer (def, Qnil, Qnil); + /* read-buffer returns a buffer name, not a buffer! */ + args[argnum] = call3 (Qread_buffer, PROMPT (), def, + Qt); + arg_from_tty = 1; + break; + } + case 'B': /* Name of buffer, possibly nonexistent */ + { + /* read-buffer returns a buffer name, not a buffer! */ + args[argnum] = call2 (Qread_buffer, PROMPT (), + Fother_buffer (Fcurrent_buffer (), Qnil, + Qnil)); + arg_from_tty = 1; + break; + } + case 'c': /* Character */ + { + Lisp_Object tem; + int shadowing_speccount = specpdl_depth (); + + specbind (Qcursor_in_echo_area, Qt); + message ("%s", string_data (XSTRING (PROMPT ()))); + tem = (call0 (Qread_char)); + args[argnum] = tem; + /* visargs[argnum] = Fsingle_key_description (tem); */ + /* FSF has visargs[argnum] = Fchar_to_string (tem); */ + + unbind_to (shadowing_speccount, Qnil); + + /* #### `C-x / a' should not leave the prompt in the minibuffer. + This isn't the right fix, because (message ...) (read-char) + shouldn't leave the message there either... */ + clear_message (); + + arg_from_tty = 1; + break; + } + case 'C': /* Command: symbol with interactive function */ + { + Lisp_Object tem = call1 (Qread_command, PROMPT ()); + args[argnum] = tem; + arg_from_tty = 1; + break; + } + case 'd': /* Value of point. Does not do I/O. */ + { + args[argnum] = Fcopy_marker (current_buffer->point_marker, Qt); + varies[argnum] = Qpoint; + break; + } + case 'e': + { + Lisp_Object event; + + if (!NILP (keys)) + event = extract_vector_nth_mouse_event (keys, + mouse_event_count); + else +#if 0 + /* This doesn't quite work because this-command-keys + behaves in utterly counterintuitive ways. Sometimes + it retrieves an event back in the future, e.g. when + one command invokes another command and both are + invoked with the mouse. */ + event = (extract_this_command_keys_nth_mouse_event + (mouse_event_count)); +#else + event = Vcurrent_mouse_event; +#endif + + if (NILP (event)) + error ("%s must be bound to a mouse or misc-user event", + (SYMBOLP (function) + ? (char *) string_data (XSYMBOL (function)->name) + : "command")); + args[argnum] = event; + mouse_event_count++; + break; + } + case 'D': /* Directory name. */ + { + args[argnum] = call4 (Qread_directory_name, PROMPT (), + Qnil, /* dir */ + current_buffer->directory, /* default */ + Qt /* must-match */ + ); + arg_from_tty = 1; + break; + } + case 'f': /* Existing file name. */ + { + Lisp_Object tem = call4 (Qread_file_name, PROMPT (), + Qnil, /* dir */ + Qnil, /* default */ + make_int (0) /* must-match */ + ); + args[argnum] = tem; + arg_from_tty = 1; + break; + } + case 'F': /* Possibly nonexistent file name. */ + { + args[argnum] = call4 (Qread_file_name, PROMPT (), + Qnil, /* dir */ + Qnil, /* default */ + Qnil /* must-match */ + ); + arg_from_tty = 1; + break; + } + case 'k': /* Key sequence (vector of events) */ + { + Lisp_Object tem = Fread_key_sequence (PROMPT (), Qnil, Qnil); + visargs[argnum] = Fkey_description (tem); + /* The following makes `describe-key' not work with + extent-local keymaps and such; and anyway, it's + contrary to the documentation. */ + /* args[argnum] = call1 (Qevents_to_keys, tem); */ + args[argnum] = tem; + arg_from_tty = 1; + break; + } + case 'K': /* Key sequence (vector of events), + no automatic downcasing */ + { + Lisp_Object tem = Fread_key_sequence (PROMPT (), Qnil, Qt); + visargs[argnum] = Fkey_description (tem); + /* The following makes `describe-key' not work with + extent-local keymaps and such; and anyway, it's + contrary to the documentation. */ + /* args[argnum] = call1 (Qevents_to_keys, tem); */ + args[argnum] = tem; + arg_from_tty = 1; + break; + } + + case 'm': /* Value of mark. Does not do I/O. */ + { + args[argnum] = current_buffer->mark; + varies[argnum] = Qmark; + break; + } + case 'n': /* Read number from minibuffer. */ + { + read_number: + args[argnum] = call2 (Qread_number, PROMPT (), Qt); + /* numbers are too boring to go on command history */ + /* arg_from_tty = 1; */ + break; + } + case 'N': /* Prefix arg, else number from minibuffer */ + { + if (NILP (prefix)) + goto read_number; + else + goto prefix_value; + } + case 'P': /* Prefix arg in raw form. Does no I/O. */ + { + args[argnum] = prefix; + break; + } + case 'p': /* Prefix arg converted to number. No I/O. */ + { + prefix_value: + { + Lisp_Object tem = Fprefix_numeric_value (prefix); + args[argnum] = tem; + } + break; + } + case 'r': /* Region, point and mark as 2 args. */ + { + Bufpos tem = check_mark (); + args[argnum] = (BUF_PT (current_buffer) < tem + ? Fcopy_marker (current_buffer->point_marker, Qt) + : current_buffer->mark); + varies[argnum] = Qregion_beginning; + args[++argnum] = (BUF_PT (current_buffer) > tem + ? Fcopy_marker (current_buffer->point_marker, + Qt) + : current_buffer->mark); + varies[argnum] = Qregion_end; + break; + } + case 's': /* String read via minibuffer. */ + { + args[argnum] = call1 (Qread_string, PROMPT ()); + arg_from_tty = 1; + break; + } + case 'S': /* Any symbol. */ + { +#if 0 /* Historical crock */ + Lisp_Object tem = intern ("minibuffer-local-ns-map"); + tem = find_symbol_value (tem); + if (UNBOUNDP (tem)) tem = Qnil; + tem = call3 (Qread_from_minibuffer, PROMPT (), Qnil, + tem); + args[argnum] = Fintern (tem, Qnil); +#else /* 1 */ + visargs[argnum] = Qnil; + for (;;) + { + Lisp_Object tem = call5 (Qcompleting_read, + PROMPT (), + Vobarray, + Qnil, + Qnil, + /* nil, or prev attempt */ + visargs[argnum]); + visargs[argnum] = tem; + /* I could use condition-case with this loser, but why bother? + * tem = Fread (tem); check-symbol-p; + */ + tem = Fintern (tem, Qnil); + args[argnum] = tem; + if (string_length (XSYMBOL (tem)->name) > 0) + /* Don't accept the empty-named symbol. If the loser + really wants this s/he can call completing-read + directly */ + break; + } +#endif /* 1 */ + arg_from_tty = 1; + break; + } + case 'v': /* Variable name: user-variable-p symbol */ + { + Lisp_Object tem = call1 (Qread_variable, PROMPT ()); + args[argnum] = tem; + arg_from_tty = 1; + break; + } + case 'x': /* Lisp expression read but not evaluated */ + { + args[argnum] = call1 (Qread_expression, PROMPT ()); + /* visargs[argnum] = Fprin1_to_string (args[argnum], Qnil); */ + arg_from_tty = 1; + break; + } + case 'X': /* Lisp expression read and evaluated */ + { + Lisp_Object tem = call1 (Qread_expression, PROMPT ()); + /* visargs[argnum] = Fprin1_to_string (tem, Qnil); */ + args[argnum] = Feval (tem); + arg_from_tty = 1; + break; + } + + /* We have a case for `+' so we get an error + if anyone tries to define one here. */ + case '+': + default: + { + error ("Invalid `interactive' control letter \"%c\" (#o%03o).", + prompt_data[prompt_index], + prompt_data[prompt_index]); + } + } +#undef PROMPT + if (NILP (visargs[argnum])) + visargs[argnum] = args[argnum]; + + if (!prompt_limit) + break; + if (STRINGP (specs)) + prompt_data = (CONST char *) string_data (XSTRING (specs)); + prompt_index += prompt_length + 1 + 1; /* +1 to skip spec, +1 for \n */ + } + unbind_to (speccount, Qnil); + + QUIT; + + if (EQ (record_flag, Qlambda)) + { + RETURN_UNGCPRO (Flist (argcount, args)); + } + + if (arg_from_tty || !NILP (record_flag)) + { + /* Reuse visargs as a temporary for constructing the command history */ + for (argnum = 0; argnum < argcount; argnum++) + { + if (!NILP (varies[argnum])) + visargs[argnum] = list1 (varies[argnum]); + else + visargs[argnum] = quotify_arg (args[argnum]); + } + Vcommand_history = Fcons (Fcons (args[-1], Flist (argcount, visargs)), + Vcommand_history); + } + + /* If we used a marker to hold point, mark, or an end of the region, + temporarily, convert it to an integer now. */ + for (argnum = 0; argnum < argcount; argnum++) + if (!NILP (varies[argnum])) + XSETINT (args[argnum], marker_position (args[argnum])); + + single_console_state (); + specbind (Qcommand_debug_status, Qnil); + fun = Ffuncall (argcount + 1, args - 1); + UNGCPRO; + if (set_zmacs_region_stays) + zmacs_region_stays = 1; + return (unbind_to (speccount, fun)); + } +} + +DEFUN ("prefix-numeric-value", Fprefix_numeric_value, Sprefix_numeric_value, + 1, 1, 0 /* +Return numeric meaning of raw prefix argument ARG. +A raw prefix argument is what you get from `(interactive \"P\")'. +Its numeric meaning is what you would get from `(interactive \"p\")'. +*/ ) + (raw) + Lisp_Object raw; +{ + int val; + + if (NILP (raw)) + val = 1; + else if (EQ (raw, Qminus)) + val = -1; + else if (INTP (raw)) + val = XINT (raw); + else if (CONSP (raw) && INTP (XCAR (raw))) + val = XINT (XCAR (raw)); + else + val = 1; + + return (make_int (val)); + +} + +void +syms_of_callint (void) +{ + defsymbol (&Qcall_interactively, "call-interactively"); + defsymbol (&Qread_from_minibuffer, "read-from-minibuffer"); + defsymbol (&Qcompleting_read, "completing-read"); + defsymbol (&Qread_file_name, "read-file-name"); + defsymbol (&Qread_directory_name, "read-directory-name"); + defsymbol (&Qread_string, "read-string"); + defsymbol (&Qread_buffer, "read-buffer"); + defsymbol (&Qread_variable, "read-variable"); + defsymbol (&Qread_function, "read-function"); + defsymbol (&Qread_command, "read-command"); + defsymbol (&Qread_number, "read-number"); + defsymbol (&Qread_expression, "read-expression"); + defsymbol (&Qevents_to_keys, "events-to-keys"); + defsymbol (&Qcommand_debug_status, "command-debug-status"); + defsymbol (&Qenable_recursive_minibuffers, "enable-recursive-minibuffers"); + defsymbol (&Qcommand_debug_status, "command-debug-status"); + defsymbol (&Quser_variable_p, "user-variable-p"); + defsymbol (&Qcurrent_prefix_arg, "current-prefix-arg"); + + defsymbol (&Qlet, "let"); + defsymbol (&QletX, "let*"); + defsymbol (&Qsave_excursion, "save-excursion"); +#if 0 /* ill-conceived */ + defsymbol (&Qmouse_leave_buffer_hook, "mouse-leave-buffer-hook"); +#endif + + defsubr (&Sinteractive); + defsubr (&Scall_interactively); + defsubr (&Sprefix_numeric_value); +} + +void +vars_of_callint (void) +{ + DEFVAR_LISP ("current-prefix-arg", &Vcurrent_prefix_arg /* +The value of the prefix argument for this editing command. +It may be a number, or the symbol `-' for just a minus sign as arg, +or a list whose car is a number for just one or more C-U's +or nil if no argument has been specified. +This is what `(interactive \"P\")' returns. +*/ ); + Vcurrent_prefix_arg = Qnil; + + DEFVAR_LISP ("command-history", &Vcommand_history /* +List of recent commands that read arguments from terminal. +Each command is represented as a form to evaluate. +*/ ); + Vcommand_history = Qnil; + + DEFVAR_LISP ("command-debug-status", &Vcommand_debug_status /* +Debugging status of current interactive command. +Bound each time `call-interactively' is called; +may be set by the debugger as a reminder for itself. +*/ ); + Vcommand_debug_status = Qnil; + +#if 0 /* FSFmacs */ + xxDEFVAR_LISP ("mark-even-if-inactive", &Vmark_even_if_inactive /* +*Non-nil means you can use the mark even when inactive. +This option makes a difference in Transient Mark mode. +When the option is non-nil, deactivation of the mark +turns off region highlighting, but commands that use the mark +behave as if the mark were still active. +*/ ); + Vmark_even_if_inactive = Qnil; +#endif + +#if 0 /* Doesn't work and is totally ill-conceived anyway. */ + xxDEFVAR_LISP ("mouse-leave-buffer-hook", &Vmouse_leave_buffer_hook /* +Hook to run when about to switch windows with a mouse command. +Its purpose is to give temporary modes such as Isearch mode +a way to turn themselves off when a mouse command switches windows. +*/ ); + Vmouse_leave_buffer_hook = Qnil; +#endif +}