/* Window creation, deletion and examination for GNU Emacs.
Does not include redisplay.
- Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1985, 1986, 1987, 1993 Free Software Foundation, Inc.
This file is part of GNU Emacs.
along with GNU Emacs; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-#include "config.h"
+#include <config.h>
#include "lisp.h"
#include "buffer.h"
#include "frame.h"
#include "disptab.h"
#include "keyboard.h"
-Lisp_Object Qwindowp;
+Lisp_Object Qwindowp, Qwindow_live_p;
Lisp_Object Fnext_window (), Fdelete_window (), Fselect_window ();
Lisp_Object Fset_window_buffer (), Fsplit_window (), Frecenter ();
-static void delete_all_subwindows ();
+void delete_all_subwindows ();
static struct window *decode_window();
/* This is the window in which the terminal's cursor should
/* Non-nil means this is the buffer whose window C-M-v should scroll. */
Lisp_Object Vother_window_scroll_buffer;
-/* Window that the mouse is over (nil if no mouse support). */
-Lisp_Object Vmouse_window;
-
-/* Last mouse click data structure (nil if no mouse support). */
-Lisp_Object Vmouse_event;
-
/* Non-nil means it's function to call to display temp buffers. */
Lisp_Object Vtemp_buffer_show_function;
return XTYPE (obj) == Lisp_Window ? Qt : Qnil;
}
+DEFUN ("window-live-p", Fwindow_live_p, Swindow_live_p, 1, 1, 0,
+ "Returns t if OBJ is a window which is currently visible.")
+ (obj)
+ Lisp_Object obj;
+{
+ return ((XTYPE (obj) == Lisp_Window
+ && ! NILP (XWINDOW (obj)->buffer))
+ ? Qt : Qnil);
+}
+
Lisp_Object
make_window ()
{
return FRAME_MINIBUF_WINDOW (XFRAME (frame));
}
-DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 1, 1, 0,
+DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, Swindow_minibuffer_p, 0, 1, 0,
"Returns non-nil if WINDOW is a minibuffer window.")
(window)
Lisp_Object window;
posint = XINT (pos);
}
- if (NILP (window))
- window = selected_window;
- else
- CHECK_WINDOW (window, 1);
- w = XWINDOW (window);
+ w = decode_window (window);
top = marker_position (w->start);
if (posint < top)
/* If that info is not correct, calculate afresh */
posval = *compute_motion (top, 0, 0, posint, height, 0,
- XFASTINT (w->width) - 1
- - (XFASTINT (w->width) + XFASTINT (w->left)
- != FRAME_WIDTH (XFRAME (w->frame))),
+ window_internal_width (w) - 1,
XINT (w->hscroll), 0);
return posval.vpos < height ? Qt : Qnil;
if (NILP (window))
return XWINDOW (selected_window);
- CHECK_WINDOW (window, 0);
+ CHECK_LIVE_WINDOW (window, 0);
return XWINDOW (window);
}
Lisp_Object window;
{
register struct window *w = decode_window (window);
- register int width = w->width;
+ register int width = XFASTINT (w->width);
- /* If this window does not end at the right margin,
- must deduct one column for the border */
- if ((width + w->left) == FRAME_WIDTH (XFRAME (WINDOW_FRAME (w))))
- return width;
- return width - 1;
+ return make_number (window_internal_width (w));
}
DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
if (XFASTINT (ncol) >= (1 << (SHORTBITS - 1)))
args_out_of_range (ncol, Qnil);
w = decode_window (window);
- if (w->hscroll != ncol)
+ if (XINT (w->hscroll) != XINT (ncol))
clip_changed = 1; /* Prevent redisplay shortcuts */
w->hscroll = ncol;
return ncol;
{
int x, y;
- CHECK_WINDOW (window, 0);
+ CHECK_LIVE_WINDOW (window, 0);
CHECK_CONS (coordinates, 1);
x = XINT (Fcar (coordinates));
y = XINT (Fcdr (coordinates));
}
DEFUN ("window-at", Fwindow_at, Swindow_at, 2, 3, 0,
- "Return window containing row ROW, column COLUMN on FRAME.\n\
+ "Return window containing coordinates X and Y on FRAME.\n\
If omitted, FRAME defaults to the currently selected frame.\n\
The top left corner of the frame is considered to be row 0,\n\
column 0.")
- (row, column, frame)
- Lisp_Object row, column, frame;
+ (x, y, frame)
+ Lisp_Object x, y, frame;
{
int part;
else
CHECK_LIVE_FRAME (frame, 2);
#endif
- CHECK_NUMBER (row, 0);
- CHECK_NUMBER (column, 1);
+ CHECK_NUMBER (x, 0);
+ CHECK_NUMBER (y, 1);
return window_from_coordinates (XFRAME (frame),
- XINT (row), XINT (column),
+ XINT (x), XINT (y),
&part);
}
{
Lisp_Object value;
struct window *w = decode_window (window);
-
+ Lisp_Object buf;
+
+ buf = w->buffer;
+ CHECK_BUFFER (buf, 0);
+
XSET (value, Lisp_Int,
- BUF_Z (current_buffer) - XFASTINT (w->window_end_pos));
+ BUF_Z (XBUFFER (buf)) - XFASTINT (w->window_end_pos));
return value;
}
DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1, 1, 0,
"Return WINDOW's dedicated object, usually t or nil.\n\
-See also `set-window-buffer-dedicated'.")
+See also `set-window-dedicated-p'.")
(window)
Lisp_Object window;
{
/* If OLD is its frame's root_window, then replacement is the new
root_window for that frame. */
- if (old == FRAME_ROOT_WINDOW (XFRAME (o->frame)))
+ if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame))))
FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement;
p->left = o->left;
register struct window *p;
register struct window *par;
+ /* Because this function is called by other C code on non-leaf
+ windows, the CHECK_LIVE_WINDOW macro would choke inappropriately,
+ so we can't decode_window here. */
if (NILP (window))
window = selected_window;
else
CHECK_WINDOW (window, 0);
-
p = XWINDOW (window);
+
+ /* It's okay to delete an already-deleted window. */
+ if (NILP (p->buffer)
+ && NILP (p->hchild)
+ && NILP (p->vchild))
+ return Qnil;
+
parent = p->parent;
if (NILP (parent))
error ("Attempt to delete minibuffer or sole ordinary window");
windows_or_buffers_changed++;
- if (EQ (window, selected_window))
- Fselect_window (Fnext_window (window, Qnil, Qnil));
+ /* Are we trying to delete any frame's selected window? */
+ {
+ Lisp_Object frame, pwindow;
+
+ /* See if the frame's selected window is either WINDOW
+ or any subwindow of it, by finding all that window's parents
+ and comparing each one with WINDOW. */
+ frame = WINDOW_FRAME (XWINDOW (window));
+ pwindow = FRAME_SELECTED_WINDOW (XFRAME (frame));
+
+ while (!NILP (pwindow))
+ {
+ if (EQ (window, pwindow))
+ break;
+ pwindow = XWINDOW (pwindow)->parent;
+ }
+
+ if (EQ (window, pwindow))
+ {
+ Lisp_Object alternative = Fnext_window (window, Qlambda, Qnil);
+
+ /* If we're about to delete the selected window on the
+ selected frame, then we should use Fselect_window to select
+ the new window. On the other hand, if we're about to
+ delete the selected window on any other frame, we shouldn't do
+ anything but set the frame's selected_window slot. */
+ if (EQ (window, selected_window))
+ Fselect_window (alternative);
+ else
+ FRAME_SELECTED_WINDOW (XFRAME (frame)) = alternative;
+ }
+ }
tem = p->buffer;
/* tem is null for dummy parent windows
unshow_buffer (p);
unchain_marker (p->pointm);
unchain_marker (p->start);
- p->buffer = Qnil;
}
tem = p->next;
set_window_{height,width} will re-position the sibling's
children. */
sib = p->next;
- XFASTINT (XWINDOW (sib)->top) = p->top;
- XFASTINT (XWINDOW (sib)->left) = p->left;
+ XWINDOW (sib)->top = p->top;
+ XWINDOW (sib)->left = p->left;
}
/* Stretch that sibling. */
/* If parent now has only one child,
put the child into the parent's place. */
-
tem = par->hchild;
if (NILP (tem))
tem = par->vchild;
if (NILP (XWINDOW (tem)->next))
replace_window (parent, tem);
+
+ /* Since we may be deleting combination windows, we must make sure that
+ not only p but all its children have been marked as deleted. */
+ if (! NILP (p->hchild))
+ delete_all_subwindows (XWINDOW (p->hchild));
+ else if (! NILP (p->vchild))
+ delete_all_subwindows (XWINDOW (p->vchild));
+
+ /* Mark this window as deleted. */
+ p->buffer = p->hchild = p->vchild = Qnil;
+
return Qnil;
}
\f
extern Lisp_Object next_frame (), prev_frame ();
-DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
+/* This comment supplies the doc string for `next-window',
+ for make-docfile to see. We cannot put this in the real DEFUN
+ due to limits in the Unix cpp.
+
+DEFUN ("next-window", Ffoo, Sfoo, 0, 3, 0,
"Return next window after WINDOW in canonical ordering of windows.\n\
If omitted, WINDOW defaults to the selected window.\n\
\n\
\n\
Optional third arg ALL-FRAMES t means include windows on all frames.\n\
ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
-above. If neither nil nor t, restrict to WINDOW's frame.")
+above. If neither nil nor t, restrict to WINDOW's frame.\n\
+\n\
+If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
+`next-window' to iterate through the entire cycle of acceptable\n\
+windows, eventually ending up back at the window you started with.\n\
+`previous-window' traverses the same cycle, in the reverse order.")
+ (window, minibuf, all_frames) */
+
+DEFUN ("next-window", Fnext_window, Snext_window, 0, 3, 0,
+ 0)
(window, minibuf, all_frames)
register Lisp_Object window, minibuf, all_frames;
{
if (NILP (window))
window = selected_window;
else
- CHECK_WINDOW (window, 0);
+ CHECK_LIVE_WINDOW (window, 0);
start_window = window;
: Qnil);
else if (! EQ (all_frames, Qt))
all_frames = Qnil;
+ /* Now all_frames is t meaning search all frames,
+ nil meaning search just current frame,
+ or a window, meaning 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. */
we've come all the way around and we're back at the original window. */
while (MINI_WINDOW_P (XWINDOW (window))
&& ! EQ (minibuf, Qt)
- && window != start_window);
+ && ! EQ (window, start_window));
return window;
}
-DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
+/* This comment supplies the doc string for `previous-window',
+ for make-docfile to see. We cannot put this in the real DEFUN
+ due to limits in the Unix cpp.
+
+DEFUN ("previous-window", Ffoo, Sfoo, 0, 3, 0,
"Return the window preceeding WINDOW in canonical ordering of windows.\n\
If omitted, WINDOW defaults to the selected window.\n\
\n\
\n\
Optional third arg ALL-FRAMES t means include windows on all frames.\n\
ALL-FRAMES nil or omitted means cycle within the frames as specified\n\
-above. If neither nil nor t, restrict to WINDOW's frame.")
+above. If neither nil nor t, restrict to WINDOW's frame.\n\
+\n\
+If you use consistent values for MINIBUF and ALL-FRAMES, you can use\n\
+`previous-window' to iterate through the entire cycle of acceptable\n\
+windows, eventually ending up back at the window you started with.\n\
+`next-window' traverses the same cycle, in the reverse order.")
+ (window, minibuf, all_frames) */
+
+
+DEFUN ("previous-window", Fprevious_window, Sprevious_window, 0, 3, 0,
+ 0)
(window, minibuf, all_frames)
register Lisp_Object window, minibuf, all_frames;
{
if (NILP (window))
window = selected_window;
else
- CHECK_WINDOW (window, 0);
+ CHECK_LIVE_WINDOW (window, 0);
start_window = window;
: Qnil);
else if (! EQ (all_frames, Qt))
all_frames = Qnil;
+ /* Now all_frames is t meaning search all frames,
+ nil meaning search just current frame,
+ or a window, meaning search the frame that window belongs to. */
/* Do this loop at least once, to get the previous window, and perhaps
again, if we hit the minibuffer and that is not acceptable. */
tem = WINDOW_FRAME (XWINDOW (window));
#ifdef MULTI_FRAME
if (! NILP (all_frames))
- tem = next_frame (tem, all_frames);
+ /* It's actually important that we use prev_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
+ forth around the ring. If we use next_frame here,
+ then Fnext_window and Fprevious_window take different
+ paths through the set of acceptable windows.
+ window_loop assumes that these `ring' requirement are
+ met. */
+ tem = prev_frame (tem, all_frames);
#endif
- tem = FRAME_ROOT_WINDOW (XFRAME (tem));
+ /* If this frame has a minibuffer, find that window first,
+ because it is conceptually the last window in that frame. */
+ if (FRAME_HAS_MINIBUF_P (XFRAME (tem)))
+ tem = FRAME_MINIBUF_WINDOW (XFRAME (tem));
+ else
+ tem = FRAME_ROOT_WINDOW (XFRAME (tem));
break;
}
we've come all the way around and we're back at the original window. */
while (MINI_WINDOW_P (XWINDOW (window))
&& !EQ (minibuf, Qt)
- && window != start_window);
+ && !EQ (window, start_window));
return window;
}
\f
/* Look at all windows, performing an operation specified by TYPE
with argument OBJ.
- If FRAMES is Qt, look at all frames, if Qnil, look at just the selected
- frame. If FRAMES is a frame, just look at windows on that frame.
+ If FRAMES is Qt, look at all frames;
+ Qnil, look at just the selected frame;
+ a frame, just look at windows on that frame.
If MINI is non-zero, perform the operation on minibuffer windows too.
*/
DELETE_OTHER_WINDOWS, /* Arg is window not to delete */
DELETE_BUFFER_WINDOWS, /* Arg is buffer */
GET_LARGEST_WINDOW,
- UNSHOW_BUFFER, /* Arg is buffer */
+ UNSHOW_BUFFER /* Arg is buffer */
};
static Lisp_Object
best_window = Qnil;
for (;;)
{
+ FRAME_PTR w_frame = XFRAME (WINDOW_FRAME (XWINDOW (w)));
+
/* Pick the next window now, since some operations will delete
the current window. */
#ifdef MULTI_FRAME
Or we know this isn't a MULTI_FRAME Emacs, so who cares? */
next_window = Fnext_window (w, mini ? Qt : Qnil, Qt);
- if (!MINI_WINDOW_P (XWINDOW (w))
+ if (! MINI_WINDOW_P (XWINDOW (w))
|| (mini && minibuf_level > 0))
switch (type)
{
case GET_BUFFER_WINDOW:
-#if 0
/* Ignore invisible and iconified frames. */
- if (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (w))))
- || FRAME_ICONIFIED_P (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
+ if (! FRAME_VISIBLE_P (w_frame)
+ || FRAME_ICONIFIED_P (w_frame))
break;
-#endif
if (XBUFFER (XWINDOW (w)->buffer) == XBUFFER (obj))
return w;
break;
case GET_LRU_WINDOW:
/* t as arg means consider only full-width windows */
if (!NILP (obj) && XFASTINT (XWINDOW (w)->width)
- != FRAME_WIDTH (frame))
+ != FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (w)))))
break;
#if 0
/* Ignore invisible and iconified frames. */
new_buffer
= Fget_buffer_create (build_string ("*scratch*"));
Fset_window_buffer (w, new_buffer);
- Fset_buffer (XWINDOW (w)->buffer);
+ if (EQ (w, selected_window))
+ Fset_buffer (XWINDOW (w)->buffer);
}
else
Fdelete_window (w);
return best_window;
}
-\f
+
DEFUN ("get-lru-window", Fget_lru_window, Sget_lru_window, 0, 1, 0,
"Return the window least recently selected or used for display.\n\
If optional argument FRAMES is t, search all frames. If FRAME is a\n\
DEFUN ("get-buffer-window", Fget_buffer_window, Sget_buffer_window, 1, 2, 0,
"Return a window currently displaying BUFFER, or nil if none.\n\
-If optional argument FRAMES is t, search all frames. If FRAME is a\n\
-frame, search only that frame.\n")
+If optional argument FRAME is t, search all visible frames.\n\
+If FRAME is nil, search only the selected frame.\n\
+If FRAME is a frame, search only that frame.\n")
(buffer, frame)
Lisp_Object buffer, frame;
{
DEFUN ("delete-other-windows", Fdelete_other_windows, Sdelete_other_windows,
0, 1, "",
"Make WINDOW (or the selected window) fill its frame.\n\
-Only the frame WINDOW is on is affected.")
+Only the frame WINDOW is on is affected.\n\
+This function tries to reduce display jumps\n\
+by keeping the text previously visible in WINDOW\n\
+in the same place on the frame. Doing this depends on\n\
+the value of (window-start WINDOW), so if calling this function\n\
+in a program gives strange scrolling, make sure the window-start\n\
+value is reasonable when this function is called.")
(window)
Lisp_Object window;
{
struct window *w;
- int opoint = point;
struct buffer *obuf = current_buffer;
+ int opoint;
int top;
if (NILP (window))
window = selected_window;
else
- CHECK_WINDOW (window, 0);
+ CHECK_LIVE_WINDOW (window, 0);
w = XWINDOW (window);
top = XFASTINT (w->top);
- window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME(w));
+ window_loop (DELETE_OTHER_WINDOWS, window, 0, WINDOW_FRAME (w));
Fset_buffer (w->buffer);
+ opoint = point;
SET_PT (marker_position (w->start));
- Frecenter (make_number (top));
+ Frecenter (make_number (top - FRAME_MENU_BAR_LINES (XFRAME (WINDOW_FRAME (w)))));
- set_buffer_internal (obuf);
SET_PT (opoint);
+ set_buffer_internal (obuf);
return Qnil;
}
DEFUN ("delete-windows-on", Fdelete_windows_on, Sdelete_windows_on,
- 1, 1, "bDelete windows on (buffer): ",
- "Delete all windows showing BUFFER.")
- (buffer)
- Lisp_Object buffer;
+ 1, 2, "bDelete windows on (buffer): ",
+ "Delete all windows showing BUFFER.\n\
+Optional second argument FRAME controls which frames are affected.\n\
+If nil or omitted, delete all windows showing BUFFER in any frame.\n\
+If t, delete only windows showing BUFFER in the selected frame.\n\
+If a frame, delete only windows showing BUFFER in that frame.")
+ (buffer, frame)
+ Lisp_Object buffer, frame;
{
+#ifdef MULTI_FRAME
+ /* FRAME uses t and nil to mean the opposite of what window_loop
+ expects. */
+ if (! FRAMEP (frame))
+ frame = NILP (frame) ? Qt : Qnil;
+#else
+ frame = Qt;
+#endif
+
if (!NILP (buffer))
{
buffer = Fget_buffer (buffer);
CHECK_BUFFER (buffer, 0);
- window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, Qt);
+ window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, frame);
}
return Qnil;
}
/* If *ROWS or *COLS are too small a size for FRAME, set them to the
minimum allowable size. */
-extern void
+void
check_frame_size (frame, rows, cols)
-FRAME_PTR frame;
-int *rows, *cols;
+ FRAME_PTR frame;
+ int *rows, *cols;
{
- /* For height, we have to see whether the frame has a minibuffer, and
- whether it wants a mode line. */
+ /* For height, we have to see:
+ whether the frame has a minibuffer,
+ whether it wants a mode line, and
+ whether it has a menu bar. */
int min_height =
- ((FRAME_MINIBUF_ONLY_P (frame)
- || ! FRAME_HAS_MINIBUF_P (frame))
- ? MIN_SAFE_WINDOW_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);
+ if (FRAME_MENU_BAR_LINES (frame) > 0)
+ min_height += FRAME_MENU_BAR_LINES (frame);
if (*rows < min_height)
*rows = min_height;
}
w->buffer = buffer;
+ w->window_end_pos = 0;
+ w->window_end_valid = Qnil;
+ w->hscroll = 0;
Fset_marker (w->pointm,
make_number (BUF_PT (XBUFFER (buffer))),
buffer);
make_number (XBUFFER (buffer)->last_window_start),
buffer);
w->start_at_line_beg = Qnil;
+ w->force_start = Qnil;
XFASTINT (w->last_modified) = 0;
windows_or_buffers_changed++;
if (EQ (window, selected_window))
register struct window *w;
register struct window *ow = XWINDOW (selected_window);
- CHECK_WINDOW (window, 0);
+ CHECK_LIVE_WINDOW (window, 0);
w = XWINDOW (window);
if (XFRAME (WINDOW_FRAME (w)) != selected_frame)
{
XFRAME (WINDOW_FRAME (w))->selected_window = window;
- Fselect_frame (WINDOW_FRAME (w), Qnil);
+ Fhandle_switch_frame (WINDOW_FRAME (w), Qnil);
}
else
selected_frame->selected_window = window;
}
DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
- "BDisplay buffer:\nP",
+ "BDisplay buffer: \nP",
"Make BUFFER appear in some window but don't select it.\n\
BUFFER can be a buffer or a buffer name.\n\
If BUFFER is shown already in some window, just use that one,\n\
unless the window is the selected window and the optional second\n\
-argument NOT_THIS_WINDOW is non-nil.\n\
+argument NOT-THIS-WINDOW is non-nil (interactively, with prefix arg).\n\
Returns the window displaying BUFFER.")
(buffer, not_this_window)
register Lisp_Object buffer, not_this_window;
= Fframe_selected_window (call0 (Vpop_up_frame_function));
Fset_window_buffer (window, buffer);
#if 0
- Fselect_frame (XWINDOW (window)->frame, Qnil);
+ Fhandle_switch_frame (XWINDOW (window)->frame, Qnil);
#endif
return window;
}
if (!NILP (window)
&& window_height (window) >= split_height_threshold
- &&
- (XFASTINT (XWINDOW (window)->width)
- == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
+ && (XFASTINT (XWINDOW (window)->width)
+ == FRAME_WIDTH (XFRAME (WINDOW_FRAME (XWINDOW (window))))))
window = Fsplit_window (window, Qnil, Qnil);
else
{
if (NILP (window))
window = selected_window;
else
- CHECK_WINDOW (window, 0);
+ CHECK_LIVE_WINDOW (window, 0);
o = XWINDOW (window);
return ht;
}
+
+/* Return the number of columns in W.
+ Don't count columns occupied by scroll bars or the vertical bar
+ separating W from the sibling to its right. */
+int
+window_internal_width (w)
+ struct window *w;
+{
+ FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
+ int left = XINT (w->left);
+ int width = XINT (w->width);
+
+ /* If this window is flush against the right edge of the frame, its
+ internal width is its full width. */
+ if (left + width >= FRAME_WIDTH (f))
+ return width;
+
+ /* If we are not flush right, then our rightmost columns are
+ occupied by some sort of separator. */
+
+ /* Scroll bars occupy a few columns. */
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+ return width - VERTICAL_SCROLL_BAR_WIDTH;
+
+ /* The column of `|' characters separating side-by-side windows
+ occupies one column only. */
+ return width - 1;
+}
+
+
/* Scroll contents of window WINDOW up N lines. */
void
window = Fdisplay_buffer (Vother_window_scroll_buffer, Qt);
}
else
- /* Nothing specified; pick a neighboring window. */
- window = Fnext_window (selected_window, Qnil, Qt);
- CHECK_WINDOW (window, 0);
+ {
+ /* Nothing specified; look for a neighboring window on the same
+ frame. */
+ window = Fnext_window (selected_window, Qnil, Qnil);
+
+ if (EQ (window, selected_window))
+ /* That didn't get us anywhere; look for a window on another
+ visible frame. */
+ do
+ window = Fnext_window (window, Qnil, Qt);
+ while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window))))
+ && ! EQ (window, selected_window));
+ }
+
+ CHECK_LIVE_WINDOW (window, 0);
if (EQ (window, selected_window))
error ("There is no other window");
}
Fset_marker (w->pointm, make_number (point), Qnil);
- unbind_to (count);
+ unbind_to (count, Qnil);
return Qnil;
}
\f
-DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 1, 1, "P",
+DEFUN ("scroll-left", Fscroll_left, Sscroll_left, 0, 1, "P",
"Scroll selected window display ARG columns left.\n\
Default for ARG is window width minus 2.")
(arg)
{
if (NILP (arg))
- XFASTINT (arg) = XFASTINT (XWINDOW (selected_window)->width) - 2;
+ XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
else
arg = Fprefix_numeric_value (arg);
+ XINT (arg)));
}
-DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 1, 1, "P",
+DEFUN ("scroll-right", Fscroll_right, Sscroll_right, 0, 1, "P",
"Scroll selected window display ARG columns right.\n\
Default for ARG is window width minus 2.")
(arg)
register Lisp_Object arg;
{
if (NILP (arg))
- XFASTINT (arg) = XFASTINT (XWINDOW (selected_window)->width) - 2;
+ XFASTINT (arg) = window_internal_width (XWINDOW (selected_window)) - 2;
else
arg = Fprefix_numeric_value (arg);
}
-DEFUN ("set-window-configuration",
- Fset_window_configuration, Sset_window_configuration,
- 1, 1, 0,
+DEFUN ("set-window-configuration", Fset_window_configuration,
+ Sset_window_configuration, 1, 1, 0,
"Set the configuration of windows and buffers as specified by CONFIGURATION.\n\
CONFIGURATION must be a value previously returned\n\
by `current-window-configuration' (which see).")
(configuration)
Lisp_Object configuration;
{
- register struct window *w;
register struct save_window_data *data;
struct Lisp_Vector *saved_windows;
- register struct saved_window *p;
- register Lisp_Object tem;
Lisp_Object new_current_buffer;
- int k;
+ Lisp_Object frame;
FRAME_PTR f;
- /* If the frame has been resized since this window configuration was
- made, we change the frame to the size specified in the
- configuration, restore the configuration, and then resize it
- back. We keep track of the prevailing height in these variables. */
- int previous_frame_height;
- int previous_frame_width;
-
while (XTYPE (configuration) != Lisp_Window_Configuration)
{
configuration = wrong_type_argument (intern ("window-configuration-p"),
data = (struct save_window_data *) XVECTOR (configuration);
saved_windows = XVECTOR (data->saved_windows);
- f = XFRAME (XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame);
-
- previous_frame_height = FRAME_HEIGHT (f);
- previous_frame_width = FRAME_WIDTH (f);
- if (XFASTINT (data->frame_height) != previous_frame_height
- || XFASTINT (data->frame_width) != previous_frame_width)
- change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
-
- windows_or_buffers_changed++;
new_current_buffer = data->current_buffer;
if (NILP (XBUFFER (new_current_buffer)->name))
new_current_buffer = Qnil;
- /* Kludge Alert!
- Mark all windows now on frame as "deleted".
- Restoring the new configuration "undeletes" any that are in it.
+ frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
+ f = XFRAME (frame);
- Save their current buffers in their height fields, since we may
- need it later, if a buffer saved in the configuration is now
- dead. */
- delete_all_subwindows (XWINDOW (FRAME_ROOT_WINDOW (f)));
-
- for (k = 0; k < saved_windows->size; k++)
+ /* If f is a dead frame, don't bother rebuilding its window tree.
+ However, there is other stuff we should still try to do below. */
+ if (FRAME_LIVE_P (f))
{
- p = SAVED_WINDOW_N (saved_windows, k);
- w = XWINDOW (p->window);
- w->next = Qnil;
+ register struct window *w;
+ register struct saved_window *p;
+ int k;
+
+ /* If the frame has been resized since this window configuration was
+ made, we change the frame to the size specified in the
+ configuration, restore the configuration, and then resize it
+ back. We keep track of the prevailing height in these variables. */
+ int previous_frame_height = FRAME_HEIGHT (f);
+ int previous_frame_width = FRAME_WIDTH (f);
+
+ if (XFASTINT (data->frame_height) != previous_frame_height
+ || XFASTINT (data->frame_width) != previous_frame_width)
+ change_frame_size (f, data->frame_height, data->frame_width, 0, 0);
+
+ windows_or_buffers_changed++;
+
+ /* Kludge Alert!
+ Mark all windows now on frame as "deleted".
+ Restoring the new configuration "undeletes" any that are in it.
+
+ Save their current buffers in their height fields, since we may
+ need it later, if a buffer saved in the configuration is now
+ dead. */
+ 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->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 (!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->width, XWINDOW (w->parent)->width))
+ {
+ XWINDOW (w->parent)->vchild = p->window;
+ XWINDOW (w->parent)->hchild = Qnil;
+ }
+ else
+ {
+ XWINDOW (w->parent)->hchild = p->window;
+ XWINDOW (w->parent)->vchild = Qnil;
+ }
+ }
+ }
+
+ /* If we squirreled away the buffer in the window's height,
+ restore it now. */
+ if (XTYPE (w->height) == Lisp_Buffer)
+ w->buffer = w->height;
+ w->left = p->left;
+ w->top = p->top;
+ w->width = p->width;
+ w->height = p->height;
+ w->hscroll = p->hscroll;
+ w->display_table = p->display_table;
+ XFASTINT (w->last_modified) = 0;
+
+ /* Reinstall the saved buffer and pointers into it. */
+ if (NILP (p->buffer))
+ w->buffer = p->buffer;
+ else
{
- if (EQ (p->width, XWINDOW (w->parent)->width))
+ if (!NILP (XBUFFER (p->buffer)->name))
+ /* If saved buffer is alive, install it. */
{
- XWINDOW (w->parent)->vchild = p->window;
- XWINDOW (w->parent)->hchild = Qnil;
+ w->buffer = p->buffer;
+ w->start_at_line_beg = p->start_at_line_beg;
+ set_marker_restricted (w->start,
+ Fmarker_position (p->start),
+ w->buffer);
+ set_marker_restricted (w->pointm,
+ Fmarker_position (p->pointm),
+ w->buffer);
+ Fset_marker (XBUFFER (w->buffer)->mark,
+ Fmarker_position (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. */
+ 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))
+ /* Else unless window has a live buffer, get one. */
+ {
+ w->buffer = Fcdr (Fcar (Vbuffer_alist));
+ /* This will set the markers to beginning of visible
+ range. */
+ 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
+ /* Keeping window's old buffer; make sure the markers
+ are real. */
{
- XWINDOW (w->parent)->hchild = p->window;
- XWINDOW (w->parent)->vchild = Qnil;
+ /* Set window markers at start of visible range. */
+ 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 (w->pointm,
+ (make_number
+ (BUF_PT (XBUFFER (w->buffer)))),
+ w->buffer);
+ w->start_at_line_beg = Qt;
}
}
}
- /* If we squirreled away the buffer in the window's height,
- restore it now. */
- if (XTYPE (w->height) == Lisp_Buffer)
- w->buffer = w->height;
- w->left = p->left;
- w->top = p->top;
- w->width = p->width;
- w->height = p->height;
- w->hscroll = p->hscroll;
- w->display_table = p->display_table;
- XFASTINT (w->last_modified) = 0;
+ FRAME_ROOT_WINDOW (f) = data->root_window;
+ Fselect_window (data->current_window);
- /* Reinstall the saved buffer and pointers into it. */
- if (NILP (p->buffer))
- w->buffer = p->buffer;
- else
- {
- if (!NILP (XBUFFER (p->buffer)->name))
- /* If saved buffer is alive, install it. */
- {
- w->buffer = p->buffer;
- w->start_at_line_beg = p->start_at_line_beg;
- set_marker_restricted (w->start, Fmarker_position (p->start), w->buffer);
- set_marker_restricted (w->pointm, Fmarker_position (p->pointm), w->buffer);
- Fset_marker (XBUFFER (w->buffer)->mark,
- Fmarker_position (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. */
- if (!EQ (p->buffer, new_current_buffer) &&
- XBUFFER (p->buffer) == current_buffer)
- Fgoto_char (w->pointm);
- }
- else if (NILP (XBUFFER (w->buffer)->name))
- /* Else if window's old buffer is dead too, get a live one. */
- {
- w->buffer = Fcdr (Fcar (Vbuffer_alist));
- /* This will set the markers to beginning of visible range. */
- 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
- /* Keeping window's old buffer; make sure the markers are real. */
- /* Else if window's old buffer is dead too, get a live one. */
- {
- /* Set window markers at start of visible range. */
- 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 (w->pointm,
- make_number (BUF_PT (XBUFFER (w->buffer))),
- w->buffer);
- w->start_at_line_beg = Qt;
- }
- }
- }
+#ifdef MULTI_FRAME
+ if (NILP (data->focus_frame)
+ || (XTYPE (data->focus_frame) == Lisp_Frame
+ && FRAME_LIVE_P (XFRAME (data->focus_frame))))
+ Fredirect_frame_focus (frame, data->focus_frame);
+#endif
+
+#if 0 /* I don't understand why this is needed, and it causes problems
+ when the frame's old selected window has been deleted. */
+#ifdef MULTI_FRAME
+ if (f != selected_frame && ! FRAME_TERMCAP_P (f))
+ Fhandle_switch_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
+#endif
+#endif
- FRAME_ROOT_WINDOW (f) = data->root_window;
- Fselect_window (data->current_window);
+ /* Set the screen height to the value it had before this function. */
+ if (previous_frame_height != FRAME_HEIGHT (f)
+ || previous_frame_width != FRAME_WIDTH (f))
+ change_frame_size (f, previous_frame_height, previous_frame_width,
+ 0, 0);
+ }
+#ifdef MULTI_FRAME
/* Fselect_window will have made f the selected frame, so we
- reselect the proper frame here. Fselect_frame will change the
+ reselect the proper frame here. Fhandle_switch_frame will change the
selected window too, but that doesn't make the call to
Fselect_window above totally superfluous; it still sets f's
selected window. */
- Fselect_frame (data->selected_frame);
+ if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
+ Fhandle_switch_frame (data->selected_frame, Qnil);
+#endif
if (!NILP (new_current_buffer))
Fset_buffer (new_current_buffer);
-#ifdef MULTI_FRAME
- {
- Lisp_Object frame;
-
- XSET (frame, Lisp_Frame, f);
- Fredirect_frame_focus (frame, data->focus_frame);
- }
-#endif
-
-#if 0 /* I don't understand why this is needed, and it causes
- problems when the frame's old selected window has been
- deleted. */
-#ifdef MULTI_FRAME
- if (f != selected_frame && ! FRAME_TERMCAP_P (f))
- Fselect_frame (WINDOW_FRAME (XWINDOW (data->root_window)), Qnil);
-#endif
-#endif
-
- /* Set the screen height to the value it had before this function. */
- if (previous_frame_height != FRAME_HEIGHT (f)
- || previous_frame_width != FRAME_WIDTH (f))
- change_frame_size (f, previous_frame_height, previous_frame_width, 0, 0);
-
Vminibuf_scroll_window = data->minibuf_scroll_window;
return (Qnil);
}
/* Mark all windows now on frame as deleted
by setting their buffers to nil. */
-static void
+void
delete_all_subwindows (w)
register struct window *w;
{
- w->height = w->buffer; /* See Fset_window_configuration for excuse. */
- w->buffer = Qnil;
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->height = w->buffer; /* See Fset_window_configuration for excuse. */
+
+ /* We set all three of these fields to nil, to make sure that we can
+ distinguish this dead window from any live window. Live leaf
+ windows will have buffer set, and combination windows will have
+ vchild or hchild set. */
+ w->buffer = Qnil;
+ w->vchild = Qnil;
+ w->hchild = Qnil;
}
\f
static int
Qnil));
XFASTINT (data->frame_width) = FRAME_WIDTH (f);
XFASTINT (data->frame_height) = FRAME_HEIGHT (f);
+#ifdef MULTI_FRAME
XSET (data->selected_frame, Lisp_Frame, selected_frame);
+#endif
data->current_window = FRAME_SELECTED_WINDOW (f);
XSET (data->current_buffer, Lisp_Buffer, current_buffer);
data->minibuf_scroll_window = Vminibuf_scroll_window;
Qwindowp = intern ("windowp");
staticpro (&Qwindowp);
+ Qwindow_live_p = intern ("window-live-p");
+ staticpro (&Qwindow_live_p);
+
#ifndef MULTI_FRAME
/* Make sure all windows get marked */
staticpro (&minibuf_window);
work using this function.");
Vdisplay_buffer_function = Qnil;
- DEFVAR_LISP ("mouse-window", &Vmouse_window,
- "Window that the last mouse click occurred on.");
- Vmouse_window = Qnil;
-
- DEFVAR_LISP ("mouse-event", &Vmouse_event,
- "The last mouse-event object. A list of four elements:\n\
- ((X-POS Y-POS) WINDOW FRAME-PART KEYSEQ).\n\
-KEYSEQ is a string, the key sequence to be looked up in the mouse maps.\n\
-WINDOW is the window that the click applies do.\n\
-If FRAME-PART is non-nil, the event was on a scrollbar;\n\
-then Y-POS is really the total length of the scrollbar, while X-POS is\n\
-the relative position of the scrollbar's value within that total length.\n\
-FRAME-PART is one of the following symbols:\n\
- `vertical-scrollbar', `vertical-slider',\n\
- `vertical-thumbup', `vertical-thumbdown',\n\
- `horizontal-scrollbar', `horizontal-slider',\n\
- `horizontal-thumbleft', `horizontal-thumbright'");
- Vmouse_event = Qnil;
-
DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuf_scroll_window,
"Non-nil means it is the window that C-M-v in minibuffer should scroll.");
Vminibuf_scroll_window = Qnil;
"If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window.");
Vother_window_scroll_buffer = Qnil;
-#ifdef MULTI_FRAME
DEFVAR_BOOL ("pop-up-frames", &pop_up_frames,
"*Non-nil means `display-buffer' should make a separate frame.");
pop_up_frames = 0;
A typical value might be `(lambda () (new-frame pop-up-frame-alist))'\n\
where `pop-up-frame-alist' would hold the default frame parameters.");
Vpop_up_frame_function = Qnil;
-#endif
DEFVAR_BOOL ("pop-up-windows", &pop_up_windows,
"*Non-nil means display-buffer should make new windows.");
defsubr (&Sminibuffer_window);
defsubr (&Swindow_minibuffer_p);
defsubr (&Swindowp);
+ defsubr (&Swindow_live_p);
defsubr (&Spos_visible_in_window_p);
defsubr (&Swindow_buffer);
defsubr (&Swindow_height);