]> git.eshelyaron.com Git - emacs.git/commitdiff
Handle persistence of windows' scroll bar and fringes settings (Bug#36193)
authorMartin Rudalics <rudalics@gmx.at>
Mon, 22 Jul 2019 07:19:18 +0000 (09:19 +0200)
committerMartin Rudalics <rudalics@gmx.at>
Mon, 22 Jul 2019 07:19:18 +0000 (09:19 +0200)
* doc/lispref/display.texi (Fringe Size/Pos): Document new
argument PERSISTENT of 'set-window-fringes'.
(Scroll Bars): Document new argument PERSISTENT of
'set-window-scroll-bars'.  Mention that HORIZONTAL-TYPE must
be 'bottom' to show a horizontal scroll bar on mini windows.
* lisp/window.el (window-min-pixel-height): For mini windows the
minimum height is one line.
(window--min-size-1): Use value returned by
'window-min-pixel-height' when dealing with mini windows.
(window--resize-mini-window): Try to handle horizontal scroll
bars and size restrictions more accurately.
(window--state-put-2): Handle persistence of scroll bar
settings.
* src/frame.c (make_frame): Allow horizontal scroll bars in
mini windows.
(adjust_frame_size): Drop PIXELWISE argument in
'resize_frame_windows' calls.
* src/window.c (set_window_buffer): Don't override WINDOW's
scroll bar and fringe settings when marked as persistent.
(resize_frame_windows): Drop fourth argument PIXELWISE - SIZE
is always specified in terms of pixels.  Try to handle height
of mini windows more accurately.
(grow_mini_window, shrink_mini_window): Use body height of
mini window when calculating expected height change.  Take
horizontal scroll bars into account.
(struct saved_window): Two new members to handle persistence
of window fringes and scroll bars.
(Fset_window_configuration, save_window_save): Handle
persistence of fringes and scroll bars.
(set_window_fringes, set_window_scroll_bars): New arguments
PERSISTENT.  Make dimension checks more accurate.
(Fset_window_fringes): New argument PERSISTENT.
(Fwindow_fringes, Fwindow_scroll_bars): Add PERSISTENT to
return values.
(Fset_window_scroll_bars): New argument PERSISTENT.  In
doc-string mention that 'bottom' must be specified to get a
horizontal scroll bar in mini windows.
(compare_window_configurations): Add checks for persistence of
fringes and scroll bars.
* src/window.h (struct window): New boolean slots
'fringes_persistent' and 'scroll_bars_persistent'.
(WINDOW_HAS_HORIZONTAL_SCROLL_BAR): Allow horizontal scroll bars
for mini windows.
(resize_frame_windows): Remove fourth argument of
'resize_frame_windows' in external declaration.
* src/xdisp.c (resize_mini_window): Use box text height to
tell whether mini window height changed.
(set_horizontal_scroll_bar): Set mini window's horizontal
scroll bar when its type is specified as 'bottom'.
* etc/NEWS: Mention new options for 'set-window-fringes' and
'set-window-scroll-bars'.

doc/lispref/display.texi
etc/NEWS
lisp/window.el
src/frame.c
src/window.c
src/window.h
src/xdisp.c

index 4b10788862e25eff155cef22222191fe7d97fdc8..3c91092906cc98c316d497defde01e0df4268b7c 100644 (file)
@@ -3959,7 +3959,7 @@ showing the buffer, unless you call @code{set-window-buffer} again in
 each affected window.  You can also use @code{set-window-fringes} to
 control the fringe display in individual windows.
 
-@defun set-window-fringes window left &optional right outside-margins
+@defun set-window-fringes window left &optional right outside-margins persistent
 This function sets the fringe widths of window @var{window}.
 If @var{window} is @code{nil}, the selected window is used.
 
@@ -3974,14 +3974,18 @@ desired width, this leaves the fringes of @var{window} unchanged.
 
 The values specified here may be later overridden by invoking
 @code{set-window-buffer} (@pxref{Buffers and Windows}) on @var{window}
-with its @var{keep-margins} argument @code{nil} or omitted.
+with its @var{keep-margins} argument @code{nil} or omitted.  However,
+if the optional fifth argument @var{persistent} is non-@code{nil} and
+the other arguments are processed successfully, the values specified
+here unconditionally survive subsequent invocations of
+@code{set-window-buffer}.
 @end defun
 
 @defun window-fringes &optional window
 This function returns information about the fringes of a window
 @var{window}.  If @var{window} is omitted or @code{nil}, the selected
 window is used.  The value has the form @code{(@var{left-width}
-@var{right-width} @var{outside-margins})}.
+@var{right-width} @var{outside-margins} @var{persistent})}.
 @end defun
 
 
@@ -4375,7 +4379,7 @@ This function returns the height of horizontal scroll bars of
 You can override the frame specific settings for individual windows by
 using the following function:
 
-@defun set-window-scroll-bars window &optional width vertical-type height horizontal-type
+@defun set-window-scroll-bars window &optional width vertical-type height horizontal-type persistent
 This function sets the width and/or height and the types of scroll bars
 for window @var{window}.  If @var{window} is @code{nil}, the selected
 window is used.
@@ -4387,18 +4391,26 @@ if so, where.  The possible values are @code{left}, @code{right},
 @code{t}, which means to use the frame's default, and @code{nil} for no
 vertical scroll bar.
 
