Mercurial > hg > xemacs-beta
comparison src/window.c @ 1149:a123f88fa975
[xemacs-hg @ 2002-12-08 10:24:33 by michaels]
2002-12-02 Mike Sperber <mike@xemacs.org>
* The Great Window Configuration rewrite: Re-implement window
configuration functionality in Emacs Lisp.
* window.h (Fcurrent_window_configuration): Don't export anymore.
(Qcurrent_window_configuration): Declare.
(Qset_window_configuration): Declare.
* event-stream.c (execute_help_form):
* bytecode.c (execute_rare_opcode): Call out to Lisp to save
window excursion.
* window.c (Qcurrent_window_configuration): Declare.
(Qwindow_configurationp):
(Vwindow_configuration_free_list):
(Qset_window_configuration):
(Qtemp_buffer_show_hook):
(struct saved_window):
(struct window_config):
(SAVED_WINDOW_N):
(XWINDOW_CONFIGURATION):
(wrap_window_configuration):
(WINDOW_CONFIGURATIONP):
(CHECK_WINDOW_CONFIGURATION):
(mark_window_config):
(sizeof_window_config_for_n_windows):
(sizeof_window_config):
(print_window_config):
(saved_window_equal):
(window_config_equal):
(Fwindow_configuration_p):
(mark_windows_in_use_closure):
(mark_windows_in_use):
(free_window_configuration):
(Fset_window_configuration):
(count_windows):
(saved_window_index):
(save_window_save):
(Fcurrent_window_configuration):
(Fsave_window_excursion): Remove.
(mark_window_as_deleted): Rectify comment about
`set-window-configuration'.
(Fset_window_buffer): Reinstate code not activated because of old
implementation of window configurations.
(temp_output_buffer_show): Don't run `temp-buffer-show-hook'
anymore---this wasn't supposed to happen anyway according to the
documentation of `temp-buffer-show-function'.
(reinit_vars_of_window): Don't do the window configuration stuff
no more
(vars_of_window): Don't set up `temp-buffer-show-hook' any more.
2002-12-02 Mike Sperber <mike@xemacs.org>
* The Great Window Configuration rewrite: Re-implement window
configuration functionality in Emacs Lisp.
* window-xemacs.el (current-window-configuration):
(set-window-configuration): (plus many functions they depend on)
Re-implement window configurations in Emacs Lisp.
author | michaels |
---|---|
date | Sun, 08 Dec 2002 10:25:14 +0000 |
parents | e6409999af4b |
children | 8e95979f01c6 |
comparison
equal
deleted
inserted
replaced
1148:1649f1fb3177 | 1149:a123f88fa975 |
---|---|
49 #include "gutter.h" | 49 #include "gutter.h" |
50 #include "objects.h" | 50 #include "objects.h" |
51 #include "redisplay.h" | 51 #include "redisplay.h" |
52 #include "window-impl.h" | 52 #include "window-impl.h" |
53 | 53 |
54 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp; | 54 Lisp_Object Qwindowp, Qwindow_live_p; |
55 Lisp_Object Qdisplay_buffer; | 55 Lisp_Object Qdisplay_buffer; |
56 | 56 |
57 #ifdef MEMORY_USAGE_STATS | 57 #ifdef MEMORY_USAGE_STATS |
58 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay; | 58 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay; |
59 #ifdef HAVE_SCROLLBARS | 59 #ifdef HAVE_SCROLLBARS |
117 Lisp_Object Vother_window_scroll_buffer; | 117 Lisp_Object Vother_window_scroll_buffer; |
118 | 118 |
119 /* Non-nil means it's the function to call to display temp buffers. */ | 119 /* Non-nil means it's the function to call to display temp buffers. */ |
120 Lisp_Object Vtemp_buffer_show_function; | 120 Lisp_Object Vtemp_buffer_show_function; |
121 | 121 |
122 Lisp_Object Vtemp_buffer_show_hook; | |
123 | |
124 /* If a window gets smaller than either of these, it is removed. */ | 122 /* If a window gets smaller than either of these, it is removed. */ |
125 Fixnum window_min_height; | 123 Fixnum window_min_height; |
126 Fixnum window_min_width; | 124 Fixnum window_min_width; |
127 | 125 |
128 /* Hook run at end of temp_output_buffer_show. */ | |
129 Lisp_Object Qtemp_buffer_show_hook; | |
130 | |
131 /* Number of lines of continuity in scrolling by screenfuls. */ | 126 /* Number of lines of continuity in scrolling by screenfuls. */ |
132 Fixnum next_screen_context_lines; | 127 Fixnum next_screen_context_lines; |
133 | 128 |
134 /* List of freed window configurations with 1 - 10 windows. */ | 129 Lisp_Object Qcurrent_window_configuration, Qset_window_configuration; |
135 static Lisp_Object Vwindow_configuration_free_list[10]; | |
136 | 130 |
137 Lisp_Object Qtruncate_partial_width_windows; | 131 Lisp_Object Qtruncate_partial_width_windows; |
138 | 132 |
139 #define SET_LAST_MODIFIED(w, cache_too) \ | 133 #define SET_LAST_MODIFIED(w, cache_too) \ |
140 do { \ | 134 do { \ |
2027 /* Free the extra data structures attached to windows immediately so | 2021 /* Free the extra data structures attached to windows immediately so |
2028 they don't sit around consuming excess space. They will be | 2022 they don't sit around consuming excess space. They will be |
2029 reinitialized by the window-configuration code as necessary. */ | 2023 reinitialized by the window-configuration code as necessary. */ |
2030 finalize_window ((void *) w, 0); | 2024 finalize_window ((void *) w, 0); |
2031 | 2025 |
2032 /* "Nobody should be accessing anything in this object any more...", | 2026 /* Nobody should be accessing anything in this object any more, |
2033 I said, but unfortunately that's not quite true. | |
2034 set-window-configuration undeletes the window and relies on | |
2035 certain items to be there already. Fuckme! we really should | |
2036 rewrite it in Lisp and just recreate the windows. (But does any | |
2037 code depend on the pointers being the same? At the very least, | |
2038 we should reinit everything in the window.) | |
2039 | |
2040 Nobody should be accessing anything in this object any more, | |
2041 and making them Qnil allows for better GC'ing in case a pointer | 2027 and making them Qnil allows for better GC'ing in case a pointer |
2042 to the dead window continues to hang around. Zero all other | 2028 to the dead window continues to hang around. Zero all other |
2043 structs in case someone tries to access something through them. | 2029 structs in case someone tries to access something through them. |
2044 | 2030 |
2045 (So, in point of fact, we zero out all of the "saved" slots, | 2031 (So, in point of fact, we zero out all of the "saved" slots, |
2053 (while t (split-window) (delete-window)) | 2039 (while t (split-window) (delete-window)) |
2054 we end up with a tree of deleted windows which are all connected | 2040 we end up with a tree of deleted windows which are all connected |
2055 through the `next' slot. This might not seem so bad, as they're | 2041 through the `next' slot. This might not seem so bad, as they're |
2056 deleted, and will presumably be GCed - but if even *one* of those | 2042 deleted, and will presumably be GCed - but if even *one* of those |
2057 windows is still being pointed to, by the user, or by a window | 2043 windows is still being pointed to, by the user, or by a window |
2058 configuration, then *all* of those windows stick around. | 2044 configuration, then *all* of those windows stick around. */ |
2059 | |
2060 Since the window-configuration code doesn't need any of the | |
2061 pointers to other windows (they are all recreated from the | |
2062 window-config data), we set them all to nil so that we | |
2063 are able to collect more actual garbage. */ | |
2064 | 2045 |
2065 #define WINDOW_SLOT(slot) | 2046 #define WINDOW_SLOT(slot) |
2066 #define WINDOW_SAVED_SLOT(slot, compare) w->slot = Qnil; | 2047 #define WINDOW_SAVED_SLOT(slot, compare) w->slot = Qnil; |
2067 #include "winslots.h" | 2048 #include "winslots.h" |
2068 | 2049 |
2193 unchain_marker (w->pointm[CMOTION_DISP]); | 2174 unchain_marker (w->pointm[CMOTION_DISP]); |
2194 unchain_marker (w->start[CURRENT_DISP]); | 2175 unchain_marker (w->start[CURRENT_DISP]); |
2195 unchain_marker (w->start[DESIRED_DISP]); | 2176 unchain_marker (w->start[DESIRED_DISP]); |
2196 unchain_marker (w->start[CMOTION_DISP]); | 2177 unchain_marker (w->start[CMOTION_DISP]); |
2197 unchain_marker (w->sb_point); | 2178 unchain_marker (w->sb_point); |
2198 /* This breaks set-window-configuration if windows in the saved | 2179 w->buffer = Qnil; |
2199 configuration get deleted and multiple frames are in use. */ | |
2200 /* w->buffer = Qnil; */ | |
2201 } | 2180 } |
2202 | 2181 |
2203 /* close up the hole in the sibling list */ | 2182 /* close up the hole in the sibling list */ |
2204 if (!NILP (w->next)) | 2183 if (!NILP (w->next)) |
2205 XWINDOW (w->next)->prev = w->prev; | 2184 XWINDOW (w->next)->prev = w->prev; |
3549 invalid_operation ("Attempt to display deleted buffer", Qunbound); | 3528 invalid_operation ("Attempt to display deleted buffer", Qunbound); |
3550 | 3529 |
3551 tem = w->buffer; | 3530 tem = w->buffer; |
3552 if (NILP (tem)) | 3531 if (NILP (tem)) |
3553 invalid_operation ("Window is deleted", Qunbound); | 3532 invalid_operation ("Window is deleted", Qunbound); |
3554 | |
3555 /* While this seems like a logical thing to do, it causes problems | |
3556 because of saved window configurations. It is possible for a | |
3557 buffer to get restored into a window in which it is already being | |
3558 displayed, but start and point are actually at completely | |
3559 different locations. So we let this function complete fully and | |
3560 it will then make sure redisplay correctly updates things. | |
3561 | |
3562 #### This is a kludge. The correct approach is not to do this | |
3563 but to fix set-window-configuration. */ | |
3564 #if 0 | |
3565 else if (EQ (tem, buffer)) | 3533 else if (EQ (tem, buffer)) |
3566 return Qnil; | 3534 return Qnil; |
3567 #endif | |
3568 else if (! EQ (tem, Qt)) /* w->buffer is t when the window | 3535 else if (! EQ (tem, Qt)) /* w->buffer is t when the window |
3569 is first being set up. */ | 3536 is first being set up. */ |
3570 { | 3537 { |
3571 if (!NILP (w->dedicated) && !EQ (tem, buffer)) | 3538 if (!NILP (w->dedicated) && !EQ (tem, buffer)) |
3572 signal_error (Qinvalid_operation, "Window is dedicated to buffer", tem); | 3539 signal_error (Qinvalid_operation, "Window is dedicated to buffer", tem); |
3741 w->hscroll = 0; | 3708 w->hscroll = 0; |
3742 w->modeline_hscroll = 0; | 3709 w->modeline_hscroll = 0; |
3743 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf); | 3710 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf); |
3744 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf); | 3711 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf); |
3745 set_marker_restricted (w->sb_point, make_int (1), buf); | 3712 set_marker_restricted (w->sb_point, make_int (1), buf); |
3746 | |
3747 /* Run temp-buffer-show-hook, with the chosen window selected. */ | |
3748 if (!preparing_for_armageddon) | |
3749 { | |
3750 Lisp_Object tem; | |
3751 tem = Fboundp (Qtemp_buffer_show_hook); | |
3752 if (!NILP (tem)) | |
3753 { | |
3754 tem = Fsymbol_value (Qtemp_buffer_show_hook); | |
3755 if (!NILP (tem)) | |
3756 { | |
3757 int count = specpdl_depth (); | |
3758 | |
3759 /* Select the window that was chosen, for running | |
3760 the hook. */ | |
3761 record_unwind_protect (save_window_excursion_unwind, | |
3762 Fcurrent_window_configuration (Qnil)); | |
3763 | |
3764 Fselect_window (window, Qnil); | |
3765 run_hook (Qtemp_buffer_show_hook); | |
3766 unbind_to (count); | |
3767 } | |
3768 } | |
3769 } | |
3770 } | 3713 } |
3771 } | 3714 } |
3772 | 3715 |
3773 static void | 3716 static void |
3774 make_dummy_parent (Lisp_Object window) | 3717 make_dummy_parent (Lisp_Object window) |
5144 | 5087 |
5145 return Fnreverse (val); | 5088 return Fnreverse (val); |
5146 } | 5089 } |
5147 | 5090 |
5148 #endif /* MEMORY_USAGE_STATS */ | 5091 #endif /* MEMORY_USAGE_STATS */ |
5149 | |
5150 | 5092 |
5151 /************************************************************************/ | |
5152 /* Window configurations */ | |
5153 /************************************************************************/ | |
5154 | |
5155 /* #### This window configuration stuff has had serious bugs lurking in it | |
5156 for years; it would be a -huge- win if this was reimplemented in lisp. | |
5157 */ | |
5158 | |
5159 /* If you add anything to this structure make sure saved_window_equal | |
5160 knows about it. */ | |
5161 struct saved_window | |
5162 { | |
5163 Lisp_Object window; /* window */ | |
5164 Lisp_Object buffer; /* buffer */ | |
5165 Lisp_Object start; /* copied marker */ | |
5166 Lisp_Object pointm; /* copied marker */ | |
5167 Lisp_Object sb_point; /* copied marker */ | |
5168 Lisp_Object mark; /* copied marker */ | |
5169 int pixel_left; | |
5170 int pixel_top; | |
5171 int pixel_width; | |
5172 int pixel_height; | |
5173 int hscroll; | |
5174 Charcount modeline_hscroll; | |
5175 int parent_index; /* index into saved_windows */ | |
5176 int prev_index; /* index into saved_windows */ | |
5177 char start_at_line_beg; /* boolean */ | |
5178 | |
5179 #define WINDOW_SLOT_DECLARATION | |
5180 #define WINDOW_SLOT(slot) | |
5181 #define WINDOW_SAVED_SLOT(slot, compare) Lisp_Object slot; | |
5182 #include "winslots.h" | |
5183 }; | |
5184 | |
5185 /* If you add anything to this structure make sure window_config_equal | |
5186 knows about it. */ | |
5187 struct window_config | |
5188 { | |
5189 struct lcrecord_header header; | |
5190 /* int frame_width; No longer needed, JV | |
5191 int frame_height; */ | |
5192 #if 0 /* FSFmacs */ | |
5193 Lisp_Object selected_frame; | |
5194 #endif | |
5195 Lisp_Object current_window; | |
5196 Lisp_Object current_buffer; | |
5197 Lisp_Object minibuffer_scroll_window; | |
5198 Lisp_Object root_window; | |
5199 int minibuf_height; /* 0 = no minibuffer, <0, size in lines, >0 in pixels */ | |
5200 /* Record the values of window-min-width and window-min-height | |
5201 so that window sizes remain consistent with them. */ | |
5202 int min_width, min_height; | |
5203 int saved_windows_count; | |
5204 /* Zero-sized arrays aren't ANSI C */ | |
5205 struct saved_window saved_windows[1]; | |
5206 }; | |
5207 | |
5208 #define SAVED_WINDOW_N(conf, n) (&((conf)->saved_windows[(n)])) | |
5209 #define XWINDOW_CONFIGURATION(x) XRECORD (x, window_configuration, struct window_config) | |
5210 #define wrap_window_configuration(p) wrap_record (p, window_configuration) | |
5211 #define WINDOW_CONFIGURATIONP(x) RECORDP (x, window_configuration) | |
5212 #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration) | |
5213 | |
5214 #ifdef USE_KKCC | |
5215 static const struct struct_description saved_window_description = { | |
5216 }; | |
5217 | |
5218 static const struct lrecord_description window_config_description [] = { | |
5219 { XD_LISP_OBJECT, offsetof (struct window_config, current_window) }, | |
5220 { XD_LISP_OBJECT, offsetof (struct window_config, current_buffer) }, | |
5221 { XD_LISP_OBJECT, offsetof (struct window_config, minibuffer_scroll_window) }, | |
5222 { XD_LISP_OBJECT, offsetof (struct window_config, root_window) }, | |
5223 { XD_END } | |
5224 }; | |
5225 #endif /* USE_KKCC */ | |
5226 | |
5227 static Lisp_Object | |
5228 mark_window_config (Lisp_Object obj) | |
5229 { | |
5230 struct window_config *config = XWINDOW_CONFIGURATION (obj); | |
5231 int i; | |
5232 mark_object (config->current_window); | |
5233 mark_object (config->current_buffer); | |
5234 mark_object (config->minibuffer_scroll_window); | |
5235 mark_object (config->root_window); | |
5236 | |
5237 for (i = 0; i < config->saved_windows_count; i++) | |
5238 { | |
5239 struct saved_window *s = SAVED_WINDOW_N (config, i); | |
5240 mark_object (s->window); | |
5241 mark_object (s->buffer); | |
5242 mark_object (s->start); | |
5243 mark_object (s->pointm); | |
5244 mark_object (s->sb_point); | |
5245 mark_object (s->mark); | |
5246 #if 0 | |
5247 /* #### This looked like this. I do not see why specifier cached | |
5248 values should not be marked, as such specifiers as toolbars | |
5249 might have GC-able instances. Freed configs are not marked, | |
5250 aren't they? -- kkm */ | |
5251 mark_object (s->dedicated); | |
5252 #else | |
5253 #define WINDOW_SLOT(slot) | |
5254 #define WINDOW_SAVED_SLOT(slot, compare) mark_object (s->slot); | |
5255 #include "winslots.h" | |
5256 #endif | |
5257 } | |
5258 return Qnil; | |
5259 } | |
5260 | |
5261 inline static Bytecount | |
5262 sizeof_window_config_for_n_windows (int n) | |
5263 { | |
5264 return FLEXIBLE_ARRAY_STRUCT_SIZEOF (struct window_config, | |
5265 struct saved_window, saved_windows, n); | |
5266 } | |
5267 | |
5268 static Bytecount | |
5269 sizeof_window_config (const void *h) | |
5270 { | |
5271 const struct window_config *c = (const struct window_config *) h; | |
5272 return sizeof_window_config_for_n_windows (c->saved_windows_count); | |
5273 } | |
5274 | |
5275 static void | |
5276 print_window_config (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) | |
5277 { | |
5278 struct window_config *config = XWINDOW_CONFIGURATION (obj); | |
5279 if (print_readably) | |
5280 printing_unreadable_object ("#<window-configuration 0x%x>", | |
5281 config->header.uid); | |
5282 write_c_string (printcharfun, "#<window-configuration "); | |
5283 write_fmt_string (printcharfun, "0x%x>", config->header.uid); | |
5284 } | |
5285 | |
5286 #ifdef USE_KKCC | |
5287 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration", | |
5288 window_configuration, | |
5289 0, /*dumpable-flag*/ | |
5290 mark_window_config, | |
5291 print_window_config, | |
5292 0, 0, 0, | |
5293 0/*window_config_description*/, sizeof_window_config, | |
5294 struct window_config); | |
5295 #else /* not USE_KKCC */ | |
5296 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("window-configuration", | |
5297 window_configuration, | |
5298 mark_window_config, | |
5299 print_window_config, | |
5300 0, 0, 0, 0, sizeof_window_config, | |
5301 struct window_config); | |
5302 #endif /* not USE_KKCC */ | |
5303 | |
5304 /* Returns a boolean indicating whether the two saved windows are | |
5305 identical. */ | |
5306 static int | |
5307 saved_window_equal (struct saved_window *win1, struct saved_window *win2) | |
5308 { | |
5309 #define WINDOW_SLOT(slot) | |
5310 #define WINDOW_SAVED_SLOT(slot, compare) \ | |
5311 if (!compare (win1->slot, win2->slot)) \ | |
5312 return 0; | |
5313 #include "winslots.h" | |
5314 | |
5315 return | |
5316 EQ (win1->window, win2->window) && | |
5317 EQ (win1->buffer, win2->buffer) && | |
5318 internal_equal (win1->start, win2->start, 0) && | |
5319 internal_equal (win1->pointm, win2->pointm, 0) && | |
5320 internal_equal (win1->sb_point, win2->sb_point, 0) && | |
5321 internal_equal (win1->mark, win2->mark, 0) && | |
5322 win1->pixel_left == win2->pixel_left && | |
5323 win1->pixel_top == win2->pixel_top && | |
5324 win1->pixel_width == win2->pixel_width && | |
5325 win1->pixel_height == win2->pixel_height && | |
5326 win1->hscroll == win2->hscroll && | |
5327 win1->modeline_hscroll == win2->modeline_hscroll && | |
5328 win1->parent_index == win2->parent_index && | |
5329 win1->prev_index == win2->prev_index && | |
5330 win1->start_at_line_beg == win2->start_at_line_beg; | |
5331 } | |
5332 | |
5333 /* Returns a boolean indicating whether the two given configurations | |
5334 are identical. */ | |
5335 static int | |
5336 window_config_equal (Lisp_Object conf1, Lisp_Object conf2) | |
5337 { | |
5338 struct window_config *fig1, *fig2; | |
5339 int i; | |
5340 | |
5341 /* First check if they are truly the same. */ | |
5342 if (EQ (conf1, conf2)) | |
5343 return 1; | |
5344 | |
5345 fig1 = XWINDOW_CONFIGURATION (conf1); | |
5346 fig2 = XWINDOW_CONFIGURATION (conf2); | |
5347 | |
5348 if (!((fig1->saved_windows_count == fig2->saved_windows_count) && | |
5349 EQ (fig1->current_window, fig2->current_window) && | |
5350 EQ (fig1->current_buffer, fig2->current_buffer) && | |
5351 EQ (fig1->root_window, fig2->root_window) && | |
5352 EQ (fig1->minibuffer_scroll_window, fig2->minibuffer_scroll_window))) | |
5353 /* && | |
5354 fig1->frame_width == fig2->frame_width && | |
5355 fig1->frame_height == fig2->frame_height)) */ | |
5356 return 0; | |
5357 | |
5358 for (i = 0; i < fig1->saved_windows_count; i++) | |
5359 { | |
5360 if (!saved_window_equal (SAVED_WINDOW_N (fig1, i), | |
5361 SAVED_WINDOW_N (fig2, i))) | |
5362 return 0; | |
5363 } | |
5364 | |
5365 return 1; | |
5366 } | |
5367 | |
5368 DEFUN ("window-configuration-p", Fwindow_configuration_p, 1, 1, 0, /* | |
5369 Return t if OBJECT is a window-configuration object. | |
5370 */ | |
5371 (object)) | |
5372 { | |
5373 return WINDOW_CONFIGURATIONP (object) ? Qt : Qnil; | |
5374 } | |
5375 | |
5376 static int | |
5377 mark_windows_in_use_closure (struct window *w, void *closure) | |
5378 { | |
5379 int mark = *(int *)closure; | |
5380 w->config_mark = mark; | |
5381 return 0; | |
5382 } | |
5383 | |
5384 static void | |
5385 mark_windows_in_use (struct frame *f, int mark) | |
5386 { | |
5387 map_windows (f, mark_windows_in_use_closure, &mark); | |
5388 } | |
5389 | |
5390 /* Lisp_Object return value so it can be used in record_unwind_protect() */ | |
5391 static Lisp_Object | |
5392 free_window_configuration (Lisp_Object window_config) | |
5393 { | |
5394 int i; | |
5395 struct window_config *config = XWINDOW_CONFIGURATION (window_config); | |
5396 | |
5397 /* Free all the markers. It's not completely necessary that | |
5398 we do this (window configs sitting in a free list aren't | |
5399 marked normally so the markers wouldn't be marked anyway) | |
5400 but it's more efficient. */ | |
5401 for (i = 0; i < config->saved_windows_count; i++) | |
5402 { | |
5403 struct saved_window *p = SAVED_WINDOW_N (config, i); | |
5404 | |
5405 if (!NILP (p->pointm)) | |
5406 { | |
5407 free_marker (XMARKER (p->pointm)); | |
5408 p->pointm = Qnil; | |
5409 } | |
5410 if (!NILP (p->start)) | |
5411 { | |
5412 free_marker (XMARKER (p->start)); | |
5413 p->start = Qnil; | |
5414 } | |
5415 if (!NILP (p->sb_point)) | |
5416 { | |
5417 free_marker (XMARKER (p->sb_point)); | |
5418 p->sb_point = Qnil; | |
5419 } | |
5420 if (!NILP (p->mark)) | |
5421 { | |
5422 free_marker (XMARKER (p->mark)); | |
5423 p->mark = Qnil; | |
5424 } | |
5425 } | |
5426 | |
5427 if (config->saved_windows_count <= countof (Vwindow_configuration_free_list)) | |
5428 free_managed_lcrecord (Vwindow_configuration_free_list | |
5429 [config->saved_windows_count - 1], | |
5430 window_config); | |
5431 | |
5432 return Qnil; | |
5433 } | |
5434 | |
5435 DEFUN ("set-window-configuration", Fset_window_configuration, 1, 1, 0, /* | |
5436 Set the configuration of windows and buffers as specified by CONFIGURATION. | |
5437 CONFIGURATION must be a value previously returned | |
5438 by `current-window-configuration' (which see). | |
5439 */ | |
5440 (configuration)) | |
5441 { | |
5442 struct window *w; | |
5443 struct window_config *config; | |
5444 struct saved_window *p; | |
5445 Lisp_Object new_current_buffer; | |
5446 int k; | |
5447 Lisp_Object frame; | |
5448 struct frame *f; | |
5449 struct gcpro gcpro1; | |
5450 Lisp_Object old_window_config; | |
5451 /* int previous_frame_height; | |
5452 int previous_frame_width;*/ | |
5453 int previous_pixel_top; | |
5454 int previous_pixel_height; | |
5455 int previous_pixel_left; | |
5456 int previous_pixel_width; | |
5457 int previous_minibuf_height, previous_minibuf_top,previous_minibuf_width; | |
5458 int real_font_height; | |
5459 int converted_minibuf_height,target_minibuf_height; | |
5460 int specpdl_count = specpdl_depth (); | |
5461 | |
5462 GCPRO1 (configuration); | |
5463 | |
5464 CHECK_WINDOW_CONFIGURATION (configuration); | |
5465 config = XWINDOW_CONFIGURATION (configuration); | |
5466 | |
5467 frame = XWINDOW (SAVED_WINDOW_N (config, 0)->window)->frame; | |
5468 f = XFRAME (frame); | |
5469 | |
5470 /* Do not signal an error here if the frame was deleted. There are | |
5471 reasonable cases where we could get here with a deleted frame and | |
5472 just want to do close to nothing instead. */ | |
5473 | |
5474 if (FRAME_LIVE_P (f)) | |
5475 { | |
5476 /* restore the frame characteristics */ | |
5477 | |
5478 new_current_buffer = config->current_buffer; | |
5479 if (!BUFFER_LIVE_P (XBUFFER (new_current_buffer))) | |
5480 new_current_buffer = Qnil; | |
5481 | |
5482 /* | |
5483 * Assumed precondition: w->config_mark = 0 for all w | |
5484 * This procedure should ensure this is true by the time it exits | |
5485 * to ensure the precondition for future calls. | |
5486 * | |
5487 * We use w->config_mark to know whether we're modifying a | |
5488 * window that is currently visible on the frame (#### we | |
5489 * should just be able to check whether the window is dead | |
5490 * or not, but this way is safer?). As we process each | |
5491 * window, we set its config_mark to 0. At the end, we | |
5492 * go through all the windows that used to be on the frame, | |
5493 * set each one's config_mark to 0 (to maintain the | |
5494 * assumed precondition) and delete each one that's no | |
5495 * longer in use. | |
5496 * | |
5497 * #### Using a window-configuration to keep track of | |
5498 * the current windows is wasteful. All we need is the | |
5499 * list of windows, so we could just use a dynarr. | |
5500 */ | |
5501 old_window_config = Fcurrent_window_configuration (frame); | |
5502 | |
5503 /* If the new configuration is already equal to the old, then stop | |
5504 right here. This saves the work below and it also saves | |
5505 triggering a full redisplay of this window. This is a huge win | |
5506 when using the mouse since the mode motion code uses | |
5507 save-window-excursion extensively but will rarely cause the | |
5508 configuration to actually change. */ | |
5509 if (window_config_equal (configuration, old_window_config)) | |
5510 { | |
5511 free_window_configuration (old_window_config); | |
5512 UNGCPRO; | |
5513 return Qnil; | |
5514 } | |
5515 | |
5516 /* We can't quit or even check for quit because that may cause | |
5517 investigation of the frame state, which may crash if the frame is | |
5518 in an inconsistent state. */ | |
5519 begin_dont_check_for_quit (); | |
5520 record_unwind_protect (free_window_configuration, old_window_config); | |
5521 | |
5522 mark_windows_in_use (f, 1); | |
5523 #ifdef BROKEN_SUBWINDOW_REDISPLAY | |
5524 /* Force subwindows to be remapped. This is overkill but saves | |
5525 us having to rely on the redisplay code to unmap any extant | |
5526 subwindows. | |
5527 | |
5528 #### It does cause some extra flashing though which we could | |
5529 possibly avoid. So consider trying to get redisplay to work | |
5530 correctly. | |
5531 | |
5532 Removing the instances from the frame cache is wrong because | |
5533 an instance is only put in the frame cache when it is | |
5534 instantiated. So if we do this there is a chance that stuff | |
5535 will never get put back in the frame cache. */ | |
5536 reset_frame_subwindow_instance_cache (f); | |
5537 #endif | |
5538 #if 0 | |
5539 /* JV: This is bogus, | |
5540 First of all, the units are inconsistent. The frame sizes are measured | |
5541 in characters but the window sizes are stored in pixels. So if a | |
5542 font size change happened between saving and restoring, the | |
5543 frame "sizes" maybe equal but the windows still should be | |
5544 resized. This is tickled a lot by the new "character size | |
5545 stays constant" policy in 21.0. It leads to very weird | |
5546 glitches (and possibly crashes when asserts are tickled). | |
5547 | |
5548 Just changing the units doesn't help because changing the | |
5549 toolbar configuration can also change the pixel positions. | |
5550 Luckily there is a much simpler way of doing this, see below. | |
5551 */ | |
5552 previous_frame_width = FRAME_WIDTH (f); | |
5553 previous_frame_height = FRAME_HEIGHT (f); | |
5554 /* If the frame has been resized since this window configuration was | |
5555 made, we change the frame to the size specified in the | |
5556 configuration, restore the configuration, and then resize it | |
5557 back. We keep track of the prevailing height in these variables. */ | |
5558 if (config->frame_height != FRAME_HEIGHT (f) | |
5559 || config->frame_width != FRAME_WIDTH (f)) | |
5560 change_frame_size (f, config->frame_height, config->frame_width, 0); | |
5561 #endif | |
5562 | |
5563 previous_pixel_top = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top; | |
5564 previous_pixel_height = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_height; | |
5565 previous_pixel_left = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left; | |
5566 previous_pixel_width = XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_width; | |
5567 | |
5568 /* remember some properties of the minibuffer */ | |
5569 | |
5570 default_face_height_and_width (frame, &real_font_height, 0); | |
5571 assert(real_font_height > 0); | |
5572 | |
5573 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f)) | |
5574 { | |
5575 previous_minibuf_height | |
5576 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height; | |
5577 previous_minibuf_top | |
5578 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_top; | |
5579 previous_minibuf_width | |
5580 = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_width; | |
5581 } | |
5582 else | |
5583 { | |
5584 previous_minibuf_height = 0; | |
5585 previous_minibuf_top = 0; | |
5586 previous_minibuf_width = 0; | |
5587 } | |
5588 converted_minibuf_height = | |
5589 (previous_minibuf_height % real_font_height) == 0 ? | |
5590 - (previous_minibuf_height / real_font_height ) : /* lines */ | |
5591 previous_minibuf_height; /* pixels */ | |
5592 | |
5593 /* Temporarily avoid any problems with windows that are smaller | |
5594 than they are supposed to be. */ | |
5595 window_min_height = 1; | |
5596 window_min_width = 1; | |
5597 | |
5598 /* OK, now restore all the windows in the window config. | |
5599 This may involve "undeleting" windows, since the | |
5600 windows in the window config may be deleted. | |
5601 */ | |
5602 for (k = 0; k < config->saved_windows_count; k++) | |
5603 { | |
5604 p = SAVED_WINDOW_N (config, k); | |
5605 w = XWINDOW (p->window); | |
5606 w->next = Qnil; | |
5607 | |
5608 /* The window might be dead. In this case, its redisplay | |
5609 structures were freed, so we need to reallocate them. */ | |
5610 if (!w->face_cachels) | |
5611 { | |
5612 w->face_cachels = Dynarr_new (face_cachel); | |
5613 reset_face_cachels (w); | |
5614 } | |
5615 if (!w->glyph_cachels) | |
5616 w->glyph_cachels = Dynarr_new (glyph_cachel); | |
5617 if (!w->line_start_cache) | |
5618 w->line_start_cache = Dynarr_new (line_start_cache); | |
5619 w->gutter_extent_modiff[0] = 0; | |
5620 w->gutter_extent_modiff[1] = 0; | |
5621 w->gutter_extent_modiff[2] = 0; | |
5622 w->gutter_extent_modiff[3] = 0; | |
5623 w->dead = 0; | |
5624 | |
5625 note_object_created (p->window); | |
5626 | |
5627 if (p->parent_index >= 0) | |
5628 w->parent = SAVED_WINDOW_N (config, p->parent_index)->window; | |
5629 else | |
5630 w->parent = Qnil; | |
5631 | |
5632 if (p->prev_index >= 0) | |
5633 { | |
5634 w->prev = SAVED_WINDOW_N (config, p->prev_index)->window; | |
5635 | |
5636 /* This is true for a minibuffer-only frame. */ | |
5637 if (!NILP (w->mini_p) && EQ (w->prev, p->window)) | |
5638 w->next = Qnil; | |
5639 else | |
5640 XWINDOW (w->prev)->next = p->window; | |
5641 } | |
5642 else | |
5643 { | |
5644 w->prev = Qnil; | |
5645 if (!NILP (w->parent)) | |
5646 { | |
5647 if (WINDOW_WIDTH (p) == WINDOW_WIDTH (XWINDOW (w->parent))) | |
5648 { | |
5649 XWINDOW (w->parent)->vchild = p->window; | |
5650 XWINDOW (w->parent)->hchild = Qnil; | |
5651 } | |
5652 else | |
5653 { | |
5654 XWINDOW (w->parent)->hchild = p->window; | |
5655 XWINDOW (w->parent)->vchild = Qnil; | |
5656 } | |
5657 } | |
5658 } | |
5659 if (!w->config_mark) | |
5660 { | |
5661 /* #### This should be equivalent to the window previously | |
5662 having been dead. If we're brave, we'll put in an | |
5663 assertion to this effect. */ | |
5664 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); | |
5665 } | |
5666 else /* if (!EQ (w->buffer, p->buffer)) */ | |
5667 { | |
5668 /* With the new redisplay we let it know that a change has | |
5669 been made and it will take care of the rest. If we don't | |
5670 tell it something has possibly changed it could lead to | |
5671 incorrect display. */ | |
5672 MARK_WINDOWS_CHANGED (w); | |
5673 } | |
5674 | |
5675 WINDOW_LEFT (w) = WINDOW_LEFT (p); | |
5676 WINDOW_TOP (w) = WINDOW_TOP (p); | |
5677 WINDOW_WIDTH (w) = WINDOW_WIDTH (p); | |
5678 WINDOW_HEIGHT (w) = WINDOW_HEIGHT (p); | |
5679 w->hscroll = p->hscroll; | |
5680 w->modeline_hscroll = p->modeline_hscroll; | |
5681 w->line_cache_last_updated = Qzero; | |
5682 /* When we restore a window's configuration, the identity of | |
5683 the window hasn't actually changed - so there is no | |
5684 reason why we shouldn't preserve the instance cache for | |
5685 it - unless it was originally deleted. This will often | |
5686 buy us something as we will not have to re-instantiate | |
5687 all the instances. This is because this is an instance | |
5688 cache - not a display cache. Preserving the display cache | |
5689 would definitely be wrong. | |
5690 | |
5691 We specifically want to do this for tabs, since for some | |
5692 reason finding a file will cause the configuration to be | |
5693 set. */ | |
5694 if (NILP (w->subwindow_instance_cache)) | |
5695 w->subwindow_instance_cache = | |
5696 make_image_instance_cache_hash_table (); | |
5697 | |
5698 SET_LAST_MODIFIED (w, 1); | |
5699 SET_LAST_FACECHANGE (w); | |
5700 w->config_mark = 0; | |
5701 | |
5702 /* #### Consider making the instance cache a WINDOW_SAVED_SLOT. */ | |
5703 #define WINDOW_SLOT(slot) | |
5704 #define WINDOW_SAVED_SLOT(slot, compare) w->slot = p->slot; | |
5705 #include "winslots.h" | |
5706 | |
5707 /* Reinstall the saved buffer and pointers into it. */ | |
5708 if (NILP (p->buffer)) | |
5709 w->buffer = p->buffer; | |
5710 else | |
5711 { | |
5712 if (BUFFER_LIVE_P (XBUFFER (p->buffer))) | |
5713 /* If saved buffer is alive, install it. */ | |
5714 { | |
5715 w->buffer = p->buffer; | |
5716 w->start_at_line_beg = p->start_at_line_beg; | |
5717 set_marker_restricted (w->start[CURRENT_DISP], | |
5718 Fmarker_position (p->start), | |
5719 w->buffer); | |
5720 set_marker_restricted (w->pointm[CURRENT_DISP], | |
5721 Fmarker_position (p->pointm), | |
5722 w->buffer); | |
5723 set_marker_restricted (w->sb_point, | |
5724 Fmarker_position (p->sb_point), | |
5725 w->buffer); | |
5726 Fset_marker (XBUFFER (w->buffer)->mark, | |
5727 Fmarker_position (p->mark), w->buffer); | |
5728 | |
5729 /* As documented in Fcurrent_window_configuration, don't | |
5730 save the location of point in the buffer which was current | |
5731 when the window configuration was recorded. */ | |
5732 if (!EQ (p->buffer, new_current_buffer) && | |
5733 XBUFFER (p->buffer) == current_buffer) | |
5734 Fgoto_char (w->pointm[CURRENT_DISP], Qnil); | |
5735 } | |
5736 else if (NILP (w->buffer) || | |
5737 !BUFFER_LIVE_P (XBUFFER (w->buffer))) | |
5738 /* Else if window's old buffer is dead too, get a live one. */ | |
5739 { | |
5740 /* #### The following line makes me nervous... */ | |
5741 /* w->buffer = Fcdr (Fcar (XFRAME (w->frame)->buffer_alist));*/ | |
5742 w->buffer = Fget_buffer_create (QSscratch); | |
5743 /* w->buffer = Fother_buffer (Qnil, w->frame, Qnil); */ | |
5744 /* This will set the markers to beginning of visible | |
5745 range. */ | |
5746 set_marker_restricted (w->start[CURRENT_DISP], Qzero, w->buffer); | |
5747 set_marker_restricted (w->pointm[CURRENT_DISP], Qzero, | |
5748 w->buffer); | |
5749 set_marker_restricted (w->sb_point, Qzero, w->buffer); | |
5750 w->start_at_line_beg = 1; | |
5751 } | |
5752 else | |
5753 /* Keeping window's old buffer; make sure the markers | |
5754 are real. */ | |
5755 { | |
5756 /* Set window markers at start of visible range. */ | |
5757 if (XMARKER (w->start[CURRENT_DISP])->buffer == 0) | |
5758 set_marker_restricted (w->start[CURRENT_DISP], Qzero, | |
5759 w->buffer); | |
5760 if (XMARKER (w->sb_point)->buffer == 0) | |
5761 set_marker_restricted (w->sb_point, Qzero, w->buffer); | |
5762 if (XMARKER (w->pointm[CURRENT_DISP])->buffer == 0) | |
5763 set_marker_restricted (w->pointm[CURRENT_DISP], | |
5764 make_int | |
5765 (BUF_PT (XBUFFER (w->buffer))), | |
5766 w->buffer); | |
5767 w->start_at_line_beg = 1; | |
5768 } | |
5769 } | |
5770 } | |
5771 | |
5772 FRAME_ROOT_WINDOW (f) = config->root_window; | |
5773 /* Note that FSFmacs unilaterally calls Fselect_window() here, and | |
5774 then calls do_switch_frame() below to select the frame that was | |
5775 recorded in the window config as being selected. | |
5776 | |
5777 Instead, we don't ever change the selected frame, and either | |
5778 call Fselect_window() below if the window config's frame is | |
5779 currently selected, or just set the selected window of the | |
5780 window config's frame. */ | |
5781 | |
5782 #if 0 | |
5783 /* Set the frame height to the value it had before this function. */ | |
5784 if (previous_frame_height != FRAME_HEIGHT (f) | |
5785 || previous_frame_width != FRAME_WIDTH (f)) | |
5786 change_frame_size (f, previous_frame_height, previous_frame_width, 0); | |
5787 #endif | |
5788 /* We just reset the size and position of the minibuffer, to its old | |
5789 value, which needn't be valid. So we do some magic to see which value | |
5790 to actually take. Then we set it. | |
5791 | |
5792 The magic: | |
5793 We take the old value if is in the same units but differs from the | |
5794 current value. | |
5795 | |
5796 #### Now we get more cases correct then ever before, but | |
5797 are we treating all? For instance what if the frames minibuf window | |
5798 is no longer the same one? | |
5799 */ | |
5800 target_minibuf_height = previous_minibuf_height; | |
5801 if (converted_minibuf_height && | |
5802 (converted_minibuf_height * config->minibuf_height) > 0 && | |
5803 (converted_minibuf_height != config->minibuf_height)) | |
5804 { | |
5805 target_minibuf_height = config->minibuf_height < 0 ? | |
5806 - (config->minibuf_height * real_font_height) : | |
5807 config->minibuf_height; | |
5808 target_minibuf_height = | |
5809 max(target_minibuf_height,real_font_height); | |
5810 } | |
5811 if (previous_minibuf_height) | |
5812 { | |
5813 XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top | |
5814 = previous_minibuf_top - | |
5815 (target_minibuf_height - previous_minibuf_height); | |
5816 set_window_pixheight (FRAME_MINIBUF_WINDOW (f), | |
5817 target_minibuf_height, 0); | |
5818 set_window_pixwidth (FRAME_MINIBUF_WINDOW (f), | |
5819 previous_minibuf_width, 0); | |
5820 } | |
5821 | |
5822 /* This is a better way to deal with frame resizing, etc. | |
5823 What we _actually_ want is for the old (just restored) | |
5824 root window to fit | |
5825 into the place of the new one. So we just do that. Simple! */ | |
5826 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top = previous_pixel_top; | |
5827 /* Note that this function also updates the subwindow | |
5828 "pixel_top"s */ | |
5829 set_window_pixheight (FRAME_ROOT_WINDOW (f), | |
5830 previous_pixel_height - | |
5831 (target_minibuf_height - previous_minibuf_height), 0); | |
5832 XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left = previous_pixel_left; | |
5833 /* Note that this function also updates the subwindow | |
5834 "pixel_left"s */ | |
5835 set_window_pixwidth (FRAME_ROOT_WINDOW (f), previous_pixel_width, 0); | |
5836 | |
5837 /* If restoring in the current frame make the window current, | |
5838 otherwise just update the frame selected_window slot to be | |
5839 the restored current_window. */ | |
5840 if (f == selected_frame ()) | |
5841 { | |
5842 #if 0 | |
5843 /* When using `pop-window-configuration', often the minibuffer | |
5844 ends up as the selected window even though it's not active ... | |
5845 I really don't know the cause of this, but it should never | |
5846 happen. This kludge should fix it. | |
5847 | |
5848 #### Find out why this is really going wrong. */ | |
5849 if (!minibuf_level && | |
5850 MINI_WINDOW_P (XWINDOW (config->current_window))) | |
5851 window_to_select = Fnext_window (config->current_window, | |
5852 Qnil, Qnil, Qnil); | |
5853 else | |
5854 window_to_select = config->current_window; | |
5855 #endif | |
5856 /* Do this last so that buffer stacking is calculated | |
5857 correctly. */ | |
5858 Fselect_window (config->current_window, Qnil); | |
5859 | |
5860 if (!NILP (new_current_buffer)) | |
5861 { | |
5862 Fset_buffer (new_current_buffer); | |
5863 Frecord_buffer (new_current_buffer); | |
5864 } | |
5865 else | |
5866 { | |
5867 Fset_buffer (XWINDOW (config->current_window)->buffer); | |
5868 Frecord_buffer (XWINDOW (config->current_window)->buffer); | |
5869 } | |
5870 } | |
5871 else | |
5872 set_frame_selected_window (f, config->current_window); | |
5873 } | |
5874 else | |
5875 old_window_config = Qnil; /* Warning suppression */ | |
5876 | |
5877 /* Restore the minimum heights recorded in the configuration. */ | |
5878 window_min_height = config->min_height; | |
5879 window_min_width = config->min_width; | |
5880 | |
5881 #if 0 /* FSFmacs */ | |
5882 /* see above comment */ | |
5883 /* Fselect_window will have made f the selected frame, so we | |
5884 reselect the proper frame here. Fhandle_switch_frame will change the | |
5885 selected window too, but that doesn't make the call to | |
5886 Fselect_window above totally superfluous; it still sets f's | |
5887 selected window. */ | |
5888 if (FRAME_LIVE_P (XFRAME (config->selected_frame))) | |
5889 do_switch_frame (config->selected_frame, Qnil, 0); | |
5890 #endif | |
5891 | |
5892 Vminibuffer_scroll_window = config->minibuffer_scroll_window; | |
5893 | |
5894 if (FRAME_LIVE_P (f)) | |
5895 { | |
5896 /* Do this before calling recompute_all_cached_specifiers_in_window() | |
5897 so that things like redisplay_redraw_cursor() won't abort due | |
5898 to no window mirror present. */ | |
5899 f->mirror_dirty = 1; | |
5900 | |
5901 config = XWINDOW_CONFIGURATION (old_window_config); | |
5902 for (k = 0; k < config->saved_windows_count; k++) | |
5903 { | |
5904 p = SAVED_WINDOW_N (config, k); | |
5905 w = XWINDOW (p->window); | |
5906 /* Remember, we set w->config_mark on all currently visible | |
5907 windows, and reset it on all newly visible windows. | |
5908 Any windows still marked need to be deleted. */ | |
5909 if (w->config_mark) | |
5910 { | |
5911 mark_window_as_deleted (w); | |
5912 w->config_mark = 0; | |
5913 } | |
5914 else | |
5915 { | |
5916 /* We just potentially changed the window's buffer and | |
5917 potentially turned a dead window into a live one, | |
5918 so we need to recompute the cached specifier values. */ | |
5919 recompute_all_cached_specifiers_in_window (w); | |
5920 } | |
5921 } | |
5922 } | |
5923 | |
5924 /* Now restore things, when everything else if OK. */ | |
5925 | |
5926 unbind_to (specpdl_count); | |
5927 | |
5928 UNGCPRO; | |
5929 | |
5930 return Qnil; | |
5931 } | |
5932 | |
5933 /* Mark all subwindows of a window as deleted. The argument | 5093 /* Mark all subwindows of a window as deleted. The argument |
5934 W is actually the subwindow tree of the window in question. */ | 5094 W is actually the subwindow tree of the window in question. */ |
5935 | 5095 |
5936 void | 5096 void |
5937 delete_all_subwindows (struct window *w) | 5097 delete_all_subwindows (struct window *w) |
5941 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild)); | 5101 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild)); |
5942 | 5102 |
5943 mark_window_as_deleted (w); | 5103 mark_window_as_deleted (w); |
5944 } | 5104 } |
5945 | 5105 |
5946 | |
5947 static int | |
5948 count_windows (struct window *window) | |
5949 { | |
5950 return 1 + | |
5951 (!NILP (window->next) ? count_windows (XWINDOW (window->next)) : 0) + | |
5952 (!NILP (window->vchild) ? count_windows (XWINDOW (window->vchild)) : 0) + | |
5953 (!NILP (window->hchild) ? count_windows (XWINDOW (window->hchild)) : 0); | |
5954 } | |
5955 | |
5956 static int | |
5957 saved_window_index (Lisp_Object window, struct window_config *config, int lim) | |
5958 { | |
5959 int j; | |
5960 for (j = 0; j < lim; j++) | |
5961 { | |
5962 if (EQ (SAVED_WINDOW_N (config, j)->window, window)) | |
5963 return j; | |
5964 } | |
5965 abort (); | |
5966 return 0; /* suppress compiler warning */ | |
5967 } | |
5968 | |
5969 static int | |
5970 save_window_save (Lisp_Object window, struct window_config *config, int i) | |
5971 { | |
5972 struct window *w; | |
5973 | |
5974 for (; !NILP (window); window = w->next) | |
5975 { | |
5976 struct saved_window *p = SAVED_WINDOW_N (config, i); | |
5977 | |
5978 w = XWINDOW (window); | |
5979 i++; | |
5980 p->window = window; | |
5981 p->buffer = w->buffer; | |
5982 WINDOW_LEFT (p) = WINDOW_LEFT (w); | |
5983 WINDOW_TOP (p) = WINDOW_TOP (w); | |
5984 WINDOW_WIDTH (p) = WINDOW_WIDTH (w); | |
5985 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (w); | |
5986 p->hscroll = w->hscroll; | |
5987 p->modeline_hscroll = w->modeline_hscroll; | |
5988 | |
5989 #define WINDOW_SLOT(slot) | |
5990 #define WINDOW_SAVED_SLOT(slot, compare) p->slot = w->slot; | |
5991 #include "winslots.h" | |
5992 | |
5993 if (!NILP (w->buffer)) | |
5994 { | |
5995 /* Save w's value of point in the window configuration. | |
5996 If w is the selected window, then get the value of point | |
5997 from the buffer; pointm is garbage in the selected window. */ | |
5998 if (EQ (window, Fselected_window (Qnil))) | |
5999 { | |
6000 p->pointm = noseeum_make_marker (); | |
6001 Fset_marker (p->pointm, | |
6002 make_int (BUF_PT (XBUFFER (w->buffer))), | |
6003 w->buffer); | |
6004 } | |
6005 else | |
6006 p->pointm = noseeum_copy_marker (w->pointm[CURRENT_DISP], Qnil); | |
6007 | |
6008 p->start = noseeum_copy_marker (w->start[CURRENT_DISP], Qnil); | |
6009 p->sb_point = noseeum_copy_marker (w->sb_point, Qnil); | |
6010 p->start_at_line_beg = w->start_at_line_beg; | |
6011 | |
6012 p->mark = noseeum_copy_marker (XBUFFER (w->buffer)->mark, Qnil); | |
6013 } | |
6014 else | |
6015 { | |
6016 p->pointm = Qnil; | |
6017 p->start = Qnil; | |
6018 p->sb_point = Qnil; | |
6019 p->mark = Qnil; | |
6020 p->start_at_line_beg = 0; | |
6021 } | |
6022 | |
6023 if (NILP (w->parent)) | |
6024 p->parent_index = -1; | |
6025 else | |
6026 p->parent_index = saved_window_index (w->parent, config, i); | |
6027 if (NILP (w->prev)) | |
6028 p->prev_index = -1; | |
6029 else | |
6030 p->prev_index = saved_window_index (w->prev, config, i); | |
6031 if (!NILP (w->vchild)) | |
6032 i = save_window_save (w->vchild, config, i); | |
6033 if (!NILP (w->hchild)) | |
6034 i = save_window_save (w->hchild, config, i); | |
6035 } | |
6036 | |
6037 return i; | |
6038 } | |
6039 | |
6040 #if 0 /* FSFmacs */ | |
6041 /* Added to doc string: | |
6042 | |
6043 This also records the currently selected frame, and FRAME's focus | |
6044 redirection (see `redirect-frame-focus'). | |
6045 | |
6046 */ | |
6047 #endif | |
6048 | |
6049 DEFUN ("current-window-configuration", Fcurrent_window_configuration, 0, 1, 0, /* | |
6050 Return an object representing the current window configuration of FRAME. | |
6051 If FRAME is nil or omitted, use the selected frame. | |
6052 This describes the number of windows, their sizes and current buffers, | |
6053 and for each window on FRAME the displayed buffer, where display | |
6054 starts, and the positions of point and mark. | |
6055 An exception is made for point in the current buffer: | |
6056 its value is -not- saved. | |
6057 */ | |
6058 (frame)) | |
6059 { | |
6060 Lisp_Object result; | |
6061 struct frame *f = decode_frame (frame); | |
6062 struct window_config *config; | |
6063 int n_windows = count_windows (XWINDOW (FRAME_ROOT_WINDOW (f))); | |
6064 int minibuf_height; | |
6065 int real_font_height; | |
6066 | |
6067 if (n_windows <= countof (Vwindow_configuration_free_list)) | |
6068 config = XWINDOW_CONFIGURATION (allocate_managed_lcrecord | |
6069 (Vwindow_configuration_free_list | |
6070 [n_windows - 1])); | |
6071 else | |
6072 /* More than ten windows; just allocate directly */ | |
6073 config = (struct window_config *) | |
6074 alloc_lcrecord (sizeof_window_config_for_n_windows (n_windows), | |
6075 &lrecord_window_configuration); | |
6076 result = wrap_window_configuration (config); | |
6077 /* | |
6078 config->frame_width = FRAME_WIDTH (f); | |
6079 config->frame_height = FRAME_HEIGHT (f); */ | |
6080 /* #### When using `push-window-configuration', often the minibuffer ends | |
6081 up as the selected window because functions run as the result of | |
6082 user interaction e.g. hyper-apropos. It seems to me the sensible | |
6083 thing to do is not record the minibuffer here. | |
6084 | |
6085 #### Unfortunately this is a change to previous behaviour, however logical | |
6086 it may be, so revert for the moment. */ | |
6087 #if 0 | |
6088 if (FRAME_MINIBUF_ONLY_P (f) || minibuf_level) | |
6089 config->current_window = FRAME_SELECTED_WINDOW (f); | |
6090 else | |
6091 config->current_window = FRAME_LAST_NONMINIBUF_WINDOW (f); | |
6092 #endif | |
6093 config->current_window = FRAME_SELECTED_WINDOW (f); | |
6094 config->current_buffer = wrap_buffer (current_buffer); | |
6095 config->minibuffer_scroll_window = Vminibuffer_scroll_window; | |
6096 config->root_window = FRAME_ROOT_WINDOW (f); | |
6097 config->min_height = window_min_height; | |
6098 config->min_width = window_min_width; | |
6099 config->saved_windows_count = n_windows; | |
6100 save_window_save (FRAME_ROOT_WINDOW (f), config, 0); | |
6101 | |
6102 /* save the minibuffer height using the heuristics from | |
6103 change_frame_size_1 */ | |
6104 | |
6105 frame = wrap_frame (f); /* frame could have been nil ! */ | |
6106 default_face_height_and_width (frame, &real_font_height, 0); | |
6107 assert(real_font_height > 0); | |
6108 | |
6109 if (FRAME_HAS_MINIBUF_P (f) && ! FRAME_MINIBUF_ONLY_P (f)) | |
6110 minibuf_height = XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height; | |
6111 else | |
6112 minibuf_height = 0; | |
6113 config->minibuf_height = (minibuf_height % real_font_height) == 0 ? | |
6114 - (minibuf_height / real_font_height ) : /* lines */ | |
6115 minibuf_height; /* pixels */ | |
6116 | |
6117 return result; | |
6118 } | |
6119 | |
6120 Lisp_Object | 5106 Lisp_Object |
6121 save_window_excursion_unwind (Lisp_Object window_config) | 5107 save_window_excursion_unwind (Lisp_Object window_config) |
6122 { | 5108 { |
6123 Lisp_Object val = Fset_window_configuration (window_config); | 5109 Lisp_Object val = call1 (Qset_window_configuration, window_config); |
6124 free_window_configuration (window_config); | |
6125 return val; | 5110 return val; |
6126 } | 5111 } |
6127 | 5112 |
6128 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /* | 5113 DEFUN ("save-window-excursion", Fsave_window_excursion, 0, UNEVALLED, 0, /* |
6129 Execute body, preserving window sizes and contents. | 5114 Execute body, preserving window sizes and contents. |
6135 { | 5120 { |
6136 /* This function can GC */ | 5121 /* This function can GC */ |
6137 int speccount = specpdl_depth (); | 5122 int speccount = specpdl_depth (); |
6138 | 5123 |
6139 record_unwind_protect (save_window_excursion_unwind, | 5124 record_unwind_protect (save_window_excursion_unwind, |
6140 Fcurrent_window_configuration (Qnil)); | 5125 call1 (Qcurrent_window_configuration, Qnil)); |
6141 return unbind_to_1 (speccount, Fprogn (args)); | 5126 return unbind_to_1 (speccount, Fprogn (args)); |
6142 } | 5127 } |
6143 | 5128 |
6144 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /* | 5129 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /* |
6145 Return the horizontal pixel position of POS in window. | 5130 Return the horizontal pixel position of POS in window. |
6146 Beginning of line is column 0. This is calculated using the redisplay | 5131 Beginning of line is column 0. This is calculated using the redisplay |
6147 display tables. If WINDOW is nil, the current window is assumed. | 5132 display tables. If WINDOW is nil, the current window is assumed. |
6148 If POS is nil, point is assumed. Note that POS must be visible for | 5133 If POS is nil, point is assumed. Note that POS must be visible for |
6261 | 5246 |
6262 void | 5247 void |
6263 syms_of_window (void) | 5248 syms_of_window (void) |
6264 { | 5249 { |
6265 INIT_LRECORD_IMPLEMENTATION (window); | 5250 INIT_LRECORD_IMPLEMENTATION (window); |
6266 INIT_LRECORD_IMPLEMENTATION (window_configuration); | |
6267 INIT_LRECORD_IMPLEMENTATION (window_mirror); | 5251 INIT_LRECORD_IMPLEMENTATION (window_mirror); |
6268 | 5252 |
6269 DEFSYMBOL (Qwindowp); | 5253 DEFSYMBOL (Qwindowp); |
6270 DEFSYMBOL (Qwindow_live_p); | 5254 DEFSYMBOL (Qwindow_live_p); |
6271 DEFSYMBOL_MULTIWORD_PREDICATE (Qwindow_configurationp); | |
6272 DEFSYMBOL (Qtemp_buffer_show_hook); | |
6273 DEFSYMBOL (Qdisplay_buffer); | 5255 DEFSYMBOL (Qdisplay_buffer); |
6274 | 5256 |
6275 #ifdef MEMORY_USAGE_STATS | 5257 #ifdef MEMORY_USAGE_STATS |
6276 DEFSYMBOL (Qface_cache); | 5258 DEFSYMBOL (Qface_cache); |
6277 DEFSYMBOL (Qglyph_cache); | 5259 DEFSYMBOL (Qglyph_cache); |
6282 DEFSYMBOL (Qother_redisplay); | 5264 DEFSYMBOL (Qother_redisplay); |
6283 /* Qother in general.c */ | 5265 /* Qother in general.c */ |
6284 #endif | 5266 #endif |
6285 | 5267 |
6286 DEFSYMBOL (Qtruncate_partial_width_windows); | 5268 DEFSYMBOL (Qtruncate_partial_width_windows); |
5269 DEFSYMBOL (Qcurrent_window_configuration); | |
5270 DEFSYMBOL (Qset_window_configuration); | |
6287 | 5271 |
6288 DEFSUBR (Fselected_window); | 5272 DEFSUBR (Fselected_window); |
6289 DEFSUBR (Flast_nonminibuf_window); | 5273 DEFSUBR (Flast_nonminibuf_window); |
6290 DEFSUBR (Fminibuffer_window); | 5274 DEFSUBR (Fminibuffer_window); |
6291 DEFSUBR (Fwindow_minibuffer_p); | 5275 DEFSUBR (Fwindow_minibuffer_p); |
6361 DEFSUBR (Fcenter_to_window_line); | 5345 DEFSUBR (Fcenter_to_window_line); |
6362 DEFSUBR (Fmove_to_window_line); | 5346 DEFSUBR (Fmove_to_window_line); |
6363 #ifdef MEMORY_USAGE_STATS | 5347 #ifdef MEMORY_USAGE_STATS |
6364 DEFSUBR (Fwindow_memory_usage); | 5348 DEFSUBR (Fwindow_memory_usage); |
6365 #endif | 5349 #endif |
6366 DEFSUBR (Fwindow_configuration_p); | |
6367 DEFSUBR (Fset_window_configuration); | |
6368 DEFSUBR (Fcurrent_window_configuration); | |
6369 DEFSUBR (Fsave_window_excursion); | 5350 DEFSUBR (Fsave_window_excursion); |
6370 DEFSUBR (Fcurrent_pixel_column); | 5351 DEFSUBR (Fcurrent_pixel_column); |
6371 } | 5352 } |
6372 | 5353 |
6373 void | 5354 void |
6374 reinit_vars_of_window (void) | 5355 reinit_vars_of_window (void) |
6375 { | 5356 { |
6376 int i; | |
6377 /* Make sure all windows get marked */ | 5357 /* Make sure all windows get marked */ |
6378 minibuf_window = Qnil; | 5358 minibuf_window = Qnil; |
6379 staticpro_nodump (&minibuf_window); | 5359 staticpro_nodump (&minibuf_window); |
6380 | |
6381 for (i = 0; i < countof (Vwindow_configuration_free_list); i++) | |
6382 { | |
6383 Vwindow_configuration_free_list[i] = | |
6384 make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1), | |
6385 &lrecord_window_configuration); | |
6386 staticpro_nodump (&Vwindow_configuration_free_list[i]); | |
6387 } | |
6388 } | 5360 } |
6389 | 5361 |
6390 void | 5362 void |
6391 vars_of_window (void) | 5363 vars_of_window (void) |
6392 { | 5364 { |
6394 | 5366 |
6395 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /* | 5367 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /* |
6396 *Non-nil means to scroll if point lands on a line which is clipped. | 5368 *Non-nil means to scroll if point lands on a line which is clipped. |
6397 */ ); | 5369 */ ); |
6398 scroll_on_clipped_lines = 1; | 5370 scroll_on_clipped_lines = 1; |
6399 | |
6400 DEFVAR_LISP ("temp-buffer-show-hook", &Vtemp_buffer_show_hook /* | |
6401 See `temp-buffer-show-function'. | |
6402 */ ); | |
6403 Vtemp_buffer_show_hook = Qnil; | |
6404 | 5371 |
6405 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /* | 5372 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /* |
6406 Non-nil means call as function to display a help buffer. | 5373 Non-nil means call as function to display a help buffer. |
6407 The function is called with one argument, the buffer to be displayed. | 5374 The function is called with one argument, the buffer to be displayed. |
6408 Used by `with-output-to-temp-buffer'. | 5375 Used by `with-output-to-temp-buffer'. |