(quoted-insert): Comment out code that treats 0240-0377 specially.
[bpt/emacs.git] / lisp / simple.el
index 885e2d5..cf1a73e 100644 (file)
@@ -391,6 +391,25 @@ Other major modes are defined by comparison with this one."
   (unless delay-mode-hooks
     (run-hooks 'after-change-major-mode-hook)))
 
+;; Special major modes to view specially formatted data rather than files.
+
+(defvar special-mode-map
+  (let ((map (make-sparse-keymap)))
+    (suppress-keymap map)
+    (define-key map "q" 'quit-window)
+    (define-key map " " 'scroll-up)
+    (define-key map "\C-?" 'scroll-down)
+    (define-key map "?" 'describe-mode)
+    (define-key map ">" 'end-of-buffer)
+    (define-key map "<" 'beginning-of-buffer)
+    (define-key map "g" 'revert-buffer)
+    map))
+   
+(put 'special-mode 'mode-class 'special)
+(define-derived-mode special-mode nil "Special"
+  "Parent major mode from which special major modes should inherit."
+  (setq buffer-read-only t))
+
 ;; Making and deleting lines.
 
 (defvar hard-newline (propertize "\n" 'hard t 'rear-nonsticky '(hard)))
@@ -668,13 +687,14 @@ useful for editing binary files."
                         (eq overwrite-mode 'overwrite-mode-binary))
                     (read-quoted-char)
                   (read-char)))))
-    ;; Assume character codes 0240 - 0377 stand for characters in some
-    ;; single-byte character set, and convert them to Emacs
-    ;; characters.
-    (if (and enable-multibyte-characters
-            (>= char ?\240)
-            (<= char ?\377))
-       (setq char (unibyte-char-to-multibyte char)))
+    ;; This used to assume character codes 0240 - 0377 stand for
+    ;; characters in some single-byte character set, and converted them
+    ;; to Emacs characters.  But in 23.1 this feature is deprecated
+    ;; in favor of inserting the corresponding Unicode characters.
+    ;; (if (and enable-multibyte-characters
+    ;;          (>= char ?\240)
+    ;;          (<= char ?\377))
+    ;;     (setq char (unibyte-char-to-multibyte char)))
     (if (> arg 0)
        (if (eq overwrite-mode 'overwrite-mode-binary)
            (delete-char arg)))
@@ -2818,7 +2838,7 @@ move the yanking point; just return the Nth kill forward."
   "Kill (\"cut\") text between point and mark.
 This deletes the text from the buffer and saves it in the kill ring.
 The command \\[yank] can retrieve it from there.
-\(If you want to kill and then yank immediately, use \\[kill-ring-save].)
+\(If you want to save the region without killing it, use \\[kill-ring-save].)
 
 If you want to append the killed region to the last killed text,
 use \\[append-next-kill] before \\[kill-region].
@@ -3797,6 +3817,10 @@ 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 the variable `line-move-visual' is non-nil, this command moves
+by display lines.  Otherwise, it moves by buffer lines, without
+taking variable-width characters or continued lines into account.
+
 The command \\[set-goal-column] can be used to create
 a semipermanent goal column for this command.
 Then instead of trying to move exactly vertically (or as close as possible),
@@ -3830,6 +3854,10 @@ If there is no character in the target line exactly over the current column,
 the cursor is positioned after the character in that line which spans this
 column, or at the end of the line if it is not long enough.
 
+If the variable `line-move-visual' is non-nil, this command moves
+by display lines.  Otherwise, it moves by buffer lines, without
+taking variable-width characters or continued lines into account.
+
 The command \\[set-goal-column] can be used to create
 a semipermanent goal column for this command.
 Then instead of trying to move exactly vertically (or as close as possible),
@@ -3852,7 +3880,8 @@ to use and more reliable (no dependence on goal column, etc.)."
 (defcustom track-eol nil
   "*Non-nil means vertical motion starting at end of line keeps to ends of lines.
 This means moving to the end of each line moved onto.
-The beginning of a blank line does not count as the end of a line."
+The beginning of a blank line does not count as the end of a line.
+This has no effect when `line-move-visual' is non-nil."
   :type 'boolean
   :group 'editing-basics)
 
@@ -3865,9 +3894,12 @@ The beginning of a blank line does not count as the end of a line."
 
 (defvar temporary-goal-column 0
   "Current goal column for vertical motion.
-It is the column where point was
-at the start of current run of vertical motion commands.
-When the `track-eol' feature is doing its job, the value is `most-positive-fixnum'.")
+It is the column where point was at the start of the current run
+of vertical motion commands.  It is a floating point number when
+moving by visual lines via `line-move-visual'; this is the
+x-position, in pixels, divided by the default column width.  When
+the `track-eol' feature is doing its job, the value is
+`most-positive-fixnum'.")
 
 (defcustom line-move-ignore-invisible t
   "*Non-nil means \\[next-line] and \\[previous-line] ignore invisible lines.
@@ -3875,6 +3907,14 @@ Outline mode sets this."
   :type 'boolean
   :group 'editing-basics)
 
+(defcustom line-move-visual t
+  "When non-nil, `line-move' moves point by visual lines.
+This movement is based on where the cursor is displayed on the
+screen, instead of relying on buffer contents alone.  It takes
+into account variable-width characters and line continuation."
+  :type 'boolean
+  :group 'editing-basics)
+
 ;; Returns non-nil if partial move was done.
 (defun line-move-partial (arg noerror to-end)
   (if (< arg 0)
@@ -3947,7 +3987,29 @@ Outline mode sets this."
               (not executing-kbd-macro)
               (line-move-partial arg noerror to-end))
     (set-window-vscroll nil 0 t)
-    (line-move-1 arg noerror to-end)))
+    (if line-move-visual
+       (line-move-visual arg noerror)
+      (line-move-1 arg noerror to-end))))
+
+;; Display-based alternative to line-move-1.
+;; Arg says how many lines to move.  The value is t if we can move the
+;; specified number of lines.
+(defun line-move-visual (arg &optional noerror)
+  (unless (and (floatp temporary-goal-column)
+              (or (memq last-command '(next-line previous-line))
+                  ;; In case we're called from some other command.
+                  (eq last-command this-command)))
+    (let ((x (car (nth 2 (posn-at-point)))))
+      (when x
+       (setq temporary-goal-column (/ (float x) (frame-char-width))))))
+  (or (= (vertical-motion
+         (cons (or goal-column (truncate temporary-goal-column)) arg))
+        arg)
+      (unless noerror
+       (signal (if (< arg 0)
+                   'beginning-of-buffer
+                 'end-of-buffer)
+               nil))))
 
 ;; This is the guts of next-line and previous-line.
 ;; Arg says how many lines to move.
@@ -3958,6 +4020,8 @@ Outline mode sets this."
   (let ((inhibit-point-motion-hooks t)
        (opoint (point))
        (orig-arg arg))
+    (if (floatp temporary-goal-column)
+       (setq temporary-goal-column (truncate temporary-goal-column)))
     (unwind-protect
        (progn
          (if (not (memq last-command '(next-line previous-line)))
@@ -4059,13 +4123,20 @@ Outline mode sets this."
          (= arg 0))
 
       (cond ((> arg 0)
-            ;; If we did not move down as far as desired,
-            ;; at least go to end of line.
-            (end-of-line))
+            ;; If we did not move down as far as desired, at least go
+            ;; to end of line.  Be sure to call point-entered and
+            ;; point-left-hooks.
+            (let* ((npoint (prog1 (line-end-position)
+                             (goto-char opoint)))
+                   (inhibit-point-motion-hooks nil))
+              (goto-char npoint)))
            ((< arg 0)
             ;; If we did not move up as far as desired,
             ;; at least go to beginning of line.
-            (beginning-of-line))
+            (let* ((npoint (prog1 (line-beginning-position)
+                             (goto-char opoint)))
+                   (inhibit-point-motion-hooks nil))
+              (goto-char npoint)))
            (t
             (line-move-finish (or goal-column temporary-goal-column)
                               opoint (> orig-arg 0)))))))
@@ -4204,7 +4275,8 @@ To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
     (while (not done)
       (let ((newpos
             (save-excursion
-              (let ((goal-column 0))
+              (let ((goal-column 0)
+                    (line-move-visual nil))
                 (and (line-move arg t)
                      (not (bobp))
                      (progn
@@ -4219,9 +4291,8 @@ To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
            (backward-char 1)
          (if (and (> (point) newpos) (not (eobp))
                   (not (eq (following-char) ?\n)))
-             ;; If we skipped something intangible
-             ;; and now we're not really at eol,
-             ;; keep going.
+             ;; If we skipped something intangible and now we're not
+             ;; really at eol, keep going.
              (setq arg 1)
            (setq done t)))))))
 
@@ -4241,7 +4312,8 @@ To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
 
     ;; Move by lines, if ARG is not 1 (the default).
     (if (/= arg 1)
-       (line-move (1- arg) t))
+       (let ((line-move-visual nil))
+         (line-move (1- arg) t)))
 
     ;; Move to beginning-of-line, ignoring fields and invisibles.
     (skip-chars-backward "^\n")
@@ -4298,7 +4370,172 @@ The goal column is stored in the variable `goal-column'."
     )
   nil)
 \f
+;;; Editing based on visual lines, as opposed to logical lines.
 
+(defun end-of-visual-line (&optional n)
+  "Move point to end of current visual line.
+With argument N not nil or 1, move forward N - 1 visual lines first.
+If point reaches the beginning or end of buffer, it stops there.
+To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
+  (interactive "^p")
+  (or n (setq n 1))
+  (if (/= n 1)
+      (let ((line-move-visual t))
+       (line-move (1- n) t)))
+  (vertical-motion (cons (window-width) 0)))
+
+(defun beginning-of-visual-line (&optional n)
+  "Move point to beginning of current visual line.
+With argument N not nil or 1, move forward N - 1 visual lines first.
+If point reaches the beginning or end of buffer, it stops there.
+To ignore intangibility, bind `inhibit-point-motion-hooks' to t."
+  (interactive "^p")
+  (or n (setq n 1))
+  (if (/= n 1)
+      (let ((line-move-visual t))
+       (line-move (1- n) t)))
+  (vertical-motion 0))
+
+(defun kill-visual-line (&optional arg)
+  "Kill the rest of the visual line.
+If there are only whitespace characters there, kill through the
+newline as well.
+
+With prefix argument, kill that many lines from point.
+Negative arguments kill lines backward.
+With zero argument, kill the text before point on the current line.
+
+When calling from a program, nil means \"no arg\",
+a number counts as a prefix arg.
+
+If `kill-whole-line' is non-nil, then this command kills the whole line
+including its terminating newline, when used at the beginning of a line
+with no argument.  As a consequence, you can always kill a whole line
+by typing \\[beginning-of-line] \\[kill-line].
+
+If you want to append the killed line to the last killed text,
+use \\[append-next-kill] before \\[kill-line].
+
+If the buffer is read-only, Emacs will beep and refrain from deleting
+the line, but put the line in the kill ring anyway.  This means that
+you can use this command to copy text from a read-only buffer.
+\(If the variable `kill-read-only-ok' is non-nil, then this won't
+even beep.)"
+  (interactive "P")
+  (let ((opoint (point))
+       (line-move-visual t)
+       end)
+    ;; It is better to move point to the other end of the kill before
+    ;; killing.  That way, in a read-only buffer, point moves across
+    ;; the text that is copied to the kill ring.  The choice has no
+    ;; effect on undo now that undo records the value of point from
+    ;; before the command was run.
+    (if arg
+       (vertical-motion (prefix-numeric-value arg))
+      (if (eobp)
+         (signal 'end-of-buffer nil))
+      (setq end (save-excursion
+                 (end-of-visual-line) (point)))
+      (if (or (save-excursion
+               ;; If trailing whitespace is visible,
+               ;; don't treat it as nothing.
+               (unless show-trailing-whitespace
+                 (skip-chars-forward " \t" end))
+               (= (point) end))
+             (and kill-whole-line (bolp)))
+         (line-move 1)
+       (goto-char end)))
+    (kill-region opoint (point))))
+
+(defun next-logical-line (&optional arg try-vscroll)
+  "Move cursor vertically down ARG lines.
+This is identical to `previous-line', except that it always moves
+by logical lines instead of visual lines, ignoring the value of
+the variable `line-move-visual'."
+  (interactive "^p\np")
+  (let ((line-move-visual nil))
+    (with-no-warnings
+      (next-line arg try-vscroll))))
+
+(defun previous-logical-line (&optional arg try-vscroll)
+  "Move cursor vertically up ARG lines.
+This is identical to `previous-line', except that it always moves
+by logical lines instead of visual lines, ignoring the value of
+the variable `line-move-visual'."
+  (interactive "^p\np")
+  (let ((line-move-visual nil))
+    (with-no-warnings
+      (previous-line arg try-vscroll))))
+
+(defgroup visual-line nil
+  "Editing based on visual lines."
+  :group 'convenience
+  :version "23.1")
+
+(defvar visual-line-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [remap kill-line] 'kill-visual-line)
+    (define-key map [remap move-beginning-of-line] 'beginning-of-visual-line)
+    (define-key map [remap move-end-of-line]  'end-of-visual-line)
+    (define-key map "\M-[" 'previous-logical-line)
+    (define-key map "\M-]" 'next-logical-line)
+    map))
+
+(defcustom visual-line-fringe-indicators '(nil nil)
+  "How fringe indicators are shown for wrapped lines in `visual-line-mode'.
+The value should be a list of the form (LEFT RIGHT), where LEFT
+and RIGHT are symbols representing the bitmaps to display, to
+indicate wrapped lines, in the left and right fringes respectively.
+See also `fringe-indicator-alist'.
+The default is not to display fringe indicators for wrapped lines.
+This variable does not affect fringe indicators displayed for
+other purposes."
+  :type '(list (choice (const :tag "Hide left indicator" nil)
+                      (const :tag "Left curly arrow" left-curly-arrow)
+                      (symbol :tag "Other bitmap"))
+              (choice (const :tag "Hide right indicator" nil)
+                      (const :tag "Right curly arrow" right-curly-arrow)
+                      (symbol :tag "Other bitmap")))
+  :set (lambda (symbol value)
+        (dolist (buf (buffer-list))
+          (with-current-buffer buf
+            (when (and (boundp 'visual-line-mode)
+                       (symbol-value 'visual-line-mode))
+              (setq fringe-indicator-alist
+                    (cons (cons 'continuation value)
+                          (assq-delete-all
+                           'continuation
+                           (copy-tree fringe-indicator-alist)))))))
+        (set-default symbol value)))
+
+(define-minor-mode visual-line-mode
+  "Redefine simple editing commands to act on visual lines, not logical lines.
+This also turns on `word-wrap' in the buffer."
+  :keymap visual-line-mode-map
+  :group 'visual-line
+  :lighter " wrap"
+  (if visual-line-mode
+      (progn
+       (set (make-local-variable 'line-move-visual) t)
+       (set (make-local-variable 'truncate-partial-width-windows) nil)
+       (setq truncate-lines nil
+             word-wrap t
+             fringe-indicator-alist
+             (cons (cons 'continuation visual-line-fringe-indicators)
+                   fringe-indicator-alist)))
+    (kill-local-variable 'line-move-visual)
+    (kill-local-variable 'word-wrap)
+    (kill-local-variable 'truncate-lines)
+    (kill-local-variable 'truncate-partial-width-windows)
+    (kill-local-variable 'fringe-indicator-alist)))
+
+(defun turn-on-visual-line-mode ()
+  (visual-line-mode 1))
+
+(define-globalized-minor-mode global-visual-line-mode
+  visual-line-mode turn-on-visual-line-mode
+  :lighter " vl")
+\f
 (defun scroll-other-window-down (lines)
   "Scroll the \"other window\" down.
 For more details, see the documentation for `scroll-other-window'."
@@ -5867,7 +6104,6 @@ call `normal-erase-is-backspace-mode' (which see) instead."
        (if (if (eq normal-erase-is-backspace 'maybe)
                (and (not noninteractive)
                     (or (memq system-type '(ms-dos windows-nt))
-                        (eq window-system 'mac)
                         (and (memq window-system '(x))
                              (fboundp 'x-backspace-delete-keys-p)
                              (x-backspace-delete-keys-p))
@@ -5917,7 +6153,7 @@ See also `normal-erase-is-backspace'."
     (set-terminal-parameter nil 'normal-erase-is-backspace
                            (if enabled 1 0))
 
-    (cond ((or (memq window-system '(x w32 mac pc))
+    (cond ((or (memq window-system '(x w32 ns pc))
               (memq system-type '(ms-dos windows-nt)))
           (let* ((bindings
                   `(([C-delete] [C-backspace])