From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: martin rudalics Newsgroups: gmane.emacs.bugs Subject: bug#10348: 24.0.92; Save and load window states Date: Thu, 29 Dec 2011 12:39:13 +0100 Message-ID: <4EFC5161.8040808@gmx.at> References: <4ef24371.94110e0a.6fbb.ffffc8f3@mx.google.com> <4EF36318.6000006@gmx.at> <4EF45888.3030204@gmx.at> <4EF59B02.9060608@gmx.at> <4EF72BE9.60604@gmx.at> <4EF8557A.3020001@gmx.at> <4EF8BC0B.6020805@gmx.at> <4EFB3C66.6040104@gmx.at> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050300020408020508060900" X-Trace: dough.gmane.org 1325158832 14241 80.91.229.12 (29 Dec 2011 11:40:32 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Thu, 29 Dec 2011 11:40:32 +0000 (UTC) Cc: Michael Bach , 10348@debbugs.gnu.org To: Stefan Monnier Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Thu Dec 29 12:40:28 2011 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1RgELT-0002Bh-LC for geb-bug-gnu-emacs@m.gmane.org; Thu, 29 Dec 2011 12:40:28 +0100 Original-Received: from localhost ([::1]:45087 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RgELT-0005jX-8C for geb-bug-gnu-emacs@m.gmane.org; Thu, 29 Dec 2011 06:40:27 -0500 Original-Received: from eggs.gnu.org ([140.186.70.92]:45265) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RgELM-0005jD-M9 for bug-gnu-emacs@gnu.org; Thu, 29 Dec 2011 06:40:25 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RgELG-0005CY-Ai for bug-gnu-emacs@gnu.org; Thu, 29 Dec 2011 06:40:20 -0500 Original-Received: from debbugs.gnu.org ([140.186.70.43]:57274) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RgELG-0005CU-7N for bug-gnu-emacs@gnu.org; Thu, 29 Dec 2011 06:40:14 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.69) (envelope-from ) id 1RgENz-0006dD-9n for bug-gnu-emacs@gnu.org; Thu, 29 Dec 2011 06:43:03 -0500 X-Loop: help-debbugs@gnu.org Resent-From: martin rudalics Original-Sender: debbugs-submit-bounces@debbugs.gnu.org Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 29 Dec 2011 11:43:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 10348 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 10348-submit@debbugs.gnu.org id=B10348.132515894125413 (code B ref 10348); Thu, 29 Dec 2011 11:43:02 +0000 Original-Received: (at 10348) by debbugs.gnu.org; 29 Dec 2011 11:42:21 +0000 Original-Received: from localhost ([127.0.0.1] helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1RgENI-0006bp-Iu for submit@debbugs.gnu.org; Thu, 29 Dec 2011 06:42:21 -0500 Original-Received: from mailout-de.gmx.net ([213.165.64.22]) by debbugs.gnu.org with smtp (Exim 4.69) (envelope-from ) id 1RgENC-0006be-UO for 10348@debbugs.gnu.org; Thu, 29 Dec 2011 06:42:17 -0500 Original-Received: (qmail invoked by alias); 29 Dec 2011 11:39:23 -0000 Original-Received: from 62-47-44-99.adsl.highway.telekom.at (EHLO [62.47.44.99]) [62.47.44.99] by mail.gmx.net (mp058) with SMTP; 29 Dec 2011 12:39:23 +0100 X-Authenticated: #14592706 X-Provags-ID: V01U2FsdGVkX19zJPhfhkxzDNlrgPiWaf5yiGUEfJNpejurm0v+vM SWppLmVs8SWonb User-Agent: Thunderbird 2.0.0.21 (Windows/20090302) In-Reply-To: X-Y-GMX-Trusted: 0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.11 Precedence: list Resent-Date: Thu, 29 Dec 2011 06:43:03 -0500 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:55266 Archived-At: This is a multi-part message in MIME format. --------------050300020408020508060900 Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit > I don't understand: you first seem to say you disagree with me, but then > what you say afterwards seems to agree with me. Indeed. > Indeed, but otherwise, as you pointed out, it makes the semantics rather > tricky if window-persistent-parameters is changed between the save and > the restore (which is something that is very likely to happen sometimes > since the restore may happen years after the save). I resolved the semantics by saving always all parameters unless I do `window-state-get' with IGNORE non-nil and the parameter is in `window-state-ignored-parameters'. When restoring parameters via `set-window-configuration'/`window-state-put', I overwrite/install a value only if the parameter is in `window-persistent-parameters'. martin --------------050300020408020508060900 Content-Type: text/plain; name="window-parameters.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="window-parameters.diff" === modified file 'doc/lispref/windows.texi' --- doc/lispref/windows.texi 2011-12-13 13:37:48 +0000 +++ doc/lispref/windows.texi 2011-12-29 10:34:38 +0000 @@ -3104,7 +3104,7 @@ @defun current-window-configuration &optional frame This function returns a new object representing @var{frame}'s current window configuration. The default for @var{frame} is the selected -frame. +frame. This function copies the value of all window parameters. @end defun @defun set-window-configuration configuration @@ -3121,6 +3121,9 @@ know how to tell whether the new configuration actually differs from the old one. +This function restores the values of all window parameters listed by +@code{window-persistent-parameters}, see below. + If the frame which @var{configuration} was saved from is dead, all this function does is restore the three variables @code{window-min-height}, @code{window-min-width} and @code{minibuffer-scroll-window}. In this @@ -3140,6 +3143,18 @@ @end example @end defun +@defvar window-persistent-parameters +This variable lists all window parameters that are restored by +@code{set-window-configuration}, see above. This means that the value +of any parameter listed by this variable and changed within the body of +@code{save-window-excursion} is restored to its previous value when the +window excursion exits. Parameters not listed by this variable are left +alone when the window excursion terminates. + +Parameters not listed by this variable are effectively not installed by +the function @code{window-state-put}, see below. +@end defvar + @defspec save-window-excursion forms@dots{} This special form records the window configuration, executes @var{forms} in sequence, then restores the earlier window configuration. The window @@ -3209,18 +3224,25 @@ configuration on disk and read it back in another Emacs session the following two functions can be used. -@defun window-state-get &optional window markers +@defun window-state-get &optional window ignore This function returns the state of @var{window} as a Lisp object. The argument @var{window} can be any window and defaults to the root window of the selected frame. -The optional argument @var{markers} non-@code{nil} means to use markers -for sampling positions like @code{window-point} or @code{window-start}. -This argument should be non-@code{nil} only if the value is used for -putting the state back in the same session since markers slow down -processing. +If the optional argument @var{ignore} is non-@code{nil}, this means to +not use markers for sampling positions like @code{window-point} or +@code{window-start} and to not save values of parameters in the list +@code{window-state-ignored-parameters}, see below. This argument should +be non-@code{nil} when the state shall be written on disk and read back +in another session. @end defun +@defvar window-state-ignored-parameters +This variable lists all parameters whose value is not recorded by the +function @code{window-state-get} when its @var{ignore} argument is +non-@code{nil}, see above. +@end defvar + The value returned by @code{window-state-get} can be converted by using one of the functions defined by Desktop Save Mode (@pxref{Desktop Save Mode}) to an object that can be written to a file. Such objects can be @@ -3239,6 +3261,10 @@ minimum window sizes and fixed size restrictions. If @var{ignore} equals @code{safe}, this means windows can get as small as one line and/or two columns. + +This function installs the values of all window parameters listed by +@code{window-persistent-parameters}, see above, provided their values +are stored in @var{state}. @end defun === modified file 'lisp/window.el' --- lisp/window.el 2011-12-24 19:16:53 +0000 +++ lisp/window.el 2011-12-29 10:11:05 +0000 @@ -3568,10 +3568,12 @@ )) ;;; Window states, how to get them and how to put them in a window. -(defvar window-state-ignored-parameters '(quit-restore) - "List of window parameters ignored by `window-state-get'.") +(defvar window-state-ignored-parameters '(quit-restore clone-of) + "Window parameters ignored by `window-state-get'. +Parameters in this list are not saved by `window-state-get' when +its IGNORE argument is non-nil.") -(defun window--state-get-1 (window &optional markers) +(defun window--state-get-1 (window &optional ignore) "Helper function for `window-state-get'." (let* ((type (cond @@ -3590,11 +3592,15 @@ (combination-limit . ,(window-combination-limit window)) ,@(let (list) (dolist (parameter (window-parameters window)) - (unless (memq (car parameter) - window-state-ignored-parameters) - (setq list (cons parameter list)))) - (unless (window-parameter window 'clone-of) - ;; Make a clone-of parameter. + ;; When IGNORE is non-nil, add a parameter if and only + ;; if it is not in `window-state-ignored-parameters'. + (unless (and ignore + (memq (car parameter) + window-state-ignored-parameters)) + (setq list (cons (cons (car parameter) (cdr parameter)) + list)))) + (unless (or ignore (window-parameter window 'clone-of)) + ;; Make `clone-of' parameter unless IGNORE is non-nil. (setq list (cons (cons 'clone-of window) list))) (when list `((parameters . ,list)))) @@ -3616,30 +3622,32 @@ (scroll-bars . ,(window-scroll-bars window)) (vscroll . ,(window-vscroll window)) (dedicated . ,(window-dedicated-p window)) - (point . ,(if markers (copy-marker point) point)) - (start . ,(if markers (copy-marker start) start)) + (point . ,(if ignore point (copy-marker point))) + (start . ,(if ignore start (copy-marker start))) ,@(when mark - `((mark . ,(if markers - (copy-marker mark) mark))))))))))) + `((mark . ,(if ignore + mark (copy-marker mark)))))))))))) (tail (when (memq type '(vc hc)) (let (list) (setq window (window-child window)) (while window - (setq list (cons (window--state-get-1 window markers) list)) + (setq list (cons (window--state-get-1 window ignore) list)) (setq window (window-right window))) (nreverse list))))) (append head tail))) -(defun window-state-get (&optional window markers) +(defun window-state-get (&optional window ignore) "Return state of WINDOW as a Lisp object. WINDOW can be any window and defaults to the root window of the selected frame. -Optional argument MARKERS non-nil means use markers for sampling -positions like `window-point' or `window-start'. MARKERS should -be non-nil only if the value is used for putting the state back -in the same session (note that markers slow down processing). +Optional argument IGNORE non-nil means do not use markers for +sampling positions like `window-point' or `window-start' and do +not record ignored window parameters as specified by +`window-state-ignored-parameters'. IGNORE should be non-nil when +the return value shall be written to a file and read back in +another session. The return value can be used as argument for `window-state-put' to put the state recorded here into an arbitrary window. The @@ -3665,7 +3673,7 @@ ;; These are probably not needed. ,@(when (window-size-fixed-p window) `((fixed-height . t))) ,@(when (window-size-fixed-p window t) `((fixed-width . t)))) - (window--state-get-1 window markers))) + (window--state-get-1 window ignore))) (defvar window-state-put-list nil "Helper variable for `window-state-put'.") @@ -3744,10 +3752,15 @@ (state (cdr (assq 'buffer item)))) (when combination-limit (set-window-combination-limit window combination-limit)) - ;; Process parameters. + ;; nil out values of parameters in `window-persistent-parameters'. + (dolist (parameter (window-parameters window)) + (when (memq (car parameter) window-persistent-parameters) + (set-window-parameter window (car parameter) nil))) + ;; Assign persistent window parameters. (when parameters (dolist (parameter parameters) - (set-window-parameter window (car parameter) (cdr parameter)))) + (when (memq (car parameter) window-persistent-parameters) + (set-window-parameter window (car parameter) (cdr parameter))))) ;; Process buffer related state. (when state ;; We don't want to raise an error here so we create a buffer if === modified file 'src/window.c' --- src/window.c 2011-12-13 13:58:20 +0000 +++ src/window.c 2011-12-29 11:21:42 +0000 @@ -5349,6 +5349,7 @@ (Lisp_Object configuration) { register struct save_window_data *data; + register Lisp_Object tem, car; struct Lisp_Vector *saved_windows; Lisp_Object new_current_buffer; Lisp_Object frame; @@ -5543,7 +5544,26 @@ w->vertical_scroll_bar_type = p->vertical_scroll_bar_type; w->dedicated = p->dedicated; w->combination_limit = p->combination_limit; - w->window_parameters = p->window_parameters; + /* nil out values of persistent window parameters. */ + if (!NILP (w->window_parameters)) + for (tem = w->window_parameters; CONSP (tem); tem = XCDR (tem)) + { + car = XCAR (tem); + if (CONSP (car) + && !NILP (Fmemq (XCAR (car), Vwindow_persistent_parameters))) + Fsetcdr (car, Qnil); + } + + /* Restore persistent window parameters. */ + if (!NILP (p->window_parameters)) + for (tem = p->window_parameters; CONSP (tem); tem = XCDR (tem)) + { + car = XCAR (tem); + if (CONSP (car) + && !NILP (Fmemq (XCAR (car), Vwindow_persistent_parameters))) + Fset_window_parameter (window, XCAR (car), XCDR (car)); + } + XSETFASTINT (w->last_modified, 0); XSETFASTINT (w->last_overlay_modified, 0); @@ -5810,7 +5830,7 @@ { register struct saved_window *p; register struct window *w; - register Lisp_Object tem; + register Lisp_Object tem, car; for (;!NILP (window); window = w->next) { @@ -5838,7 +5858,11 @@ p->vertical_scroll_bar_type = w->vertical_scroll_bar_type; p->dedicated = w->dedicated; p->combination_limit = w->combination_limit; - p->window_parameters = w->window_parameters; + /* Store copies of all window parameters. When + Fset_window_configuration later considers a parameter as + persistent it will take it from the copy stored here. */ + p->window_parameters = Fcopy_alist (w->window_parameters); + if (!NILP (w->buffer)) { /* Save w's value of point in the window configuration. @@ -6542,6 +6566,15 @@ function `set-window-combination-limit'. */); Vwindow_combination_limit = Qnil; + DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters, + doc: /* List of persistent window parameters. + +The parameters in this list are restored to their previous values by the +functions `set-window-configuration' and `window-state-put'. Any +parameterts not listed here are left alone by `set-window-configuration' +respectively not installed by `window-state-put'. */); + Vwindow_persistent_parameters = Qnil; + defsubr (&Sselected_window); defsubr (&Sminibuffer_window); defsubr (&Swindow_minibuffer_p); --------------050300020408020508060900--