]> code.delx.au - gnu-emacs-elpa/blobdiff - packages/minimap/minimap.el
Minimap: Update to version 1.1.
[gnu-emacs-elpa] / packages / minimap / minimap.el
index 7c519c0d517b3b15a5077a8f0da36f011d3688c5..86ed0a15463366b0c50e26f7188afb746b76f939 100644 (file)
@@ -1,10 +1,10 @@
 ;;; minimap.el --- Sidebar showing a "mini-map" of a buffer
 
 ;;; minimap.el --- Sidebar showing a "mini-map" of a buffer
 
-;; Copyright (C) 2009-2011 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2014 Free Software Foundation, Inc.
 
 
-;; Author: David Engster <dengste@eml.cc>
+;; Author: David Engster <deng@randomsample.de>
 ;; Keywords:
 ;; Keywords:
-;; Version: 1.0
+;; Version: 1.1
 
 ;; This file is part of GNU Emacs.
 
 
 ;; This file is part of GNU Emacs.
 
 ;; highlights the currently shown region and updates its position
 ;; automatically.  You can navigate in the minibar by dragging the
 ;; active region with the mouse, which will scroll the corresponding
 ;; highlights the currently shown region and updates its position
 ;; automatically.  You can navigate in the minibar by dragging the
 ;; active region with the mouse, which will scroll the corresponding
-;; edit buffer.
+;; edit buffer.  Additionally, you can overlay information from the
+;; tags gathered by CEDET's semantic analyzer.
 
 
-;; To create the minimap sidebar, type M-x minimap-create.
-;; To dismiss it, type M-x minimap-kill.
-
-;; Usage:
-;;  * Use 'M-x minimap-create' in a buffer you're currently editing.
-;;  * Use 'M-x minimap-kill' to kill the minimap.
-;;  * Use 'M-x customize-group RET minimap RET' to adapt minimap to your needs.
+;; Simply use M-x minimap-mode to toggle activation of the minimap.
+;; Use 'M-x customize-group RET minimap RET' to adapt minimap to your
+;; needs.
 
 ;;; KNOWN BUGS:
 
 
 ;;; KNOWN BUGS:
 
 ;; * Moving the active region with the keyboard / mouse-wheel ?
 
 
 ;; * Moving the active region with the keyboard / mouse-wheel ?
 
 
