]> code.delx.au - gnu-emacs/blobdiff - lisp/emerge.el
(ucs-names): New internal variable.
[gnu-emacs] / lisp / emerge.el
index 40ecbbe3187d6dc1bfc8430919b7a5ec4453e572..182cfa4b7fd5379cd70f25f2d945c94dbd375fe0 100644 (file)
@@ -2,7 +2,9 @@
 
 ;;; The author has placed this file in the public domain.
 
 
 ;;; The author has placed this file in the public domain.
 
-;; Author: Dale R. Worley <drw@math.mit.edu>
+;; This file is part of GNU Emacs.
+
+;; Author: Dale R. Worley <worley@world.std.com>
 ;; Version: 5fsf
 ;; Keywords: unix, tools
 
 ;; Version: 5fsf
 ;; Keywords: unix, tools
 
 ;; LOST DATA OR LOST PROFITS, OR FOR ANY SPECIAL, INCIDENTAL OR CONSEQUENTIAL
 ;; DAMAGES.
 
 ;; LOST DATA OR LOST PROFITS, OR FOR ANY SPECIAL, INCIDENTAL OR CONSEQUENTIAL
 ;; DAMAGES.
 
+;;; Commentary:
+
 ;;; Code:
 
 ;;; Code:
 
+;;;###autoload
+(defvar menu-bar-emerge-menu (make-sparse-keymap "Emerge"))
+;;;###autoload (fset 'menu-bar-emerge-menu (symbol-value 'menu-bar-emerge-menu))
+
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-merge-directories]
+;;;###autoload   '("Merge Directories..." . emerge-merge-directories))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-revisions-with-ancestor]
+;;;###autoload   '("Revisions with Ancestor..." . emerge-revisions-with-ancestor))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-revisions]
+;;;###autoload   '("Revisions..." . emerge-revisions))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-files-with-ancestor]
+;;;###autoload   '("Files with Ancestor..." . emerge-files-with-ancestor))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-files]
+;;;###autoload   '("Files..." . emerge-files))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-buffers-with-ancestor]
+;;;###autoload   '("Buffers with Ancestor..." . emerge-buffers-with-ancestor))
+;;;###autoload (define-key menu-bar-emerge-menu [emerge-buffers]
+;;;###autoload   '("Buffers..." . emerge-buffers))
+
+;; There aren't really global variables, just dynamic bindings
+(defvar A-begin)
+(defvar A-end)
+(defvar B-begin)
+(defvar B-end)
+(defvar diff)
+(defvar diff-vector)
+(defvar merge-begin)
+(defvar merge-end)
+(defvar template)
+(defvar valid-diff)
+
 ;;; Macros
 
 (defmacro emerge-eval-in-buffer (buffer &rest forms)
   "Macro to switch to BUFFER, evaluate FORMS, returns to original buffer.
 Differs from `save-excursion' in that it doesn't save the point and mark."
 ;;; Macros
 
 (defmacro emerge-eval-in-buffer (buffer &rest forms)
   "Macro to switch to BUFFER, evaluate FORMS, returns to original buffer.
 Differs from `save-excursion' in that it doesn't save the point and mark."
-  (` (let ((StartBuffer (current-buffer)))
+  `(let ((StartBuffer (current-buffer)))
     (unwind-protect
     (unwind-protect
-       (progn
-         (set-buffer (, buffer))
-         (,@ forms))
-      (set-buffer StartBuffer)))))
+         (progn
+           (set-buffer ,buffer)
+           ,@forms)
+      (set-buffer StartBuffer))))
 
 
-(defmacro emerge-defvar-local (var value doc) 
-  "Defines SYMBOL as an advertised variable.  
+(defmacro emerge-defvar-local (var value doc)
+  "Defines SYMBOL as an advertised variable.
 Performs a defvar, then executes `make-variable-buffer-local' on
 the variable.  Also sets the `preserved' property, so that
 Performs a defvar, then executes `make-variable-buffer-local' on
 the variable.  Also sets the `preserved' property, so that
-`kill-all-local-variables' (called by major-mode setting commands) 
+`kill-all-local-variables' (called by major-mode setting commands)
 won't destroy Emerge control variables."
 won't destroy Emerge control variables."
-  (` (progn
-       (defvar (, var) (, value) (, doc))
-       (make-variable-buffer-local '(, var))
-       (put '(, var) 'preserved t))))
+  `(progn
+    (defvar ,var ,value ,doc)
+    (make-variable-buffer-local ',var)
+    (put ',var 'preserved t)))
 
 ;; Add entries to minor-mode-alist so that emerge modes show correctly
 
 ;; Add entries to minor-mode-alist so that emerge modes show correctly
-(setq emerge-minor-modes-list '((emerge-mode " Emerge")
-                               (emerge-fast-mode " F")
-                               (emerge-edit-mode " E")
-                               (emerge-auto-advance " A")
-                               (emerge-skip-prefers " S")))
+(defvar emerge-minor-modes-list
+  '((emerge-mode " Emerge")
+    (emerge-fast-mode " F")
+    (emerge-edit-mode " E")
+    (emerge-auto-advance " A")
+    (emerge-skip-prefers " S")))
 (if (not (assq 'emerge-mode minor-mode-alist))
     (setq minor-mode-alist (append emerge-minor-modes-list
                                   minor-mode-alist)))
 (if (not (assq 'emerge-mode minor-mode-alist))
     (setq minor-mode-alist (append emerge-minor-modes-list
                                   minor-mode-alist)))
@@ -85,71 +121,117 @@ When called interactively, displays the version."
 
 ;;; Emerge configuration variables
 
 
 ;;; Emerge configuration variables
 
+(defgroup emerge nil
+  "Merge diffs under Emacs control."
+  :group 'tools)
+
 ;; Commands that produce difference files
 ;; All that can be configured is the name of the programs to execute
 ;; (emerge-diff-program and emerge-diff3-program) and the options
 ;; to be provided (emerge-diff-options).  The order in which the file names
 ;; are given is fixed.
 ;; The file names are always expanded (see expand-file-name) before being
 ;; Commands that produce difference files
 ;; All that can be configured is the name of the programs to execute
 ;; (emerge-diff-program and emerge-diff3-program) and the options
 ;; to be provided (emerge-diff-options).  The order in which the file names
 ;; are given is fixed.
 ;; The file names are always expanded (see expand-file-name) before being
-;; passed to diff, thus they need not be invoked under a shell that 
+;; passed to diff, thus they need not be invoked under a shell that
 ;; understands `~'.
 ;; The code which processes the diff/diff3 output depends on all the
 ;; finicky details of their output, including the somewhat strange
 ;; way they number lines of a file.
 ;; understands `~'.
 ;; The code which processes the diff/diff3 output depends on all the
 ;; finicky details of their output, including the somewhat strange
 ;; way they number lines of a file.
-(defvar emerge-diff-program "diff"
-  "*Name of the program which compares two files.")
-(defvar emerge-diff3-program "diff3"
+(defcustom emerge-diff-program "diff"
+  "*Name of the program which compares two files."
+  :type 'string
+  :group 'emerge)
+(defcustom emerge-diff3-program "diff3"
   "*Name of the program which compares three files.
   "*Name of the program which compares three files.
-Its arguments are the ancestor file and the two variant files.")
-(defvar emerge-diff-options ""
-  "*Options to pass to `emerge-diff-program' and `emerge-diff3-program'.")
-(defvar emerge-match-diff-line (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)"))
-                                (concat "^" x "\\([acd]\\)" x "$"))
+Its arguments are the ancestor file and the two variant files."
+  :type 'string
+  :group 'emerge)
+(defcustom emerge-diff-options ""
+  "*Options to pass to `emerge-diff-program' and `emerge-diff3-program'."
+  :type 'string
+  :group 'emerge)
+(defcustom emerge-match-diff-line
+  (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)"))
+    (concat "^" x "\\([acd]\\)" x "$"))
   "*Pattern to match lines produced by diff that describe differences.
   "*Pattern to match lines produced by diff that describe differences.
-This is as opposed to lines from the source files.")
-(defvar emerge-diff-ok-lines-regexp
+This is as opposed to lines from the source files."
+  :type 'regexp
+  :group 'emerge)
+(defcustom emerge-diff-ok-lines-regexp
   "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\)"
   "*Regexp that matches normal output lines from `emerge-diff-program'.
   "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\)"
   "*Regexp that matches normal output lines from `emerge-diff-program'.
-Lines that do not match are assumed to be error messages.")
-(defvar emerge-diff3-ok-lines-regexp
+Lines that do not match are assumed to be error messages."
+  :type 'regexp
+  :group 'emerge)
+(defcustom emerge-diff3-ok-lines-regexp
   "^\\([1-3]:\\|====\\|  \\)"
   "*Regexp that matches normal output lines from `emerge-diff3-program'.
   "^\\([1-3]:\\|====\\|  \\)"
   "*Regexp that matches normal output lines from `emerge-diff3-program'.
-Lines that do not match are assumed to be error messages.")
-
-(defvar emerge-rcs-ci-program "ci"
-  "*Name of the program that checks in RCS revisions.")
-(defvar emerge-rcs-co-program "co"
-  "*Name of the program that checks out RCS revisions.")
-
-(defvar emerge-process-local-variables nil
+Lines that do not match are assumed to be error messages."
+  :type 'regexp
+  :group 'emerge)
+
+(defcustom emerge-rcs-ci-program "ci"
+  "*Name of the program that checks in RCS revisions."
+  :type 'string
+  :group 'emerge)
+(defcustom emerge-rcs-co-program "co"
+  "*Name of the program that checks out RCS revisions."
+  :type 'string
+  :group 'emerge)
+
+(defcustom emerge-process-local-variables nil
   "*Non-nil if Emerge should process local-variables lists in merge buffers.
 \(You can explicitly request processing the local-variables
   "*Non-nil if Emerge should process local-variables lists in merge buffers.
 \(You can explicitly request processing the local-variables
-by executing `(hack-local-variables)'.)")
-(defvar emerge-execute-line-deletions nil
+by executing `(hack-local-variables)'.)"
+  :type 'boolean
+  :group 'emerge)
+(defcustom emerge-execute-line-deletions nil
   "*If non-nil: `emerge-execute-line' makes no output if an input was deleted.
 It concludes that an input version has been deleted when an ancestor entry
 is present, only one A or B entry is present, and an output entry is present.
 If nil: In such circumstances, the A or B file that is present will be
   "*If non-nil: `emerge-execute-line' makes no output if an input was deleted.
 It concludes that an input version has been deleted when an ancestor entry
 is present, only one A or B entry is present, and an output entry is present.
 If nil: In such circumstances, the A or B file that is present will be
-copied to the designated output file.")
+copied to the designated output file."
+  :type 'boolean
+  :group 'emerge)
+
+(defcustom emerge-before-flag "vvvvvvvvvvvvvvvvvvvv\n"
+  "*Flag placed above the highlighted block of code.  Must end with newline.
+Must be set before Emerge is loaded, or  emerge-new-flags  must be run
+after setting."
+  :type 'string
+  :group 'emerge)
+(defcustom emerge-after-flag "^^^^^^^^^^^^^^^^^^^^\n"
+  "*Flag placed below the highlighted block of code.  Must end with newline.
+Must be set before Emerge is loaded, or  emerge-new-flags  must be run
+after setting."
+  :type 'string
+  :group 'emerge)
 
 ;; Hook variables
 
 
 ;; Hook variables
 
-(defvar emerge-startup-hook nil
-  "*Hook to run in the merge buffer after the merge has been set up.")
-(defvar emerge-select-hook nil
+(defcustom emerge-startup-hook nil
+  "*Hook to run in the merge buffer after the merge has been set up."
+  :type 'hook
+  :group 'emerge)
+(defcustom emerge-select-hook nil
   "*Hook to run after a difference has been selected.
   "*Hook to run after a difference has been selected.
-The variable `n' holds the (internal) number of the difference.")
-(defvar emerge-unselect-hook nil
+The variable `n' holds the (internal) number of the difference."
+  :type 'hook
+  :group 'emerge)
+(defcustom emerge-unselect-hook nil
   "*Hook to run after a difference has been unselected.
   "*Hook to run after a difference has been unselected.
-The variable `n' holds the (internal) number of the difference.")
+The variable `n' holds the (internal) number of the difference."
+  :type 'hook
+  :group 'emerge)
 
 ;; Variables to control the default directories of the arguments to
 ;; Emerge commands.
 
 
 ;; Variables to control the default directories of the arguments to
 ;; Emerge commands.
 
-(defvar emerge-default-last-directories nil
+(defcustom emerge-default-last-directories nil
   "*If nil, default dir for filenames in emerge is `default-directory'.
 If non-nil, filenames complete in the directory of the last argument of the
   "*If nil, default dir for filenames in emerge is `default-directory'.
 If non-nil, filenames complete in the directory of the last argument of the
-same type to an `emerge-files...' command.")
+same type to an `emerge-files...' command."
+  :type 'boolean
+  :group 'emerge)
 
 (defvar emerge-last-dir-A nil
   "Last directory for the first file of an `emerge-files...' command.")
 
 (defvar emerge-last-dir-A nil
   "Last directory for the first file of an `emerge-files...' command.")
@@ -166,6 +248,20 @@ same type to an `emerge-files...' command.")
 (defvar emerge-last-revision-ancestor nil
   "Last RCS revision used for ancestor file of an `emerge-revisions...' command.")
 
 (defvar emerge-last-revision-ancestor nil
   "Last RCS revision used for ancestor file of an `emerge-revisions...' command.")
 
+(defvar emerge-before-flag-length)
+(defvar emerge-before-flag-lines)
+(defvar emerge-before-flag-match)
+(defvar emerge-after-flag-length)
+(defvar emerge-after-flag-lines)
+(defvar emerge-after-flag-match)
+(defvar emerge-diff-buffer)
+(defvar emerge-diff-error-buffer)
+(defvar emerge-prefix-argument)
+(defvar emerge-file-out)
+(defvar emerge-exit-func)
+(defvar emerge-globalized-difference-list)
+(defvar emerge-globalized-number-of-differences)
+
 ;; The flags used to mark differences in the buffers.
 
 ;; These function definitions need to be up here, because they are used
 ;; The flags used to mark differences in the buffers.
 
 ;; These function definitions need to be up here, because they are used
@@ -192,39 +288,29 @@ depend on the flags."
       (setq i (match-end 0)))
     count))
 
       (setq i (match-end 0)))
     count))
 
-(defvar emerge-before-flag "vvvvvvvvvvvvvvvvvvvv\n"
-  "*Flag placed above the highlighted block of code.  Must end with newline.
-Must be set before Emerge is loaded, or  emerge-new-flags  must be run
-after setting.")
-(defvar emerge-after-flag "^^^^^^^^^^^^^^^^^^^^\n"
-  "*Flag placed below the highlighted block of code.  Must end with newline.
-Must be set before Emerge is loaded, or  emerge-new-flags  must be run
-after setting.")
-
 ;; Calculate dependent variables
 (emerge-new-flags)
 
 ;; Calculate dependent variables
 (emerge-new-flags)
 
-(defvar emerge-min-visible-lines 3
+(defcustom emerge-min-visible-lines 3
   "*Number of lines that we want to show above and below the flags when we are
   "*Number of lines that we want to show above and below the flags when we are
-displaying a difference.")
-
-(defvar emerge-temp-file-prefix
-  (let ((env (getenv "TMPDIR"))
-       d)
-    (setq d (if (and env (> (length env) 0))
-               env
-             "/tmp"))
-    (if (= (aref d (1- (length d))) ?/)
-       (setq d (substring d 0 -1)))
-    (concat d "/emerge"))
+displaying a difference."
+  :type 'integer
+  :group 'emerge)
+
+(defcustom emerge-temp-file-prefix
+  (expand-file-name "emerge" temporary-file-directory)
   "*Prefix to put on Emerge temporary file names.
   "*Prefix to put on Emerge temporary file names.
-Do not start with `~/' or `~user-name/'.")
+Do not start with `~/' or `~USERNAME/'."
+  :type 'string
+  :group 'emerge)
 
 
-(defvar emerge-temp-file-mode 384      ; u=rw only
-  "*Mode for Emerge temporary files.")
+(defcustom emerge-temp-file-mode 384   ; u=rw only
+  "*Mode for Emerge temporary files."
+  :type 'integer
+  :group 'emerge)
 
 
-(defvar emerge-combine-versions-template
-  "#ifdef NEW\n%b#else /* NEW */\n%a#endif /* NEW */\n"
+(defcustom emerge-combine-versions-template
+  "#ifdef NEW\n%b#else /* not NEW */\n%a#endif /* not NEW */\n"
   "*Template for `emerge-combine-versions' to combine the two versions.
 The template is inserted as a string, with the following interpolations:
        %a      the A version of the difference
   "*Template for `emerge-combine-versions' to combine the two versions.
 The template is inserted as a string, with the following interpolations:
        %a      the A version of the difference
@@ -232,7 +318,9 @@ The template is inserted as a string, with the following interpolations:
        %%      the character `%'
 Don't forget to end the template with a newline.
 Note that this variable can be made local to a particular merge buffer by
        %%      the character `%'
 Don't forget to end the template with a newline.
 Note that this variable can be made local to a particular merge buffer by
-giving a prefix argument to `emerge-set-combine-versions-template'.")
+giving a prefix argument to `emerge-set-combine-versions-template'."
+  :type 'string
+  :group 'emerge)
 
 ;; Build keymaps
 
 
 ;; Build keymaps
 
@@ -245,9 +333,20 @@ must be prefixed by \\<emerge-fast-keymap>\\[emerge-basic-keymap] in `edit' mode
   "Local keymap used in Emerge `fast' mode.
 Makes Emerge commands directly available.")
 
   "Local keymap used in Emerge `fast' mode.
 Makes Emerge commands directly available.")
 
-(defvar emerge-command-prefix "\C-c\C-c"
+(defvar emerge-options-menu
+  (make-sparse-keymap "Options"))
+
+(defvar emerge-merge-menu
+  (make-sparse-keymap "Merge"))
+
+(defvar emerge-move-menu
+  (make-sparse-keymap "Move"))
+
+(defcustom emerge-command-prefix "\C-c\C-c"
   "*Command prefix for Emerge commands in `edit' mode.
   "*Command prefix for Emerge commands in `edit' mode.
-Must be set before Emerge is loaded.")
+Must be set before Emerge is loaded."
+  :type 'string
+  :group 'emerge)
 
 ;; This function sets up the fixed keymaps.  It is executed when the first
 ;; Emerge is done to allow the user maximum time to set up the global keymap.
 
 ;; This function sets up the fixed keymaps.  It is executed when the first
 ;; Emerge is done to allow the user maximum time to set up the global keymap.
@@ -305,10 +404,84 @@ Must be set before Emerge is loaded.")
   ;; Allow emerge-fast-keymap to be referenced indirectly
   (fset 'emerge-fast-keymap emerge-fast-keymap)
   ;; Suppress write-file and save-buffer
   ;; Allow emerge-fast-keymap to be referenced indirectly
   (fset 'emerge-fast-keymap emerge-fast-keymap)
   ;; Suppress write-file and save-buffer
-  (substitute-key-definition 'write-file 'emerge-query-write-file
-                            emerge-fast-keymap (current-global-map))
-  (substitute-key-definition 'save-buffer 'emerge-query-save-buffer
-                            emerge-fast-keymap (current-global-map)))
+  (define-key emerge-fast-keymap [remap write-file] 'emerge-query-write-file)
+  (define-key emerge-fast-keymap [remap save-buffer] 'emerge-query-save-buffer)
+
+  (define-key emerge-basic-keymap [menu-bar] (make-sparse-keymap))
+
+  (define-key emerge-fast-keymap [menu-bar options]
+    (cons "Options" emerge-options-menu))
+  (define-key emerge-fast-keymap [menu-bar merge]
+    (cons "Merge" emerge-merge-menu))
+  (define-key emerge-fast-keymap [menu-bar move]
+    (cons "Move" emerge-move-menu))
+
+  (define-key emerge-move-menu [emerge-scroll-reset]
+    '("Scroll Reset" . emerge-scroll-reset))
+  (define-key emerge-move-menu [emerge-scroll-right]
+    '("Scroll Right" . emerge-scroll-right))
+  (define-key emerge-move-menu [emerge-scroll-left]
+    '("Scroll Left" . emerge-scroll-left))
+  (define-key emerge-move-menu [emerge-scroll-down]
+    '("Scroll Down" . emerge-scroll-down))
+  (define-key emerge-move-menu [emerge-scroll-up]
+    '("Scroll Up" . emerge-scroll-up))
+  (define-key emerge-move-menu [emerge-recenter]
+    '("Recenter" . emerge-recenter))
+  (define-key emerge-move-menu [emerge-mark-difference]
+    '("Mark Difference" . emerge-mark-difference))
+  (define-key emerge-move-menu [emerge-jump-to-difference]
+    '("Jump To Difference" . emerge-jump-to-difference))
+  (define-key emerge-move-menu [emerge-find-difference]
+    '("Find Difference" . emerge-find-difference))
+  (define-key emerge-move-menu [emerge-previous-difference]
+    '("Previous Difference" . emerge-previous-difference))
+  (define-key emerge-move-menu [emerge-next-difference]
+    '("Next Difference" . emerge-next-difference))
+
+
+  (define-key emerge-options-menu [emerge-one-line-window]
+    '("One Line Window" . emerge-one-line-window))
+  (define-key emerge-options-menu [emerge-set-merge-mode]
+    '("Set Merge Mode" . emerge-set-merge-mode))
+  (define-key emerge-options-menu [emerge-set-combine-template]
+    '("Set Combine Template..." . emerge-set-combine-template))
+  (define-key emerge-options-menu [emerge-default-B]
+    '("Default B" . emerge-default-B))
+  (define-key emerge-options-menu [emerge-default-A]
+    '("Default A" . emerge-default-A))
+  (define-key emerge-options-menu [emerge-skip-prefers]
+    '("Skip Prefers" . emerge-skip-prefers))
+  (define-key emerge-options-menu [emerge-auto-advance]
+    '("Auto Advance" . emerge-auto-advance))
+  (define-key emerge-options-menu [emerge-edit-mode]
+    '("Edit Mode" . emerge-edit-mode))
+  (define-key emerge-options-menu [emerge-fast-mode]
+    '("Fast Mode" . emerge-fast-mode))
+
+  (define-key emerge-merge-menu [emerge-abort] '("Abort" . emerge-abort))
+  (define-key emerge-merge-menu [emerge-quit] '("Quit" . emerge-quit))
+  (define-key emerge-merge-menu [emerge-split-difference]
+    '("Split Difference" . emerge-split-difference))
+  (define-key emerge-merge-menu [emerge-join-differences]
+    '("Join Differences" . emerge-join-differences))
+  (define-key emerge-merge-menu [emerge-trim-difference]
+    '("Trim Difference" . emerge-trim-difference))
+  (define-key emerge-merge-menu [emerge-combine-versions]
+    '("Combine Versions" . emerge-combine-versions))
+  (define-key emerge-merge-menu [emerge-copy-as-kill-B]
+    '("Copy B as Kill" . emerge-copy-as-kill-B))
+  (define-key emerge-merge-menu [emerge-copy-as-kill-A]
+    '("Copy A as Kill" . emerge-copy-as-kill-A))
+  (define-key emerge-merge-menu [emerge-insert-B]
+    '("Insert B" . emerge-insert-B))
+  (define-key emerge-merge-menu [emerge-insert-A]
+    '("Insert A" . emerge-insert-A))
+  (define-key emerge-merge-menu [emerge-select-B]
+    '("Select B" . emerge-select-B))
+  (define-key emerge-merge-menu [emerge-select-A]
+    '("Select A" . emerge-select-A)))
+
 
 ;; Variables which control each merge.  They are local to the merge buffer.
 
 
 ;; Variables which control each merge.  They are local to the merge buffer.
 
@@ -396,7 +569,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
 ;;; Setup functions for two-file mode.
 
 (defun emerge-files-internal (file-A file-B &optional startup-hooks quit-hooks
 ;;; Setup functions for two-file mode.
 
 (defun emerge-files-internal (file-A file-B &optional startup-hooks quit-hooks
-                                    output-file)
+                              output-file)
   (if (not (file-readable-p file-A))
       (error "File `%s' does not exist or is not readable" file-A))
   (if (not (file-readable-p file-B))
   (if (not (file-readable-p file-A))
       (error "File `%s' does not exist or is not readable" file-A))
   (if (not (file-readable-p file-B))
@@ -409,17 +582,17 @@ This is *not* a user option, since Emerge uses it for its own processing.")
     (if output-file
        (setq emerge-last-dir-output (file-name-directory output-file)))
     ;; Make sure the entire files are seen, and they reflect what is on disk
     (if output-file
        (setq emerge-last-dir-output (file-name-directory output-file)))
     ;; Make sure the entire files are seen, and they reflect what is on disk
-    (emerge-eval-in-buffer 
+    (emerge-eval-in-buffer
      buffer-A
      (widen)
      (let ((temp (file-local-copy file-A)))
        (if temp
           (setq file-A temp
                 startup-hooks
      buffer-A
      (widen)
      (let ((temp (file-local-copy file-A)))
        (if temp
           (setq file-A temp
                 startup-hooks
-                (cons (` (lambda () (delete-file (, file-A))))
+                (cons `(lambda () (delete-file ,file-A))
                       startup-hooks))
                       startup-hooks))
-        ;; Verify that the file matches the buffer
-        (emerge-verify-file-buffer))))
+           ;; Verify that the file matches the buffer
+           (emerge-verify-file-buffer))))
     (emerge-eval-in-buffer
      buffer-B
      (widen)
     (emerge-eval-in-buffer
      buffer-B
      (widen)
@@ -427,10 +600,10 @@ This is *not* a user option, since Emerge uses it for its own processing.")
        (if temp
           (setq file-B temp
                 startup-hooks
        (if temp
           (setq file-B temp
                 startup-hooks
-                (cons (` (lambda () (delete-file (, file-B))))
+                (cons `(lambda () (delete-file ,file-B))
                       startup-hooks))
                       startup-hooks))
-        ;; Verify that the file matches the buffer
-        (emerge-verify-file-buffer))))
+           ;; Verify that the file matches the buffer
+           (emerge-verify-file-buffer))))
     (emerge-setup buffer-A file-A buffer-B file-B startup-hooks quit-hooks
                  output-file)))
 
     (emerge-setup buffer-A file-A buffer-B file-B startup-hooks quit-hooks
                  output-file)))
 
@@ -460,7 +633,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
           (if output-file
               (concat "Output to file: " output-file)
             (concat "Output to buffer: " (buffer-name merge-buffer))))
           (if output-file
               (concat "Output to file: " output-file)
             (concat "Output to buffer: " (buffer-name merge-buffer))))
-     (insert-buffer emerge-A-buffer)
+     (save-excursion (insert-buffer-substring emerge-A-buffer))
      (emerge-set-keys)
      (setq emerge-difference-list (emerge-make-diff-list file-A file-B))
      (setq emerge-number-of-differences (length emerge-difference-list))
      (emerge-set-keys)
      (setq emerge-difference-list (emerge-make-diff-list file-A file-B))
      (setq emerge-number-of-differences (length emerge-difference-list))
@@ -496,20 +669,20 @@ This is *not* a user option, since Emerge uses it for its own processing.")
      diff-buffer
      (goto-char (point-min))
      (while (re-search-forward emerge-match-diff-line nil t)
      diff-buffer
      (goto-char (point-min))
      (while (re-search-forward emerge-match-diff-line nil t)
-       (let* ((a-begin (string-to-int (buffer-substring (match-beginning 1)
-                                                       (match-end 1))))
+       (let* ((a-begin (string-to-number (buffer-substring (match-beginning 1)
+                                                           (match-end 1))))
              (a-end  (let ((b (match-beginning 3))
                            (e (match-end 3)))
                        (if b
              (a-end  (let ((b (match-beginning 3))
                            (e (match-end 3)))
                        (if b
-                           (string-to-int (buffer-substring b e))
+                           (string-to-number (buffer-substring b e))
                          a-begin)))
              (diff-type (buffer-substring (match-beginning 4) (match-end 4)))
                          a-begin)))
              (diff-type (buffer-substring (match-beginning 4) (match-end 4)))
-             (b-begin (string-to-int (buffer-substring (match-beginning 5)
-                                                       (match-end 5))))
+             (b-begin (string-to-number (buffer-substring (match-beginning 5)
+                                                           (match-end 5))))
              (b-end (let ((b (match-beginning 7))
                           (e (match-end 7)))
                       (if b
              (b-end (let ((b (match-beginning 7))
                           (e (match-end 7)))
                       (if b
-                          (string-to-int (buffer-substring b e))
+                          (string-to-number (buffer-substring b e))
                         b-begin))))
         ;; fix the beginning and end numbers, because diff is somewhat
         ;; strange about how it numbers lines
                         b-begin))))
         ;; fix the beginning and end numbers, because diff is somewhat
         ;; strange about how it numbers lines
@@ -539,7 +712,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
   (emerge-eval-in-buffer
    emerge-diff-error-buffer
    (erase-buffer)
   (emerge-eval-in-buffer
    emerge-diff-error-buffer
    (erase-buffer)
-   (insert-buffer emerge-diff-buffer)
+   (save-excursion (insert-buffer-substring emerge-diff-buffer))
    (delete-matching-lines ok-regexp)))
 
 ;;; Top-level and setup functions for three-file mode.
    (delete-matching-lines ok-regexp)))
 
 ;;; Top-level and setup functions for three-file mode.
@@ -570,10 +743,10 @@ This is *not* a user option, since Emerge uses it for its own processing.")
        (if temp
           (setq file-A temp
                 startup-hooks
        (if temp
           (setq file-A temp
                 startup-hooks
-                (cons (` (lambda () (delete-file (, file-A))))
+                (cons `(lambda () (delete-file ,file-A))
                       startup-hooks))
                       startup-hooks))
-        ;; Verify that the file matches the buffer
-        (emerge-verify-file-buffer))))
+           ;; Verify that the file matches the buffer
+           (emerge-verify-file-buffer))))
     (emerge-eval-in-buffer
      buffer-B
      (widen)
     (emerge-eval-in-buffer
      buffer-B
      (widen)
@@ -581,10 +754,10 @@ This is *not* a user option, since Emerge uses it for its own processing.")
        (if temp
           (setq file-B temp
                 startup-hooks
        (if temp
           (setq file-B temp
                 startup-hooks
-                (cons (` (lambda () (delete-file (, file-B))))
+                (cons `(lambda () (delete-file ,file-B))
                       startup-hooks))
                       startup-hooks))
-        ;; Verify that the file matches the buffer
-        (emerge-verify-file-buffer))))
+           ;; Verify that the file matches the buffer
+           (emerge-verify-file-buffer))))
     (emerge-eval-in-buffer
      buffer-ancestor
      (widen)
     (emerge-eval-in-buffer
      buffer-ancestor
      (widen)
@@ -592,10 +765,10 @@ This is *not* a user option, since Emerge uses it for its own processing.")
        (if temp
           (setq file-ancestor temp
                 startup-hooks
        (if temp
           (setq file-ancestor temp
                 startup-hooks
-                (cons (` (lambda () (delete-file (, file-ancestor))))
+                (cons `(lambda () (delete-file ,file-ancestor))
                       startup-hooks))
                       startup-hooks))
-        ;; Verify that the file matches the buffer
-        (emerge-verify-file-buffer))))
+           ;; Verify that the file matches the buffer
+           (emerge-verify-file-buffer))))
     (emerge-setup-with-ancestor buffer-A file-A buffer-B file-B
                                buffer-ancestor file-ancestor
                                startup-hooks quit-hooks output-file)))
     (emerge-setup-with-ancestor buffer-A file-A buffer-B file-B
                                buffer-ancestor file-ancestor
                                startup-hooks quit-hooks output-file)))
@@ -629,7 +802,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
           (if output-file
               (concat "Output to file: " output-file)
             (concat "Output to buffer: " (buffer-name merge-buffer))))
           (if output-file
               (concat "Output to file: " output-file)
             (concat "Output to buffer: " (buffer-name merge-buffer))))
-     (insert-buffer emerge-A-buffer)
+     (save-excursion (insert-buffer-substring emerge-A-buffer))
      (emerge-set-keys)
      (setq emerge-difference-list
           (emerge-make-diff3-list file-A file-B file-ancestor))
      (emerge-set-keys)
      (setq emerge-difference-list
           (emerge-make-diff3-list file-A file-B file-ancestor))
@@ -673,7 +846,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
         ;; if the A and B files are the same, ignore the difference
         (if (not (string-equal agreement "2"))
             (setq list
         ;; if the A and B files are the same, ignore the difference
         (if (not (string-equal agreement "2"))
             (setq list
-                  (cons 
+                  (cons
                    (let (group-1 group-3 pos)
                      (setq pos (point))
                      (setq group-1 (emerge-get-diff3-group "1"))
                    (let (group-1 group-3 pos)
                      (setq pos (point))
                      (setq group-1 (emerge-get-diff3-group "1"))
@@ -701,16 +874,16 @@ This is *not* a user option, since Emerge uses it for its own processing.")
        ;; it is a "c" group
        (if (match-beginning 2)
            ;; it has two numbers
        ;; it is a "c" group
        (if (match-beginning 2)
            ;; it has two numbers
-           (list (string-to-int
+           (list (string-to-number
                   (buffer-substring (match-beginning 1) (match-end 1)))
                   (buffer-substring (match-beginning 1) (match-end 1)))
-                 (1+ (string-to-int
+                 (1+ (string-to-number
                       (buffer-substring (match-beginning 3) (match-end 3)))))
          ;; it has one number
                       (buffer-substring (match-beginning 3) (match-end 3)))))
          ;; it has one number
-         (let ((x (string-to-int
+         (let ((x (string-to-number
                    (buffer-substring (match-beginning 1) (match-end 1)))))
            (list x (1+ x))))
       ;; it is an "a" group
                    (buffer-substring (match-beginning 1) (match-end 1)))))
            (list x (1+ x))))
       ;; it is an "a" group
-      (let ((x (1+ (string-to-int
+      (let ((x (1+ (string-to-number
                    (buffer-substring (match-beginning 1) (match-end 1))))))
        (list x x)))))
 
                    (buffer-substring (match-beginning 1) (match-end 1))))))
        (list x x)))))
 
@@ -724,17 +897,16 @@ This is *not* a user option, since Emerge uses it for its own processing.")
    (let (f)
      (list current-prefix-arg
           (setq f (emerge-read-file-name "File A to merge" emerge-last-dir-A
    (let (f)
      (list current-prefix-arg
           (setq f (emerge-read-file-name "File A to merge" emerge-last-dir-A
-                                         nil nil))
-          (emerge-read-file-name "File B to merge" emerge-last-dir-B nil f)
+                                         nil nil t))
+          (emerge-read-file-name "File B to merge" emerge-last-dir-B nil f t)
           (and current-prefix-arg
                (emerge-read-file-name "Output file" emerge-last-dir-output
           (and current-prefix-arg
                (emerge-read-file-name "Output file" emerge-last-dir-output
-                                      f f)))))
+                                      f f nil)))))
+  (if file-out
+      (add-hook 'quit-hooks `(lambda () (emerge-files-exit ,file-out))))
   (emerge-files-internal
    file-A file-B startup-hooks
   (emerge-files-internal
    file-A file-B startup-hooks
-   (if file-out
-       (cons (` (lambda () (emerge-files-exit (, file-out))))
-            quit-hooks)
-     quit-hooks)
+   quit-hooks
    file-out))
 
 ;;;###autoload
    file-out))
 
 ;;;###autoload
@@ -745,19 +917,18 @@ This is *not* a user option, since Emerge uses it for its own processing.")
    (let (f)
      (list current-prefix-arg
           (setq f (emerge-read-file-name "File A to merge" emerge-last-dir-A
    (let (f)
      (list current-prefix-arg
           (setq f (emerge-read-file-name "File A to merge" emerge-last-dir-A
-                                         nil nil))
-          (emerge-read-file-name "File B to merge" emerge-last-dir-B nil f)
+                                         nil nil t))
+          (emerge-read-file-name "File B to merge" emerge-last-dir-B nil f t)
           (emerge-read-file-name "Ancestor file" emerge-last-dir-ancestor
           (emerge-read-file-name "Ancestor file" emerge-last-dir-ancestor
-                                 nil f)
+                                 nil f t)
           (and current-prefix-arg
                (emerge-read-file-name "Output file" emerge-last-dir-output
           (and current-prefix-arg
                (emerge-read-file-name "Output file" emerge-last-dir-output
-                                      f f)))))
+                                      f f nil)))))
+  (if file-out
+      (add-hook 'quit-hooks `(lambda () (emerge-files-exit ,file-out))))
   (emerge-files-with-ancestor-internal
    file-A file-B file-ancestor startup-hooks
   (emerge-files-with-ancestor-internal
    file-A file-B file-ancestor startup-hooks
-   (if file-out
-       (cons (` (lambda () (emerge-files-exit (, file-out))))
-            quit-hooks)
-     quit-hooks)
+   quit-hooks
    file-out))
 
 ;; Write the merge buffer out in place of the file the A buffer is visiting.
    file-out))
 
 ;; Write the merge buffer out in place of the file the A buffer is visiting.
@@ -782,17 +953,17 @@ This is *not* a user option, since Emerge uses it for its own processing.")
      (write-region (point-min) (point-max) emerge-file-B nil 'no-message))
     (emerge-setup (get-buffer buffer-A) emerge-file-A
                  (get-buffer buffer-B) emerge-file-B
      (write-region (point-min) (point-max) emerge-file-B nil 'no-message))
     (emerge-setup (get-buffer buffer-A) emerge-file-A
                  (get-buffer buffer-B) emerge-file-B
-                 (cons (` (lambda ()
-                            (delete-file (, emerge-file-A))
-                            (delete-file (, emerge-file-B))))
+                 (cons `(lambda ()
+                          (delete-file ,emerge-file-A)
+                          (delete-file ,emerge-file-B))
                        startup-hooks)
                  quit-hooks
                  nil)))
 
 ;;;###autoload
 (defun emerge-buffers-with-ancestor (buffer-A buffer-B buffer-ancestor
                        startup-hooks)
                  quit-hooks
                  nil)))
 
 ;;;###autoload
 (defun emerge-buffers-with-ancestor (buffer-A buffer-B buffer-ancestor
-                                             &optional startup-hooks
-                                             quit-hooks)
+                                     &optional startup-hooks
+                                     quit-hooks)
   "Run Emerge on two buffers, giving another buffer as the ancestor."
   (interactive
    "bBuffer A to merge: \nbBuffer B to merge: \nbAncestor buffer: ")
   "Run Emerge on two buffers, giving another buffer as the ancestor."
   (interactive
    "bBuffer A to merge: \nbBuffer B to merge: \nbAncestor buffer: ")
@@ -813,11 +984,11 @@ This is *not* a user option, since Emerge uses it for its own processing.")
                                (get-buffer buffer-B) emerge-file-B
                                (get-buffer buffer-ancestor)
                                emerge-file-ancestor
                                (get-buffer buffer-B) emerge-file-B
                                (get-buffer buffer-ancestor)
                                emerge-file-ancestor
-                               (cons (` (lambda ()
-                                          (delete-file (, emerge-file-A))
-                                          (delete-file (, emerge-file-B))
-                                          (delete-file
-                                           (, emerge-file-ancestor))))
+                               (cons `(lambda ()
+                                        (delete-file ,emerge-file-A)
+                                        (delete-file ,emerge-file-B)
+                                        (delete-file
+                                         ,emerge-file-ancestor))
                                      startup-hooks)
                                quit-hooks
                                nil)))
                                      startup-hooks)
                                quit-hooks
                                nil)))
@@ -832,7 +1003,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
     (setq command-line-args-left (nthcdr 3 command-line-args-left))
     (emerge-files-internal
      file-a file-b nil
     (setq command-line-args-left (nthcdr 3 command-line-args-left))
     (emerge-files-internal
      file-a file-b nil
-     (list (` (lambda () (emerge-command-exit (, file-out))))))))
+     (list `(lambda () (emerge-command-exit ,file-out))))))
 
 ;;;###autoload
 (defun emerge-files-with-ancestor-command ()
 
 ;;;###autoload
 (defun emerge-files-with-ancestor-command ()
@@ -846,16 +1017,16 @@ This is *not* a user option, since Emerge uses it for its own processing.")
          (setq file-anc (nth 1 command-line-args-left))
          (setq file-out (nth 4 command-line-args-left))
          (setq command-line-args-left (nthcdr 5 command-line-args-left)))
          (setq file-anc (nth 1 command-line-args-left))
          (setq file-out (nth 4 command-line-args-left))
          (setq command-line-args-left (nthcdr 5 command-line-args-left)))
-      ;; arguments are "file-a file-b ancestor file-out"
-      (setq file-a (nth 0 command-line-args-left))
-      (setq file-b (nth 1 command-line-args-left))
-      (setq file-anc (nth 2 command-line-args-left))
-      (setq file-out (nth 3 command-line-args-left))
-      (setq command-line-args-left (nthcdr 4 command-line-args-left)))
+        ;; arguments are "file-a file-b ancestor file-out"
+        (setq file-a (nth 0 command-line-args-left))
+        (setq file-b (nth 1 command-line-args-left))
+        (setq file-anc (nth 2 command-line-args-left))
+        (setq file-out (nth 3 command-line-args-left))
+        (setq command-line-args-left (nthcdr 4 command-line-args-left)))
     (emerge-files-with-ancestor-internal
      file-a file-b file-anc nil
     (emerge-files-with-ancestor-internal
      file-a file-b file-anc nil
-     (list (` (lambda () (emerge-command-exit (, file-out))))))))
-      
+     (list `(lambda () (emerge-command-exit ,file-out))))))
+
 (defun emerge-command-exit (file-out)
   (emerge-write-and-delete file-out)
   (kill-emacs (if emerge-prefix-argument 1 0)))
 (defun emerge-command-exit (file-out)
   (emerge-write-and-delete file-out)
   (kill-emacs (if emerge-prefix-argument 1 0)))
@@ -867,7 +1038,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
   (setq emerge-file-out file-out)
   (emerge-files-internal
    file-a file-b nil
   (setq emerge-file-out file-out)
   (emerge-files-internal
    file-a file-b nil
-   (list (` (lambda () (emerge-remote-exit (, file-out) '(, exit-func)))))
+   (list `(lambda () (emerge-remote-exit ,file-out ',emerge-exit-func)))
    file-out)
   (throw 'client-wait nil))
 
    file-out)
   (throw 'client-wait nil))
 
@@ -876,17 +1047,18 @@ This is *not* a user option, since Emerge uses it for its own processing.")
   (setq emerge-file-out file-out)
   (emerge-files-with-ancestor-internal
    file-a file-b file-anc nil
   (setq emerge-file-out file-out)
   (emerge-files-with-ancestor-internal
    file-a file-b file-anc nil
-   (list (` (lambda () (emerge-remote-exit (, file-out) '(, exit-func)))))
+   (list `(lambda () (emerge-remote-exit ,file-out ',emerge-exit-func)))
    file-out)
   (throw 'client-wait nil))
 
    file-out)
   (throw 'client-wait nil))
 
-(defun emerge-remote-exit (file-out exit-func)
+(defun emerge-remote-exit (file-out emerge-exit-func)
   (emerge-write-and-delete file-out)
   (kill-buffer emerge-merge-buffer)
   (emerge-write-and-delete file-out)
   (kill-buffer emerge-merge-buffer)
-  (funcall exit-func (if emerge-prefix-argument 1 0)))
+  (funcall emerge-exit-func (if emerge-prefix-argument 1 0)))
 
 ;;; Functions to start Emerge on RCS versions
 
 
 ;;; Functions to start Emerge on RCS versions
 
+;;;###autoload
 (defun emerge-revisions (arg file revision-A revision-B
                         &optional startup-hooks quit-hooks)
   "Emerge two RCS revisions of a file."
 (defun emerge-revisions (arg file revision-A revision-B
                         &optional startup-hooks quit-hooks)
   "Emerge two RCS revisions of a file."
@@ -900,16 +1072,17 @@ This is *not* a user option, since Emerge uses it for its own processing.")
   (emerge-revisions-internal
    file revision-A revision-B startup-hooks
    (if arg
   (emerge-revisions-internal
    file revision-A revision-B startup-hooks
    (if arg
-       (cons (` (lambda ()
-                 (shell-command
-                  (, (format "%s %s" emerge-rcs-ci-program file)))))
+       (cons `(lambda ()
+               (shell-command
+                ,(format "%s %s" emerge-rcs-ci-program file)))
             quit-hooks)
             quit-hooks)
-     quit-hooks)))
+       quit-hooks)))
 
 
+;;;###autoload
 (defun emerge-revisions-with-ancestor (arg file revision-A
 (defun emerge-revisions-with-ancestor (arg file revision-A
-                                          revision-B ancestor
-                                          &optional
-                                          startup-hooks quit-hooks)
+                                       revision-B ancestor
+                                       &optional
+                                       startup-hooks quit-hooks)
   "Emerge two RCS revisions of a file, with another revision as ancestor."
   (interactive
    (list current-prefix-arg
   "Emerge two RCS revisions of a file, with another revision as ancestor."
   (interactive
    (list current-prefix-arg
@@ -924,14 +1097,14 @@ This is *not* a user option, since Emerge uses it for its own processing.")
    file revision-A revision-B ancestor startup-hooks
    (if arg
        (let ((cmd ))
    file revision-A revision-B ancestor startup-hooks
    (if arg
        (let ((cmd ))
-        (cons (` (lambda ()
-                   (shell-command
-                    (, (format "%s %s" emerge-rcs-ci-program file)))))
+        (cons `(lambda ()
+                 (shell-command
+                  ,(format "%s %s" emerge-rcs-ci-program file)))
               quit-hooks))
               quit-hooks))
-     quit-hooks)))
+       quit-hooks)))
 
 (defun emerge-revisions-internal (file revision-A revision-B &optional
 
 (defun emerge-revisions-internal (file revision-A revision-B &optional
-                                     startup-hooks quit-hooks output-file)
+                                  startup-hooks quit-hooks output-file)
   (let ((buffer-A (get-buffer-create (format "%s,%s" file revision-A)))
        (buffer-B (get-buffer-create (format "%s,%s" file revision-B)))
        (emerge-file-A (emerge-make-temp-file "A"))
   (let ((buffer-A (get-buffer-create (format "%s,%s" file revision-A)))
        (buffer-B (get-buffer-create (format "%s,%s" file revision-B)))
        (emerge-file-A (emerge-make-temp-file "A"))
@@ -956,18 +1129,18 @@ This is *not* a user option, since Emerge uses it for its own processing.")
     ;; Do the merge
     (emerge-setup buffer-A emerge-file-A
                  buffer-B emerge-file-B
     ;; Do the merge
     (emerge-setup buffer-A emerge-file-A
                  buffer-B emerge-file-B
-                 (cons (` (lambda ()
-                            (delete-file (, emerge-file-A))
-                            (delete-file (, emerge-file-B))))
+                 (cons `(lambda ()
+                          (delete-file ,emerge-file-A)
+                          (delete-file ,emerge-file-B))
                        startup-hooks)
                        startup-hooks)
-                 (cons (` (lambda () (emerge-files-exit (, file))))
+                 (cons `(lambda () (emerge-files-exit ,file))
                        quit-hooks)
                  nil)))
 
 (defun emerge-revision-with-ancestor-internal (file revision-A revision-B
                        quit-hooks)
                  nil)))
 
 (defun emerge-revision-with-ancestor-internal (file revision-A revision-B
-                                                   ancestor
-                                                   &optional startup-hooks
-                                                   quit-hooks output-file)
+                                               ancestor
+                                               &optional startup-hooks
+                                               quit-hooks output-file)
   (let ((buffer-A (get-buffer-create (format "%s,%s" file revision-A)))
        (buffer-B (get-buffer-create (format "%s,%s" file revision-B)))
        (buffer-ancestor (get-buffer-create (format "%s,%s" file ancestor)))
   (let ((buffer-A (get-buffer-create (format "%s,%s" file revision-A)))
        (buffer-B (get-buffer-create (format "%s,%s" file revision-B)))
        (buffer-ancestor (get-buffer-create (format "%s,%s" file ancestor)))
@@ -1004,12 +1177,12 @@ This is *not* a user option, since Emerge uses it for its own processing.")
     (emerge-setup-with-ancestor
      buffer-A emerge-file-A buffer-B emerge-file-B
      buffer-ancestor emerge-ancestor
     (emerge-setup-with-ancestor
      buffer-A emerge-file-A buffer-B emerge-file-B
      buffer-ancestor emerge-ancestor
-     (cons (` (lambda ()
-               (delete-file (, emerge-file-A))
-               (delete-file (, emerge-file-B))
-               (delete-file (, emerge-ancestor))))
+     (cons `(lambda ()
+             (delete-file ,emerge-file-A)
+             (delete-file ,emerge-file-B)
+             (delete-file ,emerge-ancestor))
           startup-hooks)
           startup-hooks)
-     (cons (` (lambda () (emerge-files-exit (, file))))
+     (cons `(lambda () (emerge-files-exit ,file))
           quit-hooks)
      output-file)))
 
           quit-hooks)
      output-file)))
 
@@ -1054,26 +1227,26 @@ Otherwise, the A or B file present is copied to the output file."
            (goto-char (match-end 0))
            ;; Store the filename in the right variable
            (cond
            (goto-char (match-end 0))
            ;; Store the filename in the right variable
            (cond
-            ((string-equal tag "a")
-             (if file-A
-                 (error "This line has two `A' entries"))
-             (setq file-A file))
-            ((string-equal tag "b")
-             (if file-B
-                 (error "This line has two `B' entries"))
-             (setq file-B file))
-            ((or (string-equal tag "anc") (string-equal tag "ancestor"))
-             (if file-ancestor
-                 (error "This line has two `ancestor' entries"))
-             (setq file-ancestor file))
-            ((or (string-equal tag "out") (string-equal tag "output"))
-             (if file-out
-                 (error "This line has two `output' entries"))
-             (setq file-out file))
-            (t
-             (error "Unrecognized entry"))))
-       ;; If the match on the entry pattern failed
-       (error "Unparsable entry")))
+              ((string-equal tag "a")
+               (if file-A
+                   (error "This line has two `A' entries"))
+               (setq file-A file))
+              ((string-equal tag "b")
+               (if file-B
+                   (error "This line has two `B' entries"))
+               (setq file-B file))
+              ((or (string-equal tag "anc") (string-equal tag "ancestor"))
+               (if file-ancestor
+                   (error "This line has two `ancestor' entries"))
+               (setq file-ancestor file))
+              ((or (string-equal tag "out") (string-equal tag "output"))
+               (if file-out
+                   (error "This line has two `output' entries"))
+               (setq file-out file))
+              (t
+               (error "Unrecognized entry"))))
+          ;; If the match on the entry pattern failed
+          (error "Unparsable entry")))
     ;; Make sure that file-A and file-B are present
     (if (not (or (and file-A file-B) file-out))
        (error "Must have both `A' and `B' entries"))
     ;; Make sure that file-A and file-B are present
     (if (not (or (and file-A file-B) file-out))
        (error "Must have both `A' and `B' entries"))
@@ -1084,45 +1257,48 @@ Otherwise, the A or B file present is copied to the output file."
     (beginning-of-line 2)
     ;; Execute the correct command
     (cond
     (beginning-of-line 2)
     ;; Execute the correct command
     (cond
-     ;; Merge of two files with ancestor
-     ((and file-A file-B file-ancestor)
-      (message "Merging %s and %s..." file-A file-B)
-      (emerge-files-with-ancestor (not (not file-out)) file-A file-B
-                                 file-ancestor file-out
-                                 nil
-                                 ;; When done, return to this buffer.
-                                 (list
-                                  (` (lambda ()
-                                       (switch-to-buffer (, (current-buffer)))
-                                       (message "Merge done."))))))
-     ;; Merge of two files without ancestor
-     ((and file-A file-B)
-      (message "Merging %s and %s..." file-A file-B)
-      (emerge-files (not (not file-out)) file-A file-B file-out
-                   nil
-                   ;; When done, return to this buffer.
-                   (list 
-                    (` (lambda ()
-                         (switch-to-buffer (, (current-buffer)))
-                         (message "Merge done."))))))
-     ;; There is an output file (or there would have been an error above),
-     ;; but only one input file.
-     ;; The file appears to have been deleted in one version; do nothing.
-     ((and file-ancestor emerge-execute-line-deletions)
-      (message "No action."))
-     ;; The file should be copied from the version that contains it
-     (t (let ((input-file (or file-A file-B)))
-         (message "Copying...")
-         (copy-file input-file file-out)
-         (message "%s copied to %s." input-file file-out))))))
+      ;; Merge of two files with ancestor
+      ((and file-A file-B file-ancestor)
+       (message "Merging %s and %s..." file-A file-B)
+       (emerge-files-with-ancestor (not (not file-out)) file-A file-B
+                                   file-ancestor file-out
+                                   nil
+                                   ;; When done, return to this buffer.
+                                   (list
+                                    `(lambda ()
+                                      (switch-to-buffer ,(current-buffer))
+                                      (message "Merge done.")))))
+      ;; Merge of two files without ancestor
+      ((and file-A file-B)
+       (message "Merging %s and %s..." file-A file-B)
+       (emerge-files (not (not file-out)) file-A file-B file-out
+                     nil
+                     ;; When done, return to this buffer.
+                     (list
+                      `(lambda ()
+                        (switch-to-buffer ,(current-buffer))
+                        (message "Merge done.")))))
+      ;; There is an output file (or there would have been an error above),
+      ;; but only one input file.
+      ;; The file appears to have been deleted in one version; do nothing.
+      ((and file-ancestor emerge-execute-line-deletions)
+       (message "No action."))
+      ;; The file should be copied from the version that contains it
+      (t (let ((input-file (or file-A file-B)))
+           (message "Copying...")
+           (copy-file input-file file-out)
+           (message "%s copied to %s." input-file file-out))))))
 
 ;;; Sample function for creating information for emerge-execute-line
 
 
 ;;; Sample function for creating information for emerge-execute-line
 
-(defvar emerge-merge-directories-filename-regexp "[^.]"
-  "Regexp describing files to be processed by `emerge-merge-directories'.")
+(defcustom emerge-merge-directories-filename-regexp "[^.]"
+  "Regexp describing files to be processed by `emerge-merge-directories'."
+  :type 'regexp
+  :group 'emerge)
 
 
+;;;###autoload
 (defun emerge-merge-directories (a-dir b-dir ancestor-dir output-dir)
 (defun emerge-merge-directories (a-dir b-dir ancestor-dir output-dir)
-  (interactive 
+  (interactive
    (list
     (read-file-name "A directory: " nil nil 'confirm)
     (read-file-name "B directory: " nil nil 'confirm)
    (list
     (read-file-name "A directory: " nil nil 'confirm)
     (read-file-name "B directory: " nil nil 'confirm)
@@ -1241,6 +1417,16 @@ Otherwise, the A or B file present is copied to the output file."
   ;; Install the Emerge commands
   (emerge-force-define-key emerge-edit-keymap emerge-command-prefix
                           'emerge-basic-keymap)
   ;; Install the Emerge commands
   (emerge-force-define-key emerge-edit-keymap emerge-command-prefix
                           'emerge-basic-keymap)
+  (define-key emerge-edit-keymap [menu-bar] (make-sparse-keymap))
+
+  ;; Create the additional menu bar items.
+  (define-key emerge-edit-keymap [menu-bar options]
+    (cons "Options" emerge-options-menu))
+  (define-key emerge-edit-keymap [menu-bar merge]
+    (cons "Merge" emerge-merge-menu))
+  (define-key emerge-edit-keymap [menu-bar move]
+    (cons "Move" emerge-move-menu))
+
   ;; Suppress write-file and save-buffer
   (substitute-key-definition 'write-file
                             'emerge-query-write-file
   ;; Suppress write-file and save-buffer
   (substitute-key-definition 'write-file
                             'emerge-query-write-file
@@ -1248,10 +1434,8 @@ Otherwise, the A or B file present is copied to the output file."
   (substitute-key-definition 'save-buffer
                             'emerge-query-save-buffer
                             emerge-edit-keymap)
   (substitute-key-definition 'save-buffer
                             'emerge-query-save-buffer
                             emerge-edit-keymap)
-  (substitute-key-definition 'write-file 'emerge-query-write-file
-                            emerge-edit-keymap (current-global-map))
-  (substitute-key-definition 'save-buffer 'emerge-query-save-buffer
-                            emerge-edit-keymap (current-global-map))
+  (define-key emerge-edit-keymap [remap write-file] 'emerge-query-write-file)
+  (define-key emerge-edit-keymap [remap save-buffer] 'emerge-query-save-buffer)
   (use-local-map emerge-fast-keymap)
   (setq emerge-edit-mode nil)
   (setq emerge-fast-mode t))
   (use-local-map emerge-fast-keymap)
   (setq emerge-edit-mode nil)
   (setq emerge-fast-mode t))
@@ -1282,7 +1466,7 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'."
                                     emerge-merging-values)))))
 
 (defun emerge-restore-buffer-characteristics ()
                                     emerge-merging-values)))))
 
 (defun emerge-restore-buffer-characteristics ()
-  "Restores characteristics saved by `emerge-remember-buffer-characteristics'."
+  "Restore characteristics saved by `emerge-remember-buffer-characteristics'."
   (let ((A-values emerge-A-buffer-values)
        (B-values emerge-B-buffer-values))
     (emerge-eval-in-buffer emerge-A-buffer
   (let ((A-values emerge-A-buffer-values)
        (B-values emerge-B-buffer-values))
     (emerge-eval-in-buffer emerge-A-buffer
@@ -1292,6 +1476,12 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'."
                           (emerge-restore-variables emerge-saved-variables
                                                     B-values))))
 
                           (emerge-restore-variables emerge-saved-variables
                                                     B-values))))
 
+;; Move to line DESIRED-LINE assuming we are at line CURRENT-LINE.
+;; Return DESIRED-LINE.
+(defun emerge-goto-line (desired-line current-line)
+  (forward-line (- desired-line current-line))
+  desired-line)
+
 (defun emerge-convert-diffs-to-markers (A-buffer
                                        B-buffer
                                        merge-buffer
 (defun emerge-convert-diffs-to-markers (A-buffer
                                        B-buffer
                                        merge-buffer
@@ -1299,17 +1489,13 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'."
   (let* (marker-list
         (A-point-min (emerge-eval-in-buffer A-buffer (point-min)))
         (offset (1- A-point-min))
   (let* (marker-list
         (A-point-min (emerge-eval-in-buffer A-buffer (point-min)))
         (offset (1- A-point-min))
-        (A-hidden-lines (emerge-eval-in-buffer
-                         A-buffer
-                         (save-restriction
-                           (widen)
-                           (count-lines 1 A-point-min))))
         (B-point-min (emerge-eval-in-buffer B-buffer (point-min)))
         (B-point-min (emerge-eval-in-buffer B-buffer (point-min)))
-        (B-hidden-lines (emerge-eval-in-buffer
-                         B-buffer
-                         (save-restriction
-                           (widen)
-                           (count-lines 1 B-point-min)))))
+        ;; Record current line number in each buffer
+        ;; so we don't have to count from the beginning.
+        (a-line 1)
+        (b-line 1))
+    (emerge-eval-in-buffer A-buffer (goto-char (point-min)))
+    (emerge-eval-in-buffer B-buffer (goto-char (point-min)))
     (while lineno-list
       (let* ((list-element (car lineno-list))
             a-begin-marker
     (while lineno-list
       (let* ((list-element (car lineno-list))
             a-begin-marker
@@ -1326,15 +1512,15 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'."
        ;; place markers at the appropriate places in the buffers
        (emerge-eval-in-buffer
         A-buffer
        ;; place markers at the appropriate places in the buffers
        (emerge-eval-in-buffer
         A-buffer
-        (goto-line (+ a-begin A-hidden-lines))
+        (setq a-line (emerge-goto-line a-begin a-line))
         (setq a-begin-marker (point-marker))
         (setq a-begin-marker (point-marker))
-        (goto-line (+ a-end A-hidden-lines))
+        (setq a-line (emerge-goto-line a-end a-line))
         (setq a-end-marker (point-marker)))
        (emerge-eval-in-buffer
         B-buffer
         (setq a-end-marker (point-marker)))
        (emerge-eval-in-buffer
         B-buffer
-        (goto-line (+ b-begin B-hidden-lines))
+        (setq b-line (emerge-goto-line b-begin b-line))
         (setq b-begin-marker (point-marker))
         (setq b-begin-marker (point-marker))
-        (goto-line (+ b-end B-hidden-lines))
+        (setq b-line (emerge-goto-line b-end b-line))
         (setq b-end-marker (point-marker)))
        (setq merge-begin-marker (set-marker
                                  (make-marker)
         (setq b-end-marker (point-marker)))
        (setq merge-begin-marker (set-marker
                                  (make-marker)
@@ -1357,7 +1543,7 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'."
     ;; fast access
     (setq emerge-difference-list (apply 'vector (nreverse marker-list)))))
 
     ;; fast access
     (setq emerge-difference-list (apply 'vector (nreverse marker-list)))))
 
-;; If we have an ancestor, select all B variants that we prefer 
+;; If we have an ancestor, select all B variants that we prefer
 (defun emerge-select-prefer-Bs ()
   (let ((n 0))
     (while (< n emerge-number-of-differences)
 (defun emerge-select-prefer-Bs ()
   (let ((n 0))
     (while (< n emerge-number-of-differences)
@@ -1412,8 +1598,8 @@ With an argument, reestablish the default three-window display."
       (let* ((merge-buffer emerge-merge-buffer)
             (buffer-A emerge-A-buffer)
             (buffer-B emerge-B-buffer)
       (let* ((merge-buffer emerge-merge-buffer)
             (buffer-A emerge-A-buffer)
             (buffer-B emerge-B-buffer)
-            (window-A (get-buffer-window buffer-A))
-            (window-B (get-buffer-window buffer-B))
+            (window-A (get-buffer-window buffer-A 'visible))
+            (window-B (get-buffer-window buffer-B 'visible))
             (merge-window (get-buffer-window merge-buffer))
             (diff-vector
              (aref emerge-difference-list emerge-current-difference)))
             (merge-window (get-buffer-window merge-buffer))
             (diff-vector
              (aref emerge-difference-list emerge-current-difference)))
@@ -1457,8 +1643,8 @@ With an argument, reestablish the default three-window display."
   (let* ((merge-buffer emerge-merge-buffer)
         (buffer-A emerge-A-buffer)
         (buffer-B emerge-B-buffer)
   (let* ((merge-buffer emerge-merge-buffer)
         (buffer-A emerge-A-buffer)
         (buffer-B emerge-B-buffer)
-        (window-A (get-buffer-window buffer-A))
-        (window-B (get-buffer-window buffer-B))
+        (window-A (get-buffer-window buffer-A 'visible))
+        (window-B (get-buffer-window buffer-B 'visible))
         (merge-window (get-buffer-window merge-buffer)))
     (if window-A (progn
                   (select-window window-A)
         (merge-window (get-buffer-window merge-buffer)))
     (if window-A (progn
                   (select-window window-A)
@@ -1481,7 +1667,7 @@ the height of the merge window.
 `C-u -' alone as argument scrolls half the height of the merge window."
   (interactive "P")
   (emerge-operate-on-windows
 `C-u -' alone as argument scrolls half the height of the merge window."
   (interactive "P")
   (emerge-operate-on-windows
-   'scroll-up 
+   'scroll-up
    ;; calculate argument to scroll-up
    ;; if there is an explicit argument
    (if (and arg (not (equal arg '-)))
    ;; calculate argument to scroll-up
    ;; if there is an explicit argument
    (if (and arg (not (equal arg '-)))
@@ -1597,7 +1783,7 @@ to the left margin, if they are in windows."
 ;; If there are min-lines lines above and below the region, then don't do
 ;; anything.
 ;; If not, recenter the region to make it so.
 ;; If there are min-lines lines above and below the region, then don't do
 ;; anything.
 ;; If not, recenter the region to make it so.
-;; If that isn't possible, remove context lines balancedly from top and botton
+;; If that isn't possible, remove context lines balancedly from top and bottom
 ;; so the entire region shows.
 ;; If that isn't possible, show the top of the region.
 ;; BEG must be at the beginning of a line.
 ;; so the entire region shows.
 ;; If that isn't possible, show the top of the region.
 ;; BEG must be at the beginning of a line.
@@ -1700,13 +1886,13 @@ buffer after this will cause serious problems."
   (emerge-restore-buffer-characteristics)
   ;; null out the difference markers so they don't slow down future editing
   ;; operations
   (emerge-restore-buffer-characteristics)
   ;; null out the difference markers so they don't slow down future editing
   ;; operations
-  (mapcar (function (lambda (d)
-                     (set-marker (aref d 0) nil)
-                     (set-marker (aref d 1) nil)
-                     (set-marker (aref d 2) nil)
-                     (set-marker (aref d 3) nil)
-                     (set-marker (aref d 4) nil)
-                     (set-marker (aref d 5) nil)))
+  (mapc (function (lambda (d)
+                   (set-marker (aref d 0) nil)
+                   (set-marker (aref d 1) nil)
+                   (set-marker (aref d 2) nil)
+                   (set-marker (aref d 3) nil)
+                   (set-marker (aref d 4) nil)
+                   (set-marker (aref d 5) nil)))
          emerge-difference-list)
   ;; allow them to be garbage collected
   (setq emerge-difference-list nil)
          emerge-difference-list)
   ;; allow them to be garbage collected
   (setq emerge-difference-list nil)
@@ -1724,7 +1910,7 @@ buffer after this will cause serious problems."
     (run-hooks 'emerge-quit-hook)))
 
 (defun emerge-select-A (&optional force)
     (run-hooks 'emerge-quit-hook)))
 
 (defun emerge-select-A (&optional force)
-  "Select the A variant of this difference.  
+  "Select the A variant of this difference.
 Refuses to function if this difference has been edited, i.e., if it
 is neither the A nor the B variant.
 A prefix argument forces the variant to be selected
 Refuses to function if this difference has been edited, i.e., if it
 is neither the A nor the B variant.
 A prefix argument forces the variant to be selected
@@ -1801,7 +1987,7 @@ which there is no preference."
        (if (zerop (% n 10))
            (message "Setting default to A...%d" n)))
       (emerge-unselect-and-select-difference selected-difference)))
        (if (zerop (% n 10))
            (message "Setting default to A...%d" n)))
       (emerge-unselect-and-select-difference selected-difference)))
-  (message "Default A set"))
+  (message "Default choice is now A"))
 
 (defun emerge-default-B ()
   "Make the B variant the default from here down.
 
 (defun emerge-default-B ()
   "Make the B variant the default from here down.
@@ -1823,7 +2009,7 @@ which there is no preference."
        (if (zerop (% n 10))
            (message "Setting default to B...%d" n)))
       (emerge-unselect-and-select-difference selected-difference)))
        (if (zerop (% n 10))
            (message "Setting default to B...%d" n)))
       (emerge-unselect-and-select-difference selected-difference)))
-  (message "Default B set"))
+  (message "Default choice is now B"))
 
 (defun emerge-fast-mode ()
   "Set fast mode, for Emerge.
 
 (defun emerge-fast-mode ()
   "Set fast mode, for Emerge.
@@ -1836,8 +2022,7 @@ need not be prefixed with \\<emerge-fast-keymap>\\[emerge-basic-keymap]."
   (setq emerge-fast-mode t)
   (setq emerge-edit-mode nil)
   (message "Fast mode set")
   (setq emerge-fast-mode t)
   (setq emerge-edit-mode nil)
   (message "Fast mode set")
-  ;; force mode line redisplay
-  (set-buffer-modified-p (buffer-modified-p)))
+  (force-mode-line-update))
 
 (defun emerge-edit-mode ()
   "Set edit mode, for Emerge.
 
 (defun emerge-edit-mode ()
   "Set edit mode, for Emerge.
@@ -1850,8 +2035,7 @@ must be prefixed with \\<emerge-fast-keymap>\\[emerge-basic-keymap]."
   (setq emerge-fast-mode nil)
   (setq emerge-edit-mode t)
   (message "Edit mode set")
   (setq emerge-fast-mode nil)
   (setq emerge-edit-mode t)
   (message "Edit mode set")
-  ;; force mode line redisplay
-  (set-buffer-modified-p (buffer-modified-p)))
+  (force-mode-line-update))
 
 (defun emerge-auto-advance (arg)
   "Toggle Auto-Advance mode, for Emerge.
 
 (defun emerge-auto-advance (arg)
   "Toggle Auto-Advance mode, for Emerge.
@@ -1863,11 +2047,10 @@ With a negative argument, turn off Auto-Advance mode."
   (setq emerge-auto-advance (if (null arg)
                                (not emerge-auto-advance)
                              (> (prefix-numeric-value arg) 0)))
   (setq emerge-auto-advance (if (null arg)
                                (not emerge-auto-advance)
                              (> (prefix-numeric-value arg) 0)))
-  (message (if emerge-skip-prefers
+  (message (if emerge-auto-advance
               "Auto-advance set"
             "Auto-advance cleared"))
               "Auto-advance set"
             "Auto-advance cleared"))
-  ;; force mode line redisplay
-  (set-buffer-modified-p (buffer-modified-p)))
+  (force-mode-line-update))
 
 (defun emerge-skip-prefers (arg)
   "Toggle Skip-Prefers mode, for Emerge.
 
 (defun emerge-skip-prefers (arg)
   "Toggle Skip-Prefers mode, for Emerge.
@@ -1882,8 +2065,7 @@ With a negative argument, turn off Skip-Prefers mode."
   (message (if emerge-skip-prefers
               "Skip-prefers set"
             "Skip-prefers cleared"))
   (message (if emerge-skip-prefers
               "Skip-prefers set"
             "Skip-prefers cleared"))
-  ;; force mode line redisplay
-  (set-buffer-modified-p (buffer-modified-p)))
+  (force-mode-line-update))
 
 (defun emerge-copy-as-kill-A ()
   "Put the A variant of this difference in the kill ring."
 
 (defun emerge-copy-as-kill-A ()
   "Put the A variant of this difference in the kill ring."
@@ -2004,7 +2186,10 @@ Use C-u l to reset the windows afterward."
                                       (princ "Ancestor buffer is: ")
                                       (princ (buffer-name))))
                                   (princ "\n")))
                                       (princ "Ancestor buffer is: ")
                                       (princ (buffer-name))))
                                   (princ "\n")))
-      (princ emerge-output-description))))
+      (princ emerge-output-description)
+      (save-excursion
+       (set-buffer standard-output)
+       (help-mode)))))
 
 (defun emerge-join-differences (arg)
   "Join the selected difference with the following one.
 
 (defun emerge-join-differences (arg)
   "Join the selected difference with the following one.
@@ -2326,10 +2511,24 @@ merge buffers."
              (setq temp (- temp emerge-after-flag-lines)))))
     temp))
 
              (setq temp (- temp emerge-after-flag-lines)))))
     temp))
 
+(defun emerge-set-combine-template (string &optional localize)
+  "Set `emerge-combine-versions-template' to STRING.
+This value controls how `emerge-combine-versions' combines the two versions.
+With prefix argument, `emerge-combine-versions-template' is made local to this
+merge buffer.  Localization is permanent for any particular merge buffer."
+  (interactive "s\nP")
+  (if localize
+      (make-local-variable 'emerge-combine-versions-template))
+  (setq emerge-combine-versions-template string)
+  (message
+   (if (assq 'emerge-combine-versions-template (buffer-local-variables))
+       "emerge-set-combine-versions-template set locally"
+     "emerge-set-combine-versions-template set")))
+
 (defun emerge-set-combine-versions-template (start end &optional localize)
   "Copy region into `emerge-combine-versions-template'.
 This controls how `emerge-combine-versions' will combine the two versions.
 (defun emerge-set-combine-versions-template (start end &optional localize)
   "Copy region into `emerge-combine-versions-template'.
 This controls how `emerge-combine-versions' will combine the two versions.
-With prefix argument, `emerge-combine-versions' is made local to this
+With prefix argument, `emerge-combine-versions-template' is made local to this
 merge buffer.  Localization is permanent for any particular merge buffer."
   (interactive "r\nP")
   (if localize
 merge buffer.  Localization is permanent for any particular merge buffer."
   (interactive "r\nP")
   (if localize
@@ -2384,15 +2583,15 @@ been edited."
         (if (= c ?%)
             (progn
               (setq i (1+ i))
         (if (= c ?%)
             (progn
               (setq i (1+ i))
-              (setq c 
+              (setq c
                     (condition-case nil
                         (aref template i)
                       (error ?%)))
               (cond ((= c ?a)
                      (insert-buffer-substring emerge-A-buffer A-begin A-end))
                     (condition-case nil
                         (aref template i)
                       (error ?%)))
               (cond ((= c ?a)
                      (insert-buffer-substring emerge-A-buffer A-begin A-end))
-                    ((= c ?b) 
+                    ((= c ?b)
                      (insert-buffer-substring emerge-B-buffer B-begin B-end))
                      (insert-buffer-substring emerge-B-buffer B-begin B-end))
-                    ((= c ?%) 
+                    ((= c ?%)
                      (insert ?%))
                     (t
                      (insert c))))
                      (insert ?%))
                     (t
                      (insert c))))
@@ -2576,7 +2775,7 @@ keymap.  Leaves merge in fast mode."
 ;; Read a file name, handling all of the various defaulting rules.
 
 (defun emerge-read-file-name (prompt alternative-default-dir default-file
 ;; Read a file name, handling all of the various defaulting rules.
 
 (defun emerge-read-file-name (prompt alternative-default-dir default-file
-                             A-file)
+                             A-file must-match)
   ;; `prompt' should not have trailing ": ", so that it can be modified
   ;; according to context.
   ;; If alternative-default-dir is non-nil, it should be used as the default
   ;; `prompt' should not have trailing ": ", so that it can be modified
   ;; according to context.
   ;; If alternative-default-dir is non-nil, it should be used as the default
@@ -2604,7 +2803,7 @@ keymap.  Leaves merge in fast mode."
                    alternative-default-dir
                    (concat alternative-default-dir
                            (file-name-nondirectory A-file))
                    alternative-default-dir
                    (concat alternative-default-dir
                            (file-name-nondirectory A-file))
-                   'confirm))
+                   (and must-match 'confirm)))
    ;; If there is a default file, use it.
    (default-file
      (read-file-name (format "%s (default %s): " prompt default-file)
    ;; If there is a default file, use it.
    (default-file
      (read-file-name (format "%s (default %s): " prompt default-file)
@@ -2613,7 +2812,7 @@ keymap.  Leaves merge in fast mode."
                     ;; Emerge as the default for this argument.
                     (and emerge-default-last-directories
                          alternative-default-dir)
                     ;; Emerge as the default for this argument.
                     (and emerge-default-last-directories
                          alternative-default-dir)
-                    default-file 'confirm))
+                    default-file (and must-match 'confirm)))
    (t
     (read-file-name (concat prompt ": ")
                    ;; If emerge-default-last-directories is set, use the
    (t
     (read-file-name (concat prompt ": ")
                    ;; If emerge-default-last-directories is set, use the
@@ -2621,7 +2820,7 @@ keymap.  Leaves merge in fast mode."
                    ;; Emerge as the default for this argument.
                    (and emerge-default-last-directories
                         alternative-default-dir)
                    ;; Emerge as the default for this argument.
                    (and emerge-default-last-directories
                         alternative-default-dir)
-                   nil 'confirm))))
+                   nil (and must-match 'confirm)))))
 
 ;; Revise the mode line to display which difference we have selected
 
 
 ;; Revise the mode line to display which difference we have selected
 
@@ -2642,8 +2841,7 @@ keymap.  Leaves merge in fast mode."
                                       (prefer-B . " - B*")
                                       (combined . " - comb"))))
                        ""))))
                                       (prefer-B . " - B*")
                                       (combined . " - comb"))))
                        ""))))
-  ;; Force mode-line redisplay
-  (set-buffer-modified-p (buffer-modified-p)))
+  (force-mode-line-update))
 
 ;; compare two regions in two buffers for containing the same text
 (defun emerge-compare-buffers (buffer-x x-begin x-end buffer-y y-begin y-end)
 
 ;; compare two regions in two buffers for containing the same text
 (defun emerge-compare-buffers (buffer-x x-begin x-end buffer-y y-begin y-end)
@@ -2654,7 +2852,7 @@ keymap.  Leaves merge in fast mode."
       (while (< x-begin x-end)
        ;; bite off and compare no more than 1000 characters at a time
        (let* ((compare-length (min (- x-end x-begin) 1000))
       (while (< x-begin x-end)
        ;; bite off and compare no more than 1000 characters at a time
        (let* ((compare-length (min (- x-end x-begin) 1000))
-              (x-string (emerge-eval-in-buffer 
+              (x-string (emerge-eval-in-buffer
                          buffer-x
                          (buffer-substring x-begin
                                            (+ x-begin compare-length))))
                          buffer-x
                          (buffer-substring x-begin
                                            (+ x-begin compare-length))))
@@ -2669,7 +2867,7 @@ keymap.  Leaves merge in fast mode."
       t)))
 
 ;; Construct a unique buffer name.
       t)))
 
 ;; Construct a unique buffer name.
-;; The first one tried is prefixsuffix, then prefix<2>suffix, 
+;; The first one tried is prefixsuffix, then prefix<2>suffix,
 ;; prefix<3>suffix, etc.
 (defun emerge-unique-buffer-name (prefix suffix)
   (if (null (get-buffer (concat prefix suffix)))
 ;; prefix<3>suffix, etc.
 (defun emerge-unique-buffer-name (prefix suffix)
   (if (null (get-buffer (concat prefix suffix)))
@@ -2691,7 +2889,7 @@ keymap.  Leaves merge in fast mode."
 ;; a list of variables.  The argument is a list of symbols (the names of
 ;; the variables).  A list element can also be a list of two functions,
 ;; the first of which (when called with no arguments) gets the value, and
 ;; a list of variables.  The argument is a list of symbols (the names of
 ;; the variables).  A list element can also be a list of two functions,
 ;; the first of which (when called with no arguments) gets the value, and
-;; the second (when called with a value as an argment) sets the value.
+;; the second (when called with a value as an argument) sets the value.
 ;; A "function" is anything that funcall can handle as an argument.
 
 (defun emerge-save-variables (vars)
 ;; A "function" is anything that funcall can handle as an argument.
 
 (defun emerge-save-variables (vars)
@@ -2713,10 +2911,12 @@ keymap.  Leaves merge in fast mode."
 ;; Make a temporary file that only we have access to.
 ;; PREFIX is appended to emerge-temp-file-prefix to make the filename prefix.
 (defun emerge-make-temp-file (prefix)
 ;; Make a temporary file that only we have access to.
 ;; PREFIX is appended to emerge-temp-file-prefix to make the filename prefix.
 (defun emerge-make-temp-file (prefix)
-  (let ((f (make-temp-name (concat emerge-temp-file-prefix prefix))))
-    ;; create the file
-    (write-region (point-min) (point-min) f nil 'no-message)
-    (set-file-modes f emerge-temp-file-mode)
+  (let (f (old-modes (default-file-modes)))
+    (unwind-protect
+       (progn
+         (set-default-file-modes emerge-temp-file-mode)
+         (setq f (make-temp-file (concat emerge-temp-file-prefix prefix))))
+      (set-default-file-modes old-modes))
     f))
 
 ;;; Functions that query the user before he can write out the current buffer.
     f))
 
 ;;; Functions that query the user before he can write out the current buffer.
@@ -2831,6 +3031,9 @@ If some prefix of KEY has a non-prefix definition, it is redefined."
 ;;                            minor-mode indicator))
 ;;             (princ (documentation minor-mode)))))
 ;;     (setq minor-modes (cdr minor-modes))))
 ;;                            minor-mode indicator))
 ;;             (princ (documentation minor-mode)))))
 ;;     (setq minor-modes (cdr minor-modes))))
+;;    (save-excursion
+;;      (set-buffer standard-output)
+;;      (help-mode))
 ;;    (print-help-return-message)))
 
 ;; This goes with the redefinition of describe-mode.
 ;;    (print-help-return-message)))
 
 ;; This goes with the redefinition of describe-mode.
@@ -2907,16 +3110,19 @@ SPC, it is ignored; if it is anything else, it is processed as a command."
        (setq name "Buffer has no file name."))
     (save-window-excursion
       (select-window (minibuffer-window))
        (setq name "Buffer has no file name."))
     (save-window-excursion
       (select-window (minibuffer-window))
-      (erase-buffer)
-      (insert name)
-      (if (not (pos-visible-in-window-p))
-         (let ((echo-keystrokes 0))
-           (while (and (not (pos-visible-in-window-p))
-                       (> (1- (screen-height)) (window-height)))
-             (enlarge-window 1))
-           (let ((c (read-event)))
+      (unwind-protect
+         (progn
+           (erase-buffer)
+           (insert name)
+           (if (not (pos-visible-in-window-p))
+               (while (and (not (pos-visible-in-window-p))
+                           (> (1- (frame-height)) (window-height)))
+                 (enlarge-window 1)))
+           (let* ((echo-keystrokes 0)
+                  (c (read-event)))
              (if (not (eq c 32))
              (if (not (eq c 32))
-                 (setq unread-command-events (list c)))))))))
+                 (setq unread-command-events (list c)))))
+       (erase-buffer)))))
 
 ;; Improved auto-save file names.
 ;; This function fixes many problems with the standard auto-save file names:
 
 ;; Improved auto-save file names.
 ;; This function fixes many problems with the standard auto-save file names:
@@ -2997,9 +3203,11 @@ See also `auto-save-file-name-p'."
 
 ;; Metacharacters that have to be protected from the shell when executing
 ;; a diff/diff3 command.
 
 ;; Metacharacters that have to be protected from the shell when executing
 ;; a diff/diff3 command.
-(defvar emerge-metachars "[ \t\n!\"#$&'()*;<=>?[\\^`{|~]"
+(defcustom emerge-metachars "[ \t\n!\"#$&'()*;<=>?[\\^`{|~]"
   "Characters that must be quoted with \\ when used in a shell command line.
   "Characters that must be quoted with \\ when used in a shell command line.
-More precisely, a [...] regexp to match any one such character.")
+More precisely, a [...] regexp to match any one such character."
+  :type 'regexp
+  :group 'emerge)
 
 ;; Quote metacharacters (using \) when executing a diff/diff3 command.
 (defun emerge-protect-metachars (s)
 
 ;; Quote metacharacters (using \) when executing a diff/diff3 command.
 (defun emerge-protect-metachars (s)
@@ -3013,4 +3221,5 @@ More precisely, a [...] regexp to match any one such character.")
 
 (provide 'emerge)
 
 
 (provide 'emerge)
 
+;; arch-tag: a575f092-6e44-400e-b8a2-4124e9377585
 ;;; emerge.el ends here
 ;;; emerge.el ends here