X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fwindow.c;h=c3e511f43eac93e187bce6d2ff4d5acf2092db98;hb=9816585ded614fa87be5a2ecfda6dc16c60beb2c;hp=2f3a6b80103440f24eee2c0ae75c2c6e8e21647a;hpb=cb9f6f4eadc44f1becb32cbbd1db26449e347755;p=chise%2Fxemacs-chise.git- diff --git a/src/window.c b/src/window.c index 2f3a6b8..c3e511f 100644 --- a/src/window.c +++ b/src/window.c @@ -38,9 +38,10 @@ Boston, MA 02111-1307, USA. */ #include "window.h" #include "elhash.h" #include "commands.h" +#include "gutter.h" Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp; -Lisp_Object Qscroll_up, Qscroll_down, Qdisplay_buffer; +Lisp_Object Qdisplay_buffer; #ifdef MEMORY_USAGE_STATS Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay; @@ -84,6 +85,9 @@ Lisp_Object Vvertical_divider_line_width; /* Spacing between outer egde of divider border and window edge */ Lisp_Object Vvertical_divider_spacing; +/* How much to scroll by per-line. */ +Lisp_Object Vwindow_pixel_scroll_increment; + /* Scroll if point lands on the bottom line and that line is partially clipped. */ int scroll_on_clipped_lines; @@ -117,7 +121,7 @@ Lisp_Object Qtemp_buffer_show_hook; int next_screen_context_lines; /* List of freed window configurations with 1 - 10 windows. */ -Lisp_Object Vwindow_configuration_free_list[10]; +static Lisp_Object Vwindow_configuration_free_list[10]; #define SET_LAST_MODIFIED(w, cache_too) \ do { \ @@ -137,38 +141,38 @@ do { \ #define MARK_DISP_VARIABLE(field) \ - markobj (window->field[CURRENT_DISP]); \ - markobj (window->field[DESIRED_DISP]); \ - markobj (window->field[CMOTION_DISP]); + mark_object (window->field[CURRENT_DISP]); \ + mark_object (window->field[DESIRED_DISP]); \ + mark_object (window->field[CMOTION_DISP]); static Lisp_Object -mark_window (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_window (Lisp_Object obj) { struct window *window = XWINDOW (obj); - markobj (window->frame); - markobj (window->mini_p); - markobj (window->next); - markobj (window->prev); - markobj (window->hchild); - markobj (window->vchild); - markobj (window->parent); - markobj (window->buffer); + mark_object (window->frame); + mark_object (window->mini_p); + mark_object (window->next); + mark_object (window->prev); + mark_object (window->hchild); + mark_object (window->vchild); + mark_object (window->parent); + mark_object (window->buffer); MARK_DISP_VARIABLE (start); MARK_DISP_VARIABLE (pointm); - markobj (window->sb_point); /* #### move to scrollbar.c? */ - markobj (window->use_time); + mark_object (window->sb_point); /* #### move to scrollbar.c? */ + mark_object (window->use_time); MARK_DISP_VARIABLE (last_modified); MARK_DISP_VARIABLE (last_point); MARK_DISP_VARIABLE (last_start); MARK_DISP_VARIABLE (last_facechange); - markobj (window->line_cache_last_updated); - markobj (window->redisplay_end_trigger); - markobj (window->subwindow_instance_cache); + mark_object (window->line_cache_last_updated); + mark_object (window->redisplay_end_trigger); + mark_object (window->subwindow_instance_cache); - mark_face_cachels (window->face_cachels, markobj); - mark_glyph_cachels (window->glyph_cachels, markobj); + mark_face_cachels (window->face_cachels); + mark_glyph_cachels (window->glyph_cachels); -#define WINDOW_SLOT(slot, compare) ((void) (markobj (window->slot))) +#define WINDOW_SLOT(slot, compare) mark_object (window->slot) #include "winslots.h" return Qnil; @@ -231,7 +235,7 @@ finalize_window (void *header, int for_disksave) DEFINE_LRECORD_IMPLEMENTATION ("window", window, mark_window, print_window, finalize_window, - 0, 0, struct window); + 0, 0, 0, struct window); #define INIT_DISP_VARIABLE(field, initialization) \ @@ -252,7 +256,7 @@ Lisp_Object allocate_window (void) { Lisp_Object val; - struct window *p = alloc_lcrecord_type (struct window, lrecord_window); + struct window *p = alloc_lcrecord_type (struct window, &lrecord_window); zero_lcrecord (p); XSETWINDOW (val, p); @@ -277,15 +281,20 @@ allocate_window (void) p->face_cachels = Dynarr_new (face_cachel); p->glyph_cachels = Dynarr_new (glyph_cachel); p->line_start_cache = Dynarr_new (line_start_cache); - p->subwindow_instance_cache = make_lisp_hash_table (10, + p->subwindow_instance_cache = make_lisp_hash_table (30, HASH_TABLE_KEY_WEAK, - HASH_TABLE_EQ); + HASH_TABLE_EQUAL); p->line_cache_last_updated = Qzero; INIT_DISP_VARIABLE (last_point_x, 0); INIT_DISP_VARIABLE (last_point_y, 0); INIT_DISP_VARIABLE (window_end_pos, 0); p->redisplay_end_trigger = Qnil; + p->gutter_extent_modiff[0] = 0; + p->gutter_extent_modiff[1] = 0; + p->gutter_extent_modiff[2] = 0; + p->gutter_extent_modiff[3] = 0; + #define WINDOW_SLOT(slot, compare) p->slot = Qnil #include "winslots.h" @@ -641,7 +650,7 @@ window_full_width_p (struct window *w) return window_is_leftmost (w) && window_is_rightmost (w); } -static int +int window_is_highest (struct window *w) { Lisp_Object parent, current_ancestor, window; @@ -669,7 +678,7 @@ window_is_highest (struct window *w) return 0; } -static int +int window_is_lowest (struct window *w) { Lisp_Object parent, current_ancestor, window; @@ -705,6 +714,11 @@ window_full_height_p (struct window *w) int window_truncation_on (struct window *w) { + /* Minibuffer windows are never truncated. + #### is this the right way ? */ + if (MINI_WINDOW_P (w)) + return 0; + /* Horizontally scrolled windows are truncated. */ if (w->hscroll) return 1; @@ -723,6 +737,17 @@ window_truncation_on (struct window *w) return 0; } +DEFUN ("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /* +Returns non-nil if text in the window is truncated. +*/ + (window)) +{ + struct window *w = decode_window (window); + + return window_truncation_on (w) ? Qt : Qnil; +} + + static int have_undivided_common_edge (struct window *w_right, void *closure) { @@ -972,32 +997,6 @@ window_right_margin_width (struct window *w) return margin_width_internal (w, 0); } -static int -window_top_toolbar_height (struct window *w) -{ - /* #### implement this shit. */ - return 0; -} - -/* #### Currently used in scrollbar.c. Does it actually need to be? */ -int -window_bottom_toolbar_height (struct window *w) -{ - return 0; -} - -static int -window_left_toolbar_width (struct window *w) -{ - return 0; -} - -static int -window_right_toolbar_width (struct window *w) -{ - return 0; -} - /***************************************************************************** Window Gutters @@ -1016,62 +1015,74 @@ window_right_toolbar_width (struct window *w) relative to the frame, not the window. ****************************************************************************/ -int -window_top_gutter_height (struct window *w) +static int +window_top_window_gutter_height (struct window *w) { - int toolbar_height = window_top_toolbar_height (w); - if (!NILP (w->hchild) || !NILP (w->vchild)) return 0; - + #ifdef HAVE_SCROLLBARS if (!NILP (w->scrollbar_on_top_p)) - return window_scrollbar_height (w) + toolbar_height; + return window_scrollbar_height (w); else #endif - return toolbar_height; + return 0; } int -window_bottom_gutter_height (struct window *w) +window_top_gutter_height (struct window *w) { - int other_height; + return window_top_window_gutter_height (w); +} + +static int +window_bottom_window_gutter_height (struct window *w) +{ + int gutter; if (!NILP (w->hchild) || !NILP (w->vchild)) return 0; - else - other_height = - window_modeline_height (w) + window_bottom_toolbar_height (w); + + gutter = window_modeline_height (w); #ifdef HAVE_SCROLLBARS if (NILP (w->scrollbar_on_top_p)) - return window_scrollbar_height (w) + other_height; + return window_scrollbar_height (w) + gutter; else #endif - return other_height; + return gutter; } int -window_left_gutter_width (struct window *w, int modeline) +window_bottom_gutter_height (struct window *w) { - int gutter = window_left_toolbar_width (w); + return window_bottom_window_gutter_height (w); +} +static int +window_left_window_gutter_width (struct window *w, int modeline) +{ if (!NILP (w->hchild) || !NILP (w->vchild)) return 0; - #ifdef HAVE_SCROLLBARS if (!modeline && !NILP (w->scrollbar_on_left_p)) - gutter += window_scrollbar_width (w); + return window_scrollbar_width (w); #endif - return gutter; + return 0; } int -window_right_gutter_width (struct window *w, int modeline) +window_left_gutter_width (struct window *w, int modeline) +{ + return window_left_window_gutter_width (w, modeline); +} + +static int +window_right_window_gutter_width (struct window *w, int modeline) { - int gutter = window_right_toolbar_width (w); + int gutter = 0; if (!NILP (w->hchild) || !NILP (w->vchild)) return 0; @@ -1087,6 +1098,18 @@ window_right_gutter_width (struct window *w, int modeline) return gutter; } +int +window_right_gutter_width (struct window *w, int modeline) +{ + return window_right_window_gutter_width (w, modeline); +} + +static int +window_pixel_height (struct window* w) +{ + return WINDOW_HEIGHT (w); +} + DEFUN ("windowp", Fwindowp, 1, 1, 0, /* Return t if OBJ is a window. @@ -1123,6 +1146,26 @@ be used. Otherwise, the selected frame is used. } } +DEFUN ("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /* +Return the last selected window that is not a minibuffer window. +If the optional argument CON-DEV-OR-FRAME is specified and is a frame, +return the last non-minibuffer window used by that frame. If +CON-DEV-OR-FRAME is a device, then the selected frame on that device +will be used. If CON-DEV-OR-FRAME is a console, the selected frame on +that console's selected device will be used. Otherwise, the selected +frame is used. +*/ + (con_dev_or_frame)) +{ + if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil))) + return Qnil; /* happens at startup */ + + { + struct frame *f = decode_frame_or_selected (con_dev_or_frame); + return FRAME_LAST_NONMINIBUF_WINDOW (f); + } +} + DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /* Return the window used now for minibuffers. If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return @@ -1136,7 +1179,7 @@ be used. Otherwise, the selected frame is used. return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame)); } -DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 1, 1, 0, /* +DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /* Return non-nil if WINDOW is a minibuffer window. */ (window)) @@ -1282,6 +1325,22 @@ be different. Use `window-height' to get consistent results in geometry calculations. Use `window-displayed-height' to get the actual number of lines currently displayed in a window. + +The names are somewhat confusing; here's a table to help out: + + width height +------------------------------------------------------------------------- +w/o gutters + (rows/columns) window-width window-text-area-height + (pixels) window-text-area-pixel-width window-text-area-pixel-height + +with gutters + (rows/columns) window-full-width window-height + (pixels) window-pixel-width window-pixel-height + +actually displayed + (rows/columns) ---- window-displayed-height + (pixels) ---- window-displayed-text-pixel-height */ (window)) { @@ -1308,7 +1367,20 @@ This includes the window's modeline and horizontal scrollbar (if any). */ (window)) { - return make_int (decode_window (window)->pixel_height); + return make_int (window_pixel_height (decode_window (window))); +} + +DEFUN ("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /* +Return the number of default lines in the text area of WINDOW. +This actually works by dividing the window's text area pixel height (i.e. +excluding the modeline and horizontal scrollbar, if any) by the height of the +default font; therefore, the number of displayed lines will probably +be different. +See also `window-height' and `window-displayed-height'. +*/ + (window)) +{ + return make_int (window_char_height (decode_window (window), 0)); } DEFUN ("window-text-area-pixel-height", @@ -1345,7 +1417,7 @@ is non-nil, do not include space occupied by clipped lines. if (NILP (window)) window = Fselected_window (Qnil); - CHECK_WINDOW (window); + CHECK_LIVE_WINDOW (window); w = XWINDOW (window); start = marker_position (w->start[CURRENT_DISP]); @@ -1389,13 +1461,25 @@ is non-nil, do not include space occupied by clipped lines. DEFUN ("window-width", Fwindow_width, 0, 1, 0, /* Return the number of display columns in WINDOW. -This is the width that is usable columns available for text in WINDOW. +This is the width that is usable columns available for text in WINDOW, +and does not include vertical scrollbars, dividers, or the like. See also +`window-full-width' and `window-height'. */ (window)) { return make_int (window_char_width (decode_window (window), 0)); } +DEFUN ("window-full-width", Fwindow_full_width, 0, 1, 0, /* +Return the total number of columns in WINDOW. +This is like `window-width' but includes vertical scrollbars, dividers, +etc. +*/ + (window)) +{ + return make_int (window_char_width (decode_window (window), 1)); +} + DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /* Return the width of WINDOW in pixels. Defaults to current window. */ @@ -1425,22 +1509,23 @@ Return the number of columns by which WINDOW is scrolled from left margin. return make_int (decode_window (window)->hscroll); } -#ifdef MODELINE_IS_SCROLLABLE DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /* -Return the number of columns by which WINDOW's modeline is scrolled from -left margin. If the window has no modeline, return nil. +Return the horizontal scrolling ammount of WINDOW's modeline. +If the window has no modeline, return nil. */ (window)) { struct window *w = decode_window (window); - return (WINDOW_HAS_MODELINE_P (w)) ? make_int (w->modeline_hscroll) : Qnil; + return (WINDOW_HAS_MODELINE_P (w)) ? make_int ((int) w->modeline_hscroll) : + Qnil; } DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /* -Set number of columns WINDOW's modeline is scrolled from left margin to NCOL. -NCOL should be zero or positive. If NCOL is negative, it will be forced to 0. -If the window has no modeline, do nothing and return nil. +Set the horizontal scrolling ammount of WINDOW's modeline to NCOL. +If NCOL is negative, it will silently be forced to 0. +If the window has no modeline, return nil. Otherwise, return the actual +value that was set. */ (window, ncol)) { @@ -1448,18 +1533,20 @@ If the window has no modeline, do nothing and return nil. if (WINDOW_HAS_MODELINE_P (w)) { - int ncols; + Charcount ncols; + CHECK_INT (ncol); - ncols = XINT (ncol); - if (ncols < 0) ncols = 0; - if (w->modeline_hscroll != ncols) - MARK_MODELINE_CHANGED; - w->modeline_hscroll = ncols; - return ncol; + ncols = (XINT (ncol) <= 0) ? 0 : (Charcount) XINT (ncol); + if (ncols != w->modeline_hscroll) + { + MARK_MODELINE_CHANGED; + w->modeline_hscroll = ncols; + } + return make_int ((int) ncols); } + return Qnil; } -#endif /* MODELINE_IS_SCROLLABLE */ DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /* Set number of columns WINDOW is scrolled from left margin to NCOL. @@ -1511,15 +1598,14 @@ Afterwards the end-trigger value is reset to nil. DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /* Return a list of the pixel edge coordinates of WINDOW. \(LEFT TOP RIGHT BOTTOM), all relative to 0, 0 at top left corner of frame. -The frame toolbars and menubars are considered to be outside of this area. +The frame toolbars, menubars and gutters are considered to be outside of this area. */ (window)) { struct window *w = decode_window (window); - struct frame *f = XFRAME (w->frame); - int left = w->pixel_left - FRAME_LEFT_BORDER_END (f); - int top = w->pixel_top - FRAME_TOP_BORDER_END (f); + int left = w->pixel_left; + int top = w->pixel_top; return list4 (make_int (left), make_int (top), @@ -1608,6 +1694,28 @@ slower with this flag set. } } +DEFUN ("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /* +Return pixel height of visible part of last window line if it is clipped. +If the last line is not clipped, return nil. +*/ + (window)) +{ + struct window *w = decode_window (window); + display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); + int num_lines = Dynarr_length (dla); + struct display_line *dl; + + /* No lines - no clipped lines */ + if (num_lines == 0 || (num_lines == 1 && Dynarr_atp (dla, 0)->modeline)) + return Qnil; + + dl = Dynarr_atp (dla, num_lines - 1); + if (dl->clip == 0) + return Qnil; + + return make_int (dl->ascent + dl->descent - dl->clip); +} + DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /* Make point value in WINDOW be at position POS in WINDOW's buffer. */ @@ -1759,6 +1867,34 @@ replace_window (Lisp_Object old, Lisp_Object replacement) /* #### Here, if replacement is a vertical combination and so is its new parent, we should make replacement's children be children of that parent instead. */ + + ERROR_CHECK_SUBWINDOW_CACHE (p); +} + +static int +window_unmap_subwindows_cache_mapper (Lisp_Object key, Lisp_Object value, + void *flag_closure) +{ + /* value can be nil; we cache failures as well as successes */ + if (!NILP (value)) + { + struct frame* f = XFRAME (XIMAGE_INSTANCE_FRAME (value)); + unmap_subwindow (value); + /* In case GC doesn't catch up fast enough, remove from the frame + cache also. Otherwise code that checks the sanity of the instance + will fail. */ + XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)) + = delq_no_quit (value, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))); + } + return 0; +} + +static void +window_unmap_subwindows (struct window* w) +{ + assert (!NILP (w->subwindow_instance_cache)); + elisp_maphash (window_unmap_subwindows_cache_mapper, + w->subwindow_instance_cache, 0); } /* we're deleting W; set the structure of W to indicate this. */ @@ -1766,6 +1902,20 @@ replace_window (Lisp_Object old, Lisp_Object replacement) static void mark_window_as_deleted (struct window *w) { + /* The window instance cache is going away now, so need to get the + cachels reset by redisplay. */ + MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (WINDOW_FRAME (w))); + + /* The cache is going away. If we leave unmapping to + reset_subwindow_cachels then we get in a situation where the + domain (the window) has been deleted but we still need access to + its attributes in order to unmap windows properly. Since the + subwindows are going to get GC'd anyway as a result of the domain + going away, it is safer to just unmap them all while we know the + domain is still valid. */ + ERROR_CHECK_SUBWINDOW_CACHE (w); + window_unmap_subwindows (w); + /* In the loop (while t (split-window) (delete-window)) we end up with a tree of deleted windows which are all connected @@ -1777,13 +1927,13 @@ mark_window_as_deleted (struct window *w) Since the window-configuration code doesn't need any of the pointers to other windows (they are all recreated from the window-config data), we set them all to nil so that we - are able to collect more actual garbage. - */ + are able to collect more actual garbage. */ w->next = Qnil; w->prev = Qnil; w->hchild = Qnil; w->vchild = Qnil; w->parent = Qnil; + w->subwindow_instance_cache = Qnil; w->dead = 1; @@ -1820,6 +1970,7 @@ will automatically call `save-buffers-kill-emacs'.) window = Fselected_window (Qnil); else CHECK_WINDOW (window); + w = XWINDOW (window); /* It's okay to delete an already-deleted window. */ @@ -1853,6 +2004,12 @@ will automatically call `save-buffers-kill-emacs'.) par = XWINDOW (parent); MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); + /* It's quite likely that deleting a window will result in + subwindows needing to be deleted also (since they are cached + per-window). So we mark them as changed, so that the cachels will + get reset by redisplay and thus deleted subwindows can get + GC'd. */ + MARK_FRAME_SUBWINDOWS_CHANGED (f); /* Are we trying to delete any frame's selected window? Note that we could be dealing with a non-leaf window @@ -2584,7 +2741,7 @@ window_loop (enum window_loop type, new_buffer = Fother_buffer (obj, Qnil, Qnil); if (NILP (new_buffer)) new_buffer = Fget_buffer_create (QSscratch); - Fset_window_buffer (w, new_buffer); + Fset_window_buffer (w, new_buffer, Qnil); if (EQ (w, Fselected_window (Qnil))) Fset_buffer (p->buffer); } @@ -2656,7 +2813,7 @@ window_loop (enum window_loop type, /* Otherwise show a different buffer in the window. */ p->dedicated = Qnil; - Fset_window_buffer (w, another_buffer); + Fset_window_buffer (w, another_buffer, Qnil); if (EQ (w, Fselected_window (Qnil))) Fset_buffer (p->buffer); } @@ -2957,17 +3114,41 @@ check_min_window_sizes (void) window_min_height = MIN_SAFE_WINDOW_HEIGHT; } +static int +frame_min_height (struct frame *frame) +{ + /* For height, we have to see whether the frame has a minibuffer, and + whether it wants a modeline. */ + return (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); +} + +/* Return non-zero if both frame sizes are less than or equal to + minimal allowed values. ROWS and COLS are in characters */ +int +frame_size_valid_p (struct frame *frame, int rows, int cols) +{ + return (rows >= frame_min_height (frame) + && cols >= MIN_SAFE_WINDOW_WIDTH); +} + +/* Return non-zero if both frame sizes are less than or equal to + minimal allowed values. WIDTH and HEIGHT are in pixels */ +int +frame_pixsize_valid_p (struct frame *frame, int width, int height) +{ + int rows, cols; + pixel_to_real_char_size (frame, width, height, &cols, &rows); + return frame_size_valid_p (frame, rows, cols); +} + /* If *ROWS or *COLS are too small a size for FRAME, set them to the minimum allowable size. */ void check_frame_size (struct frame *frame, int *rows, int *cols) { - /* For height, we have to see whether the frame has a minibuffer, and - whether it wants a modeline. */ - 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); + int min_height = frame_min_height (frame); if (*rows < min_height) *rows = min_height; @@ -3117,11 +3298,14 @@ set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete) static int window_select_count; -DEFUN ("set-window-buffer", Fset_window_buffer, 2, 2, 0, /* +DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /* Make WINDOW display BUFFER as its contents. BUFFER can be a buffer or buffer name. + +With non-nil optional argument `norecord', do not modify the +global or per-frame buffer ordering. */ - (window, buffer)) + (window, buffer, norecord)) { Lisp_Object tem; struct window *w = decode_window (window); @@ -3180,6 +3364,9 @@ BUFFER can be a buffer or buffer name. recompute_all_cached_specifiers_in_window (w); if (EQ (window, Fselected_window (Qnil))) { + if (NILP (norecord)) + Frecord_buffer (buffer); + Fset_buffer (buffer); } return Qnil; @@ -3204,8 +3391,9 @@ global or per-frame buffer ordering. /* we have already caught dead-window errors */ if (!NILP (w->hchild) || !NILP (w->vchild)) error ("Trying to select non-leaf window"); - + w->use_time = make_int (++window_select_count); + if (EQ (window, old_selected_window)) return window; @@ -3319,7 +3507,7 @@ make_dummy_parent (Lisp_Object window) { Lisp_Object new; struct window *o = XWINDOW (window); - struct window *p = alloc_lcrecord_type (struct window, lrecord_window); + struct window *p = alloc_lcrecord_type (struct window, &lrecord_window); XSETWINDOW (new, p); copy_lcrecord (p, o); @@ -3329,6 +3517,10 @@ make_dummy_parent (Lisp_Object window) p->line_start_cache = Dynarr_new (line_start_cache); p->face_cachels = Dynarr_new (face_cachel); p->glyph_cachels = Dynarr_new (glyph_cachel); + p->subwindow_instance_cache = + make_lisp_hash_table (30, + HASH_TABLE_KEY_WEAK, + HASH_TABLE_EQUAL); /* Put new into window structure in place of window */ replace_window (window, new); @@ -3366,7 +3558,7 @@ and put SIZE columns in the first of the pair. if (NILP (window)) window = Fselected_window (Qnil); else - CHECK_WINDOW (window); + CHECK_LIVE_WINDOW (window); o = XWINDOW (window); f = XFRAME (WINDOW_FRAME (o)); @@ -3482,7 +3674,7 @@ and put SIZE columns in the first of the pair. /* do this last (after the window is completely initialized and the mirror-dirty flag is set) so that specifier recomputation caused as a result of this will work properly and not abort. */ - Fset_window_buffer (new, o->buffer); + Fset_window_buffer (new, o->buffer, Qt); return new; } @@ -3544,12 +3736,6 @@ selected window. } static int -window_pixel_height (Lisp_Object window) -{ - return WINDOW_HEIGHT (XWINDOW (window)); -} - -static int window_pixel_height_to_char_height (struct window *w, int pixel_height, int include_gutters_p) { @@ -3562,8 +3748,8 @@ window_pixel_height_to_char_height (struct window *w, int pixel_height, avail_height = (pixel_height - (include_gutters_p ? 0 : - window_top_gutter_height (w) + - window_bottom_gutter_height (w))); + window_top_window_gutter_height (w) + + window_bottom_window_gutter_height (w))); default_face_height_and_width (window, &defheight, &defwidth); @@ -3594,8 +3780,8 @@ window_char_height_to_pixel_height (struct window *w, int char_height, avail_height = char_height * defheight; pixel_height = (avail_height + (include_gutters_p ? 0 : - window_top_gutter_height (w) + - window_bottom_gutter_height (w))); + window_top_window_gutter_height (w) + + window_bottom_window_gutter_height (w))); /* It's the calling function's responsibility to check these values and make sure they're not out of range. @@ -3608,11 +3794,12 @@ window_char_height_to_pixel_height (struct window *w, int char_height, /* Return number of default lines of text can fit in the window W. If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus horizontal scrollbar) in the space that is used for the calculation. + This doesn't include space used by the frame gutters. */ int window_char_height (struct window *w, int include_gutters_p) { - return window_pixel_height_to_char_height (w, WINDOW_HEIGHT (w), + return window_pixel_height_to_char_height (w, window_pixel_height (w), include_gutters_p); } @@ -3692,6 +3879,8 @@ window_pixel_width (Lisp_Object window) return WINDOW_WIDTH (XWINDOW (window)); } +/* Calculate the pixel of a window, optionally including margin space + but no vertical gutters. */ static int window_pixel_width_to_char_width (struct window *w, int pixel_width, int include_margins_p) @@ -3736,8 +3925,8 @@ window_char_width_to_pixel_width (struct window *w, int char_width, avail_width = char_width * defwidth; pixel_width = (avail_width + - window_left_gutter_width (w, 0) + - window_right_gutter_width (w, 0) + + window_left_window_gutter_width (w, 0) + + window_right_window_gutter_width (w, 0) + (include_margins_p ? 0 : window_left_margin_width (w)) + (include_margins_p ? 0 : window_right_margin_width (w))); @@ -3776,6 +3965,12 @@ window_char_width (struct window *w, int include_margins_p) (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \ ? 1 : window_min_height) +static int +window_pixheight (Lisp_Object w) +{ + return window_pixel_height (XWINDOW (w)); +} + /* Unlike set_window_pixheight, this function also changes the heights of the siblings so as to keep everything consistent. */ @@ -3791,7 +3986,7 @@ change_window_height (struct window *win, int delta, int widthflag, int *sizep; int (*sizefun) (Lisp_Object) = (widthflag ? window_pixel_width - : window_pixel_height); + : window_pixheight); void (*setsizefun) (Lisp_Object, int, int) = (widthflag ? set_window_pixwidth : set_window_pixheight); @@ -3926,6 +4121,8 @@ change_window_height (struct window *win, int delta, int widthflag, SET_LAST_MODIFIED (w, 0); SET_LAST_FACECHANGE (w); MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); + /* overkill maybe, but better to be correct */ + MARK_FRAME_GUTTERS_CHANGED (f); } #undef MINSIZE #undef CURBEG @@ -3935,7 +4132,8 @@ change_window_height (struct window *win, int delta, int widthflag, -/* Scroll contents of window WINDOW up N lines. */ +/* Scroll contents of window WINDOW up N lines. If N < (top line height / + average line height) then we just adjust the top clip. */ void window_scroll (Lisp_Object window, Lisp_Object n, int direction, Error_behavior errb) @@ -3945,6 +4143,9 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction, int selected = EQ (window, Fselected_window (Qnil)); int value = 0; Lisp_Object point, tem; + display_line_dynarr *dla; + int fheight, fwidth, modeline = 0; + struct display_line* dl; if (selected) point = make_int (BUF_PT (b)); @@ -3974,6 +4175,7 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction, window, Qnil); Fset_marker (w->start[CURRENT_DISP], point, w->buffer); w->start_at_line_beg = beginning_of_line_p (b, XINT (point)); + WINDOW_TEXT_TOP_CLIP (w) = 0; MARK_WINDOWS_CHANGED (w); } @@ -4017,82 +4219,164 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction, { return; } - else if (value > 0) - { - int vtarget; - Bufpos startp, old_start; - old_start = marker_position (w->start[CURRENT_DISP]); - startp = vmotion (w, old_start, value, &vtarget); + /* Determine parameters to test for partial line scrolling with. */ + dla = window_display_lines (w, CURRENT_DISP); + + if (INTP (Vwindow_pixel_scroll_increment)) + fheight = XINT (Vwindow_pixel_scroll_increment); + else if (!NILP (Vwindow_pixel_scroll_increment)) + default_face_height_and_width (window, &fheight, &fwidth); - if (vtarget < value && - (w->window_end_pos[CURRENT_DISP] == -1 - || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)))) + if (Dynarr_length (dla) >= 1) + modeline = Dynarr_atp (dla, 0)->modeline; + + dl = Dynarr_atp (dla, modeline); + + if (value > 0) + { + /* Go for partial display line scrolling. This just means bumping + the clip by a reasonable amount and redisplaying, everything else + remains unchanged. */ + if (!NILP (Vwindow_pixel_scroll_increment) + && + Dynarr_length (dla) >= (1 + modeline) + && + (dl->ascent - dl->top_clip) - fheight * value > 0) { - maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb); - return; + WINDOW_TEXT_TOP_CLIP (w) += value * fheight; + MARK_WINDOWS_CHANGED (w); } else { - set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), - w->buffer); - w->force_start = 1; - w->start_at_line_beg = beginning_of_line_p (b, startp); - MARK_WINDOWS_CHANGED (w); + int vtarget; + Bufpos startp, old_start; - if (!point_would_be_visible (w, startp, XINT (point))) + if (WINDOW_TEXT_TOP_CLIP (w)) { - if (selected) - BUF_SET_PT (b, startp); - else - set_marker_restricted (w->pointm[CURRENT_DISP], - make_int (startp), - w->buffer); + WINDOW_TEXT_TOP_CLIP (w) = 0; + MARK_WINDOWS_CHANGED (w); + } + + old_start = marker_position (w->start[CURRENT_DISP]); + startp = vmotion (w, old_start, value, &vtarget); + + if (vtarget < value && + (w->window_end_pos[CURRENT_DISP] == -1 + || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)))) + { + maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb); + return; + } + else + { + set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), + w->buffer); + w->force_start = 1; + w->start_at_line_beg = beginning_of_line_p (b, startp); + MARK_WINDOWS_CHANGED (w); + + if (!point_would_be_visible (w, startp, XINT (point))) + { + if (selected) + BUF_SET_PT (b, startp); + else + set_marker_restricted (w->pointm[CURRENT_DISP], + make_int (startp), + w->buffer); + } } } } else if (value < 0) { - int vtarget; - Bufpos startp, old_start; - - old_start = marker_position (w->start[CURRENT_DISP]); - startp = vmotion (w, old_start, value, &vtarget); - - if (vtarget > value - && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b)) + /* Go for partial display line scrolling. This just means bumping + the clip by a reasonable amount and redisplaying, everything else + remains unchanged. */ + if (!NILP (Vwindow_pixel_scroll_increment) + && + Dynarr_length (dla) >= (1 + modeline) + && + (dl->ascent - dl->top_clip) - fheight * value < + (dl->ascent + dl->descent - dl->clip) + && + WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0) { - maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb); - return; + WINDOW_TEXT_TOP_CLIP (w) += value * fheight; + MARK_WINDOWS_CHANGED (w); } else { - set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), - w->buffer); - w->force_start = 1; - w->start_at_line_beg = beginning_of_line_p (b, startp); - MARK_WINDOWS_CHANGED (w); + int vtarget; + Bufpos startp, old_start; - if (!point_would_be_visible (w, startp, XINT (point))) + if (WINDOW_TEXT_TOP_CLIP (w)) { - Bufpos new_point; + WINDOW_TEXT_TOP_CLIP (w) = 0; + MARK_WINDOWS_CHANGED (w); + } - if (MINI_WINDOW_P (w)) - new_point = startp; - else - new_point = start_of_last_line (w, startp); + old_start = marker_position (w->start[CURRENT_DISP]); + startp = vmotion (w, old_start, value, &vtarget); - if (selected) - BUF_SET_PT (b, new_point); - else - set_marker_restricted (w->pointm[CURRENT_DISP], - make_int (new_point), - w->buffer); + if (vtarget > value + && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b)) + { + maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb); + return; + } + else + { + set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), + w->buffer); + w->force_start = 1; + w->start_at_line_beg = beginning_of_line_p (b, startp); + MARK_WINDOWS_CHANGED (w); + + /* #### Scroll back by less than a line. This code was + originally for scrolling over large pixmaps and it + loses when a line being *exposed* at the top of the + window is bigger than the current one. However, for + pixel based scrolling in general we can guess that + the line we are going to display is probably the same + size as the one we are on. In that instance we can + have a reasonable stab at a suitable top clip. Fixing + this properly is hard (and probably slow) as we would + have to call redisplay to figure out the exposed line + size. */ + if (!NILP (Vwindow_pixel_scroll_increment) + && Dynarr_length (dla) >= (1 + modeline) + && dl->ascent + fheight * value > 0) + { + WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value); + } + + if (!point_would_be_visible (w, startp, XINT (point))) + { + Bufpos new_point; + + if (MINI_WINDOW_P (w)) + new_point = startp; + else + new_point = start_of_last_line (w, startp); + + if (selected) + BUF_SET_PT (b, new_point); + else + set_marker_restricted (w->pointm[CURRENT_DISP], + make_int (new_point), + w->buffer); + } } } } else /* value == 0 && direction == -1 */ { + if (WINDOW_TEXT_TOP_CLIP (w)) + { + WINDOW_TEXT_TOP_CLIP (w) = 0; + MARK_WINDOWS_CHANGED (w); + } if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b)) { maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb); @@ -4130,7 +4414,6 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction, } } } - } DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /* @@ -4304,7 +4587,7 @@ If WINDOW is nil, the selected window is used. if (NILP (window)) window = Fselected_window (Qnil); else - CHECK_WINDOW (window); + CHECK_LIVE_WINDOW (window); w = XWINDOW (window); b = XBUFFER (w->buffer); @@ -4606,7 +4889,7 @@ struct saved_window int pixel_width; int pixel_height; int hscroll; - int modeline_hscroll; + Charcount modeline_hscroll; int parent_index; /* index into saved_windows */ int prev_index; /* index into saved_windows */ char start_at_line_beg; /* boolean */ @@ -4621,8 +4904,8 @@ struct saved_window struct window_config { struct lcrecord_header header; - int frame_width; - int frame_height; + /* int frame_width; No longer needed, JV + int frame_height; */ #if 0 /* FSFmacs */ Lisp_Object selected_frame; #endif @@ -4630,6 +4913,7 @@ struct window_config Lisp_Object current_buffer; Lisp_Object minibuffer_scroll_window; Lisp_Object root_window; + int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */ /* Record the values of window-min-width and window-min-height so that window sizes remain consistent with them. */ int min_width, min_height; @@ -4642,36 +4926,35 @@ struct window_config #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config) #define XSETWINDOW_CONFIGURATION(x, p) XSETRECORD (x, p, window_configuration) #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration) -#define GC_WINDOW_CONFIGURATIONP(x) GC_RECORDP (x, window_configuration) #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration) static Lisp_Object -mark_window_config (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_window_config (Lisp_Object obj) { struct window_config *config = XWINDOW_CONFIGURATION (obj); int i; - markobj (config->current_window); - markobj (config->current_buffer); - markobj (config->minibuffer_scroll_window); - markobj (config->root_window); + mark_object (config->current_window); + mark_object (config->current_buffer); + mark_object (config->minibuffer_scroll_window); + mark_object (config->root_window); for (i = 0; i < config->saved_windows_count; i++) { struct saved_window *s = SAVED_WINDOW_N (config, i); - markobj (s->window); - markobj (s->buffer); - markobj (s->start); - markobj (s->pointm); - markobj (s->sb_point); - markobj (s->mark); + mark_object (s->window); + mark_object (s->buffer); + mark_object (s->start); + mark_object (s->pointm); + mark_object (s->sb_point); + mark_object (s->mark); #if 0 /* #### This looked like this. I do not see why specifier cached values should not be marked, as such specifiers as toolbars might have GC-able instances. Freed configs are not marked, aren't they? -- kkm */ - markobj (s->dedicated); + mark_object (s->dedicated); #else -#define WINDOW_SLOT(slot, compare) ((void) (markobj (s->slot))) +#define WINDOW_SLOT(slot, compare) mark_object (s->slot) #include "winslots.h" #endif } @@ -4687,9 +4970,9 @@ sizeof_window_config_for_n_windows (int n) } static size_t -sizeof_window_config (CONST void *h) +sizeof_window_config (const void *h) { - CONST struct window_config *c = (CONST struct window_config *) h; + const struct window_config *c = (const struct window_config *) h; return sizeof_window_config_for_n_windows (c->saved_windows_count); } @@ -4710,7 +4993,7 @@ DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration", window_configuration, mark_window_config, print_window_config, - 0, 0, 0, sizeof_window_config, + 0, 0, 0, 0, sizeof_window_config, struct window_config); @@ -4761,9 +5044,10 @@ window_config_equal (Lisp_Object conf1, Lisp_Object conf2) EQ (fig1->current_window, fig2->current_window) && EQ (fig1->current_buffer, fig2->current_buffer) && EQ (fig1->root_window, fig2->root_window) && - EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window) && + EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window))) + /* && fig1->frame_width == fig2->frame_width && - fig1->frame_height == fig2->frame_height)) + fig1->frame_height == fig2->frame_height)) */ return 0; for (i = 0; i < fig1->saved_windows_count; i++) @@ -4859,8 +5143,15 @@ by `current-window-configuration' (which see). struct frame *f; struct gcpro gcpro1; Lisp_Object old_window_config; - int previous_frame_height; - int previous_frame_width; + /* int previous_frame_height; + int previous_frame_width;*/ + int previous_pixel_top; + int previous_pixel_height; + int previous_pixel_left; + int previous_pixel_width; + int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width; + int real_font_height; + int converted_minibuf_height,target_minibuf_height; int specpdl_count = specpdl_depth (); GCPRO1 (configuration); @@ -4925,6 +5216,25 @@ by `current-window-configuration' (which see). mark_windows_in_use (f, 1); + /* Force subwindows to be reinstantiated. They are all going + anyway and if we don't do this GC may not happen between now + and the next time we check their integrity. */ + reset_frame_subwindow_instance_cache (f); + +#if 0 + /* JV: This is bogus, + First of all, the units are inconsistent. The frame sizes are measured + in characters but the window sizes are stored in pixels. So if a + font size change happened between saving and restoring, the + frame "sizes" maybe equal but the windows still should be + resized. This is tickled alot by the new "character size + stays constant" policy in 21.0. It leads to very wierd + glitches (and possibly crashes when asserts are tickled). + + Just changing the units doens't help because changing the + toolbar configuration can also change the pixel positions. + Luckily there is a much simpler way of doing this, see below. + */ previous_frame_width = FRAME_WIDTH (f); previous_frame_height = FRAME_HEIGHT (f); /* If the frame has been resized since this window configuration was @@ -4934,6 +5244,37 @@ by `current-window-configuration' (which see). if (config->frame_height != FRAME_HEIGHT (f) || config->frame_width != FRAME_WIDTH (f)) change_frame_size (f, config->frame_height, config->frame_width, 0); +#endif + + previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top; + previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height; + previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left; + previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width; + + /* remember some properties of the minibuffer */ + + default_face_height_and_width (frame, &real_font_height, 0); + assert(real_font_height > 0); + + if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f)) + { + previous_minibuf_height + = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height; + previous_minibuf_top + = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top; + previous_minibuf_width + = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width; + } + else + { + previous_minibuf_height = 0; + previous_minibuf_top = 0; + previous_minibuf_width = 0; + } + converted_minibuf_height = + (previous_minibuf_height % real_font_height) == 0 ? + - (previous_minibuf_height / real_font_height ) : /* lines */ + previous_minibuf_height; /* pixels */ /* Temporarily avoid any problems with windows that are smaller than they are supposed to be. */ @@ -4961,6 +5302,10 @@ by `current-window-configuration' (which see). w->glyph_cachels = Dynarr_new (glyph_cachel); if (!w->line_start_cache) w->line_start_cache = Dynarr_new (line_start_cache); + w->gutter_extent_modiff[0] = 0; + w->gutter_extent_modiff[1] = 0; + w->gutter_extent_modiff[2] = 0; + w->gutter_extent_modiff[3] = 0; w->dead = 0; if (p->parent_index >= 0) @@ -5018,11 +5363,19 @@ by `current-window-configuration' (which see). w->hscroll = p->hscroll; w->modeline_hscroll = p->modeline_hscroll; w->line_cache_last_updated = Qzero; + /* The subwindow instance cache isn't preserved across + window configurations, and in fact doing so would be + wrong. We just reset to zero and then redisplay will fill + it up as needed. */ + w->subwindow_instance_cache = + make_lisp_hash_table (30, + HASH_TABLE_KEY_WEAK, + HASH_TABLE_EQUAL); SET_LAST_MODIFIED (w, 1); SET_LAST_FACECHANGE (w); w->config_mark = 0; -#define WINDOW_SLOT(slot, compare) w->slot = p->slot; +#define WINDOW_SLOT(slot, compare) w->slot = p->slot #include "winslots.h" /* Reinstall the saved buffer and pointers into it. */ @@ -5100,16 +5453,67 @@ by `current-window-configuration' (which see). currently selected, or just set the selected window of the window config's frame. */ +#if 0 /* Set the frame 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); +#endif + /* We just reset the size and position of the minibuffer, to its old + value, which needn't be valid. So we do some magic to see which value + to actually take. Then we set it. + + The magic: + We take the old value if is in the same units but differs from the + current value. + + #### Now we get more cases correct then ever before, but + are we treating all? For instance what if the frames minibuf window + is no longer the same one? + */ + target_minibuf_height = previous_minibuf_height; + if (converted_minibuf_height && + (converted_minibuf_height * config->minibuf_height) > 0 && + (converted_minibuf_height != config->minibuf_height)) + { + target_minibuf_height = config->minibuf_height < 0 ? + - (config->minibuf_height * real_font_height) : + config->minibuf_height; + target_minibuf_height = + max(target_minibuf_height,real_font_height); + } + if (previous_minibuf_height) + { + XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top + = previous_minibuf_top - + (target_minibuf_height - previous_minibuf_height); + set_window_pixheight (FRAME_MINIBUF_WINDOW (f), + target_minibuf_height, 0); + set_window_pixwidth (FRAME_MINIBUF_WINDOW (f), + previous_minibuf_width, 0); + } + + /* This is a better way to deal with frame resizing, etc. + What we _actually_ want is for the old (just restored) + root window to fit + into the place of the new one. So we just do that. Simple! */ + XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top; + /* Note that this function also updates the subwindow + "pixel_top"s */ + set_window_pixheight (FRAME_ROOT_WINDOW (f), + previous_pixel_height - + (target_minibuf_height - previous_minibuf_height), 0); + XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left; + /* Note that this function also updates the subwindow + "pixel_left"s */ + set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0); /* If restoring in the current frame make the window current, otherwise just update the frame selected_window slot to be the restored current_window. */ if (f == selected_frame ()) { +#if 0 /* When using `pop-window-configuration', often the minibuffer ends up as the selected window even though it's not active ... I really don't know the cause of this, but it should never @@ -5118,15 +5522,25 @@ by `current-window-configuration' (which see). #### Find out why this is really going wrong. */ if (!minibuf_level && MINI_WINDOW_P (XWINDOW (config->current_window))) - Fselect_window (Fnext_window (config->current_window, - Qnil, Qnil, Qnil), - Qnil); + window_to_select = Fnext_window (config->current_window, + Qnil, Qnil, Qnil); else - Fselect_window (config->current_window, Qnil); + window_to_select = config->current_window; +#endif + /* Do this last so that buffer stacking is calculated + correctly. */ + Fselect_window (config->current_window, Qnil); + if (!NILP (new_current_buffer)) - Fset_buffer (new_current_buffer); + { + Fset_buffer (new_current_buffer); + Frecord_buffer (new_current_buffer); + } else - Fset_buffer (XWINDOW (Fselected_window (Qnil))->buffer); + { + Fset_buffer (XWINDOW (config->current_window)->buffer); + Frecord_buffer (XWINDOW (config->current_window)->buffer); + } } else set_frame_selected_window (f, config->current_window); @@ -5246,7 +5660,7 @@ save_window_save (Lisp_Object window, struct window_config *config, int i) p->hscroll = w->hscroll; p->modeline_hscroll = w->modeline_hscroll; -#define WINDOW_SLOT(slot, compare) p->slot = w->slot; +#define WINDOW_SLOT(slot, compare) p->slot = w->slot #include "winslots.h" if (!NILP (w->buffer)) @@ -5319,6 +5733,8 @@ its value is -not- saved. struct frame *f = decode_frame (frame); struct window_config *config; int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f))); + int minibuf_height; + int real_font_height; if (n_windows <= countof (Vwindow_configuration_free_list)) config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord @@ -5328,12 +5744,19 @@ its value is -not- saved. /* More than ten windows; just allocate directly */ config = (struct window_config *) alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows), - lrecord_window_configuration); + &lrecord_window_configuration); XSETWINDOW_CONFIGURATION (result, config); - + /* config->frame_width = FRAME_WIDTH (f); - config->frame_height = FRAME_HEIGHT (f); - config->current_window = FRAME_SELECTED_WINDOW (f); + config->frame_height = FRAME_HEIGHT (f); */ + /* When using `push-window-configuration', often the minibuffer ends + up as the selected window because functions run as the result of + user interaction e.g. hyper-apropros. It seems to me the sensible + thing to do is not record the minibuffer here. */ + if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level) + config->current_window = FRAME_SELECTED_WINDOW (f); + else + config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f); XSETBUFFER (config->current_buffer, current_buffer); config->minibuffer_scroll_window = Vminibuffer_scroll_window; config->root_window = FRAME_ROOT_WINDOW (f); @@ -5341,6 +5764,22 @@ its value is -not- saved. config->min_width = window_min_width; config->saved_windows_count = n_windows; save_window_save (FRAME_ROOT_WINDOW (f), config, 0); + + /* save the minibuffer height using the heuristics from + change_frame_size_1 */ + + XSETFRAME (frame, f); /* frame could have been nil ! */ + default_face_height_and_width (frame, &real_font_height, 0); + assert(real_font_height > 0); + + if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f)) + minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height; + else + minibuf_height = 0; + config->minibuf_height = (minibuf_height % real_font_height) == 0 ? + - (minibuf_height / real_font_height ) : /* lines */ + minibuf_height; /* pixels */ + return result; } @@ -5370,6 +5809,78 @@ Does not restore the value of point in current buffer. return unbind_to (speccount, val); } +DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /* +Return the horizontal pixel position of POS in window. +Beginning of line is column 0. This is calculated using the redisplay +display tables. If WINDOW is nil, the current window is assumed. +If POS is nil, point is assumed. Note that POS must be visible for +a non-nil result to be returned. +*/ + (window, pos)) +{ + struct window* w = decode_window (window); + display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); + + struct display_line *dl = 0; + struct display_block *db = 0; + struct rune* rb = 0; + int y = w->last_point_y[CURRENT_DISP]; + int x = w->last_point_x[CURRENT_DISP]; + + if (MINI_WINDOW_P (w)) + return Qnil; + + if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos)) + { + int first_line, i; + Bufpos point; + + if (NILP (pos)) + pos = Fwindow_point (window); + + CHECK_INT (pos); + point = XINT (pos); + + if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline) + first_line = 1; + else + first_line = 0; + + for (i = first_line; i < Dynarr_length (dla); i++) + { + dl = Dynarr_atp (dla, i); + /* find the vertical location first */ + if (point >= dl->bufpos && point <= dl->end_bufpos) + { + db = get_display_block_from_line (dl, TEXT); + for (i = 0; i < Dynarr_length (db->runes); i++) + { + rb = Dynarr_atp (db->runes, i); + if (point <= rb->bufpos) + goto found_bufpos; + } + return Qnil; + } + } + return Qnil; + found_bufpos: + ; + } + else + { + /* optimised case */ + dl = Dynarr_atp (dla, y); + db = get_display_block_from_line (dl, TEXT); + + if (x >= Dynarr_length (db->runes)) + return Qnil; + + rb = Dynarr_atp (db->runes, x); + } + + return make_int (rb->xpos - WINDOW_LEFT (w)); +} + #ifdef DEBUG_XEMACS /* This is short and simple in elisp, but... it was written to debug @@ -5385,15 +5896,15 @@ debug_print_window (Lisp_Object window, int level) child = Fwindow_first_hchild (window); for (i = level; i > 0; i--) - putc ('\t', stderr); + stderr_out ("\t"); - fputs ("#buffer; if (!NILP (buffer) && BUFFERP (buffer)) - fprintf (stderr, " on %s", XSTRING_DATA (XBUFFER (buffer)->name)); + stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name)); } - fprintf (stderr, " 0x%x>", XWINDOW (window)->header.uid); + stderr_out (" 0x%x>", XWINDOW (window)->header.uid); while (!NILP (child)) { @@ -5419,11 +5930,12 @@ debug_print_windows (struct frame *f) void syms_of_window (void) { + INIT_LRECORD_IMPLEMENTATION (window); + INIT_LRECORD_IMPLEMENTATION (window_configuration); + defsymbol (&Qwindowp, "windowp"); defsymbol (&Qwindow_live_p, "window-live-p"); defsymbol (&Qwindow_configurationp, "window-configuration-p"); - defsymbol (&Qscroll_up, "scroll-up"); - defsymbol (&Qscroll_down, "scroll-down"); defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook"); defsymbol (&Qdisplay_buffer, "display-buffer"); @@ -5439,6 +5951,7 @@ syms_of_window (void) #endif DEFSUBR (Fselected_window); + DEFSUBR (Flast_nonminibuf_window); DEFSUBR (Fminibuffer_window); DEFSUBR (Fwindow_minibuffer_p); DEFSUBR (Fwindowp); @@ -5449,6 +5962,7 @@ syms_of_window (void) DEFSUBR (Fwindow_previous_child); DEFSUBR (Fwindow_parent); DEFSUBR (Fwindow_lowest_p); + DEFSUBR (Fwindow_truncated_p); DEFSUBR (Fwindow_highest_p); DEFSUBR (Fwindow_leftmost_p); DEFSUBR (Fwindow_rightmost_p); @@ -5458,26 +5972,27 @@ syms_of_window (void) DEFSUBR (Fwindow_height); DEFSUBR (Fwindow_displayed_height); DEFSUBR (Fwindow_width); + DEFSUBR (Fwindow_full_width); DEFSUBR (Fwindow_pixel_height); DEFSUBR (Fwindow_pixel_width); + DEFSUBR (Fwindow_text_area_height); DEFSUBR (Fwindow_text_area_pixel_height); DEFSUBR (Fwindow_displayed_text_pixel_height); DEFSUBR (Fwindow_text_area_pixel_width); DEFSUBR (Fwindow_hscroll); -#ifdef MODELINE_IS_SCROLLABLE + DEFSUBR (Fset_window_hscroll); DEFSUBR (Fmodeline_hscroll); DEFSUBR (Fset_modeline_hscroll); -#endif /* MODELINE_IS_SCROLLABLE */ #if 0 /* bogus FSF crock */ DEFSUBR (Fwindow_redisplay_end_trigger); DEFSUBR (Fset_window_redisplay_end_trigger); #endif - DEFSUBR (Fset_window_hscroll); DEFSUBR (Fwindow_pixel_edges); DEFSUBR (Fwindow_text_area_pixel_edges); DEFSUBR (Fwindow_point); DEFSUBR (Fwindow_start); DEFSUBR (Fwindow_end); + DEFSUBR (Fwindow_last_line_visible_height); DEFSUBR (Fset_window_point); DEFSUBR (Fset_window_start); DEFSUBR (Fwindow_dedicated_p); @@ -5517,14 +6032,30 @@ syms_of_window (void) DEFSUBR (Fset_window_configuration); DEFSUBR (Fcurrent_window_configuration); DEFSUBR (Fsave_window_excursion); + DEFSUBR (Fcurrent_pixel_column); } void -vars_of_window (void) +reinit_vars_of_window (void) { + int i; /* Make sure all windows get marked */ minibuf_window = Qnil; - staticpro (&minibuf_window); + staticpro_nodump (&minibuf_window); + + for (i = 0; i < countof (Vwindow_configuration_free_list); i++) + { + Vwindow_configuration_free_list[i] = + make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1), + &lrecord_window_configuration); + staticpro_nodump (&Vwindow_configuration_free_list[i]); + } +} + +void +vars_of_window (void) +{ + reinit_vars_of_window (); DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /* *Non-nil means to scroll if point lands on a line which is clipped. @@ -5555,6 +6086,13 @@ If non-nil, this is a buffer and \\[scroll-other-window] should scroll its windo */ ); Vother_window_scroll_buffer = Qnil; + DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /* +*Number of pixels to scroll by per requested line. +If nil then normal line scrolling occurs regardless of line height. +If t then scrolling is done in increments equal to the height of the default face. +*/ ); + Vwindow_pixel_scroll_increment = Qt; + DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /* *Number of lines of continuity when scrolling by screenfuls. */ ); @@ -5569,18 +6107,6 @@ If non-nil, this is a buffer and \\[scroll-other-window] should scroll its windo *Delete any window less than this wide. */ ); window_min_width = 10; - - { - int i; - - for (i = 0; i < countof (Vwindow_configuration_free_list); i++) - { - Vwindow_configuration_free_list[i] = - make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1), - lrecord_window_configuration); - staticpro (&Vwindow_configuration_free_list[i]); - } - } } void @@ -5601,8 +6127,7 @@ This is a specifier; use `set-specifier' to change it. Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2), Qnil, Qnil, Qnil); set_specifier_caching (Vmodeline_shadow_thickness, - slot_offset (struct window, - modeline_shadow_thickness), + offsetof (struct window, modeline_shadow_thickness), modeline_shadow_thickness_changed, 0, 0); @@ -5614,8 +6139,7 @@ This is a specifier; use `set-specifier' to change it. set_specifier_fallback (Vhas_modeline_p, list1 (Fcons (Qnil, Qt))); set_specifier_caching (Vhas_modeline_p, - slot_offset (struct window, - has_modeline_p), + offsetof (struct window, has_modeline_p), /* #### It's strange that we need a special flag to indicate that the shadow-thickness has changed, but not one to indicate that @@ -5637,8 +6161,8 @@ This is a specifier; use `set-specifier' to change it. set_specifier_fallback (Vvertical_divider_always_visible_p, list1 (Fcons (Qnil, Qt))); set_specifier_caching (Vvertical_divider_always_visible_p, - slot_offset (struct window, - vertical_divider_always_visible_p), + offsetof (struct window, + vertical_divider_always_visible_p), vertical_divider_changed_in_window, 0, 0); @@ -5652,8 +6176,8 @@ This is a specifier; use `set-specifier' to change it. Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2), Qnil, Qnil, Qnil); set_specifier_caching (Vvertical_divider_shadow_thickness, - slot_offset (struct window, - vertical_divider_shadow_thickness), + offsetof (struct window, + vertical_divider_shadow_thickness), vertical_divider_changed_in_window, 0, 0); DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /* @@ -5683,8 +6207,8 @@ This is a specifier; use `set-specifier' to change it. set_specifier_fallback (Vvertical_divider_line_width, fb); } set_specifier_caching (Vvertical_divider_line_width, - slot_offset (struct window, - vertical_divider_line_width), + offsetof (struct window, + vertical_divider_line_width), vertical_divider_changed_in_window, 0, 0); @@ -5713,8 +6237,7 @@ This is a specifier; use `set-specifier' to change it. set_specifier_fallback (Vvertical_divider_spacing, fb); } set_specifier_caching (Vvertical_divider_spacing, - slot_offset (struct window, - vertical_divider_spacing), + offsetof (struct window, vertical_divider_spacing), vertical_divider_changed_in_window, 0, 0); }