X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/937054f3bd6dd1af3fb14a5552c92d99d5d6949e..e1775344cd4f67baa168a3149870edb0cf6e5b67:/lisp/simple.el diff --git a/lisp/simple.el b/lisp/simple.el index 418cba339b..aba6583b34 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1,6 +1,6 @@ ;;; simple.el --- basic editing commands for Emacs -;; Copyright (C) 1985, 1986, 1987, 1993, 1994 Free Software Foundation, Inc. +;; Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc. ;; This file is part of GNU Emacs. @@ -15,8 +15,9 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to -;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. ;;; Commentary: @@ -26,11 +27,12 @@ ;;; Code: (defun newline (&optional arg) - "Insert a newline and move to left margin of the new line. + "Insert a newline, and move to left margin of the new line if it's blank. The newline is marked with the text-property `hard'. With arg, insert that many newlines. In Auto Fill mode, if no numeric arg, break the preceding line if it's long." (interactive "*P") + (barf-if-buffer-read-only) ;; Inserting a newline at the end of a line produces better redisplay in ;; try_window_id than inserting at the beginning of a line, and the textual ;; result is the same. So, if we're at beginning of line, pretend to be at @@ -38,14 +40,24 @@ In Auto Fill mode, if no numeric arg, break the preceding line if it's long." (let ((flag (and (not (bobp)) (bolp) (< (or (previous-property-change (point)) -2) - (- (point) 2))))) + (- (point) 2)))) + (was-page-start (and (bolp) + (looking-at page-delimiter))) + (beforepos (point))) (if flag (backward-char 1)) ;; Call self-insert so that auto-fill, abbrev expansion etc. happens. ;; Set last-command-char to tell self-insert what to insert. (let ((last-command-char ?\n) ;; Don't auto-fill if we have a numeric argument. - (auto-fill-function (if arg nil auto-fill-function))) - (self-insert-command (prefix-numeric-value arg))) + ;; Also not if flag is true (it would fill wrong line); + ;; there is no need to since we're at BOL. + (auto-fill-function (if (or arg flag) nil auto-fill-function))) + (unwind-protect + (self-insert-command (prefix-numeric-value arg)) + ;; If we get an error in self-insert-command, put point at right place. + (if flag (forward-char 1)))) + ;; If we did *not* get an error, cancel that forward-char. + (if flag (backward-char 1)) ;; Mark the newline(s) `hard'. (if use-hard-newlines (let* ((from (- (point) (if arg (prefix-numeric-value arg) 1))) @@ -55,26 +67,42 @@ In Auto Fill mode, if no numeric arg, break the preceding line if it's long." (if (and (listp sticky) (not (memq 'hard sticky))) (put-text-property from (point) 'rear-nonsticky (cons 'hard sticky))))) - (if flag (forward-char 1))) - (move-to-left-margin nil t) + ;; If the newline leaves the previous line blank, + ;; and we have a left margin, delete that from the blank line. + (or flag + (save-excursion + (goto-char beforepos) + (beginning-of-line) + (and (looking-at "[ \t]$") + (> (current-left-margin) 0) + (delete-region (point) (progn (end-of-line) (point)))))) + (if flag (forward-char 1)) + ;; Indent the line after the newline, except in one case: + ;; when we added the newline at the beginning of a line + ;; which starts a page. + (or was-page-start + (move-to-left-margin nil t))) nil) (defun open-line (arg) "Insert a newline and leave point before it. If there is a fill prefix and/or a left-margin, insert them on the new line -if the line would have been empty. +if the line would have been blank. With arg N, insert N newlines." (interactive "*p") (let* ((do-fill-prefix (and fill-prefix (bolp))) (do-left-margin (and (bolp) (> (current-left-margin) 0))) (loc (point))) + (newline arg) + (goto-char loc) (while (> arg 0) - (if do-left-margin (indent-to (current-left-margin))) - (if do-fill-prefix (insert-and-inherit fill-prefix)) - (newline 1) + (cond ((bolp) + (if do-left-margin (indent-to (current-left-margin))) + (if do-fill-prefix (insert-and-inherit fill-prefix)))) + (forward-line 1) (setq arg (1- arg))) - (goto-char loc)) - (end-of-line)) + (goto-char loc) + (end-of-line))) (defun split-line () "Split current line, moving portion beyond point vertically down." @@ -258,11 +286,7 @@ and KILLP is t if a prefix arg was specified." (delete-char 1))) (forward-char -1) (setq count (1- count))))) - (delete-backward-char arg killp) - ;; In overwrite mode, back over columns while clearing them out, - ;; unless at end of line. - (and overwrite-mode (not (eolp)) - (save-excursion (insert-char ?\ arg)))) + (delete-backward-char arg killp)) (defun zap-to-char (arg char) "Kill up to and including ARG'th occurrence of CHAR. @@ -346,14 +370,23 @@ that uses or sets the mark." (count-lines start end) (- end start))) (defun what-line () - "Print the current line number (in the buffer) of point." + "Print the current buffer line number and narrowed line number of point." (interactive) - (save-restriction - (widen) + (let ((opoint (point)) start) (save-excursion - (beginning-of-line) - (message "Line %d" - (1+ (count-lines 1 (point))))))) + (save-restriction + (goto-char (point-min)) + (widen) + (beginning-of-line) + (setq start (point)) + (goto-char opoint) + (beginning-of-line) + (if (/= start 1) + (message "line %d (narrowed line %d)" + (1+ (count-lines 1 (point))) + (1+ (count-lines start (point)))) + (message "Line %d" (1+ (count-lines 1 (point))))))))) + (defun count-lines (start end) "Return number of lines between START and END. @@ -441,7 +474,7 @@ the minibuffer, then read and evaluate the result." read-expression-map t '(command-history . 1)))) ;; If command was added to command-history as a string, - ;; get rid of that. We want only evallable expressions there. + ;; get rid of that. We want only evaluable expressions there. (if (stringp (car command-history)) (setq command-history (cdr command-history))) @@ -474,7 +507,7 @@ to get different commands to edit and resubmit." (cons 'command-history arg)))) ;; If command was added to command-history as a string, - ;; get rid of that. We want only evallable expressions there. + ;; get rid of that. We want only evaluable expressions there. (if (stringp (car command-history)) (setq command-history (cdr command-history))) @@ -542,8 +575,9 @@ If N is negative, find the next or Nth next match." 'minibuffer-history-search-history))) ;; Use the last regexp specified, by default, if input is empty. (list (if (string= regexp "") - (setcar minibuffer-history-search-history - (nth 1 minibuffer-history-search-history)) + (if minibuffer-history-search-history + (car minibuffer-history-search-history) + (error "No previous history search regexp")) regexp) (prefix-numeric-value current-prefix-arg)))) (let ((history (symbol-value minibuffer-history-variable)) @@ -712,8 +746,18 @@ then call `undo-more' one or more times to undo them." (defun shell-command (command &optional output-buffer) "Execute string COMMAND in inferior shell; display output, if any. + If COMMAND ends in ampersand, execute it asynchronously. -The output appears in the buffer `*Shell Command*'. +The output appears in the buffer `*Async Shell Command*'. +That buffer is in shell mode. + +Otherwise, COMMAND is executed synchronously. The output appears in the +buffer `*Shell Command Output*'. +If the output is one line, it is displayed in the echo area *as well*, +but it is nonetheless available in buffer `*Shell Command Output*', +even though that buffer is not automatically displayed. +If there is no output, or if output is inserted in the current buffer, +then `*Shell Command Output*' is deleted. The optional second argument OUTPUT-BUFFER, if non-nil, says to put the output in some other buffer. @@ -724,30 +768,36 @@ In either case, the output is inserted after point (leaving mark after it)." (interactive (list (read-from-minibuffer "Shell command: " nil nil nil 'shell-command-history) current-prefix-arg)) - (if (and output-buffer - (not (or (bufferp output-buffer) (stringp output-buffer)))) - (progn (barf-if-buffer-read-only) - (push-mark) - ;; We do not use -f for csh; we will not support broken use of - ;; .cshrcs. Even the BSD csh manual says to use - ;; "if ($?prompt) exit" before things which are not useful - ;; non-interactively. Besides, if someone wants their other - ;; aliases for shell commands then they can still have them. - (call-process shell-file-name nil t nil - shell-command-switch command) - ;; This is like exchange-point-and-mark, but doesn't activate the mark. - ;; It is cleaner to avoid activation, even though the command - ;; loop would deactivate the mark because we inserted text. - (goto-char (prog1 (mark t) - (set-marker (mark-marker) (point) - (current-buffer))))) - ;; Preserve the match data in case called from a program. - (let ((data (match-data))) - (unwind-protect + ;; Look for a handler in case default-directory is a remote file name. + (let ((handler + (find-file-name-handler (directory-file-name default-directory) + 'shell-command))) + (if handler + (funcall handler 'shell-command command output-buffer) + (if (and output-buffer + (not (or (bufferp output-buffer) (stringp output-buffer)))) + (progn (barf-if-buffer-read-only) + (push-mark) + ;; We do not use -f for csh; we will not support broken use of + ;; .cshrcs. Even the BSD csh manual says to use + ;; "if ($?prompt) exit" before things which are not useful + ;; non-interactively. Besides, if someone wants their other + ;; aliases for shell commands then they can still have them. + (call-process shell-file-name nil t nil + shell-command-switch command) + ;; This is like exchange-point-and-mark, but doesn't + ;; activate the mark. It is cleaner to avoid activation, + ;; even though the command loop would deactivate the mark + ;; because we inserted text. + (goto-char (prog1 (mark t) + (set-marker (mark-marker) (point) + (current-buffer))))) + ;; Preserve the match data in case called from a program. + (save-match-data (if (string-match "[ \t]*&[ \t]*$" command) ;; Command ending with ampersand means asynchronous. (let ((buffer (get-buffer-create - (or output-buffer "*Shell-Command*"))) + (or output-buffer "*Async Shell Command*"))) (directory default-directory) proc) ;; Remove the ampersand. @@ -764,51 +814,22 @@ In either case, the output is inserted after point (leaving mark after it)." (erase-buffer) (display-buffer buffer) (setq default-directory directory) - (setq proc (start-process "Shell" buffer - shell-file-name + (setq proc (start-process "Shell" buffer shell-file-name shell-command-switch command)) (setq mode-line-process '(":%s")) + (require 'shell) (shell-mode) (set-process-sentinel proc 'shell-command-sentinel) - (set-process-filter proc 'shell-command-filter) )) - (shell-command-on-region (point) (point) command nil)) - (store-match-data data))))) + (shell-command-on-region (point) (point) command nil) + )))))) ;; We have a sentinel to prevent insertion of a termination message ;; in the buffer itself. (defun shell-command-sentinel (process signal) - (if (and (memq (process-status process) '(exit signal)) - (buffer-name (process-buffer process))) - (progn - (message "%s: %s." - (car (cdr (cdr (process-command process)))) - (substring signal 0 -1)) - (save-excursion - (set-buffer (process-buffer process)) - (setq mode-line-process nil)) - (delete-process process)))) - -(defun shell-command-filter (proc string) - ;; Do save-excursion by hand so that we can leave point numerically unchanged - ;; despite an insertion immediately after it. - (let* ((obuf (current-buffer)) - (buffer (process-buffer proc)) - opoint - (window (get-buffer-window buffer)) - (pos (window-start window))) - (unwind-protect - (progn - (set-buffer buffer) - (or (= (point) (point-max)) - (setq opoint (point))) - (goto-char (point-max)) - (insert-before-markers string)) - ;; insert-before-markers moved this marker: set it back. - (set-window-start window pos) - ;; Finish our save-excursion. - (if opoint - (goto-char opoint)) - (set-buffer obuf)))) + (if (memq (process-status process) '(exit signal)) + (message "%s: %s." + (car (cdr (cdr (process-command process)))) + (substring signal 0 -1)))) (defun shell-command-on-region (start end command &optional output-buffer replace) @@ -839,15 +860,18 @@ In either case, the output is inserted after point (leaving mark after it)." (read-from-minibuffer "Shell command on region: " nil nil nil 'shell-command-history))) + ;; call-interactively recognizes region-beginning and + ;; region-end specially, leaving them in the history. (list (region-beginning) (region-end) string current-prefix-arg current-prefix-arg))) (if (or replace (and output-buffer - (not (or (bufferp output-buffer) (stringp output-buffer))))) + (not (or (bufferp output-buffer) (stringp output-buffer)))) + (equal (buffer-name (current-buffer)) "*Shell Command Output*")) ;; Replace specified region with output from command. - (let ((swap (and replace (< (point) (mark))))) + (let ((swap (and replace (< start end)))) ;; Don't muck with mark unless REPLACE says we should. (goto-char start) (and replace (push-mark)) @@ -869,8 +893,8 @@ In either case, the output is inserted after point (leaving mark after it)." ;; delete everything but the specified region, ;; then replace that region with the output. (progn (setq buffer-read-only nil) - (delete-region end (point-max)) - (delete-region (point-min) start) + (delete-region (max start end) (point-max)) + (delete-region (point-min) (min start end)) (call-process-region (point-min) (point-max) shell-file-name t t nil shell-command-switch command) @@ -902,7 +926,107 @@ In either case, the output is inserted after point (leaving mark after it)." (buffer-substring (point) (progn (end-of-line) (point)))))) (t - (set-window-start (display-buffer buffer) 1)))))))) + (save-excursion + (set-buffer buffer) + (goto-char (point-min))) + (display-buffer buffer)))))))) + +(defconst universal-argument-map + (let ((map (make-sparse-keymap))) + (define-key map [t] 'universal-argument-other-key) + (define-key map (vector meta-prefix-char t) 'universal-argument-other-key) + (define-key map [switch-frame] nil) + (define-key map [?\C-u] 'universal-argument-more) + (define-key map [?-] 'universal-argument-minus) + (define-key map [?0] 'digit-argument) + (define-key map [?1] 'digit-argument) + (define-key map [?2] 'digit-argument) + (define-key map [?3] 'digit-argument) + (define-key map [?4] 'digit-argument) + (define-key map [?5] 'digit-argument) + (define-key map [?6] 'digit-argument) + (define-key map [?7] 'digit-argument) + (define-key map [?8] 'digit-argument) + (define-key map [?9] 'digit-argument) + map) + "Keymap used while processing \\[universal-argument].") + +(defvar universal-argument-num-events nil + "Number of argument-specifying events read by `universal-argument'. +`universal-argument-other-key' uses this to discard those events +from (this-command-keys), and reread only the final command.") + +(defun universal-argument () + "Begin a numeric argument for the following command. +Digits or minus sign following \\[universal-argument] make up the numeric argument. +\\[universal-argument] following the digits or minus sign ends the argument. +\\[universal-argument] without digits or minus sign provides 4 as argument. +Repeating \\[universal-argument] without digits or minus sign + multiplies the argument by 4 each time." + (interactive) + (setq prefix-arg (list 4)) + (setq universal-argument-num-events (length (this-command-keys))) + (setq overriding-terminal-local-map universal-argument-map)) + +;; A subsequent C-u means to multiply the factor by 4 if we've typed +;; nothing but C-u's; otherwise it means to terminate the prefix arg. +(defun universal-argument-more (arg) + (interactive "P") + (if (consp arg) + (setq prefix-arg (list (* 4 (car arg)))) + (setq prefix-arg arg) + (setq overriding-terminal-local-map nil)) + (setq universal-argument-num-events (length (this-command-keys)))) + +(defun negative-argument (arg) + "Begin a negative numeric argument for the next command. +\\[universal-argument] following digits or minus sign ends the argument." + (interactive "P") + (cond ((integerp arg) + (setq prefix-arg (- arg))) + ((eq arg '-) + (setq prefix-arg nil)) + (t + (setq prefix-arg '-))) + (setq universal-argument-num-events (length (this-command-keys))) + (setq overriding-terminal-local-map universal-argument-map)) + +(defun digit-argument (arg) + "Part of the numeric argument for the next command. +\\[universal-argument] following digits or minus sign ends the argument." + (interactive "P") + (let ((digit (- (logand last-command-char ?\177) ?0))) + (cond ((integerp arg) + (setq prefix-arg (+ (* arg 10) + (if (< arg 0) (- digit) digit)))) + ((eq arg '-) + ;; Treat -0 as just -, so that -01 will work. + (setq prefix-arg (if (zerop digit) '- (- digit)))) + (t + (setq prefix-arg digit)))) + (setq universal-argument-num-events (length (this-command-keys))) + (setq overriding-terminal-local-map universal-argument-map)) + +;; For backward compatibility, minus with no modifiers is an ordinary +;; command if digits have already been entered. +(defun universal-argument-minus (arg) + (interactive "P") + (if (integerp arg) + (universal-argument-other-key arg) + (negative-argument arg))) + +;; Anything else terminates the argument and is left in the queue to be +;; executed as a command. +(defun universal-argument-other-key (arg) + (interactive "P") + (setq prefix-arg arg) + (let* ((key (this-command-keys)) + (keylist (listify-key-sequence key))) + (setq unread-command-events + (append (nthcdr universal-argument-num-events keylist) + unread-command-events))) + (reset-this-command-lengths) + (setq overriding-terminal-local-map nil)) (defun forward-to-indentation (arg) "Move forward ARG lines and position at first nonblank character." @@ -1018,7 +1142,7 @@ the front of the kill ring, rather than being added to the list." (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))) (setq kill-ring-yank-pointer kill-ring) (if interprogram-cut-function - (funcall interprogram-cut-function string t))) + (funcall interprogram-cut-function string (not replace)))) (defun kill-append (string before-p) "Append STRING to the end of the latest kill in the kill ring. @@ -1063,6 +1187,10 @@ yanking point; just return the Nth kill forward." (defvar kill-read-only-ok nil "*Non-nil means don't signal an error for killing read-only text.") +(put 'text-read-only 'error-conditions + '(text-read-only buffer-read-only error)) +(put 'text-read-only 'error-message "Text is read-only") + (defun kill-region (beg end) "Kill between point and mark. The text is deleted but saved in the kill ring. @@ -1092,7 +1220,10 @@ to make one entry in the kill ring." (if kill-read-only-ok (message "Read only text copied to kill ring") (setq this-command 'kill-region) - (barf-if-buffer-read-only))) + ;; Signal an error if the buffer is read-only. + (barf-if-buffer-read-only) + ;; If the buffer isn't read-only, the text is. + (signal 'text-read-only (list (current-buffer))))) ;; In certain cases, we can arrange for the undo list and the kill ;; ring to share the same string object. This code does that. @@ -1194,7 +1325,8 @@ comes the newest one." (if (not (eq last-command 'yank)) (error "Previous command was not a yank")) (setq this-command 'yank) - (let ((before (< (point) (mark t)))) + (let ((inhibit-read-only t) + (before (< (point) (mark t)))) (delete-region (point) (mark t)) (set-marker (mark-marker) (point) (current-buffer)) (insert (current-kill arg)) @@ -1244,10 +1376,15 @@ With argument, rotate that many kills forward (or backward, if negative)." "Insert after point the contents of BUFFER. Puts mark after the inserted text. BUFFER may be a buffer or a buffer name." - (interactive (list (progn (barf-if-buffer-read-only) - (read-buffer "Insert buffer: " - (other-buffer (current-buffer) t) - t)))) + (interactive + (list + (progn + (barf-if-buffer-read-only) + (read-buffer "Insert buffer: " + (if (eq (selected-window) (next-window (selected-window))) + (other-buffer (current-buffer)) + (window-buffer (next-window (selected-window)))) + t)))) (or (bufferp buffer) (setq buffer (get-buffer buffer))) (let (start end newmark) @@ -1304,13 +1441,6 @@ START and END specify the portion of the current buffer to be copied." (save-excursion (insert-buffer-substring oldbuf start end))))) -(defvar mark-even-if-inactive nil - "*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.") - (put 'mark-inactive 'error-conditions '(mark-inactive error)) (put 'mark-inactive 'error-message "The mark is not active now") @@ -1430,7 +1560,7 @@ In Transient Mark mode, this does not activate the mark." (move-marker (car (nthcdr global-mark-ring-max global-mark-ring)) nil) (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil)))) - (or nomsg executing-macro (> (minibuffer-depth) 0) + (or nomsg executing-kbd-macro (> (minibuffer-depth) 0) (message "Mark set")) (if (or activate (not transient-mark-mode)) (set-mark (mark t))) @@ -1507,8 +1637,7 @@ column, or at the end of the line if it is not long enough. If there is no line in the buffer after this one, behavior depends on the value of `next-line-add-newlines'. If non-nil, it inserts a newline character to create a line, and moves the cursor to that line. Otherwise it moves the -cursor to the end of the buffer (if already at the end of the buffer, an error -is signaled). +cursor to the end of the buffer. The command \\[set-goal-column] can be used to create a semipermanent goal column to which this command always moves. @@ -1573,66 +1702,83 @@ When the `track-eol' feature is doing its job, the value is 9999.") "*Non-nil means \\[next-line] and \\[previous-line] ignore invisible lines. Outline mode sets this.") +;; This is the guts of next-line and previous-line. +;; Arg says how many lines to move. (defun line-move (arg) - (if (not (or (eq last-command 'next-line) - (eq last-command 'previous-line))) - (setq temporary-goal-column - (if (and track-eol (eolp) - ;; Don't count beg of empty line as end of line - ;; unless we just did explicit end-of-line. - (or (not (bolp)) (eq last-command 'end-of-line))) - 9999 - (current-column)))) - (if (and (not (integerp selective-display)) - (not line-move-ignore-invisible)) - ;; Use just newline characters. - (or (if (> arg 0) - (progn (if (> arg 1) (forward-line (1- arg))) - ;; This way of moving forward ARG lines - ;; verifies that we have a newline after the last one. - ;; It doesn't get confused by intangible text. - (end-of-line) - (zerop (forward-line 1))) - (and (zerop (forward-line arg)) - (bolp))) - (signal (if (< arg 0) - 'beginning-of-buffer - 'end-of-buffer) - nil)) - ;; Move by arg lines, but ignore invisible ones. - (while (> arg 0) - (end-of-line) - (and (zerop (vertical-motion 1)) - (signal 'end-of-buffer nil)) - ;; If the following character is currently invisible, - ;; skip all characters with that same `invisible' property value. - (while (and (not (eobp)) - (let ((prop - (get-char-property (point) 'invisible))) - (if (eq buffer-invisibility-spec t) - prop - (or (memq prop buffer-invisibility-spec) - (assq prop buffer-invisibility-spec))))) - (if (get-text-property (point) 'invisible) - (goto-char (next-single-property-change (point) 'invisible)) - (goto-char (next-overlay-change (point))))) - (setq arg (1- arg))) - (while (< arg 0) - (beginning-of-line) - (and (zerop (vertical-motion -1)) - (signal 'beginning-of-buffer nil)) - (while (and (not (bobp)) - (let ((prop - (get-char-property (1- (point)) 'invisible))) - (if (eq buffer-invisibility-spec t) - prop - (or (memq prop buffer-invisibility-spec) - (assq prop buffer-invisibility-spec))))) - (if (get-text-property (1- (point)) 'invisible) - (goto-char (previous-single-property-change (point) 'invisible)) - (goto-char (previous-overlay-change (point))))) - (setq arg (1+ arg)))) - (move-to-column (or goal-column temporary-goal-column)) + ;; Don't run any point-motion hooks, and disregard intangibility, + ;; for intermediate positions. + (let ((inhibit-point-motion-hooks t) + (opoint (point)) + new) + (unwind-protect + (progn + (if (not (or (eq last-command 'next-line) + (eq last-command 'previous-line))) + (setq temporary-goal-column + (if (and track-eol (eolp) + ;; Don't count beg of empty line as end of line + ;; unless we just did explicit end-of-line. + (or (not (bolp)) (eq last-command 'end-of-line))) + 9999 + (current-column)))) + (if (and (not (integerp selective-display)) + (not line-move-ignore-invisible)) + ;; Use just newline characters. + (or (if (> arg 0) + (progn (if (> arg 1) (forward-line (1- arg))) + ;; This way of moving forward ARG lines + ;; verifies that we have a newline after the last one. + ;; It doesn't get confused by intangible text. + (end-of-line) + (zerop (forward-line 1))) + (and (zerop (forward-line arg)) + (bolp))) + (signal (if (< arg 0) + 'beginning-of-buffer + 'end-of-buffer) + nil)) + ;; Move by arg lines, but ignore invisible ones. + (while (> arg 0) + (end-of-line) + (and (zerop (vertical-motion 1)) + (signal 'end-of-buffer nil)) + ;; If the following character is currently invisible, + ;; skip all characters with that same `invisible' property value. + (while (and (not (eobp)) + (let ((prop + (get-char-property (point) 'invisible))) + (if (eq buffer-invisibility-spec t) + prop + (or (memq prop buffer-invisibility-spec) + (assq prop buffer-invisibility-spec))))) + (if (get-text-property (point) 'invisible) + (goto-char (next-single-property-change (point) 'invisible)) + (goto-char (next-overlay-change (point))))) + (setq arg (1- arg))) + (while (< arg 0) + (beginning-of-line) + (and (zerop (vertical-motion -1)) + (signal 'beginning-of-buffer nil)) + (while (and (not (bobp)) + (let ((prop + (get-char-property (1- (point)) 'invisible))) + (if (eq buffer-invisibility-spec t) + prop + (or (memq prop buffer-invisibility-spec) + (assq prop buffer-invisibility-spec))))) + (if (get-text-property (1- (point)) 'invisible) + (goto-char (previous-single-property-change (point) 'invisible)) + (goto-char (previous-overlay-change (point))))) + (setq arg (1+ arg)))) + (move-to-column (or goal-column temporary-goal-column))) + ;; Remember where we moved to, go back home, + ;; then do the motion over again + ;; in just one step, with intangibility and point-motion hooks + ;; enabled this time. + (setq new (point)) + (goto-char opoint) + (setq inhibit-point-motion-hooks nil) + (goto-char new))) nil) ;;; Many people have said they rarely use this feature, and often type @@ -1762,7 +1908,8 @@ If this is zero, point is always centered after it moves off frame.") ;; (hscroll-point-visible)) (defun scroll-other-window-down (lines) - "Scroll the \"other window\" down." + "Scroll the \"other window\" down. +For more details, see the documentation for `scroll-other-window'." (interactive "P") (scroll-other-window ;; Just invert the argument's meaning. @@ -1770,6 +1917,7 @@ If this is zero, point is always centered after it moves off frame.") (if (eq lines '-) nil (if (null lines) '- (- (prefix-numeric-value lines)))))) +(define-key esc-map [?\C-\S-v] 'scroll-other-window-down) (defun beginning-of-buffer-other-window (arg) "Move point to the beginning of the buffer in the other window. @@ -1944,7 +2092,6 @@ If nil, use `comment-end' instead.") (defun indent-for-comment () "Indent this line's comment to comment column, or insert an empty comment." (interactive "*") - (beginning-of-line 1) (let* ((empty (save-excursion (beginning-of-line) (looking-at "[ \t]*$"))) (starter (or (and empty block-comment-start) comment-start)) @@ -1953,6 +2100,7 @@ If nil, use `comment-end' instead.") (error "No comment syntax defined") (let* ((eolpos (save-excursion (end-of-line) (point))) cpos indent begpos) + (beginning-of-line) (if (re-search-forward comment-start-skip eolpos 'move) (progn (setq cpos (point-marker)) ;; Find the start of the comment delimiter. @@ -2185,12 +2333,16 @@ Setting this variable automatically makes it local to the current buffer.") (defconst auto-fill-inhibit-regexp nil "*Regexp to match lines which should not be auto-filled.") +;; This function is the auto-fill-function of a buffer +;; when Auto-Fill mode is enabled. +;; It returns t if it really did any work. (defun do-auto-fill () - (let (fc justify bol give-up) + (let (fc justify bol give-up + (fill-prefix fill-prefix)) (if (or (not (setq justify (current-justification))) - (and (setq fc (current-fill-column)) ; make sure this gets set - (eq justify 'left) - (<= (current-column) (setq fc (current-fill-column)))) + (null (setq fc (current-fill-column))) + (and (eq justify 'left) + (<= (current-column) fc)) (save-excursion (beginning-of-line) (setq bol (point)) (and auto-fill-inhibit-regexp @@ -2198,68 +2350,83 @@ Setting this variable automatically makes it local to the current buffer.") nil ;; Auto-filling not required (if (memq justify '(full center right)) (save-excursion (unjustify-current-line))) + + ;; Choose a fill-prefix automatically. + (if (and adaptive-fill-mode + (or (null fill-prefix) (string= fill-prefix ""))) + (let ((prefix + (fill-context-prefix + (save-excursion (backward-paragraph 1) (point)) + (save-excursion (forward-paragraph 1) (point)) + ;; Don't accept a non-whitespace fill prefix + ;; from the first line of a paragraph. + "^[ \t]*$"))) + (and prefix (not (equal prefix "")) + (setq fill-prefix prefix)))) + (while (and (not give-up) (> (current-column) fc)) - ;; Determine where to split the line. - (let ((fill-point - (let ((opoint (point)) - bounce - (first t)) - (save-excursion - (move-to-column (1+ fc)) - ;; Move back to a word boundary. - (while (or first - ;; If this is after period and a single space, - ;; move back once more--we don't want to break - ;; the line there and make it look like a - ;; sentence end. - (and (not (bobp)) - (not bounce) - sentence-end-double-space - (save-excursion (forward-char -1) - (and (looking-at "\\. ") - (not (looking-at "\\. ")))))) - (setq first nil) - (skip-chars-backward "^ \t\n") - ;; If we find nowhere on the line to break it, - ;; break after one word. Set bounce to t - ;; so we will not keep going in this while loop. - (if (bolp) - (progn - (re-search-forward "[ \t]" opoint t) - (setq bounce t))) - (skip-chars-backward " \t")) - ;; Let fill-point be set to the place where we end up. - (point))))) - ;; If that place is not the beginning of the line, - ;; break the line there. - (if (save-excursion - (goto-char fill-point) - (not (bolp))) - (let ((prev-column (current-column))) - ;; If point is at the fill-point, do not `save-excursion'. - ;; Otherwise, if a comment prefix or fill-prefix is inserted, - ;; point will end up before it rather than after it. - (if (save-excursion - (skip-chars-backward " \t") - (= (point) fill-point)) - (indent-new-comment-line t) - (save-excursion - (goto-char fill-point) - (indent-new-comment-line t))) - ;; Now do justification, if required - (if (not (eq justify 'left)) - (save-excursion - (end-of-line 0) - (justify-current-line justify nil t))) - ;; If making the new line didn't reduce the hpos of - ;; the end of the line, then give up now; - ;; trying again will not help. - (if (>= (current-column) prev-column) - (setq give-up t))) - ;; No place to break => stop trying. - (setq give-up t)))) + ;; Determine where to split the line. + (let ((fill-point + (let ((opoint (point)) + bounce + (first t)) + (save-excursion + (move-to-column (1+ fc)) + ;; Move back to a word boundary. + (while (or first + ;; If this is after period and a single space, + ;; move back once more--we don't want to break + ;; the line there and make it look like a + ;; sentence end. + (and (not (bobp)) + (not bounce) + sentence-end-double-space + (save-excursion (forward-char -1) + (and (looking-at "\\. ") + (not (looking-at "\\. ")))))) + (setq first nil) + (skip-chars-backward "^ \t\n") + ;; If we find nowhere on the line to break it, + ;; break after one word. Set bounce to t + ;; so we will not keep going in this while loop. + (if (bolp) + (progn + (re-search-forward "[ \t]" opoint t) + (setq bounce t))) + (skip-chars-backward " \t")) + ;; Let fill-point be set to the place where we end up. + (point))))) + ;; If that place is not the beginning of the line, + ;; break the line there. + (if (save-excursion + (goto-char fill-point) + (not (bolp))) + (let ((prev-column (current-column))) + ;; If point is at the fill-point, do not `save-excursion'. + ;; Otherwise, if a comment prefix or fill-prefix is inserted, + ;; point will end up before it rather than after it. + (if (save-excursion + (skip-chars-backward " \t") + (= (point) fill-point)) + (indent-new-comment-line t) + (save-excursion + (goto-char fill-point) + (indent-new-comment-line t))) + ;; Now do justification, if required + (if (not (eq justify 'left)) + (save-excursion + (end-of-line 0) + (justify-current-line justify nil t))) + ;; If making the new line didn't reduce the hpos of + ;; the end of the line, then give up now; + ;; trying again will not help. + (if (>= (current-column) prev-column) + (setq give-up t))) + ;; No place to break => stop trying. + (setq give-up t)))) ;; justify last line - (justify-current-line justify t t)))) + (justify-current-line justify t t) + t))) (defun auto-fill-mode (&optional arg) "Toggle auto-fill mode. @@ -2273,8 +2440,7 @@ automatically breaks the line at a previous space." (> (prefix-numeric-value arg) 0)) 'do-auto-fill nil)) - ;; update mode-line - (set-buffer-modified-p (buffer-modified-p)))) + (force-mode-line-update))) ;; This holds a document string used to document auto-fill-mode. (defun auto-fill-function () @@ -2286,10 +2452,16 @@ automatically breaks the line at a previous space." (auto-fill-mode 1)) (defun set-fill-column (arg) - "Set `fill-column' to current column, or to argument if given. -The variable `fill-column' has a separate value for each buffer." + "Set `fill-column' to specified argument. +Just \\[universal-argument] as argument means to use the current column." (interactive "P") - (setq fill-column (if (integerp arg) arg (current-column))) + (cond ((integerp arg) + (setq fill-column arg)) + ((consp arg) + (setq fill-column (current-column))) + ;; Disallow missing argument; it's probably a typo for C-x C-f. + (t + (error "set-fill-column requires an explicit argument"))) (message "fill-column set to %d" fill-column)) (defconst comment-multi-line nil @@ -2306,6 +2478,9 @@ This command is intended for styles where you write a comment per line, starting a new comment (and terminating it if necessary) on each line. If you want to continue one comment across several lines, use \\[newline-and-indent]. +If a fill column is specified, it overrides the use of the comment column +or comment indentation. + The inserted newline is marked hard if `use-hard-newlines' is true, unless optional argument SOFT is non-nil." (interactive) @@ -2315,59 +2490,60 @@ unless optional argument SOFT is non-nil." (progn (skip-chars-forward " \t") (point))) (if soft (insert-and-inherit ?\n) (newline 1)) - (if (not comment-multi-line) - (save-excursion - (if (and comment-start-skip - (let ((opoint (point))) - (forward-line -1) - (re-search-forward comment-start-skip opoint t))) - ;; The old line is a comment. - ;; Set WIN to the pos of the comment-start. - ;; But if the comment is empty, look at preceding lines - ;; to find one that has a nonempty comment. - - ;; If comment-start-skip contains a \(...\) pair, - ;; the real comment delimiter starts at the end of that pair. - (let ((win (or (match-end 1) (match-beginning 0)))) - (while (and (eolp) (not (bobp)) - (let (opoint) - (beginning-of-line) - (setq opoint (point)) - (forward-line -1) - (re-search-forward comment-start-skip opoint t))) - (setq win (or (match-end 1) (match-beginning 0)))) - ;; Indent this line like what we found. - (goto-char win) - (setq comcol (current-column)) - (setq comstart - (buffer-substring (point) (match-end 0))))))) - (if comcol - (let ((comment-column comcol) - (comment-start comstart) - (comment-end comment-end)) - (and comment-end (not (equal comment-end "")) -; (if (not comment-multi-line) - (progn - (forward-char -1) - (insert comment-end) - (forward-char 1)) -; (setq comment-column (+ comment-column (length comment-start)) -; comment-start "") -; ) - ) - (if (not (eolp)) - (setq comment-end "")) - (insert-and-inherit ?\n) - (forward-char -1) - (indent-for-comment) + (if fill-prefix + (progn + (indent-to-left-margin) + (insert-and-inherit fill-prefix)) + (if (not comment-multi-line) (save-excursion - ;; Make sure we delete the newline inserted above. - (end-of-line) - (delete-char 1))) - (if (null fill-prefix) - (indent-according-to-mode) - (indent-to-left-margin) - (insert-and-inherit fill-prefix))))) + (if (and comment-start-skip + (let ((opoint (point))) + (forward-line -1) + (re-search-forward comment-start-skip opoint t))) + ;; The old line is a comment. + ;; Set WIN to the pos of the comment-start. + ;; But if the comment is empty, look at preceding lines + ;; to find one that has a nonempty comment. + + ;; If comment-start-skip contains a \(...\) pair, + ;; the real comment delimiter starts at the end of that pair. + (let ((win (or (match-end 1) (match-beginning 0)))) + (while (and (eolp) (not (bobp)) + (let (opoint) + (beginning-of-line) + (setq opoint (point)) + (forward-line -1) + (re-search-forward comment-start-skip opoint t))) + (setq win (or (match-end 1) (match-beginning 0)))) + ;; Indent this line like what we found. + (goto-char win) + (setq comcol (current-column)) + (setq comstart + (buffer-substring (point) (match-end 0))))))) + (if comcol + (let ((comment-column comcol) + (comment-start comstart) + (comment-end comment-end)) + (and comment-end (not (equal comment-end "")) + ; (if (not comment-multi-line) + (progn + (forward-char -1) + (insert comment-end) + (forward-char 1)) + ; (setq comment-column (+ comment-column (length comment-start)) + ; comment-start "") + ; ) + ) + (if (not (eolp)) + (setq comment-end "")) + (insert-and-inherit ?\n) + (forward-char -1) + (indent-for-comment) + (save-excursion + ;; Make sure we delete the newline inserted above. + (end-of-line) + (delete-char 1))) + (indent-according-to-mode))))) (defun set-selective-display (arg) "Set `selective-display' to ARG; clear it if no arg. @@ -2433,7 +2609,7 @@ specialization of overwrite-mode, entered by setting the 'overwrite-mode-binary)) (force-mode-line-update)) -(defvar line-number-mode nil +(defvar line-number-mode t "*Non-nil means display line number in mode line.") (defun line-number-mode (arg) @@ -2447,15 +2623,37 @@ in the mode line." (> (prefix-numeric-value arg) 0))) (force-mode-line-update)) +(defvar column-number-mode nil + "*Non-nil means display column number in mode line.") + +(defun column-number-mode (arg) + "Toggle Column Number mode. +With arg, turn Column Number mode on iff arg is positive. +When Column Number mode is enabled, the column number appears +in the mode line." + (interactive "P") + (setq column-number-mode + (if (null arg) (not column-number-mode) + (> (prefix-numeric-value arg) 0))) + (force-mode-line-update)) + (defvar blink-matching-paren t "*Non-nil means show matching open-paren when close-paren is inserted.") +(defvar blink-matching-paren-on-screen t + "*Non-nil means show matching open-paren when it is on screen. +nil means don't show it (but the open-paren can still be shown +when it is off screen.") + (defconst blink-matching-paren-distance 12000 "*If non-nil, is maximum distance to search for matching open-paren.") (defconst blink-matching-delay 1 "*The number of seconds that `blink-matching-open' will delay at a match.") +(defconst blink-matching-paren-dont-ignore-comments nil + "*Non-nil means `blink-matching-paren' should not ignore comments.") + (defun blink-matching-open () "Move cursor momentarily to the beginning of the sexp before point." (interactive) @@ -2477,19 +2675,25 @@ in the mode line." (- (point) blink-matching-paren-distance)) oldpos)) (condition-case () - (setq blinkpos (scan-sexps oldpos -1)) + (let ((parse-sexp-ignore-comments + (and parse-sexp-ignore-comments + (not blink-matching-paren-dont-ignore-comments)))) + (setq blinkpos (scan-sexps oldpos -1))) (error nil))) - (and blinkpos (/= (char-syntax (char-after blinkpos)) - ?\$) + (and blinkpos + (/= (char-syntax (char-after blinkpos)) + ?\$) (setq mismatch - (/= (char-after (1- oldpos)) - (matching-paren (char-after blinkpos))))) + (or (null (matching-paren (char-after blinkpos))) + (/= (char-after (1- oldpos)) + (matching-paren (char-after blinkpos)))))) (if mismatch (setq blinkpos nil)) (if blinkpos (progn (goto-char blinkpos) (if (pos-visible-in-window-p) - (sit-for blink-matching-delay) + (and blink-matching-paren-on-screen + (sit-for blink-matching-delay)) (goto-char blinkpos) (message "Matches %s" @@ -2613,7 +2817,8 @@ it were the arg to `interactive' (which see) to interactively read the value." ;; Define the major mode for lists of completions. -(defvar completion-list-mode-map nil) +(defvar completion-list-mode-map nil + "Local map for completion list buffers.") (or completion-list-mode-map (let ((map (make-sparse-keymap))) (define-key map [mouse-2] 'mouse-choose-completion) @@ -2627,13 +2832,17 @@ it were the arg to `interactive' (which see) to interactively read the value." ;; Completion mode is suitable only for specially formatted data. (put 'completion-list-mode 'mode-class 'special) -;; Record the buffer that was current when the completion list was requested. -;; Initial value is nil to avoid some compiler warnings. -(defvar completion-reference-buffer nil) +(defvar completion-reference-buffer nil + "Record the buffer that was current when the completion list was requested. +This is a local variable in the completion list buffer. +Initial value is nil to avoid some compiler warnings.") -;; This records the length of the text at the beginning of the buffer -;; which was not included in the completion. -(defvar completion-base-size nil) +(defvar completion-base-size nil + "Number of chars at beginning of minibuffer not involved in completion. +This is a local variable in the completion list buffer +but it talks about the buffer in `completion-reference-buffer'. +If this is nil, it means to compare text to determine which part +of the tail end of the buffer's text is involved in completion.") (defun delete-completion-window () "Delete the completion list window. @@ -2651,25 +2860,28 @@ Go to the window from which completion was requested." (defun next-completion (n) "Move to the next item in the completion list. -WIth prefix argument N, move N items (negative N means move backward)." +With prefix argument N, move N items (negative N means move backward)." (interactive "p") (while (and (> n 0) (not (eobp))) - (let ((prop (get-text-property (point) 'mouse-face))) + (let ((prop (get-text-property (point) 'mouse-face)) + (end (point-max))) ;; If in a completion, move to the end of it. (if prop - (goto-char (next-single-property-change (point) 'mouse-face))) + (goto-char (next-single-property-change (point) 'mouse-face nil end))) ;; Move to start of next one. - (goto-char (next-single-property-change (point) 'mouse-face))) + (goto-char (next-single-property-change (point) 'mouse-face nil end))) (setq n (1- n))) (while (and (< n 0) (not (bobp))) - (let ((prop (get-text-property (1- (point)) 'mouse-face))) + (let ((prop (get-text-property (1- (point)) 'mouse-face)) + (end (point-min))) ;; If in a completion, move to the start of it. (if prop - (goto-char (previous-single-property-change (point) 'mouse-face))) + (goto-char (previous-single-property-change + (point) 'mouse-face nil end))) ;; Move to end of the previous completion. - (goto-char (previous-single-property-change (point) 'mouse-face)) + (goto-char (previous-single-property-change (point) 'mouse-face nil end)) ;; Move to the start of that one. - (goto-char (previous-single-property-change (point) 'mouse-face))) + (goto-char (previous-single-property-change (point) 'mouse-face nil end))) (setq n (1+ n)))) (defun choose-completion () @@ -2715,13 +2927,20 @@ WIth prefix argument N, move N items (negative N means move backward)." (forward-char 1)) (delete-char len))) +;; Switch to BUFFER and insert the completion choice CHOICE. +;; BASE-SIZE, if non-nil, says how many characters of BUFFER's text +;; to keep. If it is nil, use choose-completion-delete-max-match instead. + +;; If BUFFER is the minibuffer, exit the minibuffer +;; unless it is reading a file name and CHOICE is a directory. (defun choose-completion-string (choice &optional buffer base-size) (let ((buffer (or buffer completion-reference-buffer))) ;; If BUFFER is a minibuffer, barf unless it's the currently ;; active minibuffer. (if (and (string-match "\\` \\*Minibuf-[0-9]+\\*\\'" (buffer-name buffer)) - (or (not (minibuffer-window-active-p (minibuffer-window))) - (not (equal buffer (window-buffer (minibuffer-window)))))) + (or (not (active-minibuffer-window)) + (not (equal buffer + (window-buffer (active-minibuffer-window)))))) (error "Minibuffer is not active for completion") ;; Insert the completion into the buffer where completion was requested. (set-buffer buffer) @@ -2737,7 +2956,12 @@ WIth prefix argument N, move N items (negative N means move backward)." ;; If completing for the minibuffer, exit it with this choice. (and (equal buffer (window-buffer (minibuffer-window))) minibuffer-completion-table - (exit-minibuffer))))) + ;; If this is reading a file name, and the file name chosen + ;; is a directory, don't exit the minibuffer. + (if (and (eq minibuffer-completion-table 'read-file-name-internal) + (file-directory-p (buffer-string))) + (select-window (active-minibuffer-window)) + (exit-minibuffer)))))) (defun completion-list-mode () "Major mode for buffers showing lists of possible completions. @@ -2754,17 +2978,26 @@ Use \\\\[mouse-choose-completion] to select one\ (setq completion-base-size nil) (run-hooks 'completion-list-mode-hook)) -(defvar completion-fixup-function nil) +(defvar completion-fixup-function nil + "A function to customize how completions are identified in completion lists. +`completion-setup-function' calls this function with no arguments +each time it has found what it thinks is one completion. +Point is at the end of the completion in the completion list buffer. +If this function moves point, it can alter the end of that completion.") + +;; This function goes in completion-setup-hook, so that it is called +;; after the text of the completion list buffer is written. (defun completion-setup-function () (save-excursion - (let ((mainbuf (current-buffer)) - (base-size (- (point-max) (point-min)))) + (let ((mainbuf (current-buffer))) (set-buffer standard-output) (completion-list-mode) (make-local-variable 'completion-reference-buffer) (setq completion-reference-buffer mainbuf) - (setq completion-base-size base-size) +;;; The value 0 is right in most cases, but not for file name completion. +;;; so this has to be turned off. +;;; (setq completion-base-size 0) (goto-char (point-min)) (if window-system (insert (substitute-command-keys @@ -2795,11 +3028,68 @@ select the completion near point.\n\n")) (defun switch-to-completions () "Select the completion list window." (interactive) + ;; Make sure we have a completions window. + (or (get-buffer-window "*Completions*") + (minibuffer-completion-help)) (select-window (get-buffer-window "*Completions*")) (goto-char (point-min)) (search-forward "\n\n") (forward-line 1)) +;; Support keyboard commands to turn on various modifiers. + +;; These functions -- which are not commands -- each add one modifier +;; to the following event. + +(defun event-apply-alt-modifier (ignore-prompt) + (vector (event-apply-modifier (read-event) 'alt 22 "A-"))) +(defun event-apply-super-modifier (ignore-prompt) + (vector (event-apply-modifier (read-event) 'super 23 "s-"))) +(defun event-apply-hyper-modifier (ignore-prompt) + (vector (event-apply-modifier (read-event) 'hyper 24 "H-"))) +(defun event-apply-shift-modifier (ignore-prompt) + (vector (event-apply-modifier (read-event) 'shift 25 "S-"))) +(defun event-apply-control-modifier (ignore-prompt) + (vector (event-apply-modifier (read-event) 'control 26 "C-"))) +(defun event-apply-meta-modifier (ignore-prompt) + (vector (event-apply-modifier (read-event) 'meta 27 "M-"))) + +(defun event-apply-modifier (event symbol lshiftby prefix) + "Apply a modifier flag to event EVENT. +SYMBOL is the name of this modifier, as a symbol. +LSHIFTBY is the numeric value of this modifier, in keyboard events. +PREFIX is the string that represents this modifier in an event type symbol." + (if (numberp event) + (cond ((eq symbol 'control) + (if (and (<= (downcase event) ?z) + (>= (downcase event) ?a)) + (- (downcase event) ?a -1) + (if (and (<= (downcase event) ?Z) + (>= (downcase event) ?A)) + (- (downcase event) ?A -1) + (logior (lsh 1 lshiftby) event)))) + ((eq symbol 'shift) + (if (and (<= (downcase event) ?z) + (>= (downcase event) ?a)) + (upcase event) + (logior (lsh 1 lshiftby) event))) + (t + (logior (lsh 1 lshiftby) event))) + (if (memq symbol (event-modifiers event)) + event + (let ((event-type (if (symbolp event) event (car event)))) + (setq event-type (intern (concat prefix (symbol-name event-type)))) + (if (symbolp event) + event-type + (cons event-type (cdr event))))))) + +(define-key function-key-map [?\C-x ?@ ?h] 'event-apply-hyper-modifier) +(define-key function-key-map [?\C-x ?@ ?s] 'event-apply-super-modifier) +(define-key function-key-map [?\C-x ?@ ?m] 'event-apply-meta-modifier) +(define-key function-key-map [?\C-x ?@ ?a] 'event-apply-alt-modifier) +(define-key function-key-map [?\C-x ?@ ?S] 'event-apply-shift-modifier) +(define-key function-key-map [?\C-x ?@ ?c] 'event-apply-control-modifier) + ;;;; Keypad support. ;;; Make the keypad keys act like ordinary typing keys. If people add