/* Divider surface width (not counting 3-d borders) */
Lisp_Object Vvertical_divider_line_width;
-/* Spacing between outer egde of divider border and window edge */
+/* Spacing between outer edge of divider border and window edge */
Lisp_Object Vvertical_divider_spacing;
/* How much to scroll by per-line. */
p->face_cachels = Dynarr_new (face_cachel);
p->glyph_cachels = Dynarr_new (glyph_cachel);
p->line_start_cache = Dynarr_new (line_start_cache);
- p->subwindow_instance_cache = make_lisp_hash_table (10,
- HASH_TABLE_KEY_WEAK,
+ p->subwindow_instance_cache = make_lisp_hash_table (30,
+ HASH_TABLE_KEY_VALUE_WEAK,
HASH_TABLE_EQ);
p->line_cache_last_updated = Qzero;
INIT_DISP_VARIABLE (last_point_x, 0);
INIT_DISP_VARIABLE (window_end_pos, 0);
p->redisplay_end_trigger = Qnil;
+ p->gutter_extent_modiff[0] = 0;
+ p->gutter_extent_modiff[1] = 0;
+ p->gutter_extent_modiff[2] = 0;
+ p->gutter_extent_modiff[3] = 0;
+
#define WINDOW_SLOT(slot, compare) p->slot = Qnil
#include "winslots.h"
window_truncation_on (struct window *w)
{
/* Minibuffer windows are never truncated.
- ### is this the right way ? */
+ #### is this the right way ? */
if (MINI_WINDOW_P (w))
return 0;
}
DEFUN ("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /*
-Returns Non-Nil iff the window is truncated.
+Returns non-nil if text in the window is truncated.
*/
(window))
{
relative to the frame, not the window.
****************************************************************************/
-int
-window_top_gutter_height (struct window *w)
+static int
+window_top_window_gutter_height (struct window *w)
{
- int gutter = WINDOW_REAL_TOP_GUTTER_BOUNDS (w);
-
if (!NILP (w->hchild) || !NILP (w->vchild))
return 0;
#ifdef HAVE_SCROLLBARS
if (!NILP (w->scrollbar_on_top_p))
- return window_scrollbar_height (w) + gutter;
+ return window_scrollbar_height (w);
else
#endif
- return gutter;
+ return 0;
}
int
-window_bottom_gutter_height (struct window *w)
+window_top_gutter_height (struct window *w)
{
- int gutter = WINDOW_REAL_BOTTOM_GUTTER_BOUNDS (w);
+ return window_top_window_gutter_height (w);
+}
+
+static int
+window_bottom_window_gutter_height (struct window *w)
+{
+ int gutter;
if (!NILP (w->hchild) || !NILP (w->vchild))
return 0;
- gutter += window_modeline_height (w);
+ gutter = window_modeline_height (w);
#ifdef HAVE_SCROLLBARS
if (NILP (w->scrollbar_on_top_p))
}
int
-window_left_gutter_width (struct window *w, int modeline)
+window_bottom_gutter_height (struct window *w)
{
- int gutter = WINDOW_REAL_LEFT_GUTTER_BOUNDS (w);
+ return window_bottom_window_gutter_height (w);
+}
+static int
+window_left_window_gutter_width (struct window *w, int modeline)
+{
if (!NILP (w->hchild) || !NILP (w->vchild))
return 0;
#ifdef HAVE_SCROLLBARS
if (!modeline && !NILP (w->scrollbar_on_left_p))
- gutter += window_scrollbar_width (w);
+ return window_scrollbar_width (w);
#endif
- return gutter;
+ return 0;
}
int
-window_right_gutter_width (struct window *w, int modeline)
+window_left_gutter_width (struct window *w, int modeline)
+{
+ return window_left_window_gutter_width (w, modeline);
+}
+
+static int
+window_right_window_gutter_width (struct window *w, int modeline)
{
- int gutter = WINDOW_REAL_RIGHT_GUTTER_BOUNDS (w);
+ int gutter = 0;
if (!NILP (w->hchild) || !NILP (w->vchild))
return 0;
return gutter;
}
+int
+window_right_gutter_width (struct window *w, int modeline)
+{
+ return window_right_window_gutter_width (w, modeline);
+}
+
+static int
+window_pixel_height (struct window* w)
+{
+ return WINDOW_HEIGHT (w);
+}
+
\f
DEFUN ("windowp", Fwindowp, 1, 1, 0, /*
Return t if OBJ is a window.
return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame));
}
-DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 1, 1, 0, /*
+DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /*
Return non-nil if WINDOW is a minibuffer window.
*/
(window))
Use `window-height' to get consistent results in geometry calculations.
Use `window-displayed-height' to get the actual number of lines
currently displayed in a window.
+
+The names are somewhat confusing; here's a table to help out:
+
+ width height
+-------------------------------------------------------------------------
+w/o gutters
+ (rows/columns) window-width window-text-area-height
+ (pixels) window-text-area-pixel-width window-text-area-pixel-height
+
+with gutters
+ (rows/columns) window-full-width window-height
+ (pixels) window-pixel-width window-pixel-height
+
+actually displayed
+ (rows/columns) ---- window-displayed-height
+ (pixels) ---- window-displayed-text-pixel-height
*/
(window))
{
*/
(window))
{
- return make_int (decode_window (window)->pixel_height);
+ return make_int (window_pixel_height (decode_window (window)));
+}
+
+DEFUN ("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /*
+Return the number of default lines in the text area of WINDOW.
+This actually works by dividing the window's text area pixel height (i.e.
+excluding the modeline and horizontal scrollbar, if any) by the height of the
+default font; therefore, the number of displayed lines will probably
+be different.
+See also `window-height' and `window-displayed-height'.
+*/
+ (window))
+{
+ return make_int (window_char_height (decode_window (window), 0));
}
DEFUN ("window-text-area-pixel-height",
DEFUN ("window-width", Fwindow_width, 0, 1, 0, /*
Return the number of display columns in WINDOW.
-This is the width that is usable columns available for text in WINDOW.
+This is the width that is usable columns available for text in WINDOW,
+and does not include vertical scrollbars, dividers, or the like. See also
+`window-full-width' and `window-height'.
*/
(window))
{
return make_int (window_char_width (decode_window (window), 0));
}
+DEFUN ("window-full-width", Fwindow_full_width, 0, 1, 0, /*
+Return the total number of columns in WINDOW.
+This is like `window-width' but includes vertical scrollbars, dividers,
+etc.
+*/
+ (window))
+{
+ return make_int (window_char_width (decode_window (window), 1));
+}
+
DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /*
Return the width of WINDOW in pixels. Defaults to current window.
*/
return make_int (decode_window (window)->hscroll);
}
-#ifdef MODELINE_IS_SCROLLABLE
DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /*
-Return the number of columns by which WINDOW's modeline is scrolled from
-left margin. If the window has no modeline, return nil.
+Return the horizontal scrolling amount of WINDOW's modeline.
+If the window has no modeline, return nil.
*/
(window))
{
struct window *w = decode_window (window);
- return (WINDOW_HAS_MODELINE_P (w)) ? make_int (w->modeline_hscroll) : Qnil;
+ return (WINDOW_HAS_MODELINE_P (w)) ? make_int ((int) w->modeline_hscroll) :
+ Qnil;
}
DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /*
-Set number of columns WINDOW's modeline is scrolled from left margin to NCOL.
-NCOL should be zero or positive. If NCOL is negative, it will be forced to 0.
-If the window has no modeline, do nothing and return nil.
+Set the horizontal scrolling amount of WINDOW's modeline to NCOL.
+If NCOL is negative, it will silently be forced to 0.
+If the window has no modeline, return nil. Otherwise, return the actual
+value that was set.
*/
(window, ncol))
{
if (WINDOW_HAS_MODELINE_P (w))
{
- int ncols;
+ Charcount ncols;
+
CHECK_INT (ncol);
- ncols = XINT (ncol);
- if (ncols < 0) ncols = 0;
- if (w->modeline_hscroll != ncols)
- MARK_MODELINE_CHANGED;
- w->modeline_hscroll = ncols;
- return ncol;
+ ncols = (XINT (ncol) <= 0) ? 0 : (Charcount) XINT (ncol);
+ if (ncols != w->modeline_hscroll)
+ {
+ MARK_MODELINE_CHANGED;
+ w->modeline_hscroll = ncols;
+ }
+ return make_int ((int) ncols);
}
+
return Qnil;
}
-#endif /* MODELINE_IS_SCROLLABLE */
DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /*
Set number of columns WINDOW is scrolled from left margin to NCOL.
DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /*
Return a list of the pixel edge coordinates of WINDOW.
\(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame.
-The frame toolbars and menubars are considered to be outside of this area.
+The frame toolbars, menubars and gutters are considered to be outside of this area.
*/
(window))
{
struct window *w = decode_window (window);
struct frame *f = XFRAME (w->frame);
- int left = w->pixel_left - FRAME_LEFT_BORDER_END (f);
- int top = w->pixel_top - FRAME_TOP_BORDER_END (f);
+ int left =
+ w->pixel_left - FRAME_LEFT_BORDER_END (f) - FRAME_LEFT_GUTTER_BOUNDS (f);
+ int top =
+ w->pixel_top - FRAME_TOP_BORDER_END (f) - FRAME_TOP_GUTTER_BOUNDS (f);
return list4 (make_int (left),
make_int (top),
DEFUN ("window-point", Fwindow_point, 0, 1, 0, /*
Return current value of point in WINDOW.
-For a nonselected window, this is the value point would have
+For a non-selected window, this is the value point would have
if that window were selected.
Note that, when WINDOW is the selected window and its buffer
}
}
+DEFUN ("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /*
+Return pixel height of visible part of last window line if it is clipped.
+If the last line is not clipped, return nil.
+*/
+ (window))
+{
+ struct window *w = decode_window (window);
+ display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
+ int num_lines = Dynarr_length (dla);
+ struct display_line *dl;
+
+ /* No lines - no clipped lines */
+ if (num_lines == 0 || (num_lines == 1 && Dynarr_atp (dla, 0)->modeline))
+ return Qnil;
+
+ dl = Dynarr_atp (dla, num_lines - 1);
+ if (dl->clip == 0)
+ return Qnil;
+
+ return make_int (dl->ascent + dl->descent - dl->clip);
+}
+
DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /*
Make point value in WINDOW be at position POS in WINDOW's buffer.
*/
/* #### Here, if replacement is a vertical combination
and so is its new parent, we should make replacement's
children be children of that parent instead. */
+
+ ERROR_CHECK_SUBWINDOW_CACHE (p);
+}
+
+static void
+window_unmap_subwindows (struct window* w)
+{
+ assert (!NILP (w->subwindow_instance_cache));
+ elisp_maphash (unmap_subwindow_instance_cache_mapper,
+ w->subwindow_instance_cache, (void*)1);
}
/* we're deleting W; set the structure of W to indicate this. */
static void
mark_window_as_deleted (struct window *w)
{
+ /* The window instance cache is going away now, so need to get the
+ cachels reset by redisplay. */
+ MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (WINDOW_FRAME (w)));
+
+ /* The cache is going away. If we leave unmapping to
+ reset_subwindow_cachels then we get in a situation where the
+ domain (the window) has been deleted but we still need access to
+ its attributes in order to unmap windows properly. Since the
+ subwindows are going to get GC'd anyway as a result of the domain
+ going away, it is safer to just unmap them all while we know the
+ domain is still valid. */
+ ERROR_CHECK_SUBWINDOW_CACHE (w);
+ window_unmap_subwindows (w);
+
/* In the loop
(while t (split-window) (delete-window))
we end up with a tree of deleted windows which are all connected
Since the window-configuration code doesn't need any of the
pointers to other windows (they are all recreated from the
window-config data), we set them all to nil so that we
- are able to collect more actual garbage.
- */
+ are able to collect more actual garbage. */
w->next = Qnil;
w->prev = Qnil;
w->hchild = Qnil;
w->vchild = Qnil;
w->parent = Qnil;
+ w->subwindow_instance_cache = Qnil;
w->dead = 1;
window = Fselected_window (Qnil);
else
CHECK_WINDOW (window);
+
w = XWINDOW (window);
/* It's okay to delete an already-deleted window. */
par = XWINDOW (parent);
MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f);
+ /* It's quite likely that deleting a window will result in
+ subwindows needing to be deleted also (since they are cached
+ per-window). So we mark them as changed, so that the cachels will
+ get reset by redisplay and thus deleted subwindows can get
+ GC'd. */
+ MARK_FRAME_SUBWINDOWS_CHANGED (f);
/* Are we trying to delete any frame's selected window?
Note that we could be dealing with a non-leaf window
\f
DEFUN ("next-window", Fnext_window, 0, 4, 0, /*
-Return next window after WINDOW in canonical ordering of windows.
+Return the next window after WINDOW in the canonical ordering of windows.
If omitted, WINDOW defaults to the selected window.
Optional second arg MINIBUF t means count the minibuffer window even
If ALL-FRAMES is a frame, restrict search to windows on that frame.
Anything else means restrict to WINDOW's frame.
-Optional fourth argument CONSOLE controls which consoles or devices the
+Optional fourth arg CONSOLE controls which consoles or devices the
returned window may be on. If CONSOLE is a console, return windows only
on that console. If CONSOLE is a device, return windows only on that
device. If CONSOLE is a console type, return windows only on consoles
minibuf = (minibuf_level ? minibuf_window : Qlambda);
else if (! EQ (minibuf, Qt))
minibuf = Qlambda;
- /* Now minibuf can be t => count all minibuffer windows,
- lambda => count none of them,
+ /* Now `minibuf' is one of:
+ t => count all minibuffer windows
+ lambda => count none of them
or a specific minibuffer window (the active one) to count. */
/* all_frames == nil doesn't specify which frames to include. */
return frame_first_window (XFRAME (all_frames));
else if (! EQ (all_frames, Qt))
all_frames = Qnil;
- /* Now all_frames is t meaning search all frames,
- nil meaning search just current frame,
- visible meaning search just visible frames,
- 0 meaning search visible and iconified frames,
- or a window, meaning search the frame that window belongs to. */
+ /* Now `all_frames' is one of:
+ t => search all frames
+ nil => search just the current frame
+ visible => search just visible frames
+ 0 => search visible and iconified frames
+ a window => search the frame that window belongs to. */
/* Do this loop at least once, to get the next window, and perhaps
again, if we hit the minibuffer and that is not acceptable. */
if (! NILP (all_frames))
{
- Lisp_Object tem1;
-
- tem1 = tem;
+ Lisp_Object tem1 = tem;
tem = next_frame (tem, all_frames, console);
+
/* In the case where the minibuffer is active,
and we include its frame as well as the selected one,
next_frame may get stuck in that frame.
else break;
}
}
- /* "acceptable" is the correct spelling. */
/* Which windows are acceptable?
Exit the loop and accept this window if
this isn't a minibuffer window,
}
DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /*
-Return the window preceding WINDOW in canonical ordering of windows.
+Return the window preceding WINDOW in the canonical ordering of windows.
If omitted, WINDOW defaults to the selected window.
Optional second arg MINIBUF t means count the minibuffer window even
counts, all windows on all frames that share that minibuffer count
too. Therefore, `previous-window' can be used to iterate through
the set of windows even when the minibuffer is on another frame. If
-the minibuffer does not count, only windows from WINDOW's frame count
+the minibuffer does not count, only windows from WINDOW's frame count.
-If optional third arg ALL-FRAMES t means include windows on all frames.
+Optional third arg ALL-FRAMES t means include windows on all frames.
ALL-FRAMES nil or omitted means cycle within the frames as specified
above. ALL-FRAMES = `visible' means include windows on all visible frames.
ALL-FRAMES = 0 means include windows on all visible and iconified frames.
If ALL-FRAMES is a frame, restrict search to windows on that frame.
Anything else means restrict to WINDOW's frame.
-Optional fourth argument CONSOLE controls which consoles or devices the
+Optional fourth arg CONSOLE controls which consoles or devices the
returned window may be on. If CONSOLE is a console, return windows only
on that console. If CONSOLE is a device, return windows only on that
device. If CONSOLE is a console type, return windows only on consoles
minibuf = (minibuf_level ? minibuf_window : Qlambda);
else if (! EQ (minibuf, Qt))
minibuf = Qlambda;
- /* Now minibuf can be t => count all minibuffer windows,
- lambda => count none of them,
+ /* Now `minibuf' is one of:
+ t => count all minibuffer windows
+ lambda => count none of them
or a specific minibuffer window (the active one) to count. */
/* all_frames == nil doesn't specify which frames to include.
return frame_first_window (XFRAME (all_frames));
else if (! EQ (all_frames, Qt))
all_frames = Qnil;
- /* Now all_frames is t meaning search all frames,
- nil meaning search just current frame,
- visible meaning search just visible frames,
- 0 meaning search visible and iconified frames,
- or a window, meaning search the frame that window belongs to. */
+ /* Now `all_frames' is one of:
+ t => search all frames
+ nil => search just the current frame
+ visible => search just visible frames
+ 0 => search visible and iconified frames
+ a window => search the frame that window belongs to. */
/* Do this loop at least once, to get the next window, and perhaps
again, if we hit the minibuffer and that is not acceptable. */
tem = WINDOW_FRAME (XWINDOW (window));
if (! NILP (all_frames))
- /* It's actually important that we use prev_frame here,
+ /* It's actually important that we use previous_frame here,
rather than next_frame. All the windows acceptable
according to the given parameters should form a ring;
Fnext_window and Fprevious_window should go back and
window_loop assumes that these `ring' requirement are
met. */
{
- Lisp_Object tem1;
-
- tem1 = tem;
- tem = prev_frame (tem, all_frames, console);
+ Lisp_Object tem1 = tem;
+ tem = previous_frame (tem, all_frames, console);
/* In the case where the minibuffer is active,
and we include its frame as well as the selected one,
next_frame may get stuck in that frame.
int lose_lose = 0;
Lisp_Object devcons, concons;
- /* FRAME_ARG is Qlambda to stick to one frame,
- Qvisible to consider all visible frames,
- or Qt otherwise. */
-
/* If we're only looping through windows on a particular frame,
FRAME points to that frame. If we're looping through windows
on all frames, FRAME is 0. */
-
if (FRAMEP (frames))
frame = XFRAME (frames);
else if (NILP (frames))
frame = selected_frame ();
else
frame = 0;
+
+ /* FRAME_ARG is Qlambda to stick to one frame,
+ Qvisible to consider all visible frames,
+ or Qt otherwise. */
if (frame)
frame_arg = Qlambda;
else if (ZEROP (frames))
if (NILP (the_frame))
continue;
- if (!device_matches_console_spec (the_frame, device, console))
+ if (!device_matches_console_spec (device,
+ NILP (console) ?
+ FRAME_CONSOLE (XFRAME (the_frame)) :
+ console))
continue;
/* Pick a window to start with. */
/* Pick the next window now, since some operations will delete
the current window. */
- next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, Qt);
+ next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, device);
/* #### Still needed ?? */
/* Given the outstanding quality of the rest of this code,
new_buffer = Fother_buffer (obj, Qnil, Qnil);
if (NILP (new_buffer))
new_buffer = Fget_buffer_create (QSscratch);
- Fset_window_buffer (w, new_buffer);
+ Fset_window_buffer (w, new_buffer, Qnil);
if (EQ (w, Fselected_window (Qnil)))
Fset_buffer (p->buffer);
}
/* Otherwise show a different buffer in the
window. */
p->dedicated = Qnil;
- Fset_window_buffer (w, another_buffer);
+ Fset_window_buffer (w, another_buffer, Qnil);
if (EQ (w, Fselected_window (Qnil)))
Fset_buffer (p->buffer);
}
window_min_height = MIN_SAFE_WINDOW_HEIGHT;
}
+static int
+frame_min_height (struct frame *frame)
+{
+ /* For height, we have to see whether the frame has a minibuffer, and
+ whether it wants a modeline. */
+ return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
+ : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
+ : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
+}
+
+/* Return non-zero if both frame sizes are less than or equal to
+ minimal allowed values. ROWS and COLS are in characters */
+int
+frame_size_valid_p (struct frame *frame, int rows, int cols)
+{
+ return (rows >= frame_min_height (frame)
+ && cols >= MIN_SAFE_WINDOW_WIDTH);
+}
+
+/* Return non-zero if both frame sizes are less than or equal to
+ minimal allowed values. WIDTH and HEIGHT are in pixels */
+int
+frame_pixsize_valid_p (struct frame *frame, int width, int height)
+{
+ int rows, cols;
+ pixel_to_real_char_size (frame, width, height, &cols, &rows);
+ return frame_size_valid_p (frame, rows, cols);
+}
+
/* If *ROWS or *COLS are too small a size for FRAME, set them to the
minimum allowable size. */
void
check_frame_size (struct frame *frame, int *rows, int *cols)
{
- /* For height, we have to see whether the frame has a minibuffer, and
- whether it wants a modeline. */
- int min_height =
- (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1
- : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT
- : 2 * MIN_SAFE_WINDOW_HEIGHT - 1);
+ int min_height = frame_min_height (frame);
if (*rows < min_height)
*rows = min_height;
\f
static int window_select_count;
-DEFUN ("set-window-buffer", Fset_window_buffer, 2, 2, 0, /*
+DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /*
Make WINDOW display BUFFER as its contents.
BUFFER can be a buffer or buffer name.
+
+With non-nil optional argument NORECORD, do not modify the
+global or per-frame buffer ordering.
*/
- (window, buffer))
+ (window, buffer, norecord))
{
Lisp_Object tem;
struct window *w = decode_window (window);
recompute_all_cached_specifiers_in_window (w);
if (EQ (window, Fselected_window (Qnil)))
{
+ if (NILP (norecord))
+ Frecord_buffer (buffer);
+
Fset_buffer (buffer);
}
return Qnil;
The main editor command loop selects the buffer of the selected window
before each command.
-With non-nil optional argument `norecord', do not modify the
+With non-nil optional argument NORECORD, do not modify the
global or per-frame buffer ordering.
*/
(window, norecord))
error ("Trying to select non-leaf window");
w->use_time = make_int (++window_select_count);
+
if (EQ (window, old_selected_window))
return window;
p->line_start_cache = Dynarr_new (line_start_cache);
p->face_cachels = Dynarr_new (face_cachel);
p->glyph_cachels = Dynarr_new (glyph_cachel);
+ p->subwindow_instance_cache =
+ make_lisp_hash_table (30,
+ HASH_TABLE_KEY_VALUE_WEAK,
+ HASH_TABLE_EQ);
/* Put new into window structure in place of window */
replace_window (window, new);
DEFUN ("split-window", Fsplit_window, 0, 3, "", /*
Split WINDOW, putting SIZE lines in the first of the pair.
WINDOW defaults to selected one and SIZE to half its size.
-If optional third arg HOR-FLAG is non-nil, split side by side
+If optional third arg HORFLAG is non-nil, split side by side
and put SIZE columns in the first of the pair.
*/
(window, chsize, horflag))
/* do this last (after the window is completely initialized and
the mirror-dirty flag is set) so that specifier recomputation
caused as a result of this will work properly and not abort. */
- Fset_window_buffer (new, o->buffer);
+ Fset_window_buffer (new, o->buffer, Qt);
return new;
}
\f
}
static int
-window_pixel_height (Lisp_Object window)
-{
- return WINDOW_HEIGHT (XWINDOW (window));
-}
-
-static int
window_pixel_height_to_char_height (struct window *w, int pixel_height,
int include_gutters_p)
{
avail_height = (pixel_height -
(include_gutters_p ? 0 :
- window_top_gutter_height (w) +
- window_bottom_gutter_height (w)));
+ window_top_window_gutter_height (w) +
+ window_bottom_window_gutter_height (w)));
default_face_height_and_width (window, &defheight, &defwidth);
avail_height = char_height * defheight;
pixel_height = (avail_height +
(include_gutters_p ? 0 :
- window_top_gutter_height (w) +
- window_bottom_gutter_height (w)));
+ window_top_window_gutter_height (w) +
+ window_bottom_window_gutter_height (w)));
/* It's the calling function's responsibility to check these values
and make sure they're not out of range.
/* Return number of default lines of text can fit in the window W.
If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus
horizontal scrollbar) in the space that is used for the calculation.
+ This doesn't include space used by the frame gutters.
*/
int
window_char_height (struct window *w, int include_gutters_p)
{
- return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w),
+ return window_pixel_height_to_char_height (w, window_pixel_height (w),
include_gutters_p);
}
return WINDOW_WIDTH (XWINDOW (window));
}
+/* Calculate the pixel of a window, optionally including margin space
+ but no vertical gutters. */
static int
window_pixel_width_to_char_width (struct window *w, int pixel_width,
int include_margins_p)
avail_width = char_width * defwidth;
pixel_width = (avail_width +
- window_left_gutter_width (w, 0) +
- window_right_gutter_width (w, 0) +
+ window_left_window_gutter_width (w, 0) +
+ window_right_window_gutter_width (w, 0) +
(include_margins_p ? 0 : window_left_margin_width (w)) +
(include_margins_p ? 0 : window_right_margin_width (w)));
(widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \
? 1 : window_min_height)
+static int
+window_pixheight (Lisp_Object w)
+{
+ return window_pixel_height (XWINDOW (w));
+}
+
/* Unlike set_window_pixheight, this function
also changes the heights of the siblings so as to
keep everything consistent. */
int *sizep;
int (*sizefun) (Lisp_Object) = (widthflag
? window_pixel_width
- : window_pixel_height);
+ : window_pixheight);
void (*setsizefun) (Lisp_Object, int, int) = (widthflag
? set_window_pixwidth
: set_window_pixheight);
if (INTP (Vwindow_pixel_scroll_increment))
fheight = XINT (Vwindow_pixel_scroll_increment);
- else if (!NILP (Vwindow_pixel_scroll_increment));
+ else if (!NILP (Vwindow_pixel_scroll_increment))
default_face_height_and_width (window, &fheight, &fwidth);
-
+
if (Dynarr_length (dla) >= 1)
modeline = Dynarr_atp (dla, 0)->modeline;
dl = Dynarr_atp (dla, modeline);
-
+
if (value > 0)
{
/* Go for partial display line scrolling. This just means bumping
{
int vtarget;
Bufpos startp, old_start;
-
+
if (WINDOW_TEXT_TOP_CLIP (w))
{
WINDOW_TEXT_TOP_CLIP (w) = 0;
old_start = marker_position (w->start[CURRENT_DISP]);
startp = vmotion (w, old_start, value, &vtarget);
-
+
if (vtarget < value &&
(w->window_end_pos[CURRENT_DISP] == -1
|| (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b))))
w->force_start = 1;
w->start_at_line_beg = beginning_of_line_p (b, startp);
MARK_WINDOWS_CHANGED (w);
-
+
if (!point_would_be_visible (w, startp, XINT (point)))
{
if (selected)
{
int vtarget;
Bufpos startp, old_start;
-
+
if (WINDOW_TEXT_TOP_CLIP (w))
{
WINDOW_TEXT_TOP_CLIP (w) = 0;
MARK_WINDOWS_CHANGED (w);
}
-
+
old_start = marker_position (w->start[CURRENT_DISP]);
startp = vmotion (w, old_start, value, &vtarget);
-
+
if (vtarget > value
&& marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b))
{
w->force_start = 1;
w->start_at_line_beg = beginning_of_line_p (b, startp);
MARK_WINDOWS_CHANGED (w);
-
+
+ /* #### Scroll back by less than a line. This code was
+ originally for scrolling over large pixmaps and it
+ loses when a line being *exposed* at the top of the
+ window is bigger than the current one. However, for
+ pixel based scrolling in general we can guess that
+ the line we are going to display is probably the same
+ size as the one we are on. In that instance we can
+ have a reasonable stab at a suitable top clip. Fixing
+ this properly is hard (and probably slow) as we would
+ have to call redisplay to figure out the exposed line
+ size. */
+ if (!NILP (Vwindow_pixel_scroll_increment)
+ && Dynarr_length (dla) >= (1 + modeline)
+ && dl->ascent + fheight * value > 0)
+ {
+ WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value);
+ }
+
if (!point_would_be_visible (w, startp, XINT (point)))
{
Bufpos new_point;
-
+
if (MINI_WINDOW_P (w))
new_point = startp;
else
new_point = start_of_last_line (w, startp);
-
+
if (selected)
BUF_SET_PT (b, new_point);
else
int pixel_width;
int pixel_height;
int hscroll;
- int modeline_hscroll;
+ Charcount modeline_hscroll;
int parent_index; /* index into saved_windows */
int prev_index; /* index into saved_windows */
char start_at_line_beg; /* boolean */
#define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config)
#define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration)
#define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration)
-#define GC_WINDOW_CONFIGURATIONP(x) GC_RECORDP (x, window_configuration)
#define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration)
static Lisp_Object
}
static size_t
-sizeof_window_config (CONST void *h)
+sizeof_window_config (const void *h)
{
- CONST struct window_config *c = (CONST struct window_config *) h;
+ const struct window_config *c = (const struct window_config *) h;
return sizeof_window_config_for_n_windows (c->saved_windows_count);
}
int previous_pixel_width;
int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width;
int real_font_height;
- int converted_minibuf_height,target_minibuf_height;
+ int converted_minibuf_height,target_minibuf_height;
int specpdl_count = specpdl_depth ();
GCPRO1 (configuration);
record_unwind_protect (free_window_configuration, old_window_config);
mark_windows_in_use (f, 1);
-
+#ifdef BROKEN_SUBWINDOW_REDISPLAY
+ /* Force subwindows to be remapped. This is overkill but saves
+ us having to rely on the redisplay code to unmap any extant
+ subwindows.
+
+ #### It does cause some extra flashing though which we could
+ possibly avoid. So consider trying to get redisplay to work
+ correctly.
+
+ Removing the instances from the frame cache is wrong because
+ an instance is only put in the frame cache when it is
+ instantiated. So if we do this there is a chance that stuff
+ will never get put back in the frame cache. */
+ reset_frame_subwindow_instance_cache (f);
+#endif
#if 0
/* JV: This is bogus,
First of all, the units are inconsistent. The frame sizes are measured
- in characters but the window sizes are stored in pixels. So if a
+ in characters but the window sizes are stored in pixels. So if a
font size change happened between saving and restoring, the
frame "sizes" maybe equal but the windows still should be
- resized. This is tickled alot by the new "character size
- stays constant" policy in 21.0. It leads to very wierd
- glitches (and possibly craches when asserts are tickled).
+ resized. This is tickled a lot by the new "character size
+ stays constant" policy in 21.0. It leads to very weird
+ glitches (and possibly crashes when asserts are tickled).
- Just changing the units doens't help because changing the
+ Just changing the units doesn't help because changing the
toolbar configuration can also change the pixel positions.
Luckily there is a much simpler way of doing this, see below.
*/
|| config->frame_width != FRAME_WIDTH (f))
change_frame_size (f, config->frame_height, config->frame_width, 0);
#endif
-
+
previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top;
previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height;
previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left;
default_face_height_and_width (frame, &real_font_height, 0);
assert(real_font_height > 0);
-
+
if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
{
previous_minibuf_height
else
{
previous_minibuf_height = 0;
+ previous_minibuf_top = 0;
previous_minibuf_width = 0;
}
converted_minibuf_height =
(previous_minibuf_height % real_font_height) == 0 ?
- (previous_minibuf_height / real_font_height ) : /* lines */
previous_minibuf_height; /* pixels */
-
+
/* Temporarily avoid any problems with windows that are smaller
than they are supposed to be. */
window_min_height = 1;
w->glyph_cachels = Dynarr_new (glyph_cachel);
if (!w->line_start_cache)
w->line_start_cache = Dynarr_new (line_start_cache);
+ w->gutter_extent_modiff[0] = 0;
+ w->gutter_extent_modiff[1] = 0;
+ w->gutter_extent_modiff[2] = 0;
+ w->gutter_extent_modiff[3] = 0;
w->dead = 0;
if (p->parent_index >= 0)
w->hscroll = p->hscroll;
w->modeline_hscroll = p->modeline_hscroll;
w->line_cache_last_updated = Qzero;
+ /* When we restore a window's configuration, the identity of
+ the window hasn't actually changed - so there is no
+ reason why we shouldn't preserve the instance cache for
+ it - unless it was originally deleted. This will often
+ buy us something as we will not have to re-instantiate
+ all the instances. This is because this is an instance
+ cache - not a display cache. Preserving the display cache
+ would definitely be wrong.
+
+ We specifically want to do this for tabs, since for some
+ reason finding a file will cause the configuration to be
+ set. */
+ if (NILP (w->subwindow_instance_cache))
+ w->subwindow_instance_cache =
+ make_lisp_hash_table (30,
+ HASH_TABLE_KEY_VALUE_WEAK,
+ HASH_TABLE_EQ);
SET_LAST_MODIFIED (w, 1);
SET_LAST_FACECHANGE (w);
w->config_mark = 0;
+ /* #### Consider making the instance cache a winslot. */
#define WINDOW_SLOT(slot, compare) w->slot = p->slot
#include "winslots.h"
#### Now we get more cases correct then ever before, but
are we treating all? For instance what if the frames minibuf window
- is no longer the same one?
+ is no longer the same one?
*/
target_minibuf_height = previous_minibuf_height;
if (converted_minibuf_height &&
set_window_pixwidth (FRAME_MINIBUF_WINDOW (f),
previous_minibuf_width, 0);
}
-
+
/* This is a better way to deal with frame resizing, etc.
What we _actually_ want is for the old (just restored)
root window to fit
/* Note that this function also updates the subwindow
"pixel_left"s */
set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0);
-
+
/* If restoring in the current frame make the window current,
otherwise just update the frame selected_window slot to be
the restored current_window. */
if (f == selected_frame ())
{
+#if 0
/* When using `pop-window-configuration', often the minibuffer
ends up as the selected window even though it's not active ...
I really don't know the cause of this, but it should never
#### Find out why this is really going wrong. */
if (!minibuf_level &&
MINI_WINDOW_P (XWINDOW (config->current_window)))
- Fselect_window (Fnext_window (config->current_window,
- Qnil, Qnil, Qnil),
- Qnil);
+ window_to_select = Fnext_window (config->current_window,
+ Qnil, Qnil, Qnil);
else
- Fselect_window (config->current_window, Qnil);
+ window_to_select = config->current_window;
+#endif
+ /* Do this last so that buffer stacking is calculated
+ correctly. */
+ Fselect_window (config->current_window, Qnil);
+
if (!NILP (new_current_buffer))
- Fset_buffer (new_current_buffer);
+ {
+ Fset_buffer (new_current_buffer);
+ Frecord_buffer (new_current_buffer);
+ }
else
- Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer);
+ {
+ Fset_buffer (XWINDOW (config->current_window)->buffer);
+ Frecord_buffer (XWINDOW (config->current_window)->buffer);
+ }
}
else
set_frame_selected_window (f, config->current_window);
/*
config->frame_width = FRAME_WIDTH (f);
config->frame_height = FRAME_HEIGHT (f); */
- config->current_window = FRAME_SELECTED_WINDOW (f);
+ /* When using `push-window-configuration', often the minibuffer ends
+ up as the selected window because functions run as the result of
+ user interaction e.g. hyper-apropos. It seems to me the sensible
+ thing to do is not record the minibuffer here. */
+ if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level)
+ config->current_window = FRAME_SELECTED_WINDOW (f);
+ else
+ config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f);
XSETBUFFER (config->current_buffer, current_buffer);
config->minibuffer_scroll_window = Vminibuffer_scroll_window;
config->root_window = FRAME_ROOT_WINDOW (f);
/* save the minibuffer height using the heuristics from
change_frame_size_1 */
-
+
XSETFRAME (frame, f); /* frame could have been nil ! */
default_face_height_and_width (frame, &real_font_height, 0);
assert(real_font_height > 0);
-
+
if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f))
minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
else
if (NILP (pos))
pos = Fwindow_point (window);
-
+
CHECK_INT (pos);
point = XINT (pos);
}
else
{
- /* optimised case */
+ /* optimized case */
dl = Dynarr_atp (dla, y);
db = get_display_block_from_line (dl, TEXT);
child = Fwindow_first_hchild (window);
for (i = level; i > 0; i--)
- putc ('\t', stderr);
+ stderr_out ("\t");
- fputs ("#<window", stderr);
+ stderr_out ("#<window");
{
Lisp_Object buffer = XWINDOW (window)->buffer;
if (!NILP (buffer) && BUFFERP (buffer))
- fprintf (stderr, " on %s", XSTRING_DATA (XBUFFER (buffer)->name));
+ stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name));
}
- fprintf (stderr, " 0x%x>", XWINDOW (window)->header.uid);
+ stderr_out (" 0x%x>", XWINDOW (window)->header.uid);
while (!NILP (child))
{
void
syms_of_window (void)
{
+ INIT_LRECORD_IMPLEMENTATION (window);
+ INIT_LRECORD_IMPLEMENTATION (window_configuration);
+
defsymbol (&Qwindowp, "windowp");
defsymbol (&Qwindow_live_p, "window-live-p");
defsymbol (&Qwindow_configurationp, "window-configuration-p");
DEFSUBR (Fwindow_height);
DEFSUBR (Fwindow_displayed_height);
DEFSUBR (Fwindow_width);
+ DEFSUBR (Fwindow_full_width);
DEFSUBR (Fwindow_pixel_height);
DEFSUBR (Fwindow_pixel_width);
+ DEFSUBR (Fwindow_text_area_height);
DEFSUBR (Fwindow_text_area_pixel_height);
DEFSUBR (Fwindow_displayed_text_pixel_height);
DEFSUBR (Fwindow_text_area_pixel_width);
DEFSUBR (Fwindow_hscroll);
-#ifdef MODELINE_IS_SCROLLABLE
+ DEFSUBR (Fset_window_hscroll);
DEFSUBR (Fmodeline_hscroll);
DEFSUBR (Fset_modeline_hscroll);
-#endif /* MODELINE_IS_SCROLLABLE */
#if 0 /* bogus FSF crock */
DEFSUBR (Fwindow_redisplay_end_trigger);
DEFSUBR (Fset_window_redisplay_end_trigger);
#endif
- DEFSUBR (Fset_window_hscroll);
DEFSUBR (Fwindow_pixel_edges);
DEFSUBR (Fwindow_text_area_pixel_edges);
DEFSUBR (Fwindow_point);
DEFSUBR (Fwindow_start);
DEFSUBR (Fwindow_end);
+ DEFSUBR (Fwindow_last_line_visible_height);
DEFSUBR (Fset_window_point);
DEFSUBR (Fset_window_start);
DEFSUBR (Fwindow_dedicated_p);
Used by `with-output-to-temp-buffer'.
If this function is used, then it must do the entire job of showing
the buffer; `temp-buffer-show-hook' is not run unless this function runs it.
+\(`temp-buffer-show-hook' is obsolete. Do not use in new code.)
*/ );
Vtemp_buffer_show_function = Qnil;
Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2),
Qnil, Qnil, Qnil);
set_specifier_caching (Vmodeline_shadow_thickness,
- slot_offset (struct window,
- modeline_shadow_thickness),
+ offsetof (struct window, modeline_shadow_thickness),
modeline_shadow_thickness_changed,
0, 0);
set_specifier_fallback (Vhas_modeline_p,
list1 (Fcons (Qnil, Qt)));
set_specifier_caching (Vhas_modeline_p,
- slot_offset (struct window,
- has_modeline_p),
+ offsetof (struct window, has_modeline_p),
/* #### It's strange that we need a special
flag to indicate that the shadow-thickness
has changed, but not one to indicate that
set_specifier_fallback (Vvertical_divider_always_visible_p,
list1 (Fcons (Qnil, Qt)));
set_specifier_caching (Vvertical_divider_always_visible_p,
- slot_offset (struct window,
- vertical_divider_always_visible_p),
+ offsetof (struct window,
+ vertical_divider_always_visible_p),
vertical_divider_changed_in_window,
0, 0);
Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2),
Qnil, Qnil, Qnil);
set_specifier_caching (Vvertical_divider_shadow_thickness,
- slot_offset (struct window,
- vertical_divider_shadow_thickness),
+ offsetof (struct window,
+ vertical_divider_shadow_thickness),
vertical_divider_changed_in_window,
0, 0);
DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /*
set_specifier_fallback (Vvertical_divider_line_width, fb);
}
set_specifier_caching (Vvertical_divider_line_width,
- slot_offset (struct window,
- vertical_divider_line_width),
+ offsetof (struct window,
+ vertical_divider_line_width),
vertical_divider_changed_in_window,
0, 0);
set_specifier_fallback (Vvertical_divider_spacing, fb);
}
set_specifier_caching (Vvertical_divider_spacing,
- slot_offset (struct window,
- vertical_divider_spacing),
+ offsetof (struct window, vertical_divider_spacing),
vertical_divider_changed_in_window,
0, 0);
}