-@var{height} specifies the height of the horizontal scroll bar in pixels
-(@code{nil} means use the height specified for the frame).
-@var{horizontal-type} specifies whether to have a horizontal scroll bar.
-The possible values are @code{bottom}, @code{t}, which means to use the
-frame's default, and @code{nil} for no horizontal scroll bar.
+@var{height} specifies the height of the horizontal scroll bar in
+pixels (@code{nil} means use the height specified for the frame).
+@var{horizontal-type} specifies whether to have a horizontal scroll
+bar.  The possible values are @code{bottom}, @code{t}, which means to
+use the frame's default, and @code{nil} for no horizontal scroll bar.
+Note that for a mini window the value @code{t} has the same meaning as
+@code{nil}, namely to not show a horizontal scroll bar.  You have to
+explicitly specify @code{bottom} in order to show a horizontal scroll
+bar in a mini window.
 
 If @var{window} is not large enough to accommodate a scroll bar of the
 desired dimension, this leaves the corresponding scroll bar unchanged.
 
 The values specified here may be later overridden by invoking
 @code{set-window-buffer} (@pxref{Buffers and Windows}) on @var{window}
-with its @var{keep-margins} argument @code{nil} or omitted.
+with its @var{keep-margins} argument @code{nil} or omitted.  However,
+if the optional fifth argument @var{persistent} is non-@code{nil} and
+the other arguments are processed successfully, the values specified
+here unconditionally survive subsequent invocations of
+@code{set-window-buffer}.
 @end defun
 
 The following four functions take as argument a live window which
@@ -4407,7 +4419,7 @@ defaults to the selected one.
 @defun window-scroll-bars &optional window
 This function returns a list of the form @code{(@var{width}
 @var{columns} @var{vertical-type} @var{height} @var{lines}
-@var{horizontal-type})}.
+@var{horizontal-type} @var{persistent})}.
 
 The value @var{width} is the value that was specified for the width of
 the vertical scroll bar (which may be @code{nil}); @var{columns} is the
@@ -4418,6 +4430,10 @@ The value @var{height} is the value that was specified for the height of
 the horizontal scroll bar (which may be @code{nil}); @var{lines} is the
 (possibly rounded) number of lines that the horizontally scroll bar
 actually occupies.
+
+The value of @var{persistent} is the value specified for @var{window}
+with the last successful invocation of @code{set-window-scroll-bars},
+@code{nil} if there never was one.
 @end defun
 
 @defun window-current-scroll-bars &optional window
@@ -4438,7 +4454,7 @@ This function returns the height in pixels of @var{window}'s horizontal
 scrollbar.
 @end defun
 
-If you don't specify these values for a window with
+If you do not specify a window's scroll bar settings via
 @code{set-window-scroll-bars}, the buffer-local variables
 @code{vertical-scroll-bar}, @code{horizontal-scroll-bar},
 @code{scroll-bar-width} and @code{scroll-bar-height} in the buffer being
index 41debac50e04a8d443d91d7a20ab502a5ab1fcd4..5378e56bca41d992656d17e3988e90cc2f254d95 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2075,6 +2075,12 @@ return the total and body sizes of any window during last redisplay.
 See the section "(elisp) Window Hooks" in the Elisp manual for a
 detailed explanation of the new behavior.
 
++++
+** Making scroll bar and fringe settings persistent for windows.
+The functions 'set-window-scroll-bars' and 'set-window-fringes' now
+have a new optional argument that makes the settings they produce
+reliably survive subsequent invocations of 'set-window-buffer'.
+
 +++
 ** New option 'resize-mini-frames'.
 This option allows to automatically resize minibuffer-only frames
