#include <config.h>
#include "lisp.h"
#include "buffer.h"
#include "keyboard.h"
#include "keymap.h"
#include "frame.h"
#include "window.h"
#include "commands.h"
#include "indent.h"
#include "termchar.h"
#include "disptab.h"
#include "dispextern.h"
#include "blockinput.h"
#include "intervals.h"
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif
#ifdef WINDOWSNT
#include "w32term.h"
#endif
#ifdef MSDOS
#include "msdos.h"
#endif
#ifdef MAC_OS
#include "macterm.h"
#endif
Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
Lisp_Object Qscroll_up, Qscroll_down;
Lisp_Object Qwindow_size_fixed;
extern Lisp_Object Qleft_margin, Qright_margin;
static int displayed_window_lines P_ ((struct window *));
static struct window *decode_window P_ ((Lisp_Object));
static int count_windows P_ ((struct window *));
static int get_leaf_windows P_ ((struct window *, struct window **, int));
static void window_scroll P_ ((Lisp_Object, int, int, int));
static void window_scroll_pixel_based P_ ((Lisp_Object, int, int, int));
static void window_scroll_line_based P_ ((Lisp_Object, int, int, int));
static int window_min_size_1 P_ ((struct window *, int));
static int window_min_size P_ ((struct window *, int, int, int *));
static void size_window P_ ((Lisp_Object, int, int, int, int, int));
static int freeze_window_start P_ ((struct window *, void *));
static int window_fixed_size_p P_ ((struct window *, int, int));
static void enlarge_window P_ ((Lisp_Object, int, int));
static Lisp_Object window_list P_ ((void));
static int add_window_to_list P_ ((struct window *, void *));
static int candidate_window_p P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object));
static Lisp_Object next_window P_ ((Lisp_Object, Lisp_Object,
Lisp_Object, int));
static void decode_next_window_args P_ ((Lisp_Object *, Lisp_Object *,
Lisp_Object *));
static int foreach_window_1 P_ ((struct window *,
int (* fn) (struct window *, void *),
void *));
static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
Lisp_Object selected_window;
Lisp_Object Vwindow_list;
Lisp_Object minibuf_window;
Lisp_Object minibuf_selected_window;
Lisp_Object Vminibuf_scroll_window;
Lisp_Object Vother_window_scroll_buffer;
Lisp_Object Vtemp_buffer_show_function;
int auto_window_vscroll_p;
int mode_line_in_non_selected_windows;
EMACS_INT window_min_height;
EMACS_INT window_min_width;
int pop_up_windows;
int pop_up_frames;
int display_buffer_reuse_frames;
Lisp_Object Vpop_up_frame_function;
Lisp_Object Vdisplay_buffer_function;
Lisp_Object Veven_window_heights;
Lisp_Object Vspecial_display_buffer_names;
Lisp_Object Vspecial_display_regexps;
Lisp_Object Vspecial_display_function;
Lisp_Object Vsame_window_buffer_names;
Lisp_Object Vsame_window_regexps;
Lisp_Object Qtemp_buffer_show_hook;
EMACS_INT split_height_threshold;
EMACS_INT next_screen_context_lines;
static int sequence_number;
static int window_initialized;
Lisp_Object Qwindow_configuration_change_hook;
Lisp_Object Vwindow_configuration_change_hook;
Lisp_Object Vscroll_preserve_screen_position;
int window_deletion_count;
static int window_scroll_pixel_based_preserve_y;
#if 0
static int inhibit_frame_unsplittable;
#endif
extern EMACS_INT scroll_margin;
extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
doc: )
(object)
Lisp_Object object;
{
return WINDOWP (object) ? Qt : Qnil;
}
DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
doc: )
(object)
Lisp_Object object;
{
return WINDOW_LIVE_P (object) ? Qt : Qnil;
}
Lisp_Object
make_window ()
{
Lisp_Object val;
register struct window *p;
p = allocate_window ();
++sequence_number;
XSETFASTINT (p->sequence_number, sequence_number);
XSETFASTINT (p->left_col, 0);
XSETFASTINT (p->top_line, 0);
XSETFASTINT (p->total_lines, 0);
XSETFASTINT (p->total_cols, 0);
XSETFASTINT (p->hscroll, 0);
XSETFASTINT (p->min_hscroll, 0);
p->orig_top_line = p->orig_total_lines = Qnil;
p->start = Fmake_marker ();
p->pointm = Fmake_marker ();
XSETFASTINT (p->use_time, 0);
p->frame = Qnil;
p->display_table = Qnil;
p->dedicated = Qnil;
p->pseudo_window_p = 0;
bzero (&p->cursor, sizeof (p->cursor));
bzero (&p->last_cursor, sizeof (p->last_cursor));
bzero (&p->phys_cursor, sizeof (p->phys_cursor));
p->desired_matrix = p->current_matrix = 0;
p->nrows_scale_factor = p->ncols_scale_factor = 1;
p->phys_cursor_type = -1;
p->phys_cursor_width = -1;
p->must_be_updated_p = 0;
XSETFASTINT (p->window_end_vpos, 0);
XSETFASTINT (p->window_end_pos, 0);
p->window_end_valid = Qnil;
p->vscroll = 0;
XSETWINDOW (val, p);
XSETFASTINT (p->last_point, 0);
p->frozen_window_start_p = 0;
p->last_cursor_off_p = p->cursor_off_p = 0;
p->left_margin_cols = Qnil;
p->right_margin_cols = Qnil;
p->left_fringe_width = Qnil;
p->right_fringe_width = Qnil;
p->fringes_outside_margins = Qnil;
p->scroll_bar_width = Qnil;
p->vertical_scroll_bar_type = Qt;
Vwindow_list = Qnil;
return val;
}
DEFUN ("selected-window", Fselected_window, Sselected_window, 0, 0, 0,
doc: )
()
{
return selected_window;
}
DEFUN ("minibuffer-window", Fminibuffer_window, Sminibuffer_window, 0, 1, 0,
doc: )
(frame)
Lisp_Object frame;
{
if (NILP (frame))
frame = selected_frame;
CHECK_LIVE_FRAME (frame);
return FRAME_MINIBUF_WINDOW (XFRAME (frame));
}
DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
struct window *w = decode_window (window);
return MINI_WINDOW_P (w) ? Qt : Qnil;
}
DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p,
Spos_visible_in_window_p, 0, 3, 0,
doc: )
(pos, window, partially)
Lisp_Object pos, window, partially;
{
register struct window *w;
register int posint;
register struct buffer *buf;
struct text_pos top;
Lisp_Object in_window = Qnil;
int rtop, rbot, rowh, vpos, fully_p = 1;
int x, y;
w = decode_window (window);
buf = XBUFFER (w->buffer);
SET_TEXT_POS_FROM_MARKER (top, w->start);
if (EQ (pos, Qt))
posint = -1;
else if (!NILP (pos))
{
CHECK_NUMBER_COERCE_MARKER (pos);
posint = XINT (pos);
}
else if (w == XWINDOW (selected_window))
posint = PT;
else
posint = XMARKER (w->pointm)->charpos;
if ((EQ (pos, Qt)
|| (posint >= CHARPOS (top) && posint <= BUF_ZV (buf)))
&& CHARPOS (top) >= BUF_BEGV (buf)
&& CHARPOS (top) <= BUF_ZV (buf)
&& pos_visible_p (w, posint, &x, &y, &rtop, &rbot, &rowh, &vpos)
&& (fully_p = !rtop && !rbot, (!NILP (partially) || fully_p)))
in_window = Qt;
if (!NILP (in_window) && !NILP (partially))
{
Lisp_Object part = Qnil;
if (!fully_p)
part = list4 (make_number (rtop), make_number (rbot),
make_number (rowh), make_number (vpos));
in_window = Fcons (make_number (x),
Fcons (make_number (y), part));
}
return in_window;
}
DEFUN ("window-line-height", Fwindow_line_height,
Swindow_line_height, 0, 2, 0,
doc: )
(line, window)
Lisp_Object line, window;
{
register struct window *w;
register struct buffer *b;
struct glyph_row *row, *end_row;
int max_y, crop, i, n;
w = decode_window (window);
if (noninteractive
|| w->pseudo_window_p)
return Qnil;
CHECK_BUFFER (w->buffer);
b = XBUFFER (w->buffer);
if (NILP (w->window_end_valid)
|| current_buffer->clip_changed
|| current_buffer->prevent_redisplay_optimizations_p
|| XFASTINT (w->last_modified) < BUF_MODIFF (b)
|| XFASTINT (w->last_overlay_modified) < BUF_OVERLAY_MODIFF (b))
return Qnil;
if (NILP (line))
{
i = w->cursor.vpos;
if (i < 0 || i >= w->current_matrix->nrows
|| (row = MATRIX_ROW (w->current_matrix, i), !row->enabled_p))
return Qnil;
max_y = window_text_bottom_y (w);
goto found_row;
}
if (EQ (line, Qheader_line))
{
if (!WINDOW_WANTS_HEADER_LINE_P (w))
return Qnil;
row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
if (!row->enabled_p)
return Qnil;
return list4 (make_number (row->height),
make_number (0), make_number (0),
make_number (0));
}
if (EQ (line, Qmode_line))
{
row = MATRIX_MODE_LINE_ROW (w->current_matrix);
if (!row->enabled_p)
return Qnil;
return list4 (make_number (row->height),
make_number (0),
make_number (WINDOW_HEADER_LINE_HEIGHT (w)
+ window_text_bottom_y (w)),
make_number (0));
}
CHECK_NUMBER (line);
n = XINT (line);
row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
max_y = window_text_bottom_y (w);
i = 0;
while ((n < 0 || i < n)
&& row <= end_row && row->enabled_p
&& row->y + row->height < max_y)
row++, i++;
if (row > end_row || !row->enabled_p)
return Qnil;
if (++n < 0)
{
if (-n > i)
return Qnil;
row += n;
i += n;
}
found_row:
crop = max (0, (row->y + row->height) - max_y);
return list4 (make_number (row->height + min (0, row->y) - crop),
make_number (i),
make_number (row->y),
make_number (crop));
}
static struct window *
decode_window (window)
register Lisp_Object window;
{
if (NILP (window))
return XWINDOW (selected_window);
CHECK_LIVE_WINDOW (window);
return XWINDOW (window);
}
static struct window *
decode_any_window (window)
register Lisp_Object window;
{
if (NILP (window))
return XWINDOW (selected_window);
CHECK_WINDOW (window);
return XWINDOW (window);
}
DEFUN ("window-buffer", Fwindow_buffer, Swindow_buffer, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
return decode_window (window)->buffer;
}
DEFUN ("window-height", Fwindow_height, Swindow_height, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
return decode_any_window (window)->total_lines;
}
DEFUN ("window-width", Fwindow_width, Swindow_width, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
return make_number (window_box_text_cols (decode_any_window (window)));
}
DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
return decode_window (window)->hscroll;
}
DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
doc: )
(window, ncol)
Lisp_Object window, ncol;
{
struct window *w = decode_window (window);
int hscroll;
CHECK_NUMBER (ncol);
hscroll = max (0, XINT (ncol));
if (XINT (w->hscroll) != hscroll)
XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
w->hscroll = make_number (hscroll);
return ncol;
}
DEFUN ("window-redisplay-end-trigger", Fwindow_redisplay_end_trigger,
Swindow_redisplay_end_trigger, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
return decode_window (window)->redisplay_end_trigger;
}
DEFUN ("set-window-redisplay-end-trigger", Fset_window_redisplay_end_trigger,
Sset_window_redisplay_end_trigger, 2, 2, 0,
doc: )
(window, value)
register Lisp_Object window, value;
{
register struct window *w;
w = decode_window (window);
w->redisplay_end_trigger = value;
return value;
}
DEFUN ("window-edges", Fwindow_edges, Swindow_edges, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
register struct window *w = decode_any_window (window);
return Fcons (make_number (WINDOW_LEFT_EDGE_COL (w)),
Fcons (make_number (WINDOW_TOP_EDGE_LINE (w)),
Fcons (make_number (WINDOW_RIGHT_EDGE_COL (w)),
Fcons (make_number (WINDOW_BOTTOM_EDGE_LINE (w)),
Qnil))));
}
DEFUN ("window-pixel-edges", Fwindow_pixel_edges, Swindow_pixel_edges, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
register struct window *w = decode_any_window (window);
return Fcons (make_number (WINDOW_LEFT_EDGE_X (w)),
Fcons (make_number (WINDOW_TOP_EDGE_Y (w)),
Fcons (make_number (WINDOW_RIGHT_EDGE_X (w)),
Fcons (make_number (WINDOW_BOTTOM_EDGE_Y (w)),
Qnil))));
}
DEFUN ("window-inside-edges", Fwindow_inside_edges, Swindow_inside_edges, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
register struct window *w = decode_any_window (window);
return list4 (make_number (WINDOW_BOX_LEFT_EDGE_COL (w)
+ WINDOW_LEFT_MARGIN_COLS (w)
+ WINDOW_LEFT_FRINGE_COLS (w)),
make_number (WINDOW_TOP_EDGE_LINE (w)
+ WINDOW_HEADER_LINE_LINES (w)),
make_number (WINDOW_BOX_RIGHT_EDGE_COL (w)
- WINDOW_RIGHT_MARGIN_COLS (w)
- WINDOW_RIGHT_FRINGE_COLS (w)),
make_number (WINDOW_BOTTOM_EDGE_LINE (w)
- WINDOW_MODE_LINE_LINES (w)));
}
DEFUN ("window-inside-pixel-edges", Fwindow_inside_pixel_edges, Swindow_inside_pixel_edges, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
register struct window *w = decode_any_window (window);
return list4 (make_number (WINDOW_BOX_LEFT_EDGE_X (w)
+ WINDOW_LEFT_MARGIN_WIDTH (w)
+ WINDOW_LEFT_FRINGE_WIDTH (w)),
make_number (WINDOW_TOP_EDGE_Y (w)
+ WINDOW_HEADER_LINE_HEIGHT (w)),
make_number (WINDOW_BOX_RIGHT_EDGE_X (w)
- WINDOW_RIGHT_MARGIN_WIDTH (w)
- WINDOW_RIGHT_FRINGE_WIDTH (w)),
make_number (WINDOW_BOTTOM_EDGE_Y (w)
- WINDOW_MODE_LINE_HEIGHT (w)));
}
static enum window_part
coordinates_in_window (w, x, y)
register struct window *w;
register int *x, *y;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
int left_x, right_x, top_y, bottom_y;
enum window_part part;
int ux = FRAME_COLUMN_WIDTH (f);
int x0 = WINDOW_LEFT_EDGE_X (w);
int x1 = WINDOW_RIGHT_EDGE_X (w);
int grabbable_width = ux;
int lmargin_width, rmargin_width, text_left, text_right;
if (w->pseudo_window_p)
{
left_x = 0;
right_x = WINDOW_TOTAL_WIDTH (w) - 1;
top_y = WINDOW_TOP_EDGE_Y (w);
bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
}
else
{
left_x = WINDOW_BOX_LEFT_EDGE_X (w);
right_x = WINDOW_BOX_RIGHT_EDGE_X (w) - 1;
top_y = WINDOW_TOP_EDGE_Y (w);
bottom_y = WINDOW_BOTTOM_EDGE_Y (w);
}
if (*y < top_y || *y >= bottom_y)
return ON_NOTHING;
if (WINDOW_WANTS_MODELINE_P (w)
&& *y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w))
{
part = ON_MODE_LINE;
header_vertical_border_check:
if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
|| WINDOW_RIGHTMOST_P (w))
{
if (!WINDOW_LEFTMOST_P (w) && abs (*x - x0) < grabbable_width)
{
*x = max (0, *x - x0);
*y -= top_y;
return ON_VERTICAL_BORDER;
}
}
else
{
if (abs (*x - x1) < grabbable_width)
{
*x = min (x1, *x) - x0;
*y -= top_y;
return ON_VERTICAL_BORDER;
}
}
if (*x < x0 || *x >= x1)
return ON_NOTHING;
*x -= x0;
*y -= top_y;
return part;
}
if (WINDOW_WANTS_HEADER_LINE_P (w)
&& *y < top_y + CURRENT_HEADER_LINE_HEIGHT (w))
{
part = ON_HEADER_LINE;
goto header_vertical_border_check;
}
if (*x < x0 || *x >= x1)
return ON_NOTHING;
if (*x < left_x || *x > right_x)
{
*y -= top_y;
return ON_SCROLL_BAR;
}
lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
text_left = window_box_left (w, TEXT_AREA);
text_right = text_left + window_box_width (w, TEXT_AREA);
if (FRAME_WINDOW_P (f))
{
if (!w->pseudo_window_p
&& !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
&& !WINDOW_RIGHTMOST_P (w)
&& (abs (*x - right_x) < grabbable_width))
{
*x = min (right_x, *x) - left_x;
*y -= top_y;
return ON_VERTICAL_BORDER;
}
}
else
{
if (!w->pseudo_window_p
&& !WINDOW_RIGHTMOST_P (w)
&& *x > right_x - ux)
{
*x = min (right_x, *x) - left_x;
*y -= top_y;
return ON_VERTICAL_BORDER;
}
}
if (*x < text_left)
{
if (lmargin_width > 0
&& (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
? (*x >= left_x + WINDOW_LEFT_FRINGE_WIDTH (w))
: (*x < left_x + lmargin_width)))
{
*x -= left_x;
if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
*x -= WINDOW_LEFT_FRINGE_WIDTH (w);
*y -= top_y;
return ON_LEFT_MARGIN;
}
*x -= left_x;
*y -= top_y;
return ON_LEFT_FRINGE;
}
if (*x >= text_right)
{
if (rmargin_width > 0
&& (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
? (*x < right_x - WINDOW_RIGHT_FRINGE_WIDTH (w))
: (*x >= right_x - rmargin_width)))
{
*x -= right_x - rmargin_width;
if (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
*x += WINDOW_RIGHT_FRINGE_WIDTH (w);
*y -= top_y;
return ON_RIGHT_MARGIN;
}
*x -= left_x + WINDOW_LEFT_FRINGE_WIDTH (w);
*y -= top_y;
return ON_RIGHT_FRINGE;
}
*x -= text_left;
*y -= top_y;
return ON_TEXT;
}
DEFUN ("coordinates-in-window-p", Fcoordinates_in_window_p,
Scoordinates_in_window_p, 2, 2, 0,
doc: )
(coordinates, window)
register Lisp_Object coordinates, window;
{
struct window *w;
struct frame *f;
int x, y;
Lisp_Object lx, ly;
CHECK_WINDOW (window);
w = XWINDOW (window);
f = XFRAME (w->frame);
CHECK_CONS (coordinates);
lx = Fcar (coordinates);
ly = Fcdr (coordinates);
CHECK_NUMBER_OR_FLOAT (lx);
CHECK_NUMBER_OR_FLOAT (ly);
x = FRAME_PIXEL_X_FROM_CANON_X (f, lx) + FRAME_INTERNAL_BORDER_WIDTH (f);
y = FRAME_PIXEL_Y_FROM_CANON_Y (f, ly) + FRAME_INTERNAL_BORDER_WIDTH (f);
switch (coordinates_in_window (w, &x, &y))
{
case ON_NOTHING:
return Qnil;
case ON_TEXT:
return Fcons (FRAME_CANON_X_FROM_PIXEL_X (f, x),
FRAME_CANON_Y_FROM_PIXEL_Y (f, y));
case ON_MODE_LINE:
return Qmode_line;
case ON_VERTICAL_BORDER:
return Qvertical_line;
case ON_HEADER_LINE:
return Qheader_line;
case ON_LEFT_FRINGE:
return Qleft_fringe;
case ON_RIGHT_FRINGE:
return Qright_fringe;
case ON_LEFT_MARGIN:
return Qleft_margin;
case ON_RIGHT_MARGIN:
return Qright_margin;
case ON_SCROLL_BAR:
return Qnil;
default:
abort ();
}
}
struct check_window_data
{
Lisp_Object *window;
int *x, *y;
enum window_part *part;
};
static int
check_window_containing (w, user_data)
struct window *w;
void *user_data;
{
struct check_window_data *cw = (struct check_window_data *) user_data;
enum window_part found;
int continue_p = 1;
found = coordinates_in_window (w, cw->x, cw->y);
if (found != ON_NOTHING)
{
*cw->part = found;
XSETWINDOW (*cw->window, w);
continue_p = 0;
}
return continue_p;
}
Lisp_Object
window_from_coordinates (f, x, y, part, wx, wy, tool_bar_p)
struct frame *f;
int x, y;
enum window_part *part;
int *wx, *wy;
int tool_bar_p;
{
Lisp_Object window;
struct check_window_data cw;
enum window_part dummy;
if (part == 0)
part = &dummy;
window = Qnil;
cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
foreach_window (f, check_window_containing, &cw);
if (NILP (window)
&& tool_bar_p
&& WINDOWP (f->tool_bar_window)
&& WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0
&& (coordinates_in_window (XWINDOW (f->tool_bar_window), &x, &y)
!= ON_NOTHING))
{
*part = ON_TEXT;
window = f->tool_bar_window;
}
if (wx) *wx = x;
if (wy) *wy = y;
return window;
}
DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
doc: )
(x, y, frame)
Lisp_Object x, y, frame;
{
struct frame *f;
if (NILP (frame))
frame = selected_frame;
CHECK_LIVE_FRAME (frame);
f = XFRAME (frame);
CHECK_NUMBER_OR_FLOAT (x);
CHECK_NUMBER_OR_FLOAT (y);
return window_from_coordinates (f,
(FRAME_PIXEL_X_FROM_CANON_X (f, x)
+ FRAME_INTERNAL_BORDER_WIDTH (f)),
(FRAME_PIXEL_Y_FROM_CANON_Y (f, y)
+ FRAME_INTERNAL_BORDER_WIDTH (f)),
0, 0, 0, 0);
}
DEFUN ("window-point", Fwindow_point, Swindow_point, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
register struct window *w = decode_window (window);
if (w == XWINDOW (selected_window)
&& current_buffer == XBUFFER (w->buffer))
return Fpoint ();
return Fmarker_position (w->pointm);
}
DEFUN ("window-start", Fwindow_start, Swindow_start, 0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
return Fmarker_position (decode_window (window)->start);
}
DEFUN ("window-end", Fwindow_end, Swindow_end, 0, 2, 0,
doc: )
(window, update)
Lisp_Object window, update;
{
Lisp_Object value;
struct window *w = decode_window (window);
Lisp_Object buf;
struct buffer *b;
buf = w->buffer;
CHECK_BUFFER (buf);
b = XBUFFER (buf);
#if 0
if (NILP (w->window_end_valid))
return Qnil;
#endif
if (! NILP (update)
&& ! (! NILP (w->window_end_valid)
&& XFASTINT (w->last_modified) >= BUF_MODIFF (b)
&& XFASTINT (w->last_overlay_modified) >= BUF_OVERLAY_MODIFF (b))
&& !noninteractive)
{
struct text_pos startp;
struct it it;
struct buffer *old_buffer = NULL;
if (b != current_buffer)
{
old_buffer = current_buffer;
set_buffer_internal (b);
}
if (XMARKER (w->start)->charpos < BEGV)
SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
else if (XMARKER (w->start)->charpos > ZV)
SET_TEXT_POS (startp, ZV, ZV_BYTE);
else
SET_TEXT_POS_FROM_MARKER (startp, w->start);
start_display (&it, w, startp);
move_it_vertically (&it, window_box_height (w));
if (it.current_y < it.last_visible_y)
move_it_past_eol (&it);
value = make_number (IT_CHARPOS (it));
if (old_buffer)
set_buffer_internal (old_buffer);
}
else
XSETINT (value, BUF_Z (b) - XFASTINT (w->window_end_pos));
return value;
}
DEFUN ("set-window-point", Fset_window_point, Sset_window_point, 2, 2, 0,
doc: )
(window, pos)
Lisp_Object window, pos;
{
register struct window *w = decode_window (window);
CHECK_NUMBER_COERCE_MARKER (pos);
if (w == XWINDOW (selected_window)
&& XBUFFER (w->buffer) == current_buffer)
Fgoto_char (pos);
else
set_marker_restricted (w->pointm, pos, w->buffer);
if (!EQ (window, selected_window))
++windows_or_buffers_changed;
return pos;
}
DEFUN ("set-window-start", Fset_window_start, Sset_window_start, 2, 3, 0,
doc: )
(window, pos, noforce)
Lisp_Object window, pos, noforce;
{
register struct window *w = decode_window (window);
CHECK_NUMBER_COERCE_MARKER (pos);
set_marker_restricted (w->start, pos, w->buffer);
w->start_at_line_beg = Qnil;
if (NILP (noforce))
w->force_start = Qt;
w->update_mode_line = Qt;
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
if (!EQ (window, selected_window))
windows_or_buffers_changed++;
return pos;
}
DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1, 1, 0,
doc: )
(window)
Lisp_Object window;
{
return decode_window (window)->dedicated;
}
DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p,
Sset_window_dedicated_p, 2, 2, 0,
doc: )
(window, arg)
Lisp_Object window, arg;
{
register struct window *w = decode_window (window);
w->dedicated = arg;
return w->dedicated;
}
DEFUN ("window-display-table", Fwindow_display_table, Swindow_display_table,
0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
return decode_window (window)->display_table;
}
struct Lisp_Char_Table *
window_display_table (w)
struct window *w;
{
struct Lisp_Char_Table *dp = NULL;
if (DISP_TABLE_P (w->display_table))
dp = XCHAR_TABLE (w->display_table);
else if (BUFFERP (w->buffer))
{
struct buffer *b = XBUFFER (w->buffer);
if (DISP_TABLE_P (b->display_table))
dp = XCHAR_TABLE (b->display_table);
else if (DISP_TABLE_P (Vstandard_display_table))
dp = XCHAR_TABLE (Vstandard_display_table);
}
return dp;
}
DEFUN ("set-window-display-table", Fset_window_display_table, Sset_window_display_table, 2, 2, 0,
doc: )
(window, table)
register Lisp_Object window, table;
{
register struct window *w;
w = decode_window (window);
w->display_table = table;
return table;
}
static void
unshow_buffer (w)
register struct window *w;
{
Lisp_Object buf;
struct buffer *b;
buf = w->buffer;
b = XBUFFER (buf);
if (b != XMARKER (w->pointm)->buffer)
abort ();
#if 0
if (w == XWINDOW (selected_window)
|| ! EQ (buf, XWINDOW (selected_window)->buffer))
#endif
b->last_window_start = marker_position (w->start);
if (! EQ (buf, XWINDOW (selected_window)->buffer)
&& !(WINDOWP (b->last_selected_window)
&& w != XWINDOW (b->last_selected_window)
&& EQ (buf, XWINDOW (b->last_selected_window)->buffer)))
temp_set_point_both (b,
clip_to_bounds (BUF_BEGV (b),
XMARKER (w->pointm)->charpos,
BUF_ZV (b)),
clip_to_bounds (BUF_BEGV_BYTE (b),
marker_byte_position (w->pointm),
BUF_ZV_BYTE (b)));
if (WINDOWP (b->last_selected_window)
&& w == XWINDOW (b->last_selected_window))
b->last_selected_window = Qnil;
}
static void
replace_window (old, replacement)
Lisp_Object old, replacement;
{
register Lisp_Object tem;
register struct window *o = XWINDOW (old), *p = XWINDOW (replacement);
if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
p->left_col = o->left_col;
p->top_line = o->top_line;
p->total_cols = o->total_cols;
p->total_lines = o->total_lines;
p->desired_matrix = p->current_matrix = 0;
p->vscroll = 0;
bzero (&p->cursor, sizeof (p->cursor));
bzero (&p->last_cursor, sizeof (p->last_cursor));
bzero (&p->phys_cursor, sizeof (p->phys_cursor));
p->phys_cursor_type = -1;
p->phys_cursor_width = -1;
p->must_be_updated_p = 0;
p->pseudo_window_p = 0;
XSETFASTINT (p->window_end_vpos, 0);
XSETFASTINT (p->window_end_pos, 0);
p->window_end_valid = Qnil;
p->frozen_window_start_p = 0;
p->orig_top_line = p->orig_total_lines = Qnil;
p->next = tem = o->next;
if (!NILP (tem))
XWINDOW (tem)->prev = replacement;
p->prev = tem = o->prev;
if (!NILP (tem))
XWINDOW (tem)->next = replacement;
p->parent = tem = o->parent;
if (!NILP (tem))
{
if (EQ (XWINDOW (tem)->vchild, old))
XWINDOW (tem)->vchild = replacement;
if (EQ (XWINDOW (tem)->hchild, old))
XWINDOW (tem)->hchild = replacement;
}
}
DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "",
doc: )
(window)
register Lisp_Object window;
{
delete_window (window);
if (! NILP (Vwindow_configuration_change_hook)
&& ! NILP (Vrun_hooks))
call1 (Vrun_hooks, Qwindow_configuration_change_hook);
return Qnil;
}
void
delete_window (window)
register Lisp_Object window;
{
register Lisp_Object tem, parent, sib;
register struct window *p;
register struct window *par;
struct frame *f;
if (NILP (window))
window = selected_window;
else
CHECK_WINDOW (window);
p = XWINDOW (window);
if (NILP (p->buffer)
&& NILP (p->hchild)
&& NILP (p->vchild))
return;
parent = p->parent;
if (NILP (parent))
error ("Attempt to delete minibuffer or sole ordinary window");
par = XWINDOW (parent);
windows_or_buffers_changed++;
Vwindow_list = Qnil;
f = XFRAME (WINDOW_FRAME (p));
FRAME_WINDOW_SIZES_CHANGED (f) = 1;
{
Lisp_Object swindow, pwindow;
swindow = FRAME_SELECTED_WINDOW (f);
while (1)
{
pwindow = swindow;
while (!NILP (pwindow))
{
if (EQ (window, pwindow))
break;
pwindow = XWINDOW (pwindow)->parent;
}
if (!EQ (window, pwindow))
break;
swindow = Fnext_window (swindow, Qlambda, Qnil);;
if (EQ (swindow, FRAME_SELECTED_WINDOW (f)))
error ("Cannot delete window");
}
if (! EQ (swindow, FRAME_SELECTED_WINDOW (f)))
{
if (EQ (FRAME_SELECTED_WINDOW (f), selected_window))
Fselect_window (swindow, Qnil);
else
FRAME_SELECTED_WINDOW (f) = swindow;
}
}
window_deletion_count++;
tem = p->buffer;
if (!NILP (tem))
{
unshow_buffer (p);
unchain_marker (XMARKER (p->pointm));
unchain_marker (XMARKER (p->start));
}
BLOCK_INPUT;
free_window_matrices (XWINDOW (FRAME_ROOT_WINDOW (f)));
tem = p->next;
if (!NILP (tem))
XWINDOW (tem)->prev = p->prev;
tem = p->prev;
if (!NILP (tem))
XWINDOW (tem)->next = p->next;
if (EQ (window, par->hchild))
par->hchild = p->next;
if (EQ (window, par->vchild))
par->vchild = p->next;
sib = p->prev;
if (NILP (sib))
{
sib = p->next;
XWINDOW (sib)->top_line = p->top_line;
XWINDOW (sib)->left_col = p->left_col;
}
if (!NILP (par->vchild))
set_window_height (sib,
XFASTINT (XWINDOW (sib)->total_lines) + XFASTINT (p->total_lines),
1);
if (!NILP (par->hchild))
set_window_width (sib,
XFASTINT (XWINDOW (sib)->total_cols) + XFASTINT (p->total_cols),
1);
tem = par->hchild;
if (NILP (tem))
tem = par->vchild;
if (NILP (XWINDOW (tem)->next)) {
replace_window (parent, tem);
par = XWINDOW (tem);
}
if (! NILP (p->hchild))
delete_all_subwindows (XWINDOW (p->hchild));
else if (! NILP (p->vchild))
delete_all_subwindows (XWINDOW (p->vchild));
p->buffer = p->hchild = p->vchild = Qnil;
if (! NILP (par->parent))
par = XWINDOW (par->parent);
if (! NILP (par->vchild) && ! NILP (XWINDOW (par->vchild)->vchild))
{
p = XWINDOW (par->vchild);
par->vchild = p->vchild;
tem = p->vchild;
}
else if (! NILP (par->hchild) && ! NILP (XWINDOW (par->hchild)->hchild))
{
p = XWINDOW (par->hchild);
par->hchild = p->hchild;
tem = p->hchild;
}
else
p = 0;
if (p)
{
while (! NILP (tem)) {
XWINDOW (tem)->parent = p->parent;
if (NILP (XWINDOW (tem)->next))
break;
tem = XWINDOW (tem)->next;
}
if (! NILP (tem)) {
XWINDOW (tem)->next = p->next;
if (! NILP (p->next))
XWINDOW (p->next)->prev = tem;
}
p->next = p->prev = p->vchild = p->hchild = p->buffer = Qnil;
}
adjust_glyphs (f);
UNBLOCK_INPUT;
}
static int
add_window_to_list (w, user_data)
struct window *w;
void *user_data;
{
Lisp_Object *list = (Lisp_Object *) user_data;
Lisp_Object window;
XSETWINDOW (window, w);
*list = Fcons (window, *list);
return 1;
}
static Lisp_Object
window_list ()
{
if (!CONSP (Vwindow_list))
{
Lisp_Object tail;
Vwindow_list = Qnil;
for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
{
Lisp_Object args[2];
args[1] = Qnil;
foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
args[0] = Vwindow_list;
args[1] = Fnreverse (args[1]);
Vwindow_list = Fnconc (2, args);
}
}
return Vwindow_list;
}
static int
candidate_window_p (window, owindow, minibuf, all_frames)
Lisp_Object window, owindow, minibuf, all_frames;
{
struct window *w = XWINDOW (window);
struct frame *f = XFRAME (w->frame);
int candidate_p = 1;
if (!BUFFERP (w->buffer))
candidate_p = 0;
else if (MINI_WINDOW_P (w)
&& (EQ (minibuf, Qlambda)
|| (WINDOWP (minibuf) && !EQ (minibuf, window))))
{
candidate_p = 0;
}
else if (EQ (all_frames, Qt))
candidate_p = 1;
else if (NILP (all_frames))
{
xassert (WINDOWP (owindow));
candidate_p = EQ (w->frame, XWINDOW (owindow)->frame);
}
else if (EQ (all_frames, Qvisible))
{
FRAME_SAMPLE_VISIBILITY (f);
candidate_p = FRAME_VISIBLE_P (f);
}
else if (INTEGERP (all_frames) && XINT (all_frames) == 0)
{
FRAME_SAMPLE_VISIBILITY (f);
candidate_p = FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f);
}
else if (WINDOWP (all_frames))
candidate_p = (EQ (FRAME_MINIBUF_WINDOW (f), all_frames)
|| EQ (XWINDOW (all_frames)->frame, w->frame)
|| EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
else if (FRAMEP (all_frames))
candidate_p = EQ (all_frames, w->frame);
return candidate_p;
}
static void
decode_next_window_args (window, minibuf, all_frames)
Lisp_Object *window, *minibuf, *all_frames;
{
if (NILP (*window))
*window = selected_window;
else
CHECK_LIVE_WINDOW (*window);
if (NILP (*minibuf))
*minibuf = minibuf_level ? minibuf_window : Qlambda;
else if (!EQ (*minibuf, Qt))
*minibuf = Qlambda;
if (NILP (*all_frames))
*all_frames = (!EQ (*minibuf, Qlambda)
? FRAME_MINIBUF_WINDOW (XFRAME (XWINDOW (*window)->frame))
: Qnil);
else if (EQ (*all_frames, Qvisible))
;
else if (EQ (*all_frames, make_number (0)))
;
else if (FRAMEP (*all_frames))
;
else if (!EQ (*all_frames, Qt))
*all_frames = Qnil;
}
static Lisp_Object
next_window (window, minibuf, all_frames, next_p)
Lisp_Object window, minibuf, all_frames;
int next_p;
{
decode_next_window_args (&window, &minibuf, &all_frames);
if (FRAMEP (all_frames)
&& !EQ (all_frames, XWINDOW (window)->frame))
return Fframe_first_window (all_frames);
if (next_p)
{
Lisp_Object list;
list = Fmemq (window, window_list ());
if (CONSP (list))
for (list = XCDR (list); CONSP (list); list = XCDR (list))
if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
break;
if (!CONSP (list))
for (list = Vwindow_list;
CONSP (list) && !EQ (XCAR (list), window);
list = XCDR (list))
if (candidate_window_p (XCAR (list), window, minibuf, all_frames))
break;
if (CONSP (list))
window = XCAR (list);
}
else
{
Lisp_Object candidate, list;
candidate = Qnil;
for (list = window_list (); CONSP (list); list = XCDR (list))
{
if (EQ (XCAR (list), window))
{
if (WINDOWP (candidate))
break;
}
else if (candidate_window_p (XCAR (list), window, minibuf,
all_frames))
candidate = XCAR (list);
}
if (WINDOWP (candidate))
window = candidate;
}
return window;
}
DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
doc: )
(window, minibuf, all_frames)
Lisp_Object window, minibuf, all_frames;
{
return next_window (window, minibuf, all_frames, 1);
}
DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
doc: )
(window, minibuf, all_frames)
Lisp_Object window, minibuf, all_frames;
{
return next_window (window, minibuf, all_frames, 0);
}
DEFUN ("other-window", Fother_window, Sother_window, 1, 2, "p",
doc: )
(arg, all_frames)
Lisp_Object arg, all_frames;
{
Lisp_Object window;
int i;
CHECK_NUMBER (arg);
window = selected_window;
for (i = XINT (arg); i > 0; --i)
window = Fnext_window (window, Qnil, all_frames);
for (; i < 0; ++i)
window = Fprevious_window (window, Qnil, all_frames);
Fselect_window (window, Qnil);
return Qnil;
}
DEFUN ("window-list", Fwindow_list, Swindow_list, 0, 3, 0,
doc: )
(frame, minibuf, window)
Lisp_Object frame, minibuf, window;
{
if (NILP (window))
window = FRAMEP (frame) ? XFRAME (frame)->selected_window : selected_window;
CHECK_WINDOW (window);
if (NILP (frame))
frame = selected_frame;
if (!EQ (frame, XWINDOW (window)->frame))
error ("Window is on a different frame");
return window_list_1 (window, minibuf, frame);
}
static Lisp_Object
window_list_1 (window, minibuf, all_frames)
Lisp_Object window, minibuf, all_frames;
{
Lisp_Object tail, list, rest;
decode_next_window_args (&window, &minibuf, &all_frames);
list = Qnil;
for (tail = window_list (); CONSP (tail); tail = XCDR (tail))
if (candidate_window_p (XCAR (tail), window, minibuf, all_frames))
list = Fcons (XCAR (tail), list);
list = Fnreverse (list);
rest = Fmemq (window, list);
if (!NILP (rest) && !EQ (rest, list))
{
for (tail = list; !EQ (XCDR (tail), rest); tail = XCDR (tail))
;
XSETCDR (tail, Qnil);
list = nconc2 (rest, list);
}
return list;
}
enum window_loop
{
WINDOW_LOOP_UNUSED,
GET_BUFFER_WINDOW,
GET_LRU_WINDOW,
DELETE_OTHER_WINDOWS,
DELETE_BUFFER_WINDOWS,
GET_LARGEST_WINDOW,
UNSHOW_BUFFER,
REDISPLAY_BUFFER_WINDOWS,
CHECK_ALL_WINDOWS
};
static Lisp_Object
window_loop (type, obj, mini, frames)
enum window_loop type;
Lisp_Object obj, frames;
int mini;
{
Lisp_Object window, windows, best_window, frame_arg;
struct frame *f;
struct gcpro gcpro1;
if (FRAMEP (frames))
f = XFRAME (frames);
else if (NILP (frames))
f = SELECTED_FRAME ();
else
f = NULL;
if (f)
frame_arg = Qlambda;
else if (EQ (frames, make_number (0)))
frame_arg = frames;
else if (EQ (frames, Qvisible))
frame_arg = frames;
else
frame_arg = Qt;
if (WINDOWP (obj))
window = obj;
else if (f)
window = FRAME_SELECTED_WINDOW (f);
else
window = FRAME_SELECTED_WINDOW (SELECTED_FRAME ());
windows = window_list_1 (window, mini ? Qt : Qnil, frame_arg);
GCPRO1 (windows);
best_window = Qnil;
for (; CONSP (windows); windows = XCDR (windows))
{
struct window *w;
window = XCAR (windows);
w = XWINDOW (window);
if (!MINI_WINDOW_P (w)
|| type == UNSHOW_BUFFER
|| (mini && minibuf_level > 0))
switch (type)
{
case GET_BUFFER_WINDOW:
if (EQ (w->buffer, obj)
&& (MINI_WINDOW_P (w)
? EQ (window, minibuf_window)
: 1))
{
if (NILP (best_window))
best_window = window;
else if (EQ (window, selected_window))
best_window = window;
}
break;
case GET_LRU_WINDOW:
if (((XINT (obj) & 1) && !WINDOW_FULL_WIDTH_P (w))
|| (!(XINT (obj) & 2) && !NILP (w->dedicated))
|| MINI_WINDOW_P (w))
break;
if (NILP (best_window)
|| (XFASTINT (XWINDOW (best_window)->use_time)
> XFASTINT (w->use_time)))
best_window = window;
break;
case DELETE_OTHER_WINDOWS:
if (!EQ (window, obj))
Fdelete_window (window);
break;
case DELETE_BUFFER_WINDOWS:
if (EQ (w->buffer, obj))
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
if (EQ (window, FRAME_ROOT_WINDOW (f))
&& !NILP (w->dedicated)
&& other_visible_frames (f))
{
while (CONSP (XCDR (windows))
&& EQ (XWINDOW (XCAR (windows))->frame,
XWINDOW (XCAR (XCDR (windows)))->frame))
windows = XCDR (windows);
Fdelete_frame (w->frame, Qnil);
}
else if (NILP (w->parent))
{
Lisp_Object buffer;
buffer = Fother_buffer (obj, Qnil, w->frame);
Fset_window_buffer (window, buffer, Qnil);
if (EQ (window, selected_window))
Fset_buffer (w->buffer);
}
else
Fdelete_window (window);
}
break;
case GET_LARGEST_WINDOW:
{
if (MINI_WINDOW_P (w) || (NILP (obj) && !NILP (w->dedicated)))
break;
if (NILP (best_window))
best_window = window;
else
{
struct window *b = XWINDOW (best_window);
if (XFASTINT (w->total_lines) * XFASTINT (w->total_cols)
> XFASTINT (b->total_lines) * XFASTINT (b->total_cols))
best_window = window;
}
}
break;
case UNSHOW_BUFFER:
if (EQ (w->buffer, obj))
{
Lisp_Object buffer;
struct frame *f = XFRAME (w->frame);
buffer = Fother_buffer (obj, Qnil, w->frame);
if (EQ (window, FRAME_ROOT_WINDOW (f))
&& !NILP (w->dedicated)
&& other_visible_frames (f))
{
while (CONSP (XCDR (windows))
&& EQ (XWINDOW (XCAR (windows))->frame,
XWINDOW (XCAR (XCDR (windows)))->frame))
windows = XCDR (windows);
Fdelete_frame (w->frame, Qnil);
}
else if (!NILP (w->dedicated) && !NILP (w->parent))
{
Lisp_Object window;
XSETWINDOW (window, w);
Fdelete_window (window);
}
else
{
w->dedicated = Qnil;
Fset_window_buffer (window, buffer, Qnil);
if (EQ (window, selected_window))
Fset_buffer (w->buffer);
}
}
break;
case REDISPLAY_BUFFER_WINDOWS:
if (EQ (w->buffer, obj))
{
mark_window_display_accurate (window, 0);
w->update_mode_line = Qt;
XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
++update_mode_lines;
best_window = window;
}
break;
case CHECK_ALL_WINDOWS:
if (! NILP (w->buffer)
&& NILP (XBUFFER (w->buffer)->name))
abort ();
break;
case WINDOW_LOOP_UNUSED:
break;
}
}
UNGCPRO;
return best_window;
}
void
check_all_windows ()
{
window_loop (CHECK_ALL_WINDOWS, Qnil, 1, Qt);
}
DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 2, 0,
doc: )
(frame, dedicated)
Lisp_Object frame, dedicated;
{
register Lisp_Object w;
w = window_loop (GET_LRU_WINDOW,
NILP (dedicated) ? make_number (1) : make_number (3),
0, frame);
if (!NILP (w) && !EQ (w, selected_window))
return w;
return window_loop (GET_LRU_WINDOW,
NILP (dedicated) ? make_number (0) : make_number (2),
0, frame);
}
DEFUN ("get-largest-window", Fget_largest_window, Sget_largest_window, 0, 2, 0,
doc: )
(frame, dedicated)
Lisp_Object frame, dedicated;
{
return window_loop (GET_LARGEST_WINDOW, dedicated, 0,
frame);
}
DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
doc: )
(buffer, frame)
Lisp_Object buffer, frame;
{
buffer = Fget_buffer (buffer);
if (BUFFERP (buffer))
return window_loop (GET_BUFFER_WINDOW, buffer, 1, frame);
else
return Qnil;
}
DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
0, 1, "",
doc: )
(window)
Lisp_Object window;
{
struct window *w;
int startpos;
int top, new_top;
if (NILP (window))
window = selected_window;
else
CHECK_LIVE_WINDOW (window);
w = XWINDOW (window);
startpos = marker_position (w->start);
top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
if (MINI_WINDOW_P (w) && top > 0)
error ("Can't expand minibuffer to full frame");
window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
new_top = WINDOW_TOP_EDGE_LINE (w) - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
if (new_top != top
&& startpos >= BUF_BEGV (XBUFFER (w->buffer))
&& startpos <= BUF_ZV (XBUFFER (w->buffer)))
{
struct position pos;
struct buffer *obuf = current_buffer;
Fset_buffer (w->buffer);
pos = *vmotion (startpos, -top, w);
set_marker_both (w->start, w->buffer, pos.bufpos, pos.bytepos);
w->window_end_valid = Qnil;
w->start_at_line_beg = ((pos.bytepos == BEGV_BYTE
|| FETCH_BYTE (pos.bytepos - 1) == '\n') ? Qt
: Qnil);
w->optional_new_start = Qt;
set_buffer_internal (obuf);
}
return Qnil;
}
DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
1, 2, "bDelete windows on (buffer): ",
doc: )
(buffer, frame)
Lisp_Object buffer, frame;
{
if (NILP (frame))
frame = Qt;
else if (EQ (frame, Qt))
frame = Qnil;
if (!NILP (buffer))
{
buffer = Fget_buffer (buffer);
CHECK_BUFFER (buffer);
window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
}
return Qnil;
}
DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows,
Sreplace_buffer_in_windows,
1, 1, "bReplace buffer in windows: ",
doc: )
(buffer)
Lisp_Object buffer;
{
if (!NILP (buffer))
{
buffer = Fget_buffer (buffer);
CHECK_BUFFER (buffer);
window_loop (UNSHOW_BUFFER, buffer, 0, Qt);
}
return Qnil;
}
void
replace_buffer_in_all_windows (buffer)
Lisp_Object buffer;
{
#ifdef MULTI_KBOARD
Lisp_Object tail, frame;
FOR_EACH_FRAME (tail, frame)
window_loop (UNSHOW_BUFFER, buffer, 1, frame);
#else
window_loop (UNSHOW_BUFFER, buffer, 1, Qt);
#endif
}
#define MIN_SAFE_WINDOW_WIDTH (2)
#define MIN_SAFE_WINDOW_HEIGHT (1)
static void
check_min_window_sizes ()
{
if (window_min_width < MIN_SAFE_WINDOW_WIDTH)
window_min_width = MIN_SAFE_WINDOW_WIDTH;
if (window_min_height < MIN_SAFE_WINDOW_HEIGHT)
window_min_height = MIN_SAFE_WINDOW_HEIGHT;
}
void
check_frame_size (frame, rows, cols)
FRAME_PTR frame;
int *rows, *cols;
{
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 (*rows < min_height)
*rows = min_height;
if (*cols < MIN_SAFE_WINDOW_WIDTH)
*cols = MIN_SAFE_WINDOW_WIDTH;
}
static int
window_fixed_size_p (w, width_p, check_siblings_p)
struct window *w;
int width_p, check_siblings_p;
{
int fixed_p;
struct window *c;
if (!NILP (w->hchild))
{
c = XWINDOW (w->hchild);
if (width_p)
{
while (c && window_fixed_size_p (c, width_p, 0))
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
fixed_p = c == NULL;
}
else
{
while (c && !window_fixed_size_p (c, width_p, 0))
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
fixed_p = c != NULL;
}
}
else if (!NILP (w->vchild))
{
c = XWINDOW (w->vchild);
if (width_p)
{
while (c && !window_fixed_size_p (c, width_p, 0))
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
fixed_p = c != NULL;
}
else
{
while (c && window_fixed_size_p (c, width_p, 0))
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
fixed_p = c == NULL;
}
}
else if (BUFFERP (w->buffer))
{
struct buffer *old = current_buffer;
Lisp_Object val;
current_buffer = XBUFFER (w->buffer);
val = find_symbol_value (Qwindow_size_fixed);
current_buffer = old;
fixed_p = 0;
if (!EQ (val, Qunbound))
{
fixed_p = !NILP (val);
if (fixed_p
&& ((EQ (val, Qheight) && width_p)
|| (EQ (val, Qwidth) && !width_p)))
fixed_p = 0;
}
if (!fixed_p && check_siblings_p && WINDOWP (w->parent))
{
Lisp_Object child;
for (child = w->prev; !NILP (child); child = XWINDOW (child)->prev)
if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
break;
if (NILP (child))
for (child = w->next; !NILP (child); child = XWINDOW (child)->next)
if (!window_fixed_size_p (XWINDOW (child), width_p, 0))
break;
if (NILP (child))
fixed_p = 1;
}
}
else
fixed_p = 1;
return fixed_p;
}
static int
window_min_size_1 (w, width_p)
struct window *w;
int width_p;
{
struct window *c;
int size;
if (!NILP (w->hchild))
{
c = XWINDOW (w->hchild);
size = 0;
if (width_p)
{
while (c)
{
size += window_min_size_1 (c, width_p);
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
}
}
else
{
while (c)
{
int min_size = window_min_size_1 (c, width_p);
size = max (min_size, size);
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
}
}
}
else if (!NILP (w->vchild))
{
c = XWINDOW (w->vchild);
size = 0;
if (width_p)
{
while (c)
{
int min_size = window_min_size_1 (c, width_p);
size = max (min_size, size);
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
}
}
else
{
while (c)
{
size += window_min_size_1 (c, width_p);
c = WINDOWP (c->next) ? XWINDOW (c->next) : NULL;
}
}
}
else
{
if (width_p)
size = max (window_min_width,
(MIN_SAFE_WINDOW_WIDTH
+ WINDOW_FRINGE_COLS (w)
+ WINDOW_SCROLL_BAR_COLS (w)));
else
{
if (MINI_WINDOW_P (w)
|| (!WINDOW_WANTS_MODELINE_P (w)
&& !WINDOW_WANTS_HEADER_LINE_P (w)))
size = 1;
else
size = window_min_height;
}
}
return size;
}
static int
window_min_size (w, width_p, ignore_fixed_p, fixed)
struct window *w;
int width_p, ignore_fixed_p, *fixed;
{
int size, fixed_p;
if (ignore_fixed_p)
fixed_p = 0;
else
fixed_p = window_fixed_size_p (w, width_p, 1);
if (fixed)
*fixed = fixed_p;
if (fixed_p)
size = width_p ? XFASTINT (w->total_cols) : XFASTINT (w->total_lines);
else
size = window_min_size_1 (w, width_p);
return size;
}
static int
adjust_window_margins (w)
struct window *w;
{
int box_cols = (WINDOW_TOTAL_COLS (w)
- WINDOW_FRINGE_COLS (w)
- WINDOW_SCROLL_BAR_COLS (w));
int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
+ WINDOW_RIGHT_MARGIN_COLS (w));
if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
return 1;
if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
return 0;
margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
{
if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
w->left_margin_cols = w->right_margin_cols
= make_number (margin_cols/2);
else
w->right_margin_cols = make_number (margin_cols);
}
else
w->left_margin_cols = make_number (margin_cols);
return 1;
}
static int *
shrink_windows (total, size, nchildren, shrinkable,
min_size, resize_fixed_p, forward, width_p)
int total, size, nchildren, shrinkable, min_size;
int resize_fixed_p, width_p;
Lisp_Object forward;
{
int available_resize = 0;
int *new_sizes;
struct window *c;
Lisp_Object child;
int smallest = total;
int total_removed = 0;
int total_shrink = total - size;
int i;
new_sizes = xmalloc (sizeof (*new_sizes) * nchildren);
for (i = 0, child = forward; !NILP (child); child = c->next, ++i)
{
int child_size;
c = XWINDOW (child);
child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
if (! resize_fixed_p && window_fixed_size_p (c, width_p, 0))
new_sizes[i] = -1;
else
{
new_sizes[i] = child_size;
if (child_size > min_size)
available_resize += child_size - min_size;
}
}
while (shrinkable > 1 && size + available_resize < total)
{
for (i = 0; i < nchildren; ++i)
if (new_sizes[i] > 0 && smallest > new_sizes[i])
smallest = new_sizes[i];
for (i = 0; i < nchildren; ++i)
if (new_sizes[i] == smallest)
{
new_sizes[i] = 0;
if (smallest > min_size)
available_resize -= smallest - min_size;
available_resize += smallest;
--shrinkable;
total_removed += smallest;
smallest = total;
break;
}
}
for (i = 0; i < nchildren; ++i)
{
if (new_sizes[i] > min_size)
{
int to_shrink = total_shrink*new_sizes[i]/total;
if (new_sizes[i] - to_shrink < min_size)
to_shrink = new_sizes[i] - min_size;
new_sizes[i] -= to_shrink;
total_removed += to_shrink;
}
}
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)
{
--new_sizes[i];
++total_removed;
break;
}
if (nonzero_sizes == 1)
break;
}
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;
}
static void
size_window (window, size, width_p, nodelete_p, first_only, last_only)
Lisp_Object window;
int size, width_p, nodelete_p;
int first_only, last_only;
{
struct window *w = XWINDOW (window);
struct window *c;
Lisp_Object child, *forward, *sideward;
int old_size, min_size, safe_min_size;
if (nodelete_p == 2)
nodelete_p = 0;
check_min_window_sizes ();
size = max (0, size);
if (width_p)
{
old_size = WINDOW_TOTAL_COLS (w);
min_size = window_min_width;
safe_min_size = (MIN_SAFE_WINDOW_WIDTH
+ WINDOW_FRINGE_COLS (w)
+ WINDOW_SCROLL_BAR_COLS (w));
}
else
{
old_size = XINT (w->total_lines);
min_size = window_min_height;
safe_min_size = MIN_SAFE_WINDOW_HEIGHT;
}
if (old_size < min_size && nodelete_p != 2)
w->too_small_ok = Qt;
if (nodelete_p != 1 && !NILP (w->parent))
{
if (!MINI_WINDOW_P (w) && !NILP (w->too_small_ok))
min_size = width_p ? MIN_SAFE_WINDOW_WIDTH : MIN_SAFE_WINDOW_HEIGHT;
if (min_size < safe_min_size)
min_size = safe_min_size;
if (size < min_size)
{
delete_window (window);
return;
}
}
w->last_modified = make_number (0);
w->last_overlay_modified = make_number (0);
windows_or_buffers_changed++;
FRAME_WINDOW_SIZES_CHANGED (XFRAME (w->frame)) = 1;
if (width_p)
{
sideward = &w->vchild;
forward = &w->hchild;
w->total_cols = make_number (size);
adjust_window_margins (w);
}
else
{
sideward = &w->hchild;
forward = &w->vchild;
w->total_lines = make_number (size);
w->orig_total_lines = Qnil;
}
if (!NILP (*sideward))
{
for (child = *sideward; !NILP (child); child = c->next)
{
c = XWINDOW (child);
if (width_p)
c->left_col = w->left_col;
else
c->top_line = w->top_line;
size_window (child, size, width_p, nodelete_p,
first_only, last_only);
}
}
else if (!NILP (*forward) && last_only)
{
Lisp_Object last_child;
int child_size;
for (child = *forward; !NILP (child); child = c->next)
{
c = XWINDOW (child);
last_child = child;
}
child_size = XINT (width_p ? c->total_cols : c->total_lines);
size_window (last_child,
size - old_size + child_size,
width_p, nodelete_p, first_only, last_only);
}
else if (!NILP (*forward) && first_only)
{
int child_size;
child = *forward;
c = XWINDOW (child);
if (width_p)
c->left_col = w->left_col;
else
c->top_line = w->top_line;
child_size = XINT (width_p ? c->total_cols : c->total_lines);
size_window (child,
size - old_size + child_size,
width_p, nodelete_p, first_only, last_only);
}
else if (!NILP (*forward))
{
int fixed_size, each, extra, n;
int resize_fixed_p, nfixed;
int last_pos, first_pos, nchildren, total;
int *new_sizes = NULL;
fixed_size = nchildren = nfixed = total = 0;
for (child = *forward; !NILP (child); child = c->next, ++nchildren)
{
int child_size;
c = XWINDOW (child);
child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
total += child_size;
if (window_fixed_size_p (c, width_p, 0))
{
fixed_size += child_size;
++nfixed;
}
}
resize_fixed_p = nfixed == nchildren || size < fixed_size;
n = resize_fixed_p ? nchildren : nchildren - nfixed;
if (size < total && n > 1)
new_sizes = shrink_windows (total, size, nchildren, n, min_size,
resize_fixed_p, *forward, width_p);
else
{
each = (size - total) / n;
extra = (size - total) - n * each;
}
first_pos = width_p ? XINT (w->left_col) : XINT (w->top_line);
last_pos = first_pos;
for (n = 0, child = *forward; !NILP (child); child = c->next, ++n)
{
int new_size, old_size;
c = XWINDOW (child);
old_size = width_p ? XFASTINT (c->total_cols) : XFASTINT (c->total_lines);
new_size = old_size;
if (width_p)
c->left_col = make_number (last_pos);
else
c->top_line = make_number (last_pos);
if (resize_fixed_p || !window_fixed_size_p (c, width_p, 0))
{
new_size = new_sizes ? new_sizes[n] : old_size + each + extra;
extra = 0;
}
size_window (child, new_size, width_p, 1, first_only, last_only);
last_pos += new_size;
}
if (new_sizes) xfree (new_sizes);
xassert (size == last_pos - first_pos);
if (!nodelete_p)
for (child = *forward; !NILP (child); child = c->next)
{
int child_size;
c = XWINDOW (child);
child_size = width_p ? XINT (c->total_cols) : XINT (c->total_lines);
size_window (child, child_size, width_p, 2, first_only, last_only);
}
}
}
void
set_window_height (window, height, nodelete)
Lisp_Object window;
int height;
int nodelete;
{
size_window (window, height, 0, nodelete, 0, 0);
}
void
set_window_width (window, width, nodelete)
Lisp_Object window;
int width;
int nodelete;
{
size_window (window, width, 1, nodelete, 0, 0);
}
void
change_window_heights (window, n)
Lisp_Object window;
int n;
{
struct window *w = XWINDOW (window);
XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n);
XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n);
if (INTEGERP (w->orig_top_line))
XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n);
if (INTEGERP (w->orig_total_lines))
XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n);
if (!NILP (w->vchild))
change_window_heights (w->vchild, n);
for (window = w->hchild; !NILP (window); window = w->next)
{
w = XWINDOW (window);
change_window_heights (window, n);
}
}
int window_select_count;
Lisp_Object
Fset_window_buffer_unwind (obuf)
Lisp_Object obuf;
{
Fset_buffer (obuf);
return Qnil;
}
EXFUN (Fset_window_fringes, 4);
EXFUN (Fset_window_scroll_bars, 4);
void
set_window_buffer (window, buffer, run_hooks_p, keep_margins_p)
Lisp_Object window, buffer;
int run_hooks_p, keep_margins_p;
{
struct window *w = XWINDOW (window);
struct buffer *b = XBUFFER (buffer);
int count = SPECPDL_INDEX ();
w->buffer = buffer;
if (EQ (window, selected_window))
b->last_selected_window = window;
b->display_error_modiff = 0;
if (INTEGERP (b->display_count))
XSETINT (b->display_count, XINT (b->display_count) + 1);
b->display_time = Fcurrent_time ();
XSETFASTINT (w->window_end_pos, 0);
XSETFASTINT (w->window_end_vpos, 0);
bzero (&w->last_cursor, sizeof w->last_cursor);
w->window_end_valid = Qnil;
w->hscroll = w->min_hscroll = make_number (0);
w->vscroll = 0;
set_marker_both (w->pointm, buffer, BUF_PT (b), BUF_PT_BYTE (b));
set_marker_restricted (w->start,
make_number (b->last_window_start),
buffer);
w->start_at_line_beg = Qnil;
w->force_start = Qnil;
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
windows_or_buffers_changed++;
if (EQ (window, selected_window))
Fset_buffer (buffer);
else if (window_initialized)
{
record_unwind_protect (Fset_window_buffer_unwind, Fcurrent_buffer ());
Fset_buffer (buffer);
}
if (!keep_margins_p)
{
Lisp_Object save_left = w->left_margin_cols;
Lisp_Object save_right = w->right_margin_cols;
w->left_margin_cols = w->right_margin_cols = Qnil;
Fset_window_fringes (window,
b->left_fringe_width, b->right_fringe_width,
b->fringes_outside_margins);
Fset_window_scroll_bars (window,
b->scroll_bar_width,
b->vertical_scroll_bar_type, Qnil);
w->left_margin_cols = save_left;
w->right_margin_cols = save_right;
Fset_window_margins (window,
b->left_margin_cols, b->right_margin_cols);
}
if (run_hooks_p)
{
if (! NILP (Vwindow_scroll_functions))
run_hook_with_args_2 (Qwindow_scroll_functions, window,
Fmarker_position (w->start));
if (! NILP (Vwindow_configuration_change_hook)
&& ! NILP (Vrun_hooks))
call1 (Vrun_hooks, Qwindow_configuration_change_hook);
}
unbind_to (count, Qnil);
}
DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
doc: )
(window, buffer, keep_margins)
register Lisp_Object window, buffer, keep_margins;
{
register Lisp_Object tem;
register struct window *w = decode_window (window);
XSETWINDOW (window, w);
buffer = Fget_buffer (buffer);
CHECK_BUFFER (buffer);
if (NILP (XBUFFER (buffer)->name))
error ("Attempt to display deleted buffer");
tem = w->buffer;
if (NILP (tem))
error ("Window is deleted");
else if (! EQ (tem, Qt))
{
if (!NILP (w->dedicated) && !EQ (tem, buffer))
error ("Window is dedicated to `%s'",
SDATA (XBUFFER (tem)->name));
unshow_buffer (w);
}
set_window_buffer (window, buffer, 1, !NILP (keep_margins));
return Qnil;
}
DEFUN ("select-window", Fselect_window, Sselect_window, 1, 2, 0,
doc: )
(window, norecord)
register Lisp_Object window, norecord;
{
register struct window *w;
register struct window *ow;
struct frame *sf;
CHECK_LIVE_WINDOW (window);
w = XWINDOW (window);
w->frozen_window_start_p = 0;
++window_select_count;
XSETFASTINT (w->use_time, window_select_count);
if (EQ (window, selected_window))
return window;
if (!NILP (selected_window))
{
ow = XWINDOW (selected_window);
if (! NILP (ow->buffer))
set_marker_both (ow->pointm, ow->buffer,
BUF_PT (XBUFFER (ow->buffer)),
BUF_PT_BYTE (XBUFFER (ow->buffer)));
}
selected_window = window;
sf = SELECTED_FRAME ();
if (XFRAME (WINDOW_FRAME (w)) != sf)
{
XFRAME (WINDOW_FRAME (w))->selected_window = window;
Fselect_frame (WINDOW_FRAME (w));
}
else
sf->selected_window = window;
if (NILP (norecord))
record_buffer (w->buffer);
Fset_buffer (w->buffer);
XBUFFER (w->buffer)->last_selected_window = window;
{
register int new_point = marker_position (w->pointm);
if (new_point < BEGV)
SET_PT (BEGV);
else if (new_point > ZV)
SET_PT (ZV);
else
SET_PT (new_point);
}
windows_or_buffers_changed++;
return window;
}
static Lisp_Object
select_window_norecord (window)
Lisp_Object window;
{
return Fselect_window (window, Qt);
}
static Lisp_Object
display_buffer_1 (window)
Lisp_Object window;
{
Lisp_Object frame = XWINDOW (window)->frame;
FRAME_PTR f = XFRAME (frame);
FRAME_SAMPLE_VISIBILITY (f);
if (EQ (frame, selected_frame))
;
else if (minibuf_level > 0
&& MINI_WINDOW_P (XWINDOW (selected_window))
&& WINDOW_LIVE_P (minibuf_selected_window)
&& EQ (frame, WINDOW_FRAME (XWINDOW (minibuf_selected_window))))
;
else
{
if (FRAME_ICONIFIED_P (f))
Fmake_frame_visible (frame);
else if (FRAME_VISIBLE_P (f))
Fraise_frame (frame);
}
return window;
}
DEFUN ("special-display-p", Fspecial_display_p, Sspecial_display_p, 1, 1, 0,
doc: )
(buffer_name)
Lisp_Object buffer_name;
{
Lisp_Object tem;
CHECK_STRING (buffer_name);
tem = Fmember (buffer_name, Vspecial_display_buffer_names);
if (!NILP (tem))
return Qt;
tem = Fassoc (buffer_name, Vspecial_display_buffer_names);
if (!NILP (tem))
return XCDR (tem);
for (tem = Vspecial_display_regexps; CONSP (tem); tem = XCDR (tem))
{
Lisp_Object car = XCAR (tem);
if (STRINGP (car)
&& fast_string_match (car, buffer_name) >= 0)
return Qt;
else if (CONSP (car)
&& STRINGP (XCAR (car))
&& fast_string_match (XCAR (car), buffer_name) >= 0)
return XCDR (car);
}
return Qnil;
}
DEFUN ("same-window-p", Fsame_window_p, Ssame_window_p, 1, 1, 0,
doc: )
(buffer_name)
Lisp_Object buffer_name;
{
Lisp_Object tem;
CHECK_STRING (buffer_name);
tem = Fmember (buffer_name, Vsame_window_buffer_names);
if (!NILP (tem))
return Qt;
tem = Fassoc (buffer_name, Vsame_window_buffer_names);
if (!NILP (tem))
return Qt;
for (tem = Vsame_window_regexps; CONSP (tem); tem = XCDR (tem))
{
Lisp_Object car = XCAR (tem);
if (STRINGP (car)
&& fast_string_match (car, buffer_name) >= 0)
return Qt;
else if (CONSP (car)
&& STRINGP (XCAR (car))
&& fast_string_match (XCAR (car), buffer_name) >= 0)
return Qt;
}
return Qnil;
}
DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 3,
"BDisplay buffer: \nP",
doc: )
(buffer, not_this_window, frame)
register Lisp_Object buffer, not_this_window, frame;
{
register Lisp_Object window, tem, swp;
struct frame *f;
swp = Qnil;
buffer = Fget_buffer (buffer);
CHECK_BUFFER (buffer);
if (!NILP (Vdisplay_buffer_function))
return call2 (Vdisplay_buffer_function, buffer, not_this_window);
if (NILP (not_this_window)
&& XBUFFER (XWINDOW (selected_window)->buffer) == XBUFFER (buffer))
return display_buffer_1 (selected_window);
if (NILP (not_this_window))
{
swp = Fsame_window_p (XBUFFER (buffer)->name);
if (!NILP (swp) && !no_switch_window (selected_window))
{
Fswitch_to_buffer (buffer, Qnil);
return display_buffer_1 (selected_window);
}
}
if (! NILP (frame))
tem = frame;
else if (pop_up_frames
|| display_buffer_reuse_frames
|| last_nonminibuf_frame == 0)
XSETFASTINT (tem, 0);
else
XSETFRAME (tem, last_nonminibuf_frame);
window = Fget_buffer_window (buffer, tem);
if (!NILP (window)
&& (NILP (not_this_window) || !EQ (window, selected_window)))
return display_buffer_1 (window);
if (!NILP (Vspecial_display_function) && NILP (swp))
{
tem = Fspecial_display_p (XBUFFER (buffer)->name);
if (EQ (tem, Qt))
return call1 (Vspecial_display_function, buffer);
if (CONSP (tem))
return call2 (Vspecial_display_function, buffer, tem);
}
if (pop_up_frames || last_nonminibuf_frame == 0)
{
window = Fframe_selected_window (call0 (Vpop_up_frame_function));
Fset_window_buffer (window, buffer, Qnil);
return display_buffer_1 (window);
}
f = SELECTED_FRAME ();
if (pop_up_windows
|| FRAME_MINIBUF_ONLY_P (f)
|| !NILP (XWINDOW (FRAME_ROOT_WINDOW (f))->dedicated))
{
Lisp_Object frames;
frames = Qnil;
if (FRAME_MINIBUF_ONLY_P (f))
XSETFRAME (frames, last_nonminibuf_frame);
if (split_height_threshold < window_min_height << 1)
split_height_threshold = window_min_height << 1;
if (FRAME_NO_SPLIT_P (NILP (frames) ? f : last_nonminibuf_frame))
{
window = Fget_largest_window (Qvisible, Qt);
if (NILP (window))
window = Fget_largest_window (make_number (0), Qt);
#if 0
if (NILP (window))
window = Fget_largest_window (Qt, Qt);
#endif
}
else
window = Fget_largest_window (frames, Qt);
if (!NILP (window)
&& ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
&& window_height (window) >= split_height_threshold
&& WINDOW_FULL_WIDTH_P (XWINDOW (window)))
window = Fsplit_window (window, Qnil, Qnil);
else
{
Lisp_Object upper, lower, other;
window = Fget_lru_window (frames, Qt);
if (!NILP (window)
&& ! FRAME_NO_SPLIT_P (XFRAME (XWINDOW (window)->frame))
&& (EQ (window, selected_window)
|| EQ (XWINDOW (window)->parent, Qnil))
&& window_height (window) >= window_min_height << 1)
window = Fsplit_window (window, Qnil, Qnil);
else
window = Fget_lru_window (frames, Qnil);
if (NILP (window))
window = Fget_buffer_window (buffer, Qvisible);
if (NILP (window))
window = Fget_largest_window (Qvisible, Qnil);
if (NILP (window))
window = Fget_buffer_window (buffer, make_number (0));
if (NILP (window))
window = Fget_largest_window (make_number (0), Qnil);
#if 0
if (NILP (window))
window = Fget_buffer_window (buffer, Qt);
if (NILP (window))
window = Fget_largest_window (Qt, Qnil);
#endif
if (NILP (window))
window = Fframe_selected_window (call0 (Vpop_up_frame_function));
other = upper = lower = Qnil;
if (!NILP (XWINDOW (window)->prev))
other = upper = XWINDOW (window)->prev, lower = window;
if (!NILP (XWINDOW (window)->next))
other = lower = XWINDOW (window)->next, upper = window;
if (!NILP (other)
&& !NILP (Veven_window_heights)
&& !EQ (XWINDOW (other)->top_line, XWINDOW (window)->top_line)
&& (XFASTINT (XWINDOW (other)->total_lines)
> XFASTINT (XWINDOW (window)->total_lines)))
{
int total = (XFASTINT (XWINDOW (other)->total_lines)
+ XFASTINT (XWINDOW (window)->total_lines));
enlarge_window (upper,
total / 2 - XFASTINT (XWINDOW (upper)->total_lines),
0);
}
}
}
else
window = Fget_lru_window (Qnil, Qnil);
Fset_window_buffer (window, buffer, Qnil);
return display_buffer_1 (window);
}
DEFUN ("force-window-update", Fforce_window_update, Sforce_window_update,
0, 1, 0,
doc: )
(object)
Lisp_Object object;
{
if (NILP (object))
{
windows_or_buffers_changed++;
update_mode_lines++;
return Qt;
}
if (WINDOWP (object))
{
struct window *w = XWINDOW (object);
mark_window_display_accurate (object, 0);
w->update_mode_line = Qt;
if (BUFFERP (w->buffer))
XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
++update_mode_lines;
return Qt;
}
if (STRINGP (object))
object = Fget_buffer (object);
if (BUFFERP (object) && !NILP (XBUFFER (object)->name))
{
object = window_loop (REDISPLAY_BUFFER_WINDOWS, object, 0, Qvisible);
return NILP (object) ? Qnil : Qt;
}
return Qnil;
}
void
temp_output_buffer_show (buf)
register Lisp_Object buf;
{
register struct buffer *old = current_buffer;
register Lisp_Object window;
register struct window *w;
XBUFFER (buf)->directory = current_buffer->directory;
Fset_buffer (buf);
BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
BEGV = BEG;
ZV = Z;
SET_PT (BEG);
#if 0
XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
#endif
set_buffer_internal (old);
if (!NILP (Vtemp_buffer_show_function))
call1 (Vtemp_buffer_show_function, buf);
else
{
window = Fdisplay_buffer (buf, Qnil, Qnil);
if (!EQ (XWINDOW (window)->frame, selected_frame))
Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window)));
Vminibuf_scroll_window = window;
w = XWINDOW (window);
XSETFASTINT (w->hscroll, 0);
XSETFASTINT (w->min_hscroll, 0);
set_marker_restricted_both (w->start, buf, BEG, BEG);
set_marker_restricted_both (w->pointm, buf, BEG, BEG);
if (!NILP (Vrun_hooks)
&& !NILP (Fboundp (Qtemp_buffer_show_hook))
&& !NILP (Fsymbol_value (Qtemp_buffer_show_hook)))
{
int count = SPECPDL_INDEX ();
Lisp_Object prev_window, prev_buffer;
prev_window = selected_window;
XSETBUFFER (prev_buffer, old);
record_unwind_protect (Fset_buffer, prev_buffer);
record_unwind_protect (select_window_norecord, prev_window);
Fselect_window (window, Qt);
Fset_buffer (w->buffer);
call1 (Vrun_hooks, Qtemp_buffer_show_hook);
unbind_to (count, Qnil);
}
}
}
static void
make_dummy_parent (window)
Lisp_Object window;
{
Lisp_Object new;
register struct window *o, *p;
int i;
o = XWINDOW (window);
p = allocate_window ();
for (i = 0; i < VECSIZE (struct window); ++i)
((struct Lisp_Vector *) p)->contents[i]
= ((struct Lisp_Vector *)o)->contents[i];
XSETWINDOW (new, p);
++sequence_number;
XSETFASTINT (p->sequence_number, sequence_number);
replace_window (window, new);
o->next = Qnil;
o->prev = Qnil;
o->vchild = Qnil;
o->hchild = Qnil;
o->parent = new;
p->start = Qnil;
p->pointm = Qnil;
p->buffer = Qnil;
}
DEFUN ("split-window", Fsplit_window, Ssplit_window, 0, 3, "",
doc: )
(window, size, horflag)
Lisp_Object window, size, horflag;
{
register Lisp_Object new;
register struct window *o, *p;
FRAME_PTR fo;
register int size_int;
if (NILP (window))
window = selected_window;
else
CHECK_LIVE_WINDOW (window);
o = XWINDOW (window);
fo = XFRAME (WINDOW_FRAME (o));
if (NILP (size))
{
if (!NILP (horflag))
size_int = (XFASTINT (o->total_cols) + 1) >> 1;
else
size_int = XFASTINT (o->total_lines) >> 1;
}
else
{
CHECK_NUMBER (size);
size_int = XINT (size);
}
if (MINI_WINDOW_P (o))
error ("Attempt to split minibuffer window");
else if (window_fixed_size_p (o, !NILP (horflag), 0))
error ("Attempt to split fixed-size window");
check_min_window_sizes ();
if (NILP (horflag))
{
if (size_int < window_min_height)
error ("Window height %d too small (after splitting)", size_int);
if (size_int + window_min_height > XFASTINT (o->total_lines))
error ("Window height %d too small (after splitting)",
XFASTINT (o->total_lines) - size_int);
if (NILP (o->parent)
|| NILP (XWINDOW (o->parent)->vchild))
{
make_dummy_parent (window);
new = o->parent;
XWINDOW (new)->vchild = window;
}
}
else
{
if (size_int < window_min_width)
error ("Window width %d too small (after splitting)", size_int);
if (size_int + window_min_width > XFASTINT (o->total_cols))
error ("Window width %d too small (after splitting)",
XFASTINT (o->total_cols) - size_int);
if (NILP (o->parent)
|| NILP (XWINDOW (o->parent)->hchild))
{
make_dummy_parent (window);
new = o->parent;
XWINDOW (new)->hchild = window;
}
}
windows_or_buffers_changed++;
FRAME_WINDOW_SIZES_CHANGED (fo) = 1;
new = make_window ();
p = XWINDOW (new);
p->frame = o->frame;
p->next = o->next;
if (!NILP (p->next))
XWINDOW (p->next)->prev = new;
p->prev = window;
o->next = new;
p->parent = o->parent;
p->buffer = Qt;
p->window_end_valid = Qnil;
bzero (&p->last_cursor, sizeof p->last_cursor);
p->left_margin_cols = o->left_margin_cols;
p->right_margin_cols = o->right_margin_cols;
p->left_fringe_width = o->left_fringe_width;
p->right_fringe_width = o->right_fringe_width;
p->fringes_outside_margins = o->fringes_outside_margins;
p->scroll_bar_width = o->scroll_bar_width;
p->vertical_scroll_bar_type = o->vertical_scroll_bar_type;
if (!NILP (horflag))
{
p->total_lines = o->total_lines;
p->top_line = o->top_line;
XSETFASTINT (p->total_cols, XFASTINT (o->total_cols) - size_int);
XSETFASTINT (o->total_cols, size_int);
XSETFASTINT (p->left_col, XFASTINT (o->left_col) + size_int);
adjust_window_margins (p);
adjust_window_margins (o);
}
else
{
p->left_col = o->left_col;
p->total_cols = o->total_cols;
XSETFASTINT (p->total_lines, XFASTINT (o->total_lines) - size_int);
XSETFASTINT (o->total_lines, size_int);
XSETFASTINT (p->top_line, XFASTINT (o->top_line) + size_int);
}
adjust_glyphs (fo);
Fset_window_buffer (new, o->buffer, Qt);
return new;
}
DEFUN ("enlarge-window", Fenlarge_window, Senlarge_window, 1, 2, "p",
doc: )
(arg, horizontal)
Lisp_Object arg, horizontal;
{
CHECK_NUMBER (arg);
enlarge_window (selected_window, XINT (arg), !NILP (horizontal));
if (! NILP (Vwindow_configuration_change_hook))
call1 (Vrun_hooks, Qwindow_configuration_change_hook);
return Qnil;
}
DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
doc: )
(arg, side)
Lisp_Object arg, side;
{
CHECK_NUMBER (arg);
enlarge_window (selected_window, -XINT (arg), !NILP (side));
if (! NILP (Vwindow_configuration_change_hook))
call1 (Vrun_hooks, Qwindow_configuration_change_hook);
return Qnil;
}
int
window_height (window)
Lisp_Object window;
{
register struct window *p = XWINDOW (window);
return WINDOW_TOTAL_LINES (p);
}
int
window_width (window)
Lisp_Object window;
{
register struct window *p = XWINDOW (window);
return WINDOW_TOTAL_COLS (p);
}
#define CURBEG(w) \
*(horiz_flag ? &(XWINDOW (w)->left_col) : &(XWINDOW (w)->top_line))
#define CURSIZE(w) \
*(horiz_flag ? &(XWINDOW (w)->total_cols) : &(XWINDOW (w)->total_lines))
static void
enlarge_window (window, delta, horiz_flag)
Lisp_Object window;
int delta, horiz_flag;
{
Lisp_Object parent, next, prev;
struct window *p;
Lisp_Object *sizep;
int maximum;
int (*sizefun) P_ ((Lisp_Object))
= horiz_flag ? window_width : window_height;
void (*setsizefun) P_ ((Lisp_Object, int, int))
= (horiz_flag ? set_window_width : set_window_height);
check_min_window_sizes ();
if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
error ("Window is not resizable");
while (1)
{
p = XWINDOW (window);
parent = p->parent;
if (NILP (parent))
{
if (horiz_flag)
error ("No other window to side of this one");
break;
}
if (horiz_flag
? !NILP (XWINDOW (parent)->hchild)
: !NILP (XWINDOW (parent)->vchild))
break;
window = parent;
}
sizep = &CURSIZE (window);
{
register int maxdelta;
maxdelta = (!NILP (parent) ? (*sizefun) (parent) - XINT (*sizep)
: !NILP (p->next) ? ((*sizefun) (p->next)
- window_min_size (XWINDOW (p->next),
horiz_flag, 0, 0))
: !NILP (p->prev) ? ((*sizefun) (p->prev)
- window_min_size (XWINDOW (p->prev),
horiz_flag, 0, 0))
: (delta = 0));
if (delta > maxdelta)
delta = maxdelta;
}
if (XINT (*sizep) + delta < window_min_size (XWINDOW (window), horiz_flag, 0, 0))
{
delete_window (window);
return;
}
if (delta == 0)
return;
maximum = 0;
for (next = p->next; ! NILP (next); next = XWINDOW (next)->next)
maximum += (*sizefun) (next) - window_min_size (XWINDOW (next),
horiz_flag, 0, 0);
for (prev = p->prev; ! NILP (prev); prev = XWINDOW (prev)->prev)
maximum += (*sizefun) (prev) - window_min_size (XWINDOW (prev),
horiz_flag, 0, 0);
if (delta <= maximum)
{
Lisp_Object first_unaffected;
Lisp_Object first_affected;
int fixed_p;
next = p->next;
prev = p->prev;
first_affected = window;
while (delta != 0
&& (!NILP (next) || !NILP (prev)))
{
if (! NILP (next))
{
int this_one = ((*sizefun) (next)
- window_min_size (XWINDOW (next),
horiz_flag, 0, &fixed_p));
if (!fixed_p)
{
if (this_one > delta)
this_one = delta;
(*setsizefun) (next, (*sizefun) (next) - this_one, 0);
(*setsizefun) (window, XINT (*sizep) + this_one, 0);
delta -= this_one;
}
next = XWINDOW (next)->next;
}
if (delta == 0)
break;
if (! NILP (prev))
{
int this_one = ((*sizefun) (prev)
- window_min_size (XWINDOW (prev),
horiz_flag, 0, &fixed_p));
if (!fixed_p)
{
if (this_one > delta)
this_one = delta;
first_affected = prev;
(*setsizefun) (prev, (*sizefun) (prev) - this_one, 0);
(*setsizefun) (window, XINT (*sizep) + this_one, 0);
delta -= this_one;
}
prev = XWINDOW (prev)->prev;
}
}
xassert (delta == 0);
first_unaffected = next;
prev = first_affected;
for (next = XWINDOW (prev)->next; ! EQ (next, first_unaffected);
prev = next, next = XWINDOW (next)->next)
{
XSETINT (CURBEG (next), XINT (CURBEG (prev)) + (*sizefun) (prev));
(*setsizefun) (next, (*sizefun) (next), 0);
}
}
else
{
register int delta1;
register int opht = (*sizefun) (parent);
if (opht <= XINT (*sizep) + delta)
{
Lisp_Object start, tem, next;
start = XWINDOW (parent)->vchild;
if (NILP (start))
start = XWINDOW (parent)->hchild;
tem = XWINDOW (window)->next;
while (! NILP (tem))
{
next = XWINDOW (tem)->next;
delete_window (tem);
tem = next;
}
tem = start;
while (! EQ (tem, window))
{
next = XWINDOW (tem)->next;
delete_window (tem);
tem = next;
}
}
else
{
struct window *w = XWINDOW (window);
Lisp_Object s;
int n = 1;
for (s = w->next; !NILP (s); s = XWINDOW (s)->next)
if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
++n;
for (s = w->prev; !NILP (s); s = XWINDOW (s)->prev)
if (!window_fixed_size_p (XWINDOW (s), horiz_flag, 0))
++n;
delta1 = n * delta;
XSETINT (CURSIZE (parent), opht + delta1);
(*setsizefun) (window, XINT (*sizep) + delta1, 0);
(*setsizefun) (parent, opht, 0);
}
}
XSETFASTINT (p->last_modified, 0);
XSETFASTINT (p->last_overlay_modified, 0);
adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
}
static void
adjust_window_trailing_edge (window, delta, horiz_flag)
Lisp_Object window;
int delta, horiz_flag;
{
Lisp_Object parent, child;
struct window *p;
Lisp_Object old_config = Fcurrent_window_configuration (Qnil);
int delcount = window_deletion_count;
check_min_window_sizes ();
if (NILP (window))
window = Fselected_window ();
CHECK_WINDOW (window);
if (window_fixed_size_p (XWINDOW (window), horiz_flag, 1))
error ("Window is not resizable");
while (1)
{
Lisp_Object first_parallel = Qnil;
if (NILP (window))
{
Fset_window_configuration (old_config);
error ("Specified window edge is fixed");
}
p = XWINDOW (window);
parent = p->parent;
if (horiz_flag)
{
if (! NILP (parent) && !NILP (XWINDOW (parent)->vchild))
first_parallel = XWINDOW (parent)->vchild;
else if (NILP (parent) && !NILP (p->next))
{
first_parallel = window;
while (! NILP (XWINDOW (first_parallel)->prev))
first_parallel = XWINDOW (first_parallel)->prev;
}
}
else
{
if (! NILP (parent) && !NILP (XWINDOW (parent)->hchild))
first_parallel = XWINDOW (parent)->hchild;
}
if (NILP (XWINDOW (window)->next) && NILP (first_parallel)
&& NILP (parent))
{
Fset_window_configuration (old_config);
error ("Specified window edge is fixed");
}
if (XINT (CURSIZE (window)) + delta
< (horiz_flag ? window_min_width : window_min_height))
{
Fset_window_configuration (old_config);
error ("Cannot adjust window size as specified");
}
XSETFASTINT (p->last_modified, 0);
XSETFASTINT (p->last_overlay_modified, 0);
XSETINT (CURSIZE (window),
XINT (CURSIZE (window)) + delta);
if (NILP (first_parallel))
{
if (!NILP (p->next))
{
if (XINT (CURSIZE (p->next)) - delta <= 0)
{
Fset_window_configuration (old_config);
error ("Cannot adjust window size as specified");
}
XSETINT (CURBEG (p->next),
XINT (CURBEG (p->next)) + delta);
size_window (p->next, XINT (CURSIZE (p->next)) - delta,
horiz_flag, 0, 1, 0);
break;
}
}
else
for (child = first_parallel;
! NILP (child);
child = XWINDOW (child)->next)
if (! EQ (child, window))
size_window (child, XINT (CURSIZE (child)) + delta,
horiz_flag, 0, 0, 1);
window = parent;
}
if (delcount != window_deletion_count)
{
Fset_window_configuration (old_config);
error ("Cannot adjust window size as specified");
}
adjust_glyphs (XFRAME (WINDOW_FRAME (XWINDOW (window))));
}
#undef CURBEG
#undef CURSIZE
DEFUN ("adjust-window-trailing-edge", Fadjust_window_trailing_edge,
Sadjust_window_trailing_edge, 3, 3, 0,
doc: )
(window, delta, horizontal)
Lisp_Object window, delta, horizontal;
{
CHECK_NUMBER (delta);
adjust_window_trailing_edge (window, XINT (delta), !NILP (horizontal));
if (! NILP (Vwindow_configuration_change_hook))
call1 (Vrun_hooks, Qwindow_configuration_change_hook);
return Qnil;
}
static void shrink_window_lowest_first P_ ((struct window *, int));
enum save_restore_action
{
CHECK_ORIG_SIZES,
SAVE_ORIG_SIZES,
RESTORE_ORIG_SIZES
};
static int save_restore_orig_size P_ ((struct window *,
enum save_restore_action));
static void
shrink_window_lowest_first (w, height)
struct window *w;
int height;
{
struct window *c;
Lisp_Object child;
int old_height;
xassert (!MINI_WINDOW_P (w));
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
windows_or_buffers_changed++;
FRAME_WINDOW_SIZES_CHANGED (XFRAME (WINDOW_FRAME (w))) = 1;
old_height = XFASTINT (w->total_lines);
XSETFASTINT (w->total_lines, height);
if (!NILP (w->hchild))
{
for (child = w->hchild; !NILP (child); child = c->next)
{
c = XWINDOW (child);
c->top_line = w->top_line;
shrink_window_lowest_first (c, height);
}
}
else if (!NILP (w->vchild))
{
Lisp_Object last_child;
int delta = old_height - height;
int last_top;
last_child = Qnil;
for (child = w->vchild; !NILP (child); child = XWINDOW (child)->next)
last_child = child;
for (child = last_child; delta && !NILP (child); child = c->prev)
{
int this_one;
c = XWINDOW (child);
this_one = XFASTINT (c->total_lines) - MIN_SAFE_WINDOW_HEIGHT;
if (this_one > delta)
this_one = delta;
shrink_window_lowest_first (c, XFASTINT (c->total_lines) - this_one);
delta -= this_one;
}
last_top = XINT (w->top_line);
for (child = w->vchild; !NILP (child); child = c->next)
{
c = XWINDOW (child);
c->top_line = make_number (last_top);
shrink_window_lowest_first (c, XFASTINT (c->total_lines));
last_top += XFASTINT (c->total_lines);
}
}
}
static int
save_restore_orig_size (w, action)
struct window *w;
enum save_restore_action action;
{
int success_p = 1;
while (w)
{
if (!NILP (w->hchild))
{
if (!save_restore_orig_size (XWINDOW (w->hchild), action))
success_p = 0;
}
else if (!NILP (w->vchild))
{
if (!save_restore_orig_size (XWINDOW (w->vchild), action))
success_p = 0;
}
switch (action)
{
case CHECK_ORIG_SIZES:
if (!INTEGERP (w->orig_top_line) || !INTEGERP (w->orig_total_lines))
return 0;
break;
case SAVE_ORIG_SIZES:
w->orig_top_line = w->top_line;
w->orig_total_lines = w->total_lines;
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
break;
case RESTORE_ORIG_SIZES:
xassert (INTEGERP (w->orig_top_line) && INTEGERP (w->orig_total_lines));
w->top_line = w->orig_top_line;
w->total_lines = w->orig_total_lines;
w->orig_total_lines = w->orig_top_line = Qnil;
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
break;
default:
abort ();
}
w = NILP (w->next) ? NULL : XWINDOW (w->next);
}
return success_p;
}
void
grow_mini_window (w, delta)
struct window *w;
int delta;
{
struct frame *f = XFRAME (w->frame);
struct window *root;
xassert (MINI_WINDOW_P (w));
xassert (delta >= 0);
check_min_window_sizes ();
root = XWINDOW (FRAME_ROOT_WINDOW (f));
if (delta)
{
int min_height = window_min_size (root, 0, 0, 0);
if (XFASTINT (root->total_lines) - delta < min_height)
delta = max (0, XFASTINT (root->total_lines) - min_height);
}
if (delta)
{
if (!save_restore_orig_size (root, CHECK_ORIG_SIZES))
save_restore_orig_size (root, SAVE_ORIG_SIZES);
shrink_window_lowest_first (root, XFASTINT (root->total_lines) - delta);
w->top_line = make_number (XFASTINT (root->top_line) + XFASTINT (root->total_lines));
w->total_lines = make_number (XFASTINT (w->total_lines) + delta);
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
adjust_glyphs (f);
}
}
void
shrink_mini_window (w)
struct window *w;
{
struct frame *f = XFRAME (w->frame);
struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
if (save_restore_orig_size (root, CHECK_ORIG_SIZES))
{
save_restore_orig_size (root, RESTORE_ORIG_SIZES);
adjust_glyphs (f);
FRAME_WINDOW_SIZES_CHANGED (f) = 1;
windows_or_buffers_changed = 1;
}
else if (XFASTINT (w->total_lines) > 1)
{
Lisp_Object window;
XSETWINDOW (window, w);
enlarge_window (window, 1 - XFASTINT (w->total_lines), 0);
}
}
void
mark_window_cursors_off (w)
struct window *w;
{
while (w)
{
if (!NILP (w->hchild))
mark_window_cursors_off (XWINDOW (w->hchild));
else if (!NILP (w->vchild))
mark_window_cursors_off (XWINDOW (w->vchild));
else
w->phys_cursor_on_p = 0;
w = NILP (w->next) ? 0 : XWINDOW (w->next);
}
}
int
window_internal_height (w)
struct window *w;
{
int ht = XFASTINT (w->total_lines);
if (!MINI_WINDOW_P (w))
{
if (!NILP (w->parent)
|| !NILP (w->vchild)
|| !NILP (w->hchild)
|| !NILP (w->next)
|| !NILP (w->prev)
|| WINDOW_WANTS_MODELINE_P (w))
--ht;
if (WINDOW_WANTS_HEADER_LINE_P (w))
--ht;
}
return ht;
}
int
window_box_text_cols (w)
struct window *w;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
int width = XINT (w->total_cols);
if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
else if (!FRAME_WINDOW_P (f)
&& !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
width -= 1;
if (FRAME_WINDOW_P (f))
width -= (WINDOW_FRINGE_COLS (w)
+ WINDOW_LEFT_MARGIN_COLS (w)
+ WINDOW_RIGHT_MARGIN_COLS (w));
return width;
}
static void
window_scroll (window, n, whole, noerror)
Lisp_Object window;
int n;
int whole;
int noerror;
{
immediate_quit = 1;
if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
window_scroll_pixel_based (window, n, whole, noerror);
else
window_scroll_line_based (window, n, whole, noerror);
immediate_quit = 0;
}
static void
window_scroll_pixel_based (window, n, whole, noerror)
Lisp_Object window;
int n;
int whole;
int noerror;
{
struct it it;
struct window *w = XWINDOW (window);
struct text_pos start;
int this_scroll_margin;
int vscrolled = 0;
int x, y, rtop, rbot, rowh, vpos;
SET_TEXT_POS_FROM_MARKER (start, w->start);
if (!pos_visible_p (w, PT, &x, &y, &rtop, &rbot, &rowh, &vpos))
{
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
it.current_y = it.last_visible_y;
move_it_vertically_backward (&it, window_box_height (w) / 2);
if (it.current_y <= 0)
{
init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
move_it_vertically_backward (&it, 0);
it.current_y = 0;
}
start = it.current.pos;
}
else if (auto_window_vscroll_p)
{
if (rtop || rbot)
{
int px;
int dy = WINDOW_FRAME_LINE_HEIGHT (w);
if (whole)
dy = max ((window_box_height (w)
- next_screen_context_lines * dy),
dy);
dy *= n;
if (n < 0)
{
if (w->vscroll < 0 && rtop > 0)
{
px = max (0, -w->vscroll - min (rtop, -dy));
Fset_window_vscroll (window, make_number (px), Qt);
return;
}
}
if (n > 0)
{
if (rbot > 0 && (w->vscroll < 0 || vpos == 0))
{
px = max (0, -w->vscroll + min (rbot, dy));
Fset_window_vscroll (window, make_number (px), Qt);
return;
}
if (rbot > 0 || w->vscroll < 0)
{
int spos;
Fset_window_vscroll (window, make_number (0), Qt);
if (rbot > 0)
spos = XINT (Fline_beginning_position (Qnil));
else
spos = min (XINT (Fline_end_position (Qnil)) + 1, ZV);
set_marker_restricted (w->start, make_number (spos),
w->buffer);
w->start_at_line_beg = Qt;
w->update_mode_line = Qt;
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
w->force_start = Qt;
return;
}
}
}
Fset_window_vscroll (window, make_number (0), Qt);
}
if (!NILP (Vscroll_preserve_screen_position))
{
if (window_scroll_pixel_based_preserve_y < 0
|| (!EQ (current_kboard->Vlast_command, Qscroll_up)
&& !EQ (current_kboard->Vlast_command, Qscroll_down)))
{
start_display (&it, w, start);
move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
window_scroll_pixel_based_preserve_y = it.current_y;
}
}
else
window_scroll_pixel_based_preserve_y = -1;
start_display (&it, w, start);
if (whole)
{
int start_pos = IT_CHARPOS (it);
int dy = WINDOW_FRAME_LINE_HEIGHT (w);
dy = max ((window_box_height (w)
- next_screen_context_lines * dy),
dy) * n;
if (dy <= 0)
{
move_it_vertically_backward (&it, -dy);
while (start_pos == IT_CHARPOS (it)
&& start_pos > BEGV)
move_it_by_lines (&it, -1, 1);
}
else if (dy > 0)
{
move_it_to (&it, ZV, -1, it.current_y + dy, -1,
MOVE_TO_POS | MOVE_TO_Y);
while (start_pos == IT_CHARPOS (it)
&& start_pos < ZV)
move_it_by_lines (&it, 1, 1);
}
}
else
move_it_by_lines (&it, n, 1);
if ((n > 0 && IT_CHARPOS (it) == ZV)
|| (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
{
if (IT_CHARPOS (it) == ZV)
{
if (it.current_y < it.last_visible_y
&& (it.current_y + it.max_ascent + it.max_descent
> it.last_visible_y))
{
w->vscroll = (it.last_visible_y
- it.current_y + it.max_ascent + it.max_descent);
adjust_glyphs (it.f);
}
else if (noerror)
return;
else if (n < 0)
xsignal0 (Qbeginning_of_buffer);
else
xsignal0 (Qend_of_buffer);
}
else
{
if (w->vscroll != 0)
w->vscroll = 0;
else if (noerror)
return;
else
xsignal0 (Qbeginning_of_buffer);
}
XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
vscrolled = 1;
}
if (! vscrolled)
{
int pos = IT_CHARPOS (it);
int bytepos;
if (in_display_vector_p (&it))
{
++pos;
move_it_to (&it, pos, -1, -1, -1, MOVE_TO_POS);
}
set_marker_restricted (w->start, make_number (pos),
w->buffer);
bytepos = XMARKER (w->start)->bytepos;
w->start_at_line_beg = ((pos == BEGV || FETCH_BYTE (bytepos - 1) == '\n')
? Qt : Qnil);
w->update_mode_line = Qt;
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
w->force_start = Qt;
}
it.current_y = it.vpos = 0;
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);
if (n > 0)
{
move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
if (IT_CHARPOS (it) == PT && it.current_y >= this_scroll_margin
&& (NILP (Vscroll_preserve_screen_position)
|| EQ (Vscroll_preserve_screen_position, Qt)))
;
else if (window_scroll_pixel_based_preserve_y >= 0)
{
move_it_to (&it, -1, -1,
window_scroll_pixel_based_preserve_y
- (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0 ),
-1, MOVE_TO_Y);
SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
}
else
{
while (it.current_y < this_scroll_margin)
{
int prev = it.current_y;
move_it_by_lines (&it, 1, 1);
if (prev == it.current_y)
break;
}
SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
}
}
else if (n < 0)
{
int charpos, bytepos;
int partial_p;
charpos = IT_CHARPOS (it);
bytepos = IT_BYTEPOS (it);
move_it_to (&it, PT, -1,
(it.last_visible_y - CURRENT_HEADER_LINE_HEIGHT (w)
- this_scroll_margin - 1),
-1,
MOVE_TO_POS | MOVE_TO_Y);
charpos = IT_CHARPOS (it);
bytepos = IT_BYTEPOS (it);
if (it.what == IT_EOB)
partial_p = it.current_y + it.ascent + it.descent > it.last_visible_y;
else
{
move_it_by_lines (&it, 1, 1);
partial_p = it.current_y > it.last_visible_y;
}
if (charpos == PT && !partial_p
&& (NILP (Vscroll_preserve_screen_position)
|| EQ (Vscroll_preserve_screen_position, Qt)))
;
else if (window_scroll_pixel_based_preserve_y >= 0)
{
SET_TEXT_POS_FROM_MARKER (start, w->start);
start_display (&it, w, start);
move_it_to (&it, -1, -1, window_scroll_pixel_based_preserve_y, -1,
MOVE_TO_Y);
SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
}
else
{
if (partial_p)
{
move_it_by_lines (&it, -2, 0);
SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
}
else
SET_PT_BOTH (charpos, bytepos);
}
}
}
static void
window_scroll_line_based (window, n, whole, noerror)
Lisp_Object window;
int n;
int whole;
int noerror;
{
register struct window *w = XWINDOW (window);
register int opoint = PT, opoint_byte = PT_BYTE;
register int pos, pos_byte;
register int ht = window_internal_height (w);
register Lisp_Object tem;
int lose;
Lisp_Object bolp;
int startpos;
struct position posit;
int original_vpos;
if (whole)
n *= max (1, ht - next_screen_context_lines);
startpos = marker_position (w->start);
posit = *compute_motion (startpos, 0, 0, 0,
PT, ht, 0,
-1, XINT (w->hscroll),
0, w);
original_vpos = posit.vpos;
XSETFASTINT (tem, PT);
tem = Fpos_visible_in_window_p (tem, window, Qnil);
if (NILP (tem))
{
Fvertical_motion (make_number (- (ht / 2)), window);
startpos = PT;
}
SET_PT (startpos);
lose = n < 0 && PT == BEGV;
Fvertical_motion (make_number (n), window);
pos = PT;
pos_byte = PT_BYTE;
bolp = Fbolp ();
SET_PT_BOTH (opoint, opoint_byte);
if (lose)
{
if (noerror)
return;
else
xsignal0 (Qbeginning_of_buffer);
}
if (pos < ZV)
{
int this_scroll_margin = scroll_margin;
if (this_scroll_margin < 0)
this_scroll_margin = 0;
if (XINT (w->total_lines) < 4 * scroll_margin)
this_scroll_margin = XINT (w->total_lines) / 4;
set_marker_restricted_both (w->start, w->buffer, pos, pos_byte);
w->start_at_line_beg = bolp;
w->update_mode_line = Qt;
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
w->force_start = Qt;
if (!NILP (Vscroll_preserve_screen_position)
&& (whole || !EQ (Vscroll_preserve_screen_position, Qt)))
{
SET_PT_BOTH (pos, pos_byte);
Fvertical_motion (make_number (original_vpos), window);
}
else if (n > 0)
{
int top_margin;
if (this_scroll_margin > 0)
{
SET_PT_BOTH (pos, pos_byte);
Fvertical_motion (make_number (this_scroll_margin), window);
top_margin = PT;
}
else
top_margin = pos;
if (top_margin <= opoint)
SET_PT_BOTH (opoint, opoint_byte);
else if (!NILP (Vscroll_preserve_screen_position))
{
SET_PT_BOTH (pos, pos_byte);
Fvertical_motion (make_number (original_vpos), window);
}
else
SET_PT (top_margin);
}
else if (n < 0)
{
int bottom_margin;
SET_PT_BOTH (pos, pos_byte);
tem = Fvertical_motion (make_number (ht - this_scroll_margin), window);
if (XFASTINT (tem) == ht - this_scroll_margin)
bottom_margin = PT;
else
bottom_margin = PT + 1;
if (bottom_margin > opoint)
SET_PT_BOTH (opoint, opoint_byte);
else
{
if (!NILP (Vscroll_preserve_screen_position))
{
SET_PT_BOTH (pos, pos_byte);
Fvertical_motion (make_number (original_vpos), window);
}
else
Fvertical_motion (make_number (-1), window);
}
}
}
else
{
if (noerror)
return;
else
xsignal0 (Qend_of_buffer);
}
}
static void
scroll_command (n, direction)
Lisp_Object n;
int direction;
{
int count = SPECPDL_INDEX ();
xassert (abs (direction) == 1);
if (XBUFFER (XWINDOW (selected_window)->buffer) != current_buffer)
{
record_unwind_protect (save_excursion_restore, save_excursion_save ());
Fset_buffer (XWINDOW (selected_window)->buffer);
++windows_or_buffers_changed;
}
if (NILP (n))
window_scroll (selected_window, direction, 1, 0);
else if (EQ (n, Qminus))
window_scroll (selected_window, -direction, 1, 0);
else
{
n = Fprefix_numeric_value (n);
window_scroll (selected_window, XINT (n) * direction, 0, 0);
}
unbind_to (count, Qnil);
}
DEFUN ("scroll-up", Fscroll_up, Sscroll_up, 0, 1, "P",
doc: )
(arg)
Lisp_Object arg;
{
scroll_command (arg, 1);
return Qnil;
}
DEFUN ("scroll-down", Fscroll_down, Sscroll_down, 0, 1, "P",
doc: )
(arg)
Lisp_Object arg;
{
scroll_command (arg, -1);
return Qnil;
}
DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, Sother_window_for_scrolling, 0, 0, 0,
doc: )
()
{
Lisp_Object window;
if (MINI_WINDOW_P (XWINDOW (selected_window))
&& !NILP (Vminibuf_scroll_window))
window = Vminibuf_scroll_window;
else if (!NILP (Vother_window_scroll_buffer))
{
window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil);
if (NILP (window))
window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt, Qnil);
}
else
{
window = Fnext_window (selected_window, Qnil, Qnil);
if (EQ (window, selected_window))
do
window = Fnext_window (window, Qnil, Qt);
while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
&& ! EQ (window, selected_window));
}
CHECK_LIVE_WINDOW (window);
if (EQ (window, selected_window))
error ("There is no other window");
return window;
}
DEFUN ("scroll-other-window", Fscroll_other_window, Sscroll_other_window, 0, 1, "P",
doc: )
(arg)
Lisp_Object arg;
{
Lisp_Object window;
struct window *w;
int count = SPECPDL_INDEX ();
window = Fother_window_for_scrolling ();
w = XWINDOW (window);
record_unwind_protect (save_excursion_restore, save_excursion_save ());
++windows_or_buffers_changed;
Fset_buffer (w->buffer);
SET_PT (marker_position (w->pointm));
if (NILP (arg))
window_scroll (window, 1, 1, 1);
else if (EQ (arg, Qminus))
window_scroll (window, -1, 1, 1);
else
{
if (CONSP (arg))
arg = Fcar (arg);
CHECK_NUMBER (arg);
window_scroll (window, XINT (arg), 0, 1);
}
set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
unbind_to (count, Qnil);
return Qnil;
}
DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 2, "P\np",
doc: )
(arg, set_minimum)
register Lisp_Object arg, set_minimum;
{
Lisp_Object result;
int hscroll;
struct window *w = XWINDOW (selected_window);
if (NILP (arg))
XSETFASTINT (arg, window_box_text_cols (w) - 2);
else
arg = Fprefix_numeric_value (arg);
hscroll = XINT (w->hscroll) + XINT (arg);
result = Fset_window_hscroll (selected_window, make_number (hscroll));
if (!NILP (set_minimum))
w->min_hscroll = w->hscroll;
return result;
}
DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 2, "P\np",
doc: )
(arg, set_minimum)
register Lisp_Object arg, set_minimum;
{
Lisp_Object result;
int hscroll;
struct window *w = XWINDOW (selected_window);
if (NILP (arg))
XSETFASTINT (arg, window_box_text_cols (w) - 2);
else
arg = Fprefix_numeric_value (arg);
hscroll = XINT (w->hscroll) - XINT (arg);
result = Fset_window_hscroll (selected_window, make_number (hscroll));
if (!NILP (set_minimum))
w->min_hscroll = w->hscroll;
return result;
}
DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
doc: )
()
{
if (minibuf_level > 0
&& MINI_WINDOW_P (XWINDOW (selected_window))
&& WINDOW_LIVE_P (minibuf_selected_window))
return minibuf_selected_window;
return Qnil;
}
static int
displayed_window_lines (w)
struct window *w;
{
struct it it;
struct text_pos start;
int height = window_box_height (w);
struct buffer *old_buffer;
int bottom_y;
if (XBUFFER (w->buffer) != current_buffer)
{
old_buffer = current_buffer;
set_buffer_internal (XBUFFER (w->buffer));
}
else
old_buffer = NULL;
if (XMARKER (w->start)->charpos < BEGV)
SET_TEXT_POS (start, BEGV, BEGV_BYTE);
else if (XMARKER (w->start)->charpos > ZV)
SET_TEXT_POS (start, ZV, ZV_BYTE);
else
SET_TEXT_POS_FROM_MARKER (start, w->start);
start_display (&it, w, start);
move_it_vertically (&it, height);
bottom_y = line_bottom_y (&it);
if (! FRAME_WINDOW_P (XFRAME (w->frame)))
height++;
if (bottom_y < height)
{
int uy = FRAME_LINE_HEIGHT (it.f);
it.vpos += (height - bottom_y + uy - 1) / uy;
}
if (old_buffer)
set_buffer_internal (old_buffer);
return it.vpos;
}
DEFUN ("recenter", Frecenter, Srecenter, 0, 1, "P",
doc: )
(arg)
register Lisp_Object arg;
{
struct window *w = XWINDOW (selected_window);
struct buffer *buf = XBUFFER (w->buffer);
struct buffer *obuf = current_buffer;
int center_p = 0;
int charpos, bytepos;
int iarg;
int this_scroll_margin;
obuf->display_error_modiff = 0;
if (NILP (arg))
{
int i;
for (i = 0; i < n_compositions; i++)
composition_table[i]->font = NULL;
WINDOW_XFRAME (w)->minimize_tool_bar_window_p = 1;
Fredraw_frame (WINDOW_FRAME (w));
SET_FRAME_GARBAGED (WINDOW_XFRAME (w));
center_p = 1;
}
else if (CONSP (arg))
center_p = 1;
else
{
arg = Fprefix_numeric_value (arg);
CHECK_NUMBER (arg);
iarg = XINT (arg);
}
set_buffer_internal (buf);
this_scroll_margin = max (0, scroll_margin);
this_scroll_margin = min (this_scroll_margin,
XFASTINT (w->total_lines) / 4);
if (FRAME_WINDOW_P (XFRAME (w->frame)))
{
if (center_p)
{
struct it it;
struct text_pos pt;
SET_TEXT_POS (pt, PT, PT_BYTE);
start_display (&it, w, pt);
move_it_vertically_backward (&it, window_box_height (w) / 2);
charpos = IT_CHARPOS (it);
bytepos = IT_BYTEPOS (it);
}
else if (iarg < 0)
{
struct it it;
struct text_pos pt;
int nlines = -iarg;
int extra_line_spacing;
int h = window_box_height (w);
iarg = - max (-iarg, this_scroll_margin);
SET_TEXT_POS (pt, PT, PT_BYTE);
start_display (&it, w, pt);
move_it_by_lines (&it, 0, 1);
it.current_y = 0;
it.vpos = 0;
move_it_by_lines (&it, nlines, 1);
if (it.vpos == nlines)
h -= it.current_y;
else
{
h -= line_bottom_y (&it);
it.vpos++;
}
extra_line_spacing = it.max_extra_line_spacing;
if (it.vpos < nlines)
{
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;
start_display (&it, w, pt);
it.current_y = 0;
move_it_vertically_backward (&it, h);
h += extra_line_spacing;
while (-it.current_y > h)
move_it_by_lines (&it, 1, 1);
charpos = IT_CHARPOS (it);
bytepos = IT_BYTEPOS (it);
}
else
{
struct position pos;
iarg = max (iarg, this_scroll_margin);
pos = *vmotion (PT, -iarg, w);
charpos = pos.bufpos;
bytepos = pos.bytepos;
}
}
else
{
struct position pos;
int ht = window_internal_height (w);
if (center_p)
iarg = ht / 2;
else if (iarg < 0)
iarg += ht;
iarg = max (iarg, this_scroll_margin);
iarg = min (iarg, ht - this_scroll_margin - 1);
pos = *vmotion (PT, - iarg, w);
charpos = pos.bufpos;
bytepos = pos.bytepos;
}
set_marker_both (w->start, w->buffer, charpos, bytepos);
w->window_end_valid = Qnil;
w->optional_new_start = Qt;
if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
w->start_at_line_beg = Qt;
else
w->start_at_line_beg = Qnil;
set_buffer_internal (obuf);
return Qnil;
}
DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
struct window *w = decode_window (window);
int pixel_height = window_box_height (w);
int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
return make_number (line_height);
}
DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
1, 1, "P",
doc: )
(arg)
Lisp_Object arg;
{
struct window *w = XWINDOW (selected_window);
int lines, start;
Lisp_Object window;
#if 0
int this_scroll_margin;
#endif
window = selected_window;
start = marker_position (w->start);
if (start < BEGV || start > ZV)
{
int height = window_internal_height (w);
Fvertical_motion (make_number (- (height / 2)), window);
set_marker_both (w->start, w->buffer, PT, PT_BYTE);
w->start_at_line_beg = Fbolp ();
w->force_start = Qt;
}
else
Fgoto_char (w->start);
lines = displayed_window_lines (w);
#if 0
this_scroll_margin = max (0, scroll_margin);
this_scroll_margin = min (this_scroll_margin, lines / 4);
#endif
if (NILP (arg))
XSETFASTINT (arg, lines / 2);
else
{
int iarg = XINT (Fprefix_numeric_value (arg));
if (iarg < 0)
iarg = iarg + lines;
#if 0
iarg = max (iarg, this_scroll_margin);
iarg = min (iarg, lines - this_scroll_margin - 1);
#endif
arg = make_number (iarg);
}
if (w->vscroll)
XSETINT (arg, XINT (arg) + 1);
return Fvertical_motion (arg, window);
}
struct save_window_data
{
EMACS_INT size_from_Lisp_Vector_struct;
struct Lisp_Vector *next_from_Lisp_Vector_struct;
Lisp_Object frame_cols, frame_lines, frame_menu_bar_lines;
Lisp_Object frame_tool_bar_lines;
Lisp_Object selected_frame;
Lisp_Object current_window;
Lisp_Object current_buffer;
Lisp_Object minibuf_scroll_window;
Lisp_Object minibuf_selected_window;
Lisp_Object root_window;
Lisp_Object focus_frame;
Lisp_Object min_width, min_height;
Lisp_Object saved_windows;
};
struct saved_window
{
EMACS_INT size_from_Lisp_Vector_struct;
struct Lisp_Vector *next_from_Lisp_Vector_struct;
Lisp_Object window;
Lisp_Object buffer, start, pointm, mark;
Lisp_Object left_col, top_line, total_cols, total_lines;
Lisp_Object hscroll, min_hscroll;
Lisp_Object parent, prev;
Lisp_Object start_at_line_beg;
Lisp_Object display_table;
Lisp_Object orig_top_line, orig_total_lines;
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;
Lisp_Object dedicated;
};
#define SAVED_WINDOW_N(swv,n) \
((struct saved_window *) (XVECTOR ((swv)->contents[(n)])))
DEFUN ("window-configuration-p", Fwindow_configuration_p, Swindow_configuration_p, 1, 1, 0,
doc: )
(object)
Lisp_Object object;
{
return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil;
}
DEFUN ("window-configuration-frame", Fwindow_configuration_frame, Swindow_configuration_frame, 1, 1, 0,
doc: )
(config)
Lisp_Object config;
{
register struct save_window_data *data;
struct Lisp_Vector *saved_windows;
CHECK_WINDOW_CONFIGURATION (config);
data = (struct save_window_data *) XVECTOR (config);
saved_windows = XVECTOR (data->saved_windows);
return XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
}
DEFUN ("set-window-configuration", Fset_window_configuration,
Sset_window_configuration, 1, 1, 0,
doc: )
(configuration)
Lisp_Object configuration;
{
register struct save_window_data *data;
struct Lisp_Vector *saved_windows;
Lisp_Object new_current_buffer;
Lisp_Object frame;
FRAME_PTR f;
int old_point = -1;
CHECK_WINDOW_CONFIGURATION (configuration);
data = (struct save_window_data *) XVECTOR (configuration);
saved_windows = XVECTOR (data->saved_windows);
new_current_buffer = data->current_buffer;
if (NILP (XBUFFER (new_current_buffer)->name))
new_current_buffer = Qnil;
else
{
if (XBUFFER (new_current_buffer) == current_buffer)
if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
&& WINDOWP (selected_window)
&& EQ (XWINDOW (selected_window)->buffer, new_current_buffer)
&& !EQ (selected_window, data->current_window))
old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
else
old_point = PT;
else
if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer)
&& !EQ (selected_window, data->current_window))
old_point = XMARKER (XWINDOW (data->current_window)->pointm)->charpos;
else
old_point = BUF_PT (XBUFFER (new_current_buffer));
}
frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
f = XFRAME (frame);
if (FRAME_LIVE_P (f))
{
register struct window *w;
register struct saved_window *p;
struct window *root_window;
struct window **leaf_windows;
int n_leaf_windows;
int k, i, n;
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);
BLOCK_INPUT;
if (XFASTINT (data->frame_lines) != previous_frame_lines
|| XFASTINT (data->frame_cols) != previous_frame_cols)
change_frame_size (f, XFASTINT (data->frame_lines),
XFASTINT (data->frame_cols), 0, 0, 0);
#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
if (XFASTINT (data->frame_menu_bar_lines)
!= previous_frame_menu_bar_lines)
x_set_menu_bar_lines (f, data->frame_menu_bar_lines, make_number (0));
#ifdef HAVE_WINDOW_SYSTEM
if (XFASTINT (data->frame_tool_bar_lines)
!= previous_frame_tool_bar_lines)
x_set_tool_bar_lines (f, data->frame_tool_bar_lines, make_number (0));
#endif
#endif
if (! NILP (XWINDOW (selected_window)->buffer))
{
w = XWINDOW (selected_window);
set_marker_both (w->pointm,
w->buffer,
BUF_PT (XBUFFER (w->buffer)),
BUF_PT_BYTE (XBUFFER (w->buffer)));
}
windows_or_buffers_changed++;
FRAME_WINDOW_SIZES_CHANGED (f) = 1;
root_window = XWINDOW (FRAME_ROOT_WINDOW (f));
leaf_windows
= (struct window **) alloca (count_windows (root_window)
* sizeof (struct window *));
n_leaf_windows = get_leaf_windows (root_window, leaf_windows, 0);
window_min_height = 1;
window_min_width = 1;
delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
for (k = 0; k < saved_windows->size; k++)
{
p = SAVED_WINDOW_N (saved_windows, k);
w = XWINDOW (p->window);
w->next = Qnil;
if (!NILP (p->parent))
w->parent = SAVED_WINDOW_N (saved_windows,
XFASTINT (p->parent))->window;
else
w->parent = Qnil;
if (!NILP (p->prev))
{
w->prev = SAVED_WINDOW_N (saved_windows,
XFASTINT (p->prev))->window;
XWINDOW (w->prev)->next = p->window;
}
else
{
w->prev = Qnil;
if (!NILP (w->parent))
{
if (EQ (p->total_cols, XWINDOW (w->parent)->total_cols))
{
XWINDOW (w->parent)->vchild = p->window;
XWINDOW (w->parent)->hchild = Qnil;
}
else
{
XWINDOW (w->parent)->hchild = p->window;
XWINDOW (w->parent)->vchild = Qnil;
}
}
}
if (BUFFERP (w->total_lines))
w->buffer = w->total_lines;
w->left_col = p->left_col;
w->top_line = p->top_line;
w->total_cols = p->total_cols;
w->total_lines = p->total_lines;
w->hscroll = p->hscroll;
w->min_hscroll = p->min_hscroll;
w->display_table = p->display_table;
w->orig_top_line = p->orig_top_line;
w->orig_total_lines = p->orig_total_lines;
w->left_margin_cols = p->left_margin_cols;
w->right_margin_cols = p->right_margin_cols;
w->left_fringe_width = p->left_fringe_width;
w->right_fringe_width = p->right_fringe_width;
w->fringes_outside_margins = p->fringes_outside_margins;
w->scroll_bar_width = p->scroll_bar_width;
w->vertical_scroll_bar_type = p->vertical_scroll_bar_type;
w->dedicated = p->dedicated;
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
if (NILP (p->buffer))
w->buffer = p->buffer;
else
{
if (!NILP (XBUFFER (p->buffer)->name))
{
w->buffer = p->buffer;
w->start_at_line_beg = p->start_at_line_beg;
set_marker_restricted (w->start, p->start, w->buffer);
set_marker_restricted (w->pointm, p->pointm, w->buffer);
Fset_marker (XBUFFER (w->buffer)->mark,
p->mark, w->buffer);
if (!EQ (p->buffer, new_current_buffer)
&& XBUFFER (p->buffer) == current_buffer)
Fgoto_char (w->pointm);
}
else if (NILP (w->buffer) || NILP (XBUFFER (w->buffer)->name))
{
w->buffer = Fcdr (Fcar (Vbuffer_alist));
set_marker_restricted (w->start, make_number (0), w->buffer);
set_marker_restricted (w->pointm, make_number (0),w->buffer);
w->start_at_line_beg = Qt;
}
else
{
if (XMARKER (w->start)->buffer == 0)
set_marker_restricted (w->start, make_number (0),
w->buffer);
if (XMARKER (w->pointm)->buffer == 0)
set_marker_restricted_both (w->pointm, w->buffer,
BUF_PT (XBUFFER (w->buffer)),
BUF_PT_BYTE (XBUFFER (w->buffer)));
w->start_at_line_beg = Qt;
}
}
}
FRAME_ROOT_WINDOW (f) = data->root_window;
selected_window = Qnil;
if (EQ (XWINDOW (data->current_window)->buffer, new_current_buffer))
set_marker_restricted (XWINDOW (data->current_window)->pointm,
make_number (old_point),
XWINDOW (data->current_window)->buffer);
Fselect_window (data->current_window, Qnil);
XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
= selected_window;
if (NILP (data->focus_frame)
|| (FRAMEP (data->focus_frame)
&& FRAME_LIVE_P (XFRAME (data->focus_frame))))
Fredirect_frame_focus (frame, data->focus_frame);
#if 0
if (f != selected_frame && FRAME_WINDOW_P (f))
do_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)),
0, 0);
#endif
if (previous_frame_lines != FRAME_LINES (f)
|| previous_frame_cols != FRAME_COLS (f))
change_frame_size (f, previous_frame_lines, previous_frame_cols,
0, 0, 0);
#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS)
if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
x_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
#endif
for (i = n = 0; i < n_leaf_windows; ++i)
{
if (NILP (leaf_windows[i]->buffer))
{
xassert (NILP (leaf_windows[i]->hchild)
&& NILP (leaf_windows[i]->vchild));
free_window_matrices (leaf_windows[i]);
}
else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
++n;
}
adjust_glyphs (f);
UNBLOCK_INPUT;
if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
do_switch_frame (data->selected_frame, 0, 0);
if (! NILP (Vwindow_configuration_change_hook)
&& ! NILP (Vrun_hooks))
call1 (Vrun_hooks, Qwindow_configuration_change_hook);
}
if (!NILP (new_current_buffer))
Fset_buffer (new_current_buffer);
window_min_height = XINT (data->min_height);
window_min_width = XINT (data->min_width);
Vminibuf_scroll_window = data->minibuf_scroll_window;
minibuf_selected_window = data->minibuf_selected_window;
return (FRAME_LIVE_P (f) ? Qt : Qnil);
}
void
delete_all_subwindows (w)
register struct window *w;
{
if (!NILP (w->next))
delete_all_subwindows (XWINDOW (w->next));
if (!NILP (w->vchild))
delete_all_subwindows (XWINDOW (w->vchild));
if (!NILP (w->hchild))
delete_all_subwindows (XWINDOW (w->hchild));
w->total_lines = w->buffer;
if (!NILP (w->buffer))
unshow_buffer (w);
w->buffer = Qnil;
w->vchild = Qnil;
w->hchild = Qnil;
Vwindow_list = Qnil;
}
static int
count_windows (window)
register struct window *window;
{
register int count = 1;
if (!NILP (window->next))
count += count_windows (XWINDOW (window->next));
if (!NILP (window->vchild))
count += count_windows (XWINDOW (window->vchild));
if (!NILP (window->hchild))
count += count_windows (XWINDOW (window->hchild));
return count;
}
static int
get_leaf_windows (w, flat, i)
struct window *w;
struct window **flat;
int i;
{
while (w)
{
if (!NILP (w->hchild))
i = get_leaf_windows (XWINDOW (w->hchild), flat, i);
else if (!NILP (w->vchild))
i = get_leaf_windows (XWINDOW (w->vchild), flat, i);
else
flat[i++] = w;
w = NILP (w->next) ? 0 : XWINDOW (w->next);
}
return i;
}
struct glyph *
get_phys_cursor_glyph (w)
struct window *w;
{
struct glyph_row *row;
struct glyph *glyph;
if (w->phys_cursor.vpos >= 0
&& w->phys_cursor.vpos < w->current_matrix->nrows
&& (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
row->enabled_p)
&& row->used[TEXT_AREA] > w->phys_cursor.hpos)
glyph = row->glyphs[TEXT_AREA] + w->phys_cursor.hpos;
else
glyph = NULL;
return glyph;
}
static int
save_window_save (window, vector, i)
Lisp_Object window;
struct Lisp_Vector *vector;
int i;
{
register struct saved_window *p;
register struct window *w;
register Lisp_Object tem;
for (;!NILP (window); window = w->next)
{
p = SAVED_WINDOW_N (vector, i);
w = XWINDOW (window);
XSETFASTINT (w->temslot, i); i++;
p->window = window;
p->buffer = w->buffer;
p->left_col = w->left_col;
p->top_line = w->top_line;
p->total_cols = w->total_cols;
p->total_lines = w->total_lines;
p->hscroll = w->hscroll;
p->min_hscroll = w->min_hscroll;
p->display_table = w->display_table;
p->orig_top_line = w->orig_top_line;
p->orig_total_lines = w->orig_total_lines;
p->left_margin_cols = w->left_margin_cols;
p->right_margin_cols = w->right_margin_cols;
p->left_fringe_width = w->left_fringe_width;
p->right_fringe_width = w->right_fringe_width;
p->fringes_outside_margins = w->fringes_outside_margins;
p->scroll_bar_width = w->scroll_bar_width;
p->vertical_scroll_bar_type = w->vertical_scroll_bar_type;
p->dedicated = w->dedicated;
if (!NILP (w->buffer))
{
if (EQ (window, selected_window))
{
p->pointm = Fmake_marker ();
set_marker_both (p->pointm, w->buffer,
BUF_PT (XBUFFER (w->buffer)),
BUF_PT_BYTE (XBUFFER (w->buffer)));
}
else
p->pointm = Fcopy_marker (w->pointm, Qnil);
p->start = Fcopy_marker (w->start, Qnil);
p->start_at_line_beg = w->start_at_line_beg;
tem = XBUFFER (w->buffer)->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;
if (!NILP (w->vchild))
i = save_window_save (w->vchild, vector, i);
if (!NILP (w->hchild))
i = save_window_save (w->hchild, vector, i);
}
return i;
}
DEFUN ("current-window-configuration", Fcurrent_window_configuration,
Scurrent_window_configuration, 0, 1, 0,
doc: )
(frame)
Lisp_Object frame;
{
register Lisp_Object tem;
register int n_windows;
register struct save_window_data *data;
register struct Lisp_Vector *vec;
register int i;
FRAME_PTR f;
if (NILP (frame))
frame = selected_frame;
CHECK_LIVE_FRAME (frame);
f = XFRAME (frame);
n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f)));
vec = allocate_other_vector (VECSIZE (struct save_window_data));
data = (struct save_window_data *)vec;
XSETFASTINT (data->frame_cols, FRAME_COLS (f));
XSETFASTINT (data->frame_lines, FRAME_LINES (f));
XSETFASTINT (data->frame_menu_bar_lines, FRAME_MENU_BAR_LINES (f));
XSETFASTINT (data->frame_tool_bar_lines, FRAME_TOOL_BAR_LINES (f));
data->selected_frame = selected_frame;
data->current_window = FRAME_SELECTED_WINDOW (f);
XSETBUFFER (data->current_buffer, current_buffer);
data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil;
data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil;
data->root_window = FRAME_ROOT_WINDOW (f);
data->focus_frame = FRAME_FOCUS_FRAME (f);
XSETINT (data->min_height, window_min_height);
XSETINT (data->min_width, window_min_width);
tem = Fmake_vector (make_number (n_windows), Qnil);
data->saved_windows = tem;
for (i = 0; i < n_windows; i++)
XVECTOR (tem)->contents[i]
= Fmake_vector (make_number (VECSIZE (struct saved_window)), Qnil);
save_window_save (FRAME_ROOT_WINDOW (f), XVECTOR (tem), 0);
XSETWINDOW_CONFIGURATION (tem, data);
return (tem);
}
DEFUN ("save-window-excursion", Fsave_window_excursion, Ssave_window_excursion,
0, UNEVALLED, 0,
doc: )
(args)
Lisp_Object args;
{
register Lisp_Object val;
register int count = SPECPDL_INDEX ();
record_unwind_protect (Fset_window_configuration,
Fcurrent_window_configuration (Qnil));
val = Fprogn (args);
return unbind_to (count, val);
}
static Lisp_Object
window_tree (w)
struct window *w;
{
Lisp_Object tail = Qnil;
Lisp_Object result = Qnil;
while (w)
{
Lisp_Object wn;
XSETWINDOW (wn, w);
if (!NILP (w->hchild))
wn = Fcons (Qnil, Fcons (Fwindow_edges (wn),
window_tree (XWINDOW (w->hchild))));
else if (!NILP (w->vchild))
wn = Fcons (Qt, Fcons (Fwindow_edges (wn),
window_tree (XWINDOW (w->vchild))));
if (NILP (result))
{
result = tail = Fcons (wn, Qnil);
}
else
{
XSETCDR (tail, Fcons (wn, Qnil));
tail = XCDR (tail);
}
w = NILP (w->next) ? 0 : XWINDOW (w->next);
}
return result;
}
DEFUN ("window-tree", Fwindow_tree, Swindow_tree,
0, 1, 0,
doc: )
(frame)
Lisp_Object frame;
{
FRAME_PTR f;
if (NILP (frame))
frame = selected_frame;
CHECK_FRAME (frame);
f = XFRAME (frame);
if (!FRAME_LIVE_P (f))
return Qnil;
return window_tree (XWINDOW (FRAME_ROOT_WINDOW (f)));
}
DEFUN ("set-window-margins", Fset_window_margins, Sset_window_margins,
2, 3, 0,
doc: )
(window, left_width, right_width)
Lisp_Object window, left_width, right_width;
{
struct window *w = decode_window (window);
if (!NILP (left_width))
{
CHECK_NUMBER (left_width);
if (XINT (left_width) <= 0)
left_width = Qnil;
}
if (!NILP (right_width))
{
CHECK_NUMBER (right_width);
if (XINT (right_width) <= 0)
right_width = Qnil;
}
if (!EQ (w->left_margin_cols, left_width)
|| !EQ (w->right_margin_cols, right_width))
{
w->left_margin_cols = left_width;
w->right_margin_cols = right_width;
adjust_window_margins (w);
++windows_or_buffers_changed;
adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
}
return Qnil;
}
DEFUN ("window-margins", Fwindow_margins, Swindow_margins,
0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
struct window *w = decode_window (window);
return Fcons (w->left_margin_cols, w->right_margin_cols);
}
DEFUN ("set-window-fringes", Fset_window_fringes, Sset_window_fringes,
2, 4, 0,
doc: )
(window, left_width, right_width, outside_margins)
Lisp_Object window, left_width, right_width, outside_margins;
{
struct window *w = decode_window (window);
if (!NILP (left_width))
CHECK_NATNUM (left_width);
if (!NILP (right_width))
CHECK_NATNUM (right_width);
if (FRAME_WINDOW_P (WINDOW_XFRAME (w))
&& (!EQ (w->left_fringe_width, left_width)
|| !EQ (w->right_fringe_width, right_width)
|| !EQ (w->fringes_outside_margins, outside_margins)))
{
w->left_fringe_width = left_width;
w->right_fringe_width = right_width;
w->fringes_outside_margins = outside_margins;
adjust_window_margins (w);
clear_glyph_matrix (w->current_matrix);
w->window_end_valid = Qnil;
++windows_or_buffers_changed;
adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
}
return Qnil;
}
DEFUN ("window-fringes", Fwindow_fringes, Swindow_fringes,
0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
struct window *w = decode_window (window);
return Fcons (make_number (WINDOW_LEFT_FRINGE_WIDTH (w)),
Fcons (make_number (WINDOW_RIGHT_FRINGE_WIDTH (w)),
Fcons ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
? Qt : Qnil), Qnil)));
}
DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars, Sset_window_scroll_bars,
2, 4, 0,
doc: )
(window, width, vertical_type, horizontal_type)
Lisp_Object window, width, vertical_type, horizontal_type;
{
struct window *w = decode_window (window);
if (!NILP (width))
{
CHECK_NATNUM (width);
if (XINT (width) == 0)
vertical_type = Qnil;
}
if (!(EQ (vertical_type, Qnil)
|| EQ (vertical_type, Qleft)
|| EQ (vertical_type, Qright)
|| EQ (vertical_type, Qt)))
error ("Invalid type of vertical scroll bar");
if (!EQ (w->scroll_bar_width, width)
|| !EQ (w->vertical_scroll_bar_type, vertical_type))
{
w->scroll_bar_width = width;
w->vertical_scroll_bar_type = vertical_type;
adjust_window_margins (w);
clear_glyph_matrix (w->current_matrix);
w->window_end_valid = Qnil;
++windows_or_buffers_changed;
adjust_glyphs (XFRAME (WINDOW_FRAME (w)));
}
return Qnil;
}
DEFUN ("window-scroll-bars", Fwindow_scroll_bars, Swindow_scroll_bars,
0, 1, 0,
doc: )
(window)
Lisp_Object window;
{
struct window *w = decode_window (window);
return Fcons (make_number ((WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)
: WINDOW_SCROLL_BAR_AREA_WIDTH (w))),
Fcons (make_number (WINDOW_SCROLL_BAR_COLS (w)),
Fcons (w->vertical_scroll_bar_type,
Fcons (Qnil, Qnil))));
}
DEFUN ("window-vscroll", Fwindow_vscroll, Swindow_vscroll, 0, 2, 0,
doc: )
(window, pixels_p)
Lisp_Object window, pixels_p;
{
Lisp_Object result;
struct frame *f;
struct window *w;
if (NILP (window))
window = selected_window;
else
CHECK_WINDOW (window);
w = XWINDOW (window);
f = XFRAME (w->frame);
if (FRAME_WINDOW_P (f))
result = (NILP (pixels_p)
? FRAME_CANON_Y_FROM_PIXEL_Y (f, -w->vscroll)
: make_number (-w->vscroll));
else
result = make_number (0);
return result;
}
DEFUN ("set-window-vscroll", Fset_window_vscroll, Sset_window_vscroll,
2, 3, 0,
doc: )
(window, vscroll, pixels_p)
Lisp_Object window, vscroll, pixels_p;
{
struct window *w;
struct frame *f;
if (NILP (window))
window = selected_window;
else
CHECK_WINDOW (window);
CHECK_NUMBER_OR_FLOAT (vscroll);
w = XWINDOW (window);
f = XFRAME (w->frame);
if (FRAME_WINDOW_P (f))
{
int old_dy = w->vscroll;
w->vscroll = - (NILP (pixels_p)
? FRAME_LINE_HEIGHT (f) * XFLOATINT (vscroll)
: XFLOATINT (vscroll));
w->vscroll = min (w->vscroll, 0);
if (w->vscroll != old_dy)
{
if (w->vscroll < 0 && w->vscroll < old_dy)
adjust_glyphs (f);
XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
}
}
return Fwindow_vscroll (window, pixels_p);
}
void
foreach_window (f, fn, user_data)
struct frame *f;
int (* fn) P_ ((struct window *, void *));
void *user_data;
{
if (WINDOWP (FRAME_ROOT_WINDOW (f)))
foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
}
static int
foreach_window_1 (w, fn, user_data)
struct window *w;
int (* fn) P_ ((struct window *, void *));
void *user_data;
{
int cont;
for (cont = 1; w && cont;)
{
if (!NILP (w->hchild))
cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
else if (!NILP (w->vchild))
cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
else
cont = fn (w, user_data);
w = NILP (w->next) ? 0 : XWINDOW (w->next);
}
return cont;
}
static int
freeze_window_start (w, freeze_p)
struct window *w;
void *freeze_p;
{
if (w == XWINDOW (selected_window)
|| MINI_WINDOW_P (w)
|| (MINI_WINDOW_P (XWINDOW (selected_window))
&& ! NILP (Vminibuf_scroll_window)
&& w == XWINDOW (Vminibuf_scroll_window)))
freeze_p = NULL;
w->frozen_window_start_p = freeze_p != NULL;
return 1;
}
void
freeze_window_starts (f, freeze_p)
struct frame *f;
int freeze_p;
{
foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
}
int
compare_window_configurations (c1, c2, ignore_positions)
Lisp_Object c1, c2;
int ignore_positions;
{
register struct save_window_data *d1, *d2;
struct Lisp_Vector *sw1, *sw2;
int i;
CHECK_WINDOW_CONFIGURATION (c1);
CHECK_WINDOW_CONFIGURATION (c2);
d1 = (struct save_window_data *) XVECTOR (c1);
d2 = (struct save_window_data *) XVECTOR (c2);
sw1 = XVECTOR (d1->saved_windows);
sw2 = XVECTOR (d2->saved_windows);
if (! EQ (d1->frame_cols, d2->frame_cols))
return 0;
if (! EQ (d1->frame_lines, d2->frame_lines))
return 0;
if (! EQ (d1->frame_menu_bar_lines, d2->frame_menu_bar_lines))
return 0;
if (! EQ (d1->selected_frame, d2->selected_frame))
return 0;
if (! EQ (d1->current_buffer, d2->current_buffer))
return 0;
if (! ignore_positions)
{
if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window))
return 0;
if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window))
return 0;
}
if (! EQ (d1->focus_frame, d2->focus_frame))
return 0;
if (! EQ (d1->min_width, d2->min_width))
return 0;
if (! EQ (d1->min_height, d2->min_height))
return 0;
if (sw1->size != sw2->size)
return 0;
for (i = 0; i < sw1->size; i++)
{
struct saved_window *p1, *p2;
int w1_is_current, w2_is_current;
p1 = SAVED_WINDOW_N (sw1, i);
p2 = SAVED_WINDOW_N (sw2, i);
w1_is_current = EQ (d1->current_window, p1->window);
w2_is_current = EQ (d2->current_window, p2->window);
if (w1_is_current != w2_is_current)
return 0;
if (! EQ (p1->buffer, p2->buffer))
return 0;
if (! EQ (p1->left_col, p2->left_col))
return 0;
if (! EQ (p1->top_line, p2->top_line))
return 0;
if (! EQ (p1->total_cols, p2->total_cols))
return 0;
if (! EQ (p1->total_lines, p2->total_lines))
return 0;
if (! EQ (p1->display_table, p2->display_table))
return 0;
if (! EQ (p1->parent, p2->parent))
return 0;
if (! EQ (p1->prev, p2->prev))
return 0;
if (! ignore_positions)
{
if (! EQ (p1->hscroll, p2->hscroll))
return 0;
if (!EQ (p1->min_hscroll, p2->min_hscroll))
return 0;
if (! EQ (p1->start_at_line_beg, p2->start_at_line_beg))
return 0;
if (NILP (Fequal (p1->start, p2->start)))
return 0;
if (NILP (Fequal (p1->pointm, p2->pointm)))
return 0;
if (NILP (Fequal (p1->mark, p2->mark)))
return 0;
}
if (! EQ (p1->left_margin_cols, p2->left_margin_cols))
return 0;
if (! EQ (p1->right_margin_cols, p2->right_margin_cols))
return 0;
if (! EQ (p1->left_fringe_width, p2->left_fringe_width))
return 0;
if (! EQ (p1->right_fringe_width, p2->right_fringe_width))
return 0;
if (! EQ (p1->fringes_outside_margins, p2->fringes_outside_margins))
return 0;
if (! EQ (p1->scroll_bar_width, p2->scroll_bar_width))
return 0;
if (! EQ (p1->vertical_scroll_bar_type, p2->vertical_scroll_bar_type))
return 0;
}
return 1;
}
DEFUN ("compare-window-configurations", Fcompare_window_configurations,
Scompare_window_configurations, 2, 2, 0,
doc: )
(x, y)
Lisp_Object x, y;
{
if (compare_window_configurations (x, y, 1))
return Qt;
return Qnil;
}
void
init_window_once ()
{
struct frame *f = make_terminal_frame ();
XSETFRAME (selected_frame, f);
Vterminal_frame = selected_frame;
minibuf_window = f->minibuffer_window;
selected_window = f->selected_window;
last_nonminibuf_frame = f;
window_initialized = 1;
}
void
init_window ()
{
Vwindow_list = Qnil;
}
void
syms_of_window ()
{
Qscroll_up = intern ("scroll-up");
staticpro (&Qscroll_up);
Qscroll_down = intern ("scroll-down");
staticpro (&Qscroll_down);
Qwindow_size_fixed = intern ("window-size-fixed");
staticpro (&Qwindow_size_fixed);
Fset (Qwindow_size_fixed, Qnil);
staticpro (&Qwindow_configuration_change_hook);
Qwindow_configuration_change_hook
= intern ("window-configuration-change-hook");
Qwindowp = intern ("windowp");
staticpro (&Qwindowp);
Qwindow_configuration_p = intern ("window-configuration-p");
staticpro (&Qwindow_configuration_p);
Qwindow_live_p = intern ("window-live-p");
staticpro (&Qwindow_live_p);
Qtemp_buffer_show_hook = intern ("temp-buffer-show-hook");
staticpro (&Qtemp_buffer_show_hook);
staticpro (&Vwindow_list);
minibuf_selected_window = Qnil;
staticpro (&minibuf_selected_window);
window_scroll_pixel_based_preserve_y = -1;
DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
doc: );
Vtemp_buffer_show_function = Qnil;
DEFVAR_LISP ("display-buffer-function", &Vdisplay_buffer_function,
doc: );
Vdisplay_buffer_function = Qnil;
DEFVAR_LISP ("even-window-heights", &Veven_window_heights,
doc: );
Veven_window_heights = Qt;
DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
doc: );
Vminibuf_scroll_window = Qnil;
DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows,
doc: );
mode_line_in_non_selected_windows = 1;
DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer,
doc: );
Vother_window_scroll_buffer = Qnil;
DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
doc: );
pop_up_frames = 0;
DEFVAR_BOOL ("auto-window-vscroll", &auto_window_vscroll_p,
doc: );
auto_window_vscroll_p = 1;
DEFVAR_BOOL ("display-buffer-reuse-frames", &display_buffer_reuse_frames,
doc: );
display_buffer_reuse_frames = 0;
DEFVAR_LISP ("pop-up-frame-function", &Vpop_up_frame_function,
doc: );
Vpop_up_frame_function = Qnil;
DEFVAR_LISP ("special-display-buffer-names", &Vspecial_display_buffer_names,
doc: );
Vspecial_display_buffer_names = Qnil;
DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
doc: );
Vspecial_display_regexps = Qnil;
DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
doc: );
Vspecial_display_function = Qnil;
DEFVAR_LISP ("same-window-buffer-names", &Vsame_window_buffer_names,
doc: );
Vsame_window_buffer_names = Qnil;
DEFVAR_LISP ("same-window-regexps", &Vsame_window_regexps,
doc: );
Vsame_window_regexps = Qnil;
DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
doc: );
pop_up_windows = 1;
DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines,
doc: );
next_screen_context_lines = 2;
DEFVAR_INT ("split-height-threshold", &split_height_threshold,
doc: );
split_height_threshold = 500;
DEFVAR_INT ("window-min-height", &window_min_height,
doc: );
window_min_height = 4;
DEFVAR_INT ("window-min-width", &window_min_width,
doc: );
window_min_width = 10;
DEFVAR_LISP ("scroll-preserve-screen-position",
&Vscroll_preserve_screen_position,
doc: );
Vscroll_preserve_screen_position = Qnil;
DEFVAR_LISP ("window-configuration-change-hook",
&Vwindow_configuration_change_hook,
doc: );
Vwindow_configuration_change_hook = Qnil;
defsubr (&Sselected_window);
defsubr (&Sminibuffer_window);
defsubr (&Swindow_minibuffer_p);
defsubr (&Swindowp);
defsubr (&Swindow_live_p);
defsubr (&Spos_visible_in_window_p);
defsubr (&Swindow_line_height);
defsubr (&Swindow_buffer);
defsubr (&Swindow_height);
defsubr (&Swindow_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_inside_edges);
defsubr (&Swindow_inside_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 (&Sother_window);
defsubr (&Sget_lru_window);
defsubr (&Sget_largest_window);
defsubr (&Sget_buffer_window);
defsubr (&Sdelete_other_windows);
defsubr (&Sdelete_windows_on);
defsubr (&Sreplace_buffer_in_windows);
defsubr (&Sdelete_window);
defsubr (&Sset_window_buffer);
defsubr (&Sselect_window);
defsubr (&Sspecial_display_p);
defsubr (&Ssame_window_p);
defsubr (&Sdisplay_buffer);
defsubr (&Sforce_window_update);
defsubr (&Ssplit_window);
defsubr (&Senlarge_window);
defsubr (&Sshrink_window);
defsubr (&Sadjust_window_trailing_edge);
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_height);
defsubr (&Smove_to_window_line);
defsubr (&Swindow_configuration_p);
defsubr (&Swindow_configuration_frame);
defsubr (&Sset_window_configuration);
defsubr (&Scurrent_window_configuration);
defsubr (&Ssave_window_excursion);
defsubr (&Swindow_tree);
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);
}
void
keys_of_window ()
{
initial_define_key (control_x_map, '1', "delete-other-windows");
initial_define_key (control_x_map, '2', "split-window");
initial_define_key (control_x_map, '0', "delete-window");
initial_define_key (control_x_map, 'o', "other-window");
initial_define_key (control_x_map, '^', "enlarge-window");
initial_define_key (control_x_map, '<', "scroll-left");
initial_define_key (control_x_map, '>', "scroll-right");
initial_define_key (global_map, Ctl ('V'), "scroll-up");
initial_define_key (meta_map, Ctl ('V'), "scroll-other-window");
initial_define_key (meta_map, 'v', "scroll-down");
initial_define_key (global_map, Ctl('L'), "recenter");
initial_define_key (meta_map, 'r', "move-to-window-line");
}