]> code.delx.au - gnu-emacs/blobdiff - lisp/emerge.el
(find-file-literally): New function.
[gnu-emacs] / lisp / emerge.el
index 58d9c8e7fabe7077e47fa68be25e13fa99d0beac..b8b085f64e54ceb6068d8873efc16c925441ce7a 100644 (file)
@@ -2,7 +2,7 @@
 
 ;;; The author has placed this file in the public domain.
 
-;; Author: Dale R. Worley <drw@math.mit.edu>
+;; Author: Dale R. Worley <worley@world.std.com>
 ;; Version: 5fsf
 ;; Keywords: unix, tools
 
 
 ;;; 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]
+  '("Merge Directories..." . emerge-merge-directories))
+;;;###autoload
+(define-key menu-bar-emerge-menu [emerge-revisions-with-ancestor]
+  '("Revisions with Ancestor..." . emerge-revisions-with-ancestor))
+;;;###autoload
+(define-key menu-bar-emerge-menu [emerge-revisions]
+  '("Revisions..." . emerge-revisions))
+;;;###autoload
+(define-key menu-bar-emerge-menu [emerge-files-with-ancestor]
+  '("Files with Ancestor..." . emerge-files-with-ancestor))
+;;;###autoload
+(define-key menu-bar-emerge-menu [emerge-files]
+  '("Files..." . emerge-files))
+;;;###autoload
+(define-key menu-bar-emerge-menu [emerge-buffers-with-ancestor]
+  '("Buffers with Ancestor..." . emerge-buffers-with-ancestor))
+;;;###autoload
+(define-key menu-bar-emerge-menu [emerge-buffers]
+  '("Buffers..." . emerge-buffers))
+
 ;;; Macros
 
 (defmacro emerge-eval-in-buffer (buffer &rest forms)
@@ -45,11 +72,12 @@ won't destroy Emerge control variables."
        (put '(, var) 'preserved t))))
 
 ;; 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)))
@@ -107,11 +135,11 @@ Its arguments are the ancestor file and the two variant files.")
                                 (concat "^" x "\\([acd]\\)" x "$"))
   "*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
