(image-mode-current-vscroll, image-mode-current-hscroll): Make buffer-local.
[bpt/emacs.git] / lisp / follow.el
index 2ea4466..1096239 100644 (file)
@@ -1,7 +1,7 @@
 ;;; follow.el --- synchronize windows showing the same buffer
 
 ;; Copyright (C) 1995, 1996, 1997, 1999, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007 Free Software Foundation, Inc.
+;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 ;; Author: Anders Lindgren <andersl@andersl.com>
 ;; Maintainer: FSF (Anders' email bounces, Sep 2005)
 ;; Should someone come up with a better solution, please let me
 ;; know.
 
+(require 'easymenu)
+
 (eval-when-compile
   (if (or (featurep 'bytecomp)
          (featurep 'byte-compile))
@@ -335,123 +337,45 @@ After that, changing the prefix key requires manipulating keymaps."
     ;; the look and feel of Follow mode.)
     (define-key mainmap [remap end-of-buffer] 'follow-end-of-buffer)
 
-    ;;
-    ;; The menu.
-    ;;
-
-    (if (not (featurep 'xemacs))
-
-       ;;
-       ;; Emacs
-       ;;
-       (let ((menumap (funcall (symbol-function 'make-sparse-keymap)
-                                "Follow"))
-             (count 0)
-             id)
-         (mapcar
-          (function
-           (lambda (item)
-             (setq id
-                   (or (cdr item)
-                       (progn
-                         (setq count (+ count 1))
-                         (intern (format "separator-%d" count)))))
-             (define-key menumap (vector id) item)
-             (or (eq id 'follow-mode)
-                 (put id 'menu-enable 'follow-mode))))
-          ;; In reverse order:
-          '(("Toggle Follow mode" . follow-mode)
-            ("--")
-            ("Recenter"           . follow-recenter)
-            ("--")
-            ("Previous Window"    . follow-previous-window)
-            ("Next Windows"       . follow-next-window)
-            ("Last Window"        . follow-last-window)
-            ("First Window"       . follow-first-window)
-            ("--")
-            ("Switch To Buffer (all windows)"
-              . follow-switch-to-buffer-all)
-            ("Switch To Buffer"   . follow-switch-to-buffer)
-            ("--")
-            ("Delete Other Windows and Split"
-              . follow-delete-other-windows-and-split)
-            ("--")
-            ("Scroll Down"        . follow-scroll-down)
-            ("Scroll Up"          . follow-scroll-up)))
-
-         ;; If there is a `tools' menu, we use it.  However, we can't add a
-         ;; minor-mode specific item to it (it's broken), so we make the
-         ;; contents ghosted when not in use, and add ourselves to the
-         ;; global map.  If no `tools' menu is present, just make a
-         ;; top-level menu visible when the mode is activated.
-
-         (let ((tools-map (lookup-key (current-global-map) [menu-bar tools]))
-               (last nil))
-           (if (sequencep tools-map)
-               (progn
-                 ;; Find the last entry in the menu and store it in `last'.
-                 (mapcar (function
-                          (lambda (x)
-                            (setq last (or (cdr-safe
-                                            (cdr-safe
-                                             (cdr-safe x)))
-                                           last))))
-                         tools-map)
-                 (if last
-                     (progn
-                       (funcall (symbol-function 'define-key-after)
-                                 tools-map [separator-follow] '("--") last)
-                       (funcall (symbol-function 'define-key-after)
-                                tools-map [follow] (cons "Follow" menumap)
-                                'separator-follow))
-                   ;; Didn't find the last item, adding to the top of
-                   ;; tools.  (This will probably never happen...)
-                   (define-key (current-global-map) [menu-bar tools follow]
-                     (cons "Follow" menumap))))
-             ;; No tools menu, add "Follow" to the menubar.
-             (define-key mainmap [menu-bar follow]
-               (cons "Follow" menumap)))))
-
-      ;;
-      ;; XEmacs.
-      ;;
-
-      ;; place the menu in the `Tools' menu.
-      (let ((menu '("Follow"
-                   :filter follow-menu-filter
-                   ["Scroll Up" follow-scroll-up t]
-                   ["Scroll Down" follow-scroll-down t]
-                   ["Delete Other Windows and Split"
-                    follow-delete-other-windows-and-split t]
-                   ["Switch To Buffer" follow-switch-to-buffer t]
-                   ["Switch To Buffer (all windows)"
-                    follow-switch-to-buffer-all t]
-                   ["First Window" follow-first-window t]
-                   ["Last Window" follow-last-window t]
-                   ["Next Windows" follow-next-window t]
-                   ["Previous Window" follow-previous-window t]
-                   ["Recenter" follow-recenter t]
-                   ["Deactivate" follow-mode t])))
-
-       ;; Why not just `(set-buffer-menubar current-menubar)'?  The
-       ;; question is a very good question.  The reason is that under
-       ;; Emacs, neither `set-buffer-menubar' nor
-       ;; `current-menubar' is defined, hence the byte-compiler will
-       ;; warn.
-       (funcall (symbol-function 'set-buffer-menubar)
-                (symbol-value 'current-menubar))
-       (funcall (symbol-function 'add-submenu) '("Tools") menu))
-
-      ;; When the mode is not activated, only one item is visible:
-      ;; "Activate".
-      (defun follow-menu-filter (menu)
-       (if follow-mode
-           menu
-         '(["Activate          " follow-mode t]))))
-
     mainmap)
   "Minor mode keymap for Follow mode.")
 
+;; When the mode is not activated, only one item is visible to activate
+;; the mode.
+(defun follow-menu-filter (menu)
+  (if (bound-and-true-p follow-mode)
+      menu
+    '(["Follow mode"   follow-mode
+       :style toggle :selected follow-mode])))
+
+;; If there is a `tools' menu, we use it.  However, we can't add a
+;; minor-mode specific item to it (it's broken), so we make the
+;; contents ghosted when not in use, and add ourselves to the
+;; global map.
+(easy-menu-add-item nil '("Tools")
+  '("Follow"
+    ;; The Emacs code used to just grey out operations when follow-mode was
+    ;; not enabled, whereas the XEmacs code used to remove it altogether.
+    ;; Not sure which is preferable, but clearly the preference should not
+    ;; depend on the flavor.
+    :filter follow-menu-filter
+    ["Scroll Up"       follow-scroll-up        follow-mode]
+    ["Scroll Down"     follow-scroll-down      follow-mode]
+    "--"
+    ["Delete Other Windows and Split" follow-delete-other-windows-and-split follow-mode]
+    "--"
+    ["Switch To Buffer"        follow-switch-to-buffer follow-mode]
+    ["Switch To Buffer (all windows)" follow-switch-to-buffer-all follow-mode]
+    "--"
+    ["First Window"    follow-first-window     follow-mode]
+    ["Last Window"     follow-last-window      follow-mode]
+    ["Next Window"     follow-next-window      follow-mode]
+    ["Previous Window" follow-previous-window  follow-mode]
+    "--"
+    ["Recenter"                follow-recenter         follow-mode]
+    "--"
+    ["Follow mode"     follow-mode :style toggle :selected follow-mode]))
+
 ;;}}}
 
 (defcustom follow-mode-line-text " Follow"
@@ -552,14 +476,12 @@ Used by `follow-window-size-change'.")
 ;;;###autoload
 (defun turn-on-follow-mode ()
   "Turn on Follow mode.  Please see the function `follow-mode'."
-  (interactive)
   (follow-mode 1))
 
 
 ;;;###autoload
 (defun turn-off-follow-mode ()
   "Turn off Follow mode.  Please see the function `follow-mode'."
-  (interactive)
   (follow-mode -1))
 
 (put 'follow-mode 'permanent-local t)
@@ -908,7 +830,7 @@ of the way from the true end."
   "Return all windows displaying the same buffer as the TESTWIN.
 The list contains only windows displayed in the same frame as TESTWIN.
 If TESTWIN is nil the selected window is used."
-  (or (and testwin (window-live-p testwin))
+  (or (window-live-p testwin)
       (setq testwin (selected-window)))
   (let* ((top (frame-first-window (window-frame testwin)))
         (win top)
@@ -1345,7 +1267,7 @@ position of the first window.  Otherwise it is a good guess."
     (let ((done nil)
          win-start
          res)
-      ;; Always calculate what happend when no line is displayed in the first
+      ;; Always calculate what happens when no line is displayed in the first
       ;; window. (The `previous' res is needed below!)
       (goto-char guess)
       (vertical-motion 0 (car windows))
@@ -1586,9 +1508,9 @@ non-first windows in Follow mode."
                    (setq win-start-end (follow-windows-start-end windows))
                    (follow-invalidate-cache)
                    ;; When the point ends up in another window. This
-                   ;; happends when dest is in the beginning of the
+                   ;; happens when dest is in the beginning of the
                    ;; file and the selected window is not the first.
-                   ;; It can also, in rare situations happend when
+                   ;; It can also, in rare situations happen when
                    ;; long lines are used and there is a big
                    ;; difference between the width of the windows.
                    ;; (When scrolling one line in a wide window which
@@ -1602,6 +1524,8 @@ non-first windows in Follow mode."
              ;; If the region is visible, make it look good when spanning
              ;; multiple windows.
              (if (or (and (boundp 'mark-active) (symbol-value 'mark-active))
+                     ;; The following isn't used in Emacs,
+                     ;; since `mark-active' is bound.
                      (and (fboundp 'region-active-p)
                           (funcall (symbol-function 'region-active-p))))
                  (follow-maximize-region
@@ -1898,17 +1822,14 @@ would interfere with some other package.  If this happens, please
 report this using the `report-emacs-bug' function."
   (interactive)
   (follow-tidy-process-filter-alist)
-  (let ((list (process-list)))
-    (while list
-      (if (eq (follow-call-process-filter (car list)) 'follow-generic-filter)
-         (progn
-           (follow-call-set-process-filter
-            (car list)
-            (cdr-safe (assq (car list) follow-process-filter-alist)))
-           (setq follow-process-filter-alist
-                 (delq (assq (car list) follow-process-filter-alist)
-                       follow-process-filter-alist))))
-      (setq list (cdr list))))
+  (dolist (process (process-list))
+    (when (eq (follow-call-process-filter process) 'follow-generic-filter)
+      (follow-call-set-process-filter
+       process
+       (cdr-safe (assq process follow-process-filter-alist)))
+      (setq follow-process-filter-alist
+           (delq (assq process follow-process-filter-alist)
+                 follow-process-filter-alist))))
   (setq follow-intercept-processes nil))
 
 ;;}}}
@@ -1964,7 +1885,7 @@ report this using the `report-emacs-bug' function."
     ;; If we're in follow mode, do our stuff.  Select a new window and
     ;; redisplay.  (Actually, it is redundant to check `buf', but I
     ;; feel it's more correct.)
-    (if (and buf win (window-live-p win))
+    (if (and buf (window-live-p win))
        (progn
          (set-buffer buf)
          (if (and (boundp 'follow-mode) follow-mode)
@@ -2105,12 +2026,12 @@ report this using the `report-emacs-bug' function."
                      (setq windows (follow-all-followers win))
                      (if (memq orig-window windows)
                          (progn
-                           ;; Make sure we're redrawing around the
-                           ;; selected window.
-                           ;;
-                           ;; We must be really careful not to do this
-                           ;; when we are (indirectly) called by
-                           ;; `post-command-hook'.
+                            ;; Make sure we're redrawing around the
+                            ;; selected window.
+                            ;;
+                            ;; We must be really careful not to do this
+                            ;; when we are (indirectly) called by
+                            ;; `post-command-hook'.
                            (select-window orig-window)
                            (follow-post-command-hook)
                            (setq orig-window (selected-window)))
@@ -2244,6 +2165,8 @@ This prevents `mouse-drag-region' from messing things up."
 ;;{{{ The end
 
 (defun follow-unload-function ()
+  "Unload Follow mode library."
+  (easy-menu-remove-item nil '("Tools") "Follow")
   (follow-stop-intercept-process-output)
   (dolist (group '((before
                    ;; XEmacs
@@ -2269,10 +2192,9 @@ This prevents `mouse-drag-region' from messing things up."
                                  (intern (concat "follow-" (symbol-name fun))))
                (ad-update fun))
            (error nil))))))
+  ;; continue standard processing
   nil)
 
-(defvar follow-unload-function 'follow-unload-function)
-
 ;;
 ;; We're done!
 ;;