Add arch taglines
[bpt/emacs.git] / lisp / forms.el
index 226474c..76d4bc4 100644 (file)
@@ -1,6 +1,6 @@
 ;;; forms.el --- Forms mode: edit a file as a form to fill in
 
-;; Copyright (C) 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1991, 1994, 1995, 1996, 1997, 2003 Free Software Foundation, Inc.
 
 ;; Author: Johan Vromans <jvromans@squirrel.nl>
 
@@ -31,9 +31,9 @@
 ;; Names which start with 'forms--' are intended for internal use, and
 ;; should *NOT* be used from the outside.
 ;;
-;; All variables are buffer-local, to enable multiple forms visits 
+;; All variables are buffer-local, to enable multiple forms visits
 ;; simultaneously.
-;; Variable `forms--mode-setup' is local to *ALL* buffers, for it 
+;; Variable `forms--mode-setup' is local to *ALL* buffers, for it
 ;; controls if forms-mode has been enabled in a buffer.
 ;;
 ;; === How it works ===
@@ -60,9 +60,9 @@
 ;; You may also visit the control file, and switch to forms mode by hand
 ;; with M-x `forms-mode'.
 ;;
-;; Automatic mode switching is supported if you specify 
+;; Automatic mode switching is supported if you specify
 ;; "-*- forms -*-" in the first line of the control file.
-;; 
+;;
 ;; The control file is visited, evaluated using `eval-current-buffer',
 ;; and should set at least the following variables:
 ;;
 ;;
 ;;   - a string, e.g. "hello".  The string is inserted in the forms
 ;;     "as is".
-;;   
+;;
 ;;   - an integer, denoting a field number.
 ;;     The contents of this field are inserted at this point.
 ;;     Fields are numbered starting with number one.
-;;   
+;;
 ;;   - a function call, e.g. (insert "text").
 ;;     This function call is dynamically evaluated and should return a
 ;;     string.  It should *NOT* have side-effects on the forms being
 ;;     constructed.  The current fields are available to the function
 ;;     in the variable `forms-fields', they should *NOT* be modified.
-;;   
+;;
 ;;   - a lisp symbol, that must evaluate to one of the above.
 ;;
 ;; Optional variables which may be set in the control file:
 ;;                     Non-nil means that the data file is visited
 ;;                     read-only (view mode) as opposed to edit mode.
 ;;                     If no write access to the data file is
-;;                     possible, view mode is enforced. 
+;;                     possible, view mode is enforced.
 ;;
 ;;     forms-check-number-of-fields            [bool, default t]
 ;;                     If non-nil, a warning will be issued whenever
 ;;                     first record.
 ;;
 ;;     forms-read-file-filter                  [symbol, default nil]
-;;                     If not nil: this should be the name of a 
+;;                     If not nil: this should be the name of a
 ;;                     function that is called after the forms data file
 ;;                     has been read.  It can be used to transform
 ;;                     the contents of the file into a format more suitable
 ;;                     for forms-mode processing.
 ;;
 ;;     forms-write-file-filter                 [symbol, default nil]
-;;                     If not nil: this should be the name of a 
+;;                     If not nil: this should be the name of a
 ;;                     function that is called before the forms data file
 ;;                     is written (saved) to disk.  It can be used to undo
 ;;                     the effects of `forms-read-file-filter', if any.
 ;;
 ;;     forms-new-record-filter                 [symbol, default nil]
-;;                     If not nil: this should be the name of a 
+;;                     If not nil: this should be the name of a
 ;;                     function that is called when a new
 ;;                     record is created.  It can be used to fill in
 ;;                     the new record with default fields, for example.
 ;;
 ;;     forms-modified-record-filter            [symbol, default nil]
