X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/db98a733f233eb929be98919fbf0da12b2418196..335406fc22134b33f3982486cb9954823ce321ca:/src/window.c diff --git a/src/window.c b/src/window.c index 34b64ca24d..c5360a886b 100644 --- a/src/window.c +++ b/src/window.c @@ -1,6 +1,6 @@ /* 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. @@ -29,6 +29,7 @@ Boston, MA 02111-1307, USA. */ #include "termchar.h" #include "disptab.h" #include "keyboard.h" +#include "blockinput.h" Lisp_Object Qwindowp, Qwindow_live_p; @@ -111,10 +112,17 @@ static int sequence_number; /* 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; @@ -253,8 +261,17 @@ POS defaults to point; WINDOW, to the selected window.") 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); @@ -440,7 +457,7 @@ If they are on the border between WINDOW and its right sibling,\n\ 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; @@ -776,6 +793,18 @@ DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "", "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; @@ -794,7 +823,7 @@ DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "", if (NILP (p->buffer) && NILP (p->hchild) && NILP (p->vchild)) - return Qnil; + return; parent = p->parent; if (NILP (parent)) @@ -901,8 +930,6 @@ DEFUN ("delete-window", Fdelete_window, Sdelete_window, 0, 1, "", /* Mark this window as deleted. */ p->buffer = p->hchild = p->vchild = Qnil; - - return Qnil; } @@ -1573,7 +1600,7 @@ value is reasonable when this function is called.") 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. */ @@ -1708,9 +1735,11 @@ set_window_height (window, height, nodelete) 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; } @@ -1774,7 +1803,7 @@ set_window_width (window, width, nodelete) if (!nodelete && width < window_min_width && !NILP (w->parent)) { - Fdelete_window (window); + delete_window (window); return; } @@ -1865,6 +1894,9 @@ BUFFER can be a buffer or buffer name.") 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; @@ -1898,6 +1930,10 @@ BUFFER can be a buffer or buffer name.") 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; @@ -2057,7 +2093,7 @@ See `same-window-buffer-names' and `same-window-regexps'.") } 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\ @@ -2186,13 +2222,20 @@ buffer names are handled.") && 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. */ @@ -2207,15 +2250,19 @@ buffer names are handled.") 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; } } @@ -2235,6 +2282,8 @@ temp_output_buffer_show (buf) 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; @@ -2353,8 +2402,6 @@ and put SIZE columns in the first of the pair.") 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 (); @@ -2408,8 +2455,6 @@ and put SIZE columns in the first of the pair.") 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)) @@ -2429,6 +2474,8 @@ and put SIZE columns in the first of the pair.") XSETFASTINT (p->top, XFASTINT (o->top) + size_int); } + Fset_window_buffer (new, o->buffer); + return new; } @@ -2440,6 +2487,10 @@ From program, optional second arg non-nil means grow sideways ARG columns.") { 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; } @@ -2451,6 +2502,10 @@ From program, optional second arg non-nil means shrink sideways arg columns.") { 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; } @@ -2540,7 +2595,7 @@ change_window_height (delta, widthflag) if (*sizep + delta < MINSIZE (window)) { - Fdelete_window (window); + delete_window (window); return; } @@ -2555,7 +2610,7 @@ change_window_height (delta, widthflag) 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; @@ -2566,7 +2621,7 @@ change_window_height (delta, widthflag) /* 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; @@ -2795,7 +2850,7 @@ window_scroll (window, n, whole, noerror) Fvertical_motion (make_number (original_vpos), window); } else - SET_PT (pos); + SET_PT (top_margin); } else if (n < 0) { @@ -3055,7 +3110,7 @@ redraws with point in the center of the current window.") 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; @@ -3161,6 +3216,7 @@ by `current-window-configuration' (which see).") Lisp_Object new_current_buffer; Lisp_Object frame; FRAME_PTR f; + int old_point = -1; while (!WINDOW_CONFIGURATIONP (configuration)) { @@ -3174,6 +3230,11 @@ by `current-window-configuration' (which see).") 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); @@ -3194,6 +3255,10 @@ by `current-window-configuration' (which see).") 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); @@ -3325,6 +3390,8 @@ by `current-window-configuration' (which see).") 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) @@ -3347,6 +3414,8 @@ by `current-window-configuration' (which see).") 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. */ @@ -3362,9 +3431,22 @@ by `current-window-configuration' (which see).") 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); } @@ -3442,7 +3524,8 @@ save_window_save (window, vector, i) 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 @@ -3571,6 +3654,10 @@ init_window_once () syms_of_window () { + staticpro (&Qwindow_configuration_change_hook); + Qwindow_configuration_change_hook + = intern ("window-configuration-change-hook"); + Qwindowp = intern ("windowp"); staticpro (&Qwindowp); @@ -3627,7 +3714,12 @@ There are two ways to use a list as an element:\n\ 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, @@ -3642,7 +3734,12 @@ There are two ways to use a list as an element:\n\ 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, @@ -3710,6 +3807,12 @@ If there is only one window, it is split regardless of this value."); "*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);