]> code.delx.au - gnu-emacs/blobdiff - lisp/simple.el
Initial revision
[gnu-emacs] / lisp / simple.el
index 3b2f28b6e333029fdf24e3f89918c89893ecaaf0..dfca44cffc6968dabe2603e9141e71a679e7456f 100644 (file)
@@ -301,7 +301,7 @@ that uses or sets the mark."
   (goto-char (point-min)))
 
 (defun count-lines-region (start end)
-  "Print number of lines and charcters in the region."
+  "Print number of lines and characters in the region."
   (interactive "r")
   (message "Region has %d lines, %d characters"
           (count-lines start end) (- end start)))
@@ -597,7 +597,8 @@ Get previous element of history which is a completion of minibuffer contents."
 Repeat this command to undo more changes.
 A numeric argument serves as a repeat count."
   (interactive "*p")
-  (let ((modified (buffer-modified-p)))
+  (let ((modified (buffer-modified-p))
+       (recent-save (recent-auto-save-p)))
     (or (eq (selected-window) (minibuffer-window))
        (message "Undo!"))
     (or (eq last-command 'undo)
@@ -606,7 +607,10 @@ A numeric argument serves as a repeat count."
     (setq this-command 'undo)
     (undo-more (or arg 1))
     (and modified (not (buffer-modified-p))
-        (delete-auto-save-file-if-necessary))))
+        (delete-auto-save-file-if-necessary recent-save))))
+
+(defvar pending-undo-list nil
+  "Within a run of consecutive undo commands, list remaining to be undone.")
 
 (defun undo-start ()
   "Set `pending-undo-list' to the front of the undo list.
@@ -645,7 +649,12 @@ This cannot be done asynchronously."
             ;; aliases for shell commands then they can still have them.
             (call-process shell-file-name nil t nil
                           "-c" command)
-            (exchange-point-and-mark))
+            ;; 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
@@ -892,20 +901,23 @@ when given no argument at the beginning of a line."
   "Function to call to make a killed region available to other programs.
 
 Most window systems provide some sort of facility for cutting and
-pasting text between the windows of different programs.  On startup,
-this variable is set to a function which emacs will call whenever text
-is put in the kill ring to make the new kill available to other
+pasting text between the windows of different programs.
+This variable holds a function that Emacs calls whenever text
+is put in the kill ring, to make the new kill available to other
 programs.
 
