/* Window creation, deletion and examination for GNU Emacs.
Does not include redisplay.
- Copyright (C) 1985,86,87,93,94,95,96,97,1998,2000, 2001
+ Copyright (C) 1985,86,87,93,94,95,96,97,1998,2000, 2001, 2002
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#ifdef MSDOS
#include "msdos.h"
#endif
-#ifdef macintosh
+#ifdef MAC_OS
#include "macterm.h"
#endif
ON_VERTICAL_BORDER,
ON_HEADER_LINE,
ON_LEFT_FRINGE,
- ON_RIGHT_FRINGE
+ ON_RIGHT_FRINGE,
+ ON_LEFT_MARGIN,
+ ON_RIGHT_MARGIN
};
Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
Lisp_Object Qwindow_size_fixed;
+extern Lisp_Object Qleft_margin, Qright_margin;
extern Lisp_Object Qheight, Qwidth;
static int displayed_window_lines P_ ((struct window *));
/* If a window gets smaller than either of these, it is removed. */
-int window_min_height;
-int window_min_width;
+EMACS_INT window_min_height;
+EMACS_INT window_min_width;
/* Nonzero implies Fdisplay_buffer should create windows. */
/* Fdisplay_buffer always splits the largest window
if that window is more than this high. */
-int split_height_threshold;
+EMACS_INT split_height_threshold;
/* Number of lines of continuity in scrolling by screenfuls. */
-int next_screen_context_lines;
+EMACS_INT next_screen_context_lines;
/* Incremented for each window created. */
static int inhibit_frame_unsplittable;
#endif /* 0 */
-extern int scroll_margin;
+extern EMACS_INT scroll_margin;
extern Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
\f
bzero (&p->phys_cursor, sizeof (p->phys_cursor));
p->desired_matrix = p->current_matrix = 0;
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);
XSETWINDOW (val, p);
XSETFASTINT (p->last_point, 0);
p->frozen_window_start_p = 0;
+ p->height_fixed_p = 0;
+ p->last_cursor_off_p = p->cursor_off_p = 0;
Vwindow_list = Qnil;
return val;
DEFUN ("set-window-hscroll", Fset_window_hscroll, Sset_window_hscroll, 2, 2, 0,
doc: /* Set number of columns WINDOW is scrolled from left margin to NCOL.
-NCOL should be zero or positive. */)
+NCOL should be zero or positive.
+
+Note that if `automatic-hscrolling' is non-nil, you cannot scroll the
+window so that the location of point becomes invisible. */)
(window, ncol)
Lisp_Object window, ncol;
{
return 3.
if it is on the window's top line, return 4;
if it is in left or right fringe of the window,
- return 5 or 6, and convert *X and *Y to window-relative corrdinates.
+ return 5 or 6, and convert *X and *Y to window-relative coordinates;
+ if it is in the marginal area to the left/right of the window,
+ return 7 or 8, and convert *X and *Y to window-relative coordinates.
X and Y are frame relative pixel coordinates. */
/* The width of the area where the vertical line can be dragged.
(Between mode lines for instance. */
int grabbable_width = ux;
+ int lmargin_width = 0, rmargin_width = 0;
if (*x < x0 || *x >= x1)
return ON_NOTHING;
}
else
{
- *x -= left_x;
- *y -= top_y;
- part = ON_TEXT;
+ lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
+ rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
+ /* You can never be on a margin area if its width is zero. */
+ if (lmargin_width
+ && *x <= window_box_right (w, LEFT_MARGIN_AREA))
+ part = ON_LEFT_MARGIN;
+ else if (rmargin_width
+ && *x >= window_box_left (w, RIGHT_MARGIN_AREA))
+ part = ON_RIGHT_MARGIN;
+ else
+ {
+ part = ON_TEXT;
+ *x -= left_x;
+ *y -= top_y;
+ }
}
}
else
}
else
{
- /* Convert X and Y to window-relative pixel coordinates. */
- *x -= left_x;
- *y -= top_y;
- part = ON_TEXT;
+ lmargin_width = window_box_width (w, LEFT_MARGIN_AREA);
+ rmargin_width = window_box_width (w, RIGHT_MARGIN_AREA);
+ /* You can never be on a margin area if its width is zero.
+ This is especially important for character terminals. */
+ if (lmargin_width
+ && *x <= window_box_right (w, LEFT_MARGIN_AREA))
+ part = ON_LEFT_MARGIN;
+ else if (rmargin_width
+ && *x >= window_box_left (w, RIGHT_MARGIN_AREA))
+ part = ON_RIGHT_MARGIN;
+ else
+ {
+ part = ON_TEXT;
+ /* Convert X and Y to window-relative pixel coordinates. */
+ *x -= left_x;
+ *y -= top_y;
+ }
}
}
If they are in the left fringe of WINDOW, `left-fringe' is returned.
If they are in the right fringe of WINDOW, `right-fringe' is returned.
If they are on the border between WINDOW and its right sibling,
- `vertical-line' is returned. */)
+ `vertical-line' is returned.
+If they are in the windows's left or right marginal areas, `left-margin'\n\
+ or `right-margin' is returned. */)
(coordinates, window)
register Lisp_Object coordinates, window;
{
case ON_RIGHT_FRINGE:
return Qright_fringe;
+ case ON_LEFT_MARGIN:
+ return Qleft_margin;
+
+ case ON_RIGHT_MARGIN:
+ return Qright_margin;
+
default:
abort ();
}
struct buffer *old_buffer = NULL, *b = XBUFFER (buf);
/* In case W->start is out of the range, use something
- reasonable. This situation occured when loading a file with
+ reasonable. This situation occurred when loading a file with
`-l' containing a call to `rmail' with subsequent other
commands. At the end, W->start happened to be BEG, while
rmail had already narrowed the buffer. */
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);
if (!NILP (obj) && !WINDOW_FULL_WIDTH_P (w))
break;
/* Ignore dedicated windows and minibuffers. */
- if (MINI_WINDOW_P (w) || !NILP (w->dedicated))
+ if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
break;
if (NILP (best_window)
|| (XFASTINT (XWINDOW (best_window)->use_time)
case GET_LARGEST_WINDOW:
{
/* Ignore dedicated windows and minibuffers. */
- if (MINI_WINDOW_P (w) || !NILP (w->dedicated))
+ if (MINI_WINDOW_P (w) || EQ (w->dedicated, Qt))
break;
if (NILP (best_window))
/* Now we can safely delete the frame. */
Fdelete_frame (w->frame, Qnil);
}
+ else if (!NILP (w->dedicated) && !NILP (w->parent))
+ {
+ Lisp_Object window;
+ XSETWINDOW (window, w);
+ /* If this window is dedicated and not the only window
+ in its frame, then kill it. */
+ Fdelete_window (window);
+ }
else
{
/* Otherwise show a different buffer in the window. */
{
struct window *w = XWINDOW (window);
struct buffer *b = XBUFFER (buffer);
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
w->buffer = buffer;
{
if (!NILP (w->dedicated) && !EQ (tem, buffer))
error ("Window is dedicated to `%s'",
- XSTRING (XBUFFER (tem)->name)->data);
+ SDATA (XBUFFER (tem)->name));
unshow_buffer (w);
}
DEFUN ("select-window", Fselect_window, Sselect_window, 1, 1, 0,
doc: /* Select WINDOW. Most editing will apply to WINDOW's buffer.
If WINDOW is not already selected, also make WINDOW's buffer current.
+Also make WINDOW the frame's selected window.
+
Note that the main editor command loop
selects the buffer of the selected window before each command. */)
(window)
argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).
If `pop-up-frames' is non-nil, make a new frame if no window shows BUFFER.
Returns the window displaying BUFFER.
-If `display-reuse-frames' is non-nil, and another frame is currently
+If `display-buffer-reuse-frames' is non-nil, and another frame is currently
displaying BUFFER, then simply raise that frame.
The variables `special-display-buffer-names', `special-display-regexps',
}
}
- /* If the user wants pop-up-frames or display-reuse-frames, then
+ /* If the user wants pop-up-frames or display-buffer-reuse-frames,
look for a window showing BUFFER on any visible or iconified frame.
Otherwise search only the current frame. */
if (! NILP (frame))
frames = Qnil;
if (FRAME_MINIBUF_ONLY_P (f))
XSETFRAME (frames, last_nonminibuf_frame);
- /* Don't try to create a window if would get an error */
+ /* Don't try to create a window if we would get an error. */
if (split_height_threshold < window_min_height << 1)
split_height_threshold = window_min_height << 1;
BEGV = BEG;
ZV = Z;
SET_PT (BEG);
+#if 0 /* rms: there should be no reason for this. */
XBUFFER (buf)->prevent_redisplay_optimizations_p = 1;
+#endif
set_buffer_internal (old);
if (!EQ (Vtemp_buffer_show_function, Qnil))
set_marker_restricted_both (w->pointm, buf, 1, 1);
/* Run temp-buffer-show-hook, with the chosen window selected
- and it sbuffer current. */
+ and its buffer current. */
if (!NILP (Vrun_hooks))
{
Lisp_Object tem;
tem = Fsymbol_value (Qtemp_buffer_show_hook);
if (!NILP (tem))
{
- int count = specpdl_ptr - specpdl;
+ int count = SPECPDL_INDEX ();
Lisp_Object prev_window;
prev_window = selected_window;
/* Select the window that was chosen, for running the hook. */
+ /* Both this Fselect_window and the select_window_1
+ below will (may) incorrectly set-buffer to the buffer
+ displayed in the window. --stef */
record_unwind_protect (Fselect_window, prev_window);
select_window_1 (window, 0);
Fset_buffer (w->buffer);
return Qnil;
}
-DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 2, "p",
+DEFUN ("shrink-window", Fshrink_window, Sshrink_window, 1, 3, "p",
doc: /* Make current window ARG lines smaller.
From program, optional second arg non-nil means shrink sideways arg columns.
-Interactively, if an argument is not given, make the window one line smaller. */)
- (arg, side)
- register Lisp_Object arg, side;
+Interactively, if an argument is not given, make the window one line smaller.
+
+Optional third arg PRESERVE-BEFORE, if non-nil, means do not change the size
+of the siblings above or to the left of the selected window. Only
+siblings to the right or below are changed. */)
+ (arg, side, preserve_before)
+ register Lisp_Object arg, side, preserve_before;
{
CHECK_NUMBER (arg);
- enlarge_window (selected_window, -XINT (arg), !NILP (side), 0);
+ enlarge_window (selected_window, -XINT (arg), !NILP (side),
+ !NILP (preserve_before));
if (! NILP (Vwindow_configuration_change_hook))
call1 (Vrun_hooks, Qwindow_configuration_change_hook);
delta1/n = delta
delta1 = n * delta.
- The number of children n rquals the number of resizable
+ The number of children n equals the number of resizable
children of this window + 1 because we know window itself
is resizable (otherwise we would have signalled an error. */
int whole;
int noerror;
{
+ immediate_quit = 1;
+
/* If we must, use the pixel-based version which is much slower than
the line-based one but can handle varying line heights. */
if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
window_scroll_pixel_based (window, n, whole, noerror);
else
window_scroll_line_based (window, n, whole, noerror);
+
+ immediate_quit = 0;
}
else
move_it_by_lines (&it, n, 1);
- /* End if we end up at ZV or BEGV. */
+ /* We failed if we find ZV is already on the screen (scrolling up,
+ means there's nothing past the end), or if we can't start any
+ earlier (scrolling down, means there's nothing past the top). */
if ((n > 0 && IT_CHARPOS (it) == ZV)
|| (n < 0 && IT_CHARPOS (it) == CHARPOS (start)))
{
if (IT_CHARPOS (it) == ZV)
{
- if (it.current_y + it.max_ascent + it.max_descent
- > it.last_visible_y)
+ if (it.current_y < it.last_visible_y
+ && (it.current_y + it.max_ascent + it.max_descent
+ >= it.last_visible_y))
{
/* The last line was only partially visible, make it fully
visible. */
if (! vscrolled)
{
+ int pos = IT_CHARPOS (it);
+ int bytepos;
/* Set the window start, and set up the window for redisplay. */
- set_marker_restricted (w->start, make_number (IT_CHARPOS (it)),
+ set_marker_restricted (w->start, make_number (pos),
w->buffer);
- w->start_at_line_beg = Fbolp ();
+ 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);
in the scroll margin at the top. */
move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
while (it.current_y < this_scroll_margin)
- move_it_by_lines (&it, 1, 1);
+ {
+ 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)
Lisp_Object n;
int direction;
{
- int count = BINDING_STACK_SIZE ();
+ int count = SPECPDL_INDEX ();
xassert (abs (direction) == 1);
{
Lisp_Object window;
struct window *w;
- int count = BINDING_STACK_SIZE ();
+ int count = SPECPDL_INDEX ();
window = Fother_window_for_scrolling ();
w = XWINDOW (window);
return result;
}
+DEFUN ("minibuffer-selected-window", Fminibuffer_selected_window, Sminibuffer_selected_window, 0, 0, 0,
+ doc: /* Return the window which was selected when entering the minibuffer.
+Returns nil, if current window is not a minibuffer window. */)
+ ()
+{
+ if (minibuf_level > 0
+ && MINI_WINDOW_P (XWINDOW (selected_window))
+ && !NILP (minibuf_selected_window)
+ && WINDOW_LIVE_P (minibuf_selected_window))
+ return minibuf_selected_window;
+
+ return Qnil;
+}
+
/* Value is the number of lines actually displayed in window W,
as opposed to its height. */
move_it_vertically (&it, height);
bottom_y = line_bottom_y (&it);
+ /* rms: On a non-window display,
+ the value of it.vpos at the bottom of the screen
+ seems to be 1 larger than window_box_height (w).
+ This kludge fixes a bug whereby (move-to-window-line -1)
+ when ZV is on the last screen line
+ moves to the previous screen line instead of the last one. */
+ if (! FRAME_WINDOW_P (XFRAME (w->frame)))
+ height++;
+
/* Add in empty lines at the bottom of the window. */
if (bottom_y < height)
{
/* Set the new window start. */
set_marker_both (w->start, w->buffer, charpos, bytepos);
w->window_end_valid = Qnil;
- w->force_start = Qt;
+
+ w->optional_new_start = Qt;
+
if (bytepos == BEGV_BYTE || FETCH_BYTE (bytepos - 1) == '\n')
w->start_at_line_beg = Qt;
else
{
if (XBUFFER (new_current_buffer) == current_buffer)
old_point = PT;
+ else
+ old_point = BUF_PT (XBUFFER (new_current_buffer));
}
frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
p->mark, w->buffer);
/* As documented in Fcurrent_window_configuration, don't
- save the location of point in the buffer which was current
- when the window configuration was recorded. */
+ restore the location of point in the buffer which was
+ current when the window configuration was recorded. */
if (!EQ (p->buffer, new_current_buffer)
&& XBUFFER (p->buffer) == current_buffer)
Fgoto_char (w->pointm);
FRAME_ROOT_WINDOW (f) = data->root_window;
/* Prevent "swapping out point" in the old selected window
using the buffer that has been restored into it.
- That swapping out has already been done,
- near the beginning of this function. */
+ Use the point value from the beginning of this function
+ since unshow_buffer (called from delete_all_subwindows)
+ could have altered it. */
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);
XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
= selected_window;
else if (EQ (leaf_windows[i]->buffer, new_current_buffer))
++n;
}
-
- /* If more than one window shows the new and old current buffer,
- don't try to preserve point in that buffer. */
- if (old_point > 0 && n > 1)
- old_point = -1;
adjust_glyphs (f);
}
if (!NILP (new_current_buffer))
- {
- Fset_buffer (new_current_buffer);
-
- /* If the buffer that is current now is the same
- that was current before setting the window configuration,
- don't alter its PT. */
- if (old_point >= 0)
- SET_PT (old_point);
- }
+ Fset_buffer (new_current_buffer);
/* Restore the minimum heights recorded in the configuration. */
window_min_height = XINT (data->min_height);
Lisp_Object args;
{
register Lisp_Object val;
- register int count = specpdl_ptr - specpdl;
+ register int count = SPECPDL_INDEX ();
record_unwind_protect (Fset_window_configuration,
Fcurrent_window_configuration (Qnil));
staticpro (&Qtemp_buffer_show_hook);
staticpro (&Vwindow_list);
+
+ minibuf_selected_window = Qnil;
staticpro (&minibuf_selected_window);
DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function,
doc: /* Function to call to make a new frame for a special buffer.
It is called with two arguments, the buffer and optional buffer specific
data, and should return a window displaying that buffer.
-The default value makes a separate frame for the buffer,
-using `special-display-frame-alist' to specify the frame parameters.
-
-A buffer is special if its is listed in `special-display-buffer-names'
+The default value normally makes a separate frame for the buffer,
+ using `special-display-frame-alist' to specify the frame parameters.
+But if the buffer specific data includes (same-buffer . t) then the
+ buffer is displayed in the current selected window.
+Otherwise if it includes (same-frame . t) then the buffer is displayed in
+ a new window in the currently selected frame.
+
+A buffer is special if it is listed in `special-display-buffer-names'
or matches a regexp in `special-display-regexps'. */);
Vspecial_display_function = Qnil;
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);