Lisp_Object Qwindow_configuration_change_hook;
Lisp_Object Vwindow_configuration_change_hook;
-/* Nonzero means scroll commands try to put point
+/* Non-nil means scroll commands try to put point
at the same screen height as previously. */
Lisp_Object Vscroll_preserve_screen_position;
register struct window *p;
p = allocate_window ();
- XSETFASTINT (p->sequence_number, ++sequence_number);
+ ++sequence_number;
+ XSETFASTINT (p->sequence_number, sequence_number);
XSETFASTINT (p->left_col, 0);
XSETFASTINT (p->top_line, 0);
XSETFASTINT (p->total_lines, 0);
int grabbable_width = ux;
int lmargin_width, rmargin_width, text_left, text_right;
- if (*x < x0 || *x >= x1)
- return ON_NOTHING;
-
/* In what's below, we subtract 1 when computing right_x because we
want the rightmost pixel, which is given by left_pixel+width-1. */
if (w->pseudo_window_p)
return ON_VERTICAL_BORDER;
}
+ if (*x < x0 || *x >= x1)
+ return ON_NOTHING;
+
/* Convert X and Y to window relative coordinates.
Mode line starts at left edge of window. */
*x -= x0;
goto header_vertical_border_check;
}
+ if (*x < x0 || *x >= x1)
+ return ON_NOTHING;
+
/* Outside any interesting column? */
if (*x < left_x || *x > right_x)
return ON_SCROLL_BAR;
: Qnil);
else if (EQ (*all_frames, Qvisible))
;
- else if (XFASTINT (*all_frames) == 0)
+ else if (EQ (*all_frames, make_number (0)))
;
else if (FRAMEP (*all_frames))
;
rest = Fmemq (window, list);
if (!NILP (rest) && !EQ (rest, list))
{
- for (tail = list; XCDR (tail) != rest; tail = XCDR (tail))
+ for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
;
XSETCDR (tail, Qnil);
list = nconc2 (rest, list);
if (f)
frame_arg = Qlambda;
- else if (XFASTINT (frames) == 0)
+ else if (EQ (frames, make_number (0)))
frame_arg = frames;
else if (EQ (frames, Qvisible))
frame_arg = frames;
doc: /* Return the window least recently selected or used for display.
Return a full-width window if possible.
A minibuffer window is never a candidate.
+A dedicated window is never a candidate, so if all windows are dedicated,
+the value is nil.
If optional argument FRAME is `visible', search all visible frames.
If FRAME is 0, search all visible and iconified frames.
If FRAME is t, search all frames.
DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 1, 0,
doc: /* Return the largest window in area.
A minibuffer window is never a candidate.
+A dedicated window is never a candidate, so if all windows are dedicated,
+the value is nil.
If optional argument FRAME is `visible', search all visible frames.
If FRAME is 0, search all visible and iconified frames.
If FRAME is t, search all frames.
--shrinkable;
total_removed += smallest;
+ /* We don't know what the smallest is now. */
+ smallest = total;
+
/* Out of for, just remove one window at the time and
check again if we have enough space. */
break;
that are left and still can be shrunk. */
while (total_shrink > total_removed)
{
+ int nonzero_sizes = 0;
+ int nonzero_idx = -1;
+
+ for (i = 0; i < nchildren; ++i)
+ if (new_sizes[i] > 0)
+ {
+ ++nonzero_sizes;
+ nonzero_idx = i;
+ }
+
for (i = 0; i < nchildren; ++i)
if (new_sizes[i] > min_size)
{
check again if we have enough space. */
break;
}
+
+
+ /* Special case, only one window left. */
+ if (nonzero_sizes == 1)
+ break;
+ }
+
+ /* Any surplus due to rounding, we add to windows that are left. */
+ while (total_shrink < total_removed)
+ {
+ for (i = 0; i < nchildren; ++i)
+ {
+ if (new_sizes[i] != 0 && total_shrink < total_removed)
+ {
+ ++new_sizes[i];
+ --total_removed;
+ break;
+ }
+ }
}
return new_sizes;
if (EQ (window, selected_window))
b->last_selected_window = window;
+ /* Let redisplay errors through. */
+ b->display_error_modiff = 0;
+
/* Update time stamps of buffer display. */
if (INTEGERP (b->display_count))
XSETINT (b->display_count, XINT (b->display_count) + 1);
Optional third arg KEEP-MARGINS non-nil means that WINDOW's current
display margins, fringe widths, and scroll bar settings are maintained;
the default is to reset these from BUFFER's local settings or the frame
-defaults. */)
+defaults.
+
+This function runs the hook `window-scroll-functions'. */)
(window, buffer, keep_margins)
register Lisp_Object window, buffer, keep_margins;
{
w = XWINDOW (window);
w->frozen_window_start_p = 0;
- XSETFASTINT (w->use_time, ++window_select_count);
+ ++window_select_count;
+ XSETFASTINT (w->use_time, window_select_count);
if (EQ (window, selected_window))
return window;
}
DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
- doc: /* Returns non-nil if a buffer named BUFFER-NAME would be created specially.
-The value is actually t if the frame should be called with default frame
-parameters, and a list of frame parameters if they were specified.
-See `special-display-buffer-names', and `special-display-regexps'. */)
+ doc: /* Returns non-nil if a buffer named BUFFER-NAME gets a special frame.
+If the value is t, a frame would be created for that buffer
+using the default frame parameters. If the value is a list,
+it is a list of frame parameters that would be used
+to make a frame for that buffer.
+The variables `special-display-buffer-names'
+and `special-display-regexps' control this. */)
(buffer_name)
Lisp_Object buffer_name;
{
= ((struct Lisp_Vector *)o)->contents[i];
XSETWINDOW (new, p);
- XSETFASTINT (p->sequence_number, ++sequence_number);
+ ++sequence_number;
+ XSETFASTINT (p->sequence_number, sequence_number);
/* Put new into window structure in place of window */
replace_window (window, new);
results for variable height lines. */
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
it.current_y = it.last_visible_y;
- move_it_vertically (&it, - window_box_height (w) / 2);
+ move_it_vertically_backward (&it, window_box_height (w) / 2);
/* The function move_iterator_vertically may move over more than
the specified y-distance. If it->w is small, e.g. a
if (it.current_y <= 0)
{
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
- move_it_vertically (&it, 0);
+ move_it_vertically_backward (&it, 0);
it.current_y = 0;
}
start = it.current.pos;
}
- /* If scroll_preserve_screen_position is non-zero, we try to set
+ /* If scroll_preserve_screen_position is non-nil, we try to set
point in the same window line as it is now, so get that line. */
if (!NILP (Vscroll_preserve_screen_position))
{
w->force_start = Qt;
}
+ /* The rest of this function uses current_y in a nonstandard way,
+ not including the height of the header line if any. */
it.current_y = it.vpos = 0;
- /* Preserve the screen position if we must. */
+ /* Preserve the screen position if we should. */
if (preserve_y >= 0)
{
+ /* If we have a header line, take account of it. */
+ if (WINDOW_WANTS_HEADER_LINE_P (w))
+ preserve_y -= CURRENT_HEADER_LINE_HEIGHT (w);
+
move_it_to (&it, -1, -1, preserve_y, -1, MOVE_TO_Y);
SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
}
else
{
- /* Move PT out of scroll margins. */
+ /* Move PT out of scroll margins.
+ This code wants current_y to be zero at the window start position
+ even if there is a header line. */
this_scroll_margin = max (0, scroll_margin);
this_scroll_margin = min (this_scroll_margin, XFASTINT (w->total_lines) / 4);
this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
posit = *compute_motion (startpos, 0, 0, 0,
PT, ht, 0,
- window_box_text_cols (w), XINT (w->hscroll),
+ -1, XINT (w->hscroll),
0, w);
original_vpos = posit.vpos;
return Qnil;
}
\f
-DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
+DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "P\np",
doc: /* Scroll selected window display ARG columns left.
Default for ARG is window width minus 2.
Value is the total amount of leftward horizontal scrolling in
effect after the change.
-If `automatic-hscrolling' is non-nil, the argument ARG modifies
-a lower bound for automatic scrolling, i.e. automatic scrolling
+If SET_MINIMUM is non-nil, the new scroll amount becomes the
+lower bound for automatic scrolling, i.e. automatic scrolling
will not scroll a window to a column less than the value returned
-by this function. */)
- (arg)
- register Lisp_Object arg;
+by this function. This happens in an interactive call. */)
+ (arg, set_minimum)
+ register Lisp_Object arg, set_minimum;
{
Lisp_Object result;
int hscroll;
hscroll = XINT (w->hscroll) + XINT (arg);
result = Fset_window_hscroll (selected_window, make_number (hscroll));
- if (interactive_p (0))
+ if (!NILP (set_minimum))
w->min_hscroll = w->hscroll;
return result;
}
-DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
+DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "P\np",
doc: /* Scroll selected window display ARG columns right.
Default for ARG is window width minus 2.
Value is the total amount of leftward horizontal scrolling in
effect after the change.
-If `automatic-hscrolling' is non-nil, the argument ARG modifies
-a lower bound for automatic scrolling, i.e. automatic scrolling
+If SET_MINIMUM is non-nil, the new scroll amount becomes the
+lower bound for automatic scrolling, i.e. automatic scrolling
will not scroll a window to a column less than the value returned
-by this function. */)
- (arg)
- register Lisp_Object arg;
+by this function. This happens in an interactive call. */)
+ (arg, set_minimum)
+ register Lisp_Object arg, set_minimum;
{
Lisp_Object result;
int hscroll;
hscroll = XINT (w->hscroll) - XINT (arg);
result = Fset_window_hscroll (selected_window, make_number (hscroll));
- if (interactive_p (0))
+ if (!NILP (set_minimum))
w->min_hscroll = w->hscroll;
return result;
SET_TEXT_POS (pt, PT, PT_BYTE);
start_display (&it, w, pt);
- move_it_vertically (&it, - window_box_height (w) / 2);
+ move_it_vertically_backward (&it, window_box_height (w) / 2);
charpos = IT_CHARPOS (it);
bytepos = IT_BYTEPOS (it);
}
{
struct it it;
struct text_pos pt;
- int y0, y1, h, nlines;
+ int nlines = - XINT (arg);
+ int extra_line_spacing;
+ int h = window_box_height (w);
SET_TEXT_POS (pt, PT, PT_BYTE);
start_display (&it, w, pt);
- y0 = it.current_y;
+
+ /* Be sure we have the exact height of the full line containing PT. */
+ move_it_by_lines (&it, 0, 1);
/* The amount of pixels we have to move back is the window
height minus what's displayed in the line containing PT,
and the lines below. */
- nlines = - XINT (arg) - 1;
+ it.current_y = 0;
+ it.vpos = 0;
move_it_by_lines (&it, nlines, 1);
- y1 = line_bottom_y (&it);
+ if (it.vpos == nlines)
+ h -= it.current_y;
+ else
+ {
+ /* Last line has no newline */
+ h -= line_bottom_y (&it);
+ it.vpos++;
+ }
+
+ /* Don't reserve space for extra line spacing of last line. */
+ extra_line_spacing = it.max_extra_line_spacing;
/* If we can't move down NLINES lines because we hit
the end of the buffer, count in some empty lines. */
if (it.vpos < nlines)
- y1 += (nlines - it.vpos) * FRAME_LINE_HEIGHT (it.f);
-
- h = window_box_height (w) - (y1 - y0);
+ {
+ nlines -= it.vpos;
+ extra_line_spacing = it.extra_line_spacing;
+ h -= nlines * (FRAME_LINE_HEIGHT (it.f) + extra_line_spacing);
+ }
+ if (h <= 0)
+ return Qnil;
+ /* Now find the new top line (starting position) of the window. */
start_display (&it, w, pt);
- move_it_vertically (&it, - h);
+ it.current_y = 0;
+ move_it_vertically_backward (&it, h);
+
+ /* If extra line spacing is present, we may move too far
+ back. This causes the last line to be only partially
+ visible (which triggers redisplay to recenter that line
+ in the middle), so move forward.
+ But ignore extra line spacing on last line, as it is not
+ considered to be part of the visible height of the line.
+ */
+ h += extra_line_spacing;
+ while (-it.current_y > h)
+ move_it_by_lines (&it, 1, 1);
+
charpos = IT_CHARPOS (it);
bytepos = IT_BYTEPOS (it);
}
p = SAVED_WINDOW_N (vector, i);
w = XWINDOW (window);
- XSETFASTINT (w->temslot, i++);
+ XSETFASTINT (w->temslot, i); i++;
p->window = window;
p->buffer = w->buffer;
p->left_col = w->left_col;
struct window *w = decode_window (window);
if (!NILP (left))
- CHECK_NUMBER (left);
+ CHECK_NATNUM (left);
if (!NILP (right))
- CHECK_NUMBER (right);
+ CHECK_NATNUM (right);
if (!EQ (w->left_fringe_width, left)
|| !EQ (w->right_fringe_width, right)
struct window *w = decode_window (window);
if (!NILP (width))
- CHECK_NUMBER (width);
+ {
+ CHECK_NATNUM (width);
- if (XINT (width) == 0)
- vertical_type = Qnil;
+ if (XINT (width) == 0)
+ vertical_type = Qnil;
+ }
if (!(EQ (vertical_type, Qnil)
|| EQ (vertical_type, Qleft)