-The function takes one argument, TEXT, which is a string containing
-the text which should be made available.")
+The function takes one or two arguments.
+The first argument, TEXT, is a string containing
+the text which should be made available.
+The second, PUSH, if non-nil means this is a \"new\" kill;
+nil means appending to an \"old\" kill.")
 
 (defvar interprogram-paste-function nil
   "Function to call to get text cut from other programs.
 
 Most window systems provide some sort of facility for cutting and
-pasting text between the windows of different programs.  On startup,
-this variable is set to a function which emacs will call to obtain
+pasting text between the windows of different programs.
+This variable holds a function that Emacs calls to obtain
 text that other programs have provided for pasting.
 
 The function should be called with no arguments.  If the function
@@ -949,7 +961,7 @@ If `interprogram-cut-function' is non-nil, apply it to STRING."
       (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)))
+      (funcall interprogram-cut-function string t)))
 
 (defun kill-append (string before-p)
   "Append STRING to the end of the latest kill in the kill ring.
@@ -1028,11 +1040,18 @@ to make one entry in the kill ring."
             (eq last-command 'kill-region)
             (eq beg end)))
     ;; Don't let the undo list be truncated before we can even access it.
-    (let ((undo-strong-limit (+ (- (max beg end) (min beg end)) 100)))
+    (let ((undo-strong-limit (+ (- (max beg end) (min beg end)) 100))
+         (old-list buffer-undo-list)
+         tail)
       (delete-region beg end)
+      ;; Search back in buffer-undo-list for this string,
+      ;; in case a change hook made property changes.
+      (setq tail buffer-undo-list)
+      (while (not (stringp (car (car tail))))
+       (setq tail (cdr tail)))
       ;; Take the same string recorded for undo
       ;; and put it in the kill-ring.
-      (kill-new (car (car buffer-undo-list)))
+      (kill-new (car (car tail)))
       (setq this-command 'kill-region)))
 
    (t
@@ -1052,28 +1071,41 @@ system cut and paste."
 
 (defun kill-ring-save (beg end)
   "Save the region as if killed, but don't kill it.
-This command is similar to copy-region-as-kill, except that it gives
+This command is similar to `copy-region-as-kill', except that it gives
 visual feedback indicating the extent of the region being copied.
 If `interprogram-cut-function' is non-nil, also save the text for a window
 system cut and paste."
   (interactive "r")
   (copy-region-as-kill beg end)
   (if (interactive-p)
-      (save-excursion
-       (let ((other-end (if (= (point) beg) end beg)))
-         (if (pos-visible-in-window-p other-end (selected-window))
-             (let ((omark (mark t))) 
-               (set-marker (mark-marker) (point) (current-buffer))
-               (goto-char other-end)
-               (sit-for 1))              
-           (let* ((killed-text (current-kill 0))
-                  (message-len (min (length killed-text) 40)))
-             (if (= (point) beg)
-                 ;; Don't say "killed"; that is misleading.
-                 (message "Saved text until \"%s\""
-                         (substring killed-text (- message-len)))
-               (message "Saved text from \"%s\""
-                       (substring killed-text 0 message-len)))))))))
+      (let ((other-end (if (= (point) beg) end beg))
+           (opoint (point))
+           ;; Inhibit quitting so we can make a quit here
+           ;; look like a C-g typed as a command.
+           (inhibit-quit t))
+       (if (pos-visible-in-window-p other-end (selected-window))
+           (progn
+             ;; Swap point and mark.
+             (set-marker (mark-marker) (point) (current-buffer))
+             (goto-char other-end)
+             (sit-for 1)
+             ;; Swap back.
+             (set-marker (mark-marker) other-end (current-buffer))
+             (goto-char opoint)
+             ;; If user quit, deactivate the mark
+             ;; as C-g would as a command.
+             (and quit-flag mark-active
+                  (progn
+                    (message "foo")    ;XXX what is this here for?  --roland
+                    (deactivate-mark))))
+         (let* ((killed-text (current-kill 0))
+                (message-len (min (length killed-text) 40)))
+           (if (= (point) beg)
+               ;; Don't say "killed"; that is misleading.
+               (message "Saved text until \"%s\""
+                       (substring killed-text (- message-len)))
+             (message "Saved text from \"%s\""
+                     (substring killed-text 0 message-len))))))))
 
 (defun append-next-kill ()
   "Cause following command, if it kills, to append to previous kill."
@@ -1168,7 +1200,8 @@ When calling from a program, give three arguments:
 BUFFER (or buffer name), START and END.
 START and END specify the portion of the current buffer to be copied."
   (interactive
-   (list (read-buffer "Append to buffer: " (other-buffer nil t) t)))
+   (list (read-buffer "Append to buffer: " (other-buffer nil t))
+        (region-beginning) (region-end)))
   (let ((oldbuf (current-buffer)))
     (save-excursion
       (set-buffer (get-buffer-create buffer))
@@ -1203,16 +1236,35 @@ START and END specify the portion of the current buffer to be copied."
       (save-excursion
        (insert-buffer-substring oldbuf start end)))))
 \f
+(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")
+
 (defun mark (&optional force)
-  "Return this buffer's mark value as integer, or nil if no active mark now.
+  "Return this buffer's mark value as integer; error if mark inactive.
 If optional argument FORCE is non-nil, access the mark value
-even if the mark is not currently active.
+even if the mark is not currently active, and return nil
+if there is no mark at all.
 
 If you are using this in an editing command, you are most likely making
 a mistake; see the documentation of `set-mark'."
-  (if (or force mark-active)
+  (if (or force mark-active mark-even-if-inactive)
       (marker-position (mark-marker))
-    (error "The mark is not currently active")))
+    (signal 'mark-inactive nil)))
+
+;; Many places set mark-active directly, and several of them failed to also
+;; run deactivate-mark-hook.  This shorthand should simplify.
+(defsubst deactivate-mark ()
+  "Deactivate the mark by setting `mark-active' to nil.
+Also runs the hook `deactivate-mark-hook'."
+  (setq mark-active nil)
+  (run-hooks 'deactivate-mark-hook))
 
 (defun set-mark (pos)
   "Set this buffer's mark to POS.  Don't use this function!
@@ -1289,8 +1341,7 @@ Does not set point.  Does nothing if mark ring is empty."
       (progn
        (setq mark-ring (nconc mark-ring (list (copy-marker (mark-marker)))))
        (set-marker (mark-marker) (+ 0 (car mark-ring)) (current-buffer))
-       (if transient-mark-mode
-           (setq mark-active nil))
+       (deactivate-mark)
        (move-marker (car mark-ring) nil)
        (if (null (mark t)) (ding))
        (setq mark-ring (cdr mark-ring)))))
@@ -1310,7 +1361,7 @@ and it reactivates the mark."
 
 (defun transient-mark-mode (arg)
   "Toggle Transient Mark mode.
-With arg, turn Transient Mark mode on if and only if arg is positive.
+With arg, turn Transient Mark mode on if arg is positive, off otherwise.
 
 In Transient Mark mode, changing the buffer \"deactivates\" the mark.
 While the mark is active, the region is highlighted."
@@ -1449,16 +1500,28 @@ If this is zero, point is always centered after it moves off frame.")
 
 (defun hscroll-point-visible ()
   "Scrolls the window horizontally to make point visible."
-  (let*  ((min (window-hscroll))
-          (max (- (+ min (window-width)) 2))
-          (here (current-column))
-          (delta (if (zerop hscroll-step) (/ (window-width) 2) hscroll-step))
-          )
-    (if (< here min)
-        (scroll-right (max 0 (+ (- min here) delta)))
-      (if (>= here  max)
-          (scroll-left (- (- here min) delta))
-        ))))
+  (let* ((here (current-column))
+        (left (window-hscroll))
+        (right (- (+ left (window-width)) 3)))
+    (cond
+     ;; Should we recenter?
+     ((or (< here (- left  hscroll-step))
+         (> here (+ right hscroll-step)))
+      (set-window-hscroll
+       (selected-window)
+       ;; Recenter, but don't show too much white space off the end of
+       ;; the line.
+       (max 0
+           (min (- (save-excursion (end-of-line) (current-column))
+                   (window-width)
+                   -5)
+                (- here (/ (window-width) 2))))))
+     ;; Should we scroll left?
+     ((> here right)
+      (scroll-left hscroll-step))
+     ;; Or right?
+     ((< here left)
+      (scroll-right hscroll-step)))))
   
 ;; rms: (1) The definitions of arrow keys should not simply restate
 ;; what keys they are.  The arrow keys should run the ordinary commands.
@@ -2092,8 +2155,7 @@ in the mode line."
 During execution of Lisp code, this character causes a quit directly.
 At top-level, as an editor command, this simply beeps."
   (interactive)
-  (if transient-mark-mode
-      (setq mark-active nil))
+  (deactivate-mark)
   (signal 'quit nil))
 
 (define-key global-map "\C-g" 'keyboard-quit)
@@ -2133,4 +2195,30 @@ it were the arg to `interactive' (which see) to interactively read the value."
               (eval-minibuffer (format "Set %s to value: " var)))))))
   (set var val))
 
+\f
+;;;; Keypad support.
+
+;;; Make the keypad keys act like ordinary typing keys.  If people add
+;;; bindings for the function key symbols, then those bindings will
+;;; override these, so this shouldn't interfere with any existing
+;;; bindings.
+
+(mapcar
+ (lambda (keypad-normal)
+   (let ((keypad (nth 0 keypad-normal))
+        (normal (nth 1 keypad-normal)))
+     (define-key function-key-map (vector keypad) (vector normal))))
+ '((kp-0 ?0) (kp-1 ?1) (kp-2 ?2) (kp-3 ?3) (kp-4 ?4)
+   (kp-5 ?5) (kp-6 ?6) (kp-7 ?7) (kp-8 ?8) (kp-9 ?9)
+   (kp-space ?\ )
+   (kp-tab ?\t)
+   (kp-enter ?\r)
+   (kp-multiply ?*)
+   (kp-add ?+)
+   (kp-separator ?,)
+   (kp-subtract ?-)
+   (kp-decimal ?.)
+   (kp-divide ?/)
+   (kp-equal ?=)))
+
 ;;; simple.el ends here