/* Window creation, deletion and examination for GNU Emacs.
Does not include redisplay.
- Copyright (C) 1985-1987, 1993-1998, 2000-2014 Free Software
+ Copyright (C) 1985-1987, 1993-1998, 2000-2015 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
+static Lisp_Object Qwindow_sanitize_window_sizes;
static Lisp_Object Qwindow_pixel_to_total;
static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
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
{
w->combination_limit = val;
}
+
static void
wset_dedicated (struct window *w, Lisp_Object val)
{
w->dedicated = val;
}
+
static void
wset_display_table (struct window *w, Lisp_Object val)
{
w->display_table = val;
}
+
static void
wset_new_normal (struct window *w, Lisp_Object val)
{
w->new_normal = val;
}
+
static void
wset_new_total (struct window *w, Lisp_Object val)
{
w->new_total = val;
}
+
static void
wset_normal_cols (struct window *w, Lisp_Object val)
{
w->normal_cols = val;
}
+
static void
wset_normal_lines (struct window *w, Lisp_Object val)
{
w->normal_lines = val;
}
+
static void
wset_parent (struct window *w, Lisp_Object val)
{
w->parent = val;
}
+
static void
wset_pointm (struct window *w, Lisp_Object val)
{
w->pointm = val;
}
+
+static void
+wset_old_pointm (struct window *w, Lisp_Object val)
+{
+ w->old_pointm = val;
+}
+
static void
wset_start (struct window *w, Lisp_Object val)
{
w->start = val;
}
+
static void
wset_temslot (struct window *w, Lisp_Object val)
{
w->temslot = val;
}
+
static void
wset_vertical_scroll_bar_type (struct window *w, Lisp_Object val)
{
w->vertical_scroll_bar_type = val;
}
+
static void
wset_window_parameters (struct window *w, Lisp_Object val)
{
w->window_parameters = val;
}
+
static void
wset_combination (struct window *w, bool horflag, Lisp_Object val)
{
DEFUN ("window-valid-p", Fwindow_valid_p, Swindow_valid_p, 1, 1, 0,
doc: /* Return t if OBJECT is a valid window and nil otherwise.
A valid window is either a window that displays a buffer or an internal
-window. Deleted windows are not live. */)
+window. Windows that have been deleted are not valid. */)
(Lisp_Object object)
{
return WINDOW_VALID_P (object) ? Qt : Qnil;
DEFUN ("window-new-total", Fwindow_new_total, Swindow_new_total, 0, 1, 0,
doc: /* Return the new total size of window WINDOW.
-WINDOW must be a valid window and defaults to the selected one. */)
+WINDOW must be a valid window and defaults to the selected one.
+
+The new total size of WINDOW is the value set by the last call of
+`set-window-new-total' for WINDOW. If it is valid, it will be shortly
+installed as WINDOW's total height (see `window-total-height') or total
+width (see `window-total-width'). */)
(Lisp_Object window)
{
return decode_valid_window (window)->new_total;
DEFUN ("window-normal-size", Fwindow_normal_size, Swindow_normal_size, 0, 2, 0,
doc: /* Return the normal height of window WINDOW.
WINDOW must be a valid window and defaults to the selected one.
-If HORIZONTAL is non-nil, return the normal width of WINDOW. */)
+If HORIZONTAL is non-nil, return the normal width of WINDOW.
+
+The normal height of a frame's root window or a window that is
+horizontally combined (a window that has a left or right sibling) is
+1.0. The normal height of a window that is vertically combined (has a
+sibling above or below) is the fraction of the window's height with
+respect to its parent. The sum of the normal heights of all windows in a
+vertical combination equals 1.0.
+
+Similarly, the normal width of a frame's root window or a window that is
+vertically combined equals 1.0. The normal width of a window that is
+horizontally combined is the fraction of the window's width with respect
+to its parent. The sum of the normal widths of all windows in a
+horizontal combination equals 1.0.
+
+The normal sizes of windows are used to restore the proportional sizes
+of windows after they have been shrunk to their minimum sizes; for
+example when a frame is temporarily made very small and afterwards gets
+re-enlarged to its previous size. */)
(Lisp_Object window, Lisp_Object horizontal)
{
struct window *w = decode_valid_window (window);
DEFUN ("window-new-normal", Fwindow_new_normal, Swindow_new_normal, 0, 1, 0,
doc: /* Return new normal size of window WINDOW.
-WINDOW must be a valid window and defaults to the selected one. */)
+WINDOW must be a valid window and defaults to the selected one.
+
+The new normal size of WINDOW is the value set by the last call of
+`set-window-new-normal' for WINDOW. If valid, it will be shortly
+installed as WINDOW's normal size (see `window-normal-size'). */)
(Lisp_Object window)
{
return decode_valid_window (window)->new_normal;
DEFUN ("window-new-pixel", Fwindow_new_pixel, Swindow_new_pixel, 0, 1, 0,
doc: /* Return new pixel size of window WINDOW.
-WINDOW must be a valid window and defaults to the selected one. */)
+WINDOW must be a valid window and defaults to the selected one.
+
+The new pixel size of WINDOW is the value set by the last call of
+`set-window-new-pixel' for WINDOW. If it is valid, it will be shortly
+installed as WINDOW's pixel height (see `window-pixel-height') or pixel
+width (see `window-pixel-width'). */)
(Lisp_Object window)
{
return decode_valid_window (window)->new_pixel;
{
int height = (w->pixel_height
- WINDOW_HEADER_LINE_HEIGHT (w)
+ - (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
+ ? WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
+ : 0)
- WINDOW_MODE_LINE_HEIGHT (w)
- WINDOW_BOTTOM_DIVIDER_WIDTH (w));
return (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (decode_live_window (window))));
}
+DEFUN ("window-scroll-bar-height", Fwindow_scroll_bar_height,
+ Swindow_scroll_bar_height, 0, 1, 0,
+ doc: /* Return the height in pixels of WINDOW's horizontal scrollbar.
+WINDOW must be a live window and defaults to the selected one. */)
+ (Lisp_Object window)
+{
+ return (make_number (WINDOW_SCROLL_BAR_AREA_HEIGHT (decode_live_window (window))));
+}
+
DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
doc: /* Return the number of columns by which WINDOW is scrolled from left margin.
WINDOW must be a live window and defaults to the selected one. */)
XBUFFER (w->contents)->prevent_redisplay_optimizations_p = 1;
w->hscroll = new_hscroll;
+ w->suspend_auto_hscroll = 1;
+
return make_number (new_hscroll);
}
return list4i ((WINDOW_BOX_LEFT_EDGE_COL (w)
+ WINDOW_LEFT_MARGIN_COLS (w)
- + WINDOW_LEFT_FRINGE_COLS (w)),
+ + ((WINDOW_LEFT_FRINGE_WIDTH (w)
+ + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
+ / WINDOW_FRAME_COLUMN_WIDTH (w))),
(WINDOW_TOP_EDGE_LINE (w)
+ WINDOW_HEADER_LINE_LINES (w)),
(WINDOW_BOX_RIGHT_EDGE_COL (w)
- WINDOW_RIGHT_MARGIN_COLS (w)
- - WINDOW_RIGHT_FRINGE_COLS (w)),
+ - ((WINDOW_RIGHT_FRINGE_WIDTH (w)
+ + WINDOW_FRAME_COLUMN_WIDTH (w) - 1)
+ / WINDOW_FRAME_COLUMN_WIDTH (w))),
(WINDOW_BOTTOM_EDGE_LINE (w)
- WINDOW_MODE_LINE_LINES (w)));
}
&& x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
&& x <= right_x)
return ON_RIGHT_DIVIDER;
+ /* On the horizontal scroll bar? (Including the empty space at its
+ right!) */
+ else if ((WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w)
+ && y >= (bottom_y
+ - WINDOW_SCROLL_BAR_AREA_HEIGHT (w)
+ - CURRENT_MODE_LINE_HEIGHT (w)
+ - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+ && y <= (bottom_y
+ - CURRENT_MODE_LINE_HEIGHT (w)
+ - WINDOW_BOTTOM_DIVIDER_WIDTH (w))))
+ return ON_HORIZONTAL_SCROLL_BAR;
/* On the mode or header line? */
else if ((WINDOW_WANTS_MODELINE_P (w)
&& y >= (bottom_y
/* Outside any interesting column? */
if (x < left_x || x > right_x)
- return ON_SCROLL_BAR;
+ return ON_VERTICAL_SCROLL_BAR;
lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
case ON_RIGHT_MARGIN:
return Qright_margin;
- case ON_SCROLL_BAR:
+ case ON_VERTICAL_SCROLL_BAR:
/* Historically we are supposed to return nil in this case. */
return Qnil;
+ case ON_HORIZONTAL_SCROLL_BAR:
+ return Qnil;
+
case ON_RIGHT_DIVIDER:
return Qright_divider;
return Fmarker_position (w->pointm);
}
+DEFUN ("window-old-point", Fwindow_old_point, Swindow_old_point, 0, 1, 0,
+ doc: /* Return old value of point in WINDOW.
+WINDOW must be a live window and defaults to the selected one. */)
+ (Lisp_Object window)
+{
+ return Fmarker_position (decode_live_window (window)->old_pointm);
+}
+
DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
doc: /* Return position at which display currently starts in WINDOW.
WINDOW must be a live window and defaults to the selected one.
return Qnil;
}
+
static Lisp_Object
resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore, Lisp_Object pixelwise)
{
}
+Lisp_Object
+sanitize_window_sizes (Lisp_Object frame, Lisp_Object horizontal)
+{
+ return call2 (Qwindow_sanitize_window_sizes, frame, horizontal);
+}
+
+
static Lisp_Object
window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal)
{
- return call2(Qwindow_pixel_to_total, frame, horizontal);
+ return call2 (Qwindow_pixel_to_total, frame, horizontal);
}
window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame);
}
}
-
-/* If *HEIGHT or *WIDTH are too small a size for FRAME, set them to the
- minimum allowable size. PIXELWISE means interpret these as pixel
- sizes. */
-
-void
-check_frame_size (struct frame *frame, int *width, int *height, bool pixelwise)
-{
- /* For height, we have to see:
- how many windows the frame has at minimum (one or two),
- and whether it has a menu bar or other special stuff at the top. */
- if (pixelwise)
- {
- int min_height = MIN_SAFE_WINDOW_HEIGHT * FRAME_LINE_HEIGHT (frame);
- int min_width = MIN_SAFE_WINDOW_WIDTH * FRAME_COLUMN_WIDTH (frame);
-
- if (!FRAME_MINIBUF_ONLY_P (frame) && FRAME_HAS_MINIBUF_P (frame))
- min_height = 2 * min_height;
-
- min_height += FRAME_TOP_MARGIN_HEIGHT (frame);
- min_height += FRAME_INTERNAL_BORDER_WIDTH (frame);
-
- if (*height < min_height)
- *height = min_height;
- if (*width < min_width)
- *width = min_width;
- }
- else
- {
- int min_height
- = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
- ? MIN_SAFE_WINDOW_HEIGHT
- : 2 * MIN_SAFE_WINDOW_HEIGHT);
-
- if (FRAME_TOP_MARGIN (frame) > 0)
- min_height += FRAME_TOP_MARGIN (frame);
-
- if (*height < min_height)
- *height = min_height;
- if (*width < MIN_SAFE_WINDOW_WIDTH)
- *width = MIN_SAFE_WINDOW_WIDTH;
- }
-}
-
-/* Adjust the margins of window W if text area is too small.
- Return 1 if window width is ok after adjustment; 0 if window
- is still too narrow. */
-
-static int
-adjust_window_margins (struct window *w)
-{
- int box_width = (WINDOW_PIXEL_WIDTH (w)
- - WINDOW_FRINGES_WIDTH (w)
- - WINDOW_SCROLL_BAR_AREA_WIDTH (w));
- int margin_width = WINDOW_MARGINS_WIDTH (w);
-
- if (box_width - margin_width >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
- return 1;
-
- if (margin_width < 0 || box_width < MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
- return 0;
- else
- /* Window's text area is too narrow, but reducing the window
- margins will fix that. */
- {
- int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
-
- margin_width = box_width - MIN_SAFE_WINDOW_PIXEL_WIDTH (w);
-
- if (WINDOW_RIGHT_MARGIN_WIDTH (w) > 0)
- {
- if (WINDOW_LEFT_MARGIN_WIDTH (w) > 0)
- w->left_margin_cols = w->right_margin_cols =
- margin_width / (2 * unit);
- else
- w->right_margin_cols = margin_width / unit;
- }
- else
- w->left_margin_cols = margin_width / unit;
-
- return 1;
- }
-}
\f
/* The following three routines are needed for running a window's
configuration change hook. */
= Fdefault_value (Qwindow_configuration_change_hook);
XSETFRAME (frame, f);
- if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code))
+ if (NILP (Vrun_hooks)
+ || !(f->can_x_set_window_size)
+ || !(f->can_run_window_configuration_change_hook))
return;
/* Use the right buffer. Matters when running the local hooks. */
w->last_cursor_vpos = 0;
if (!(keep_margins_p && samebuf))
- { /* If we're not actually changing the buffer, don't reset hscroll and
- vscroll. This case happens for example when called from
+ { /* If we're not actually changing the buffer, don't reset hscroll
+ and vscroll. This case happens for example when called from
change_frame_size_1, where we use a dummy call to
- Fset_window_buffer on the frame's selected window (and no other)
- just in order to run window-configuration-change-hook.
- Resetting hscroll and vscroll here is problematic for things like
- image-mode and doc-view-mode since it resets the image's position
- whenever we resize the frame. */
- w->hscroll = w->min_hscroll = 0;
+ Fset_window_buffer on the frame's selected window (and no
+ other) just in order to run window-configuration-change-hook
+ (no longer true since change_frame_size_1 directly calls
+ run_window_configuration_change_hook). Resetting hscroll and
+ vscroll here is problematic for things like image-mode and
+ doc-view-mode since it resets the image's position whenever we
+ resize the frame. */
+ w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
+ w->suspend_auto_hscroll = 0;
w->vscroll = 0;
set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
+ set_marker_both (w->old_pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
set_marker_restricted (w->start,
make_number (b->last_window_start),
buffer);
Fset_buffer (buffer);
XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
+ XMARKER (w->old_pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
if (!keep_margins_p)
{
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), Qnil);
+ BVAR (b, vertical_scroll_bar_type),
+ BVAR (b, scroll_bar_height),
+ BVAR (b, horizontal_scroll_bar_type));
set_window_margins (w, BVAR (b, left_margin_cols),
BVAR (b, right_margin_cols));
apply_window_adjustment (w);
Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
Vminibuf_scroll_window = window;
w = XWINDOW (window);
- w->hscroll = 0;
- w->min_hscroll = 0;
+ w->hscroll = w->min_hscroll = w->hscroll_whole = 0;
+ w->suspend_auto_hscroll = 0;
set_marker_restricted_both (w->start, buf, BEG, BEG);
set_marker_restricted_both (w->pointm, buf, BEG, BEG);
+ set_marker_restricted_both (w->old_pointm, buf, BEG, BEG);
/* Run temp-buffer-show-hook, with the chosen window selected
and its buffer current. */
/* ...but now P becomes an internal window. */
wset_start (p, Qnil);
wset_pointm (p, Qnil);
+ wset_old_pointm (p, Qnil);
wset_buffer (p, Qnil);
wset_combination (p, horflag, window);
wset_combination_limit (p, Qnil);
wset_new_pixel (w, make_number (0));
wset_start (w, Fmake_marker ());
wset_pointm (w, Fmake_marker ());
+ wset_old_pointm (w, Fmake_marker ());
wset_vertical_scroll_bar_type (w, Qt);
+ wset_horizontal_scroll_bar_type (w, Qt);
/* These Lisp fields are marked specially so they're not set to nil by
allocate_window. */
wset_prev_buffers (w, Qnil);
#endif
w->sequence_number = ++sequence_number;
w->scroll_bar_width = -1;
+ w->scroll_bar_height = -1;
w->column_number_displayed = -1;
-
/* Reset window_list. */
Vwindow_list = Qnil;
/* Return window. */
Optional argument ADD non-nil means add SIZE to the new pixel size of
WINDOW and return the sum.
+The new pixel size of WINDOW, if valid, will be shortly installed as
+WINDOW's pixel height (see `window-pixel-height') or pixel width (see
+`window-pixel-width').
+
Note: This function does not operate on any child windows of WINDOW. */)
(Lisp_Object window, Lisp_Object size, Lisp_Object add)
{
Optional argument ADD non-nil means add SIZE to the new total size of
WINDOW and return the sum.
+The new total size of WINDOW, if valid, will be shortly installed as
+WINDOW's total height (see `window-total-height') or total width (see
+`window-total-width').
+
Note: This function does not operate on any child windows of WINDOW. */)
(Lisp_Object window, Lisp_Object size, Lisp_Object add)
{
WINDOW must be a valid window and defaults to the selected one.
Return SIZE.
+The new normal size of WINDOW, if valid, will be shortly installed as
+WINDOW's normal size (see `window-normal-size').
+
Note: This function does not operate on any child windows of WINDOW. */)
(Lisp_Object window, Lisp_Object size)
{
}
-/* Set w->pixel_height (w->pixel_height if HORIZONTAL is non-zero) to
+/* Set w->pixel_height (w->pixel_width if HORFLAG is non-zero) to
w->new_pixel for window W and recursively all child windows of W.
Also calculate and assign the new vertical (horizontal) pixel start
positions of each of these windows.
}
}
else
- {
- adjust_window_margins (w);
- /* Bug#15957. */
- w->window_end_valid = 0;
- }
+ /* Bug#15957. */
+ w->window_end_valid = 0;
}
-/* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
+/* Set w->total_lines (w->total_cols if HORFLAG is non-zero) to
w->new_total for window W and recursively all child windows of W.
Also calculate and assign the new vertical (horizontal) start
positions of each of these windows. */
Optional argument HORIZONTAL omitted or nil means apply requested
height values. HORIZONTAL non-nil means apply requested width values.
-This function checks whether the requested values sum up to a valid
-window layout, recursively assigns the new sizes of all child windows
-and calculates and assigns the new start positions of these windows.
+The requested size values are those set by `set-window-new-pixel' and
+`set-window-new-normal'. This function checks whether the requested
+values sum up to a valid window layout, recursively assigns the new
+sizes of all child windows and calculates and assigns the new start
+positions of these windows.
+
+Return t if the requested values have been applied correctly, nil
+otherwise.
Note: This function does not check any of `window-fixed-size-p',
`window-min-height' or `window-min-width'. All these checks have to
/* Resize frame F's windows when number of lines of F is set to SIZE.
HORFLAG 1 means resize windows when number of columns of F is set to
- SIZE. PIXELWISE 1 means to interpret SIZE as pixels.
-
- This function can delete all windows but the selected one in order to
- satisfy the request. The result will be meaningful if and only if
- F's windows have meaningful sizes when you call this. */
+ SIZE. PIXELWISE 1 means to interpret SIZE as pixels. */
void
resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
{
/* 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;
+ int old_pixel_top = r->pixel_top;
/* 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);
new_pixel_size = max (horflag
? size
: (size
- - FRAME_TOP_MARGIN_HEIGHT (f)
- ((FRAME_HAS_MINIBUF_P (f)
&& !FRAME_MINIBUF_ONLY_P (f))
? FRAME_LINE_HEIGHT (f) : 0)),
new_size = max (horflag
? size
: (size
- - FRAME_TOP_MARGIN (f)
- ((FRAME_HAS_MINIBUF_P (f)
&& !FRAME_MINIBUF_ONLY_P (f))
? 1 : 0)),
r->top_line = FRAME_TOP_MARGIN (f);
r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
- if (new_pixel_size == old_pixel_size)
+ if (new_pixel_size == old_pixel_size
+ && r->pixel_top == old_pixel_top)
;
else if (WINDOW_LEAF_P (r))
/* For a leaf root window just set the size. */
{
window_resize_apply (r, horflag);
window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
+#if 0 /* Let's try without safe sizes and/or killing other windows. */
}
else
{
window_resize_apply (r, horflag);
window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
}
-#if 0 /* Let's try without killing other windows. */
else
{
/* We lost. Delete all windows but the frame's
n->right_fringe_width = r->right_fringe_width;
n->fringes_outside_margins = r->fringes_outside_margins;
n->scroll_bar_width = r->scroll_bar_width;
+ n->scroll_bar_height = r->scroll_bar_height;
wset_vertical_scroll_bar_type (n, r->vertical_scroll_bar_type);
+ wset_horizontal_scroll_bar_type (n, r->horizontal_scroll_bar_type);
/* Directly assign orthogonal coordinates and sizes. */
if (horflag)
{
unshow_buffer (w);
unchain_marker (XMARKER (w->pointm));
+ unchain_marker (XMARKER (w->old_pointm));
unchain_marker (XMARKER (w->start));
wset_buffer (w, Qnil);
}
block_input ();
window_resize_apply (r, 0);
- w->total_lines = XFASTINT (w->new_total);
- w->top_line = r->top_line + r->total_lines;
w->pixel_height = XFASTINT (w->new_pixel);
+ w->total_lines = w->pixel_height / FRAME_LINE_HEIGHT (f);
w->pixel_top = r->pixel_top + r->pixel_height;
+ w->top_line = r->top_line + r->total_lines;
fset_redisplay (f);
FRAME_WINDOW_SIZES_CHANGED (f) = 1;
return ht;
}
+
\f
/************************************************************************
Window Scrolling
static void
window_scroll (Lisp_Object window, EMACS_INT n, bool whole, int noerror)
{
+ ptrdiff_t count = SPECPDL_INDEX ();
+
immediate_quit = 1;
n = clip_to_bounds (INT_MIN, n, INT_MAX);
wset_redisplay (XWINDOW (window));
+ if (whole && Vfast_but_imprecise_scrolling)
+ specbind (Qfontification_functions, Qnil);
+
/* If we must, use the pixel-based version which is much slower than
the line-based one but can handle varying line heights. */
if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
else
window_scroll_line_based (window, n, whole, noerror);
+ unbind_to (count, Qnil);
+
/* Bug#15957. */
XWINDOW (window)->window_end_valid = 0;
immediate_quit = 0;
void *itdata = NULL;
int window_total_lines;
int frame_line_height = default_line_pixel_height (w);
+ bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
+ Fwindow_old_point (window)));
SET_TEXT_POS_FROM_MARKER (start, w->start);
/* Scrolling a minibuffer window via scroll bar when the echo area
/* The function move_iterator_vertically may move over more than
the specified y-distance. If it->w is small, e.g. a
mini-buffer window, we may end up in front of the window's
- display area. This is the case when Start displaying at the
- start of the line containing PT in this case. */
+ display area. Start displaying at the start of the line
+ containing PT in this case. */
if (it.current_y <= 0)
{
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
{
int px;
int dy = frame_line_height;
+ /* In the below we divide the window box height by the
+ frame's line height to make the result predictable when
+ the window box is not an integral multiple of the line
+ height. This is important to ensure we get back to the
+ same position when scrolling up, then down. */
if (whole)
- dy = max ((window_box_height (w)
- - next_screen_context_lines * dy),
+ dy = max ((window_box_height (w) / dy
+ - next_screen_context_lines) * dy,
dy);
dy *= n;
{
ptrdiff_t start_pos = IT_CHARPOS (it);
int dy = frame_line_height;
- dy = max ((window_box_height (w)
- - next_screen_context_lines * dy),
+ /* In the below we divide the window box height by the frame's
+ line height to make the result predictable when the window
+ box is not an integral multiple of the line height. This is
+ important to ensure we get back to the same position when
+ scrolling up, then down. */
+ dy = max ((window_box_height (w) / dy - next_screen_context_lines) * dy,
dy) * n;
/* Note that move_it_vertically always moves the iterator to the
charpos = IT_CHARPOS (it);
bytepos = IT_BYTEPOS (it);
+ /* If PT is in the screen line at the last fully visible line,
+ move_it_to will stop at X = 0 in that line, because the
+ required Y coordinate is reached there. See if we can get to
+ PT without descending lower in Y, and if we can, it means we
+ reached PT before the scroll margin. */
+ if (charpos != PT)
+ {
+ struct it it2;
+ void *it_data;
+
+ it2 = it;
+ it_data = bidi_shelve_cache ();
+ move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
+ if (IT_CHARPOS (it) == PT && it.current_y == it2.current_y)
+ {
+ charpos = IT_CHARPOS (it);
+ bytepos = IT_BYTEPOS (it);
+ bidi_unshelve_cache (it_data, 1);
+ }
+ else
+ {
+ it = it2;
+ bidi_unshelve_cache (it_data, 0);
+ }
+ }
+
/* See if point is on a partially visible line at the end. */
if (it.what == IT_EOB)
partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
}
}
bidi_unshelve_cache (itdata, 0);
+
+ if (adjust_old_pointm)
+ Fset_marker (w->old_pointm,
+ ((w == XWINDOW (selected_window))
+ ? make_number (BUF_PT (XBUFFER (w->contents)))
+ : Fmarker_position (w->pointm)),
+ w->contents);
}
ptrdiff_t startpos = marker_position (w->start);
ptrdiff_t startbyte = marker_byte_position (w->start);
Lisp_Object original_pos = Qnil;
+ bool adjust_old_pointm = !NILP (Fequal (Fwindow_point (window),
+ Fwindow_old_point (window)));
/* If scrolling screen-fulls, compute the number of lines to
scroll from the window's height. */
struct position posit
= *compute_motion (startpos, startbyte, 0, 0, 0,
PT, ht, 0, -1, w->hscroll, 0, w);
+
window_scroll_preserve_vpos = posit.vpos;
window_scroll_preserve_hpos = posit.hpos + w->hscroll;
}
else
xsignal0 (Qend_of_buffer);
}
+
+ if (adjust_old_pointm)
+ Fset_marker (w->old_pointm,
+ ((w == XWINDOW (selected_window))
+ ? make_number (BUF_PT (XBUFFER (w->contents)))
+ : Fmarker_position (w->pointm)),
+ w->contents);
}
Fset_buffer (w->contents);
SET_PT_BOTH (marker_position (w->pointm), marker_byte_position (w->pointm));
+ SET_PT_BOTH (marker_position (w->old_pointm), marker_byte_position (w->old_pointm));
if (NILP (arg))
window_scroll (window, 1, 1, 1);
}
set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
+ set_marker_both (w->old_pointm, Qnil, PT, PT_BYTE);
unbind_to (count, Qnil);
return Qnil;
if (!NILP (set_minimum))
w->min_hscroll = w->hscroll;
+ w->suspend_auto_hscroll = 1;
+
return result;
}
if (!NILP (set_minimum))
w->min_hscroll = w->hscroll;
+ w->suspend_auto_hscroll = 1;
+
return result;
}
if (buf != current_buffer)
error ("`recenter'ing a window that does not display current-buffer.");
-
+
/* If redisplay is suppressed due to an error, try again. */
buf->display_error_modiff = 0;
w->start_at_line_beg = (bytepos == BEGV_BYTE
|| FETCH_BYTE (bytepos - 1) == '\n');
+ wset_redisplay (w);
+
return Qnil;
}
DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
- 0, 1, 0,
+ 0, 2, 0,
doc: /* Return the width in columns of the text display area of WINDOW.
WINDOW must be a live window and defaults to the selected one.
The returned width does not include dividers, scrollbars, margins,
fringes, nor any partial-width columns at the right of the text
-area. */)
- (Lisp_Object window)
+area.
+
+Optional argument PIXELWISE non-nil, means to return the width in
+pixels. */)
+ (Lisp_Object window, Lisp_Object pixelwise)
{
struct window *w = decode_live_window (window);
- return make_number (window_box_width (w, TEXT_AREA)
- / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
+ if (NILP (pixelwise))
+ return make_number (window_box_width (w, TEXT_AREA)
+ / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
+ else
+ return make_number (window_box_width (w, TEXT_AREA));
}
DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
- 0, 1, 0,
+ 0, 2, 0,
doc: /* Return the height in lines of the text display area of WINDOW.
WINDOW must be a live window and defaults to the selected one.
The returned height does not include dividers, the mode line, any header
-line, nor any partial-height lines at the bottom of the text area. */)
- (Lisp_Object window)
+line, nor any partial-height lines at the bottom of the text area.
+
+Optional argument PIXELWISE non-nil, means to return the height in
+pixels. */)
+ (Lisp_Object window, Lisp_Object pixelwise)
{
struct window *w = decode_live_window (window);
- return make_number (window_box_height (w)
- / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
+ if (NILP (pixelwise))
+ return make_number (window_box_height (w)
+ / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
+ else
+ return make_number (window_box_height (w));
}
\f
DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
{
struct vectorlike_header header;
- Lisp_Object window, buffer, start, pointm;
+ Lisp_Object window, buffer, start, pointm, old_pointm;
Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
Lisp_Object left_col, top_line, total_cols, total_lines;
Lisp_Object normal_cols, normal_lines;
- Lisp_Object hscroll, min_hscroll;
+ Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll;
Lisp_Object parent, prev;
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 scroll_bar_height, horizontal_scroll_bar_type;
Lisp_Object combination_limit, window_parameters;
};
return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
}
-/* From Chong's unwind_create_frame_1. */
-static void
-unwind_change_frame (Lisp_Object val)
-{
- inhibit_lisp_code = val;
-}
-
DEFUN ("set-window-configuration", Fset_window_configuration,
Sset_window_configuration, 1, 1, 0,
doc: /* Set the configuration of windows and buffers as specified by CONFIGURATION.
Lisp_Object frame;
struct frame *f;
ptrdiff_t old_point = -1;
+ USE_SAFE_ALLOCA;
CHECK_WINDOW_CONFIGURATION (configuration);
int n_leaf_windows;
ptrdiff_t k;
int i, n;
- ptrdiff_t count = SPECPDL_INDEX ();
- /* If the frame has been resized since this window configuration was
- made, we change the frame to the size specified in the
- configuration, restore the configuration, and then resize it
- back. We keep track of the prevailing height in these variables. */
- int previous_frame_text_height = FRAME_TEXT_HEIGHT (f);
- int previous_frame_text_width = FRAME_TEXT_WIDTH (f);
- /* int previous_frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f); */
- /* int previous_frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f); */
- /* int previous_frame_lines = FRAME_LINES (f); */
- /* int previous_frame_cols = FRAME_COLS (f); */
- int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
- int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
/* Don't do this within the main loop below: This may call Lisp
code and is thus potentially unsafe while input is blocked. */
call1 (Qrecord_window_buffer, window);
}
- /* Don't run lisp in the following segment since the frame is in a
- completely inconsistent state. See Bug#16207. */
- record_unwind_protect (unwind_change_frame, inhibit_lisp_code);
- inhibit_lisp_code = Qt;
+ /* Disallow x_set_window_size, temporarily. */
+ f->can_x_set_window_size = false;
/* The mouse highlighting code could get screwed up
if it runs during this. */
block_input ();
- if (data->frame_text_width != previous_frame_text_width
- || data->frame_text_height != previous_frame_text_height)
- change_frame_size (f, data->frame_text_width,
- data->frame_text_height, 0, 0, 0, 1);
-
- if (data->frame_menu_bar_lines != previous_frame_menu_bar_lines)
- {
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
- make_number (0));
- else /* TTY or MSDOS */
-#endif
- set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
- make_number (0));
- }
-#ifdef HAVE_WINDOW_SYSTEM
- if (data->frame_tool_bar_lines != previous_frame_tool_bar_lines)
- x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
- make_number (0));
-#endif
-
/* "Swap out" point from the selected window's buffer
into the window itself. (Normally the pointm of the selected
window holds garbage.) We do this now, before
really like to do is to free only those matrices not reused
below. */
root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
- leaf_windows = alloca (count_windows (root_window)
- * sizeof *leaf_windows);
+ int nwindows = count_windows (root_window);
+ SAFE_NALLOCA (leaf_windows, 1, nwindows);
n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
/* Kludge Alert!
wset_normal_cols (w, p->normal_cols);
wset_normal_lines (w, p->normal_lines);
w->hscroll = XFASTINT (p->hscroll);
+ w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll);
w->min_hscroll = XFASTINT (p->min_hscroll);
+ w->hscroll_whole = XFASTINT (p->hscroll_whole);
wset_display_table (w, p->display_table);
w->left_margin_cols = XINT (p->left_margin_cols);
w->right_margin_cols = XINT (p->right_margin_cols);
w->right_fringe_width = XINT (p->right_fringe_width);
w->fringes_outside_margins = !NILP (p->fringes_outside_margins);
w->scroll_bar_width = XINT (p->scroll_bar_width);
+ w->scroll_bar_height = XINT (p->scroll_bar_height);
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);
wset_combination_limit (w, p->combination_limit);
/* Restore any window parameters that have been saved.
wset_buffer (w, p->buffer);
w->start_at_line_beg = !NILP (p->start_at_line_beg);
set_marker_restricted (w->start, p->start, w->contents);
- set_marker_restricted (w->pointm, p->pointm,
- w->contents);
-
+ set_marker_restricted (w->pointm, p->pointm, w->contents);
+ set_marker_restricted (w->old_pointm, p->old_pointm, w->contents);
/* As documented in Fcurrent_window_configuration, don't
restore the location of point in the buffer which was
current when the window configuration was recorded. */
if (!EQ (p->buffer, new_current_buffer)
&& XBUFFER (p->buffer) == current_buffer)
Fgoto_char (w->pointm);
- }
+ }
else if (BUFFERP (w->contents) && BUFFER_LIVE_P (XBUFFER (w->contents)))
/* Keep window's old buffer; make sure the markers are real. */
{
(w->pointm, w->contents,
BUF_PT (XBUFFER (w->contents)),
BUF_PT_BYTE (XBUFFER (w->contents)));
+ if (XMARKER (w->old_pointm)->buffer == 0)
+ set_marker_restricted_both
+ (w->old_pointm, w->contents,
+ BUF_PT (XBUFFER (w->contents)),
+ BUF_PT_BYTE (XBUFFER (w->contents)));
w->start_at_line_beg = 1;
}
else if (!NILP (w->start))
/* Leaf window has no live buffer, get one. */
{
/* Get the buffer via other_buffer_safely in order to
- avoid showing an unimportant buffer and, if necessary, to
- recreate *scratch* in the course (part of Juanma's bs-show
- scenario from March 2011). */
+ avoid showing an unimportant buffer and, if necessary, to
+ recreate *scratch* in the course (part of Juanma's bs-show
+ scenario from March 2011). */
wset_buffer (w, other_buffer_safely (Fcurrent_buffer ()));
/* This will set the markers to beginning of visible
range. */
set_marker_restricted_both (w->start, w->contents, 0, 0);
set_marker_restricted_both (w->pointm, w->contents, 0, 0);
+ set_marker_restricted_both (w->old_pointm, w->contents, 0, 0);
w->start_at_line_beg = 1;
if (!NILP (w->dedicated))
/* Record this window as dead. */
&& FRAME_LIVE_P (XFRAME (data->focus_frame))))
Fredirect_frame_focus (frame, data->focus_frame);
- /* Set the frame size to the value it had before this function. */
- if (previous_frame_text_width != FRAME_TEXT_WIDTH (f)
- || previous_frame_text_height != FRAME_TEXT_HEIGHT (f))
- change_frame_size (f, previous_frame_text_width,
- previous_frame_text_height, 0, 0, 0, 1);
-
- if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
- {
-#ifdef HAVE_WINDOW_SYSTEM
- if (FRAME_WINDOW_P (f))
- x_set_menu_bar_lines (f,
- make_number (previous_frame_menu_bar_lines),
- make_number (0));
- else /* TTY or MSDOS */
-#endif
- set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
- make_number (0));
- }
-#ifdef HAVE_WINDOW_SYSTEM
- if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
- x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
- make_number (0));
-#endif
-
/* Now, free glyph matrices in windows that were not reused. */
for (i = n = 0; i < n_leaf_windows; ++i)
{
++n;
}
+ /* Allow x_set_window_size again and apply frame size changes if
+ needed. */
+ f->can_x_set_window_size = true;
+ adjust_frame_size (f, -1, -1, 1, 0, Qnil);
+
adjust_frame_glyphs (f);
unblock_input ();
- unbind_to (count, Qnil);
/* Scan dead buffer windows. */
for (; CONSP (dead_windows); dead_windows = XCDR (dead_windows))
Vminibuf_scroll_window = data->minibuf_scroll_window;
minibuf_selected_window = data->minibuf_selected_window;
+ SAFE_FREE ();
return (FRAME_LIVE_P (f) ? Qt : Qnil);
}
+
void
restore_window_configuration (Lisp_Object configuration)
{
{
unshow_buffer (w);
unchain_marker (XMARKER (w->pointm));
+ unchain_marker (XMARKER (w->old_pointm));
unchain_marker (XMARKER (w->start));
/* Since combination limit makes sense for an internal windows
only, we use this slot to save the buffer for the sake of
p->normal_cols = w->normal_cols;
p->normal_lines = w->normal_lines;
XSETFASTINT (p->hscroll, w->hscroll);
+ p->suspend_auto_hscroll = w->suspend_auto_hscroll ? Qt : Qnil;
XSETFASTINT (p->min_hscroll, w->min_hscroll);
+ XSETFASTINT (p->hscroll_whole, w->hscroll_whole);
p->display_table = w->display_table;
p->left_margin_cols = make_number (w->left_margin_cols);
p->right_margin_cols = make_number (w->right_margin_cols);
p->right_fringe_width = make_number (w->right_fringe_width);
p->fringes_outside_margins = w->fringes_outside_margins ? Qt : Qnil;
p->scroll_bar_width = make_number (w->scroll_bar_width);
+ p->scroll_bar_height = make_number (w->scroll_bar_height);
p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
+ p->horizontal_scroll_bar_type = w->horizontal_scroll_bar_type;
p->dedicated = w->dedicated;
p->combination_limit = w->combination_limit;
p->window_parameters = Qnil;
BUF_PT_BYTE (XBUFFER (w->contents)));
else
p->pointm = Fcopy_marker (w->pointm, Qnil);
+ p->old_pointm = Fcopy_marker (w->old_pointm, Qnil);
XMARKER (p->pointm)->insertion_type
= !NILP (buffer_local_value /* Don't signal error if void. */
(Qwindow_point_insertion_type, w->contents));
+ XMARKER (p->old_pointm)->insertion_type
+ = !NILP (buffer_local_value /* Don't signal error if void. */
+ (Qwindow_point_insertion_type, w->contents));
p->start = Fcopy_marker (w->start, Qnil);
p->start_at_line_beg = w->start_at_line_beg ? Qt : Qnil;
else
{
p->pointm = Qnil;
+ p->old_pointm = Qnil;
p->start = Qnil;
p->start_at_line_beg = Qnil;
}
apply_window_adjustment (struct window *w)
{
eassert (w);
- adjust_window_margins (w);
clear_glyph_matrix (w->current_matrix);
w->window_end_valid = 0;
windows_or_buffers_changed = 30;
Lisp_Object right_width)
{
int left, right;
+ int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
- /* FIXME: what about margins that are too wide? */
left = (NILP (left_width) ? 0
: (CHECK_NATNUM (left_width), XINT (left_width)));
right = (NILP (right_width) ? 0
if (w->left_margin_cols != left || w->right_margin_cols != right)
{
- w->left_margin_cols = left;
- w->right_margin_cols = right;
- return w;
+ /* Don't change anything if new margins won't fit. */
+ if ((WINDOW_PIXEL_WIDTH (w)
+ - WINDOW_FRINGES_WIDTH (w)
+ - WINDOW_SCROLL_BAR_AREA_WIDTH (w)
+ - (left + right) * unit)
+ >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
+ {
+ w->left_margin_cols = left;
+ w->right_margin_cols = right;
+
+ return w;
+ }
+ else
+ return NULL;
}
- return NULL;
+ else
+ return NULL;
}
DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
|| w->right_fringe_width != right
|| w->fringes_outside_margins != outside))
{
+ if (left > 0 || right > 0)
+ {
+ /* 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->left_fringe_width = left;
w->right_fringe_width = right;
w->fringes_outside_margins = outside;
+
return w;
}
- return NULL;
+ else
+ return NULL;
}
DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
static struct window *
set_window_scroll_bars (struct window *w, Lisp_Object width,
- Lisp_Object vertical_type, Lisp_Object horizontal_type)
+ Lisp_Object vertical_type, Lisp_Object height,
+ Lisp_Object horizontal_type)
{
int iwidth = (NILP (width) ? -1 : (CHECK_NATNUM (width), XINT (width)));
+ bool changed = 0;
if (iwidth == 0)
vertical_type = Qnil;
if (w->scroll_bar_width != iwidth
|| !EQ (w->vertical_scroll_bar_type, vertical_type))
{
- w->scroll_bar_width = iwidth;
- wset_vertical_scroll_bar_type (w, vertical_type);
- return w;
+ /* Don't change anything if new scroll bar won't fit. */
+ if ((WINDOW_PIXEL_WIDTH (w)
+ - WINDOW_MARGINS_WIDTH (w)
+ - WINDOW_FRINGES_WIDTH (w)
+ - max (iwidth, 0))
+ >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
+ {
+ w->scroll_bar_width = iwidth;
+ wset_vertical_scroll_bar_type (w, vertical_type);
+ changed = 1;
+ }
}
- return NULL;
+
+#if USE_HORIZONTAL_SCROLL_BARS
+ {
+ int iheight = (NILP (height) ? -1 : (CHECK_NATNUM (height), XINT (height)));
+
+ if (MINI_WINDOW_P (w) || iheight == 0)
+ horizontal_type = Qnil;
+
+ 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 = 1;
+ }
+ }
+ }
+#else
+ wset_horizontal_scroll_bar_type (w, Qnil);
+#endif
+
+ return changed ? w : NULL;
}
DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
- Sset_window_scroll_bars, 2, 4, 0,
+ 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.
-Second parameter WIDTH specifies the pixel width for the scroll bar.
+Second parameter 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
-bar: left, right, or nil.
-If WIDTH is nil, use the frame's scroll-bar width.
-If VERTICAL-TYPE is t, use the frame's scroll-bar type.
-Fourth parameter HORIZONTAL-TYPE is currently unused.
+bar: left, right, or nil. If VERTICAL-TYPE is t, this means use the
+frame's scroll-bar type.
+
+Fourth parameter 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: nil, bottom, or t. If HORIZONTAL-TYPE is t, this
+means to use the frame's horizontal scroll-bar type.
Return t if scroll bars were actually changed and nil otherwise. */)
- (Lisp_Object window, Lisp_Object width,
- Lisp_Object vertical_type, Lisp_Object horizontal_type)
+ (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type,
+ Lisp_Object height, Lisp_Object horizontal_type)
{
struct window *w
= set_window_scroll_bars (decode_live_window (window),
- width, vertical_type, horizontal_type);
+ width, vertical_type, height, horizontal_type);
return w ? (apply_window_adjustment (w), Qt) : Qnil;
}
doc: /* Get width and type of scroll bars of window WINDOW.
WINDOW must be a live window and defaults to the selected one.
-Value is a list of the form (WIDTH COLS VERTICAL-TYPE HORIZONTAL-TYPE).
-If WIDTH is nil or TYPE is t, the window is using the frame's corresponding
+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. */)
(Lisp_Object window)
{
struct window *w = decode_live_window (window);
- return list4 (make_number (WINDOW_SCROLL_BAR_AREA_WIDTH (w)),
- make_number (WINDOW_SCROLL_BAR_COLS (w)),
- w->vertical_scroll_bar_type, Qnil);
+ return Fcons (((w->scroll_bar_width >= 0)
+ ? make_number (w->scroll_bar_width)
+ : Qnil),
+ list5 (make_number (WINDOW_SCROLL_BAR_COLS (w)),
+ w->vertical_scroll_bar_type,
+ ((w->scroll_bar_height >= 0)
+ ? make_number (w->scroll_bar_height)
+ : Qnil),
+ make_number (WINDOW_SCROLL_BAR_LINES (w)),
+ w->horizontal_scroll_bar_type));
}
-
-
\f
/***********************************************************************
Smooth scrolling
|| !EQ (sw1->right_fringe_width, sw2->right_fringe_width)
|| !EQ (sw1->fringes_outside_margins, sw2->fringes_outside_margins)
|| !EQ (sw1->scroll_bar_width, sw2->scroll_bar_width)
- || !EQ (sw1->vertical_scroll_bar_type, sw2->vertical_scroll_bar_type))
+ || !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))
return 0;
}
DEFSYM (Qdelete_window, "delete-window");
DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
+ DEFSYM (Qwindow_sanitize_window_sizes, "window--sanitize-window-sizes");
DEFSYM (Qwindow_pixel_to_total, "window--pixel-to-total");
DEFSYM (Qsafe, "safe");
DEFSYM (Qdisplay_buffer, "display-buffer");
doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows.
If the minibuffer is active, the `minibuffer-scroll-window' mode line
is displayed in the `mode-line' face. */);
- mode_line_in_non_selected_windows = 1;
+ mode_line_in_non_selected_windows = true;
DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window. */);
DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
doc: /* Non-nil means to automatically adjust `window-vscroll' to view tall lines. */);
- auto_window_vscroll_p = 1;
+ auto_window_vscroll_p = true;
DEFVAR_INT ("next-screen-context-lines", next_screen_context_lines,
doc: /* Number of lines of continuity when scrolling by screenfuls. */);
Note that when a frame's pixel size is not a multiple of the
frame's character size, at least one window may get resized
pixelwise even if this option is nil. */);
- window_resize_pixelwise = 0;
+ window_resize_pixelwise = false;
+
+ DEFVAR_BOOL ("fast-but-imprecise-scrolling",
+ Vfast_but_imprecise_scrolling,
+ doc: /* When non-nil, accelerate scrolling operations.
+This comes into play when scrolling rapidly over previously
+unfontified buffer regions. Only those portions of the buffer which
+are actually going to be displayed get fontified.
+
+Note that this optimization can cause the portion of the buffer
+displayed after a scrolling operation to be somewhat inaccurate. */);
+ Vfast_but_imprecise_scrolling = false;
defsubr (&Sselected_window);
defsubr (&Sminibuffer_window);
defsubr (&Swindow_right_divider_width);
defsubr (&Swindow_bottom_divider_width);
defsubr (&Swindow_scroll_bar_width);
+ defsubr (&Swindow_scroll_bar_height);
defsubr (&Swindow_inside_edges);
defsubr (&Swindow_inside_pixel_edges);
defsubr (&Swindow_inside_absolute_pixel_edges);
defsubr (&Scoordinates_in_window_p);
defsubr (&Swindow_at);
defsubr (&Swindow_point);
+ defsubr (&Swindow_old_point);
defsubr (&Swindow_start);
defsubr (&Swindow_end);
defsubr (&Sset_window_point);