-;;                     If not nil: this should be the name of a 
+;;                     If not nil: this should be the name of a
 ;;                     function that is called when a record has
 ;;                     been modified.  It is called after the fields
 ;;                     are parsed.  It can be used to register
 ;; Normal operation is to transfer one line (record) from the data file,
 ;; split it into fields (into `forms--the-record-list'), and display it
 ;; using the specs in `forms-format-list'.
-;; A format routine `forms--format' is built upon startup to format 
+;; A format routine `forms--format' is built upon startup to format
 ;; the records according to `forms-format-list'.
 ;;
 ;; When a form is changed the record is updated as soon as this form
 ;; contents of the buffer.
 ;;
 ;; Edit mode commands:
-;; 
+;;
 ;; TAB          forms-next-field
 ;; \C-c TAB     forms-next-field
 ;; \C-c <       forms-first-record
 ;; \C-c \C-r    forms-search-backward
 ;; \C-c \C-s    forms-search-forward
 ;; \C-c \C-x    forms-exit
-;; 
+;;
 ;; Read-only mode commands:
-;; 
+;;
 ;; SPC          forms-next-record
 ;; DEL  forms-prev-record
 ;; ?    describe-mode
 ;; r    forms-search-backward
 ;; s    forms-search-forward
 ;; x    forms-exit
-;; 
+;;
 ;; Of course, it is also possible to use the \C-c prefix to obtain the
 ;; same command keys as in edit mode.
-;; 
-;; The following bindings are available, independent of the mode: 
-;; 
+;;
+;; The following bindings are available, independent of the mode:
+;;
 ;; [next]        forms-next-record
 ;; [prior]       forms-prev-record
 ;; [begin]       forms-first-record
 ;; forms mode functions next/prev record and first/last
 ;; record.
 ;;
-;; `local-write-file-hooks' is defined to save the actual data file
+;; `write-file-functions' is defined to save the actual data file
 ;; instead of the buffer data, `revert-file-hook' is defined to
 ;; revert a forms to original.
 \f
 (provide 'forms)                       ;;; official
 (provide 'forms-mode)                  ;;; for compatibility
 
-(defconst forms-version (substring "$Revision: 2.39 $" 11 -2)
+(defconst forms-version (substring "$Revision: 2.48 $" 11 -2)
   "The version number of forms-mode (as string).  The complete RCS id is:
 
-  $Id: forms.el,v 2.39 1999/05/31 08:34:19 eliz Exp $")
+  $Id: forms.el,v 2.48 2003/05/29 23:53:21 monnier Exp $")
 
-(defcustom forms-mode-hooks nil
-  "Hook functions to be run upon entering Forms mode."
+(defcustom forms-mode-hook nil
+  "Hook run upon entering Forms mode."
   :group 'forms
-  :type 'function)
+  :type 'hook)
 \f
 ;;; Mandatory variables - must be set by evaluating the control file.
 
@@ -368,7 +368,7 @@ This can be used to undo the effects of `form-read-file-hook'.")
 
 (defvar forms-fields nil
   "List with fields of the current forms.  First field has number 1.
-This variable is for use by the filter routines only. 
+This variable is for use by the filter routines only.
 The contents may NOT be modified.")
 
 (defcustom forms-use-text-properties t
@@ -417,7 +417,7 @@ Also, initial position is at last record."
 (defvar forms--dyntexts nil
   "Dynamic texts (resulting from function calls) on the screen.")
 
-(defvar forms--the-record-list nil 
+(defvar forms--the-record-list nil
    "List of strings of the current record, as parsed from the file.")
 
 (defvar forms--search-regexp nil
@@ -445,13 +445,13 @@ Also, initial position is at last record."
 (defvar forms--rw-face nil
   "Face used to represent read-write data on the screen.")
 \f
-;;;###autoload 
+;;;###autoload
 (defun forms-mode (&optional primary)
   "Major mode to visit files in a field-structured manner using a form.
 
 Commands:                        Equivalent keys in read-only mode:
  TAB            forms-next-field          TAB
- C-c TAB        forms-next-field          
+ C-c TAB        forms-next-field
  C-c <          forms-first-record         <
  C-c >          forms-last-record          >
  C-c ?          describe-mode              ?
@@ -510,7 +510,7 @@ Commands:                        Equivalent keys in read-only mode:
        (setq forms-new-record-filter nil)
        (setq forms-modified-record-filter nil)
 
-       ;; If running Emacs 19 under X, setup faces to show read-only and 
+       ;; If running Emacs 19 under X, setup faces to show read-only and
        ;; read-write fields.
        (if (fboundp 'make-face)
            (progn
@@ -521,7 +521,7 @@ Commands:                        Equivalent keys in read-only mode:
        ;;(message "forms: processing control file...")
        ;; If enable-local-eval is not set to t the user is asked first.
        (if (or (eq enable-local-eval t)
-               (yes-or-no-p 
+               (yes-or-no-p
                 (concat "Evaluate lisp code in buffer "
                         (buffer-name) " to display forms ")))
            (eval-current-buffer)
@@ -529,7 +529,7 @@ Commands:                        Equivalent keys in read-only mode:
 
        ;; Check if the mandatory variables make sense.
        (or forms-file
-           (error (concat "Forms control file error: " 
+           (error (concat "Forms control file error: "
                           "`forms-file' has not been set")))
 
        ;; Check forms-field-sep first, since it can be needed to
@@ -554,13 +554,13 @@ Commands:                        Equivalent keys in read-only mode:
            (if (and (stringp forms-multi-line)
                     (eq (length forms-multi-line) 1))
                (if (string= forms-multi-line forms-field-sep)
-                   (error (concat "Forms control file error: " 
+                   (error (concat "Forms control file error: "
                                   "`forms-multi-line' is equal to 'forms-field-sep'")))
              (error (concat "Forms control file error: "
                             "`forms-multi-line' must be nil or a one-character string"))))
        (or (fboundp 'set-text-properties)
            (setq forms-use-text-properties nil))
-           
+
        ;; Validate and process forms-format-list.
        ;;(message "forms: pre-processing format list...")
        (make-local-variable 'forms--elements)
@@ -648,30 +648,24 @@ Commands:                        Equivalent keys in read-only mode:
   (let ((read-file-filter forms-read-file-filter)
        (write-file-filter forms-write-file-filter))
     (if read-file-filter
-       (save-excursion
-         (set-buffer forms--file-buffer)
+       (with-current-buffer forms--file-buffer
          (let ((inhibit-read-only t)
                (file-modified (buffer-modified-p)))
            (run-hooks 'read-file-filter)
            (if (not file-modified) (set-buffer-modified-p nil)))
          (if write-file-filter
-             (progn
-               (make-variable-buffer-local 'local-write-file-hooks)
-               (setq local-write-file-hooks (list write-file-filter)))))
+             (add-hook 'write-file-functions write-file-filter nil t)))
       (if write-file-filter
-         (save-excursion
-           (set-buffer forms--file-buffer)
-           (make-variable-buffer-local 'local-write-file-hooks)
-           (setq local-write-file-hooks (list write-file-filter))))))
+         (with-current-buffer forms--file-buffer
+           (add-hook 'write-file-functions write-file-filter nil t)))))
 
   ;; count the number of records, and set see if it may be modified
   (let (ro)
     (setq forms--total-records
-         (save-excursion
+         (with-current-buffer forms--file-buffer
            (prog1
                (progn
                  ;;(message "forms: counting records...")
-                 (set-buffer forms--file-buffer)
                  (bury-buffer (current-buffer))
                  (setq ro buffer-read-only)
                  (count-lines (point-min) (point-max)))
@@ -699,7 +693,7 @@ Commands:                        Equivalent keys in read-only mode:
   (if (= forms--total-records 0)
       ;;(message "forms: proceeding setup (new file)...")
       (progn
-       (insert 
+       (insert
         "GNU Emacs Forms Mode version " forms-version "\n\n"
         (if (file-exists-p forms-file)
             (concat "No records available in file `" forms-file "'\n\n")
@@ -724,7 +718,7 @@ Commands:                        Equivalent keys in read-only mode:
 
   ;; user customising
   ;;(message "forms: proceeding setup (user hooks)...")
-  (run-hooks 'forms-mode-hooks)
+  (run-hooks 'forms-mode-hook 'forms-mode-hooks)
   ;;(message "forms: setting up... done.")
 
   ;; be helpful
@@ -736,7 +730,7 @@ Commands:                        Equivalent keys in read-only mode:
   ;; Symbols in the list are evaluated, and consecutive strings are
   ;; concatenated.
   ;; Array `forms--elements' is constructed that contains the order
-  ;; of the fields on the display. This array is used by 
+  ;; of the fields on the display. This array is used by
   ;; `forms--parser-using-text-properties' to extract the fields data
   ;; from the form on the screen.
   ;; Upon completion, `forms-format-list' is guaranteed correct, so
@@ -757,9 +751,8 @@ Commands:                        Equivalent keys in read-only mode:
   (setq forms--elements (make-vector forms-number-of-fields nil))
 
   (let ((the-list forms-format-list)   ; the list of format elements
-       (this-item 0)                   ; element in list
        (prev-item nil)
-       (field-num 0))                  ; highest field number 
+       (field-num 0))                  ; highest field number
 
     (setq forms-format-list nil)       ; gonna rebuild
 
@@ -785,7 +778,7 @@ Commands:                        Equivalent keys in read-only mode:
            (setq prev-item el)))
 
         ;; Try numeric ...
-        ((numberp el) 
+        ((numberp el)
 
          ;; Validate range.
          (if (or (<= el 0)
@@ -862,8 +855,8 @@ Commands:                        Equivalent keys in read-only mode:
 (defun forms--iif-hook (begin end)
   "`insert-in-front-hooks' function for read-only segments."
 
-  ;; Note start location.  By making it a marker that points one 
-  ;; character beyond the actual location, it is guaranteed to move 
+  ;; Note start location.  By making it a marker that points one
+  ;; character beyond the actual location, it is guaranteed to move
   ;; correctly if text is inserted.
   (or forms--iif-start
       (setq forms--iif-start (copy-marker (1+ (point)))))
@@ -874,12 +867,12 @@ Commands:                        Equivalent keys in read-only mode:
                             'read-only))
       (progn
        ;; Fetch current properties.
-       (setq forms--iif-properties 
+       (setq forms--iif-properties
              (text-properties-at (1- forms--iif-start)))
 
        ;; Replace them.
        (let ((inhibit-read-only t))
-         (set-text-properties 
+         (set-text-properties
           (1- forms--iif-start) forms--iif-start
           (list 'face forms--rw-face 'front-sticky '(face))))
 
@@ -900,7 +893,7 @@ Commands:                        Equivalent keys in read-only mode:
   ;; Restore properties.
   (if forms--iif-start
       (let ((inhibit-read-only t))
-       (set-text-properties 
+       (set-text-properties
         (1- forms--iif-start) forms--iif-start
         forms--iif-properties)))
 
@@ -920,9 +913,9 @@ Commands:                        Equivalent keys in read-only mode:
 
   (let ((forms--marker 0)
        (forms--dyntext 0))
-    (setq 
+    (setq
      forms--format
-     (if forms-use-text-properties 
+     (if forms-use-text-properties
         `(lambda (arg)
            (let ((inhibit-read-only t))
              ,@(apply 'append
@@ -957,9 +950,9 @@ Commands:                        Equivalent keys in read-only mode:
   ;;   (let ((inhibit-read-only t))
   ;;
   ;;     ;; A string, e.g. "text: ".
-  ;;     (set-text-properties 
+  ;;     (set-text-properties
   ;;      (point)
-  ;;      (progn (insert "text: ") (point)) 
+  ;;      (progn (insert "text: ") (point))
   ;;      (list 'face forms--ro-face
   ;;           'read-only 1
   ;;           'insert-in-front-hooks 'forms--iif-hook
@@ -970,7 +963,7 @@ Commands:                        Equivalent keys in read-only mode:
   ;;       (aset forms--markers 0 (point-marker))
   ;;       (insert (elt arg 5))
   ;;       (or (= (point) here)
-  ;;     (set-text-properties 
+  ;;     (set-text-properties
   ;;      here (point)
   ;;      (list 'face forms--rw-face
   ;;            'front-sticky '(face))))
@@ -1008,8 +1001,8 @@ Commands:                        Equivalent keys in read-only mode:
 
   (cond
    ((stringp el)
-    
-    `((set-text-properties 
+
+    `((set-text-properties
        (point)                         ; start at point
        (progn                          ; until after insertion
         (insert ,el)
@@ -1020,16 +1013,16 @@ Commands:                        Equivalent keys in read-only mode:
             'insert-in-front-hooks '(forms--iif-hook)
             'rear-nonsticky '(face read-only insert-in-front-hooks
                                    intangible)))))
-    
+
    ((numberp el)
     `((let ((here (point)))
-       (aset forms--markers 
+       (aset forms--markers
              ,(prog1 forms--marker
                 (setq forms--marker (1+ forms--marker)))
              (point-marker))
        (insert (elt arg ,(1- el)))
        (or (= (point) here)
-           (set-text-properties 
+           (set-text-properties
             here (point)
             (list 'face forms--rw-face
                   'front-sticky '(face)))))))
@@ -1038,7 +1031,7 @@ Commands:                        Equivalent keys in read-only mode:
     `((set-text-properties
        (point)
        (progn
-        (insert (aset forms--dyntexts 
+        (insert (aset forms--dyntexts
                       ,(prog1 forms--dyntext
                          (setq forms--dyntext (1+ forms--dyntext)))
                       ,el))
@@ -1071,7 +1064,7 @@ Commands:                        Equivalent keys in read-only mode:
   ;;   (insert (aset forms--dyntexts 0 (tocol 40)))
   ;;   ... )
 
-  (cond 
+  (cond
    ((stringp el)
     `((insert ,el)))
    ((numberp el)
@@ -1110,8 +1103,8 @@ Commands:                        Equivalent keys in read-only mode:
          (let (here)
            (goto-char (point-min))
            ,@(apply 'append
-                    (mapcar 
-                     'forms--make-parser-elt 
+                    (mapcar
+                     'forms--make-parser-elt
                      (append forms-format-list (list nil)))))))))
 
   (forms--debug 'forms--parser))
@@ -1128,7 +1121,7 @@ Commands:                        Equivalent keys in read-only mode:
       (goto-char (setq here (aref forms--markers i)))
       (if (get-text-property here 'read-only)
          (aset forms--recordv (aref forms--elements i) nil)
-       (if (setq there 
+       (if (setq there
                  (next-single-property-change here 'read-only))
            (aset forms--recordv (aref forms--elements i)
                  (buffer-substring-no-properties here there))
@@ -1144,12 +1137,12 @@ Commands:                        Equivalent keys in read-only mode:
   ;; (lambda nil
   ;;   (let (here)
   ;;     (goto-char (point-min))
-  ;; 
+  ;;
   ;;    ;;  "text: "
   ;;     (if (not (looking-at "text: "))
   ;;       (error "Parse error: cannot find \"text: \""))
   ;;     (forward-char 6)      ; past "text: "
-  ;; 
+  ;;
   ;;     ;;  6
   ;;    ;;  "\nmore text: "
   ;;     (setq here (point))
@@ -1163,7 +1156,7 @@ Commands:                        Equivalent keys in read-only mode:
   ;;         (error "Parse error: not looking at \"%s\"" forms--dyntext))
   ;;     (forward-char (length forms--dyntext))
   ;;     (setq forms--dynamic-text (cdr-safe forms--dynamic-text)))
-  ;;     ... 
+  ;;     ...
   ;;     ;; final flush (due to terminator sentinel, see below)
   ;;   (aset forms--recordv 7 (buffer-substring-no-properties (point) (point-max)))
 
@@ -1219,27 +1212,25 @@ Commands:                        Equivalent keys in read-only mode:
 
       ;; Need a file to do this.
       (if (not (file-exists-p forms-file))
-         (error "Need existing file or explicit 'forms-number-of-records'.")
+         (error "Need existing file or explicit 'forms-number-of-records'")
 
        ;; Visit the file and extract the first record.
        (setq forms--file-buffer (find-file-noselect forms-file))
        (let ((read-file-filter forms-read-file-filter)
              (the-record))
          (setq the-record
-               (save-excursion
-                 (set-buffer forms--file-buffer)
+               (with-current-buffer forms--file-buffer
                  (let ((inhibit-read-only t))
                    (run-hooks 'read-file-filter))
                  (goto-char (point-min))
                  (forms--get-record)))
 
-         ;; This may be overkill, but try to avoid interference with 
+         ;; This may be overkill, but try to avoid interference with
          ;; the normal processing.
          (kill-buffer forms--file-buffer)
 
          ;; Count the number of fields in `the-record'.
-         (let (the-result
-               (start-pos 0)
+         (let ((start-pos 0)
                found-pos
                (field-sep-length (length forms-field-sep)))
            (setq forms-number-of-fields 1)
@@ -1260,8 +1251,8 @@ Commands:                        Equivalent keys in read-only mode:
 (defun forms--set-keymaps ()
   "Set the keymaps used in this mode."
 
-  (use-local-map (if forms-read-only 
-                    forms-mode-ro-map 
+  (use-local-map (if forms-read-only
+                    forms-mode-ro-map
                   forms-mode-edit-map)))
 
 (defun forms--mode-commands ()
@@ -1287,7 +1278,6 @@ Commands:                        Equivalent keys in read-only mode:
   (setq forms-mode-ro-map (make-keymap))
   (suppress-keymap forms-mode-ro-map)
   (define-key forms-mode-ro-map "\C-c" forms-mode-map)
-  (define-key forms-mode-ro-map "\t" 'forms-next-field)
   (define-key forms-mode-ro-map "q" 'forms-toggle-read-only)
   (define-key forms-mode-ro-map "l" 'forms-jump-record)
   (define-key forms-mode-ro-map "n" 'forms-next-record)
@@ -1304,7 +1294,6 @@ Commands:                        Equivalent keys in read-only mode:
 
   ;; This is the normal, local map.
   (setq forms-mode-edit-map (make-keymap))
-  (define-key forms-mode-edit-map "\t"   'forms-next-field)
   (define-key forms-mode-edit-map "\C-c" forms-mode-map)
   (forms--mode-commands1 forms-mode-edit-map)
   (forms--mode-menu-edit forms-mode-edit-map)
@@ -1403,9 +1392,9 @@ Commands:                        Equivalent keys in read-only mode:
   (put 'forms-delete-record 'menu-enable '(not forms-read-only))
 )
 
-(defun forms--mode-commands1 (map) 
+(defun forms--mode-commands1 (map)
   "Helper routine to define keys."
-  (define-key map [TAB] 'forms-next-field)
+  (define-key map "\t" 'forms-next-field)
   (define-key map [S-tab] 'forms-prev-field)
   (define-key map [next] 'forms-next-record)
   (define-key map [prior] 'forms-prev-record)
@@ -1423,23 +1412,15 @@ Commands:                        Equivalent keys in read-only mode:
   ;; scroll-up -> forms-next-record
   (if forms-forms-scroll
       (progn
-       (substitute-key-definition 'scroll-up 'forms-next-record
-                                  (current-local-map)
-                                  (current-global-map))
-       (substitute-key-definition 'scroll-down 'forms-prev-record
-                                  (current-local-map)
-                                  (current-global-map))))
+       (local-set-key [remap scroll-up] 'forms-next-record)
+       (local-set-key [remap scroll-down] 'forms-prev-record)))
   ;;
   ;; beginning-of-buffer -> forms-first-record
   ;; end-of-buffer -> forms-end-record
   (if forms-forms-jump
       (progn
-       (substitute-key-definition 'beginning-of-buffer 'forms-first-record
-                                  (current-local-map)
-                                  (current-global-map))
-       (substitute-key-definition 'end-of-buffer 'forms-last-record
-                                  (current-local-map)
-                                  (current-global-map))))
+       (local-set-key [remap beginning-of-buffer] 'forms-first-record)
+       (local-set-key [remap end-of-buffer] 'forms-last-record)))
   ;;
   ;; Save buffer
   (local-set-key "\C-x\C-s" 'forms-save-buffer)
@@ -1463,14 +1444,13 @@ Commands:                        Equivalent keys in read-only mode:
   "Translate in SUBJ all chars ARG into char REP.  ARG and REP should
  be single-char strings."
   (let ((i 0)
-       (x (length subj))
        (re (regexp-quote arg))
        (k (string-to-char rep)))
     (while (setq i (string-match re subj i))
       (aset subj i k)
       (setq i (1+ i)))))
 
-(defun forms--exit (query &optional save)
+(defun forms--exit (&optional save)
   "Internal exit from forms mode function."
 
   (let ((buf (buffer-name forms--file-buffer)))
@@ -1478,8 +1458,7 @@ Commands:                        Equivalent keys in read-only mode:
     (if (and save
             (buffer-modified-p forms--file-buffer))
        (forms-save-buffer))
-    (save-excursion
-      (set-buffer forms--file-buffer)
+    (with-current-buffer forms--file-buffer
       (delete-auto-save-file-if-necessary)
       (kill-buffer (current-buffer)))
     (if (get-buffer buf)       ; not killed???
@@ -1534,10 +1513,10 @@ Commands:                        Equivalent keys in read-only mode:
       (message "Warning: this record has %d fields instead of %d"
               (length forms--the-record-list) forms-number-of-fields))
     (if (< (length forms--the-record-list) forms-number-of-fields)
-       (setq forms--the-record-list 
+       (setq forms--the-record-list
              (append forms--the-record-list
-                     (make-list 
-                      (- forms-number-of-fields 
+                     (make-list
+                      (- forms-number-of-fields
                          (length forms--the-record-list))
                       "")))))
 
@@ -1557,7 +1536,7 @@ Commands:                        Equivalent keys in read-only mode:
   "Parse contents of form into list of strings."
   ;; The contents of the form are parsed, and a new list of strings
   ;; is constructed.
-  ;; A vector with the strings from the original record is 
+  ;; A vector with the strings from the original record is
   ;; constructed, which is updated with the new contents.  Therefore
   ;; fields which were not in the form are not modified.
   ;; Finally, the vector is transformed into a list for further processing.
@@ -1593,11 +1572,11 @@ As a side effect: sets `forms--the-record-list'."
     (setq forms--the-record-list (forms--parse-form))
     (setq the-record
          (mapconcat 'identity forms--the-record-list forms-field-sep))
-    
+
     (if (string-match (regexp-quote forms-field-sep)
                      (mapconcat 'identity forms--the-record-list ""))
        (error "Field separator occurs in record - update refused"))
-    
+
     ;; Handle multi-line fields, if allowed.
     (if forms-multi-line
        (forms--trans the-record "\n" forms-multi-line))
@@ -1606,12 +1585,10 @@ As a side effect: sets `forms--the-record-list'."
     (if (string-match "\n" the-record)
        (error "Multi-line fields in this record - update refused"))
 
-    (save-excursion
-      (set-buffer forms--file-buffer)
+    (with-current-buffer forms--file-buffer
       ;; Use delete-region instead of kill-region, to avoid
       ;; adding junk to the kill-ring.
-      (delete-region (save-excursion (beginning-of-line) (point))
-                    (save-excursion (end-of-line) (point)))
+      (delete-region (line-beginning-position) (line-end-position))
       (insert the-record)
       (beginning-of-line))))
 
@@ -1643,15 +1620,15 @@ As a side effect: sets `forms--the-record-list'."
     (find-file-other-window fn)
     (or forms--mode-setup (forms-mode t))))
 
-(defun forms-exit (query)
+(defun forms-exit ()
   "Normal exit from Forms mode.  Modified buffers are saved."
-  (interactive "P")
-  (forms--exit query t))
+  (interactive)
+  (forms--exit t))
 
-(defun forms-exit-no-save (query)
+(defun forms-exit-no-save ()
   "Exit from Forms mode without saving buffers."
-  (interactive "P")
-  (forms--exit query nil))
+  (interactive)
+  (forms--exit nil))
 \f
 ;;; Navigating commands
 
@@ -1665,6 +1642,16 @@ As a side effect: sets `forms--the-record-list'."
   (interactive "P")
   (forms-jump-record (- forms--current-record (prefix-numeric-value arg)) t))
 
+(defun forms--goto-record (rn &optional current)
+  "Goto record number RN.
+If CURRENT is provided, it specifies the current record and can be used
+to speed up access to RN.  Returns the number of records missing, if any."
+  (if current
+      (forward-line (- rn current))
+    ;; goto-line does not do what we want when the buffer is narrowed.
+    (goto-char (point-min))
+    (forward-line (1- rn))))
+
 (defun forms-jump-record (arg &optional relative)
   "Jump to a random record."
   (interactive "NRecord number: ")
@@ -1683,24 +1670,18 @@ As a side effect: sets `forms--the-record-list'."
   (forms--checkmod)
 
   ;; Calculate displacement.
-  (let ((disp (- arg forms--current-record))
-       (cur forms--current-record))
+  (let ((cur forms--current-record))
 
     ;; `forms--show-record' needs it now.
     (setq forms--current-record arg)
 
     ;; Get the record and show it.
     (forms--show-record
-     (save-excursion
-       (set-buffer forms--file-buffer)
+     (with-current-buffer forms--file-buffer
        (beginning-of-line)
 
        ;; Move, and adjust the amount if needed (shouldn't happen).
-       (if relative
-          (if (zerop disp)
-              nil
-            (setq cur (+ cur disp (- (forward-line disp)))))
-        (setq cur (+ cur disp (- (goto-line arg)))))
+       (setq cur (- arg (forms--goto-record arg (if relative cur))))
 
        (forms--get-record)))
 
@@ -1720,9 +1701,8 @@ As a side effect: sets `forms--the-record-list'."
 As a side effect: re-calculates the number of records in the data file."
   (interactive)
   (let
-      ((numrec 
-       (save-excursion
-         (set-buffer forms--file-buffer)
+      ((numrec
+       (with-current-buffer forms--file-buffer
          (count-lines (point-min) (point-max)))))
     (if (= numrec forms--total-records)
        nil
@@ -1747,8 +1727,7 @@ Otherwise enables edit mode if the visited file is writable."
 
       ;; Enable edit mode, if possible.
       (let ((ro forms-read-only))
-       (if (save-excursion
-             (set-buffer forms--file-buffer)
+       (if (with-current-buffer forms--file-buffer
              buffer-read-only)
            (progn
              (setq forms-read-only t)
@@ -1776,7 +1755,7 @@ Otherwise enables edit mode if the visited file is writable."
 (defun forms-insert-record (arg)
   "Create a new record before the current one.
 With ARG: store the record after the current one.
-If `forms-new-record-filter' contains the name of a function, 
+If `forms-new-record-filter' contains the name of a function,
 it is called to fill (some of) the fields with default values.
 If `forms-insert-after is non-nil, the default behavior is to insert
 after the current record."
@@ -1808,13 +1787,12 @@ after the current record."
          the-list
          forms-field-sep))
 
-    (save-excursion
-      (set-buffer forms--file-buffer)
-      (goto-line ln)
+    (with-current-buffer forms--file-buffer
+      (forms--goto-record ln)
       (open-line 1)
       (insert the-record)
       (beginning-of-line))
-    
+
     (setq forms--current-record ln))
 
   (setq forms--total-records (1+ forms--total-records))
@@ -1831,9 +1809,8 @@ after the current record."
   (if (or arg
          (y-or-n-p "Really delete this record? "))
       (let ((ln forms--current-record))
-       (save-excursion
-         (set-buffer forms--file-buffer)
-         (goto-line ln)
+       (with-current-buffer forms--file-buffer
+         (forms--goto-record ln)
          ;; Use delete-region instead of kill-region, to avoid
          ;; adding junk to the kill-ring.
          (delete-region (progn (beginning-of-line) (point))
@@ -1846,8 +1823,8 @@ after the current record."
 
 (defun forms-search-forward (regexp)
   "Search forward for record containing REGEXP."
-  (interactive 
-   (list (read-string (concat "Search forward for" 
+  (interactive
+   (list (read-string (concat "Search forward for"
                                  (if forms--search-regexp
                                   (concat " ("
                                           forms--search-regexp
@@ -1857,10 +1834,8 @@ after the current record."
       (setq regexp forms--search-regexp))
   (forms--checkmod)
 
-  (let (the-line the-record here
-                (fld-sep forms-field-sep))
-    (save-excursion
-      (set-buffer forms--file-buffer)
+  (let (the-line the-record here)
+    (with-current-buffer forms--file-buffer
       (end-of-line)
       (setq here (point))
       (if (or (re-search-forward regexp nil t)
@@ -1882,8 +1857,8 @@ after the current record."
 
 (defun forms-search-backward (regexp)
   "Search backward for record containing REGEXP."
-  (interactive 
-   (list (read-string (concat "Search backward for" 
+  (interactive
+   (list (read-string (concat "Search backward for"
                                  (if forms--search-regexp
                                   (concat " ("
                                           forms--search-regexp
@@ -1893,10 +1868,8 @@ after the current record."
       (setq regexp forms--search-regexp))
   (forms--checkmod)
 
-  (let (the-line the-record here
-                (fld-sep forms-field-sep))
-    (save-excursion
-      (set-buffer forms--file-buffer)
+  (let (the-line the-record here)
+    (with-current-buffer forms--file-buffer
       (beginning-of-line)
       (setq here (point))
       (if (or (re-search-backward regexp nil t)
@@ -1926,12 +1899,11 @@ after writing out the data."
   (let ((write-file-filter forms-write-file-filter)
        (read-file-filter forms-read-file-filter)
        (cur forms--current-record))
-    (save-excursion
-      (set-buffer forms--file-buffer)
+    (with-current-buffer forms--file-buffer
       (let ((inhibit-read-only t))
-       ;; Write file hooks are run via local-write-file-hooks.
-       ;; (if write-file-filter 
-       ;;  (save-excursion 
+       ;; Write file hooks are run via write-file-functions.
+       ;; (if write-file-filter
+       ;;  (save-excursion
        ;;   (run-hooks 'write-file-filter)))
 
        ;; If they have a write-file-filter, force the buffer to be
@@ -2026,16 +1998,14 @@ after writing out the data."
     (while (<= nb-record forms--total-records)
       (forms-jump-record nb-record)
       (setq record (buffer-string))
-      (save-excursion
-       (set-buffer (get-buffer-create "*forms-print*"))
+      (with-current-buffer (get-buffer-create "*forms-print*")
        (goto-char (buffer-end 1))
        (insert record)
        (setq buffer-read-only nil)
        (if (< nb-record total-nb-records)
            (insert "\n\f\n")))
       (setq nb-record (1+ nb-record)))
-    (save-excursion
-      (set-buffer "*forms-print*")
+    (with-current-buffer "*forms-print*"
       (print-buffer)
       (set-buffer-modified-p nil)
       (kill-buffer (current-buffer)))
@@ -2081,13 +2051,13 @@ Usage: (setq forms-number-of-fields
                    (setq ret (concat ret (prin1-to-string vel) "\n")))
                (setq ret (concat ret "<unbound>" "\n")))
              (if (fboundp el)
-                 (setq ret (concat ret (prin1-to-string (symbol-function el)) 
+                 (setq ret (concat ret (prin1-to-string (symbol-function el))
                                    "\n"))))))
-       (save-excursion
-         (set-buffer (get-buffer-create "*forms-mode debug*"))
+       (with-current-buffer (get-buffer-create "*forms-mode debug*")
          (if (zerop (buffer-size))
              (emacs-lisp-mode))
          (goto-char (point-max))
          (insert ret)))))
 
-;;; forms.el ends here.
+;;; arch-tag: 4a6695c7-d47a-4a21-809b-5cec7f8ec7a1
+;;; forms.el ends here