index 8cb9670ae47a9738a3de65715d165ebacf4c9e97..8597f870a5b78079ed8f11584700dc88cc1ed002 100644 (file)
@@ -434,7 +434,8 @@ shorter, explicitly specify the SIZE argument of that function."
 
 (defun window-min-pixel-height (&optional window)
   "Return the minimum pixel height of window WINDOW."
-  (* (max window-min-height window-safe-min-height)
+  (* (max (if (window-minibuffer-p window) 1 window-min-height)
+          window-safe-min-height)
      (frame-char-size window)))
 
 ;; This must go to C, finally (or get removed).
@@ -1603,8 +1604,6 @@ return the minimum pixel-size of WINDOW."
          value)
       (with-current-buffer (window-buffer window)
        (cond
-        ((window-minibuffer-p window)
-         (if pixelwise (frame-char-height (window-frame window)) 1))
         ((window-size-fixed-p window horizontal ignore)
          ;; The minimum size of a fixed size window is its size.
          (window-size window horizontal pixelwise))
@@ -2739,30 +2738,32 @@ windows."
   (when (window-right window)
     (window--resize-reset-1 (window-right window) horizontal)))
 
+;; The following is the internal function used when resizing mini
+;; windows "manually", for example, when dragging a divider between
+;; root and mini window.  The routines for automatic minibuffer window
+;; resizing call `window--resize-root-window-vertically' instead.
 (defun window--resize-mini-window (window delta)
-  "Resize minibuffer window WINDOW by DELTA pixels.
+  "Change height of mini window WINDOW by DELTA pixels.
 If WINDOW cannot be resized by DELTA pixels make it as large (or
 as small) as possible, but don't signal an error."
   (when (window-minibuffer-p window)
     (let* ((frame (window-frame window))
           (root (frame-root-window frame))
           (height (window-pixel-height window))
-          (min-delta
-           (- (window-pixel-height root)
-              (window-min-size root nil nil t))))
-      ;; Sanitize DELTA.
-      (cond
-       ((<= (+ height delta) 0)
-       (setq delta (- (frame-char-height frame) height)))
-       ((> delta min-delta)
-       (setq delta min-delta)))
+           (min-height (+ (frame-char-height frame)
+                          (- (window-pixel-height window)
+                             (window-body-height window t))))
+           (max-delta (- (window-pixel-height root)
+                        (window-min-size root nil nil t))))
+      ;; Don't make mini window too small.
+      (when (< (+ height delta) min-height)
+       (setq delta (- min-height height)))
+      ;; Don't make root window too small.
+      (when (> delta max-delta)
+       (setq delta max-delta))
 
       (unless (zerop delta)
-       ;; Resize now.
        (window--resize-reset frame)
-       ;; Ideally we should be able to resize just the last child of root
-       ;; here.  See the comment in `resize-root-window-vertically' for
-       ;; why we do not do that.
        (window--resize-this-window root (- delta) nil nil t)
        (set-window-new-pixel window (+ height delta))
        ;; The following routine catches the case where we want to resize
@@ -5881,7 +5882,7 @@ value can be also stored on disk and read back in a new session."
                (let ((scroll-bars (cdr (assq 'scroll-bars state))))
                  (set-window-scroll-bars
                   window (car scroll-bars) (nth 2 scroll-bars)
-                  (nth 3 scroll-bars) (nth 5 scroll-bars)))
+                  (nth 3 scroll-bars) (nth 5 scroll-bars) (nth 6 scroll-bars)))
                (set-window-vscroll window (cdr (assq 'vscroll state)))
                ;; Adjust vertically.
                (if (or (memq window-size-fixed '(t height))
@@ -8497,7 +8498,7 @@ parameters of FRAME."
             (if parent
                 (frame-native-height parent)
               (- (nth 3 geometry) (nth 1 geometry))))
-           ;; FRAME'S parent or workarea sizes.  Used when no margins
+           ;; FRAME's parent or workarea sizes.  Used when no margins
            ;; are specified.
            (parent-or-workarea
             (if parent
index 6363a873684b47750b573072876922ea1adb4ce5..d94de417e4ded4c9197e26e6be94e1df3c81528b 100644 (file)
@@ -712,7 +712,7 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
 
   if (new_windows_width != old_windows_width)
     {
-      resize_frame_windows (f, new_windows_width, 1, 1);
+      resize_frame_windows (f, new_windows_width, true);
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
         manipulating video hardware.  */
@@ -737,7 +737,7 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
         left edges.  */
       || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f))
     {
-      resize_frame_windows (f, new_windows_height, 0, 1);
+      resize_frame_windows (f, new_windows_height, false);
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
         manipulating video hardware.  */
@@ -931,15 +931,11 @@ make_frame (bool mini_p)
   }
 
   if (mini_p)
-    {
-      set_window_buffer (mini_window,
-                        (NILP (Vminibuffer_list)
-                         ? get_minibuffer (0)
-                         : Fcar (Vminibuffer_list)),
-                        0, 0);
-      /* No horizontal scroll bars in minibuffers.  */
-      wset_horizontal_scroll_bar (mw, Qnil);
-    }
+    set_window_buffer (mini_window,
+                      (NILP (Vminibuffer_list)
+                       ? get_minibuffer (0)
+                       : Fcar (Vminibuffer_list)),
+                      0, 0);
 
   fset_root_window (f, root_window);
   fset_selected_window (f, root_window);
index 1b205367275791cd33fb13c759f0b9c501e60f01..9a0a9a115c2bc2357094b7cb51174db25fe67e37 100644 (file)
@@ -59,12 +59,13 @@ static void select_window_1 (Lisp_Object, bool);
 static void run_window_configuration_change_hook (struct frame *);
 
 static struct window *set_window_fringes (struct window *, Lisp_Object,
-                                         Lisp_Object, Lisp_Object);
+                                         Lisp_Object, Lisp_Object,
+                                         Lisp_Object);
 static struct window *set_window_margins (struct window *, Lisp_Object,
                                          Lisp_Object);
 static struct window *set_window_scroll_bars (struct window *, Lisp_Object,
                                              Lisp_Object, Lisp_Object,
-                                             Lisp_Object);
+                                             Lisp_Object, Lisp_Object);
 static void apply_window_adjustment (struct window *);
 
 /* This is the window in which the terminal's cursor should
@@ -3983,14 +3984,18 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
 
   if (!keep_margins_p)
     {
-      /* Set left and right marginal area width etc. from buffer.  */
-      set_window_fringes (w, BVAR (b, left_fringe_width),
-                         BVAR (b, right_fringe_width),
-                         BVAR (b, fringes_outside_margins));
-      set_window_scroll_bars (w, BVAR (b, scroll_bar_width),
-                             BVAR (b, vertical_scroll_bar_type),
-                             BVAR (b, scroll_bar_height),
-                             BVAR (b, horizontal_scroll_bar_type));
+      /* Set fringes and scroll bars from buffer unless they have been
+        declared as persistent.  */
+      if (!w->fringes_persistent)
+       set_window_fringes (w, BVAR (b, left_fringe_width),
+                           BVAR (b, right_fringe_width),
+                           BVAR (b, fringes_outside_margins), Qnil);
+      if (!w->scroll_bars_persistent)
+       set_window_scroll_bars (w, BVAR (b, scroll_bar_width),
+                               BVAR (b, vertical_scroll_bar_type),
+                               BVAR (b, scroll_bar_height),
+                               BVAR (b, horizontal_scroll_bar_type), Qnil);
+      /* Set left and right marginal area width from buffer.  */
       set_window_margins (w, BVAR (b, left_margin_cols),
                          BVAR (b, right_margin_cols));
       apply_window_adjustment (w);
@@ -4661,78 +4666,49 @@ values.  */)
 }
 
 
-/* Resize frame F's windows when F's width or height is set to SIZE.
-   If HORFLAG is zero, F's width was set to SIZE, otherwise its height
-   was set.  SIZE is interpreted in F's canonical character units
-   (a.k.a. "columns" or "lines"), unless PIXELWISE is non-zero, which
-   means to interpret SIZE in pixel units.  */
+/**
+Resize frame F's windows when F's inner height (inner width if HORFLAG
+is true) has been set to SIZE pixels.  */
 void
-resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
+resize_frame_windows (struct frame *f, int size, bool horflag)
 {
   Lisp_Object root = f->root_window;
   struct window *r = XWINDOW (root);
-  Lisp_Object mini = f->minibuffer_window;
-  struct window *m;
-  /* old_size is the old size of the frame's root window.  */
-  int old_size = horflag ? r->total_cols : r->total_lines;
   int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
-  /* new_size is the new size of the frame's root window.  */
   int new_size, new_pixel_size;
   int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
+  Lisp_Object mini = f->minibuffer_window;
+  struct window *m = WINDOWP (mini) ? XWINDOW (mini) : NULL;
+  int mini_height = ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
+                    ? unit + m->pixel_height - window_body_height (m, true)
+                    : 0);
 
-  /* Don't let the size drop below one unit.  This is more comforting
-     when we are called from *_set_tool_bar_lines since the latter may
-     have implicitly given us a zero or negative height.  */
-  if (pixelwise)
-    {
-      /* Note: This does not include the size for internal borders
-        since these are not part of the frame's text area.  */
-      new_pixel_size = max (horflag
-                           ? size
-                           : (size
-                              - ((FRAME_HAS_MINIBUF_P (f)
-                                  && !FRAME_MINIBUF_ONLY_P (f))
-                                 ? FRAME_LINE_HEIGHT (f) : 0)),
-                           unit);
-      new_size = new_pixel_size / unit;
-    }
-  else
-    {
-      new_size = max (size - (!horflag
-                             && FRAME_HAS_MINIBUF_P (f)
-                             && !FRAME_MINIBUF_ONLY_P (f)),
-                     1);
-      new_pixel_size = new_size * unit;
-    }
+  new_pixel_size = max (horflag ? size : size - mini_height, unit);
+  new_size = new_pixel_size / unit;
 
   if (new_pixel_size == old_pixel_size
       && (horflag || r->pixel_top == FRAME_TOP_MARGIN_HEIGHT (f)))
     ;
   else if (WINDOW_LEAF_P (r))
-    /* For a leaf root window just set the size.  */
-    if (horflag)
-      {
-       bool changed = r->pixel_width != new_pixel_size;
-
-       r->total_cols = new_size;
-       r->pixel_width = new_pixel_size;
-
-       if (changed && !WINDOW_PSEUDO_P (r))
-         FRAME_WINDOW_CHANGE (f) = true;
-      }
-    else
-      {
-       bool changed = r->pixel_height != new_pixel_size;
-
-       r->top_line = FRAME_TOP_MARGIN (f);
-       r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
+    {
+      /* For a leaf root window just set the size.  */
+      if (horflag)
+       {
+         r->total_cols = new_size;
+         r->pixel_width = new_pixel_size;
+       }
+      else
+       {
+         r->top_line = FRAME_TOP_MARGIN (f);
+         r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
 
-       r->total_lines = new_size;
-       r->pixel_height = new_pixel_size;
+         r->total_lines = new_size;
+         r->pixel_height = new_pixel_size;
+       }
 
-       if (changed && !WINDOW_PSEUDO_P (r))
-         FRAME_WINDOW_CHANGE (f) = true;
-      }
+      FRAME_WINDOW_CHANGE (f)
+       = !WINDOW_PSEUDO_P (r) && new_pixel_size != old_pixel_size;
+    }
   else
     {
       Lisp_Object delta;
@@ -4743,14 +4719,10 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
          r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
        }
 
-      if (pixelwise)
-       XSETINT (delta, new_pixel_size - old_pixel_size);
-      else
-       XSETINT (delta, new_size - old_size);
+      XSETINT (delta, new_pixel_size - old_pixel_size);
 
       /* Try a "normal" resize first.  */
-      resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil,
-                         pixelwise ? Qt : Qnil);
+      resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil, Qt);
       if (window_resize_check (r, horflag)
          && new_pixel_size == XFIXNUM (r->new_pixel))
        {
@@ -4760,8 +4732,7 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
       else
        {
          /* Try with "reasonable" minimum sizes next.  */
-         resize_root_window (root, delta, horflag ? Qt : Qnil, Qt,
-                             pixelwise ? Qt : Qnil);
+         resize_root_window (root, delta, horflag ? Qt : Qnil, Qt, Qt);
          if (window_resize_check (r, horflag)
              && new_pixel_size == XFIXNUM (r->new_pixel))
            {
@@ -4781,9 +4752,8 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
        }
       else
        {
-         /* Are we sure we always want 1 line here?  */
-         m->total_lines = 1;
-         m->pixel_height = FRAME_LINE_HEIGHT (f);
+         m->total_lines = mini_height / unit;
+         m->pixel_height = mini_height;
          m->top_line = r->top_line + r->total_lines;
          m->pixel_top = r->pixel_top + r->pixel_height;
        }
@@ -5211,17 +5181,11 @@ void
 grow_mini_window (struct window *w, int delta)
 {
   struct frame *f = XFRAME (w->frame);
-  int old_height = WINDOW_PIXEL_HEIGHT (w);
-  int min_height = FRAME_LINE_HEIGHT (f);
+  int old_height = window_body_height (w, true);
 
   eassert (MINI_WINDOW_P (w));
 
-  if (old_height + delta < min_height)
-    /* Never shrink mini-window to less than its minimum
-       height.  */
-    delta = old_height > min_height ? min_height - old_height : 0;
-
-  if (delta != 0)
+  if ((delta != 0) && (old_height + delta >= FRAME_LINE_HEIGHT (f)))
     {
       Lisp_Object root = FRAME_ROOT_WINDOW (f);
       struct window *r = XWINDOW (root);
@@ -5246,7 +5210,7 @@ void
 shrink_mini_window (struct window *w)
 {
   struct frame *f = XFRAME (w->frame);
-  int delta = WINDOW_PIXEL_HEIGHT (w) - FRAME_LINE_HEIGHT (f);
+  int delta = window_body_height (w, true) - FRAME_LINE_HEIGHT (f);
 
   eassert (MINI_WINDOW_P (w));
 
@@ -5263,6 +5227,11 @@ shrink_mini_window (struct window *w)
       if (FIXNUMP (grow) && window_resize_check (r, false))
        resize_mini_window_apply (w, -XFIXNUM (grow));
     }
+  else if (delta < 0)
+    /* delta can be less than zero after adding horizontal scroll
+       bar.  */
+    grow_mini_window (w, -delta);
+
 }
 
 DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal,
@@ -6740,9 +6709,11 @@ struct saved_window
   Lisp_Object start_at_line_beg;
   Lisp_Object display_table;
   Lisp_Object left_margin_cols, right_margin_cols;
-  Lisp_Object left_fringe_width, right_fringe_width, fringes_outside_margins;
-  Lisp_Object scroll_bar_width, vertical_scroll_bar_type, dedicated;
+  Lisp_Object left_fringe_width, right_fringe_width;
+  Lisp_Object fringes_outside_margins, fringes_persistent;
+  Lisp_Object scroll_bar_width, vertical_scroll_bar_type;
   Lisp_Object scroll_bar_height, horizontal_scroll_bar_type;
+  Lisp_Object scroll_bars_persistent, dedicated;
   Lisp_Object combination_limit, window_parameters;
 };
 
@@ -6957,8 +6928,10 @@ the return value is nil.  Otherwise the value is t.  */)
          w->left_fringe_width = XFIXNUM (p->left_fringe_width);
          w->right_fringe_width = XFIXNUM (p->right_fringe_width);
          w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
+         w->fringes_persistent = !NILP (p->fringes_persistent);
          w->scroll_bar_width = XFIXNUM (p->scroll_bar_width);
          w->scroll_bar_height = XFIXNUM (p->scroll_bar_height);
+         w->scroll_bars_persistent = !NILP (p->scroll_bars_persistent);
          wset_vertical_scroll_bar_type (w, p->vertical_scroll_bar_type);
          wset_horizontal_scroll_bar_type (w, p->horizontal_scroll_bar_type);
          wset_dedicated (w, p->dedicated);
@@ -7279,8 +7252,10 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i)
       p->left_fringe_width = make_fixnum (w->left_fringe_width);
       p->right_fringe_width = make_fixnum (w->right_fringe_width);
       p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
+      p->fringes_persistent = w->fringes_persistent ? Qt : Qnil;
       p->scroll_bar_width = make_fixnum (w->scroll_bar_width);
       p->scroll_bar_height = make_fixnum (w->scroll_bar_height);
+      p->scroll_bars_persistent = w->scroll_bars_persistent ? Qt : Qnil;
       p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
       p->horizontal_scroll_bar_type = w->horizontal_scroll_bar_type;
       p->dedicated = w->dedicated;
@@ -7516,49 +7491,71 @@ as nil.  */)
  ***********************************************************************/
 
 static struct window *
-set_window_fringes (struct window *w, Lisp_Object left_width,
-                   Lisp_Object right_width, Lisp_Object outside_margins)
+set_window_fringes (struct window *w,
+                   Lisp_Object left_width, Lisp_Object right_width,
+                   Lisp_Object outside_margins, Lisp_Object persistent)
 {
-  bool outside = !NILP (outside_margins);
-  int left = extract_dimension (left_width);
-  int right = extract_dimension (right_width);
-
-  /* Do nothing on a tty or if nothing to actually change.  */
-  if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
-      && (w->left_fringe_width != left
-         || w->right_fringe_width != right
-         || w->fringes_outside_margins != outside))
+  /* Do nothing on a tty.  */
+  if (!FRAME_WINDOW_P (WINDOW_XFRAME (w)))
+    return NULL;
+  else
     {
-      if (left > 0 || right > 0)
+      struct frame *f = XFRAME (WINDOW_FRAME (w));
+      int old_left = WINDOW_LEFT_FRINGE_WIDTH (w);
+      int old_right = WINDOW_RIGHT_FRINGE_WIDTH (w);
+      int new_left = extract_dimension (left_width);
+      int new_right = extract_dimension (right_width);
+      bool outside = !NILP (outside_margins);
+      bool changed = false;
+      bool failed = false;
+
+      /* Check dimensions of new fringes.  Make changes only if they
+        fit the window's dimensions.  */
+      if ((WINDOW_PIXEL_WIDTH (w)
+          - WINDOW_MARGINS_WIDTH (w)
+          - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
+          - WINDOW_RIGHT_DIVIDER_WIDTH (w)
+          - (new_left == -1 ? FRAME_LEFT_FRINGE_WIDTH (f) : new_left)
+          - (new_right == -1 ? FRAME_RIGHT_FRINGE_WIDTH (f) : new_right))
+         >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
+       {
+         w->left_fringe_width = new_left;
+         w->right_fringe_width = new_right;
+         changed = new_left != old_left || new_right != old_right;
+       }
+      else
+       failed = true;
+
+      /* Placing fringes ouside margins.  */
+      if (outside != w->fringes_outside_margins)
        {
-         /* Don't change anything if new fringes don't fit.  */
-         if ((WINDOW_PIXEL_WIDTH (w)
-              - WINDOW_MARGINS_WIDTH (w)
-              - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
-              - max (left, 0) - max (right, 0))
-             < MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
-           return NULL;
+         w->fringes_outside_margins = outside;
+         changed = true;
        }
 
-      w->left_fringe_width = left;
-      w->right_fringe_width = right;
-      w->fringes_outside_margins = outside;
+      /* Make settings persistent unless we failed to apply some
+        changes.  */
+      if (!failed)
+       w->fringes_persistent = !NILP (persistent);
 
       /* This is needed to trigger immediate redisplay of the window
         when its fringes are changed, because fringes are redrawn
         only if update_window is called, so we must trigger that even
         if the window's glyph matrices did not change at all.  */
-      windows_or_buffers_changed = 35;
-      return w;
+      if (changed)
+       {
+         windows_or_buffers_changed = 35;
+         return w;
+       }
+      else
+       return NULL;
     }
-  else
-    return NULL;
 }
 
 DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
-       2, 4, 0,
-       doc: /* Set the fringe widths of window WINDOW.
-WINDOW must be a live window and defaults to the selected one.
+       2, 5, 0,
+       doc: /* Set fringes of specified WINDOW.
+WINDOW must specify a live window and defaults to the selected one.
 
 Second arg LEFT-WIDTH specifies the number of pixels to reserve for
 the left fringe.  Optional third arg RIGHT-WIDTH specifies the right
@@ -7570,32 +7567,40 @@ If optional fourth arg OUTSIDE-MARGINS is non-nil, draw the fringes
 outside of the display margins.  By default, fringes are drawn between
 display marginal areas and the text area.
 
+Optional fifth argument PERSISTENT non-nil means that fringe settings
+for WINDOW are persistent, i.e., remain unchanged when another buffer
+is shown in WINDOW.  PERSISTENT nil means that fringes are reset from
+buffer local values when 'set-window-buffer' is called on WINDOW with
+the argument KEEP-MARGINS nil.
+
 Leave fringes unchanged if WINDOW is not large enough to accommodate
 fringes of the desired width.  Return t if any fringe was actually
 changed and nil otherwise.  */)
-  (Lisp_Object window, Lisp_Object left_width,
-   Lisp_Object right_width, Lisp_Object outside_margins)
+  (Lisp_Object window, Lisp_Object left_width, Lisp_Object right_width,
+   Lisp_Object outside_margins, Lisp_Object persistent)
 {
   struct window *w
-    = set_window_fringes (decode_live_window (window),
-                         left_width, right_width, outside_margins);
+    = set_window_fringes (decode_live_window (window), left_width,
+                         right_width, outside_margins, persistent);
   return w ? (apply_window_adjustment (w), Qt) : Qnil;
 }
 
 
 DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
        0, 1, 0,
-       doc: /* Get width of fringes of window WINDOW.
+       doc: /* Return fringe settings for specified WINDOW.
 WINDOW must be a live window and defaults to the selected one.
 
-Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS).  */)
+Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS
+PERSISTENT), see `set-window-fringes'.  */)
   (Lisp_Object window)
 {
   struct window *w = decode_live_window (window);
 
-  return list3 (make_fixnum (WINDOW_LEFT_FRINGE_WIDTH (w)),
+  return list4 (make_fixnum (WINDOW_LEFT_FRINGE_WIDTH (w)),
                make_fixnum (WINDOW_RIGHT_FRINGE_WIDTH (w)),
-               WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil);
+               WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w) ? Qt : Qnil,
+               w->fringes_persistent ? Qt : Qnil);
 }
 
 
@@ -7607,105 +7612,127 @@ Value is a list of the form (LEFT-WIDTH RIGHT-WIDTH OUTSIDE-MARGINS).  */)
 static struct window *
 set_window_scroll_bars (struct window *w, Lisp_Object width,
                        Lisp_Object vertical_type, Lisp_Object height,
-                       Lisp_Object horizontal_type)
+                       Lisp_Object horizontal_type, Lisp_Object persistent)
 {
-  int iwidth = extract_dimension (width);
-  bool changed = false;
-
-  if (iwidth == 0)
-    vertical_type = Qnil;
-
-  if (!(NILP (vertical_type)
-       || EQ (vertical_type, Qleft)
-       || EQ (vertical_type, Qright)
-       || EQ (vertical_type, Qt)))
-    error ("Invalid type of vertical scroll bar");
-
-  if (w->scroll_bar_width != iwidth
-      || !EQ (w->vertical_scroll_bar_type, vertical_type))
+  /* Do nothing on a tty.  */
+  if (!FRAME_WINDOW_P (WINDOW_XFRAME (w)))
+    return NULL;
+  else
     {
-      /* Don't change anything if new scroll bar won't fit.  */
+      struct frame *f = XFRAME (WINDOW_FRAME (w));
+      int new_width = extract_dimension (width);
+      bool changed = false;
+      bool failed = false;
+
+      if (new_width == 0)
+       vertical_type = Qnil;
+      else if (!(NILP (vertical_type)
+                || EQ (vertical_type, Qleft)
+                || EQ (vertical_type, Qright)
+                || EQ (vertical_type, Qt)))
+       error ("Invalid type of vertical scroll bar");
+
+      /* Check dimension of new scroll bar.  Make changes only if it
+        fit the window's dimensions.  */
       if ((WINDOW_PIXEL_WIDTH (w)
           - WINDOW_MARGINS_WIDTH (w)
           - WINDOW_FRINGES_WIDTH (w)
-          - max (iwidth, 0))
+          - WINDOW_RIGHT_DIVIDER_WIDTH (w)
+          - (new_width == -1 ? FRAME_SCROLL_BAR_AREA_WIDTH (f) : new_width))
          >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
        {
-         w->scroll_bar_width = iwidth;
+         changed = (!EQ (vertical_type, w->vertical_scroll_bar_type)
+                    || new_width != WINDOW_SCROLL_BAR_AREA_WIDTH (w));
          wset_vertical_scroll_bar_type (w, vertical_type);
-         changed = true;
+         w->scroll_bar_width = new_width;
        }
-    }
+      else
+       failed = true;
 
 #if USE_HORIZONTAL_SCROLL_BARS
-  {
-    int iheight = extract_dimension (height);
+      int new_height = extract_dimension (height);
 
-    if (MINI_WINDOW_P (w) || iheight == 0)
-      horizontal_type = Qnil;
+      if ((MINI_WINDOW_P (w) && !EQ (horizontal_type, Qbottom))
+         || new_height == 0)
+       horizontal_type = Qnil;
 
-    if (!(NILP (horizontal_type)
-         || EQ (horizontal_type, Qbottom)
-         || EQ (horizontal_type, Qt)))
-      error ("Invalid type of horizontal scroll bar");
+      if (!(NILP (horizontal_type)
+           || EQ (horizontal_type, Qbottom)
+           || EQ (horizontal_type, Qt)))
+       error ("Invalid type of horizontal scroll bar");
 
-    if (w->scroll_bar_height != iheight
-       || !EQ (w->horizontal_scroll_bar_type, horizontal_type))
-      {
-       /* Don't change anything if new scroll bar won't fit.  */
-       if ((WINDOW_PIXEL_HEIGHT (w)
-            - WINDOW_HEADER_LINE_HEIGHT (w)
-            - WINDOW_MODE_LINE_HEIGHT (w)
-            - max (iheight, 0))
-           >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w))
-         {
-           w->scroll_bar_height = iheight;
-           wset_horizontal_scroll_bar_type (w, horizontal_type);
-           changed = true;
-         }
-      }
-  }
+      /* Don't change anything if new scroll bar won't fit.  */
+      if ((WINDOW_PIXEL_HEIGHT (w)
+          - WINDOW_HEADER_LINE_HEIGHT (w)
+          - WINDOW_MODE_LINE_HEIGHT (w)
+          - (new_height == -1 ? FRAME_SCROLL_BAR_AREA_HEIGHT (f) : new_height))
+         >= MIN_SAFE_WINDOW_PIXEL_HEIGHT (w))
+       {
+         changed = (changed
+                    || !EQ (horizontal_type, w->horizontal_scroll_bar_type)
+                    || new_height != WINDOW_SCROLL_BAR_AREA_HEIGHT (w));
+         wset_horizontal_scroll_bar_type (w, horizontal_type);
+         w->scroll_bar_height = new_height;
+       }
+      else
+       failed = true;
 #else
-  wset_horizontal_scroll_bar_type (w, Qnil);
+      wset_horizontal_scroll_bar_type (w, Qnil);
 #endif
 
-  /* This is needed to trigger immediate redisplay of the window when
-     scroll bars are changed, because scroll bars are redisplayed only
-     if more than a single window needs to be considered, see
-     redisplay_internal.  */
-  if (changed)
-    windows_or_buffers_changed = 31;
-  return changed ? w : NULL;
+      /* Make settings persistent unless we failed to apply some
+        changes.  */
+      if (!failed)
+       w->scroll_bars_persistent = !NILP (persistent);
+
+      /* This is needed to trigger immediate redisplay of the window when
+        scroll bars are changed, because scroll bars are redisplayed only
+        if more than a single window needs to be considered, see
+        redisplay_internal.  */
+      if (changed)
+       windows_or_buffers_changed = 31;
+
+      return changed ? w : NULL;
+    }
 }
 
 DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
-       Sset_window_scroll_bars, 1, 5, 0,
-       doc: /* Set width and type of scroll bars of window WINDOW.
-WINDOW must be a live window and defaults to the selected one.
+       Sset_window_scroll_bars, 1, 6, 0,
+       doc: /* Set width and type of scroll bars of specified WINDOW.
+WINDOW must specify a live window and defaults to the selected one.
 
-Second parameter WIDTH specifies the pixel width for the vertical scroll
+Second argument WIDTH specifies the pixel width for the vertical scroll
 bar.  If WIDTH is nil, use the scroll bar width of WINDOW's frame.
-Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
+Third argument VERTICAL-TYPE specifies the type of the vertical scroll
 bar: left, right, nil or t where nil means to not display a vertical
 scroll bar on WINDOW and t means to use WINDOW frame's vertical scroll
 bar type.
 
-Fourth parameter HEIGHT specifies the pixel height for the horizontal
+Fourth argument HEIGHT specifies the pixel height for the horizontal
 scroll bar.  If HEIGHT is nil, use the scroll bar height of WINDOW's
-frame.  Fifth parameter HORIZONTAL-TYPE specifies the type of the
-horizontal scroll bar: bottom, nil, or t where nil means to not display
-a horizontal scroll bar on WINDOW and t means to use WINDOW frame's
-horizontal scroll bar type.
+frame.  Fifth argument HORIZONTAL-TYPE specifies the type of the
+horizontal scroll bar: bottom, nil, or t where nil means to not
+display a horizontal scroll bar on WINDOW and t means to use WINDOW
+frame's horizontal scroll bar type.  If WINDOW is a mini window, t
+effectively behaves like nil.  HORIZONTAL-TYPE must equal bottom in
+order to show a scroll bar for mini windows.
+
+Optional sixth argument PERSISTENT non-nil means that scroll bar
+settings for WINDOW are persistent, i.e., remain unchanged when
+another buffer is shown in WINDOW.  PERSISTENT nil means that scroll
+bars are reset from buffer local values when 'set-window-buffer' is
+called on WINDOW with the argument KEEP-MARGINS nil.
 
 If WINDOW is not large enough to accommodate a scroll bar of the
 desired dimension, leave the corresponding scroll bar unchanged.
 Return t if scroll bars were actually changed and nil otherwise.  */)
   (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type,
-   Lisp_Object height, Lisp_Object horizontal_type)
+   Lisp_Object height, Lisp_Object horizontal_type, Lisp_Object persistent)
 {
   struct window *w
     = set_window_scroll_bars (decode_live_window (window),
-                             width, vertical_type, height, horizontal_type);
+                             width, vertical_type, height,
+                             horizontal_type, persistent);
   return w ? (apply_window_adjustment (w), Qt) : Qnil;
 }
 
@@ -7716,9 +7743,9 @@ DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
 WINDOW must be a live window and defaults to the selected one.
 
 Value is a list of the form (WIDTH COLUMNS VERTICAL-TYPE HEIGHT LINES
-HORIZONTAL-TYPE).  If WIDTH or HEIGHT is nil or VERTICAL-TYPE or
-HORIZONTAL-TYPE is t, the window is using the frame's corresponding
-value.  */)
+HORIZONTAL-TYPE PERSISTENT), see `set-window-scroll-bars'.  If WIDTH
+or HEIGHT is nil or VERTICAL-TYPE or HORIZONTAL-TYPE is t, WINDOW is
+using the frame's corresponding value.  */)
   (Lisp_Object window)
 {
   struct window *w = decode_live_window (window);
@@ -7726,13 +7753,14 @@ value.  */)
   return Fcons (((w->scroll_bar_width >= 0)
                 ? make_fixnum (w->scroll_bar_width)
                 : Qnil),
-               list5 (make_fixnum (WINDOW_SCROLL_BAR_COLS (w)),
-                      w->vertical_scroll_bar_type,
-                      ((w->scroll_bar_height >= 0)
-                       ? make_fixnum (w->scroll_bar_height)
-                       : Qnil),
-                      make_fixnum (WINDOW_SCROLL_BAR_LINES (w)),
-                      w->horizontal_scroll_bar_type));
+               Fcons (make_fixnum (WINDOW_SCROLL_BAR_COLS (w)),
+                      list5 (w->vertical_scroll_bar_type,
+                             ((w->scroll_bar_height >= 0)
+                              ? make_fixnum (w->scroll_bar_height)
+                              : Qnil),
+                             make_fixnum (WINDOW_SCROLL_BAR_LINES (w)),
+                             w->horizontal_scroll_bar_type,
+                             w->scroll_bars_persistent ? Qt : Qnil)));
 }
 \f
 /***********************************************************************
@@ -7927,10 +7955,12 @@ compare_window_configurations (Lisp_Object configuration1,
          || !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
          || !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
          || !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
+         || !EQ (sw1->fringes_persistent, sw2->fringes_persistent)
          || !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
          || !EQ (sw1->scroll_bar_height, sw2->scroll_bar_height)
          || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type)
-         || !EQ (sw1->horizontal_scroll_bar_type, sw2->horizontal_scroll_bar_type))
+         || !EQ (sw1->horizontal_scroll_bar_type, sw2->horizontal_scroll_bar_type)
+         || !EQ (sw1->scroll_bars_persistent, sw2->scroll_bars_persistent))
        return false;
     }
 
index 6b0f0e5d07cca8c734883ec951fc2bb0952d7e23..dfbc6385312f29d163c319a440455f1f09bd419f 100644 (file)
@@ -422,6 +422,14 @@ struct window
        Otherwise draw them between margin areas and text.  */
     bool_bf fringes_outside_margins : 1;
 
