summaryrefslogtreecommitdiffstats
path: root/emacs.d/nxhtml/util/winsav.el
diff options
context:
space:
mode:
Diffstat (limited to 'emacs.d/nxhtml/util/winsav.el')
-rw-r--r--emacs.d/nxhtml/util/winsav.el1585
1 files changed, 0 insertions, 1585 deletions
diff --git a/emacs.d/nxhtml/util/winsav.el b/emacs.d/nxhtml/util/winsav.el
deleted file mode 100644
index 771f6ce..0000000
--- a/emacs.d/nxhtml/util/winsav.el
+++ /dev/null
@@ -1,1585 +0,0 @@
-;;; winsav.el --- Save and restore window structure
-;;
-;; Author: Lennart Borgman
-;; Created: Sun Jan 14 2007
-(defconst winsav:version "0.77") ;;Version: 0.77
-;; Last-Updated: 2009-08-04 Tue
-;; Keywords:
-;; Compatibility:
-;;
-;; Features that might be required by this library:
-;;
-;; None
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Commentary:
-;;
-;; This library contains both user level commands and options and
-;; functions for use in other elisp libraries.
-;;
-;;;; User level commands and options
-;;
-;; The user level commands and options are for saving frame, windows
-;; and buffers between Emacs sessions. To do that you can customize
-;; the options `desktop-save-mode' and `winsav-save-mode' or put this
-;; at the end of your .emacs:
-;;
-;; (desktop-save-mode 1)
-;; (winsav-save-mode 1)
-;;
-;; You can also save configurations that you later switch between.
-;; For more information see the command `winsav-save-mode'.
-;;
-;; (There is also a command in this library for rotating window
-;; borders in a frame, `winsav-rotate'. It is here just because the
-;; needed support functions lives here.)
-;;
-;;
-;;
-;;;; Commands for other elisp libraries
-;;
-;; This library was orignally written to solve the problem of adding a
-;; window to the left of some windows in a frame like the one below
-;;
-;; ___________
-;; | | |
-;; | 1 | 2 |
-;; |____|____|
-;; | |
-;; | 3 |
-;; |_________|
-;;
-;; so that the window structure on the frame becomes
-;;
-;; ___________
-;; | | | |
-;; | | 1| 2 |
-;; | B|__|___|
-;; | A| |
-;; | R| 3 |
-;; |__|______|
-;;
-;;
-;; This problem can be solved by this library. However the solution in
-;; this library is a bit more general: You first copy the window
-;; structure and then restore that into another window. To do the
-;; above you first copy the window structure in the first frame above
-;; with `winsav-get-window-tree'. Then you create windows like this:
-;;
-;; ___________
-;; | | |
-;; | | |
-;; | B| |
-;; | A| |
-;; | R| |
-;; |__|______|
-;;
-;;
-;; Finally you use `winsav-put-window-tree' to put the window
-;; structure into the right window. (Of course you could have put BAR
-;; above, under etc.)
-;;
-;;
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; Bugs and limitations:
-;;
-;; Juanma Barranquero has pointed out there is a serious limitation in
-;; this way of doing it when overlays with 'window properties are
-;; used. The problem is that any pointers to windows are made invalid
-;; since they are deleted. So in fact any code that relies on saved
-;; pointers to windows will have problem if the window is one of those
-;; that are involved here.
-;;
-;; To overcome this problem when doing something like inserting a BAR
-;; window (see above) a new window has to be inserted in the existing
-;; window tree on a frame in a way that is currently not supported in
-;; Emacs.
-;;
-;; It would be nice to be have primitives to manipulate the window
-;; tree more generally from elisp. That requires implementation of
-;; them at the C level of course.
-;;
-;; However it is probably much easier to implement it quite a bit less
-;; general. The concept of splitting is maybe then the right level to
-;; search for primitives at.
-;;
-;; My conclusion is that it will take some time to find suitable
-;; primitives for this.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Change log:
-;;
-;; Version 0.72:
-;;
-;; - Format of window structure changed in Emacs 23. Adopted to that.
-;; - Added save and restore of frame/window configurations between
-;; Emacs sessions.
-;; - Added named winsav configurations for save and restore of frames,
-;; windows, buffers and files.
-;;
-;; Version 0.71:
-;;
-;; - Added rotation of window structure.
-;;
-;; Version 0.70:
-;;
-;; - Support for save and restore from file.
-;;
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
-;; any later version.
-;;
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with this program; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;
-;;; Code:
-
-
-(eval-when-compile (require 'cl))
-(eval-and-compile (require 'desktop))
-
-;; (defun winsav-upper-left-window(&optional frame w)
-;; (let* ((tree (if w w (car (window-tree frame))))
-;; (is-split (not (windowp tree))))
-;; (if (not is-split)
-;; tree
-;; (winsav-upper-left-window frame (nth 2 tree)))))
-
-
-(defcustom winsav-after-get-hook nil
- "Hook to run after at the end of `winsav-get-window-tree'.
-The functions in this hook are called with one parameter which is
-the same as the return value from the function above."
- :type 'hook
- :group 'winsav)
-
-(defcustom winsav-after-put-hook nil
- "Hook to run after at the end of `winsav-put-window-tree'.
-The functions in this hook are called with one parameter which is
-a list where each element is a list \(old-win new-win) where
-OLD-WIN are the window from `winsav-get-window-tree' and NEW-WIN
-is the newly created corresponding window. This list is the same
-as the return value from the function above."
- :type 'hook
- :group 'winsav)
-
-(defun winsav-get-window-tree(&optional frame)
- "Get window structure.
-This returns an object with current windows with values, buffers,
-points and the selected window.
-
-FRAME is the frame to save structure from. If nil use selected.
-
-At the very end of this function the hook `winsav-after-get' is
-run."
- ;;(let* ((upper-left (winsav-upper-left-window frame))
- (let* ((upper-left (frame-first-window frame))
- (num -1)
- sel-num)
- (dolist (w (window-list frame nil upper-left))
- (setq num (1+ num))
- (when (eq w (selected-window))
- (setq sel-num num)))
- (let ((ret (list sel-num
- (winsav-get-window-tree-1 frame nil))))
- (run-hook-with-args 'winsav-after-get-hook ret)
- ret)))
-
-;; Fix-me: add window-hscroll
-(defun winsav-get-window-tree-1(frame w)
- (let ((tree (if w w (car (window-tree frame)))))
- (if (windowp tree)
- ;; Note: Desktop is used for saving buffers.
- (with-current-buffer (window-buffer tree)
- (list (window-buffer tree)
- ;; buffer
- (buffer-name)
- (buffer-file-name)
- ;;buffer-read-only
- ;;(if mumamo-multi-major-mode mumamo-multi-major-mode major-mode)
- ;;minor-modes
- ;;buffer locals
- ;;(cons (+ 0 (mark-marker)) (mark-active))
- ;; window
- (window-point tree)
- (window-edges tree)
- (window-scroll-bars tree)
- (window-fringes tree)
- (window-margins tree)
- (window-hscroll tree)
- ;; misc
- (window-dedicated-p tree)
- (when (fboundp 'window-redisplay-end-trigger)
- (window-redisplay-end-trigger tree))
- (window-start tree)
- tree))
- (let* ((dir (nth 0 tree))
- (split (nth 1 tree))
- (wt (cddr tree))
- (wsubs (mapcar (lambda(wc)
- (winsav-get-window-tree-1 nil wc))
- wt)))
- (append (list dir split) wsubs)))))
-
-;;;###autoload
-(defun winsav-put-window-tree (saved-tree window &optional copy-win-ovl win-ovl-all-bufs)
- "Put window structure SAVED-TREE into WINDOW.
-Restore a structure SAVED-TREE returned from
-`winsav-get-window-tree' into window WINDOW.
-
-If COPY-WIN-OVL is non-nil then overlays having a 'window
-property pointing to one of the windows in SAVED-TREE where this
-window still is shown will be copied to a new overlay with
-'window property pointing to the corresponding new window.
-
-If WIN-OVL-ALL-BUFS is non-nil then all buffers will be searched
-for overlays with a 'window property of the kind above.
-
-At the very end of this function the hook `winsav-after-put' is
-run."
- (let* ((sel-num (nth 0 saved-tree))
- (tree (nth 1 saved-tree))
- nsiz
- nh
- nw
- osiz
- oh
- ow
- scale-w
- scale-h
- first-win
- winsav-put-return)
- (unless (or (bufferp (car tree))
- (eq 'buffer (car tree)))
- (setq nsiz (window-edges window))
- (setq nh (- (nth 3 nsiz) (nth 1 nsiz)))
- (setq nw (- (nth 2 nsiz) (nth 0 nsiz)))
- (setq osiz (cadr tree))
- (setq oh (- (nth 3 osiz) (nth 1 osiz)))
- (setq ow (- (nth 2 osiz) (nth 0 osiz)))
- (setq scale-w (unless (= ow nw) (/ nw (float ow))))
- (setq scale-h (unless (= oh nh) (/ nh (float oh)))))
- (setq first-win (winsav-put-window-tree-1 tree window scale-w scale-h t 1))
- (select-window first-win)
- (when sel-num (other-window sel-num))
- (winsav-fix-win-ovl winsav-put-return copy-win-ovl win-ovl-all-bufs)
- (run-hook-with-args 'winsav-after-put-hook winsav-put-return)
- winsav-put-return))
-
-(defun winsav-put-window-tree-1 (saved-tree window scale-w scale-h first-call level)
- "Helper for `winsav-put-window-tree'.
-For the arguments SAVED-TREE and WINDOW see that function.
-
-The arguments SCALE-W and SCALE-H are used to make the saved
-window config fit into its new place. FIRST-CALL is a state
-variable telling if this is the first round. LEVEL helps
-debugging by tells how far down we are in the call chain."
- (if (or (bufferp (car saved-tree))
- ;;(not (car saved-tree))
- (eq 'buffer (car saved-tree))
- )
- (let ((buffer (nth 0 saved-tree))
- ;; buffer
- (bufnam (nth 1 saved-tree))
- (filnam (nth 2 saved-tree))
- ;;(mark (nth 3 saved-tree))
- ;; window
- (point (nth 3 saved-tree))
- (edges (nth 4 saved-tree))
- (scroll (nth 5 saved-tree))
- (fringe (nth 6 saved-tree))
- (margs (nth 7 saved-tree))
- (hscroll (nth 8 saved-tree))
- (dedic (nth 9 saved-tree))
- (trigger (nth 10 saved-tree))
- (start (nth 11 saved-tree))
- (ovlwin (nth 12 saved-tree))
- scr2
- (misbuf " *Winsav information: Buffer is gone*"))
- (or (windowp ovlwin)
- (not ovlwin)
- (error "Parameter mismatch, ovlwin not window: %s" ovlwin))
- (when first-call
- (add-to-list 'winsav-put-return (list ovlwin window))
- (when (eq 'buffer buffer)
- (when filnam
- (setq buffer (winsav-find-file-noselect filnam)))
- (if (buffer-live-p buffer)
- (or (string= bufnam (buffer-name buffer))
- (eq (string-to-char bufnam) 32) ;; Avoid system buffer names
- (rename-buffer bufnam))
- (when (eq (string-to-char bufnam) 32)
- (setq bufnam " *Winsav dummy buffer*"))
- ;; Fix-me, this might need some tweaking: Don't restore
- ;; buffers without a file name and without
- ;; content. (desktop-mode will make that when
- ;; necessary.) Just show the scratch buffer instead.
- (setq buffer (get-buffer bufnam))
- (unless (and buffer
- (< 0 (buffer-size buffer)))
- (setq buffer (get-buffer-create "*scratch*")))))
- (set-window-buffer window buffer)
- (set-window-dedicated-p window dedic)
- ;; Strange incompatibility in scroll args:
- (setq scr2 (list (nth 0 scroll) (nth 2 scroll) (nth 3 scroll)))
- (apply 'set-window-scroll-bars (append (list window) scr2))
- (apply 'set-window-fringes (append (list window) fringe))
- (set-window-margins window (car margs) (cdr margs))
- (set-window-hscroll window hscroll)
- (unless (>= emacs-major-version 23)
- (with-no-warnings
- (set-window-redisplay-end-trigger window trigger))))
- (let* ((nsiz (window-edges window))
- (nh (- (nth 3 nsiz) (nth 1 nsiz)))
- (nw (- (nth 2 nsiz) (nth 0 nsiz)))
- (osiz edges) ;(nth 2 saved-tree))
- (oh (- (nth 3 osiz) (nth 1 osiz)))
- (ow (- (nth 2 osiz) (nth 0 osiz)))
- (diff-w (- (if scale-w
- (round (* scale-w ow))
- ow)
- nw))
- (diff-h (- (if scale-h
- (round (* scale-h oh))
- oh)
- nh)))
- ;; Avoid rounding naggings:
- (when (> (abs diff-h) 1)
- (bw-adjust-window window diff-h nil))
- (when (> (abs diff-w) 1)
- (bw-adjust-window window diff-w t)))
- ;; Fix-me: there were some problems getting point correctly. Don't know why...
- (with-selected-window window
- (with-current-buffer (window-buffer window)
- (goto-char point))
- (set-window-point window point)
- ;;(unless (buffer-live-p buffer) (setq point 1) (setq start 1))
- (set-window-start window start)
- ;; Maybe point got off screen?
- (when (/= point (window-point window))
- (set-window-point window point)))
- window)
- (let* ((ver (car saved-tree))
- (wtree (list (cons window (caddr saved-tree))))
- (nwin window)
- pwin
- pdelta
- (first-win nwin))
- ;; First split to get it in correct order
- (when first-call
- (dolist (subtree (cdddr saved-tree))
- (setq pwin nwin)
- ;;(message "nwin edges=%s, ver=%s" (window-edges nwin) ver)
- (let ((split-err nil)
- (window-min-height 1)
- (window-min-width 1))
- (setq nwin (split-window nwin nil (not ver))))
- ;; Make the previous window as small as permitted to allow
- ;; splitting as many times as possible
- (setq pdelta (-
- (if ver
- window-min-height
- window-min-width)
- (if ver
- (window-width pwin)
- (window-height pwin))))
- ;;(message "pwin=%s, edges=%s, pdelta=%s, ver=%s" pwin (window-edges pwin) pdelta ver)
- ;; No reason to fail here:
- (condition-case err
- (adjust-window-trailing-edge pwin pdelta (not ver))
- (error
- ;;(message "awt=>%s" (error-message-string err))
- nil
- ))
- ;; Add to traverse
- (add-to-list 'wtree
- (cons nwin subtree)
- t)))
- ;; Now traverse. Sizing is a bit tricky, multiple runs have to
- ;; be done (as in balance-windows).
- (let (tried-sizes
- last-sizes
- (windows (window-list (selected-frame))))
- (while (not (member last-sizes tried-sizes))
- (when last-sizes (setq tried-sizes (cons last-sizes tried-sizes)))
- (setq last-sizes (mapcar (lambda (w)
- (window-edges w))
- windows))
- (dolist (wsub (reverse wtree))
- (select-window (car wsub))
- (winsav-put-window-tree-1 (cdr wsub) (selected-window)
- scale-w scale-h
- first-call
- (1+ level)
- ))
- (setq first-call nil)
- ))
- first-win)))
-
-(defun winsav-fix-win-ovl(win-list copy-win-ovl win-ovl-all-bufs)
- (let ((oldwins (mapcar (lambda(elt)
- (car elt))
- win-list))
- ovlwin
- window)
- (let (buffers)
- (if win-ovl-all-bufs
- (setq buffers (buffer-list))
- (mapc (lambda(w)
- (when (window-live-p w)
- (add-to-list 'buffers (window-buffer w))))
- oldwins))
- (dolist (buf buffers)
- (with-current-buffer buf
- (save-restriction
- (widen)
- (dolist (overlay (overlays-in (point-min) (point-max)))
- (when (setq ovlwin (car (memq (overlay-get overlay 'window) oldwins)))
- (setq window (cadr (assoc ovlwin win-list)))
- ;; If the old window is still alive then maybe copy
- ;; overlay, otherwise change the 'window prop. However
- ;; copy only if COPY-WIN-OVL is non-nil.
- (if (not (and (window-live-p ovlwin)
- (window-frame ovlwin)))
- (overlay-put overlay 'window window)
- (when copy-win-ovl
- (let* ((props (overlay-properties overlay))
- (start (overlay-start overlay))
- (end (overlay-end overlay))
- ;; Fix-me: start and end marker props
- (newovl (make-overlay start end)))
- (while props
- (let ((key (car props))
- (val (cadr props)))
- (setq props (cddr props))
- (when (eq key 'window)
- (setq val window))
- (overlay-put newovl key val))))))))))))))
-
-
-
-(defun winsav-transform-edges (edges)
- "Just rotate the arguments in EDGES to make them fit next function."
- (let ((le (nth 0 edges))
- (te (nth 1 edges))
- (re (nth 2 edges))
- (be (nth 3 edges)))
- (list te le be re)))
-
-(defun winsav-transform-1 (tree mirror transpose)
- "Mirroring of the window tree TREE.
-MIRROR could be 'mirror-top-bottom or 'mirror-left-right which I
-think explain what it does here. TRANSPOSE shifts the tree
-between a horisontal and vertical tree."
- (let* ((vertical (nth 0 tree))
- (edges (nth 1 tree))
- (subtrees (nthcdr 2 tree))
- )
- ;;(winsav-log "tree 1" tree)
- (when transpose
- (cond
- ((eq vertical nil)
- (setcar tree t))
- ((eq vertical t)
- (setcar tree nil))
- (t
- (error "Uh? vertical=%S" vertical))))
- (setcar (nthcdr 1 tree) (winsav-transform-edges edges))
- (dolist (subtree subtrees)
- (if (bufferp (car subtree))
- (when transpose
- (let ((edges (nth 4 subtree)))
- ;;(winsav-log "subtree 1" subtree)
- (setcar (nthcdr 4 subtree) (winsav-transform-edges edges))
- ;;(winsav-log "subtree 2" subtree)
- ))
- (winsav-transform-1 subtree mirror transpose)))
- (when (case mirror
- ('mirror-top-bottom vertical)
- ('mirror-left-right (not vertical))
- (nil) ;; Don't mirror
- (t
- (error "Uh? mirror=%s" mirror)))
- (setcdr (nthcdr 1 tree) (reverse subtrees))
- )
- ))
-
-(defun winsav-find-file-noselect (filename)
- "Read file FILENAME into a buffer and return the buffer.
-Like `find-file-noselect', but if file is not find then creates a
-buffer with a message about that."
- (let ((buf (find-file-noselect filename)))
- (unless buf
- (setq buf (generate-new-buffer filename))
- (with-current-buffer buf
- (insert "Winsav could not find the file " filename)
- (set-buffer-modified-p nil)))
- buf))
-
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Session saving and restore etc
-
-;;;###autoload
-(defgroup winsav nil
- "Save frames and windows when you exit Emacs."
- :group 'frames)
-
-;;;###autoload
-(define-minor-mode winsav-save-mode
- "Toggle winsav configuration saving mode.
-With numeric ARG, turn winsav saving on if ARG is positive, off
-otherwise.
-
-When this mode is turned on, winsav configurations are saved from
-one session to another. A winsav configuration consists of
-frames, windows and visible buffers configurations plus
-optionally buffers and files managed by the functions used by
-option `desktop-save-mode'
-
-By default this is integrated with `desktop-save-mode'. If
-`desktop-save-mode' is on and `winsav-handle-also-desktop' is
-non-nil then save and restore also desktop.
-
-See the command `winsav-switch-config' for more information and
-other possibilities.
-
-Note: If you want to avoid saving when you exit just turn off
-this minor mode.
-
-For information about what is saved and restored and how to save
-and restore additional information see the function
-`winsav-save-configuration'."
- :global t
- :group 'winsav)
-
-(defun winsav-save-mode-on ()
- "Ensable option `winsav-save-mode'. Provided for use in hooks."
- (winsav-save-mode 1))
-
-(defun winsav-save-mode-off ()
- "Disable option `winsav-save-mode'. Provided for use in hooks."
- (winsav-save-mode -1))
-
-(defcustom winsav-save 'ask-if-new
- "Specifies whether the winsav config should be saved when it is killed.
-A winsav config \(winsav frame configuration) is killed when the
-user changes winsav directory or quits Emacs.
-
-Possible values are:
- t -- always save.
- ask -- always ask.
- ask-if-new -- ask if no winsav file exists, otherwise just save.
- ask-if-exists -- ask if winsav file exists, otherwise don't save.
- if-exists -- save if winsav file exists, otherwise don't save.
- nil -- never save.
-The winsav config is never saved when the option `winsav-save-mode' is nil.
-The variables `winsav-dirname' and `winsav-base-file-name'
-determine where the winsav config is saved."
- :type
- '(choice
- (const :tag "Always save" t)
- (const :tag "Always ask" ask)
- (const :tag "Ask if winsav file is new, else do save" ask-if-new)
- (const :tag "Ask if winsav file exists, else don't save" ask-if-exists)
- (const :tag "Save if winsav file exists, else don't" if-exists)
- (const :tag "Never save" nil))
- :group 'winsav)
-
-(defcustom winsav-handle-also-desktop t
- "If this is non-nil then desktop is also saved and restored.
-See option `winsav-save-mode' for more information."
- :type 'boolean
- :group 'winsav)
-
-(defcustom winsav-base-file-name
- (convert-standard-filename ".emacs.winsav")
- "Base name of file for Emacs winsav, excluding directory part.
-The actual file name will have a system identifier added too."
- :type 'file
- :group 'winsav)
-
-(defvar winsav-dirname nil
- "The directory in which the winsav file should be saved.")
-
-(defun winsav-current-default-dir ()
- "Current winsav configuration directory."
- (or winsav-dirname "~/"))
-
-;;(find-file (winsav-full-file-name))
-(defun winsav-default-file-name ()
- "Default winsav save file name.
-The file name consist of `winsav-base-file-name' with a system
-identifier added. This will be '-nw' for a terminal and '-' +
-the value of `window-system' otherwise."
- (let ((sys-id (if (not window-system)
- "nw"
- (format "%s" window-system))))
- (concat winsav-base-file-name "-" sys-id)))
-
-(defun winsav-full-file-name (&optional dirname)
- "Return the full name of the winsav session file in DIRNAME.
-DIRNAME omitted or nil means use `~'.
-
-The file name part is given by `winsav-default-file-name'."
- ;; Fix-me: Different frames in different files? Can multi-tty be handled??
- (expand-file-name (winsav-default-file-name) (or dirname
- (winsav-current-default-dir))))
-
-
-
-(defun winsav-serialize (obj)
- "Return a string with the printed representation of OBJ.
-This should be possible to eval and get a similar object like OBJ
-again."
- ;;(message "winsav-serialize a")
- (prin1-to-string obj)
- ;;(message "winsav-serialize b")
- )
-
-(defcustom winsav-before-save-configuration-hook nil
- "Hook called before saving frames.
-Hook for writing elisp code at the beginning of a winsav
-configuration file. When this hook is called the current buffer
-and point is where the code should be written.
-
-This is a normal hook. For more information see
-`winsav-save-configuration'."
- :type 'hook
- :group 'winsav)
-
-(defcustom winsav-after-save-configuration-hook nil
- "Hook called after saving frames.
-Hook for writing elisp code at the end of a winsav configuration
-file. When this hook is called the current buffer and point is
-where the code should be written.
-
-This is a normal hook. For more information see
-`winsav-save-configuration'."
- :type 'hook
- :group 'winsav)
-
-(defcustom winsav-after-save-frame-hook nil
- "Hook called when saving a frame after saving frame data.
-Hook for writing elisp code in a winsav configuration file after
-each frame creation. When this hook is called code for restoring
-a frame has been written and code that sets
-`winsav-last-loaded-frame' to point to it. Point is in the
-configuration file buffer right after this.
-
-This is a normal hook. For more information see
-`winsav-save-configuration'."
- :type 'hook
- :group 'winsav)
-
-(defvar winsav-loaded-frames nil)
-(defvar winsav-last-loaded-frame nil)
-
-(defun winsav-restore-frame (frame-params
- window-tree-params
- use-minibuffer-frame
- window-state
- window-visible)
- "Restore a frame with specified values.
-If this is a minibuffer only frame then just apply the frame
-parameters FRAME-PARAMS. Otherwise create a new frame using
-FRAME-PARAMS and set up windows and buffers according to
-WINDOW-TREE-PARAMS. Also, if USE-MINIBUFFER-FRAME let the new
-frame have this minibuffer frame.
-
-WINDOW-STATE is 1 for minimized, 2 for normal and 3 for
-maximized."
- (let* ((default-minibuffer-frame use-minibuffer-frame)
- (frame-name (cdr (assoc 'name frame-params)))
- (minibuffer-val (cdr (assoc 'minibuffer frame-params)))
- (minibuffer-only (eq 'only minibuffer-val))
- (mini-frames
- (delq nil (mapcar (lambda (frm)
- (when (eq 'only (frame-parameter frm 'minibuffer))
- frm))
- (frame-list))))
- (frame-with-that-name
- (when (and frame-name minibuffer-only)
- (catch 'frame
- (dolist (frame (frame-list))
- (when (string= frame-name (frame-parameter frame 'name))
- (throw 'frame frame))))))
- ;; If this is a minibuffer only frame then if it is already
- ;; there under a correct name then do not create it because
- ;; there might be variables pointing to it; just set the
- ;; parameters. Perhaps even better: if it is not already
- ;; there give an error - because it might be impossible to
- ;; set things up correctly then.
- (frame-with-that-name-has-mini
- (when frame-with-that-name
- (eq 'only
- (frame-parameter frame-with-that-name 'minibuffer))))
- (this-mini-frame (when minibuffer-only
- (or frame-with-that-name
- (and (= 1 (length mini-frames))
- (car mini-frames)))))
- (create-new
- (if minibuffer-only
- (if this-mini-frame ;frame-with-that-name-has-mini
- nil
- (error "Winsav: Can't find minibuffer only frame with name %s"
- frame-name))
- t))
- (this-frame (if create-new
- (make-frame frame-params)
- this-mini-frame))
- (win (frame-first-window this-frame)))
- ;;(message "create-new=%s, frame-with-that-name=%s" create-new frame-with-that-name)
- ;; (when was-max
- ;; (winsav-set-maximized-size this-frame)
- ;; ;; Wait for maximize to occur so horizontal scrolling gets ok.
- ;; (sit-for 1.5)
- ;; )
- (case window-state
- (1 (winsav-set-minimized-state this-frame))
- (3 (winsav-set-maximized-state this-frame)))
- (unless window-visible
- (make-frame-invisible this-frame))
- (if create-new
- (winsav-put-window-tree window-tree-params win)
- (modify-frame-parameters this-frame frame-params))
- (setq winsav-last-loaded-frame this-frame)
- (setq winsav-loaded-frames (cons this-frame winsav-loaded-frames))
- ))
-
-(defcustom winsav-frame-parameters-to-save
- '(
- ;;explicit-name
- ;;name
- ;;parent-id
- ;;title
- alpha
- auto-lower
- auto-raise
- background-color
- background-mode
- border-color
- border-width
- buffer-predicate
- cursor-color
- cursor-type
- font
- font-backend
- foreground-color
- fullscreen
- icon-name
- icon-type
- icon-left
- icon-top
- internal-border-width
- left-fringe
- line-spacing
- menu-bar-lines
- modeline
- mouse-color
- right-fringe
- screen-gamma
- scroll-bar-width
- tool-bar-lines
- top left width height
- tty-color-mode ;; ??
- unsplittable
- user-position
- user-size
- vertical-scroll-bars
- visibility
- )
- "Parameters saved for frames by `winsav-save-configuration'.
-Parameters are those returned by `frame-parameters'."
- :type '(repeat (symbol :tag "Frame parameter"))
- :group 'winsav)
-
-(defun frame-visible-really-p (frame)
- "Return t if FRAME is visible.
-This tries to be more corrent on w32 than `frame-visible-p'."
- (cond ((fboundp 'w32-frame-placement)
- (< 0 (nth 4 (w32-frame-placement frame))))
- (t
- (frame-visible-p frame))))
-
-(defun frame-maximized-p (frame)
- "Return t if it is known that frame is maximized."
- (cond ((fboundp 'w32-frame-placement)
- (= 3 (abs (nth 4 (w32-frame-placement frame)))))
- (t nil)))
-
-(defun frame-minimized-p (frame)
- "Return t if it is known that frame is minimized."
- (cond ((fboundp 'w32-frame-placement)
- (= 3 (abs (nth 4 (w32-frame-placement frame)))))
- (t nil)))
-
-;;(winsav-set-restore-size nil)
-;; (defun winsav-set-restore-size (frame)
-;; (when (fboundp 'w32-send-sys-command)
-;; (let ((cur-frm (selected-frame)))
-;; (select-frame-set-input-focus frame)
-;; (w32-send-sys-command #xf120)
-;; ;; Note: sit-for must be used, not sleep-for. Using the latter
-;; ;; prevents the fetching of the new size (for some reason I do not
-;; ;; understand).
-;; (sit-for 1.5)
-;; (select-frame-set-input-focus cur-frm))
-;; t))
-
-(defun winsav-set-maximized-state (frame)
- (when (fboundp 'w32-send-sys-command)
- (select-frame-set-input-focus frame)
- (w32-send-sys-command #xf030)
- (sit-for 1.0)
- t))
-
-(defun winsav-set-minimized-state (frame)
- (when (fboundp 'w32-send-sys-command)
- (select-frame-set-input-focus frame)
- (w32-send-sys-command #xf020)
- (sit-for 1.0)
- t))
-
-(defun winsav-save-frame (frame mb-frm-nr buffer)
- "Write into buffer BUFFER elisp code to recreate frame FRAME.
-If MB-FRM-NR is a number then it is the order number of the frame
-whose minibuffer should be used."
- (message "winsav-save-frame buffer=%s" buffer)
- (message "winsav-save-frame buffer 2=%s" (current-buffer))
- (let* ((start nil)
- (end nil)
- (obj (winsav-get-window-tree frame))
- (dummy (message "winsav-save-frame buffer 3=%s" (current-buffer)))
- (frm-size-now (cons (frame-pixel-height frame)
- (frame-pixel-width frame)))
- (dummy (message "winsav-save-frame buffer 4=%s" (current-buffer)))
- (placement (when (fboundp 'w32-frame-placement) (w32-frame-placement frame)))
- ;; (was-max (and frm-size-rst
- ;; (not (equal frm-size-now frm-size-rst))))
- (window-state (abs (nth 4 placement)))
- ;; (frm-size-rst (when (winsav-set-restore-size frame)
- ;; (cons (frame-pixel-height frame)
- ;; (frame-pixel-width frame))))
- ;;(frm-size-rst (when was-max))
- ;;(frm-size-rst (when (= 3 (abs (nth 4 placement)))))
- (dummy (message "winsav-save-frame buffer 5=%s" (current-buffer)))
- (frm-par (frame-parameters frame))
- (dummy (message "winsav-save-frame buffer 6=%s" (current-buffer)))
- )
- (message "winsav-save-frame a1 cb=%s" (current-buffer))
- (with-current-buffer buffer
- ;;(y-or-n-p (format "was-max=%s" was-max))
- (message "winsav-save-frame a2 cb=%s" (current-buffer))
- (setq frm-par
- (delq nil
- (mapcar (lambda (elt)
- (cond
- ((memq (car elt) winsav-frame-parameters-to-save)
- elt)
- ((eq (car elt) 'minibuffer)
- (let ((val (cdr elt)))
- (if (not (windowp val))
- elt
- (if (eq (window-frame val) frame)
- nil
- (cons 'minibuffer nil)))))))
- frm-par)))
- (message "winsav-save-frame b cb=%s" (current-buffer))
- (insert "(winsav-restore-frame\n'"
- ;;make-frame-params
- (winsav-serialize frm-par))
- (message "winsav-save-frame b.0.1")
- ;;window-tree-params
- (setq start (point))
- (insert "'" (winsav-serialize obj) "\n")
- (message "winsav-save-frame b.0.2")
- (setq end (copy-marker (point) t))
- (message "winsav-save-frame b.0.3")
- (message "winsav-save-frame b.1")
- ;; (replace-regexp (rx "#<buffer "
- ;; (1+ (not (any ">")))
- ;; (1+ ">")) ;; 1+ for indirect buffers ...
- ;; "buffer"
- ;; nil start end)
- (goto-char start)
- (while (re-search-forward (rx "#<buffer "
- (1+ (not (any ">")))
- (1+ ">")) ;; 1+ for indirect buffers ...
- end t)
- (replace-match "buffer" nil t))
- (message "winsav-save-frame b.2")
- ;; (replace-regexp (rx "#<window "
- ;; (1+ (not (any ">")))
- ;; (1+ ">"))
- ;; "nil"
- ;; nil start end)
- (goto-char start)
- (while (re-search-forward (rx "#<window "
- (1+ (not (any ">")))
- (1+ ">")) ;; 1+ for indirect buffers ...
- end t)
- (replace-match "nil" nil t))
- (message "winsav-save-frame c")
- (goto-char end)
- ;;use-minibuffer-frame
- (insert (if mb-frm-nr
- (format "(nth %s (reverse winsav-loaded-frames))" mb-frm-nr)
- "nil")
- (format " %s" window-state)
- (if (frame-visible-really-p frame) " t " " nil ")
- ")\n\n")
-
- (insert " ;; ---- before after-save-frame-hook ----\n")
- ;; (dolist (fun winsav-after-save-frame-hook)
- ;; (funcall fun frame (current-buffer)))
- (run-hooks winsav-after-save-frame-hook)
- (message "winsav-save-frame d")
- (insert " ;; ---- after after-save-frame-hook ----\n")
-
- ;;(insert " )\n\n\n")
- )))
-
-(defvar winsav-file-version "1"
- "Version number of winsav file format.
-Written into the winsav file and used at winsav read to provide
-backward compatibility.")
-
-
-;; fix-me: This should be in desktop.el
-;; Fix-me: incomplete, not ready.
-(defun winsav-restore-indirect-file-buffer (file name)
- "Make indirect buffer from file buffer visiting file FILE.
-Give it the name NAME."
- (let* ((fbuf (find-file-noselect file)))
- (when fbuf
- (make-indirect-buffer fbuf name))))
-
-(defun winsav-save-indirect-buffers (to-buffer)
- "Save information about indirect buffers.
-Only file visiting buffers currently. Clone the base buffers."
- (with-current-buffer to-buffer
- (dolist (buf (buffer-list))
- (when (buffer-base-buffer buf)
- (let* ((base-buf (buffer-base-buffer buf))
- (file (buffer-file-name base-buf)))
- (when file
- (insert "(winsav-restore-indirect-file-buffer \""
- file "\" \"" (buffer-name buf) "\")\n")))))))
-
-;; Fix-me: test
-;; (defun winsav-restore-minibuffer (frame-num frm-num win-num)
-;; (let* ((frame (nth (1- frame-num) winsav-loaded-frames))
-;; (mini-frm (nth (1- frm-num) winsav-loaded-frames))
-;; (mini-win (nth (1- win-num) (reverse (window-list mini-frm))))
-;; )
-;; (with-selected-frame frame
-;; (set-minibuffer-window mini-win))))
-
-(defvar winsav-minibuffer-alist nil)
-(defun winsav-save-minibuffers (sorted-frames to-buffer)
- "Save information about minibuffer frames.
-SORTED-FRAMES should be a list of all frames sorted using
-`winsav-frame-sort-predicate'."
- (with-current-buffer to-buffer
- (setq winsav-minibuffer-alist nil)
- (dolist (frame sorted-frames)
- (let* ((num-frames (length sorted-frames))
- (mini-win (minibuffer-window frame))
- (mini-frm (window-frame mini-win))
- (win-num (length
- (memq mini-win
- (window-list mini-frm t (frame-first-window mini-frm)))))
- (frm-num (- num-frames (length (memq mini-frm sorted-frames))))
- (frame-num (- num-frames (length (memq frame sorted-frames)))))
- (unless (and (eq mini-frm frame)
- (= win-num 1))
- ;; Not the normal minibuffer window
- ;;(insert (format ";;(winsav-restore-minibuffer %s %s %s)\n"
- ;;(insert (format "'(%s %s)\n" frame-num frm-num)
- (setq winsav-minibuffer-alist (cons (list frame-num frm-num) winsav-minibuffer-alist))
- )))
- (insert "(setq winsav-minibuffer-alist '"
- (winsav-serialize winsav-minibuffer-alist)
- ")\n")))
-
-(defun winsav-restore-dedicated-window (frame-num win-num dedicate-flag)
- "Set dedicated window flag.
-On frame number FRAME-NUM in `winsav-loaded-frames' set the
-dedicated flag on window number WIN-NUM to DEDICATE-FLAG."
- (let* ((frame (nth (1- frame-num) winsav-loaded-frames))
- (win (nth (1- win-num) (reverse (window-list frame t
- (frame-first-window frame))))))
- (set-window-dedicated-p win dedicate-flag)))
-
-(defun winsav-save-dedicated-windows (sorted-frames)
- "Save information about dedicated windows on frames in SORTED-FRAMES.
-Write this to current buffer."
- (dolist (frame sorted-frames)
- (dolist (win (window-list frame))
- (when (window-dedicated-p win)
- (let ((frame-num (length (memq frame sorted-frames)))
- (win-num (length
- (memq win
- (window-list frame t (frame-first-window frame)))))
- (flag (window-dedicated-p win)))
- (insert (format "(winsav-restore-dedicated-window %s %s %S)\n" frame-num win-num flag))
- )))))
-
-(defun winsav-restore-ecb (frame-num layout-ecb)
- "Restore ECB.
-On frame number FRAME-NUM-ECB in `winsav-loaded-frames' restore
-ECB layout LAYOUT-ECB."
- (when (boundp 'ecb-minor-mode)
- (let* ((frame (nth (1- frame-num) winsav-loaded-frames)))
- (select-frame frame)
- (unless (string= layout-ecb ecb-layout-name)
- (setq ecb-layout-name layout-ecb))
- (ecb-minor-mode 1))))
-
-(defun winsav-save-ecb (frame-ecb layout-ecb sorted-frames)
- "Save information about ECB layout on frames in SORTED-FRAMES.
-Write this in current buffer."
- (dolist (frame sorted-frames)
- (when (eq frame frame-ecb)
- (let ((frame-num (length (memq frame sorted-frames))))
- (insert (format "(winsav-restore-ecb %s %S)\n" frame-num layout-ecb))))))
-
-;; (make-frame '((minibuffer)))
-;; (sort (frame-list) 'winsav-frame-sort-predicate)
-(defun winsav-frame-sort-predicate (a b)
- "Compare frame A and B for sorting.
-Sort in the order frames can be created.
-
-- Frames without minibuffers will come later since the need to
- refer to the minibuffer frame when they are created.
-
-- Invisible frames comes last since there must be at least one
- visible frame from the beginning."
- (let* ((a-mbw (minibuffer-window a))
- (a-mbw-frm (window-frame a-mbw))
- (b-mbw (minibuffer-window b))
- (b-mbw-frm (window-frame b-mbw))
- (a-visible (frame-visible-really-p a))
- (b-visible (frame-visible-really-p b))
- )
- ;;(message "a-mbw-frm=%s, b=%s" a-mbw-frm b)
- ;;(message "b-mbw-frm=%s, a=%s" a-mbw-frm b)
- (when (or (not b-visible)
- (eq a-mbw-frm b)
- (not (eq b-mbw-frm b)))
- ;;(message "a > b")
- t
- )))
-
-(defun winsav-can-read-config (config-version)
- "Return t we can read config file version CONFIG-VERSION."
- (when (<= config-version 1)
- t))
-
-(defvar winsav-file-modtime nil)
-
-;; Like desktop-save, fix-me
-(defun winsav-save-configuration (&optional dirname release)
- "Write elisp code to recreate all frames.
-Write into the file name computed by `winsav-full-file-name'
-given the argument DIRNAME.
-
-The information that is saved for each frame is its size and
-position, the window configuration including buffers and the
-parameters in `winsav-frame-parameters-to-save'. If you want save
-more information for frames you can do that in the hook
-`winsav-after-save-frame-hook'.
-
-See also the hook variables
-`winsav-before-save-configuration-hook' and
-`winsav-after-save-configuration-hook'.
-
-Fix-me: RELEASE is not implemented."
- (winsav-save-config-to-file (winsav-full-file-name dirname)))
-
-(defun winsav-save-config-to-file (conf-file)
- "Write elisp code to recreate all frames to CONF-FILE."
- (let (start
- end
- (sorted-frames (sort (frame-list) 'winsav-frame-sort-predicate))
- (frm-nr 0)
- frame-ecb
- layout-ecb)
- ;; Recreating invisible frames hits Emacs bug 3859
- (setq sorted-frames
- (delq nil
- (mapcar (lambda (f)
- (when (frame-parameter f 'visibility) f))
- sorted-frames)))
- (when (and (boundp 'ecb-minor-mode) ecb-minor-mode)
- (when (frame-live-p ecb-frame)
- (setq layout-ecb ecb-layout-name)
- (setq frame-ecb ecb-frame))
- (ecb-minor-mode -1)
- (sit-for 0) ;; Fix-me: is this needed?
- )
- (message "winsav-save-config:here a")
- (with-temp-buffer
- (let ((this-buffer (current-buffer)))
- (message "winsav-save-config:here b")
- ;;(erase-buffer)
- (insert
- ";; -*- mode: emacs-lisp; coding: utf-8; -*-\n"
- ";; --------------------------------------------------------------------------\n"
- ";; Winsav File for Emacs\n"
- ";; --------------------------------------------------------------------------\n"
- ";; Created " (current-time-string) "\n"
- ";; Winsav file format version " winsav-file-version "\n"
- ";; Emacs version " emacs-version "\n\n"
- "(if (not (winsav-can-read-config " winsav-file-version "))\n\n"
- " (message \"Winsav: Can't read config file with version " winsav-file-version "\")\n")
- (message "winsav-save-config:here c")
- (insert ";; ---- indirect buffers ------------------------\n")
- (winsav-save-indirect-buffers this-buffer)
- (message "winsav-save-config:here c.1")
- ;;(insert ";; ---- special minibuffers ------------------------\n")
- (winsav-save-minibuffers sorted-frames this-buffer)
- (message "winsav-save-config:here c.2")
- (insert "(setq winsav-loaded-frames nil)\n")
- (insert ";; ---- before winsav-before-save-configuration-hook ------------------------\n")
- (run-hooks 'winsav-before-save-configuration-hook)
- (message "winsav-save-config:here c.2a cb=%s" (current-buffer))
- (insert ";; ---- after winsav-before-save-configuration-hook ------------------------\n\n")
- (dolist (frm sorted-frames)
- (let ((mb-frm-nr (cadr (assoc frm-nr winsav-minibuffer-alist)))
- ;;(mb-frm (when mb-frm-nr (nth mb-frm-nr sorted-frames)))
- )
- (message "winsav-save-config:here c.2b.1 tb=%s cb=%s frm=%s" this-buffer (current-buffer) frm)
- (winsav-save-frame frm mb-frm-nr this-buffer)
- (message "winsav-save-config:here c.2b.2")
- (setq frm-nr (1+ frm-nr))))
- (message "winsav-save-config:here c.2c cb=%s" (current-buffer))
- (insert ";; ---- dedicated windows ------------------------\n")
- (winsav-save-dedicated-windows sorted-frames)
- (message "winsav-save-config:here c.3")
- (insert ";; ---- ECB --------------------------------------\n")
- (winsav-save-ecb frame-ecb layout-ecb sorted-frames)
- (message "winsav-save-config:here c.4")
- (insert "\n\n;; ---- before winsav-after-save-configuration-hook ------------------------\n")
- (run-hooks 'winsav-after-save-configuration-hook)
- (message "winsav-save-config:here c.5")
- (insert "\n\n;; ---- before winsav-after-save-configuration-hook ------------------------\n")
- (run-hooks 'winsav-after-save-configuration-hook)
- (message "winsav-save-config:here c.6")
- (insert ";; ---- after winsav-after-save-configuration-hook ------------------------\n")
- (insert "\n)\n")
- (message "winsav-save-config:here d")
- ;; For pp-buffer:
- (let (emacs-lisp-mode-hook
- after-change-major-mode-hook
- change-major-mode-hook)
- (font-lock-mode -1)
- (emacs-lisp-mode))
- (message "winsav-save-config:here e")
- (pp-buffer)
- (message "winsav-save-config:here f")
- (indent-region (point-min) (point-max))
- (message "winsav-save-config:here g")
- ;;(save-buffer 0) ;; No backups
- ;;(kill-buffer)
-
- ;;(with-current-buffer (find-file-noselect file)
- (let ((coding-system-for-write 'utf-8))
- (write-region (point-min) (point-max) conf-file nil 'nomessage))
- (setq winsav-file-modtime (nth 5 (file-attributes conf-file)))
- (setq winsav-dirname (file-name-as-directory (file-name-directory conf-file)))
- (message "winsav-save-config:here h")
- ))))
-
-(defvar winsav-current-config-name nil)
-
-;;(winsav-restore-configuration)
-;;(winsav-full-file-name "~")
-;; (defun winsav-restore-winsav-configuration ()
-;; )
-
-(defcustom winsav-after-restore-hook nil
- "Normal hook run after a successful `winsav-restore-configuration'."
- :type 'hook
- :group 'winsav)
-
-;; Like desktop-read, fix-me
-(defun winsav-restore-configuration (&optional dirname)
- "Restore frames from default file in directory DIRNAME.
-The default file is given by `winsav-default-file-name'.
-
-The file was probably written by `winsav-save-configuration'.
-Delete the frames that were used before."
- ;;(message "winsav-restore-configuration %s" dirname)
- (winsav-restore-config-from-file (winsav-full-file-name dirname)))
-
-(defun winsav-restore-config-from-file (conf-file)
- "Restore frames from configuration file CONF-FILE.
-The file was probably written by `winsav-save-configuration'.
-Delete the frames that were used before."
- (let ((old-frames (sort (frame-list) 'winsav-frame-sort-predicate))
- (num-old-deleted 0)
- ;; Avoid winsav saving during restore.
- (winsav-save nil))
- ;;(message "winsav:conf-file=%s" conf-file)
- (if (or (not conf-file)
- (not (file-exists-p conf-file)))
- (progn
- (message (propertize "Winsav: No default configuration file found"
- 'face 'secondary-selection))
- t) ;; Ok
- (setq debug-on-error t) ;; fix-me
- (if (file-exists-p conf-file)
- (progn
- (load conf-file nil nil t)
- (setq winsav-file-modtime (nth 5 (file-attributes conf-file)))
- (setq winsav-dirname (file-name-as-directory (file-name-directory conf-file)))
- (when (< 0 (length winsav-loaded-frames))
- (dolist (old (reverse old-frames))
- (unless (eq 'only (frame-parameter old 'minibuffer))
- (setq num-old-deleted (1+ num-old-deleted))
- (delete-frame old)))
- )
- (message "winsav-after-restore-hook =%S" winsav-after-restore-hook)
- (run-hooks 'winsav-after-restore-hook)
- (message "Winsav: %s frame(s) restored" (length winsav-loaded-frames))
- t)
- ;; No winsav file found
- ;;(winsav-clear)
- (message "No winsav file: %s" conf-file)
- nil))))
-
-;; (defcustom winsav-add-to-desktop nil
-;; "Set this to let desktop save and restore also winsav configurations."
-;; :type 'boolean
-;; :set (lambda (sym val)
-;; (set-default sym val)
-;; (if value
-;; (progn
-;; (add-hook 'desktop-after-read-hook 'winsav-restore-configuration)
-;; (add-hook 'desktop-save-hook 'winsav-save-configuration))
-;; (remove-hook 'desktop-after-read-hook 'winsav-restore-configuration)
-;; (remove-hook 'desktop-save-hook 'winsav-save-configuration)) )
-;; :group 'winsav)
-
-(defun winsav-restore-configuration-protected (&optional dirname)
- "Like `winsav-restore-configuration' but protect for errors.
-DIRNAME has the same meaning."
- (condition-case err
- (winsav-restore-configuration dirname)
- (error
- (message "winsav-restore-configuration: %s" err))))
-
-(defun winsav-relative-~-or-full (dirname)
- (let* ((rel-dir (file-relative-name dirname
- (file-name-directory
- (winsav-full-file-name "~"))))
- (confname (if (string= ".." (substring rel-dir 0 2))
- winsav-dirname
- (if (string= rel-dir "./")
- "(default)"
- (concat "~/" rel-dir)))))
- confname))
-
-(defun winsav-tell-configuration ()
- "Tell which winsav configuration that is used."
- (interactive)
- (save-match-data ;; runs in timer
- (let ((confname (if (not winsav-dirname)
- "(none)"
- (winsav-relative-~-or-full winsav-dirname))))
- (if t ;;(called-interactively-p)
- (message (propertize (format "Current winsav config is '%s'" confname)
- 'face 'secondary-selection))
- (save-window-excursion
- (delete-other-windows)
- (set-window-buffer (selected-window)
- (get-buffer-create " *winsav*"))
- (with-current-buffer (window-buffer)
- (momentary-string-display
- (propertize
- (format "\n\n\n Current winsav config is '%s'\n\n\n\n" confname)
- 'face 'secondary-selection)
- (window-start)
- (kill-buffer))))))))
-
-(defun winsav-tell-configuration-request ()
- "Start an idle timer to call `winsav-tell-configuration'."
- (run-with-idle-timer 1 nil 'winsav-tell-configuration))
-
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Startup and shut down
-
-;; Run after desktop at startup so that desktop has loaded files and
-;; buffers.
-(defun winsav-after-init ()
- "Restore frames and windows.
-Run this once after Emacs startup, after desktop in the
-`after-init-hook'."
- ;; Turn off with --no-deskttop:
- (unless desktop-save-mode (winsav-save-mode -1))
- (when winsav-save-mode
- ;;(run-with-idle-timer 0.1 nil 'winsav-restore-configuration-protected)
- ;;(message "winsav-after-init")
- ;;(winsav-restore-configuration-protected)
- ;; In case of error make sure winsav-save-mode is turned off
- (setq inhibit-startup-screen t)
- (winsav-save-mode -1)
- (winsav-restore-configuration)
- (winsav-save-mode 1)
- ))
-
-(add-hook 'after-init-hook 'winsav-after-init t)
-
-(add-hook 'kill-emacs-hook 'winsav-kill)
-;;(remove-hook 'kill-emacs-hook 'winsav-kill)
-
-(defun winsav-kill ()
- "Save winsav frame configuration.
-Run this before Emacs exits."
- ;; (when winsav-save-mode
- ;; (let ((conf-dir (when winsav-current-config-name
- ;; (winsav-full-config-dir-name winsav-current-config-name))))
- ;; (winsav-save-configuration conf-dir))))
- (when (and winsav-save-mode
- (let ((exists (file-exists-p (winsav-full-file-name))))
- (or (eq winsav-save t)
- (and exists (memq winsav-save '(ask-if-new if-exists)))
- (and
- (or (memq winsav-save '(ask ask-if-new))
- (and exists (eq winsav-save 'ask-if-exists)))
- (y-or-n-p "Save winsav? ")))))
- (unless winsav-dirname
- ;; Fix-me: Since this can be a new user of winsav I think the
- ;; best thing to do here is to encourage the user to save in the
- ;; default directory since otherwise the winsav file will not be
- ;; loaded at startup. Desktop does not currently do that however
- ;; (report that!).
- (when (y-or-n-p "Winsav was not loaded from file. Save it to file? ")
- (let* ((full-file (winsav-full-file-name))
- (default-directory (directory-file-name
- (file-name-directory full-file))))
- (setq winsav-dirname
- (file-name-as-directory
- (expand-file-name
- (read-directory-name "Directory for winsav file: " nil nil t)))))))
- (when winsav-dirname
- (condition-case err
- ;;(winsav-save winsav-dirname t)
- (winsav-save-configuration winsav-dirname)
- (file-error
- (unless (yes-or-no-p
- (format "Error while saving winsav config: %s Save anyway? "
- (error-message-string err)))
- (signal (car err) (cdr err)))))))
- ;; If we own it, we don't anymore.
- ;;(when (eq (emacs-pid) (winsav-owner)) (winsav-release-lock))
- )
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Switching configurations
-
-(defun winsav-restore-full-config (dirname)
- "Restore the winsav configuration in directory DIRNAME.
-If NAME is nil then restore the startup configuration."
- ;;(desktop-change-dir dirname)
- (when (and winsav-handle-also-desktop desktop-save-mode)
- (when (eq (emacs-pid) (desktop-owner)) (desktop-release-lock))
- (desktop-clear)
- (desktop-read dirname))
- (winsav-restore-configuration dirname)
- ;;(setq winsav-current-config-name name)
- (winsav-tell-configuration-request))
-
-(defun winsav-full-config-dir-name (name)
- "Return full directory path where configuration NAME is stored."
- (let* ((base-dir (concat (winsav-full-file-name) ".d"))
- (conf-dir (expand-file-name name base-dir)))
- (setq conf-dir (file-name-as-directory conf-dir))
- ;;(message "conf-dir=%s" conf-dir)
- conf-dir))
-
-;;;###autoload
-(defun winsav-save-full-config (dirname)
- "Saved current winsav configuration in directory DIRNAME.
-Then change to this configuration.
-
-See also `winsav-switch-config'."
- (unless (file-name-absolute-p dirname)
- (error "Directory ame must be absolute: %s" dirname))
- (let* ((conf-dir (or dirname "~"))
- (old-conf-dir winsav-dirname))
- (make-directory conf-dir t)
- (winsav-save-configuration conf-dir)
- (when (and winsav-handle-also-desktop desktop-save-mode)
- (desktop-release-lock)
- (desktop-save conf-dir))
- ;;(unless (string= winsav-current-config-name name)
- (unless (string= old-conf-dir conf-dir)
- ;;(setq winsav-current-config-name name)
- (winsav-tell-configuration-request))))
-
-;; Fix-me: remove named configurations, use just dir as desktop
-(defun winsav-switch-to-default-config ()
- "Change to default winsav configuration.
-See also `winsav-switch-config'."
- (interactive)
- (winsav-switch-config "~"))
-
-;;;###autoload
-(defun winsav-switch-config (dirname)
- "Change to winsav configuration in directory DIRNAME.
-If DIRNAME is the current winsav configuration directory then
-offer to save it or restore it from saved values.
-
-Otherwise, before switching offer to save the current winsav
-configuration. Then finally switch to the new winsav
-configuration, creating it if it does not exist.
-
-If option `desktop-save-mode' is on then buffers and files are also
-restored and saved the same way.
-
-See also option `winsav-save-mode' and command
-`winsav-tell-configuration'."
- (interactive
- (list
- (let ((default-directory (or winsav-dirname default-directory))
- (base-dir (concat (winsav-full-file-name) ".d"))
- new-dir)
- (make-directory base-dir t)
- (setq new-dir
- (read-directory-name "Winsav: Switch config directory: "))
- (when (string= "" new-dir) (setq new-dir nil))
- (or new-dir
- "~"))))
- (setq dirname (file-name-as-directory (expand-file-name dirname)))
- (catch 'stop
- (let ((conf-file (expand-file-name winsav-base-file-name dirname))
- config-exists)
- (if (file-exists-p conf-file)
- (setq config-exists t)
- (unless (y-or-n-p (format "%s was not found. Create it? " conf-file))
- (throw 'stop nil)))
- (if (string= winsav-dirname dirname)
- (if (y-or-n-p "You are already using this configuration, restore it from saved values? ")
- (winsav-restore-full-config winsav-dirname)
- (when (y-or-n-p "You are already using this winsav configuration, save it? ")
- (winsav-save-full-config winsav-dirname)))
- (when (y-or-n-p
- (format "Save current config, %s,\n first before switching to %s? "
- (if (and winsav-dirname
- (not (string= winsav-dirname
- (file-name-directory (winsav-full-file-name "~")))))
- winsav-dirname
- "the startup config")
- dirname))
- (winsav-save-full-config winsav-dirname))
- (if config-exists
- (winsav-restore-full-config dirname)
- (winsav-save-full-config dirname))))))
-
-
-
-
-;;; Old things
-
-;; (defun winsav-log-buffer ()
-;; (get-buffer-create "winsav log buffer"))
-
-;; (defun winsav-log (mark obj)
-;; (with-current-buffer (winsav-log-buffer)
-;; (insert "=== " mark "===\n" (pp-to-string obj))))
-
-;; (global-set-key [f2] 'winsav-test-get)
-;; (global-set-key [f3] 'winsav-test-put)
-;; (defvar winsav-saved-window-tree nil)
-
-;; (defun winsav-test-get()
-;; (interactive)
-;; (setq winsav-saved-window-tree (winsav-get-window-tree)))
-
-;; (defun winsav-test-put()
-;; (interactive)
-;; (let ((ret (winsav-put-window-tree winsav-saved-window-tree
-;; (selected-window))))
-;; ;;(message "ret=%s" ret)
-;; ))
-
-;; (defun winsav-serialize-to-file (obj file)
-;; (with-current-buffer (find-file-noselect file)
-;; ;;(erase-buffer)
-;; (save-restriction
-;; (widen)
-;; (goto-char (point-max))
-;; (insert (winsav-serialize obj)
-;; "\n"))
-;; ;;(basic-save-buffer)
-;; ))
-
-;;(global-set-key [f11] 'winsav-rotate)
-
-;; (defun winsav-de-serialize-window-tree-from-file (file)
-;; (with-current-buffer (find-file-noselect file)
-;; (save-restriction
-;; (widen)
-;; (let ((start (point))
-;; (end nil))
-;; (forward-list)
-;; (setq end (point))
-;; ;;(goto-char (point-min))
-;; (winsav-de-serialize-window-tree (buffer-substring-no-properties start end))))))
-
-;; (defun winsav-restore-from-file (file)
-;; (winsav-put-window-tree
-;; (winsav-de-serialize-window-tree-from-file file)
-;; (selected-window)))
-
-;; (defun winsav-de-serialize-window-tree (str)
-;; (save-match-data
-;; (let ((read-str
-;; (replace-regexp-in-string (rx "#<buffer "
-;; (1+ (not (any ">")))
-;; ">")
-;; "buffer"
-;; str))
-;; obj-last
-;; obj
-;; last)
-;; (setq read-str
-;; (replace-regexp-in-string (rx "#<window "
-;; (1+ (not (any ">")))
-;; ">")
-;; "nil"
-;; read-str))
-;; (setq obj-last (read-from-string read-str))
-;; (setq obj (car obj-last))
-;; (setq last (cdr obj-last))
-;; ;; Fix me, maby check there are only spaces left (or trim them above...)
-;; obj)))
-
-(provide 'winsav)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; winsav.el ends here