/* Window creation, deletion and examination for GNU Emacs.
Does not include redisplay.
- Copyright (C) 1985, 86, 87, 93, 94, 95, 96 Free Software Foundation, Inc.
+ Copyright (C) 1985,86,87,93,94,95,96,1997 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "termchar.h"
#include "disptab.h"
#include "keyboard.h"
+#include "blockinput.h"
Lisp_Object Qwindowp, Qwindow_live_p;
/* Nonzero after init_window_once has finished. */
static int window_initialized;
+/* Hook to run when window config changes. */
+Lisp_Object Qwindow_configuration_change_hook;
+Lisp_Object Vwindow_configuration_change_hook;
+
/* Nonzero means scroll commands try to put point
at the same screen height as previously. */
static int scroll_preserve_screen_position;
+/* Nonzero means we can split a frame even if it is "unsplittable". */
+static int inhibit_frame_unsplittable;
+
#define min(a, b) ((a) < (b) ? (a) : (b))
extern int scroll_margin;
return Qnil;
/* If that info is not correct, calculate afresh */
+ /* BUG FIX for the 7th arg (TOHPOS).
+
+ '0' is harmless, however, ' - (1 << (BITS_PER_SHORT - 1))' is
+ more appropriate here. In case of HSCROLL > 0, this can avoid
+ needless calculation done until (HPOS == 0).
+
+ We want to determine if the position POSINT is in HEIGHT or
+ not. We don't have to do calculation until (HPOS == 0). We
+ can stop it when VPOS goes beyond HEIGHT. */
posval = *compute_motion (top, 0, (hscroll ? 1 - hscroll : 0), 0,
- posint, height, 0,
+ posint, height, - (1 << (BITS_PER_SHORT - 1)),
window_internal_width (w) - 1,
hscroll, 0, w);
return Qnil;
case 1: /* In text part of window. */
- return Fcons (x, y);
+ return Fcons (make_number (x), make_number (y));
case 2: /* In mode line of window. */
return Qmode_line;
"Remove WINDOW from the display. Default is selected window.")
(window)
register Lisp_Object window;
+{
+ delete_window (window);
+
+ if (! NILP (Vwindow_configuration_change_hook)
+ && ! NILP (Vrun_hooks))
+ call1 (Vrun_hooks, Qwindow_configuration_change_hook);
+
+ return Qnil;
+}
+
+delete_window (window)
+ register Lisp_Object window;
{
register Lisp_Object tem, parent, sib;
register struct window *p;
if (NILP (p->buffer)
&& NILP (p->hchild)
&& NILP (p->vchild))
- return Qnil;
+ return;
parent = p->parent;
if (NILP (parent))
/* Mark this window as deleted. */
p->buffer = p->hchild = p->vchild = Qnil;
-
- return Qnil;
}
\f
Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
w->start_at_line_beg = ((pos.bufpos == BEGV
- || FETCH_CHAR (pos.bufpos - 1) == '\n') ? Qt
+ || FETCH_BYTE (pos.bufpos - 1) == '\n') ? Qt
: Qnil);
/* We need to do this, so that the window-scroll-functions
get called. */
if (!nodelete
&& ! NILP (w->parent)
- && height < window_min_height)
+ && (MINI_WINDOW_P (w)
+ ? height < 1
+ : height < window_min_height))
{
- Fdelete_window (window);
+ delete_window (window);
return;
}
if (!nodelete && width < window_min_width && !NILP (w->parent))
{
- Fdelete_window (window);
+ delete_window (window);
return;
}
if (EQ (window, selected_window))
XBUFFER (w->buffer)->last_selected_window = window;
+ if (INTEGERP (XBUFFER (buffer)->display_count))
+ XSETINT (XBUFFER (buffer)->display_count,
+ XINT (XBUFFER (buffer)->display_count) + 1);
XSETFASTINT (w->window_end_pos, 0);
w->window_end_valid = Qnil;
run_hook_with_args_2 (Qwindow_scroll_functions, window,
Fmarker_position (w->start));
+ if (! NILP (Vwindow_configuration_change_hook)
+ && ! NILP (Vrun_hooks))
+ call1 (Vrun_hooks, Qwindow_configuration_change_hook);
+
unbind_to (count, Qnil);
return Qnil;
}
DEFUN ("display-buffer", Fdisplay_buffer, Sdisplay_buffer, 1, 2,
- "bDisplay buffer: \nP",
+ "BDisplay buffer: \nP", /* Use B so the default is (other-buffer). */
"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\
&& window_height (window) >= window_min_height << 1)
window = Fsplit_window (window, Qnil, Qnil);
/* If Fget_lru_window returned nil, try other approaches. */
+
/* Try visible frames first. */
+ if (NILP (window))
+ window = Fget_buffer_window (buffer, Qvisible);
if (NILP (window))
window = Fget_largest_window (Qvisible);
/* If that didn't work, try iconified frames. */
+ if (NILP (window))
+ window = Fget_buffer_window (buffer, make_number (0));
if (NILP (window))
window = Fget_largest_window (make_number (0));
/* Try invisible frames. */
+ if (NILP (window))
+ window = Fget_buffer_window (buffer, Qt);
if (NILP (window))
window = Fget_largest_window (Qt);
/* As a last resort, make a new frame. */
other = lower = XWINDOW (window)->next, upper = window;
if (!NILP (other)
/* Check that OTHER and WINDOW are vertically arrayed. */
- && XWINDOW (other)->top != XWINDOW (window)->top
- && XWINDOW (other)->height > XWINDOW (window)->height)
+ && !EQ (XWINDOW (other)->top, XWINDOW (window)->top)
+ && (XFASTINT (XWINDOW (other)->height)
+ > XFASTINT (XWINDOW (window)->height)))
{
- int total = XWINDOW (other)->height + XWINDOW (window)->height;
+ int total = (XFASTINT (XWINDOW (other)->height)
+ + XFASTINT (XWINDOW (window)->height));
Lisp_Object old_selected_window;
old_selected_window = selected_window;
selected_window = upper;
- change_window_height (total / 2 - XWINDOW (upper)->height, 0);
+ change_window_height ((total / 2
+ - XFASTINT (XWINDOW (upper)->height)),
+ 0);
selected_window = old_selected_window;
}
}
register Lisp_Object window;
register struct window *w;
+ XBUFFER (buf)->directory = current_buffer->directory;
+
Fset_buffer (buf);
BUF_SAVE_MODIFF (XBUFFER (buf)) = MODIFF;
BEGV = BEG;
if (MINI_WINDOW_P (o))
error ("Attempt to split minibuffer window");
- else if (FRAME_NO_SPLIT_P (fo))
- error ("Attempt to split unsplittable frame");
check_min_window_sizes ();
p->parent = o->parent;
p->buffer = Qt;
- Fset_window_buffer (new, o->buffer);
-
/* Apportion the available frame space among the two new windows */
if (!NILP (horflag))
XSETFASTINT (p->top, XFASTINT (o->top) + size_int);
}
+ Fset_window_buffer (new, o->buffer);
+
return new;
}
\f
{
CHECK_NUMBER (arg, 0);
change_window_height (XINT (arg), !NILP (side));
+
+ if (! NILP (Vwindow_configuration_change_hook))
+ call1 (Vrun_hooks, Qwindow_configuration_change_hook);
+
return Qnil;
}
{
CHECK_NUMBER (arg, 0);
change_window_height (-XINT (arg), !NILP (side));
+
+ if (! NILP (Vwindow_configuration_change_hook))
+ call1 (Vrun_hooks, Qwindow_configuration_change_hook);
+
return Qnil;
}
if (*sizep + delta < MINSIZE (window))
{
- Fdelete_window (window);
+ delete_window (window);
return;
}
maximum += (*sizefun) (prev) - MINSIZE (prev);
/* If we can get it all from them, do so. */
- if (delta < maximum)
+ if (delta <= maximum)
{
Lisp_Object first_unaffected;
Lisp_Object first_affected;
/* Look at one sibling at a time,
moving away from this window in both directions alternately,
and take as much as we can get without deleting that sibling. */
- while (delta > 0)
+ while (delta != 0)
{
if (delta == 0)
break;
Fvertical_motion (make_number (original_vpos), window);
}
else
- SET_PT (pos);
+ SET_PT (top_margin);
}
else if (n < 0)
{
Fset_marker (w->start, make_number (pos.bufpos), w->buffer);
w->start_at_line_beg = ((pos.bufpos == BEGV
- || FETCH_CHAR (pos.bufpos - 1) == '\n')
+ || FETCH_BYTE (pos.bufpos - 1) == '\n')
? Qt : Qnil);
w->force_start = Qt;
Lisp_Object new_current_buffer;
Lisp_Object frame;
FRAME_PTR f;
+ int old_point = -1;
while (!WINDOW_CONFIGURATIONP (configuration))
{
new_current_buffer = data->current_buffer;
if (NILP (XBUFFER (new_current_buffer)->name))
new_current_buffer = Qnil;
+ else
+ {
+ if (XBUFFER (new_current_buffer) == current_buffer)
+ old_point = PT;
+ }
frame = XWINDOW (SAVED_WINDOW_N (saved_windows, 0)->window)->frame;
f = XFRAME (frame);
int previous_frame_width = FRAME_WIDTH (f);
int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
+ /* The mouse highlighting code could get screwed up
+ if it runs during this. */
+ BLOCK_INPUT;
+
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);
FRAME_ROOT_WINDOW (f) = data->root_window;
Fselect_window (data->current_window);
+ XBUFFER (XWINDOW (selected_window)->buffer)->last_selected_window
+ = selected_window;
if (NILP (data->focus_frame)
|| (FRAMEP (data->focus_frame)
if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
x_set_menu_bar_lines (f, previous_frame_menu_bar_lines, 0);
#endif
+
+ UNBLOCK_INPUT;
}
/* Restore the minimum heights recorded in the configuration. */
do_switch_frame (data->selected_frame, Qnil, 0);
if (!NILP (new_current_buffer))
- Fset_buffer (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);
+ }
Vminibuf_scroll_window = data->minibuf_scroll_window;
+
+ if (! NILP (Vwindow_configuration_change_hook)
+ && ! NILP (Vrun_hooks))
+ call1 (Vrun_hooks, Qwindow_configuration_change_hook);
+
return (Qnil);
}
if (EQ (window, selected_window))
{
p->pointm = Fmake_marker ();
- Fset_marker (p->pointm, BUF_PT (XBUFFER (w->buffer)),
+ Fset_marker (p->pointm,
+ make_number (BUF_PT (XBUFFER (w->buffer))),
w->buffer);
}
else
syms_of_window ()
{
+ staticpro (&Qwindow_configuration_change_hook);
+ Qwindow_configuration_change_hook
+ = intern ("window-configuration-change-hook");
+
Qwindowp = intern ("windowp");
staticpro (&Qwindowp);
In the first case, FRAME-PARAMETERS are used to create the frame.\n\
In the latter case, FUNCTION is called with BUFFER as the first argument,\n\
followed by OTHER-ARGS--it can display BUFFER in any way it likes.\n\
-All this is done by the function found in `special-display-function'.");
+All this is done by the function found in `special-display-function'.\n\
+\n\
+If this variable appears \"not to work\", because you add a name to it\n\
+but that buffer still appears in the selected window, look at the\n\
+values of `same-window-buffer-names' and `same-window-regexps'.\n\
+Those variables take precedence over this one.");
Vspecial_display_buffer_names = Qnil;
DEFVAR_LISP ("special-display-regexps", &Vspecial_display_regexps,
In the first case, FRAME-PARAMETERS are used to create the frame.\n\
In the latter case, FUNCTION is called with the buffer as first argument,\n\
followed by OTHER-ARGS--it can display the buffer in any way it likes.\n\
-All this is done by the function found in `special-display-function'.");
+All this is done by the function found in `special-display-function'.\n\
+\n\
+If this variable appears \"not to work\", because you add a regexp to it\n\
+but the matching buffers still appear in the selected window, look at the\n\
+values of `same-window-buffer-names' and `same-window-regexps'.\n\
+Those variables take precedence over this one.");
Vspecial_display_regexps = Qnil;
DEFVAR_LISP ("special-display-function", &Vspecial_display_function,
"*Nonzero means scroll commands move point to keep its screen line unchanged.");
scroll_preserve_screen_position = 0;
+ DEFVAR_LISP ("window-configuration-change-hook",
+ &Vwindow_configuration_change_hook,
+ "Functions to call when window configuration changes.\n\
+The selected frae is the one whose configuration has changed.");
+ Vwindow_configuration_change_hook = Qnil;
+
defsubr (&Sselected_window);
defsubr (&Sminibuffer_window);
defsubr (&Swindow_minibuffer_p);