initial commit
[emacs-init.git] / nxhtml / util / pointback.el
1 ;;; pointback.el --- Restore window points when returning to buffers
2
3 ;; Copyright (C) 2009  Markus Triska
4
5 ;; Author: Markus Triska <markus.triska@gmx.at>
6 ;; Keywords: convenience
7
8 ;; This program is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation, either version 3 of the License, or
11 ;; (at your option) any later version.
12
13 ;; This program is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
21 ;;; Commentary:
22
23 ;; When you have two windows X and Y showing different sections of the
24 ;; same buffer B, then switch to a different buffer in X, and then
25 ;; show B in X again, the new point in X will be the same as in Y.
26 ;; With pointback-mode, window points are preserved instead, and point
27 ;; will be where it originally was in X for B when you return to B.
28
29 ;; Use M-x pointback-mode RET to enable pointback-mode for a buffer.
30 ;; Use M-x global-pointback-mode RET to enable it for all buffers.
31
32 ;;; Code:
33
34 (require 'assoc)
35
36 (defconst pointback-version "0.2")
37
38 (defvar pointback-windows nil
39   "Association list of windows to buffers and window points.")
40
41 (defun pointback-store-point ()
42   "Save window point and start for the current buffer of the
43 selected window."
44   (sit-for 0)                       ; redisplay to update window-start
45   (let* ((buffers (cdr (assq (selected-window) pointback-windows)))
46          (b (assq (current-buffer) buffers))
47          (p (cons (point) (window-start))))
48     (if b
49         (setcdr b p)
50       (let ((current (cons (current-buffer) p)))
51         (aput 'pointback-windows (selected-window) (cons current buffers))))))
52
53 (defun pointback-restore ()
54   "Restore previously stored window point for the selected window."
55   (let* ((buffers (cdr (assq (selected-window) pointback-windows)))
56          (b (assq (current-buffer) buffers))
57          (p (cdr b)))
58     (when b
59       (goto-char (car p))
60       (set-window-start (selected-window) (cdr p) t)))
61   ;; delete dead windows from pointback-windows
62   (dolist (w pointback-windows)
63     (unless (window-live-p (car w))
64       (adelete 'pointback-windows (car w))))
65   ;; delete window points of dead buffers
66   (dolist (w pointback-windows)
67     (let (buffers)
68       (dolist (b (cdr w))
69         (when (buffer-live-p (car b))
70           (push b buffers)))
71       (aput 'pointback-windows (car w) buffers))))
72
73 ;;;###autoload
74 (define-minor-mode pointback-mode
75   "Restore previous window point when switching back to a buffer."
76   :lighter ""
77   (if pointback-mode
78       (progn
79         (add-hook 'post-command-hook 'pointback-store-point nil t)
80         (add-hook 'window-configuration-change-hook
81                   'pointback-restore nil t))
82     (remove-hook 'post-command-hook 'pointback-store-point t)
83     (remove-hook 'window-configuration-change-hook 'pointback-restore t)
84     (setq pointback-windows nil)))
85
86 ;;;###autoload
87 (define-globalized-minor-mode global-pointback-mode pointback-mode pointback-on)
88
89 (defun pointback-on ()
90   (pointback-mode 1))
91
92 (provide 'pointback)
93 ;;; pointback.el ends here