+(defvar emerge-diff-ok-lines-regexp
   "^\\([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
+(defvar emerge-diff3-ok-lines-regexp
   "^\\([1-3]:\\|====\\|  \\)"
   "*Regexp that matches normal output lines from `emerge-diff3-program'.
 Lines that do not match are assumed to be error messages.")
@@ -132,6 +160,15 @@ 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.")
 
+(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.")
+
 ;; Hook variables
 
 (defvar emerge-startup-hook nil
@@ -166,6 +203,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-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
@@ -192,15 +243,6 @@ depend on the flags."
       (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)
 
@@ -209,7 +251,9 @@ after setting.")
 displaying a difference.")
 
 (defvar emerge-temp-file-prefix
-  (let ((env (getenv "TMPDIR"))
+  (let ((env (or (getenv "TMPDIR")
+                (getenv "TMP")
+                (getenv "TEMP")))
        d)
     (setq d (if (and env (> (length env) 0))
                env
@@ -224,7 +268,7 @@ Do not start with `~/' or `~user-name/'.")
   "*Mode for Emerge temporary files.")
 
 (defvar emerge-combine-versions-template
-  "#ifdef NEW\n%b#else /* NEW */\n%a#endif /* NEW */\n"
+  "#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
@@ -232,7 +276,7 @@ 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
-giving a prefix argument to  emerge-set-combine-versions-template .")
+giving a prefix argument to `emerge-set-combine-versions-template'.")
 
 ;; Build keymaps
 
@@ -245,6 +289,15 @@ 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.")
 
+(defvar emerge-options-menu
+  (make-sparse-keymap "Options"))
+
+(defvar emerge-merge-menu
+  (make-sparse-keymap "Merge"))
+
+(defvar emerge-move-menu
+  (make-sparse-keymap "Move"))
+
 (defvar emerge-command-prefix "\C-c\C-c"
   "*Command prefix for Emerge commands in `edit' mode.
 Must be set before Emerge is loaded.")
@@ -261,6 +314,7 @@ Must be set before Emerge is loaded.")
   (define-key emerge-basic-keymap "a" 'emerge-select-A)
   (define-key emerge-basic-keymap "b" 'emerge-select-B)
   (define-key emerge-basic-keymap "j" 'emerge-jump-to-difference)
+  (define-key emerge-basic-keymap "." 'emerge-find-difference)
   (define-key emerge-basic-keymap "q" 'emerge-quit)
   (define-key emerge-basic-keymap "\C-]" 'emerge-abort)
   (define-key emerge-basic-keymap "f" 'emerge-fast-mode)
@@ -286,11 +340,8 @@ Must be set before Emerge is loaded.")
   (define-key emerge-basic-keymap "|" 'emerge-scroll-reset)
   (define-key emerge-basic-keymap "x" nil)
   (define-key emerge-basic-keymap "x1" 'emerge-one-line-window)
-  (define-key emerge-basic-keymap "xa" 'emerge-find-difference-A)
-  (define-key emerge-basic-keymap "xb" 'emerge-find-difference-B)
   (define-key emerge-basic-keymap "xc" 'emerge-combine-versions)
   (define-key emerge-basic-keymap "xC" 'emerge-combine-versions-register)
-  (define-key emerge-basic-keymap "xd" 'emerge-find-difference)
   (define-key emerge-basic-keymap "xf" 'emerge-file-names)
   (define-key emerge-basic-keymap "xj" 'emerge-join-differences)
   (define-key emerge-basic-keymap "xl" 'emerge-line-numbers)
@@ -310,7 +361,83 @@ Must be set before Emerge is loaded.")
   (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)))
+                            emerge-fast-keymap (current-global-map))
+
+  (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.
 
@@ -367,9 +494,9 @@ the markers.
        default-B       the merge buffer contains the B variant by default,
                        but this difference hasn't been selected yet, so
                        change-default commands can alter it
-       prefer-A        in a three-file merge, the A variant is the prefered
+       prefer-A        in a three-file merge, the A variant is the preferred
                        choice
-       prefer-B        in a three-file merge, the B variant is the prefered
+       prefer-B        in a three-file merge, the B variant is the preferred
                        choice")
 (emerge-defvar-local emerge-current-difference -1
   "The difference that is currently selected.")
@@ -487,7 +614,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
            (emerge-protect-metachars file-A)
            (emerge-protect-metachars file-B))
     t))
-  (emerge-prepare-error-list emerge-diff-ok-lines)
+  (emerge-prepare-error-list emerge-diff-ok-lines-regexp)
   (emerge-convert-diffs-to-markers
    emerge-A-buffer emerge-B-buffer emerge-merge-buffer
    (emerge-extract-diffs emerge-diff-buffer)))
@@ -655,11 +782,11 @@ This is *not* a user option, since Emerge uses it for its own processing.")
    (shell-command
     (format "%s %s %s %s %s"
            emerge-diff3-program emerge-diff-options
-           (emerge-protect-metachars file-ancestor)
            (emerge-protect-metachars file-A)
+           (emerge-protect-metachars file-ancestor)
            (emerge-protect-metachars file-B))
     t))
-  (emerge-prepare-error-list emerge-diff3-ok-lines)
+  (emerge-prepare-error-list emerge-diff3-ok-lines-regexp)
   (emerge-convert-diffs-to-markers
    emerge-A-buffer emerge-B-buffer emerge-merge-buffer
    (emerge-extract-diffs3 emerge-diff-buffer)))
@@ -673,17 +800,17 @@ This is *not* a user option, since Emerge uses it for its own processing.")
        (beginning-of-line 2)
        (let ((agreement (buffer-substring (match-beginning 1) (match-end 1))))
         ;; if the A and B files are the same, ignore the difference
-        (if (not (string-equal agreement "1"))
+        (if (not (string-equal agreement "2"))
             (setq list
                   (cons 
-                   (let (group-2 group-3 pos)
+                   (let (group-1 group-3 pos)
                      (setq pos (point))
-                     (setq group-2 (emerge-get-diff3-group "2"))
+                     (setq group-1 (emerge-get-diff3-group "1"))
                      (goto-char pos)
                      (setq group-3 (emerge-get-diff3-group "3"))
-                     (vector (car group-2) (car (cdr group-2))
+                     (vector (car group-1) (car (cdr group-1))
                              (car group-3) (car (cdr group-3))
-                             (cond ((string-equal agreement "2") 'prefer-A)
+                             (cond ((string-equal agreement "1") 'prefer-A)
                                    ((string-equal agreement "3") 'prefer-B)
                                    (t 'default-A))))
                    list))))))
@@ -726,17 +853,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
-                                         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
-                                      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
-   (if file-out
-       (cons (` (lambda () (emerge-files-exit (, file-out))))
-            quit-hooks)
-     quit-hooks)
+   quit-hooks
    file-out))
 
 ;;;###autoload
@@ -747,19 +873,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
-                                         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
-                                 nil f)
+                                 nil f t)
           (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
-   (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.
@@ -869,7 +994,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
-   (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))
 
@@ -878,17 +1003,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
-   (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))
 
-(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)
-  (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
 
+;;;###autoload
 (defun emerge-revisions (arg file revision-A revision-B
                         &optional startup-hooks quit-hooks)
   "Emerge two RCS revisions of a file."
@@ -908,6 +1034,7 @@ This is *not* a user option, since Emerge uses it for its own processing.")
             quit-hooks)
      quit-hooks)))
 
+;;;###autoload
 (defun emerge-revisions-with-ancestor (arg file revision-A
                                           revision-B ancestor
                                           &optional
@@ -1075,7 +1202,7 @@ Otherwise, the A or B file present is copied to the output file."
             (t
              (error "Unrecognized entry"))))
        ;; If the match on the entry pattern failed
-       (error "Unparseable entry")))
+       (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"))
@@ -1123,6 +1250,7 @@ Otherwise, the A or B file present is copied to the output file."
 (defvar emerge-merge-directories-filename-regexp "[^.]"
   "Regexp describing files to be processed by `emerge-merge-directories'.")
 
+;;;###autoload
 (defun emerge-merge-directories (a-dir b-dir ancestor-dir output-dir)
   (interactive 
    (list
@@ -1243,6 +1371,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)
+  (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
@@ -1294,6 +1432,12 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'."
                           (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
@@ -1301,17 +1445,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))
-        (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-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
@@ -1328,15 +1468,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
-        (goto-line (+ a-begin A-hidden-lines))
+        (setq a-line (emerge-goto-line a-begin a-line))
         (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
-        (goto-line (+ b-begin B-hidden-lines))
+        (setq b-line (emerge-goto-line b-begin b-line))
         (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)
@@ -1376,7 +1516,7 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'."
 (defun emerge-handle-local-variables ()
   (if emerge-process-local-variables
       (condition-case err
-         (hack-local-variables t)
+         (hack-local-variables)
        (error (message "Local-variables error in merge buffer: %s"
                        (prin1-to-string err))))))
 
@@ -1414,8 +1554,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)
-            (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)))
@@ -1459,8 +1599,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)
-        (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)
@@ -1599,7 +1739,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 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.
@@ -1800,10 +1940,10 @@ which there is no preference."
                (emerge-select-A)
                (aset diff-vector 6 'default-A))))
        (setq n (1+ n))
-       (if (= (* (/ n 10) 10) n)
+       (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.
@@ -1822,10 +1962,10 @@ which there is no preference."
                (emerge-select-B)
                (aset diff-vector 6 'default-B))))
        (setq n (1+ n))
-       (if (= (* (/ n 10) 10) n)
+       (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.
@@ -1838,8 +1978,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")
-  ;; force mode line redisplay
-  (set-buffer-modified-p (buffer-modified-p)))
+  (force-mode-line-update))
 
 (defun emerge-edit-mode ()
   "Set edit mode, for Emerge.
@@ -1852,8 +1991,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")
-  ;; 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.
@@ -1865,11 +2003,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)))
-  (message (if emerge-skip-prefers
+  (message (if emerge-auto-advance
               "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.
@@ -1884,8 +2021,7 @@ With a negative argument, turn off Skip-Prefers mode."
   (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."
@@ -2006,11 +2142,14 @@ Use C-u l to reset the windows afterward."
                                       (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.
-With a prefix argument, join with the preceeding one."
+With a prefix argument, join with the preceding one."
   (interactive "P")
   (let ((n emerge-current-difference))
     ;; adjust n to be first difference to join
@@ -2216,6 +2355,18 @@ ancestor version does not share.)"
   "Find the difference containing the current position of the point.
 If there is no containing difference and the prefix argument is positive,
 it finds the nearest following difference.  A negative prefix argument finds
+the nearest previous difference."
+  (interactive "P")
+  (cond ((eq (current-buffer) emerge-A-buffer)
+        (emerge-find-difference-A arg))
+       ((eq (current-buffer) emerge-B-buffer)
+        (emerge-find-difference-B arg))
+       (t (emerge-find-difference-merge arg))))
+
+(defun emerge-find-difference-merge (arg)
+  "Find the difference containing point, in the merge buffer.
+If there is no containing difference and the prefix argument is positive,
+it finds the nearest following difference.  A negative prefix argument finds
 the nearest previous difference."
   (interactive "P")
   ;; search for the point in the merge buffer, using the markers
@@ -2223,7 +2374,7 @@ the nearest previous difference."
   (emerge-find-difference1 arg (point) 4 5))
 
 (defun emerge-find-difference-A (arg)
-  "Find the difference containing the position of the point in the A buffer.
+  "Find the difference containing point, in the A buffer.
 This command must be executed in the merge buffer.
 If there is no containing difference and the prefix argument is positive,
 it finds the nearest following difference.  A negative prefix argument finds
@@ -2236,7 +2387,7 @@ the nearest previous difference."
                           0 1))
 
 (defun emerge-find-difference-B (arg)
-  "Find the difference containing the position of the point in the B buffer.
+  "Find the difference containing point, in the B buffer.
 This command must be executed in the merge buffer.
 If there is no containing difference and the prefix argument is positive,
 it finds the nearest following difference.  A negative prefix argument finds
@@ -2279,11 +2430,11 @@ the nearest previous difference."
        (if (< index emerge-number-of-differences)
           index
         (error "No difference contains or follows point")))
-      ;; if the arg is negative, select the preceeding difference
+      ;; if the arg is negative, select the preceding difference
       (t
        (if (> index 0)
           (1- index)
-        (error "No difference contains or preceeds point")))))))
+        (error "No difference contains or precedes point")))))))
 
 (defun emerge-line-numbers ()
   "Display the current line numbers.
@@ -2316,10 +2467,24 @@ merge buffers."
              (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.
-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
@@ -2566,7 +2731,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
-                             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
@@ -2594,7 +2759,7 @@ keymap.  Leaves merge in fast mode."
                    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)
@@ -2603,7 +2768,7 @@ keymap.  Leaves merge in fast mode."
                     ;; 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
@@ -2611,7 +2776,7 @@ keymap.  Leaves merge in fast mode."
                    ;; 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
 
@@ -2632,8 +2797,7 @@ keymap.  Leaves merge in fast mode."
                                       (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)
@@ -2681,7 +2845,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
-;; 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)
@@ -2821,6 +2985,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))))
+;;    (save-excursion
+;;      (set-buffer standard-output)
+;;      (help-mode))
 ;;    (print-help-return-message)))
 
 ;; This goes with the redefinition of describe-mode.