428
|
1 ;;; cmdloop.el --- support functions for the top-level command loop.
|
|
2
|
|
3 ;; Copyright (C) 1992-4, 1997 Free Software Foundation, Inc.
|
1333
|
4 ;; Copyright (C) 2001, 2002, 2003 Ben Wing.
|
428
|
5
|
|
6 ;; Author: Richard Mlynarik
|
|
7 ;; Date: 8-Jul-92
|
|
8 ;; Maintainer: XEmacs Development Team
|
|
9 ;; Keywords: internal, dumped
|
|
10
|
|
11 ;; This file is part of XEmacs.
|
|
12
|
|
13 ;; XEmacs is free software; you can redistribute it and/or modify it
|
|
14 ;; under the terms of the GNU General Public License as published by
|
|
15 ;; the Free Software Foundation; either version 2, or (at your option)
|
|
16 ;; any later version.
|
|
17
|
|
18 ;; XEmacs is distributed in the hope that it will be useful, but
|
|
19 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
21 ;; General Public License for more details.
|
|
22
|
|
23 ;; You should have received a copy of the GNU General Public License
|
|
24 ;; along with XEmacs; see the file COPYING. If not, write to the
|
|
25 ;; Free Software Foundation, 59 Temple Place - Suite 330,
|
|
26 ;; Boston, MA 02111-1307, USA.
|
|
27
|
|
28 ;;; Synched up with: FSF 19.30. (Some of the stuff below is in FSF's subr.el.)
|
1333
|
29 ;;; Some parts synched with FSF 21.2.
|
428
|
30
|
|
31 ;;; Commentary:
|
|
32
|
|
33 ;; This file is dumped with XEmacs.
|
|
34
|
|
35 ;;; Code:
|
|
36
|
|
37 (defun recursion-depth ()
|
|
38 "Return the current depth in recursive edits."
|
|
39 (+ command-loop-level (minibuffer-depth)))
|
|
40
|
|
41 (defun top-level ()
|
|
42 "Exit all recursive editing levels."
|
|
43 (interactive)
|
|
44 (throw 'top-level nil))
|
|
45
|
|
46 (defun exit-recursive-edit ()
|
|
47 "Exit from the innermost recursive edit or minibuffer."
|
|
48 (interactive)
|
|
49 (if (> (recursion-depth) 0)
|
|
50 (throw 'exit nil))
|
|
51 (error "No recursive edit is in progress"))
|
|
52
|
|
53 (defun abort-recursive-edit ()
|
|
54 "Abort the command that requested this recursive edit or minibuffer input."
|
|
55 (interactive)
|
|
56 (if (> (recursion-depth) 0)
|
|
57 (throw 'exit t))
|
|
58 (error "No recursive edit is in progress"))
|
|
59
|
|
60 ;; (defun keyboard-quit ()
|
|
61 ;; "Signal a `quit' condition."
|
|
62 ;; (interactive)
|
|
63 ;; (deactivate-mark)
|
|
64 ;; (signal 'quit nil))
|
|
65
|
|
66 ;; moved here from pending-del.
|
|
67 (defun keyboard-quit ()
|
|
68 "Signal a `quit' condition.
|
|
69 If this character is typed while lisp code is executing, it will be treated
|
|
70 as an interrupt.
|
|
71 If this character is typed at top-level, this simply beeps.
|
|
72 If `zmacs-regions' is true, and the zmacs region is active in this buffer,
|
|
73 then this key deactivates the region without beeping or signalling."
|
|
74 (interactive)
|
2611
|
75 (if (region-active-p)
|
428
|
76 ;; pseudo-zmacs compatibility: don't beep if this ^G is simply
|
|
77 ;; deactivating the region. If it is inactive, beep.
|
|
78 nil
|
|
79 (signal 'quit nil)))
|
|
80
|
|
81 (defvar buffer-quit-function nil
|
|
82 "Function to call to \"quit\" the current buffer, or nil if none.
|
|
83 \\[keyboard-escape-quit] calls this function when its more local actions
|
|
84 \(such as cancelling a prefix argument, minibuffer or region) do not apply.")
|
|
85
|
|
86 (defun keyboard-escape-quit ()
|
|
87 "Exit the current \"mode\" (in a generalized sense of the word).
|
|
88 This command can exit an interactive command such as `query-replace',
|
|
89 can clear out a prefix argument or a region,
|
|
90 can get out of the minibuffer or other recursive edit,
|
|
91 cancel the use of the current buffer (for special-purpose buffers),
|
|
92 or go back to just one window (by deleting all but the selected window)."
|
|
93 (interactive)
|
|
94 (cond ((eq last-command 'mode-exited) nil)
|
|
95 ((> (minibuffer-depth) 0)
|
|
96 (abort-recursive-edit))
|
|
97 (current-prefix-arg
|
|
98 nil)
|
|
99 ((region-active-p)
|
|
100 (zmacs-deactivate-region))
|
|
101 ((> (recursion-depth) 0)
|
|
102 (exit-recursive-edit))
|
|
103 (buffer-quit-function
|
|
104 (funcall buffer-quit-function))
|
|
105 ((not (one-window-p t))
|
|
106 (delete-other-windows))
|
|
107 ((string-match "^ \\*" (buffer-name (current-buffer)))
|
|
108 (bury-buffer))))
|
|
109
|
|
110 ;; `cancel-mode-internal' is a function of a misc-user event, which is
|
|
111 ;; queued when window system directs XEmacs frame to cancel any modal
|
|
112 ;; behavior it exposes, like mouse pointer grabbing.
|
|
113 ;;
|
|
114 ;; This function does nothing at the top level, but the code which
|
|
115 ;; runs modal event loops, such as selection drag loop in `mouse-track',
|
|
116 ;; check if misc-user function symbol is `cancel-mode-internal', and
|
|
117 ;; takes necessary cleanup actions.
|
|
118 (defun cancel-mode-internal (object)
|
|
119 (setq zmacs-region-stays t))
|
|
120
|
|
121 ;; Someone wrote: "This should really be a ring of last errors."
|
|
122 ;;
|
|
123 ;; But why bother? This stuff is not all that necessary now that we
|
|
124 ;; have message log, anyway.
|
|
125 (defvar last-error nil
|
|
126 "Object describing the last signaled error.")
|
|
127
|
|
128 (defcustom errors-deactivate-region nil
|
|
129 "*Non-nil means that errors will cause the region to be deactivated."
|
|
130 :type 'boolean
|
|
131 :group 'editing-basics)
|
|
132
|
|
133 (defun command-error (error-object)
|
771
|
134 ;; if you want a backtrace before exiting, set stack-trace-on-error.
|
|
135 (let* ((inhibit-quit t)
|
442
|
136 (debug-on-error nil)
|
|
137 (etype (car-safe error-object)))
|
428
|
138 (setq quit-flag nil)
|
|
139 (setq standard-output t)
|
|
140 (setq standard-input t)
|
|
141 (setq executing-kbd-macro nil)
|
|
142 (and errors-deactivate-region
|
|
143 (zmacs-deactivate-region))
|
|
144 (discard-input)
|
|
145
|
|
146 (setq last-error error-object)
|
|
147
|
|
148 (message nil)
|
|
149 (ding nil (cond ((eq etype 'undefined-keystroke-sequence)
|
|
150 (if (and (vectorp (nth 1 error-object))
|
|
151 (/= 0 (length (nth 1 error-object)))
|
|
152 (button-event-p (aref (nth 1 error-object) 0)))
|
|
153 'undefined-click
|
|
154 'undefined-key))
|
|
155 ((eq etype 'quit)
|
|
156 'quit)
|
|
157 ((memq etype '(end-of-buffer beginning-of-buffer))
|
|
158 'buffer-bound)
|
|
159 ((eq etype 'buffer-read-only)
|
|
160 'read-only)
|
|
161 (t 'command-error)))
|
|
162 (display-error error-object t)
|
|
163
|
|
164 (if (noninteractive)
|
|
165 (progn
|
1445
|
166 (message "\n%s exiting.\n" emacs-program-name)
|
428
|
167 (kill-emacs -1)))
|
|
168 t))
|
|
169
|
|
170 (defun describe-last-error ()
|
|
171 "Redisplay the last error-message. See the variable `last-error'."
|
|
172 (interactive)
|
|
173 (if last-error
|
|
174 (with-displaying-help-buffer
|
|
175 (lambda ()
|
|
176 (princ "Last error was:\n" standard-output)
|
|
177 (display-error last-error standard-output)))
|
|
178 (message "No error yet")))
|
|
179
|
|
180
|
|
181 ;;#### Must be done later in the loadup sequence
|
|
182 ;(define-key (symbol-function 'help-command) "e" 'describe-last-error)
|
|
183
|
|
184
|
|
185 (defun truncate-command-history-for-gc ()
|
3698
|
186 ;; We should try to avoid accessing any bindings to speak of in this
|
|
187 ;; function; as this hook is called asynchronously, the search for
|
|
188 ;; those bindings might search local bindings from essentially
|
|
189 ;; arbitrary functions. We force the body of the function to run at
|
|
190 ;; command-loop level, where the danger of local bindings is much
|
|
191 ;; reduced; the code can still do its job because the command history
|
|
192 ;; and values list will not grow before then anyway.
|
|
193 ;;
|
|
194 ;; Nothing is done in batch mode, both because it is a waste of time
|
|
195 ;; (there is no command loop!) and because this any GCs during dumping
|
|
196 ;; will invoke this code, and if it were to enqueue an eval event,
|
|
197 ;; the portable dumper would try to dump it and fail.
|
|
198 (if (not (noninteractive))
|
|
199 (enqueue-eval-event
|
|
200 (lambda (arg)
|
|
201 (let ((tail (nthcdr 30 command-history)))
|
|
202 (if tail (setcdr tail nil)))
|
|
203 (let ((tail (nthcdr 30 values)))
|
|
204 (if tail (setcdr tail nil))))
|
|
205 nil)))
|
428
|
206
|
|
207 (add-hook 'pre-gc-hook 'truncate-command-history-for-gc)
|
|
208
|
|
209
|
|
210 ;;;; Object-oriented programming at its finest
|
|
211
|
|
212 ;; Now in src/print.c; used by Ferror_message_string and others
|
|
213 ;(defun display-error (error-object stream) ;(defgeneric report-condition ...)
|
|
214 ; "Display `error-object' on `stream' in a user-friendly way."
|
|
215 ; (funcall (or (let ((type (car-safe error-object)))
|
|
216 ; (catch 'error
|
|
217 ; (and (consp error-object)
|
|
218 ; (symbolp type)
|
|
219 ; ;;(stringp (get type 'error-message))
|
|
220 ; (consp (get type 'error-conditions))
|
|
221 ; (let ((tail (cdr error-object)))
|
|
222 ; (while (not (null tail))
|
|
223 ; (if (consp tail)
|
|
224 ; (setq tail (cdr tail))
|
|
225 ; (throw 'error nil)))
|
|
226 ; t)
|
|
227 ; ;; (check-type condition condition)
|
|
228 ; (get type 'error-conditions)
|
|
229 ; ;; Search class hierarchy
|
|
230 ; (let ((tail (get type 'error-conditions)))
|
|
231 ; (while (not (null tail))
|
|
232 ; (cond ((not (and (consp tail)
|
|
233 ; (symbolp (car tail))))
|
|
234 ; (throw 'error nil))
|
|
235 ; ((get (car tail) 'display-error)
|
|
236 ; (throw 'error (get (car tail)
|
|
237 ; 'display-error)))
|
|
238 ; (t
|
|
239 ; (setq tail (cdr tail)))))
|
|
240 ; ;; Default method
|
|
241 ; #'(lambda (error-object stream)
|
|
242 ; (let ((type (car error-object))
|
|
243 ; (tail (cdr error-object))
|
|
244 ; (first t)
|
|
245 ; (print-message-label 'error))
|
|
246 ; (if (eq type 'error)
|
|
247 ; (progn (princ (car tail) stream)
|
|
248 ; (setq tail (cdr tail)))
|
|
249 ; (princ (or (gettext (get type 'error-message)) type)
|
|
250 ; stream))
|
|
251 ; (while tail
|
|
252 ; (princ (if first ": " ", ") stream)
|
|
253 ; (prin1 (car tail) stream)
|
|
254 ; (setq tail (cdr tail)
|
|
255 ; first nil))))))))
|
|
256 ; #'(lambda (error-object stream)
|
|
257 ; (princ (gettext "Peculiar error ") stream)
|
|
258 ; (prin1 error-object stream)))
|
|
259 ; error-object stream))
|
|
260
|
|
261 (put 'file-error 'display-error
|
|
262 #'(lambda (error-object stream)
|
1346
|
263 (let ((type (car error-object))
|
|
264 (tail (cdr error-object))
|
|
265 (first t)
|
|
266 (print-message-label 'error))
|
|
267 (if (eq type 'file-error)
|
|
268 (progn (princ (car tail) stream)
|
|
269 (setq tail (cdr tail)))
|
|
270 (princ (or (gettext (get type 'error-message)) type)
|
|
271 stream))
|
|
272 (while tail
|
|
273 (princ (if first ": " ", ") stream)
|
|
274 (prin1 (car tail) stream)
|
|
275 (setq tail (cdr tail)
|
|
276 first nil)))))
|
428
|
277
|
|
278 (put 'undefined-keystroke-sequence 'display-error
|
|
279 #'(lambda (error-object stream)
|
|
280 (princ (key-description (car (cdr error-object))) stream)
|
|
281 ;; #### I18N3: doesn't localize properly.
|
|
282 (princ (gettext " not defined.") stream) ; doo dah, doo dah.
|
|
283 ))
|
|
284
|
|
285
|
|
286 (defcustom teach-extended-commands-p t
|
|
287 "*If true, then `\\[execute-extended-command]' will teach you keybindings.
|
|
288 Any time you execute a command with \\[execute-extended-command] which has a
|
|
289 shorter keybinding, you will be shown the alternate binding before the
|
|
290 command executes. There is a short pause after displaying the binding,
|
|
291 before executing it; the length can be controlled by
|
|
292 `teach-extended-commands-timeout'."
|
|
293 :type 'boolean
|
|
294 :group 'keyboard)
|
|
295
|
|
296 (defcustom teach-extended-commands-timeout 4
|
|
297 "*How long to pause after displaying a keybinding before executing.
|
|
298 The value is measured in seconds. This only applies if
|
|
299 `teach-extended-commands-p' is true."
|
|
300 :type 'number
|
|
301 :group 'keyboard)
|
|
302
|
|
303 ;That damn RMS went off and implemented something differently, after
|
|
304 ;we had already implemented it. We can't support both properly until
|
|
305 ;we have Lisp magic variables.
|
|
306 ;(defvar suggest-key-bindings t
|
|
307 ; "*FSFmacs equivalent of `teach-extended-commands-*'.
|
|
308 ;Provided for compatibility only.
|
|
309 ;Non-nil means show the equivalent key-binding when M-x command has one.
|
|
310 ;The value can be a length of time to show the message for.
|
|
311 ;If the value is non-nil and not a number, we wait 2 seconds.")
|
|
312 ;
|
|
313 ;(make-obsolete-variable 'suggest-key-bindings 'teach-extended-commands-p)
|
|
314
|
|
315 (defun execute-extended-command (prefix-arg)
|
|
316 "Read a command name from the minibuffer using 'completing-read'.
|
|
317 Then call the specified command using 'command-execute' and return its
|
|
318 return value. If the command asks for a prefix argument, supply the
|
|
319 value of the current raw prefix argument, or the value of PREFIX-ARG
|
|
320 when called from Lisp."
|
|
321 (interactive "P")
|
|
322 ;; Note: This doesn't hack "this-command-keys"
|
|
323 (let ((prefix-arg prefix-arg))
|
|
324 (setq this-command (read-command
|
|
325 ;; Note: this has the hard-wired
|
|
326 ;; "C-u" and "M-x" string bug in common
|
613
|
327 ;; with all Emacs's.
|
428
|
328 ;; (i.e. it prints C-u and M-x regardless of
|
|
329 ;; whether some other keys were actually bound
|
|
330 ;; to `execute-extended-command' and
|
|
331 ;; `universal-argument'.
|
|
332 (cond ((eq prefix-arg '-)
|
|
333 "- M-x ")
|
|
334 ((equal prefix-arg '(4))
|
|
335 "C-u M-x ")
|
|
336 ((integerp prefix-arg)
|
|
337 (format "%d M-x " prefix-arg))
|
|
338 ((and (consp prefix-arg)
|
|
339 (integerp (car prefix-arg)))
|
|
340 (format "%d M-x " (car prefix-arg)))
|
|
341 (t
|
|
342 "M-x ")))))
|
|
343
|
|
344 (if (and teach-extended-commands-p
|
|
345 (interactive-p))
|
|
346 ;; Remember the keys, run the command, and show the keys (if
|
|
347 ;; any). The funny variable names are a poor man's guarantee
|
|
348 ;; that we don't get tripped by this-command doing something
|
|
349 ;; funny. Quoth our forefathers: "We want lexical scope!"
|
|
350 (let ((_execute_command_keys_ (where-is-internal this-command))
|
|
351 (_execute_command_name_ this-command)) ; the name can change
|
|
352 (command-execute this-command t)
|
|
353 (when _execute_command_keys_
|
|
354 ;; Normally the region is adjusted in post_command_hook;
|
|
355 ;; however, it is not called until after we finish. It
|
|
356 ;; looks ugly for the region to get updated after the
|
|
357 ;; delays, so we do it now. The code below is a Lispified
|
|
358 ;; copy of code in event-stream.c:post_command_hook().
|
|
359 (if (and (not zmacs-region-stays)
|
|
360 (or (not (eq (selected-window) (minibuffer-window)))
|
|
361 (eq (zmacs-region-buffer) (current-buffer))))
|
|
362 (zmacs-deactivate-region)
|
|
363 (zmacs-update-region))
|
|
364 ;; Wait for a while, so the user can see a message printed,
|
|
365 ;; if any.
|
|
366 (when (sit-for 1)
|
|
367 (display-message
|
|
368 'no-log
|
|
369 (format (if (cdr _execute_command_keys_)
|
|
370 "Command `%s' is bound to keys: %s"
|
|
371 "Command `%s' is bound to key: %s")
|
|
372 _execute_command_name_
|
|
373 (sorted-key-descriptions _execute_command_keys_)))
|
|
374 (sit-for teach-extended-commands-timeout)
|
|
375 (clear-message 'no-log))))
|
|
376 ;; Else, just run the command.
|
|
377 (command-execute this-command t)))
|
|
378
|
|
379
|
|
380 ;;; C code calls this; the underscores in the variable names are to avoid
|
|
381 ;;; cluttering the specbind namespace (lexical scope! lexical scope!)
|
|
382 ;;; Putting this in Lisp instead of C slows kbd macros by 50%.
|
|
383 ;(defun command-execute (_command &optional _record-flag)
|
|
384 ; "Execute CMD as an editor command.
|
|
385 ;CMD must be a symbol that satisfies the `commandp' predicate.
|
|
386 ;Optional second arg RECORD-FLAG non-nil
|
|
387 ;means unconditionally put this command in `command-history'.
|
|
388 ;Otherwise, that is done only if an arg is read using the minibuffer."
|
|
389 ; (let ((_prefix prefix-arg)
|
|
390 ; (_cmd (indirect-function _command)))
|
|
391 ; (setq prefix-arg nil
|
|
392 ; this-command _command
|
|
393 ; current-prefix-arg _prefix
|
|
394 ; zmacs-region-stays nil)
|
|
395 ; ;; #### debug_on_next_call = 0;
|
|
396 ; (cond ((and (symbolp _command)
|
|
397 ; (get _command 'disabled))
|
|
398 ; (run-hooks disabled-command-hook))
|
|
399 ; ((or (stringp _cmd) (vectorp _cmd))
|
|
400 ; ;; If requested, place the macro in the command history.
|
|
401 ; ;; For other sorts of commands, call-interactively takes
|
|
402 ; ;; care of this.
|
|
403 ; (if _record-flag
|
|
404 ; (setq command-history
|
|
405 ; (cons (list 'execute-kbd-macro _cmd _prefix)
|
|
406 ; command-history)))
|
|
407 ; (execute-kbd-macro _cmd _prefix))
|
|
408 ; (t
|
|
409 ; (call-interactively _command _record-flag)))))
|
|
410
|
|
411 (defun y-or-n-p-minibuf (prompt)
|
|
412 "Ask user a \"y or n\" question. Return t if answer is \"y\".
|
|
413 Takes one argument, which is the string to display to ask the question.
|
|
414 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.
|
|
415 No confirmation of the answer is requested; a single character is enough.
|
|
416 Also accepts Space to mean yes, or Delete to mean no."
|
|
417 (save-excursion
|
|
418 (let* ((pre "")
|
|
419 (yn (gettext "(y or n) "))
|
|
420 ;; we need to translate the prompt ourselves because of the
|
|
421 ;; strange way we handle it.
|
|
422 (prompt (gettext prompt))
|
|
423 event)
|
|
424 (while (stringp yn)
|
|
425 (if (let ((cursor-in-echo-area t)
|
|
426 (inhibit-quit t))
|
|
427 (message "%s%s%s" pre prompt yn)
|
|
428 (setq event (next-command-event event))
|
|
429 (condition-case nil
|
|
430 (prog1
|
|
431 (or quit-flag (eq 'keyboard-quit (key-binding event)))
|
|
432 (setq quit-flag nil))
|
|
433 (wrong-type-argument t)))
|
|
434 (progn
|
|
435 (message "%s%s%s%s" pre prompt yn (single-key-description event))
|
|
436 (setq quit-flag nil)
|
|
437 (signal 'quit '())))
|
|
438 (let* ((keys (events-to-keys (vector event)))
|
|
439 (def (lookup-key query-replace-map keys)))
|
|
440 (cond ((eq def 'skip)
|
|
441 (message "%s%sNo" prompt yn)
|
|
442 (setq yn nil))
|
|
443 ((eq def 'act)
|
|
444 (message "%s%sYes" prompt yn)
|
|
445 (setq yn t))
|
|
446 ((eq def 'recenter)
|
|
447 (recenter))
|
|
448 ((or (eq def 'quit) (eq def 'exit-prefix))
|
|
449 (signal 'quit '()))
|
|
450 ((button-release-event-p event) ; ignore them
|
|
451 nil)
|
|
452 (t
|
|
453 (message "%s%s%s%s" pre prompt yn
|
|
454 (single-key-description event))
|
|
455 (ding nil 'y-or-n-p)
|
|
456 (discard-input)
|
|
457 (if (= (length pre) 0)
|
|
458 (setq pre (gettext "Please answer y or n. ")))))))
|
|
459 yn)))
|
|
460
|
|
461 (defun yes-or-no-p-minibuf (prompt)
|
|
462 "Ask user a yes-or-no question. Return t if answer is yes.
|
|
463 Takes one argument, which is the string to display to ask the question.
|
|
464 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.
|
|
465 The user must confirm the answer with RET,
|
|
466 and can edit it until it has been confirmed."
|
|
467 (save-excursion
|
|
468 (let ((p (concat (gettext prompt) (gettext "(yes or no) ")))
|
|
469 (ans ""))
|
|
470 (while (stringp ans)
|
|
471 (setq ans (downcase (read-string p nil t))) ;no history
|
|
472 (cond ((string-equal ans (gettext "yes"))
|
|
473 (setq ans t))
|
|
474 ((string-equal ans (gettext "no"))
|
|
475 (setq ans nil))
|
|
476 (t
|
|
477 (ding nil 'yes-or-no-p)
|
|
478 (discard-input)
|
|
479 (message "Please answer yes or no.")
|
|
480 (sleep-for 2))))
|
|
481 ans)))
|
|
482
|
442
|
483 (defun yes-or-no-p (prompt)
|
|
484 "Ask user a yes-or-no question. Return t if answer is yes.
|
|
485 The question is asked with a dialog box or the minibuffer, as appropriate.
|
|
486 Takes one argument, which is the string to display to ask the question.
|
|
487 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.
|
|
488 The user must confirm the answer with RET,
|
|
489 and can edit it until it as been confirmed."
|
|
490 (if (should-use-dialog-box-p)
|
|
491 (yes-or-no-p-dialog-box prompt)
|
|
492 (yes-or-no-p-minibuf prompt)))
|
|
493
|
|
494 (defun y-or-n-p (prompt)
|
|
495 "Ask user a \"y or n\" question. Return t if answer is \"y\".
|
|
496 Takes one argument, which is the string to display to ask the question.
|
|
497 The question is asked with a dialog box or the minibuffer, as appropriate.
|
|
498 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.
|
|
499 No confirmation of the answer is requested; a single character is enough.
|
|
500 Also accepts Space to mean yes, or Delete to mean no."
|
|
501 (if (should-use-dialog-box-p)
|
|
502 (yes-or-no-p-dialog-box prompt)
|
|
503 (y-or-n-p-minibuf prompt)))
|
|
504
|
428
|
505
|
|
506
|
|
507 (defun read-char ()
|
|
508 "Read a character from the command input (keyboard or macro).
|
|
509 If a mouse click or non-ASCII character is detected, an error is
|
|
510 signalled. The character typed is returned as an ASCII value. This
|
|
511 is most likely the wrong thing for you to be using: consider using
|
|
512 the `next-command-event' function instead."
|
|
513 (save-excursion
|
|
514 (let ((event (next-command-event)))
|
|
515 (or inhibit-quit
|
|
516 (and (event-matches-key-specifier-p event (quit-char))
|
|
517 (signal 'quit nil)))
|
|
518 (prog1 (or (event-to-character event)
|
|
519 ;; Kludge. If the event we read was a mouse-release,
|
|
520 ;; discard it and read the next one.
|
|
521 (if (button-release-event-p event)
|
|
522 (event-to-character (next-command-event event)))
|
|
523 (error "Key read has no ASCII equivalent %S" event))
|
|
524 ;; this is not necessary, but is marginally more efficient than GC.
|
|
525 (deallocate-event event)))))
|
|
526
|
|
527 (defun read-char-exclusive ()
|
|
528 "Read a character from the command input (keyboard or macro).
|
|
529 If a mouse click or non-ASCII character is detected, it is discarded.
|
|
530 The character typed is returned as an ASCII value. This is most likely
|
|
531 the wrong thing for you to be using: consider using the
|
|
532 `next-command-event' function instead."
|
|
533 (let (event ch)
|
|
534 (while (progn
|
|
535 (setq event (next-command-event))
|
|
536 (or inhibit-quit
|
|
537 (and (event-matches-key-specifier-p event (quit-char))
|
|
538 (signal 'quit nil)))
|
|
539 (setq ch (event-to-character event))
|
|
540 (deallocate-event event)
|
|
541 (null ch)))
|
|
542 ch))
|
|
543
|
1333
|
544 ;;;; Input and display facilities.
|
|
545
|
|
546 ;; BEGIN SYNCHED WITH FSF 21.2.
|
|
547
|
|
548 (defvar read-quoted-char-radix 8
|
|
549 "*Radix for \\[quoted-insert] and other uses of `read-quoted-char'.
|
|
550 Legitimate radix values are 8, 10 and 16.")
|
|
551
|
|
552 (custom-declare-variable-early
|
|
553 'read-quoted-char-radix 8
|
|
554 "*Radix for \\[quoted-insert] and other uses of `read-quoted-char'.
|
|
555 Legitimate radix values are 8, 10 and 16."
|
|
556 :type '(choice (const 8) (const 10) (const 16))
|
|
557 :group 'editing-basics)
|
|
558
|
428
|
559 (defun read-quoted-char (&optional prompt)
|
3341
|
560 ;; XEmacs change; description of the character code input
|
1333
|
561 "Like `read-char', but do not allow quitting.
|
3341
|
562
|
|
563 Also, if the first character read is a digit of base (the value of)
|
|
564 `read-quoted-char-radix', we read as many of such digits as are
|
|
565 typed and return a character with the corresponding Unicode code
|
3344
|
566 point. Any input that is not a digit (in the base used) terminates
|
|
567 the sequence. If the terminator is RET, it is discarded; any other
|
3341
|
568 terminator is used itself as input.
|
1333
|
569
|
|
570 The optional argument PROMPT specifies a string to use to prompt the user.
|
|
571 The variable `read-quoted-char-radix' controls which radix to use
|
|
572 for numeric input."
|
|
573 (let (;(message-log-max nil)
|
|
574 done (first t) (code 0) char event
|
428
|
575 (prompt (and prompt (gettext prompt)))
|
1333
|
576 )
|
|
577 (while (not done)
|
|
578 (let ((inhibit-quit first)
|
3341
|
579 ;; Don't let C-h get the help message--only help
|
|
580 ;; function keys.
|
|
581 ;; XEmacs: we don't support the help function keys as of
|
|
582 ;; 2006-04-16. GNU have a Vhelp_event_list in addition
|
|
583 ;; to help-char in src/keyboard.c, and it's only useful
|
|
584 ;; to set help-form while help-char is nil when that
|
|
585 ;; functionality is available.
|
428
|
586 (help-char nil)
|
3341
|
587 (help-form (format
|
428
|
588 "Type the special character you want to use,
|
3341
|
589 or the character code, base %d (the value of `read-quoted-char-radix')
|
1333
|
590 RET terminates the character code and is discarded;
|
3341
|
591 any other non-digit terminates the character code and is then used as input."
|
|
592 read-quoted-char-radix)))
|
428
|
593 (and prompt (display-message 'prompt (format "%s-" prompt)))
|
|
594 (setq event (next-command-event)
|
3474
|
595 ;; If event-to-character fails, this is fine, we handle that
|
|
596 ;; with the (null char) cond branch below.
|
|
597 char (event-to-character event))
|
428
|
598 (if inhibit-quit (setq quit-flag nil)))
|
1333
|
599 ;; Translate TAB key into control-I ASCII character, and so on.
|
|
600 (and char
|
|
601 (let ((translated (lookup-key function-key-map (vector char))))
|
|
602 (if (arrayp translated)
|
|
603 (setq char (aref translated 0)))))
|
|
604 (cond ((null char))
|
|
605 ((not (characterp char))
|
3196
|
606 ;; XEmacs change; event instead of char.
|
|
607 (setq unread-command-events (list event)
|
1333
|
608 done t))
|
|
609 ; ((/= (logand char ?\M-\^@) 0)
|
|
610 ; ;; Turn a meta-character into a character with the 0200 bit set.
|
|
611 ; (setq code (logior (logand char (lognot ?\M-\^@)) 128)
|
|
612 ; done t))
|
|
613 ((and (<= ?0 char) (< char (+ ?0 (min 10 read-quoted-char-radix))))
|
|
614 (setq code (+ (* code read-quoted-char-radix) (- char ?0)))
|
|
615 (and prompt (setq prompt (display-message 'prompt
|
|
616 (format "%s %c" prompt char)))))
|
|
617 ((and (<= ?a (downcase char))
|
|
618 (< (downcase char) (+ ?a -10 (min 26 read-quoted-char-radix))))
|
|
619 (setq code (+ (* code read-quoted-char-radix)
|
|
620 (+ 10 (- (downcase char) ?a))))
|
|
621 (and prompt (setq prompt (display-message 'prompt
|
|
622 (format "%s %c" prompt char)))))
|
|
623 ((and (not first) (eq char ?\C-m))
|
|
624 (setq done t))
|
|
625 ((not first)
|
3196
|
626 ;; XEmacs change; event instead of char.
|
|
627 (setq unread-command-events (list event)
|
428
|
628 done t))
|
1346
|
629 (t (setq code (char-to-int char)
|
1333
|
630 done t)))
|
|
631 (setq first nil))
|
3341
|
632 ;; XEmacs change; unicode-to-char instead of int-to-char
|
|
633 (unicode-to-char code)))
|
1333
|
634
|
|
635 ;; in passwd.el.
|
|
636 ; (defun read-passwd (prompt &optional confirm default)
|
|
637 ; "Read a password, prompting with PROMPT. Echo `.' for each character typed.
|
|
638 ; End with RET, LFD, or ESC. DEL or C-h rubs out. C-u kills line.
|
|
639 ; Optional argument CONFIRM, if non-nil, then read it twice to make sure.
|
|
640 ; Optional DEFAULT is a default password to use instead of empty input."
|
|
641 ; (if confirm
|
|
642 ; (let (success)
|
|
643 ; (while (not success)
|
|
644 ; (let ((first (read-passwd prompt nil default))
|
|
645 ; (second (read-passwd "Confirm password: " nil default)))
|
|
646 ; (if (equal first second)
|
|
647 ; (progn
|
|
648 ; (and (arrayp second) (fillarray second ?\0))
|
|
649 ; (setq success first))
|
|
650 ; (and (arrayp first) (fillarray first ?\0))
|
|
651 ; (and (arrayp second) (fillarray second ?\0))
|
|
652 ; (message "Password not repeated accurately; please start over")
|
|
653 ; (sit-for 1))))
|
|
654 ; success)
|
|
655 ; (let ((pass nil)
|
|
656 ; (c 0)
|
|
657 ; (echo-keystrokes 0)
|
|
658 ; (cursor-in-echo-area t))
|
|
659 ; (while (progn (message "%s%s"
|
|
660 ; prompt
|
|
661 ; (make-string (length pass) ?.))
|
|
662 ; (setq c (read-char-exclusive nil t))
|
|
663 ; (and (/= c ?\r) (/= c ?\n) (/= c ?\e)))
|
|
664 ; (clear-this-command-keys)
|
|
665 ; (if (= c ?\C-u)
|
|
666 ; (progn
|
|
667 ; (and (arrayp pass) (fillarray pass ?\0))
|
|
668 ; (setq pass ""))
|
|
669 ; (if (and (/= c ?\b) (/= c ?\177))
|
|
670 ; (let* ((new-char (char-to-string c))
|
|
671 ; (new-pass (concat pass new-char)))
|
|
672 ; (and (arrayp pass) (fillarray pass ?\0))
|
|
673 ; (fillarray new-char ?\0)
|
|
674 ; (setq c ?\0)
|
|
675 ; (setq pass new-pass))
|
|
676 ; (if (> (length pass) 0)
|
|
677 ; (let ((new-pass (substring pass 0 -1)))
|
|
678 ; (and (arrayp pass) (fillarray pass ?\0))
|
|
679 ; (setq pass new-pass))))))
|
|
680 ; (message nil)
|
|
681 ; (or pass default ""))))
|
|
682
|
|
683 ;; aliased to redraw-modeline, a built-in.
|
|
684 ; (defun force-mode-line-update (&optional all)
|
|
685 ; "Force the mode-line of the current buffer to be redisplayed.
|
|
686 ; With optional non-nil ALL, force redisplay of all mode-lines."
|
|
687 ; (if all (save-excursion (set-buffer (other-buffer))))
|
|
688 ; (set-buffer-modified-p (buffer-modified-p)))
|
428
|
689
|
|
690 (defun momentary-string-display (string pos &optional exit-char message)
|
|
691 "Momentarily display STRING in the buffer at POS.
|
|
692 Display remains until next character is typed.
|
|
693 If the char is EXIT-CHAR (optional third arg, default is SPC) it is swallowed;
|
|
694 otherwise it is then available as input (as a command if nothing else).
|
|
695 Display MESSAGE (optional fourth arg) in the echo area.
|
|
696 If MESSAGE is nil, instructions to type EXIT-CHAR are displayed there."
|
|
697 (or exit-char (setq exit-char ?\ ))
|
1333
|
698 (let ((inhibit-read-only t)
|
428
|
699 ;; Don't modify the undo list at all.
|
|
700 (buffer-undo-list t)
|
|
701 (modified (buffer-modified-p))
|
|
702 (name buffer-file-name)
|
|
703 insert-end)
|
|
704 (unwind-protect
|
|
705 (progn
|
|
706 (save-excursion
|
|
707 (goto-char pos)
|
|
708 ;; defeat file locking... don't try this at home, kids!
|
|
709 (setq buffer-file-name nil)
|
|
710 (insert-before-markers (gettext string))
|
|
711 (setq insert-end (point))
|
1333
|
712 ;; If the message end is off screen, recenter now.
|
|
713 (if (< (window-end nil t) insert-end)
|
428
|
714 (recenter (/ (window-height) 2)))
|
|
715 ;; If that pushed message start off the frame,
|
|
716 ;; scroll to start it at the top of the frame.
|
|
717 (move-to-window-line 0)
|
|
718 (if (> (point) pos)
|
|
719 (progn
|
|
720 (goto-char pos)
|
|
721 (recenter 0))))
|
|
722 (message (or message (gettext "Type %s to continue editing."))
|
|
723 (single-key-description exit-char))
|
|
724 (let ((event (save-excursion (next-command-event))))
|
|
725 (or (eq (event-to-character event) exit-char)
|
1333
|
726 (setq unread-command-events (list event)))))
|
428
|
727 (if insert-end
|
|
728 (save-excursion
|
|
729 (delete-region pos insert-end)))
|
|
730 (setq buffer-file-name name)
|
|
731 (set-buffer-modified-p modified))))
|
|
732
|
1333
|
733 ;; END SYNCHED WITH FSF 21.2.
|
|
734
|
428
|
735 ;;; cmdloop.el ends here
|