#include "buffer.h"
#include "keyboard.h"
#include "keymap.h"
+#include "menu.h"
#include "frame.h"
#include "window.h"
#include "commands.h"
static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
static Lisp_Object Qfloor, Qceiling;
+static Lisp_Object Qwindow_point_insertion_type;
static int displayed_window_lines (struct window *);
static int count_windows (struct window *);
/* Incremented for each window created. */
static int sequence_number;
-/* Nonzero after init_window_once has finished. */
-static int window_initialized;
-
/* Hook to run when window config changes. */
static Lisp_Object Qwindow_configuration_change_hook;
-/* Used by the function window_scroll_pixel_based */
+/* Used by the function window_scroll_pixel_based. */
static int window_scroll_pixel_based_preserve_x;
static int window_scroll_pixel_based_preserve_y;
DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
doc: /* Select WINDOW which must be a live window.
Also make WINDOW's frame the selected frame and WINDOW that frame's
-selected window. In addition, make WINDOW's buffer current and set that
+selected window. In addition, make WINDOW's buffer current and set its
buffer's value of `point' to the value of WINDOW's `window-point'.
Return WINDOW.
front of the buffer list and do not make this window the most recently
selected one.
-Note that the main editor command loop sets the current buffer to the
-buffer of the selected window before each command. */)
+Run `buffer-list-update-hook' unless NORECORD is non-nil. Note that
+applications and internal routines often select a window temporarily for
+various purposes; mostly, to simplify coding. As a rule, such
+selections should be not recorded and therefore will not pollute
+`buffer-list-update-hook'. Selections that "really count" are those
+causing a visible change in the next redisplay of WINDOW's frame and
+should be always recorded. So if you think of running a function each
+time a window gets selected put it on `buffer-list-update-hook'.
+
+Also note that the main editor command loop sets the current buffer to
+the buffer of the selected window before each command. */)
(register Lisp_Object window, Lisp_Object norecord)
{
return select_window (window, norecord, 0);
doc: /* Return the height of window WINDOW in pixels.
WINDOW must be a valid window and defaults to the selected one.
-The return value includes the mode line and header line, if any. If
-WINDOW is an internal window, its pixel height is the height of the
-screen areas spanned by its children. */)
+The return value includes the mode line and header line and the bottom
+divider, if any. If WINDOW is an internal window, its pixel height is
+the height of the screen areas spanned by its children. */)
(Lisp_Object window)
{
return make_number (decode_valid_window (window)->pixel_height);
if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
return ON_NOTHING;
- /* On vertical window divider (which prevails horizontal
- dividers)? */
- if (!WINDOW_RIGHTMOST_P (w)
- && WINDOW_RIGHT_DIVIDER_WIDTH (w)
- && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
- && x <= right_x)
- return ON_RIGHT_DIVIDER;
- /* On the horizontal window divider? */
- else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
- && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
- && y <= bottom_y)
+ /* On the horizontal window divider (which prevails the vertical
+ divider)? */
+ if (WINDOW_BOTTOM_DIVIDER_WIDTH (w) > 0
+ && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+ && y <= bottom_y)
return ON_BOTTOM_DIVIDER;
+ /* On vertical window divider? */
+ else if (!WINDOW_RIGHTMOST_P (w)
+ && WINDOW_RIGHT_DIVIDER_WIDTH (w) > 0
+ && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
+ && x <= right_x)
+ return ON_RIGHT_DIVIDER;
/* On the mode or header line? */
else if ((WINDOW_WANTS_MODELINE_P (w)
&& y >= (bottom_y
resize windows horizontally in case we're using toolkit scroll
bars. Note: If scrollbars are on the left, the window that
must be eventually resized is that on the left of WINDOW. */
- if ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
- && !WINDOW_LEFTMOST_P (w)
- && eabs (x - left_x) < grabbable_width)
- || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
- && !WINDOW_RIGHTMOST_P (w)
- && eabs (x - right_x) < grabbable_width))
+ if ((WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0)
+ && ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
+ && !WINDOW_LEFTMOST_P (w)
+ && eabs (x - left_x) < grabbable_width)
+ || (!WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
+ && !WINDOW_RIGHTMOST_P (w)
+ && eabs (x - right_x) < grabbable_width)))
return ON_VERTICAL_BORDER;
else
return part;
if (FRAME_WINDOW_P (f))
{
if (!w->pseudo_window_p
+ && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
&& !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
&& !WINDOW_RIGHTMOST_P (w)
&& (eabs (x - right_x) < grabbable_width))
/* Need to say "x > right_x" rather than >=, since on character
terminals, the vertical line's x coordinate is right_x. */
else if (!w->pseudo_window_p
+ && WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
&& !WINDOW_RIGHTMOST_P (w)
/* Why check ux if we are not the rightmost window? Also
shouldn't a pseudo window always be rightmost? */
? (x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
: (x < left_x + lmargin_width)))
return ON_LEFT_MARGIN;
-
- return ON_LEFT_FRINGE;
+ else
+ return ON_LEFT_FRINGE;
}
if (x >= text_right)
? (x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
: (x >= right_x - rmargin_width)))
return ON_RIGHT_MARGIN;
-
- return ON_RIGHT_FRINGE;
+ else
+ return ON_RIGHT_FRINGE;
}
/* Everything special ruled out - must be on text area */
case ON_TEXT:
return x - window_box_left (w, TEXT_AREA);
+ case ON_HEADER_LINE:
+ case ON_MODE_LINE:
case ON_LEFT_FRINGE:
return x - left_x;
frame.
If COORDINATES are in the text portion of WINDOW,
the coordinates relative to the window are returned.
+If they are in the bottom divider of WINDOW, `bottom-divider' is returned.
+If they are in the right divider of WINDOW, `right-divider' is returned.
If they are in the mode line of WINDOW, `mode-line' is returned.
-If they are in the top mode line of WINDOW, `header-line' is returned.
+If they are in the header line of WINDOW, `header-line' is returned.
If they are in the left fringe of WINDOW, `left-fringe' is returned.
If they are in the right fringe of WINDOW, `right-fringe' is returned.
If they are on the border between WINDOW and its right sibling,
{
if (EQ (window, selected_window))
/* Preferably return the selected window. */
- RETURN_UNGCPRO (window);
+ return window;
else if (EQ (XWINDOW (window)->frame, selected_frame)
&& !frame_best_window_flag)
/* Prefer windows on the current frame (but don't
void
run_window_configuration_change_hook (struct frame *f)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object frame, global_wcch
= Fdefault_value (Qwindow_configuration_change_hook);
XSETFRAME (frame, f);
- if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code))
+ if (NILP (Vrun_hooks) || !NILP (inhibit_lisp_code)) {
+ dynwind_end ();
return;
+ }
/* Use the right buffer. Matters when running the local hooks. */
if (current_buffer != XBUFFER (Fwindow_buffer (Qnil)))
if (!NILP (Flocal_variable_p (Qwindow_configuration_change_hook,
buffer)))
{
- ptrdiff_t inner_count = SPECPDL_INDEX ();
+ dynwind_begin ();
record_unwind_protect (select_window_norecord, selected_window);
select_window_norecord (window);
run_funs (Fbuffer_local_value (Qwindow_configuration_change_hook,
buffer));
- unbind_to (inner_count, Qnil);
+ dynwind_end ();
}
}
}
run_funs (global_wcch);
- unbind_to (count, Qnil);
+ dynwind_end ();
}
DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
{
struct window *w = XWINDOW (window);
struct buffer *b = XBUFFER (buffer);
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
bool samebuf = EQ (buffer, w->contents);
wset_buffer (w, buffer);
wset_redisplay (w);
w->update_mode_line = true;
- /* We must select BUFFER for running the window-scroll-functions. */
- /* We can't check ! NILP (Vwindow_scroll_functions) here
- because that might itself be a local variable. */
- if (window_initialized)
- {
- record_unwind_current_buffer ();
- Fset_buffer (buffer);
- }
+ /* We must select BUFFER to run the window-scroll-functions and to look up
+ the buffer-local value of Vwindow_point_insertion_type. */
+ record_unwind_current_buffer ();
+ Fset_buffer (buffer);
XMARKER (w->pointm)->insertion_type = !NILP (Vwindow_point_insertion_type);
run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
}
- unbind_to (count, Qnil);
+ dynwind_end ();
}
DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
/* Run temp-buffer-show-hook, with the chosen window selected
and its buffer current. */
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
Lisp_Object prev_window, prev_buffer;
prev_window = selected_window;
XSETBUFFER (prev_buffer, old);
Fselect_window (window, Qt);
Fset_buffer (w->contents);
Frun_hooks (1, &Qtemp_buffer_show_hook);
- unbind_to (count, Qnil);
+ dynwind_end ();
}
}
}
/* If PT is not visible in WINDOW, move back one half of
the screen. Allow PT to be partially visible, otherwise
something like (scroll-down 1) with PT in the line before
- the partially visible one would recenter. */
+ the partially visible one would recenter. */
if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
{
}
else if (auto_window_vscroll_p)
{
- if (rtop || rbot) /* partially visible */
+ if (rtop || rbot) /* Partially visible. */
{
int px;
int dy = frame_line_height;
static void
scroll_command (Lisp_Object n, int direction)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
eassert (eabs (direction) == 1);
window_scroll (selected_window, XINT (n) * direction, 0, 0);
}
- unbind_to (count, Qnil);
+ dynwind_end ();
}
DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "^P",
if (MINI_WINDOW_P (XWINDOW (selected_window))
&& !NILP (Vminibuf_scroll_window))
window = Vminibuf_scroll_window;
- /* If buffer is specified, scroll that buffer. */
- else if (!NILP (Vother_window_scroll_buffer))
+ /* If buffer is specified and live, scroll that buffer. */
+ else if (!NILP (Vother_window_scroll_buffer)
+ && BUFFERP (Vother_window_scroll_buffer)
+ && BUFFER_LIVE_P (XBUFFER (Vother_window_scroll_buffer)))
{
window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
if (NILP (window))
{
Lisp_Object window;
struct window *w;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
window = Fother_window_for_scrolling ();
w = XWINDOW (window);
}
set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
- unbind_to (count, Qnil);
+ dynwind_end ();
return Qnil;
}
{
struct window *w = XWINDOW (selected_window);
struct buffer *buf = XBUFFER (w->contents);
- struct buffer *obuf = current_buffer;
bool center_p = 0;
ptrdiff_t charpos, bytepos;
EMACS_INT iarg IF_LINT (= 0);
int this_scroll_margin;
+ 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. */
- obuf->display_error_modiff = 0;
+ buf->display_error_modiff = 0;
if (NILP (arg))
{
center_p = 1;
}
- else if (CONSP (arg)) /* Just C-u. */
+ else if (CONSP (arg)) /* Just C-u. */
center_p = 1;
else
{
iarg = XINT (arg);
}
- set_buffer_internal (buf);
-
/* Do this after making BUF current
in case scroll_margin is buffer-local. */
- this_scroll_margin =
- max (0, min (scroll_margin, w->total_lines / 4));
+ this_scroll_margin
+ = max (0, min (scroll_margin, w->total_lines / 4));
/* Handle centering on a graphical frame specially. Such frames can
have variable-height lines and centering point on the basis of
h -= it.current_y;
else
{
- /* Last line has no newline */
+ /* Last line has no newline. */
h -= line_bottom_y (&it);
it.vpos++;
}
w->optional_new_start = 1;
- w->start_at_line_beg = (bytepos == BEGV_BYTE ||
- FETCH_BYTE (bytepos - 1) == '\n');
+ w->start_at_line_beg = (bytepos == BEGV_BYTE
+ || FETCH_BYTE (bytepos - 1) == '\n');
- set_buffer_internal (obuf);
return Qnil;
}
int frame_menu_bar_height, frame_tool_bar_height;
};
-/* This is saved as a Lisp_Vector */
+/* This is saved as a Lisp_Vector. */
struct saved_window
{
struct vectorlike_header header;
- Lisp_Object window, buffer, start, pointm, mark;
+ Lisp_Object window, buffer, start, 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;
set_marker_restricted (w->start, p->start, w->contents);
set_marker_restricted (w->pointm, p->pointm,
w->contents);
- Fset_marker (BVAR (XBUFFER (w->contents), mark),
- p->mark, w->contents);
/* As documented in Fcurrent_window_configuration, don't
restore the location of point in the buffer which was
else
p->pointm = Fcopy_marker (w->pointm, Qnil);
XMARKER (p->pointm)->insertion_type
- = !NILP (Vwindow_point_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;
-
- tem = BVAR (XBUFFER (w->contents), mark);
- p->mark = Fcopy_marker (tem, Qnil);
}
else
{
p->pointm = Qnil;
p->start = Qnil;
- p->mark = Qnil;
p->start_at_line_beg = Qnil;
}
- if (NILP (w->parent))
- p->parent = Qnil;
- else
- p->parent = XWINDOW (w->parent)->temslot;
-
- if (NILP (w->prev))
- p->prev = Qnil;
- else
- p->prev = XWINDOW (w->prev)->temslot;
+ p->parent = NILP (w->parent) ? Qnil : XWINDOW (w->parent)->temslot;
+ p->prev = NILP (w->prev) ? Qnil : XWINDOW (w->prev)->temslot;
if (WINDOWP (w->contents))
i = save_window_save (w->contents, vector, i);
doc: /* Return an object representing the current window configuration of FRAME.
If FRAME is nil or omitted, use the selected frame.
This describes the number of windows, their sizes and current buffers,
-and for each displayed buffer, where display starts, and the positions of
-point and mark. An exception is made for point in the current buffer:
+and for each displayed buffer, where display starts, and the position of
+point. An exception is made for point in the current buffer:
its value is -not- saved.
This also records the currently selected frame, and FRAME's focus
redirection (see `redirect-frame-focus'). The variable
|| !EQ (sw1->min_hscroll, sw2->min_hscroll)
|| !EQ (sw1->start_at_line_beg, sw2->start_at_line_beg)
|| NILP (Fequal (sw1->start, sw2->start))
- || NILP (Fequal (sw1->pointm, sw2->pointm))
- || NILP (Fequal (sw1->mark, sw2->mark))))
+ || NILP (Fequal (sw1->pointm, sw2->pointm))))
|| !EQ (sw1->left_margin_cols, sw2->left_margin_cols)
|| !EQ (sw1->right_margin_cols, sw2->right_margin_cols)
|| !EQ (sw1->left_fringe_width, sw2->left_fringe_width)
DEFUN ("compare-window-configurations", Fcompare_window_configurations,
Scompare_window_configurations, 2, 2, 0,
doc: /* Compare two window configurations as regards the structure of windows.
-This function ignores details such as the values of point and mark
+This function ignores details such as the values of point
and scrolling positions. */)
(Lisp_Object x, Lisp_Object y)
{
Vterminal_frame = selected_frame;
minibuf_window = f->minibuffer_window;
selected_window = f->selected_window;
-
- window_initialized = 1;
}
void
void
syms_of_window (void)
{
+#include "window.x"
+
DEFSYM (Qscroll_up, "scroll-up");
DEFSYM (Qscroll_down, "scroll-down");
DEFSYM (Qscroll_command, "scroll-command");
mode_line_in_non_selected_windows = 1;
DEFVAR_LISP ("other-window-scroll-buffer", Vother_window_scroll_buffer,
- doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */);
+ doc: /* If this is a live buffer, \\[scroll-other-window] should scroll its window. */);
Vother_window_scroll_buffer = Qnil;
DEFVAR_BOOL ("auto-window-vscroll", auto_window_vscroll_p,
DEFVAR_LISP ("window-point-insertion-type", Vwindow_point_insertion_type,
doc: /* Type of marker to use for `window-point'. */);
Vwindow_point_insertion_type = Qnil;
+ DEFSYM (Qwindow_point_insertion_type, "window_point_insertion_type");
DEFVAR_LISP ("window-configuration-change-hook",
Vwindow_configuration_change_hook,
frame's character size, at least one window may get resized
pixelwise even if this option is nil. */);
window_resize_pixelwise = 0;
-
- defsubr (&Sselected_window);
- defsubr (&Sminibuffer_window);
- defsubr (&Swindow_minibuffer_p);
- defsubr (&Swindowp);
- defsubr (&Swindow_valid_p);
- defsubr (&Swindow_live_p);
- defsubr (&Swindow_frame);
- defsubr (&Sframe_root_window);
- defsubr (&Sframe_first_window);
- defsubr (&Sframe_selected_window);
- defsubr (&Sset_frame_selected_window);
- defsubr (&Spos_visible_in_window_p);
- defsubr (&Swindow_line_height);
- defsubr (&Swindow_buffer);
- defsubr (&Swindow_parent);
- defsubr (&Swindow_top_child);
- defsubr (&Swindow_left_child);
- defsubr (&Swindow_next_sibling);
- defsubr (&Swindow_prev_sibling);
- defsubr (&Swindow_combination_limit);
- defsubr (&Sset_window_combination_limit);
- defsubr (&Swindow_use_time);
- defsubr (&Swindow_pixel_width);
- defsubr (&Swindow_pixel_height);
- defsubr (&Swindow_total_width);
- defsubr (&Swindow_total_height);
- defsubr (&Swindow_normal_size);
- defsubr (&Swindow_new_pixel);
- defsubr (&Swindow_new_total);
- defsubr (&Swindow_new_normal);
- defsubr (&Swindow_pixel_left);
- defsubr (&Swindow_pixel_top);
- defsubr (&Swindow_left_column);
- defsubr (&Swindow_top_line);
- defsubr (&Sset_window_new_pixel);
- defsubr (&Sset_window_new_total);
- defsubr (&Sset_window_new_normal);
- defsubr (&Swindow_resize_apply);
- defsubr (&Swindow_resize_apply_total);
- defsubr (&Swindow_body_height);
- defsubr (&Swindow_body_width);
- defsubr (&Swindow_hscroll);
- defsubr (&Sset_window_hscroll);
- defsubr (&Swindow_redisplay_end_trigger);
- defsubr (&Sset_window_redisplay_end_trigger);
- defsubr (&Swindow_edges);
- defsubr (&Swindow_pixel_edges);
- defsubr (&Swindow_absolute_pixel_edges);
- defsubr (&Swindow_mode_line_height);
- defsubr (&Swindow_header_line_height);
- defsubr (&Swindow_right_divider_width);
- defsubr (&Swindow_bottom_divider_width);
- defsubr (&Swindow_scroll_bar_width);
- 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_start);
- defsubr (&Swindow_end);
- defsubr (&Sset_window_point);
- defsubr (&Sset_window_start);
- defsubr (&Swindow_dedicated_p);
- defsubr (&Sset_window_dedicated_p);
- defsubr (&Swindow_display_table);
- defsubr (&Sset_window_display_table);
- defsubr (&Snext_window);
- defsubr (&Sprevious_window);
- defsubr (&Sget_buffer_window);
- defsubr (&Sdelete_other_windows_internal);
- defsubr (&Sdelete_window_internal);
- defsubr (&Sresize_mini_window_internal);
- defsubr (&Sset_window_buffer);
- defsubr (&Srun_window_configuration_change_hook);
- defsubr (&Srun_window_scroll_functions);
- defsubr (&Sselect_window);
- defsubr (&Sforce_window_update);
- defsubr (&Ssplit_window_internal);
- defsubr (&Sscroll_up);
- defsubr (&Sscroll_down);
- defsubr (&Sscroll_left);
- defsubr (&Sscroll_right);
- defsubr (&Sother_window_for_scrolling);
- defsubr (&Sscroll_other_window);
- defsubr (&Sminibuffer_selected_window);
- defsubr (&Srecenter);
- defsubr (&Swindow_text_width);
- defsubr (&Swindow_text_height);
- defsubr (&Smove_to_window_line);
- defsubr (&Swindow_configuration_p);
- defsubr (&Swindow_configuration_frame);
- defsubr (&Sset_window_configuration);
- defsubr (&Scurrent_window_configuration);
- defsubr (&Sset_window_margins);
- defsubr (&Swindow_margins);
- defsubr (&Sset_window_fringes);
- defsubr (&Swindow_fringes);
- defsubr (&Sset_window_scroll_bars);
- defsubr (&Swindow_scroll_bars);
- defsubr (&Swindow_vscroll);
- defsubr (&Sset_window_vscroll);
- defsubr (&Scompare_window_configurations);
- defsubr (&Swindow_list);
- defsubr (&Swindow_list_1);
- defsubr (&Swindow_prev_buffers);
- defsubr (&Sset_window_prev_buffers);
- defsubr (&Swindow_next_buffers);
- defsubr (&Sset_window_next_buffers);
- defsubr (&Swindow_parameters);
- defsubr (&Swindow_parameter);
- defsubr (&Sset_window_parameter);
}
void