+;;; News:
+
+;;;; Changes since v1.0:
+;;
+;; - Largely rewritten as a minor mode; use M-x minimap-mode to
+;;   enable/disable.
+;; - Minimap will now remain active for all buffers which derive from
+;;   `prog-mode' (can be changed through `minimap-major-modes').  The
+;;   minimap window will be automatically created or deleted (see new
+;;   variables `minimap-recreate-window' and
+;;   `minimap-automatically-delete-window').
+;; - Possibility to set a minimum width of the minimap window
+;;   (`minimap-minimum-width').
+;; - Minimap window will be marked so that you should not be able to
+;;   enter it.
+;; - Semantic overlays will be automatically updated during editing.
+;; - Lots of bug fixes.
+
 ;;; Customizable variables:
 
 (defgroup minimap nil
 ;;; Customizable variables:
 
 (defgroup minimap nil
@@ -76,37 +91,43 @@ By default, this is only a different background color."
   '((((background dark))
      (:box (:line-width 1 :color "white")
           :inherit (font-lock-function-name-face minimap-font-face)
   '((((background dark))
      (:box (:line-width 1 :color "white")
           :inherit (font-lock-function-name-face minimap-font-face)
-          :height 2.5 :background "gray10"))
+          :height 2.75 :background "gray10"))
     (t (:box (:line-width 1 :color "black")
             :inherit (font-lock-function-name-face minimap-font-face)
     (t (:box (:line-width 1 :color "black")
             :inherit (font-lock-function-name-face minimap-font-face)
-            :height 2.5 :background "gray90")))
+            :height 2.75 :background "gray90")))
   "Face used for functions in the semantic overlay.")
 
 (defface minimap-semantic-variable-face
   '((((background dark))
      (:box (:line-width 1 :color "white")
           :inherit (font-lock-variable-name-face minimap-font-face)
   "Face used for functions in the semantic overlay.")
 
 (defface minimap-semantic-variable-face
   '((((background dark))
      (:box (:line-width 1 :color "white")
           :inherit (font-lock-variable-name-face minimap-font-face)
-           :height 2.5 :background "gray10"))
+           :height 2.75 :background "gray10"))
     (t (:box (:line-width 1 :color "black")
             :inherit (font-lock-function-name-face minimap-font-face)
     (t (:box (:line-width 1 :color "black")
             :inherit (font-lock-function-name-face minimap-font-face)
-            :height 2.5 :background "gray90")))
+            :height 2.75 :background "gray90")))
   "Face used for variables in the semantic overlay.")
 
 (defface minimap-semantic-type-face
   '((((background dark))
      (:box (:line-width 1 :color "white")
           :inherit (font-lock-type-face minimap-font-face)
   "Face used for variables in the semantic overlay.")
 
 (defface minimap-semantic-type-face
   '((((background dark))
      (:box (:line-width 1 :color "white")
           :inherit (font-lock-type-face minimap-font-face)
-          :height 2.5 :background "gray10"))
+          :height 2.75 :background "gray10"))
     (t (:box (:line-width 1 :color "black")
             :inherit (font-lock-function-name-face minimap-font-face)
     (t (:box (:line-width 1 :color "black")
             :inherit (font-lock-function-name-face minimap-font-face)
-            :height 2.5 :background "gray90")))
+            :height 2.75 :background "gray90")))
   "Face used for types in the semantic overlay.")
 
   "Face used for types in the semantic overlay.")
 
-(defcustom minimap-width-fraction 0.2
+(defcustom minimap-width-fraction 0.15
   "Fraction of width which should be used for minimap sidebar."
   :type 'number
   :group 'minimap)
 
   "Fraction of width which should be used for minimap sidebar."
   :type 'number
   :group 'minimap)
 
+(defcustom minimap-minimum-width 30
+  "Minimum width of minimap in characters (default size).
+Use nil to disable."
+  :type 'number
+  :group 'minimap)
+
 (defcustom minimap-window-location 'left
   "Location of the minimap window.
 Can be either the symbol `left' or `right'."
 (defcustom minimap-window-location 'left
   "Location of the minimap window.
 Can be either the symbol `left' or `right'."
@@ -114,8 +135,8 @@ Can be either the symbol `left' or `right'."
                 (const :tag "Right" right))
   :group 'minimap)
 
                 (const :tag "Right" right))
   :group 'minimap)
 
-(defcustom minimap-buffer-name-prefix "*MINIMAP* "
-  "Prefix for buffer names of minimap sidebar."
+(defcustom minimap-buffer-name " *MINIMAP*"
+  "Buffer name of minimap sidebar."
   :type 'string
   :group 'minimap)
 
   :type 'string
   :group 'minimap)
 
@@ -167,12 +188,12 @@ bottom or top."
   :type 'boolean
   :group 'minimap)
 
   :type 'boolean
   :group 'minimap)
 
-(defcustom minimap-hide-fringes t
+(defcustom minimap-hide-fringes nil
   "Whether the minimap should hide the fringes."
   :type 'boolean
   :group 'minimap)
 
   "Whether the minimap should hide the fringes."
   :type 'boolean
   :group 'minimap)
 
-(defcustom minimap-dedicated-window nil
+(defcustom minimap-dedicated-window t
   "Whether the minimap should create a dedicated window."
   :type 'boolean
   :group 'minimap)
   "Whether the minimap should create a dedicated window."
   :type 'boolean
   :group 'minimap)
@@ -229,119 +250,198 @@ minimap buffer."
   :type '(repeat symbol)
   :group 'minimap)
 
   :type '(repeat symbol)
   :group 'minimap)
 
+(defcustom minimap-major-modes '(prog-mode)
+  "Major modes for which a minimap should be created.
+This can also be a parent mode like 'prog-mode.
+If nil, a minimap must be explicitly created for each buffer."
+  :type '(repeat symbol)
+  :group 'minimap)
+
+(defcustom minimap-recreate-window t
+  "Whether the minimap window should be automatically re-created.
+If this is non-nil, the side window for the minimap will be
+automatically re-created as soon as you kill it."
+  :type 'boolean
+  :group 'minimap)
+
+(defcustom minimap-automatically-delete-window t
+  "Whether the minimap window should be automatically deleted.
+Setting this to non-nil will delete the minibuffer side window
+when you enter a buffer which is not derived from
+`minimap-major-modes' (excluding the minibuffer)."
+  :type 'boolean
+  :group 'minimap)
+
 ;;; Internal variables
 
 ;;; Internal variables
 
+;; The buffer currently displayed in the minimap
+(defvar minimap-active-buffer nil)
+;; Window start/end from the base buffer
 (defvar minimap-start nil)
 (defvar minimap-end nil)
 (defvar minimap-start nil)
 (defvar minimap-end nil)
+;; General overlay for the minimap
+(defvar minimap-base-overlay nil)
+;; Overlay for the active region
 (defvar minimap-active-overlay nil)
 (defvar minimap-active-overlay nil)
-(defvar minimap-bufname nil)
+;; Timer
 (defvar minimap-timer-object nil)
 (defvar minimap-timer-object nil)
-(defvar minimap-active-minimaps 0)
-(defvar minimap-base-overlay nil)
+;; Lines the minimap can display
 (defvar minimap-numlines nil)
 (defvar minimap-pointmin-overlay nil)
 
 (defvar minimap-numlines nil)
 (defvar minimap-pointmin-overlay nil)
 
-(make-variable-buffer-local 'minimap-start)
-(make-variable-buffer-local 'minimap-end)
-(make-variable-buffer-local 'minimap-active-overlay)
-(make-variable-buffer-local 'minimap-bufname)
-(make-variable-buffer-local 'minimap-base-overlay)
-(make-variable-buffer-local 'minimap-numlines)
-(make-variable-buffer-local 'minimap-pointmin-overlay)
+;;; Helpers
+
+(defun minimap-active-current-buffer-p ()
+  "Whether the current buffer is displayed in the minimap."
+  (and (eq (current-buffer) minimap-active-buffer)
+       (get-buffer minimap-buffer-name)
+       (with-current-buffer minimap-buffer-name
+        (eq minimap-active-buffer (buffer-base-buffer)))))
+
+(defsubst minimap-get-window ()
+  "Get current minimap window."
+  (when (get-buffer minimap-buffer-name)
+    (get-buffer-window minimap-buffer-name)))
+
+(defsubst minimap-kill-buffer ()
+  "Kill the minimap buffer."
+  (when (get-buffer minimap-buffer-name)
+    (kill-buffer minimap-buffer-name)))
+
+(defun minimap-create-window ()
+  (let ((width (round (* (window-width)
+                        minimap-width-fraction))))
+    (when (< width minimap-minimum-width)
+      (setq width minimap-minimum-width))
+    (if (eq minimap-window-location 'left)
+       (split-window-horizontally width)
+      (split-window-horizontally
+       (* -1 width))
+      (other-window 1))
+    ;; Set up the minimap window:
+    ;; You should not be able to enter the minimap window.
+    (set-window-parameter nil 'no-other-window t)
+    ;; Hide things.
+    (when minimap-hide-scroll-bar
+      (setq vertical-scroll-bar nil))
+    (when minimap-hide-fringes
+      (set-window-fringes nil 0 0))
+    ;; Switch to buffer.
+    (switch-to-buffer
+     (get-buffer-create minimap-buffer-name) t t)
+    ;; Do not fold lines in the minimap.
+    (toggle-truncate-lines 1)
+    ;; Make it dedicated.
+    (when minimap-dedicated-window
+      (set-window-dedicated-p nil t))
+    (prog1
+       (selected-window)
+      (other-window 1))))
+
+(defun minimap-setup-hooks (&optional remove)
+  "Hook minimap into other modes.
+If REMOVE is non-nil, remove minimap from other modes."
+  (if remove
+      (progn
+       (remove-hook 'outline-view-change-hook 'minimap-sync-overlays)
+       (remove-hook 'hs-hide-hook 'minimap-sync-overlays)
+       (remove-hook 'hs-show-hook 'minimap-sync-overlays))
+    ;; outline-(minor-)mode
+    (add-hook 'outline-view-change-hook 'minimap-sync-overlays)
+    ;; hideshow
+    (add-hook 'hs-hide-hook 'minimap-sync-overlays)
+    (add-hook 'hs-show-hook 'minimap-sync-overlays)))
 
 ;;; Minimap creation / killing
 
 
 ;;; Minimap creation / killing
 
+(define-minor-mode minimap-mode
+  "Toggle minimap mode."
+  :global t
+  :group 'minimap
+  :lighter " MMap"
+  (if minimap-mode
+      (progn
+       (when (and minimap-major-modes
+                  (apply 'derived-mode-p minimap-major-modes))
+         (unless (minimap-get-window)
+           (minimap-create-window))
+         ;; Create minimap.
+         (minimap-new-minimap))
+       ;; Create timer.
+       (setq minimap-timer-object
+             (run-with-idle-timer minimap-update-delay t 'minimap-update))
+       ;; Hook into other modes.
+       (minimap-setup-hooks))
+    ;; Turn it off
+    (minimap-kill)
+    (minimap-setup-hooks t)))
+
 ;;;###autoload
 (defun minimap-create ()
 ;;;###autoload
 (defun minimap-create ()
-  "Create a minimap sidebar for the current window."
+  "Create a minimap sidebar."
   (interactive)
   (interactive)
-  ;; If minimap is visible, do nothing.
-  (unless (and minimap-bufname
-              (get-buffer minimap-bufname)
-              (get-buffer-window (get-buffer minimap-bufname)))
-    (let ((bufname (concat minimap-buffer-name-prefix
-                          (buffer-name (current-buffer))))
-         (new-win (if (eq minimap-window-location 'left)
-                      (split-window-horizontally
-                       (round (* (window-width)
-                                 minimap-width-fraction)))
-                    (split-window-horizontally
-                     (round (* (window-width)
-                               (- 1 minimap-width-fraction))))
-                    (other-window 1))))
-      ;; If minimap exists but isn't visible, reuse it.
-      (if (and minimap-bufname
-              (get-buffer minimap-bufname))
-         (switch-to-buffer minimap-bufname t)
-       ;; Otherwise create new minimap
-       (minimap-new-minimap bufname)
-       ;; If this is the first minimap, create the idle timer.
-       (when (zerop minimap-active-minimaps)
-         (setq minimap-timer-object
-               (run-with-idle-timer minimap-update-delay t 'minimap-update)))
-       (setq minimap-active-minimaps
-             (1+ minimap-active-minimaps))))
-    (other-window 1)
-    (minimap-sync-overlays)))
+  (minimap-mode 1))
 
 
-(defun minimap-new-minimap (bufname)
-  "Create new minimap BUFNAME for current buffer and window."
-  (let ((indbuf (make-indirect-buffer (current-buffer) bufname t))
+(defun minimap-new-minimap ()
+  "Create new minimap BUFNAME for current buffer and window.
+Re-use already existing minimap window if possible."
+  (interactive)
+  (let ((currentbuffer (current-buffer))
+       (win (minimap-get-window))
+       (indbuf (make-indirect-buffer (current-buffer)
+                                     (concat minimap-buffer-name "_temp")))
        (edges (window-pixel-edges)))
        (edges (window-pixel-edges)))
-    (setq minimap-bufname bufname)
-    (set-buffer indbuf)
-    (when minimap-hide-scroll-bar
-      (setq vertical-scroll-bar nil))
-    (switch-to-buffer indbuf)
-    (setq minimap-base-overlay (make-overlay (point-min) (point-max) nil t t))
-    (overlay-put minimap-base-overlay 'face 'minimap-font-face)
-    (overlay-put minimap-base-overlay 'priority 1)
-    (setq minimap-pointmin-overlay (make-overlay (point-min) (1+ (point-min))))
-    (setq minimap-start (window-start)
-         minimap-end (window-end)
-         minimap-active-overlay (make-overlay minimap-start minimap-end)
-         line-spacing 0)
-    (overlay-put minimap-active-overlay 'face
-                'minimap-active-region-background)
-    (overlay-put minimap-active-overlay 'priority 5)
-    (minimap-mode 1)
-    (when (and (boundp 'linum-mode)
-              linum-mode)
-      (linum-mode 0))
-    (when minimap-hide-fringes
-      (set-window-fringes nil 0 0))
-    (when minimap-dedicated-window
-      (set-window-dedicated-p nil t))
-    (setq buffer-read-only t)
-    ;; Calculate the actual number of lines displayable with the minimap face.
-    (setq minimap-numlines
-         (floor
-          (/
-           (- (nth 3 edges) (nth 1 edges))
-           (car (progn (redisplay) (window-line-height))))))))
+    ;; Remember the active buffer currently displayed in the minimap.
+    (setq minimap-active-buffer (current-buffer))
+    ;; Hook into CEDET if necessary.
+    (when (and minimap-display-semantic-overlays
+              (boundp 'semantic-after-toplevel-cache-change-hook))
+      (add-hook 'semantic-after-partial-cache-change-hook
+               'minimap-apply-semantic-overlays nil t)
+      (add-hook 'semantic-after-toplevel-cache-change-hook
+               'minimap-apply-semantic-overlays nil t))
+    (with-selected-window win
+      ;; Now set up the minimap:
+      (when (window-dedicated-p)
+       (set-window-dedicated-p nil nil))
+      (switch-to-buffer indbuf t t)
+      (minimap-kill-buffer)
+      (rename-buffer minimap-buffer-name)
+      ;; Do not fold lines in the minimap.
+      (toggle-truncate-lines 1)
+      (when minimap-dedicated-window
+       (set-window-dedicated-p nil t))
+      (setq minimap-base-overlay (make-overlay (point-min) (point-max) nil t t))
+      (overlay-put minimap-base-overlay 'face 'minimap-font-face)
+      (overlay-put minimap-base-overlay 'priority 1)
+      (setq minimap-pointmin-overlay (make-overlay (point-min) (1+ (point-min))))
+      (setq minimap-start (window-start)
+           minimap-end (window-end)
+           minimap-active-overlay (make-overlay minimap-start minimap-end)
+           line-spacing 0)
+      (overlay-put minimap-active-overlay 'face
+                  'minimap-active-region-background)
+      (overlay-put minimap-active-overlay 'priority 5)
+      (minimap-sb-mode 1)
+      (when (and (boundp 'linum-mode)
+                linum-mode)
+       (linum-mode 0))
+      (setq buffer-read-only t)
+      ;; Calculate the actual number of lines displayable with the minimap face.
+      (setq minimap-numlines
+           (floor
+            (/
+             (- (nth 3 edges) (nth 1 edges))
+             (car (progn (redisplay t) (window-line-height)))))))
+    (minimap-sync-overlays)))
 
 ;;;###autoload
 (defun minimap-kill ()
 
 ;;;###autoload
 (defun minimap-kill ()
-  "Kill minimap for current buffer.
-Cancel the idle timer if no more minimaps are active."
+  "Kill minimap."
   (interactive)
   (interactive)
-  (if (null minimap-bufname)
-      (message "No minimap associated with %s." (buffer-name (current-buffer)))
-    (let ((curname (buffer-name (current-buffer)))
-         (buf (get-buffer minimap-bufname))
-         (win (get-buffer-window minimap-bufname)))
-      (setq minimap-bufname nil)
-      (if (null buf)
-         (message "No minimap associated with %s." curname)
-       (when win
-         (delete-window win))
-       (kill-buffer buf)
-       (when (zerop
-              (setq minimap-active-minimaps
-                    (1- minimap-active-minimaps)))
-         (cancel-timer minimap-timer-object)
-         (setq minimap-timer-object nil))
-       (message "Minimap for %s killed." curname)))))
+  (when (minimap-get-window)
+    (delete-window (minimap-get-window)))
+  (cancel-timer minimap-timer-object))
 
 ;;; Minimap update
 
 
 ;;; Minimap update
 
@@ -349,28 +449,70 @@ Cancel the idle timer if no more minimaps are active."
   "Update minimap sidebar if necessary.
 This is meant to be called from the idle-timer or the post command hook.
 When FORCE, enforce update of the active region."
   "Update minimap sidebar if necessary.
 This is meant to be called from the idle-timer or the post command hook.
 When FORCE, enforce update of the active region."
-  (when minimap-bufname
-    (let ((win (get-buffer-window minimap-bufname))
-         start end pt ov)
-      (when win
-       (setq start (window-start)
-             end (window-end)
-             pt (point)
-             ov)
-       (with-selected-window win
-         (unless (and (not force)
-                      (= minimap-start start)
-                      (= minimap-end end))
-           (move-overlay minimap-active-overlay start end)
-           (setq minimap-start start
-                 minimap-end end)
-           (minimap-recenter (line-number-at-pos (/ (+ end start) 2))
-                             (/ (- (line-number-at-pos end)
-                                   (line-number-at-pos start))
-                                2)))
-         (goto-char pt)
-         (when minimap-always-recenter
-           (recenter (round (/ (window-height) 2)))))))))
+  (interactive)
+  ;; If we are in the minibuffer, do nothing.
+  (unless (active-minibuffer-window)
+    (if (minimap-active-current-buffer-p)
+       ;; We are still in the same buffer, so just update the minimap.
+       (let ((win (minimap-get-window))
+             (start (window-start))
+             (end (window-end))
+             (pt (point)))
+         (when (and (null win)
+                    minimap-recreate-window)
+           ;; The minimap window is no longer visible, so create it again...
+           (setq win (minimap-create-window))
+           ;; ...and switch to existing minimap buffer.
+           (with-selected-window win
+             (when (window-dedicated-p)
+               (set-window-dedicated-p nil nil))
+             (switch-to-buffer minimap-buffer-name t t)
+             (when minimap-dedicated-window
+               (set-window-dedicated-p nil t))))
+         (with-selected-window win
+           ;; Make sure the base overlay spans the whole buffer.
+           (unless (and (= (overlay-start minimap-base-overlay) (point-min))
+                        (= (overlay-end minimap-base-overlay) (point-max)))
+             (move-overlay minimap-base-overlay (point-min) (point-max)))
+           (unless (and (not force)
+                        (= minimap-start start)
+                        (= minimap-end end))
+             ;; Update the overlay.
+             (move-overlay minimap-active-overlay start end)
+             (setq minimap-start start
+                   minimap-end end)
+             (minimap-recenter (line-number-at-pos (/ (+ end start) 2))
+                               (/ (- (line-number-at-pos end)
+                                     (line-number-at-pos start))
+                                  2)))
+           (goto-char pt)
+           (when minimap-always-recenter
+             (recenter (round (/ (window-height) 2)))))
+         ;; Redisplay
+         (sit-for 0))
+      ;; The buffer was switched, check if the minimap should switch, too.
+      (if (and minimap-major-modes
+              (apply 'derived-mode-p minimap-major-modes))
+         (progn
+           ;; Create window if necessary...
+           (unless (minimap-get-window)
+             (minimap-create-window))
+           ;; ...and re-create minimap with new buffer...
+           (minimap-new-minimap)
+           ;; Redisplay
+           (sit-for 0)
+           ;; ...and call update again.
+           (minimap-update t))
+       ;; Otherwise, delete window if the user so wishes.
+       (when (and (minimap-get-window)
+                  minimap-automatically-delete-window)
+         ;; We wait a tiny bit before deleting the window, since we
+         ;; might only be temporarily in another buffer.
+         (run-with-timer 0.3 nil
+                         (lambda ()
+                           (when (and (null (minimap-active-current-buffer-p))
+                                      (minimap-get-window))
+                             (delete-window (minimap-get-window))))))))))
 
 ;;; Overlay movement
 
 
 ;;; Overlay movement
 
@@ -384,6 +526,7 @@ When FORCE, enforce update of the active region."
           (start-point (posn-point end-posn))
           (make-cursor-line-fully-visible nil)
           (cursor-type nil)
           (start-point (posn-point end-posn))
           (make-cursor-line-fully-visible nil)
           (cursor-type nil)
+          (minimap-automatically-delete-window nil)
           (pcselmode (when (boundp 'pc-selection-mode)
                        pc-selection-mode))
            pt ev)
           (pcselmode (when (boundp 'pc-selection-mode)
                        pc-selection-mode))
            pt ev)
@@ -501,16 +644,16 @@ active region."
 
 ;;; Minimap minor mode
 
 
 ;;; Minimap minor mode
 
-(defvar minimap-mode-map (make-sparse-keymap)
-  "Keymap used by `minimap-mode'.")
+ (defvar minimap-sb-mode-map (make-sparse-keymap)
+  "Keymap used by `minimap-sb-mode'.")
 
 
-(define-key minimap-mode-map [down-mouse-1] 'minimap-move-overlay-mouse)
-(define-key minimap-mode-map [down-mouse-2] 'minimap-move-overlay-mouse)
-(define-key minimap-mode-map [down-mouse-3] 'minimap-move-overlay-mouse)
+(define-key minimap-sb-mode-map [down-mouse-1] 'minimap-move-overlay-mouse)
+(define-key minimap-sb-mode-map [down-mouse-2] 'minimap-move-overlay-mouse)
+(define-key minimap-sb-mode-map [down-mouse-3] 'minimap-move-overlay-mouse)
 
 
-(define-minor-mode minimap-mode
+(define-minor-mode minimap-sb-mode
   "Minor mode for minimap sidebar."
   "Minor mode for minimap sidebar."
-  nil "minimap" minimap-mode-map)
+  nil "minimap" minimap-sb-mode-map)
 
 ;;; Sync minimap with modes which create/delete overlays.
 
 
 ;;; Sync minimap with modes which create/delete overlays.
 
@@ -518,39 +661,48 @@ active region."
   "Synchronize overlays between base and minimap buffer.
 Apply semantic overlays or face enlargement if necessary."
   (interactive)
   "Synchronize overlays between base and minimap buffer.
 Apply semantic overlays or face enlargement if necessary."
   (interactive)
-  (when minimap-bufname
-    (let ((baseov (overlays-in (point-min) (point-max)))
-         (semantic (and (boundp 'semantic-version)
-                        (semantic-active-p)))
-         ov props p)
-      (with-current-buffer minimap-bufname
-       (remove-overlays)
-       (while baseov
-         (when (setq props (minimap-get-sync-properties (car baseov)))
-           (setq ov (make-overlay (overlay-start (car baseov))
-                                  (overlay-end (car baseov))))
-           (while (setq p (car props))
-             (overlay-put ov (car p) (cadr p))
-             (setq props (cdr props))))
-         (setq baseov (cdr baseov)))
-       (move-overlay minimap-pointmin-overlay (point-min) (1+ (point-min)))
-       ;; Re-apply font overlay
-       (move-overlay minimap-base-overlay (point-min) (point-max)))
-      ;; Face enlargement
-      (when (and font-lock-mode
-                (or (eq minimap-enlarge-certain-faces 'always)
-                    (and (eq minimap-enlarge-certain-faces 'as-fallback)
-                         (or (not minimap-display-semantic-overlays)
-                             (not semantic)))))
-       (when (eq font-lock-support-mode 'jit-lock-mode)
-         (jit-lock-fontify-now))
-       (with-current-buffer minimap-bufname
-         (minimap-enlarge-faces)))
-      ;; Semantic overlays
-      (when (and semantic
-                minimap-display-semantic-overlays)
-         (minimap-apply-semantic-overlays)))
-    (minimap-update t)))
+  ;; Get overlays and Semantic status from base buffer.
+  (when (and minimap-mode
+            (minimap-active-current-buffer-p))
+    (with-current-buffer minimap-active-buffer
+      (let ((baseov (overlays-in (point-min) (point-max)))
+           (semantic (and (boundp 'semantic-version)
+                          (semantic-active-p)))
+           ov props p)
+       ;; Apply overlays to minimap.
+       (with-current-buffer minimap-buffer-name
+         ;; Delete overlays (but keep our own).
+         (let ((ovs (overlays-in (point-min) (point-max))))
+           (dolist (ov ovs)
+             (unless (member ov (list minimap-pointmin-overlay
+                                      minimap-base-overlay
+                                      minimap-active-overlay))
+               (delete-overlay ov))))
+         (while baseov
+           (when (and (eq (overlay-buffer (car baseov)) minimap-active-buffer)
+                      (setq props (minimap-get-sync-properties (car baseov))))
+             (setq ov (make-overlay (overlay-start (car baseov))
+                                    (overlay-end (car baseov))))
+             (while (setq p (car props))
+               (overlay-put ov (car p) (cadr p))
+               (setq props (cdr props))))
+           (setq baseov (cdr baseov)))
+         (move-overlay minimap-pointmin-overlay (point-min) (1+ (point-min)))
+         ;; Re-apply font overlay
+         (move-overlay minimap-base-overlay (point-min) (point-max)))
+       ;; Face enlargement
+       (when (and font-lock-mode
+                  (or (eq minimap-enlarge-certain-faces 'always)
+                      (and (eq minimap-enlarge-certain-faces 'as-fallback)
+                           (or (not minimap-display-semantic-overlays)
+                               (not semantic)))))
+         (when (eq font-lock-support-mode 'jit-lock-mode)
+           (jit-lock-fontify-now))
+         (minimap-enlarge-faces))
+       ;; Semantic overlays
+       (when (and semantic
+                  minimap-display-semantic-overlays)
+         (minimap-apply-semantic-overlays t))))))
 
 (defun minimap-get-sync-properties (ov)
   "Get properties from overlay OV which should be synced.
 
 (defun minimap-get-sync-properties (ov)
   "Get properties from overlay OV which should be synced.
@@ -566,61 +718,67 @@ You can specify those properties with
         minimap-sync-overlay-properties)))
 
 (defun minimap-enlarge-faces ()
         minimap-sync-overlay-properties)))
 
 (defun minimap-enlarge-faces ()
-  "Apply default font to all faces in `minimap-normal-height-faces'.
-This has to be called in the minimap buffer."
+  "Apply default font to all faces in `minimap-normal-height-faces'."
   (let ((pos (next-single-property-change (point-min) 'face))
        next ov face)
     (while pos
       (setq face (get-text-property pos 'face))
   (let ((pos (next-single-property-change (point-min) 'face))
        next ov face)
     (while pos
       (setq face (get-text-property pos 'face))
-      (when (delq nil (mapcar (lambda (x) (equal x face))
-                             minimap-normal-height-faces))
-       (setq ov
-             (make-overlay pos
-                           (setq pos (next-single-property-change pos 'face))))
-       (overlay-put ov 'face `(:family ,(face-font 'default)))
-       (overlay-put ov 'priority 5))
+      (when (and face
+                (member face minimap-normal-height-faces))
+       (with-current-buffer minimap-buffer-name
+         (setq ov
+               (make-overlay pos
+                             (setq pos (next-single-property-change pos 'face))))
+         (overlay-put ov 'face `(:family ,(face-font 'default)))
+         (overlay-put ov 'priority 5)))
       (setq pos (next-single-property-change pos 'face)))))
 
       (setq pos (next-single-property-change pos 'face)))))
 
-(defun minimap-apply-semantic-overlays ()
+(defun minimap-apply-semantic-overlays (tags)
   "Apply semantic overlays to the minimap.
   "Apply semantic overlays to the minimap.
-This has to be called from the base buffer."
-    (let ((tags (semantic-fetch-tags))
-         tag class ov ovnew)
-      (while tags
-       (setq tag (car tags))
-       (setq class (semantic-tag-class tag))
-       (setq ov (semantic-tag-overlay tag))
-       (when (and (overlayp ov)
-                  (or (eq class 'function)
-                      (eq class 'type)
-                      (eq class 'variable)))
-         (with-current-buffer minimap-bufname
-           (let ((start (overlay-start ov))
-                 (end (overlay-end ov))
-                 (name (semantic-tag-name tag)))
-             (overlay-put
-              (setq ovnew (make-overlay start end))
-              'face `(:background ,(face-background
-                                    (intern (format "minimap-semantic-%s-face"
-                                                    (symbol-name class))))))
-             (overlay-put ovnew 'priority 1)
-             (setq start
-                   (minimap-line-to-pos (/ (+ (line-number-at-pos start)
-                                              (line-number-at-pos end)) 2)))
-             (setq end (progn (goto-char start) (point-at-eol)))
-             (setq ovnew (make-overlay start end))
-             (overlay-put ovnew 'face (format "minimap-semantic-%s-face"
-                                              (symbol-name class)))
-             (overlay-put ovnew 'display (concat "  " name "  "))
-             (overlay-put ovnew 'priority 6))))
-       (setq tags (cdr tags)))))
-
-;; outline-(minor-)mode
-(add-hook 'outline-view-change-hook 'minimap-sync-overlays)
-
-;; hideshow
-(add-hook 'hs-hide-hook 'minimap-sync-overlays)
-(add-hook 'hs-show-hook 'minimap-sync-overlays)
+TAGS is the list of tags.  If it is t, fetch tags from buffer."
+  (when (and tags
+            minimap-mode)
+    (with-current-buffer minimap-active-buffer
+      (let (tag class ov ovnew)
+       (when (eq tags t)
+         (setq tags (semantic-fetch-tags)))
+       (while tags
+         (setq tag (car tags))
+         (setq class (semantic-tag-class tag))
+         (setq ov (semantic-tag-overlay tag))
+         (when (and (overlayp ov)
+                    (or (eq class 'function)
+                        (eq class 'type)
+                        (eq class 'variable)))
+           (with-current-buffer minimap-buffer-name
+             (let ((start (overlay-start ov))
+                   (end (overlay-end ov))
+                   (name (semantic-tag-name tag)))
+               ;; First, remove old Semantic overlays.
+               (remove-overlays start end 'minimap-semantic t)
+               ;; Now put the new ones.
+               (overlay-put
+                (setq ovnew (make-overlay start end))
+                'face `(:background ,(face-background
+                                      (intern (format "minimap-semantic-%s-face"
+                                                      (symbol-name class))))))
+               (overlay-put ovnew 'priority 1)
+               (overlay-put ovnew 'minimap-semantic t)
+               (setq start
+                     (minimap-line-to-pos (/ (+ (line-number-at-pos start)
+                                                (line-number-at-pos end)) 2)))
+               (goto-char start)
+               (while (looking-at "^$")
+                 (forward-line -1))
+               (setq start (point))
+               (setq end (progn (goto-char start) (point-at-eol)))
+               (setq ovnew (make-overlay start end))
+               (overlay-put ovnew 'face (format "minimap-semantic-%s-face"
+                                                (symbol-name class)))
+               (overlay-put ovnew 'display (concat "  " name "  "))
+               (overlay-put ovnew 'priority 6)
+               (overlay-put ovnew 'minimap-semantic t))))
+         (setq tags (cdr tags)))))))
 
 (provide 'minimap)
 
 
 (provide 'minimap)