Also require comint when loading.
[bpt/emacs.git] / lisp / image-mode.el
index 6b02db5..56dff23 100644 (file)
 
 ;;; Image scrolling functions
 
 
 ;;; Image scrolling functions
 
+(defvar image-mode-current-vscroll nil
+  "An alist with elements (WINDOW . VSCROLL).")
+(make-variable-buffer-local 'image-mode-current-vscroll)
+
+(defvar image-mode-current-hscroll nil
+  "An alist with elements (WINDOW . HSCROLL).")
+(make-variable-buffer-local 'image-mode-current-hscroll)
+
+(defun image-set-window-vscroll (window vscroll &optional pixels-p)
+  (setq image-mode-current-vscroll
+       (cons (cons window vscroll)
+              (delq (assq window image-mode-current-vscroll)
+                    image-mode-current-vscroll)))
+  (set-window-vscroll window vscroll pixels-p))
+
+(defun image-set-window-hscroll (window ncol)
+  (setq image-mode-current-hscroll
+       (cons (cons window ncol)
+              (delq (assq window image-mode-current-hscroll)
+                    image-mode-current-hscroll)))
+  (set-window-hscroll window ncol))
+
+(defun image-reset-current-vhscroll ()
+  (walk-windows
+   (lambda (win)
+     (with-current-buffer (window-buffer win)
+       ;; When set-window-buffer, set hscroll and vscroll to what they were
+       ;; last time the image was displayed in this window.  If it's the first
+       ;; time it's displayed in this window, use the most recent setting.
+       (when image-mode-current-hscroll
+         (set-window-hscroll win (cdr (or (assoc win image-mode-current-hscroll)
+                                          (car image-mode-current-hscroll)))))
+       (when image-mode-current-vscroll
+         (set-window-vscroll win (cdr (or (assoc win image-mode-current-vscroll)
+                                          (car image-mode-current-vscroll)))))))
+   'nomini
+   (selected-frame)))
+
+(defun image-get-display-property ()
+  (get-char-property (point-min) 'display
+                     ;; There might be different images for different displays.
+                     (if (eq (window-buffer) (current-buffer))
+                         (selected-window))))
+
 (defun image-forward-hscroll (&optional n)
   "Scroll image in current window to the left by N character widths.
 Stop if the right edge of the image is reached."
   (interactive "p")
   (cond ((= n 0) nil)
        ((< n 0)
 (defun image-forward-hscroll (&optional n)
   "Scroll image in current window to the left by N character widths.
 Stop if the right edge of the image is reached."
   (interactive "p")
   (cond ((= n 0) nil)
        ((< n 0)
-        (set-window-hscroll (selected-window)
-                            (max 0 (+ (window-hscroll) n))))
+        (image-set-window-hscroll (selected-window)
+                                  (max 0 (+ (window-hscroll) n))))
        (t
        (t
-        (let* ((image (get-char-property (point-min) 'display))
+        (let* ((image (image-get-display-property))
                (edges (window-inside-edges))
                (win-width (- (nth 2 edges) (nth 0 edges)))
                (img-width (ceiling (car (image-size image)))))
                (edges (window-inside-edges))
                (win-width (- (nth 2 edges) (nth 0 edges)))
                (img-width (ceiling (car (image-size image)))))
-          (set-window-hscroll (selected-window)
-                              (min (max 0 (- img-width win-width))
-                                   (+ n (window-hscroll))))))))
+          (image-set-window-hscroll (selected-window)
+                                    (min (max 0 (- img-width win-width))
+                                         (+ n (window-hscroll))))))))
 
 (defun image-backward-hscroll (&optional n)
   "Scroll image in current window to the right by N character widths.
 
 (defun image-backward-hscroll (&optional n)
   "Scroll image in current window to the right by N character widths.
@@ -79,16 +123,16 @@ Stop if the bottom edge of the image is reached."
   (interactive "p")
   (cond ((= n 0) nil)
        ((< n 0)
   (interactive "p")
   (cond ((= n 0) nil)
        ((< n 0)
-        (set-window-vscroll (selected-window)
-                            (max 0 (+ (window-vscroll) n))))
+        (image-set-window-vscroll (selected-window)
+                                  (max 0 (+ (window-vscroll) n))))
        (t
        (t
-        (let* ((image (get-char-property (point-min) 'display))
+        (let* ((image (image-get-display-property))
                (edges (window-inside-edges))
                (win-height (- (nth 3 edges) (nth 1 edges)))
                (img-height (ceiling (cdr (image-size image)))))
                (edges (window-inside-edges))
                (win-height (- (nth 3 edges) (nth 1 edges)))
                (img-height (ceiling (cdr (image-size image)))))
-          (set-window-vscroll (selected-window)
-                              (min (max 0 (- img-height win-height))
-                                   (+ n (window-vscroll))))))))
+          (image-set-window-vscroll (selected-window)
+                                    (min (max 0 (- img-height win-height))
+                                         (+ n (window-vscroll))))))))
 
 (defun image-previous-line (&optional n)
   "Scroll image in current window downward by N lines.
 
 (defun image-previous-line (&optional n)
   "Scroll image in current window downward by N lines.
@@ -118,7 +162,7 @@ When calling from a program, supply as argument a number, nil, or `-'."
        (t (image-next-line (prefix-numeric-value n)))))
 
 (defun image-scroll-down (&optional n)
        (t (image-next-line (prefix-numeric-value n)))))
 
 (defun image-scroll-down (&optional n)
-  "Scroll image in current window downward by N lines
+  "Scroll image in current window downward by N lines.
 Stop if the top edge of the image is reached.
 If ARG is omitted or nil, scroll downward by a near full screen.
 A near full screen is `next-screen-context-lines' less than a full screen.
 Stop if the top edge of the image is reached.
 If ARG is omitted or nil, scroll downward by a near full screen.
 A near full screen is `next-screen-context-lines' less than a full screen.
@@ -146,7 +190,7 @@ stopping if the top or bottom edge of the image is reached."
   (and arg
        (/= (setq arg (prefix-numeric-value arg)) 1)
        (image-next-line (- arg 1)))
   (and arg
        (/= (setq arg (prefix-numeric-value arg)) 1)
        (image-next-line (- arg 1)))
-  (set-window-hscroll (selected-window) 0))
+  (image-set-window-hscroll (selected-window) 0))
 
 (defun image-eol (arg)
   "Scroll horizontally to the right edge of the image in the current window.
 
 (defun image-eol (arg)
   "Scroll horizontally to the right edge of the image in the current window.
@@ -156,30 +200,30 @@ stopping if the top or bottom edge of the image is reached."
   (and arg
        (/= (setq arg (prefix-numeric-value arg)) 1)
        (image-next-line (- arg 1)))
   (and arg
        (/= (setq arg (prefix-numeric-value arg)) 1)
        (image-next-line (- arg 1)))
-  (let* ((image (get-char-property (point-min) 'display))
+  (let* ((image (image-get-display-property))
         (edges (window-inside-edges))
         (win-width (- (nth 2 edges) (nth 0 edges)))
         (img-width (ceiling (car (image-size image)))))
         (edges (window-inside-edges))
         (win-width (- (nth 2 edges) (nth 0 edges)))
         (img-width (ceiling (car (image-size image)))))
-    (set-window-hscroll (selected-window)
-                       (max 0 (- img-width win-width)))))
+    (image-set-window-hscroll (selected-window)
+                             (max 0 (- img-width win-width)))))
 
 (defun image-bob ()
   "Scroll to the top-left corner of the image in the current window."
   (interactive)
 
 (defun image-bob ()
   "Scroll to the top-left corner of the image in the current window."
   (interactive)
-  (set-window-hscroll (selected-window) 0)
-  (set-window-vscroll (selected-window) 0))
+  (image-set-window-hscroll (selected-window) 0)
+  (image-set-window-vscroll (selected-window) 0))
 
 (defun image-eob ()
   "Scroll to the bottom-right corner of the image in the current window."
   (interactive)
 
 (defun image-eob ()
   "Scroll to the bottom-right corner of the image in the current window."
   (interactive)
-  (let* ((image (get-char-property (point-min) 'display))
+  (let* ((image (image-get-display-property))
         (edges (window-inside-edges))
         (win-width (- (nth 2 edges) (nth 0 edges)))
         (img-width (ceiling (car (image-size image))))
         (win-height (- (nth 3 edges) (nth 1 edges)))
         (img-height (ceiling (cdr (image-size image)))))
         (edges (window-inside-edges))
         (win-width (- (nth 2 edges) (nth 0 edges)))
         (img-width (ceiling (car (image-size image))))
         (win-height (- (nth 3 edges) (nth 1 edges)))
         (img-height (ceiling (cdr (image-size image)))))
-    (set-window-hscroll (selected-window) (max 0 (- img-width win-width)))
-    (set-window-vscroll (selected-window) (max 0 (- img-height win-height)))))
+    (image-set-window-hscroll (selected-window) (max 0 (- img-width win-width)))
+    (image-set-window-vscroll (selected-window) (max 0 (- img-height win-height)))))
 
 ;;; Image Mode setup
 
 
 ;;; Image Mode setup
 
@@ -224,9 +268,16 @@ to toggle between display as an image and display as text."
   ;; Use our own bookmarking function for images.
   (set (make-local-variable 'bookmark-make-cell-function)
        'image-bookmark-make-cell)
   ;; Use our own bookmarking function for images.
   (set (make-local-variable 'bookmark-make-cell-function)
        'image-bookmark-make-cell)
+
+  ;; Keep track of [vh]scroll when switching buffers
+  (image-set-window-hscroll (selected-window) (window-hscroll))
+  (image-set-window-vscroll (selected-window) (window-vscroll))
+  (add-hook 'window-configuration-change-hook
+           'image-reset-current-vhscroll nil t)
+
   (add-hook 'change-major-mode-hook 'image-toggle-display-text nil t)
   (if (and (display-images-p)
   (add-hook 'change-major-mode-hook 'image-toggle-display-text nil t)
   (if (and (display-images-p)
-          (not (get-char-property (point-min) 'display)))
+          (not (image-get-display-property)))
       (image-toggle-display)
     ;; Set next vars when image is already displayed but local
     ;; variables were cleared by kill-all-local-variables
       (image-toggle-display)
     ;; Set next vars when image is already displayed but local
     ;; variables were cleared by kill-all-local-variables
@@ -237,7 +288,7 @@ to toggle between display as an image and display as text."
       (message "%s" (concat
                     (substitute-command-keys
                      "Type \\[image-toggle-display] to view as ")
       (message "%s" (concat
                     (substitute-command-keys
                      "Type \\[image-toggle-display] to view as ")
-                    (if (get-char-property (point-min) 'display)
+                    (if (image-get-display-property)
                         "text" "an image") "."))))
 
 ;;;###autoload
                         "text" "an image") "."))))
 
 ;;;###autoload
@@ -250,14 +301,14 @@ See the command `image-mode' for more information on this mode."
   :version "22.1"
   (if (not image-minor-mode)
       (image-toggle-display-text)
   :version "22.1"
   (if (not image-minor-mode)
       (image-toggle-display-text)
-    (if (get-char-property (point-min) 'display)
+    (if (image-get-display-property)
        (setq cursor-type nil truncate-lines t)
       (setq image-type "text"))
     (add-hook 'change-major-mode-hook (lambda () (image-minor-mode -1)) nil t)
     (message "%s" (concat (substitute-command-keys
        (setq cursor-type nil truncate-lines t)
       (setq image-type "text"))
     (add-hook 'change-major-mode-hook (lambda () (image-minor-mode -1)) nil t)
     (message "%s" (concat (substitute-command-keys
-                     "Type \\[image-toggle-display] to view the image as ")
-                    (if (get-char-property (point-min) 'display)
-                        "text" "an image") "."))))
+                          "Type \\[image-toggle-display] to view the image as ")
+                         (if (image-get-display-property)
+                             "text" "an image") "."))))
 
 ;;;###autoload
 (defun image-mode-maybe ()
 
 ;;;###autoload
 (defun image-mode-maybe ()
@@ -286,7 +337,7 @@ information on these modes."
 
 (defun image-toggle-display-text ()
   "Showing the text of the image file."
 
 (defun image-toggle-display-text ()
   "Showing the text of the image file."
-  (if (get-char-property (point-min) 'display)
+  (if (image-get-display-property)
       (image-toggle-display)))
 
 (defvar archive-superior-buffer)
       (image-toggle-display)))
 
 (defvar archive-superior-buffer)
@@ -297,7 +348,7 @@ information on these modes."
 This command toggles between showing the text of the image file
 and showing the image as an image."
   (interactive)
 This command toggles between showing the text of the image file
 and showing the image as an image."
   (interactive)
-  (if (get-char-property (point-min) 'display)
+  (if (image-get-display-property)
       (let ((inhibit-read-only t)
            (buffer-undo-list t)
            (modified (buffer-modified-p)))
       (let ((inhibit-read-only t)
            (buffer-undo-list t)
            (modified (buffer-modified-p)))
@@ -333,9 +384,9 @@ and showing the image as an image."
           (image (create-image file-or-data type data-p))
           (props
            `(display ,image
           (image (create-image file-or-data type data-p))
           (props
            `(display ,image
-             intangible ,image
-             rear-nonsticky (display intangible)
-             read-only t front-sticky (read-only)))
+                     intangible ,image
+                     rear-nonsticky (display intangible)
+                     read-only t front-sticky (read-only)))
           (inhibit-read-only t)
           (buffer-undo-list t)
           (modified (buffer-modified-p)))
           (inhibit-read-only t)
           (buffer-undo-list t)
           (modified (buffer-modified-p)))