X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/192c3131345ac1f3445dd4bbdb46156ed4d6e122..74d70085965d7d63b4f69393d70926760296f78a:/src/window.c diff --git a/src/window.c b/src/window.c index e3914f8f97..24a95dc53a 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,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. @@ -44,7 +44,7 @@ Boston, MA 02111-1307, USA. */ #ifdef MSDOS #include "msdos.h" #endif -#ifdef macintosh +#ifdef MAC_OS #include "macterm.h" #endif @@ -58,12 +58,15 @@ enum window_part 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 *)); @@ -120,6 +123,11 @@ Lisp_Object Vwindow_list; Lisp_Object minibuf_window; +/* Non-nil means it is the window whose mode line should be + shown as the selected window when the minibuffer is selected. */ + +Lisp_Object minibuf_selected_window; + /* Non-nil means it is the window for C-M-v to scroll when the mini-buffer is selected. */ @@ -133,10 +141,15 @@ Lisp_Object Vother_window_scroll_buffer; Lisp_Object Vtemp_buffer_show_function; +/* Non-zero means to use mode-line-inactive face in all windows but the + selected-window and the minibuffer-scroll-window when the + minibuffer is active. */ +int mode_line_in_non_selected_windows; + /* 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. */ @@ -189,11 +202,11 @@ Lisp_Object Qtemp_buffer_show_hook; /* 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. */ @@ -218,7 +231,7 @@ Lisp_Object Vscroll_preserve_screen_position; 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; @@ -265,6 +278,7 @@ make_window () 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); @@ -273,6 +287,8 @@ make_window () 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; @@ -498,7 +514,9 @@ and BOTTOM is one more than the bottommost row used by WINDOW 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. */ @@ -518,6 +536,7 @@ coordinates_in_window (w, x, y) /* 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; @@ -612,9 +631,21 @@ coordinates_in_window (w, x, y) } 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 @@ -642,10 +673,23 @@ coordinates_in_window (w, x, y) } 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; + } } } @@ -667,7 +711,9 @@ If they are in the top mode line of WINDOW, `header-line' is returned. 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; { @@ -713,6 +759,12 @@ If they are on the border between WINDOW and its right sibling, case ON_RIGHT_FRINGE: return Qright_fringe; + case ON_LEFT_MARGIN: + return Qleft_margin; + + case ON_RIGHT_MARGIN: + return Qright_margin; + default: abort (); } @@ -1134,6 +1186,7 @@ replace_window (old, replacement) 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); @@ -2118,7 +2171,7 @@ replace_buffer_in_all_windows (buffer) might crash Emacs. */ #define MIN_SAFE_WINDOW_WIDTH (2) -#define MIN_SAFE_WINDOW_HEIGHT (2) +#define MIN_SAFE_WINDOW_HEIGHT (1) /* Make sure that window_min_height and window_min_width are not too small; if they are, set them to safe minima. */ @@ -2142,13 +2195,12 @@ check_frame_size (frame, rows, cols) int *rows, *cols; { /* 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) ? MIN_SAFE_WINDOW_HEIGHT - 1 - : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT - : 2 * MIN_SAFE_WINDOW_HEIGHT - 1); + how many windows the frame has at minimum (one or two), + and whether it has a menu bar or other special stuff at the top. */ + int min_height + = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame)) + ? MIN_SAFE_WINDOW_HEIGHT + : 2 * MIN_SAFE_WINDOW_HEIGHT); if (FRAME_TOP_MARGIN (frame) > 0) min_height += FRAME_TOP_MARGIN (frame); @@ -2887,7 +2939,7 @@ unless the window is the selected window and the optional second 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', @@ -2935,7 +2987,7 @@ displayed. */) } } - /* 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)) @@ -3543,11 +3595,36 @@ enlarge_window (window, delta, widthflag, preserve_before) register int delta1; register int opht = (*sizefun) (parent); - /* If trying to grow this window to or beyond size of the parent, - make delta1 so big that, on shrinking back down, - all the siblings end up with less than one line and are deleted. */ if (opht <= XINT (*sizep) + delta) - delta1 = opht * opht * 2; + { + /* If trying to grow this window to or beyond size of the parent, + just delete all the sibling windows. */ + Lisp_Object start, tem, next; + + start = XWINDOW (parent)->vchild; + if (NILP (start)) + start = XWINDOW (parent)->hchild; + + /* Delete any siblings that come after WINDOW. */ + tem = XWINDOW (window)->next; + while (! NILP (tem)) + { + next = XWINDOW (tem)->next; + delete_window (tem); + tem = next; + } + + /* Delete any siblings that come after WINDOW. + Note that if START is not WINDOW, then WINDOW still + Fhas siblings, so WINDOW has not yet replaced its parent. */ + tem = start; + while (! EQ (tem, window)) + { + next = XWINDOW (tem)->next; + delete_window (tem); + tem = next; + } + } else { /* Otherwise, make delta1 just right so that if we add @@ -3590,19 +3667,20 @@ enlarge_window (window, delta, widthflag, preserve_before) ++n; delta1 = n * delta; - } - /* Add delta1 lines or columns to this window, and to the parent, - keeping things consistent while not affecting siblings. */ - XSETINT (CURSIZE (parent), opht + delta1); - (*setsizefun) (window, XINT (*sizep) + delta1, 0); - - /* Squeeze out delta1 lines or columns from our parent, - shriking this window and siblings proportionately. - This brings parent back to correct size. - Delta1 was calculated so this makes this window the desired size, - taking it all out of the siblings. */ - (*setsizefun) (parent, opht, 0); + /* Add delta1 lines or columns to this window, and to the parent, + keeping things consistent while not affecting siblings. */ + XSETINT (CURSIZE (parent), opht + delta1); + (*setsizefun) (window, XINT (*sizep) + delta1, 0); + + /* Squeeze out delta1 lines or columns from our parent, + shriking this window and siblings proportionately. + This brings parent back to correct size. + Delta1 was calculated so this makes this window the desired size, + taking it all out of the siblings. */ + (*setsizefun) (parent, opht, 0); + + } } XSETFASTINT (p->last_modified, 0); @@ -4117,7 +4195,12 @@ window_scroll_pixel_based (window, n, whole, noerror) 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) @@ -4512,6 +4595,20 @@ by this function. */) 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. */ @@ -4763,6 +4860,7 @@ struct save_window_data Lisp_Object current_window; Lisp_Object current_buffer; Lisp_Object minibuf_scroll_window; + Lisp_Object minibuf_selected_window; Lisp_Object root_window; Lisp_Object focus_frame; /* Record the values of window-min-width and window-min-height @@ -5126,6 +5224,7 @@ the return value is nil. Otherwise the value is t. */) window_min_width = XINT (data->min_width); Vminibuf_scroll_window = data->minibuf_scroll_window; + minibuf_selected_window = data->minibuf_selected_window; return (FRAME_LIVE_P (f) ? Qt : Qnil); } @@ -5335,7 +5434,8 @@ redirection (see `redirect-frame-focus'). */) data->selected_frame = selected_frame; data->current_window = FRAME_SELECTED_WINDOW (f); XSETBUFFER (data->current_buffer, current_buffer); - data->minibuf_scroll_window = Vminibuf_scroll_window; + data->minibuf_scroll_window = minibuf_level > 0 ? Vminibuf_scroll_window : Qnil; + data->minibuf_selected_window = minibuf_level > 0 ? minibuf_selected_window : Qnil; data->root_window = FRAME_ROOT_WINDOW (f); data->focus_frame = FRAME_FOCUS_FRAME (f); XSETINT (data->min_height, window_min_height); @@ -5619,8 +5719,12 @@ compare_window_configurations (c1, c2, ignore_positions) if (! EQ (d1->current_buffer, d2->current_buffer)) return 0; if (! ignore_positions) - if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)) - return 0; + { + if (! EQ (d1->minibuf_scroll_window, d2->minibuf_scroll_window)) + return 0; + if (! EQ (d1->minibuf_selected_window, d2->minibuf_selected_window)) + return 0; + } /* Don't compare the root_window field. We don't require the two configurations to use the same window object, @@ -5746,6 +5850,9 @@ syms_of_window () staticpro (&Vwindow_list); + minibuf_selected_window = Qnil; + staticpro (&minibuf_selected_window); + DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function, doc: /* Non-nil means call as function to display a help buffer. The function is called with one argument, the buffer to be displayed. @@ -5771,6 +5878,12 @@ If nil, `display-buffer' will leave the window configuration alone. */); doc: /* Non-nil means it is the window that C-M-v in minibuffer should scroll. */); Vminibuf_scroll_window = Qnil; + DEFVAR_BOOL ("mode-line-in-non-selected-windows", &mode_line_in_non_selected_windows, + doc: /* Non-nil means to use `mode-line-inactive' face in non-selected windows. +If the minibuffer is active, the `minibuffer-scroll-window' mode line +is displayed in the `mode-line' face. */); + mode_line_in_non_selected_windows = 1; + DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer, doc: /* If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. */); Vother_window_scroll_buffer = Qnil; @@ -5959,6 +6072,7 @@ This variable automatically becomes buffer-local when set. */); 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);