|
|
1.1 ! root 1: /* Call a Lisp function interactively. ! 2: Copyright (C) 1985 Richard M. Stallman. ! 3: ! 4: This file is part of GNU Emacs. ! 5: ! 6: GNU Emacs is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the GNU Emacs General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: GNU Emacs, but only under the conditions described in the ! 15: GNU Emacs General Public License. A copy of this license is ! 16: supposed to have been given to you along with GNU Emacs so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: ! 22: #include "config.h" ! 23: #include "lisp.h" ! 24: #include "buffer.h" ! 25: #include "commands.h" ! 26: #include "window.h" ! 27: ! 28: extern struct Lisp_Vector *CurrentGlobalMap; ! 29: ! 30: extern int num_input_chars; ! 31: ! 32: Lisp_Object Vprefix_arg, Vcurrent_prefix_arg, Qminus; ! 33: Lisp_Object Qcall_interactively; ! 34: Lisp_Object Vcommand_history; ! 35: ! 36: extern Lisp_Object ml_apply (); ! 37: extern Lisp_Object Fread_buffer (), Fread_key_sequence (), Fread_file_name (); ! 38: ! 39: /* ARGSUSED */ ! 40: DEFUN ("interactive", Finteractive, Sinteractive, 0, UNEVALLED, 0, ! 41: 0 /* See auxdoc.c */) ! 42: (args) ! 43: Lisp_Object args; ! 44: { ! 45: return Qnil; ! 46: } ! 47: ! 48: /* Quotify EXP: if EXP is constant, return it. ! 49: If EXP is not constant, return (quote EXP). */ ! 50: Lisp_Object ! 51: quotify_arg (exp) ! 52: register Lisp_Object exp; ! 53: { ! 54: if (XTYPE (exp) != Lisp_Int && XTYPE (exp) != Lisp_String ! 55: && !NULL (exp) && !EQ (exp, Qt)) ! 56: return Fcons (Qquote, Fcons (exp, Qnil)); ! 57: ! 58: return exp; ! 59: } ! 60: ! 61: /* Modify EXP by quotifying each element (except the first). */ ! 62: Lisp_Object ! 63: quotify_args (exp) ! 64: Lisp_Object exp; ! 65: { ! 66: register Lisp_Object tail; ! 67: register struct Lisp_Cons *ptr; ! 68: for (tail = exp; LISTP (tail); tail = ptr->cdr) ! 69: { ! 70: ptr = XCONS (tail); ! 71: ptr->car = quotify_arg (ptr->car); ! 72: } ! 73: return exp; ! 74: } ! 75: ! 76: char *callint_argfuns[] ! 77: = {"", "point", "mark", "region-beginning", "region-end"}; ! 78: ! 79: #define argfuns callint_argfuns ! 80: ! 81: DEFUN ("call-interactively", Fcall_interactively, Scall_interactively, 1, 2, 0, ! 82: "Call FUNCTION, reading args from the terminal,\n\ ! 83: if the interactive calling specs of FUNCTION request one.\n\ ! 84: \n\ ! 85: The function contains a specification of how to do the argument reading.\n\ ! 86: In the case of user-defined functions, this is specified by placing a call to\n\ ! 87: the function interactive at the top level of the function body. See interactive.") ! 88: (function, record) ! 89: Lisp_Object function, record; ! 90: { ! 91: Lisp_Object *args, *visargs; ! 92: unsigned char **argstrings; ! 93: Lisp_Object fun; ! 94: Lisp_Object funcar; ! 95: Lisp_Object specs; ! 96: Lisp_Object teml; ! 97: ! 98: Lisp_Object prefix_arg; ! 99: unsigned char *string; ! 100: unsigned char *tem; ! 101: int *varies; ! 102: register int i, j; ! 103: int count, foo; ! 104: char prompt[100]; ! 105: char prompt1[100]; ! 106: char *tem1; ! 107: int arg_from_tty = 0; ! 108: struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; ! 109: extern char *index (); ! 110: ! 111: /* Save this now, since use ofminibuffer will clobber it. */ ! 112: prefix_arg = Vcurrent_prefix_arg; ! 113: ! 114: retry: ! 115: ! 116: fun = function; ! 117: while (XTYPE (fun) == Lisp_Symbol && !EQ (fun, Qunbound)) fun = XSYMBOL (fun)->function; ! 118: ! 119: if (XTYPE (fun) == Lisp_Subr) ! 120: { ! 121: string = (unsigned char *) XSUBR (fun)->prompt; ! 122: if (!string) ! 123: { ! 124: lose: ! 125: function = wrong_type_argument (Qcommandp, function, 0); ! 126: goto retry; ! 127: } ! 128: else if ((int) string == 1) ! 129: return Fapply (function, Qnil); ! 130: } ! 131: else if (!LISTP (fun)) ! 132: goto lose; ! 133: else if (funcar = Fcar (fun), EQ (funcar, Qautoload)) ! 134: { ! 135: GCPRO2 (function, prefix_arg); ! 136: do_autoload (fun, function); ! 137: UNGCPRO; ! 138: goto retry; ! 139: } ! 140: else if (EQ (funcar, Qlambda)) ! 141: { ! 142: specs = Fassq (Qinteractive, Fcdr (Fcdr (fun))); ! 143: if (NULL (specs)) ! 144: goto lose; ! 145: specs = Fcar (Fcdr (specs)); ! 146: if (XTYPE (specs) == Lisp_String) ! 147: string = XSTRING (specs)->data; ! 148: else ! 149: { ! 150: i = num_input_chars; ! 151: specs = Feval (specs); ! 152: if (i != num_input_chars || !NULL (record)) ! 153: Vcommand_history ! 154: = Fcons (Fcons (function, quotify_args (Fcopy_sequence (specs))), ! 155: Vcommand_history); ! 156: return Fapply (function, specs); ! 157: } ! 158: } ! 159: else if (EQ (funcar, Qmocklisp)) ! 160: return ml_apply (fun, Qinteractive); ! 161: else ! 162: goto lose; ! 163: ! 164: /* Here if function specifies a string to control parsing the defaults */ ! 165: ! 166: /* First character '*' means barf if buffer read-only */ ! 167: if (*string == '*') ! 168: { string++; ! 169: if (!NULL (bf_cur->read_only)) ! 170: Fbarf_if_buffer_read_only (); ! 171: } ! 172: ! 173: tem = string; ! 174: for (j = 0; *tem; j++) ! 175: { ! 176: if (*tem == 'r') j++; ! 177: tem = (unsigned char *) index (tem, '\n'); ! 178: if (tem) tem++; ! 179: else tem = (unsigned char *) ""; ! 180: } ! 181: count = j; ! 182: ! 183: args = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object)); ! 184: visargs = (Lisp_Object *) alloca ((count + 1) * sizeof (Lisp_Object)); ! 185: argstrings = (unsigned char **) alloca ((count + 1) * sizeof (char *)); ! 186: varies = (int *) alloca ((count + 1) * sizeof (int)); ! 187: ! 188: for (i = 0; i < (count + 1); i++) ! 189: { ! 190: args[i] = Qnil; ! 191: visargs[i] = Qnil; ! 192: varies[i] = 0; ! 193: } ! 194: ! 195: GCPRO4 (prefix_arg, function, *args, *visargs); ! 196: gcpro3.nvars = (count + 1); ! 197: gcpro4.nvars = (count + 1); ! 198: ! 199: tem = string; ! 200: for (i = 1; *tem; i++) ! 201: { ! 202: strncpy (prompt1, tem + 1, sizeof prompt1 - 1); ! 203: prompt1[sizeof prompt1 - 1] = 0; ! 204: tem1 = index (prompt1, '\n'); ! 205: if (tem1) *tem1 = 0; ! 206: for (j = 1; j < i; j++) ! 207: argstrings[j] = XSTRING (visargs[j])->data; ! 208: ! 209: doprnt (prompt, sizeof prompt, prompt1, argstrings + 1); ! 210: ! 211: switch (*tem) ! 212: { ! 213: case 'a': /* Symbol defined as a function */ ! 214: visargs[i] = Fcompleting_read (build_string (prompt), ! 215: Vobarray, Qfboundp, Qt, Qnil); ! 216: /* Passing args[i] directly stimulates compiler bug */ ! 217: teml = visargs[i]; ! 218: args[i] = Fintern (teml, Qnil); ! 219: break; ! 220: ! 221: case 'b': /* Name of existing buffer */ ! 222: args[i] = Fcurrent_buffer (); ! 223: if (EQ (selected_window, minibuf_window)) ! 224: args[i] = Fother_buffer (args[i]); ! 225: args[i] = Fread_buffer (build_string (prompt), args[i], Qt); ! 226: break; ! 227: ! 228: case 'B': /* Name of buffer, possibly nonexistent */ ! 229: args[i] = Fread_buffer (build_string (prompt), ! 230: Fother_buffer (Fcurrent_buffer ()), Qnil); ! 231: break; ! 232: ! 233: case 'c': /* Character */ ! 234: message1 (prompt); ! 235: args[i] = Fread_char (); ! 236: /* Passing args[i] directly stimulates compiler bug */ ! 237: teml = args[i]; ! 238: visargs[i] = Fchar_to_string (teml); ! 239: break; ! 240: ! 241: case 'C': /* Command: symbol with interactive function */ ! 242: visargs[i] = Fcompleting_read (build_string (prompt), ! 243: Vobarray, Qcommandp, Qt, Qnil); ! 244: /* Passing args[i] directly stimulates compiler bug */ ! 245: teml = visargs[i]; ! 246: args[i] = Fintern (teml, Qnil); ! 247: break; ! 248: ! 249: case 'd': /* Value of point. Does not do I/O. */ ! 250: XFASTINT (args[i]) = point; ! 251: visargs[i] = build_string ("point"); ! 252: varies[i] = 1; ! 253: break; ! 254: ! 255: case 'D': /* Directory name. */ ! 256: args[i] = Fread_file_name (build_string (prompt), Qnil, ! 257: bf_cur->directory, Qlambda); ! 258: break; ! 259: ! 260: case 'f': /* Existing file name. */ ! 261: args[i] = Fread_file_name (build_string (prompt), ! 262: Qnil, Qnil, Qlambda); ! 263: break; ! 264: ! 265: case 'F': /* Possibly nonexistent file name. */ ! 266: args[i] = Fread_file_name (build_string (prompt), ! 267: Qnil, Qnil, Qnil); ! 268: break; ! 269: ! 270: case 'k': /* Key sequence (string) */ ! 271: args[i] = Fread_key_sequence (build_string (prompt)); ! 272: teml = args[i]; ! 273: visargs[i] = Fkey_description (teml); ! 274: break; ! 275: ! 276: case 'm': /* Value of mark. Does not do I/O. */ ! 277: if (NULL (bf_cur->mark)) ! 278: error ("The mark is not set now"); ! 279: visargs[i] = build_string ("the mark"); ! 280: XFASTINT (args[i]) = marker_position (bf_cur->mark); ! 281: varies[i] = 2; ! 282: break; ! 283: ! 284: case 'n': /* Read number from minibuffer. */ ! 285: do ! 286: args[i] = Fread_minibuffer (build_string (prompt), Qnil); ! 287: while (XTYPE (args[i]) != Lisp_Int); ! 288: visargs[i] = last_minibuf_string; ! 289: break; ! 290: ! 291: case 'P': /* Prefix arg in raw form. Does no I/O. */ ! 292: args[i] = prefix_arg; ! 293: XFASTINT (visargs[i]) = (int) ""; ! 294: varies[i] = -1; ! 295: break; ! 296: ! 297: case 'p': /* Prefix arg converted to number. No I/O. */ ! 298: args[i] = Fprefix_numeric_value (prefix_arg); ! 299: XFASTINT (visargs[i]) = (int) ""; ! 300: varies[i] = -1; ! 301: break; ! 302: ! 303: case 'r': /* Region, point and mark as 2 args. */ ! 304: if (NULL (bf_cur->mark)) ! 305: error ("The mark is not set now"); ! 306: foo = marker_position (bf_cur->mark); ! 307: visargs[i] = build_string ("point"); ! 308: XFASTINT (args[i]) = point < foo ? point : foo; ! 309: varies[i] = 3; ! 310: visargs[++i] = build_string ("the mark"); ! 311: XFASTINT (args[i]) = point > foo ? point : foo; ! 312: varies[i] = 4; ! 313: break; ! 314: ! 315: case 's': /* String read via minibuffer. */ ! 316: args[i] = Fread_string (build_string (prompt), Qnil); ! 317: break; ! 318: ! 319: case 'S': /* Any symbol. */ ! 320: visargs[i] = read_minibuf_string (Vminibuffer_local_ns_map, ! 321: Qnil, ! 322: build_string (prompt)); ! 323: /* Passing args[i] directly stimulates compiler bug */ ! 324: teml = visargs[i]; ! 325: args[i] = Fintern (teml, Qnil); ! 326: break; ! 327: ! 328: case 'v': /* Variable name: symbol that is ! 329: user-variable-p. */ ! 330: args[i] = Fread_variable (build_string (prompt)); ! 331: visargs[i] = last_minibuf_string; ! 332: break; ! 333: ! 334: case 'x': /* Lisp expression read but not evaluated */ ! 335: args[i] = Fread_minibuffer (build_string (prompt), Qnil); ! 336: visargs[i] = last_minibuf_string; ! 337: break; ! 338: ! 339: case 'X': /* Lisp expression read and evaluated */ ! 340: args[i] = Feval_minibuffer (build_string (prompt), Qnil); ! 341: visargs[i] = last_minibuf_string; ! 342: break; ! 343: ! 344: default: ! 345: error ("Invalid control letter in interactive calling string"); ! 346: } ! 347: ! 348: if (varies[i] == 0) ! 349: arg_from_tty = 1; ! 350: ! 351: if (NULL (visargs[i])) ! 352: visargs[i] = args[i]; ! 353: ! 354: tem = (unsigned char *) index (tem, '\n'); ! 355: if (tem) tem++; ! 356: else tem = (unsigned char *) ""; ! 357: } ! 358: ! 359: UNGCPRO; ! 360: ! 361: QUIT; ! 362: ! 363: args[0] = function; ! 364: ! 365: if (arg_from_tty || !NULL (record)) ! 366: { ! 367: visargs[0] = function; ! 368: for (i = 1; i < count + 1; i++) ! 369: if (varies[i] > 0) ! 370: visargs[i] = Fcons (intern (argfuns[varies[i]]), Qnil); ! 371: else ! 372: visargs[i] = quotify_arg (args[i]); ! 373: Vcommand_history = Fcons (Flist (count + 1, visargs), ! 374: Vcommand_history); ! 375: } ! 376: ! 377: return Ffuncall (count + 1, args); ! 378: } ! 379: ! 380: DEFUN ("prefix-numeric-value", Fprefix_numeric_value, Sprefix_numeric_value, ! 381: 1, 1, 0, ! 382: "Return numeric meaning of raw prefix argument.\n\ ! 383: A raw prefix argument is what you get from (interactive \"P\").") ! 384: (raw) ! 385: Lisp_Object raw; ! 386: { ! 387: Lisp_Object val; ! 388: ! 389: if (NULL (raw)) ! 390: XFASTINT (val) = 1; ! 391: else if (XTYPE (raw) == Lisp_Symbol) ! 392: { ! 393: XFASTINT (val) = 0; ! 394: XSETINT (val, -1); ! 395: } ! 396: else if (LISTP (raw)) ! 397: val = XCONS (raw)->car; ! 398: else if (XTYPE (raw) == Lisp_Int) ! 399: val = raw; ! 400: else ! 401: XFASTINT (val) = 1; ! 402: ! 403: return val; ! 404: } ! 405: ! 406: syms_of_callint () ! 407: { ! 408: Qminus = intern ("-"); ! 409: staticpro (&Qminus); ! 410: ! 411: Qcall_interactively = intern ("call-interactively"); ! 412: staticpro (&Qcall_interactively); ! 413: ! 414: DefLispVar ("prefix-arg", &Vprefix_arg, ! 415: "The value of the prefix argument for the next editing command.\n\ ! 416: It may be a number, or the symbol - for just a minus sign as arg,\n\ ! 417: or a list whose car is a number for just one or more C-U's\n\ ! 418: or nil if no argument has been specified.\n\ ! 419: \n\ ! 420: You cannot examine this variable to find the argument for this command\n\ ! 421: since it has been set to nil by the time you can look.\n\ ! 422: Instead, you should use the variable current-prefix-arg, although\n\ ! 423: normally commands can get this prefix argument with (interactive \"P\")."); ! 424: ! 425: DefLispVar ("current-prefix-arg", &Vcurrent_prefix_arg, ! 426: "The value of the prefix argument for this editing command.\n\ ! 427: It may be a number, or the symbol - for just a minus sign as arg,\n\ ! 428: or a list whose car is a number for just one or more C-U's\n\ ! 429: or nil if no argument has been specified.\n\ ! 430: This is what (interactive \"P\") returns."); ! 431: ! 432: DefLispVar ("command-history", &Vcommand_history, ! 433: "List of recent commands that read arguments from terminal.\n\ ! 434: Each command is represented as a form to evaluate."); ! 435: Vcommand_history = Qnil; ! 436: ! 437: defsubr (&Sinteractive); ! 438: defsubr (&Scall_interactively); ! 439: defsubr (&Sprefix_numeric_value); ! 440: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.