+    /* True if this window's fringe specifications are persistent,
+       i.e., always survive Fset_window_buffer.  */
+    bool_bf fringes_persistent : 1;
+
+    /* True if this window's croll bar specifications are persistent,
+       i.e., always survive Fset_window_buffer.  */
+    bool_bf scroll_bars_persistent : 1;
+
     /* True if window_end_pos and window_end_vpos are truly valid.
        This is false if nontrivial redisplay is preempted since in that case
        the frame image that window_end_pos did not get onto the frame.  */
@@ -860,7 +868,9 @@ wset_next_buffers (struct window *w, Lisp_Object val)
    W.  Horizontal scrollbars exist for toolkit versions only.  */
 #if USE_HORIZONTAL_SCROLL_BARS
 #define WINDOW_HAS_HORIZONTAL_SCROLL_BAR(W)                    \
-  ((WINDOW_PSEUDO_P (W) || MINI_NON_ONLY_WINDOW_P (W))         \
+  ((WINDOW_PSEUDO_P (W)                                                \
+    || (MINI_WINDOW_P (W)                                      \
+       && !EQ (W->horizontal_scroll_bar_type, Qbottom)))       \
    ? false                                                     \
    : EQ (W->horizontal_scroll_bar_type, Qt)                    \
    ? FRAME_HAS_HORIZONTAL_SCROLL_BARS (WINDOW_XFRAME (W))      \
@@ -1059,7 +1069,7 @@ extern Lisp_Object minibuf_selected_window;
 extern Lisp_Object make_window (void);
 extern Lisp_Object window_from_coordinates (struct frame *, int, int,
                                             enum window_part *, bool);
-extern void resize_frame_windows (struct frame *, int, bool, bool);
+extern void resize_frame_windows (struct frame *, int, bool);
 extern void restore_window_configuration (Lisp_Object);
 extern void delete_all_child_windows (Lisp_Object);
 extern void grow_mini_window (struct window *, int);
index 50f6443f6b26b663ea519274e2fe7a1728301ced..1bb5f5e0f2a5c0d5710112aa65df3c76e301965b 100644 (file)
@@ -11368,7 +11368,7 @@ bool
 resize_mini_window (struct window *w, bool exact_p)
 {
   struct frame *f = XFRAME (w->frame);
-  int old_height = WINDOW_PIXEL_HEIGHT (w);
+  int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
 
   eassert (MINI_WINDOW_P (w));
 
@@ -11400,7 +11400,6 @@ resize_mini_window (struct window *w, bool exact_p)
   else
     {
       struct it it;
-      int old_height = WINDOW_PIXEL_HEIGHT (w);
       int unit = FRAME_LINE_HEIGHT (f);
       int height, max_height;
       struct text_pos start;
@@ -11470,7 +11469,7 @@ resize_mini_window (struct window *w, bool exact_p)
        set_buffer_internal (old_current_buffer);
     }
 
-  return WINDOW_PIXEL_HEIGHT (w) != old_height;
+  return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
 }
 
 
@@ -16679,9 +16678,7 @@ set_horizontal_scroll_bar (struct window *w)
 {
   int start, end, whole, portion;
 
-  if (!MINI_WINDOW_P (w)
-      || (w == XWINDOW (minibuf_window)
-         && NILP (echo_area_buffer[0])))
+  if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
     {
       struct buffer *b = XBUFFER (w->contents);
       struct buffer *old_buffer = NULL;