Mercurial > hg > xemacs-beta
annotate src/window.c @ 5146:88bd4f3ef8e4
make lrecord UID's have a separate UID space for each object, resurrect debug SOE code in extents.c
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-03-15 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (c_readonly):
* alloc.c (deadbeef_memory):
* alloc.c (make_compiled_function):
* alloc.c (make_button_data):
* alloc.c (make_motion_data):
* alloc.c (make_process_data):
* alloc.c (make_timeout_data):
* alloc.c (make_magic_data):
* alloc.c (make_magic_eval_data):
* alloc.c (make_eval_data):
* alloc.c (make_misc_user_data):
* alloc.c (noseeum_make_marker):
* alloc.c (ADDITIONAL_FREE_string):
* alloc.c (common_init_alloc_early):
* alloc.c (init_alloc_once_early):
* bytecode.c (print_compiled_function):
* bytecode.c (mark_compiled_function):
* casetab.c:
* casetab.c (print_case_table):
* console.c:
* console.c (print_console):
* database.c (print_database):
* database.c (finalize_database):
* device-msw.c (sync_printer_with_devmode):
* device-msw.c (print_devmode):
* device-msw.c (finalize_devmode):
* device.c:
* device.c (print_device):
* elhash.c:
* elhash.c (print_hash_table):
* eval.c (print_multiple_value):
* eval.c (mark_multiple_value):
* events.c (deinitialize_event):
* events.c (print_event):
* events.c (event_equal):
* extents.c:
* extents.c (soe_dump):
* extents.c (soe_insert):
* extents.c (soe_delete):
* extents.c (soe_move):
* extents.c (extent_fragment_update):
* extents.c (print_extent_1):
* extents.c (print_extent):
* extents.c (vars_of_extents):
* frame.c:
* frame.c (print_frame):
* free-hook.c:
* free-hook.c (check_free):
* glyphs.c:
* glyphs.c (print_image_instance):
* glyphs.c (print_glyph):
* gui.c:
* gui.c (copy_gui_item):
* hash.c:
* hash.c (NULL_ENTRY):
* hash.c (KEYS_DIFFER_P):
* keymap.c (print_keymap):
* keymap.c (MARKED_SLOT):
* lisp.h:
* lrecord.h:
* lrecord.h (LISP_OBJECT_UID):
* lrecord.h (set_lheader_implementation):
* lrecord.h (struct old_lcrecord_header):
* lstream.c (print_lstream):
* lstream.c (finalize_lstream):
* marker.c (print_marker):
* marker.c (marker_equal):
* mc-alloc.c (visit_all_used_page_headers):
* mule-charset.c:
* mule-charset.c (print_charset):
* objects.c (print_color_instance):
* objects.c (print_font_instance):
* objects.c (finalize_font_instance):
* opaque.c (print_opaque):
* opaque.c (print_opaque_ptr):
* opaque.c (equal_opaque_ptr):
* print.c (internal_object_printer):
* print.c (enum printing_badness):
* rangetab.c (print_range_table):
* rangetab.c (range_table_equal):
* specifier.c (print_specifier):
* specifier.c (finalize_specifier):
* symbols.c:
* symbols.c (print_symbol_value_magic):
* tooltalk.c:
* tooltalk.c (print_tooltalk_message):
* tooltalk.c (print_tooltalk_pattern):
* window.c (print_window):
* window.c (debug_print_window):
(1) Make lrecord UID's have a separate UID space for each object.
Otherwise, with 20-bit UID's, we rapidly wrap around, especially
when common objects like conses and strings increment the UID value
for every object created. (Originally I tried making two UID spaces,
one for objects that always print readably and hence don't display
the UID, and one for other objects. But certain objects like markers
for which a UID is displayed are still generated rapidly enough that
UID overflow is a serious issue.) This also has the advantage of
making UID values smaller, hence easier to remember -- their main
purpose is to make it easier to keep track of different objects of
the same type when debugging code. Make sure we dump lrecord UID's
so that we don't have problems with pdumped and non-dumped objects
having the same UID.
(2) Display UID's consistently whenever an object (a) doesn't
consistently print readably (objects like cons and string, which
always print readably, can't display a UID), and (b) doesn't
otherwise have a unique property that makes objects of a
particular type distinguishable. (E.g. buffers didn't and still
don't print an ID, but the buffer name uniquely identifies the
buffer.) Some types, such as event, extent, compiled-function,
didn't always (or didn't ever) display an ID; others (such as
marker, extent, lstream, opaque, opaque-ptr, any object using
internal_object_printer()) used to display the actual machine
pointer instead.
(3) Rename NORMAL_LISP_OBJECT_UID to LISP_OBJECT_UID; make it work
over all Lisp objects and take a Lisp object, not a struct pointer.
(4) Some misc cleanups in alloc.c, elhash.c.
(5) Change code in events.c that "deinitializes" an event so that
it doesn't increment the event UID counter in the process. Also
use deadbeef_memory() to overwrite memory instead of doing the same
with custom code. In the process, make deadbeef_memory() in
alloc.c always available, and delete extraneous copy in mc-alloc.c.
Also capitalize all uses of 0xDEADBEEF. Similarly in elhash.c
call deadbeef_memory().
(6) Resurrect "debug SOE" code in extents.c. Make it conditional
on DEBUG_XEMACS and on a `debug-soe' variable, rather than on
SOE_DEBUG. Make it output to stderr, not stdout.
(7) Delete some custom print methods that were identical to
external_object_printer().
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Mon, 15 Mar 2010 16:35:38 -0500 |
parents | f965e31a35f0 |
children | 1fae11d56ad2 |
rev | line source |
---|---|
428 | 1 /* Window creation, deletion and examination for XEmacs. |
2 Copyright (C) 1985-1987, 1992-1995 Free Software Foundation, Inc. | |
3 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. | |
5043 | 4 Copyright (C) 1995, 1996, 2002, 2010 Ben Wing. |
428 | 5 Copyright (C) 1996 Chuck Thompson. |
6 | |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* Synched up with: FSF 19.30. */ | |
25 /* Beginning to diverge significantly. */ | |
26 | |
853 | 27 /* Authorship: |
28 | |
29 Based on code from pre-release FSF 19, c. 1991. | |
30 Significantly reworked by Chuck Thompson, 1993-1996. | |
31 window mirror stuff added by Chuck Thompson c. 1993. | |
32 various cleanup by Ben Wing c. 1995 (window slots, window init code, | |
33 memory usage, synch. up to FSF 19.30, other). | |
34 Unknown work by Andy Piper. | |
35 new window-width/height fns. by Ben Wing, Mar 2000. */ | |
36 | |
428 | 37 /* This file has been Mule-ized. */ |
38 | |
39 #include <config.h> | |
40 #include "lisp.h" | |
41 | |
42 #include "buffer.h" | |
800 | 43 #include "commands.h" |
872 | 44 #include "device-impl.h" |
800 | 45 #include "elhash.h" |
428 | 46 #include "faces.h" |
872 | 47 #include "frame-impl.h" |
800 | 48 #include "glyphs.h" |
49 #include "gutter.h" | |
428 | 50 #include "objects.h" |
51 #include "redisplay.h" | |
872 | 52 #include "window-impl.h" |
428 | 53 |
1149 | 54 Lisp_Object Qwindowp, Qwindow_live_p; |
428 | 55 Lisp_Object Qdisplay_buffer; |
56 | |
57 #ifdef MEMORY_USAGE_STATS | |
58 Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay; | |
59 #ifdef HAVE_SCROLLBARS | |
60 Lisp_Object Qscrollbar_instances; | |
61 #endif | |
62 #endif | |
63 | |
1979 | 64 extern int allow_deletion_of_last_visible_frame; |
65 | |
428 | 66 EXFUN (Fnext_window, 4); |
67 | |
68 static int window_pixel_width_to_char_width (struct window *w, | |
69 int pixel_width, | |
70 int include_margins_p); | |
71 static int window_char_width_to_pixel_width (struct window *w, | |
72 int char_width, | |
73 int include_margins_p); | |
74 static int window_pixel_height_to_char_height (struct window *w, | |
75 int pixel_height, | |
76 int include_gutters_p); | |
77 static int window_char_height_to_pixel_height (struct window *w, | |
78 int char_height, | |
79 int include_gutters_p); | |
444 | 80 static void change_window_height (Lisp_Object window, int delta, |
81 Lisp_Object horizontalp, int inpixels); | |
428 | 82 |
83 /* Thickness of shadow border around 3d modelines. */ | |
84 Lisp_Object Vmodeline_shadow_thickness; | |
85 | |
86 /* Whether vertical dividers are draggable and displayed */ | |
87 Lisp_Object Vvertical_divider_always_visible_p; | |
88 | |
89 /* Whether a modeline should be displayed. */ | |
90 Lisp_Object Vhas_modeline_p; | |
91 | |
92 /* Thickness of shadow border around vertical dividers. */ | |
93 Lisp_Object Vvertical_divider_shadow_thickness; | |
94 | |
95 /* Divider surface width (not counting 3-d borders) */ | |
96 Lisp_Object Vvertical_divider_line_width; | |
97 | |
442 | 98 /* Spacing between outer edge of divider border and window edge */ |
428 | 99 Lisp_Object Vvertical_divider_spacing; |
100 | |
101 /* How much to scroll by per-line. */ | |
102 Lisp_Object Vwindow_pixel_scroll_increment; | |
103 | |
104 /* Scroll if point lands on the bottom line and that line is partially | |
105 clipped. */ | |
106 int scroll_on_clipped_lines; | |
107 | |
108 /* The minibuffer window of the selected frame. | |
109 Note that you cannot test for minibufferness of an arbitrary window | |
110 by comparing against this; but you can test for minibufferness of | |
111 the selected window. */ | |
112 Lisp_Object minibuf_window; | |
113 | |
114 /* Non-nil means it is the window for C-M-v to scroll | |
115 when the minibuffer is selected. */ | |
116 Lisp_Object Vminibuffer_scroll_window; | |
117 | |
118 /* Non-nil means this is the buffer whose window C-M-v should scroll. */ | |
119 Lisp_Object Vother_window_scroll_buffer; | |
120 | |
121 /* Non-nil means it's the function to call to display temp buffers. */ | |
122 Lisp_Object Vtemp_buffer_show_function; | |
123 | |
124 /* If a window gets smaller than either of these, it is removed. */ | |
458 | 125 Fixnum window_min_height; |
126 Fixnum window_min_width; | |
428 | 127 |
128 /* Number of lines of continuity in scrolling by screenfuls. */ | |
458 | 129 Fixnum next_screen_context_lines; |
428 | 130 |
1149 | 131 Lisp_Object Qcurrent_window_configuration, Qset_window_configuration; |
428 | 132 |
707 | 133 Lisp_Object Qtruncate_partial_width_windows; |
134 | |
428 | 135 #define SET_LAST_MODIFIED(w, cache_too) \ |
136 do { \ | |
137 (w)->last_modified[CURRENT_DISP] = Qzero; \ | |
138 (w)->last_modified[DESIRED_DISP] = Qzero; \ | |
139 (w)->last_modified[CMOTION_DISP] = Qzero; \ | |
140 if (cache_too) \ | |
141 (w)->line_cache_last_updated = Qzero; \ | |
142 } while (0) | |
143 | |
144 #define SET_LAST_FACECHANGE(w) \ | |
145 do { \ | |
146 (w)->last_facechange[CURRENT_DISP] = Qzero; \ | |
147 (w)->last_facechange[DESIRED_DISP] = Qzero; \ | |
148 (w)->last_facechange[CMOTION_DISP] = Qzero; \ | |
149 } while (0) | |
150 | |
151 | |
1204 | 152 |
153 static const struct memory_description int_description_1[] = { | |
154 { XD_END } | |
155 }; | |
156 | |
157 static const struct sized_memory_description int_description = { | |
158 sizeof (int), | |
159 int_description_1 | |
160 }; | |
161 | |
162 static const struct memory_description int_dynarr_description_1[] = { | |
163 XD_DYNARR_DESC (int_dynarr, &int_description), | |
164 { XD_END } | |
165 }; | |
166 | |
167 static const struct sized_memory_description int_dynarr_description = { | |
168 sizeof (int_dynarr), | |
169 int_dynarr_description_1 | |
170 }; | |
171 | |
172 static const struct memory_description face_cachel_description_1[] = { | |
2367 | 173 { XD_BLOCK_PTR, offsetof (face_cachel, merged_faces), |
2551 | 174 1, { &int_dynarr_description } }, |
1204 | 175 { XD_LISP_OBJECT, offsetof (face_cachel, face) }, |
176 { XD_LISP_OBJECT, offsetof (face_cachel, foreground) }, | |
177 { XD_LISP_OBJECT, offsetof (face_cachel, background) }, | |
178 { XD_LISP_OBJECT_ARRAY, offsetof (face_cachel, font), NUM_LEADING_BYTES }, | |
179 { XD_LISP_OBJECT, offsetof (face_cachel, display_table) }, | |
180 { XD_LISP_OBJECT, offsetof (face_cachel, background_pixmap) }, | |
181 { XD_END } | |
182 }; | |
183 | |
3092 | 184 #ifdef NEW_GC |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
185 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("face-cachel", face_cachel, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
186 0, face_cachel_description_1, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
187 Lisp_Face_Cachel); |
3092 | 188 #endif /* NEW_GC */ |
189 | |
1204 | 190 static const struct sized_memory_description face_cachel_description = { |
191 sizeof (face_cachel), | |
192 face_cachel_description_1 | |
193 }; | |
194 | |
195 static const struct memory_description face_cachel_dynarr_description_1[] = { | |
3092 | 196 #ifdef NEW_GC |
197 XD_LISP_DYNARR_DESC (face_cachel_dynarr, &face_cachel_description), | |
198 #else /* not NEW_GC */ | |
1204 | 199 XD_DYNARR_DESC (face_cachel_dynarr, &face_cachel_description), |
3092 | 200 #endif /* not NEW_GC */ |
1204 | 201 { XD_END } |
202 }; | |
203 | |
3092 | 204 #ifdef NEW_GC |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
205 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("face-cachel-dynarr", face_cachel_dynarr, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
206 0, face_cachel_dynarr_description_1, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
207 face_cachel_dynarr); |
3092 | 208 #else /* not NEW_GC */ |
1204 | 209 static const struct sized_memory_description face_cachel_dynarr_description = { |
210 sizeof (face_cachel_dynarr), | |
211 face_cachel_dynarr_description_1 | |
212 }; | |
3092 | 213 #endif /* not NEW_GC */ |
1204 | 214 |
215 static const struct memory_description glyph_cachel_description_1[] = { | |
216 { XD_LISP_OBJECT, offsetof (glyph_cachel, glyph) }, | |
217 { XD_END } | |
218 }; | |
219 | |
3092 | 220 #ifdef NEW_GC |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
221 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("glyph-cachel", glyph_cachel, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
222 0, glyph_cachel_description_1, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
223 Lisp_Glyph_Cachel); |
3092 | 224 #endif /* NEW_GC */ |
225 | |
1204 | 226 static const struct sized_memory_description glyph_cachel_description = { |
227 sizeof (glyph_cachel), | |
228 glyph_cachel_description_1 | |
229 }; | |
230 | |
231 static const struct memory_description glyph_cachel_dynarr_description_1[] = { | |
3092 | 232 #ifdef NEW_GC |
233 XD_LISP_DYNARR_DESC (glyph_cachel_dynarr, &glyph_cachel_description), | |
234 #else /* not NEW_GC */ | |
1204 | 235 XD_DYNARR_DESC (glyph_cachel_dynarr, &glyph_cachel_description), |
3092 | 236 #endif /* not NEW_GC */ |
1204 | 237 { XD_END } |
238 }; | |
239 | |
3092 | 240 #ifdef NEW_GC |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
241 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("glyph-cachel-dynarr", |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
242 glyph_cachel_dynarr, 0, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
243 glyph_cachel_dynarr_description_1, |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
244 glyph_cachel_dynarr); |
3092 | 245 #else /* not NEW_GC */ |
1204 | 246 static const struct sized_memory_description glyph_cachel_dynarr_description = { |
247 sizeof (glyph_cachel_dynarr), | |
248 glyph_cachel_dynarr_description_1 | |
249 }; | |
3092 | 250 #endif /* not NEW_GC */ |
1204 | 251 |
252 static const struct memory_description line_start_cache_description_1[] = { | |
253 { XD_END } | |
254 }; | |
255 | |
256 static const struct sized_memory_description line_start_cache_description = { | |
257 sizeof (line_start_cache), | |
258 line_start_cache_description_1 | |
259 }; | |
260 | |
261 static const struct memory_description line_start_cache_dynarr_description_1[] = { | |
262 XD_DYNARR_DESC (line_start_cache_dynarr, &line_start_cache_description), | |
263 { XD_END } | |
264 }; | |
265 | |
266 static const struct sized_memory_description line_start_cache_dynarr_description = { | |
267 sizeof (line_start_cache_dynarr), | |
268 line_start_cache_dynarr_description_1 | |
269 }; | |
270 | |
271 static const struct memory_description window_description [] = { | |
272 #define WINDOW_SLOT(slot) { XD_LISP_OBJECT, offsetof (struct window, slot) }, | |
273 #define WINDOW_SLOT_ARRAY(slot, size) \ | |
274 { XD_LISP_OBJECT_ARRAY, offsetof (struct window, slot), size }, | |
275 #include "winslots.h" | |
276 | |
3092 | 277 #ifdef NEW_GC |
278 { XD_LISP_OBJECT, offsetof (struct window, face_cachels) }, | |
279 { XD_LISP_OBJECT, offsetof (struct window, glyph_cachels) }, | |
280 #else /* not NEW_GC */ | |
2367 | 281 { XD_BLOCK_PTR, offsetof (struct window, face_cachels), |
2551 | 282 1, { &face_cachel_dynarr_description } }, |
2367 | 283 { XD_BLOCK_PTR, offsetof (struct window, glyph_cachels), |
2551 | 284 1, { &glyph_cachel_dynarr_description } }, |
3092 | 285 #endif /* not NEW_GC */ |
2367 | 286 { XD_BLOCK_PTR, offsetof (struct window, line_start_cache), |
2775 | 287 1, { &line_start_cache_dynarr_description }, XD_FLAG_NO_KKCC }, |
1204 | 288 { XD_END } |
289 }; | |
428 | 290 |
291 static Lisp_Object | |
292 mark_window (Lisp_Object obj) | |
293 { | |
294 struct window *window = XWINDOW (obj); | |
295 | |
296 mark_face_cachels (window->face_cachels); | |
297 mark_glyph_cachels (window->glyph_cachels); | |
298 | |
617 | 299 #define WINDOW_SLOT(slot) mark_object (window->slot); |
428 | 300 #include "winslots.h" |
301 | |
302 return Qnil; | |
303 } | |
304 | |
305 static void | |
2286 | 306 print_window (Lisp_Object obj, Lisp_Object printcharfun, |
307 int UNUSED (escapeflag)) | |
428 | 308 { |
4846 | 309 Lisp_Object buf; |
310 | |
428 | 311 if (print_readably) |
5142
f965e31a35f0
reduce lcrecord headers to 2 words, rename printing_unreadable_object
Ben Wing <ben@xemacs.org>
parents:
5128
diff
changeset
|
312 printing_unreadable_lisp_object (obj, 0); |
428 | 313 |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4932
diff
changeset
|
314 write_ascstring (printcharfun, "#<window"); |
4846 | 315 buf = XWINDOW_BUFFER (obj); |
316 if (EQ (buf, Qt)) | |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4932
diff
changeset
|
317 write_ascstring (printcharfun, " during creation"); |
4846 | 318 else if (!NILP (buf)) |
428 | 319 { |
4846 | 320 |
321 Lisp_Object name = XBUFFER (buf)->name; | |
800 | 322 write_fmt_string_lisp (printcharfun, " on %S", 1, name); |
428 | 323 } |
5146
88bd4f3ef8e4
make lrecord UID's have a separate UID space for each object, resurrect debug SOE code in extents.c
Ben Wing <ben@xemacs.org>
parents:
5142
diff
changeset
|
324 write_fmt_string (printcharfun, " 0x%x>", LISP_OBJECT_UID (obj)); |
428 | 325 } |
326 | |
327 static void | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
328 finalize_window (Lisp_Object obj) |
428 | 329 { |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
330 struct window *w = XWINDOW (obj); |
428 | 331 |
332 if (w->line_start_cache) | |
333 { | |
334 Dynarr_free (w->line_start_cache); | |
335 w->line_start_cache = 0; | |
336 } | |
337 | |
338 if (w->face_cachels) | |
339 { | |
340 int i; | |
341 | |
342 for (i = 0; i < Dynarr_length (w->face_cachels); i++) | |
343 { | |
344 struct face_cachel *cachel = Dynarr_atp (w->face_cachels, i); | |
345 if (cachel->merged_faces) | |
346 { | |
347 Dynarr_free (cachel->merged_faces); | |
348 cachel->merged_faces = 0; | |
349 } | |
350 } | |
351 Dynarr_free (w->face_cachels); | |
352 w->face_cachels = 0; | |
353 } | |
354 | |
355 if (w->glyph_cachels) | |
356 { | |
357 Dynarr_free (w->glyph_cachels); | |
358 w->glyph_cachels = 0; | |
359 } | |
360 } | |
361 | |
844 | 362 /* These caches map buffers to markers. They are key-weak so that entries |
363 remain around as long as the buffers do. */ | |
364 | |
365 static Lisp_Object | |
366 make_saved_buffer_point_cache (void) | |
367 { | |
368 return make_lisp_hash_table (20, HASH_TABLE_KEY_WEAK, HASH_TABLE_EQ); | |
369 } | |
370 | |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
371 DEFINE_NODUMP_LISP_OBJECT ("window", window, |
5124
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
372 mark_window, print_window, finalize_window, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
373 0, 0, window_description, struct window); |
428 | 374 |
375 #define INIT_DISP_VARIABLE(field, initialization) \ | |
376 p->field[CURRENT_DISP] = initialization; \ | |
377 p->field[DESIRED_DISP] = initialization; \ | |
378 p->field[CMOTION_DISP] = initialization; | |
379 | |
380 /* We have an implicit assertion that the first two elements (default | |
381 and modeline faces) are always present in the face_element_cache. | |
382 Normally redisplay ensures this. However, it is possible for a | |
383 window to get created and functions which reference these values | |
384 called before redisplay works with the window for the first time. | |
385 All callers of allocate_window should therefore call | |
386 reset_face_cachels on the created window. We can't do it | |
387 here because the window must have its frame pointer set or | |
388 reset_face_cachels will fail. */ | |
389 Lisp_Object | |
390 allocate_window (void) | |
391 { | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
392 Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (window); |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
393 struct window *p = XWINDOW (obj); |
617 | 394 |
395 #define WINDOW_SLOT(slot) p->slot = Qnil; | |
396 #include "winslots.h" | |
397 | |
428 | 398 INIT_DISP_VARIABLE (start, Fmake_marker ()); |
399 INIT_DISP_VARIABLE (pointm, Fmake_marker ()); | |
400 p->sb_point = Fmake_marker (); | |
844 | 401 p->saved_point_cache = make_saved_buffer_point_cache (); |
402 p->saved_last_window_start_cache = make_saved_buffer_point_cache (); | |
428 | 403 p->use_time = Qzero; |
404 INIT_DISP_VARIABLE (last_modified, Qzero); | |
405 INIT_DISP_VARIABLE (last_point, Fmake_marker ()); | |
406 INIT_DISP_VARIABLE (last_start, Fmake_marker ()); | |
407 INIT_DISP_VARIABLE (last_facechange, Qzero); | |
3092 | 408 #ifdef NEW_GC |
409 p->face_cachels = Dynarr_lisp_new (face_cachel, | |
410 &lrecord_face_cachel_dynarr, | |
411 &lrecord_face_cachel); | |
412 p->glyph_cachels = Dynarr_lisp_new (glyph_cachel, | |
413 &lrecord_glyph_cachel_dynarr, | |
414 &lrecord_glyph_cachel); | |
415 #else /* not NEW_GC */ | |
428 | 416 p->face_cachels = Dynarr_new (face_cachel); |
417 p->glyph_cachels = Dynarr_new (glyph_cachel); | |
3092 | 418 #endif /* not NEW_GC */ |
428 | 419 p->line_start_cache = Dynarr_new (line_start_cache); |
450 | 420 p->subwindow_instance_cache = make_image_instance_cache_hash_table (); |
421 | |
428 | 422 p->line_cache_last_updated = Qzero; |
442 | 423 |
428 | 424 p->windows_changed = 1; |
425 p->shadow_thickness_changed = 1; | |
426 | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
427 return obj; |
428 | 428 } |
429 #undef INIT_DISP_VARIABLE | |
430 | |
617 | 431 /************************************************************************/ |
432 /* Window mirror structure */ | |
433 /************************************************************************/ | |
434 | |
428 | 435 /* |
436 * The redisplay structures used to be stored with each window. While | |
437 * they are logically something associated with frames they can't be | |
438 * stored there with a redisplay which handles variable height lines. | |
439 * Lines in horizontally split windows might not line up. So they get | |
440 * stored with the windows. | |
441 * | |
442 * The problem with this is window configurations. When restoring a | |
443 * window configuration it now becomes problematic to do an | |
444 * incremental redisplay. The solution is to store the redisplay | |
445 * structures with the frame as they should be but laid out in the | |
446 * same manner as the window structure. Thus is born the window | |
447 * mirror. | |
448 * | |
449 * It also becomes a convenient place to stick scrollbar instances | |
450 * since they extrapolate out to having the same problem described for | |
451 * the display structures. | |
452 */ | |
453 | |
617 | 454 /* NOTE: The window-mirror structure formerly was not a Lisp object, and |
455 marking was handled specially. I've gotten recurring crashes, however, | |
456 using the mouse wheel under Windows, where either the window mirror | |
457 accessed through a scrollbar instance, or the frame pointed to by that | |
458 window mirror, gets garbaged. Things are tricky under windows because | |
459 the scrollbar instances are stored in HWND-specific data. Furthermore, | |
460 we have scrollbar-instance caches to complicate things. Both of these | |
461 make it very difficult (for me at least, not being intimately familiar | |
462 with the redisplay code) to track exactly when and where a particular | |
463 window mirror or scrollbar instance has pointers to it, or whether a | |
464 window mirror might have a dead frame or buffer in it (i.e. not | |
465 necessarily gc-protected by being on a global list). By far the safest | |
466 thing, then, is to make both structures Lisp objects and not explicitly | |
467 xfree() them. This should make no practical difference in memory usage | |
468 because neither structure is created very often (only when windows are | |
469 created or deleted). --ben */ | |
470 | |
1204 | 471 static const struct memory_description window_mirror_description [] = { |
472 { XD_LISP_OBJECT, offsetof (struct window_mirror, frame) }, | |
473 { XD_LISP_OBJECT, offsetof (struct window_mirror, next) }, | |
474 { XD_LISP_OBJECT, offsetof (struct window_mirror, hchild) }, | |
475 { XD_LISP_OBJECT, offsetof (struct window_mirror, vchild) }, | |
476 | |
2367 | 477 { XD_BLOCK_PTR, offsetof (struct window_mirror, current_display_lines), |
2551 | 478 1, { &display_line_dynarr_description } }, |
2367 | 479 { XD_BLOCK_PTR, offsetof (struct window_mirror, desired_display_lines), |
2551 | 480 1, { &display_line_dynarr_description } }, |
1204 | 481 |
482 { XD_LISP_OBJECT, offsetof (struct window_mirror, buffer) }, | |
483 | |
484 #ifdef HAVE_SCROLLBARS | |
485 { XD_LISP_OBJECT, offsetof (struct window_mirror, | |
486 scrollbar_vertical_instance) }, | |
487 { XD_LISP_OBJECT, offsetof (struct window_mirror, | |
488 scrollbar_horizontal_instance) }, | |
489 #endif /* HAVE_SCROLLBARS */ | |
490 | |
934 | 491 { XD_END } |
492 }; | |
493 | |
617 | 494 static Lisp_Object |
495 mark_window_mirror (Lisp_Object obj) | |
496 { | |
497 struct window_mirror *mir = XWINDOW_MIRROR (obj); | |
498 | |
499 if (mir->current_display_lines) | |
500 mark_redisplay_structs (mir->current_display_lines); | |
501 if (mir->desired_display_lines) | |
502 mark_redisplay_structs (mir->desired_display_lines); | |
503 | |
504 if (mir->hchild) | |
505 mark_object (wrap_window_mirror (mir->hchild)); | |
506 if (mir->vchild) | |
507 mark_object (wrap_window_mirror (mir->vchild)); | |
508 | |
509 if (mir->frame) | |
510 mark_object (wrap_frame (mir->frame)); | |
511 if (mir->buffer) | |
512 mark_object (wrap_buffer (mir->buffer)); | |
513 | |
514 #ifdef HAVE_SCROLLBARS | |
515 if (mir->scrollbar_vertical_instance) | |
516 mark_object (wrap_scrollbar_instance (mir->scrollbar_vertical_instance)); | |
517 if (mir->scrollbar_horizontal_instance) | |
518 mark_object (wrap_scrollbar_instance (mir->scrollbar_horizontal_instance)); | |
519 #endif /* HAVE_SCROLLBARS */ | |
520 if (mir->next) | |
521 return wrap_window_mirror (mir->next); | |
522 else | |
523 return Qnil; | |
524 } | |
525 | |
5124
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
526 DEFINE_NODUMP_INTERNAL_LISP_OBJECT ("window-mirror", window_mirror, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
527 mark_window_mirror, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
528 window_mirror_description, |
623d57b7fbe8
separate regular and disksave finalization, print method fixes.
Ben Wing <ben@xemacs.org>
parents:
5120
diff
changeset
|
529 struct window_mirror); |
617 | 530 |
428 | 531 /* Create a new window mirror structure and associated redisplay |
532 structs. */ | |
533 static struct window_mirror * | |
534 new_window_mirror (struct frame *f) | |
535 { | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
536 Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (window_mirror); |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
537 struct window_mirror *t = XWINDOW_MIRROR (obj); |
428 | 538 |
539 t->frame = f; | |
540 t->current_display_lines = Dynarr_new (display_line); | |
541 t->desired_display_lines = Dynarr_new (display_line); | |
542 | |
543 return t; | |
544 } | |
545 | |
546 /* Synchronize the mirror structure with a given window structure. | |
547 This is normally called from update_frame_window_mirror with a | |
548 starting window of f->root_window. */ | |
549 static struct window_mirror * | |
550 update_mirror_internal (Lisp_Object win, struct window_mirror *mir) | |
551 { | |
552 if (NILP (win)) | |
553 { | |
554 if (mir) | |
555 { | |
556 free_window_mirror (mir); | |
557 mir = NULL; | |
558 } | |
559 return mir; | |
560 } | |
561 else | |
562 if (!mir) | |
563 mir = new_window_mirror (XFRAME (XWINDOW (win)->frame)); | |
564 | |
1204 | 565 mir->next = update_mirror_internal (XWINDOW (win)->next, mir->next); |
428 | 566 mir->hchild = update_mirror_internal (XWINDOW (win)->hchild, mir->hchild); |
567 mir->vchild = update_mirror_internal (XWINDOW (win)->vchild, mir->vchild); | |
568 | |
569 /* | |
570 * If the redisplay structs are not empty and the mirror has | |
571 * children, then this mirror structure was formerly being used for | |
572 * display but is no longer. Reset its current display structs so | |
573 * that redisplay doesn't accidentally think they are accurate if it | |
574 * is later used for display purposes once again. Also, mark the | |
575 * scrollbar instance as not active. | |
576 */ | |
577 if (mir->vchild || mir->hchild) | |
578 { | |
579 /* The redisplay structures are big. Leaving them around in | |
580 non-leaf windows can add up to a lot of wasted space. So | |
581 don't do it. */ | |
582 free_display_structs (mir); | |
583 mir->current_display_lines = Dynarr_new (display_line); | |
584 mir->desired_display_lines = Dynarr_new (display_line); | |
585 | |
586 #ifdef HAVE_SCROLLBARS | |
587 update_window_scrollbars (XWINDOW (win), mir, 0, 0); | |
588 #endif | |
589 mir->buffer = NULL; | |
590 } | |
591 | |
592 return mir; | |
593 } | |
594 | |
595 /* Given a window mirror, determine which real window it contains the | |
596 redisplay structures for. */ | |
597 static Lisp_Object | |
598 real_window_internal (Lisp_Object win, struct window_mirror *rmir, | |
599 struct window_mirror *mir) | |
600 { | |
601 for (; !NILP (win) && rmir ; win = XWINDOW (win)->next, rmir = rmir->next) | |
602 { | |
603 if (mir == rmir) | |
604 return win; | |
605 if (!NILP (XWINDOW (win)->vchild)) | |
606 { | |
607 Lisp_Object retval = | |
608 real_window_internal (XWINDOW (win)->vchild, rmir->vchild, mir); | |
609 if (!NILP (retval)) | |
610 return retval; | |
611 } | |
612 if (!NILP (XWINDOW (win)->hchild)) | |
613 { | |
614 Lisp_Object retval = | |
615 real_window_internal (XWINDOW (win)->hchild, rmir->hchild, mir); | |
616 if (!NILP (retval)) | |
617 return retval; | |
618 } | |
619 } | |
620 | |
621 return Qnil; | |
622 } | |
623 | |
624 /* Given a real window, find the mirror structure which contains its | |
625 redisplay structures. */ | |
626 static struct window_mirror * | |
627 find_window_mirror_internal (Lisp_Object win, struct window_mirror *rmir, | |
628 struct window *w) | |
629 { | |
630 for (; !NILP (win); win = XWINDOW (win)->next, rmir = rmir->next) | |
631 { | |
632 if (w == XWINDOW (win)) | |
633 return rmir; | |
634 | |
635 if (!NILP (XWINDOW (win)->vchild)) | |
636 { | |
637 struct window_mirror *retval = | |
638 find_window_mirror_internal (XWINDOW (win)->vchild, | |
639 rmir->vchild, w); | |
640 if (retval) return retval; | |
641 } | |
642 | |
643 if (!NILP (XWINDOW (win)->hchild)) | |
644 { | |
645 struct window_mirror *retval = | |
646 find_window_mirror_internal (XWINDOW (win)->hchild, | |
647 rmir->hchild, w); | |
648 if (retval) return retval; | |
649 } | |
650 } | |
651 | |
652 return 0; | |
653 } | |
654 | |
655 /* Update the mirror structure for the given frame. */ | |
656 void | |
657 update_frame_window_mirror (struct frame *f) | |
658 { | |
617 | 659 f->root_mirror = |
660 wrap_window_mirror (update_mirror_internal | |
661 (f->root_window, | |
662 NILP (f->root_mirror) ? 0 : | |
663 XWINDOW_MIRROR (f->root_mirror))); | |
428 | 664 f->mirror_dirty = 0; |
665 } | |
666 | |
667 /* Free a given mirror structure along with all of its children as | |
668 well as their associated display structures. */ | |
669 void | |
670 free_window_mirror (struct window_mirror *mir) | |
671 { | |
672 while (mir) | |
673 { | |
674 if (mir->hchild) free_window_mirror (mir->hchild); | |
675 if (mir->vchild) free_window_mirror (mir->vchild); | |
676 #ifdef HAVE_SCROLLBARS | |
677 release_window_mirror_scrollbars (mir); | |
678 #endif | |
679 free_display_structs (mir); | |
680 mir = mir->next; | |
5142
f965e31a35f0
reduce lcrecord headers to 2 words, rename printing_unreadable_object
Ben Wing <ben@xemacs.org>
parents:
5128
diff
changeset
|
681 /* not worth calling free_normal_lisp_object() -- window mirrors |
617 | 682 are not created that frequently and it's dangerous. we don't |
683 know for sure that there aren't other pointers around -- e.g. | |
684 in a scrollbar instance. */ | |
428 | 685 } |
686 } | |
687 | |
688 /* Given a mirror structure, return the window it mirrors. Calls | |
689 real_window_internal to do most of the work. */ | |
690 Lisp_Object | |
691 real_window (struct window_mirror *mir, int no_abort) | |
692 { | |
617 | 693 Lisp_Object retval = |
694 real_window_internal (mir->frame->root_window, | |
695 XWINDOW_MIRROR (mir->frame->root_mirror), mir); | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
696 assert (!NILP (retval) || no_abort); |
428 | 697 |
698 return retval; | |
699 } | |
700 | |
701 /* Given a real window, return its mirror structure. Calls | |
702 find_window_mirror_internal to do all of the work. */ | |
703 struct window_mirror * | |
704 find_window_mirror (struct window *w) | |
705 { | |
706 struct frame *f = XFRAME (w->frame); | |
707 if (f->mirror_dirty) | |
708 update_frame_window_mirror (f); | |
617 | 709 return find_window_mirror_internal (f->root_window, |
710 XWINDOW_MIRROR (f->root_mirror), w); | |
428 | 711 } |
712 | |
713 /***************************************************************************** | |
714 find_window_by_pixel_pos | |
715 | |
716 Given a pixel position relative to a frame, find the window at that | |
717 position. | |
718 ****************************************************************************/ | |
719 struct window * | |
720 find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win) | |
721 { | |
722 if (NILP (win)) | |
723 return 0; | |
724 | |
725 for (; !NILP (win); win = XWINDOW (win)->next) | |
726 { | |
727 struct window *w; | |
728 | |
729 if (!NILP (XWINDOW (win)->vchild)) | |
730 { | |
731 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->vchild); | |
732 if (w) return w; | |
733 } | |
734 if (!NILP (XWINDOW (win)->hchild)) | |
735 { | |
736 w = find_window_by_pixel_pos (pix_x, pix_y, XWINDOW (win)->hchild); | |
737 if (w) return w; | |
738 } | |
739 w = XWINDOW (win); | |
740 if (pix_x >= WINDOW_LEFT (w) | |
741 && pix_x <= WINDOW_RIGHT (w) | |
742 && pix_y >= WINDOW_TOP (w) | |
743 && pix_y <= WINDOW_BOTTOM (w)) | |
744 return w; | |
745 } | |
746 return NULL; | |
747 } | |
748 | |
749 /* Return a pointer to the display structures for the given window. */ | |
750 display_line_dynarr * | |
751 window_display_lines (struct window *w, int which) | |
752 { | |
753 struct window_mirror *t; | |
754 | |
755 if (XFRAME (w->frame)->mirror_dirty) | |
756 update_frame_window_mirror (XFRAME (w->frame)); | |
757 t = find_window_mirror (w); | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
758 assert (t); |
428 | 759 |
760 if (which == CURRENT_DISP) | |
761 return t->current_display_lines; | |
762 else if (which == DESIRED_DISP) | |
763 return t->desired_display_lines; | |
764 else if (which == CMOTION_DISP) | |
765 /* The CMOTION_DISP display lines are global. */ | |
766 return cmotion_display_lines; | |
767 else | |
2500 | 768 ABORT (); |
428 | 769 |
770 return 0; /* shut up compiler */ | |
771 } | |
772 | |
773 struct buffer * | |
774 window_display_buffer (struct window *w) | |
775 { | |
776 struct window_mirror *t; | |
777 | |
778 if (XFRAME (w->frame)->mirror_dirty) | |
779 update_frame_window_mirror (XFRAME (w->frame)); | |
780 t = find_window_mirror (w); | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
781 assert (t); |
428 | 782 |
783 return t->buffer; | |
784 } | |
785 | |
786 void | |
787 set_window_display_buffer (struct window *w, struct buffer *b) | |
788 { | |
789 struct window_mirror *t; | |
790 | |
791 if (XFRAME (w->frame)->mirror_dirty) | |
792 update_frame_window_mirror (XFRAME (w->frame)); | |
793 t = find_window_mirror (w); | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
794 assert (t); |
428 | 795 |
796 t->buffer = b; | |
797 } | |
798 | |
799 | |
800 /* Determining a window's position based solely on its pixel | |
801 positioning doesn't work. Instead, we do it the intelligent way, | |
802 by checking its positioning in the window hierarchy. */ | |
803 int | |
804 window_is_leftmost (struct window *w) | |
805 { | |
806 Lisp_Object parent, current_ancestor, window; | |
807 | |
793 | 808 window = wrap_window (w); |
428 | 809 |
810 parent = XWINDOW (window)->parent; | |
811 current_ancestor = window; | |
812 | |
813 while (!NILP (parent)) | |
814 { | |
815 if (!NILP (XWINDOW (parent)->hchild) && | |
816 !EQ (XWINDOW (parent)->hchild, current_ancestor)) | |
817 return 0; | |
818 | |
819 current_ancestor = parent; | |
820 parent = XWINDOW (parent)->parent; | |
821 } | |
822 | |
823 return 1; | |
824 } | |
825 | |
826 int | |
827 window_is_rightmost (struct window *w) | |
828 { | |
829 Lisp_Object parent, current_ancestor, window; | |
830 | |
793 | 831 window = wrap_window (w); |
428 | 832 |
833 parent = XWINDOW (window)->parent; | |
834 current_ancestor = window; | |
835 | |
836 while (!NILP (parent)) | |
837 { | |
838 if (!NILP (XWINDOW (parent)->hchild) | |
839 && !NILP (XWINDOW (current_ancestor)->next)) | |
840 return 0; | |
841 | |
842 current_ancestor = parent; | |
843 parent = XWINDOW (parent)->parent; | |
844 } | |
845 | |
846 return 1; | |
847 } | |
848 | |
849 static int | |
850 window_full_width_p (struct window *w) | |
851 { | |
852 return window_is_leftmost (w) && window_is_rightmost (w); | |
853 } | |
854 | |
855 int | |
856 window_is_highest (struct window *w) | |
857 { | |
858 Lisp_Object parent, current_ancestor, window; | |
859 | |
793 | 860 window = wrap_window (w); |
428 | 861 |
862 parent = XWINDOW (window)->parent; | |
863 current_ancestor = window; | |
864 | |
865 while (!NILP (parent)) | |
866 { | |
867 if (!NILP (XWINDOW (parent)->vchild) && | |
868 !EQ (XWINDOW (parent)->vchild, current_ancestor)) | |
869 return 0; | |
870 | |
871 current_ancestor = parent; | |
872 parent = XWINDOW (parent)->parent; | |
873 } | |
874 | |
875 /* This is really to catch the minibuffer but we make it generic in | |
876 case we ever change things around to let the minibuffer be on top. */ | |
877 if (NILP (XWINDOW (current_ancestor)->prev)) | |
878 return 1; | |
879 else | |
880 return 0; | |
881 } | |
882 | |
883 int | |
884 window_is_lowest (struct window *w) | |
885 { | |
886 Lisp_Object parent, current_ancestor, window; | |
887 | |
793 | 888 window = wrap_window (w); |
428 | 889 |
890 parent = XWINDOW (window)->parent; | |
891 current_ancestor = window; | |
892 | |
893 while (!NILP (parent)) | |
894 { | |
895 if (!NILP (XWINDOW (parent)->vchild) | |
896 && !NILP (XWINDOW (current_ancestor)->next)) | |
897 return 0; | |
898 | |
899 current_ancestor = parent; | |
900 parent = XWINDOW (parent)->parent; | |
901 } | |
902 | |
903 return 1; | |
904 } | |
905 | |
906 #if 0 /* not currently used */ | |
907 | |
908 static int | |
909 window_full_height_p (struct window *w) | |
910 { | |
911 return window_is_highest (w) && window_is_lowest (w); | |
912 } | |
913 | |
914 #endif | |
915 | |
916 int | |
917 window_truncation_on (struct window *w) | |
918 { | |
919 /* Minibuffer windows are never truncated. | |
440 | 920 #### is this the right way ? */ |
428 | 921 if (MINI_WINDOW_P (w)) |
922 return 0; | |
923 | |
924 /* Horizontally scrolled windows are truncated. */ | |
925 if (w->hscroll) | |
926 return 1; | |
927 | |
928 /* If truncate_partial_width_windows is true and the window is not | |
929 the full width of the frame it is truncated. */ | |
707 | 930 if (!NILP (symbol_value_in_buffer (Qtruncate_partial_width_windows, |
931 w->buffer)) | |
428 | 932 && !(window_is_leftmost (w) && window_is_rightmost (w))) |
933 return 1; | |
934 | |
935 /* If the window's buffer's value of truncate_lines is non-nil, then | |
936 the window is truncated. */ | |
937 if (!NILP (XBUFFER (w->buffer)->truncate_lines)) | |
938 return 1; | |
939 | |
940 return 0; | |
941 } | |
942 | |
943 DEFUN ("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /* | |
442 | 944 Returns non-nil if text in the window is truncated. |
428 | 945 */ |
946 (window)) | |
947 { | |
948 struct window *w = decode_window (window); | |
949 | |
950 return window_truncation_on (w) ? Qt : Qnil; | |
951 } | |
952 | |
953 | |
954 static int | |
955 have_undivided_common_edge (struct window *w_right, void *closure) | |
956 { | |
957 struct window *w_left = (struct window *) closure; | |
958 return (WINDOW_RIGHT (w_left) == WINDOW_LEFT (w_right) | |
959 && WINDOW_TOP (w_left) < WINDOW_BOTTOM (w_right) | |
960 && WINDOW_TOP (w_right) < WINDOW_BOTTOM (w_left) | |
961 #ifdef HAVE_SCROLLBARS | |
962 && (NILP (w_right->scrollbar_on_left_p) | |
963 || NILP (w_right->vertical_scrollbar_visible_p) | |
964 || ZEROP (w_right->scrollbar_width)) | |
965 #endif | |
966 ); | |
967 } | |
968 | |
969 static int | |
970 window_needs_vertical_divider_1 (struct window *w) | |
971 { | |
972 /* Never if we're on the right */ | |
973 if (window_is_rightmost (w)) | |
974 return 0; | |
975 | |
976 /* Always if draggable */ | |
977 if (!NILP (w->vertical_divider_always_visible_p)) | |
978 return 1; | |
979 | |
980 #ifdef HAVE_SCROLLBARS | |
981 /* Our right scrollbar is enough to separate us at the right */ | |
982 if (NILP (w->scrollbar_on_left_p) | |
983 && !NILP (w->vertical_scrollbar_visible_p) | |
984 && !ZEROP (w->scrollbar_width)) | |
985 return 0; | |
986 #endif | |
987 | |
988 /* Ok. to determine whether we need a divider on the left, we must | |
989 check that our right neighbor windows have scrollbars on their | |
990 left sides. We must check all such windows which have common | |
991 left edge with our window's right edge. */ | |
992 return map_windows (XFRAME (WINDOW_FRAME (w)), | |
993 have_undivided_common_edge, (void*)w); | |
994 } | |
995 | |
996 int | |
997 window_needs_vertical_divider (struct window *w) | |
998 { | |
999 if (!w->need_vertical_divider_valid_p) | |
1000 { | |
1001 w->need_vertical_divider_p = | |
1002 window_needs_vertical_divider_1 (w); | |
1003 w->need_vertical_divider_valid_p = 1; | |
1004 } | |
1005 return w->need_vertical_divider_p; | |
1006 } | |
1007 | |
1008 /* Called from invalidate_vertical_divider_cache_in_frame */ | |
1009 int | |
1010 invalidate_vertical_divider_cache_in_window (struct window *w, | |
2286 | 1011 void *UNUSED (unused)) |
428 | 1012 { |
1013 w->need_vertical_divider_valid_p = 0; | |
1014 return 0; | |
1015 } | |
1016 | |
1017 /* Calculate width of vertical divider, including its shadows | |
1018 and spacing. The returned value is effectively the distance | |
1019 between adjacent window edges. This function does not check | |
1020 whether a window needs a vertical divider, so the returned | |
1021 value is a "theoretical" one */ | |
1022 int | |
1023 window_divider_width (struct window *w) | |
1024 { | |
1025 /* the shadow thickness can be negative. This means that the divider | |
1026 will have a depressed look */ | |
1027 | |
1028 if (FRAME_WIN_P (XFRAME (WINDOW_FRAME (w)))) | |
1029 return | |
1030 XINT (w->vertical_divider_line_width) | |
1031 + 2 * XINT (w->vertical_divider_spacing) | |
1032 + 2 * abs (XINT (w->vertical_divider_shadow_thickness)); | |
1033 else | |
1034 return XINT (w->vertical_divider_line_width) == 0 ? 0 : 1; | |
1035 } | |
1036 | |
1037 int | |
4932 | 1038 window_scrollbar_width (struct window * USED_IF_SCROLLBARS (w)) |
428 | 1039 { |
1040 #ifdef HAVE_SCROLLBARS | |
1041 if (!WINDOW_WIN_P (w) | |
1042 || MINI_WINDOW_P (w) | |
1043 || NILP (w->buffer) | |
1044 || NILP (w->vertical_scrollbar_visible_p)) | |
1045 /* #### when does NILP (w->buffer) happen? */ | |
1046 return 0; | |
1047 | |
1048 return XINT (w->scrollbar_width); | |
1049 #else | |
1050 return 0; | |
1051 #endif /* HAVE_SCROLLBARS */ | |
1052 } | |
1053 | |
1054 /* Horizontal scrollbars are only active on windows with truncation | |
1055 turned on. */ | |
1056 int | |
4932 | 1057 window_scrollbar_height (struct window * USED_IF_SCROLLBARS (w)) |
428 | 1058 { |
1059 #ifdef HAVE_SCROLLBARS | |
1060 if (!WINDOW_WIN_P (w) | |
1061 || MINI_WINDOW_P (w) | |
1062 || NILP (w->buffer) | |
1063 || NILP (w->horizontal_scrollbar_visible_p) | |
1064 || !window_truncation_on (w)) | |
1065 return 0; | |
1066 | |
1067 return XINT (w->scrollbar_height); | |
1068 #else | |
1069 return 0; | |
1070 #endif /* HAVE_SCROLLBARS */ | |
1071 } | |
1072 | |
1073 int | |
1074 window_modeline_height (struct window *w) | |
1075 { | |
1076 struct frame *f = XFRAME (w->frame); | |
1077 int modeline_height; | |
1078 | |
1079 if (MINI_WINDOW_P (w) || NILP (w->buffer)) | |
1080 { | |
1081 modeline_height = 0; | |
1082 } | |
1083 else if (!WINDOW_HAS_MODELINE_P (w)) | |
1084 { | |
1085 if (window_scrollbar_height (w)) | |
1086 modeline_height = 0; | |
1087 else | |
1088 { | |
1089 modeline_height = FRAMEMETH (f, divider_height, ()); | |
1090 | |
1091 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) | |
1092 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w)); | |
1093 } | |
1094 } | |
1095 else | |
1096 { | |
1097 if (noninteractive) | |
1098 modeline_height = 0; | |
1099 else | |
1100 { | |
1101 display_line_dynarr *dla; | |
1102 | |
1103 /* We don't force a regeneration of the modeline here. | |
1104 Instead it is now a precondition that any function calling | |
1105 this should make sure that one of these structures is | |
1106 up-to-date. In practice this only affects two internal | |
1107 redisplay functions, regenerate_window and | |
1108 regenerate_window_point_center. */ | |
1109 /* We check DESIRED_DISP because if it is valid it is more | |
1110 up-to-date than CURRENT_DISP. For calls to this outside | |
1111 of redisplay it doesn't matter which structure we check | |
1112 since there is a redisplay condition that these | |
1113 structures be identical outside of redisplay. */ | |
1114 dla = window_display_lines (w, DESIRED_DISP); | |
4967 | 1115 if (dla && Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
1116 modeline_height = (Dynarr_begin (dla)->ascent + | |
1117 Dynarr_begin (dla)->descent); | |
428 | 1118 else |
1119 { | |
1120 dla = window_display_lines (w, CURRENT_DISP); | |
4967 | 1121 if (dla && Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
1122 modeline_height = (Dynarr_begin (dla)->ascent + | |
1123 Dynarr_begin (dla)->descent); | |
428 | 1124 else |
1125 /* This should be an abort except I'm not yet 100% | |
1126 confident that it won't ever get hit (though I | |
1127 haven't been able to trigger it). It is extremely | |
1128 unlikely to cause any noticeable problem and even if | |
1129 it does it will be a minor display glitch. */ | |
1130 /* #### Bullshit alert. It does get hit and it causes | |
1131 noticeable glitches. real_current_modeline_height | |
1132 is a kludge to fix this for 19.14. */ | |
1133 modeline_height = real_current_modeline_height (w); | |
1134 } | |
1135 | |
1136 if (!EQ (Qzero, w->modeline_shadow_thickness) && FRAME_WIN_P (f)) | |
1137 modeline_height += (2 * MODELINE_SHADOW_THICKNESS (w)); | |
1138 } | |
1139 } | |
1140 | |
1141 return modeline_height; | |
1142 } | |
1143 | |
1144 /***************************************************************************** | |
1145 margin_width_internal | |
1146 | |
1147 For a given window, return the width in pixels of the specified margin. | |
1148 ****************************************************************************/ | |
1149 static int | |
1150 margin_width_internal (struct window *w, int left_margin) | |
1151 { | |
1152 int window_cwidth = window_char_width (w, 1); | |
1153 int margin_cwidth; | |
1154 int font_width; | |
1155 Lisp_Object window; | |
1156 | |
1157 /* We might be getting called on a non-leaf. */ | |
1158 if (NILP (w->buffer)) | |
1159 return 0; | |
1160 | |
1161 /* The minibuffer never has margins. */ | |
1162 if (MINI_WINDOW_P (w)) | |
1163 return 0; | |
1164 | |
793 | 1165 window = wrap_window (w); |
428 | 1166 margin_cwidth = (left_margin ? XINT (w->left_margin_width) : |
1167 XINT (w->right_margin_width)); | |
1168 | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
1169 default_face_width_and_height (window, &font_width, 0); |
428 | 1170 |
1171 /* The left margin takes precedence over the right margin so we | |
1172 subtract its width from the space available for the right | |
1173 margin. */ | |
1174 if (!left_margin) | |
1175 window_cwidth -= XINT (w->left_margin_width); | |
1176 | |
1177 /* The margin cannot be wider than the window is. We allow the | |
1178 value to be bigger since it is possible for the user to enlarge | |
1179 the window such that the left margin value would no longer be too | |
1180 big, but we won't return a value that is larger. */ | |
1181 if (margin_cwidth > window_cwidth) | |
1182 margin_cwidth = window_cwidth; | |
1183 | |
1184 /* At the user level the margin is always specified in characters. | |
1185 Internally however it is manipulated in terms of pixels. */ | |
1186 return margin_cwidth * font_width; | |
1187 } | |
1188 | |
1189 int | |
1190 window_left_margin_width (struct window *w) | |
1191 { | |
1192 return margin_width_internal (w, 1); | |
1193 } | |
1194 | |
1195 int | |
1196 window_right_margin_width (struct window *w) | |
1197 { | |
1198 return margin_width_internal (w, 0); | |
1199 } | |
1200 | |
1201 /***************************************************************************** | |
1202 Window Gutters | |
1203 | |
1204 The gutters of a window are those areas in the boundary defined by | |
1205 w->pixel_top, w->pixel_left, w->pixel_height and w->pixel_width which | |
1206 do not contain text. Items which may be in the gutters include | |
1207 scrollbars, toolbars and modelines. The margin areas are not | |
1208 included. This is an exception made because redisplay special cases | |
1209 the handling of those areas in many places in such a way that | |
1210 including them in the gutter area would make life difficult. | |
1211 | |
1212 The size functions refer to height for the bottom and top gutters and | |
1213 width for the left and right gutters. The starting position | |
1214 functions refer to the Y coord for bottom and top gutters and the X | |
1215 coord for left and right gutters. All starting positions are | |
1216 relative to the frame, not the window. | |
1217 ****************************************************************************/ | |
1218 | |
442 | 1219 static int |
1220 window_top_window_gutter_height (struct window *w) | |
1221 { | |
428 | 1222 if (!NILP (w->hchild) || !NILP (w->vchild)) |
1223 return 0; | |
1224 | |
1225 #ifdef HAVE_SCROLLBARS | |
1226 if (!NILP (w->scrollbar_on_top_p)) | |
442 | 1227 return window_scrollbar_height (w); |
428 | 1228 else |
1229 #endif | |
442 | 1230 return 0; |
428 | 1231 } |
1232 | |
1233 int | |
442 | 1234 window_top_gutter_height (struct window *w) |
1235 { | |
1236 return window_top_window_gutter_height (w); | |
1237 } | |
1238 | |
1239 static int | |
1240 window_bottom_window_gutter_height (struct window *w) | |
1241 { | |
1242 int gutter; | |
428 | 1243 |
1244 if (!NILP (w->hchild) || !NILP (w->vchild)) | |
1245 return 0; | |
1246 | |
442 | 1247 gutter = window_modeline_height (w); |
428 | 1248 |
1249 #ifdef HAVE_SCROLLBARS | |
1250 if (NILP (w->scrollbar_on_top_p)) | |
1251 return window_scrollbar_height (w) + gutter; | |
1252 else | |
1253 #endif | |
1254 return gutter; | |
1255 } | |
1256 | |
1257 int | |
442 | 1258 window_bottom_gutter_height (struct window *w) |
1259 { | |
1260 return window_bottom_window_gutter_height (w); | |
1261 } | |
1262 | |
1263 static int | |
4932 | 1264 window_left_window_gutter_width (struct window *w, |
1265 int USED_IF_SCROLLBARS (modeline)) | |
442 | 1266 { |
428 | 1267 if (!NILP (w->hchild) || !NILP (w->vchild)) |
1268 return 0; | |
1269 | |
1270 #ifdef HAVE_SCROLLBARS | |
1271 if (!modeline && !NILP (w->scrollbar_on_left_p)) | |
442 | 1272 return window_scrollbar_width (w); |
428 | 1273 #endif |
1274 | |
442 | 1275 return 0; |
428 | 1276 } |
1277 | |
1278 int | |
442 | 1279 window_left_gutter_width (struct window *w, int modeline) |
1280 { | |
1281 return window_left_window_gutter_width (w, modeline); | |
1282 } | |
1283 | |
1284 static int | |
4932 | 1285 window_right_window_gutter_width (struct window *w, |
1286 int USED_IF_SCROLLBARS (modeline)) | |
442 | 1287 { |
1288 int gutter = 0; | |
428 | 1289 |
1290 if (!NILP (w->hchild) || !NILP (w->vchild)) | |
1291 return 0; | |
1292 | |
1293 #ifdef HAVE_SCROLLBARS | |
1294 if (!modeline && NILP (w->scrollbar_on_left_p)) | |
1295 gutter += window_scrollbar_width (w); | |
1296 #endif | |
1297 | |
1298 if (window_needs_vertical_divider (w)) | |
1299 gutter += window_divider_width (w); | |
1300 | |
1301 return gutter; | |
1302 } | |
1303 | |
442 | 1304 int |
1305 window_right_gutter_width (struct window *w, int modeline) | |
1306 { | |
1307 return window_right_window_gutter_width (w, modeline); | |
1308 } | |
1309 | |
1310 static int | |
1311 window_pixel_height (struct window* w) | |
1312 { | |
1313 return WINDOW_HEIGHT (w); | |
1314 } | |
1315 | |
428 | 1316 |
1317 DEFUN ("windowp", Fwindowp, 1, 1, 0, /* | |
444 | 1318 Return t if OBJECT is a window. |
428 | 1319 */ |
444 | 1320 (object)) |
1321 { | |
1322 return WINDOWP (object) ? Qt : Qnil; | |
428 | 1323 } |
1324 | |
1325 DEFUN ("window-live-p", Fwindow_live_p, 1, 1, 0, /* | |
444 | 1326 Return t if OBJECT is a window which is currently visible. |
428 | 1327 */ |
444 | 1328 (object)) |
1329 { | |
1330 return WINDOWP (object) && WINDOW_LIVE_P (XWINDOW (object)) | |
1331 ? Qt : Qnil; | |
428 | 1332 } |
1333 | |
1334 DEFUN ("selected-window", Fselected_window, 0, 1, 0, /* | |
1335 Return the window that the cursor now appears in and commands apply to. | |
1336 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return | |
1337 the selected window used by that frame. If CON-DEV-OR-FRAME is a device, | |
1338 then the selected frame on that device will be used. If CON-DEV-OR-FRAME | |
1339 is a console, the selected frame on that console's selected device will | |
1340 be used. Otherwise, the selected frame is used. | |
1341 */ | |
1342 (con_dev_or_frame)) | |
1343 { | |
1344 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil))) | |
1345 return Qnil; /* happens at startup */ | |
1346 | |
1347 { | |
1348 struct frame *f = decode_frame_or_selected (con_dev_or_frame); | |
1349 return FRAME_SELECTED_WINDOW (f); | |
1350 } | |
1351 } | |
1352 | |
1353 DEFUN ("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /* | |
1354 Return the last selected window that is not a minibuffer window. | |
1355 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, | |
1356 return the last non-minibuffer window used by that frame. If | |
1357 CON-DEV-OR-FRAME is a device, then the selected frame on that device | |
1358 will be used. If CON-DEV-OR-FRAME is a console, the selected frame on | |
1359 that console's selected device will be used. Otherwise, the selected | |
1360 frame is used. | |
1361 */ | |
1362 (con_dev_or_frame)) | |
1363 { | |
1364 if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil))) | |
1365 return Qnil; /* happens at startup */ | |
1366 | |
1367 { | |
1368 struct frame *f = decode_frame_or_selected (con_dev_or_frame); | |
1369 return FRAME_LAST_NONMINIBUF_WINDOW (f); | |
1370 } | |
1371 } | |
1372 | |
1373 DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /* | |
1374 Return the window used now for minibuffers. | |
1375 If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return | |
1376 the minibuffer window used by that frame. If CON-DEV-OR-FRAME is a device, | |
1377 then the selected frame on that device will be used. If CON-DEV-OR-FRAME | |
1378 is a console, the selected frame on that console's selected device will | |
1379 be used. Otherwise, the selected frame is used. | |
1380 */ | |
1381 (con_dev_or_frame)) | |
1382 { | |
1383 return FRAME_MINIBUF_WINDOW (decode_frame_or_selected (con_dev_or_frame)); | |
1384 } | |
1385 | |
438 | 1386 DEFUN ("window-minibuffer-p", Fwindow_minibuffer_p, 0, 1, 0, /* |
428 | 1387 Return non-nil if WINDOW is a minibuffer window. |
1388 */ | |
1389 (window)) | |
1390 { | |
1391 return MINI_WINDOW_P (decode_window (window)) ? Qt : Qnil; | |
1392 } | |
1393 | |
1394 DEFUN ("window-first-hchild", Fwindow_first_hchild, 1, 1, 0, /* | |
1395 Return the first horizontal child of WINDOW, or nil. | |
1396 */ | |
1397 (window)) | |
1398 { | |
1399 return decode_window (window)->hchild; | |
1400 } | |
1401 | |
1402 DEFUN ("window-first-vchild", Fwindow_first_vchild, 1, 1, 0, /* | |
1403 Return the first vertical child of WINDOW, or nil. | |
1404 */ | |
1405 (window)) | |
1406 { | |
1407 return decode_window (window)->vchild; | |
1408 } | |
1409 | |
1410 DEFUN ("window-next-child", Fwindow_next_child, 1, 1, 0, /* | |
1411 Return the next window on the same level as WINDOW, or nil. | |
1412 */ | |
1413 (window)) | |
1414 { | |
1415 return decode_window (window)->next; | |
1416 } | |
1417 | |
1418 DEFUN ("window-previous-child", Fwindow_previous_child, 1, 1, 0, /* | |
1419 Return the previous window on the same level as WINDOW, or nil. | |
1420 */ | |
1421 (window)) | |
1422 { | |
1423 return decode_window (window)->prev; | |
1424 } | |
1425 | |
1426 DEFUN ("window-parent", Fwindow_parent, 1, 1, 0, /* | |
1427 Return the parent of WINDOW, or nil. | |
1428 */ | |
1429 (window)) | |
1430 { | |
1431 return decode_window (window)->parent; | |
1432 } | |
1433 | |
1434 DEFUN ("window-lowest-p", Fwindow_lowest_p, 1, 1, 0, /* | |
1435 Return non-nil if WINDOW is along the bottom of its frame. | |
1436 */ | |
1437 (window)) | |
1438 { | |
1439 return window_is_lowest (decode_window (window)) ? Qt : Qnil; | |
1440 } | |
1441 | |
1442 DEFUN ("window-highest-p", Fwindow_highest_p, 1, 1, 0, /* | |
1443 Return non-nil if WINDOW is along the top of its frame. | |
1444 */ | |
1445 (window)) | |
1446 { | |
1447 return window_is_highest (decode_window (window)) ? Qt : Qnil; | |
1448 } | |
1449 | |
1450 DEFUN ("window-leftmost-p", Fwindow_leftmost_p, 1, 1, 0, /* | |
1451 Return non-nil if WINDOW is along the left edge of its frame. | |
1452 */ | |
1453 (window)) | |
1454 { | |
1455 return window_is_leftmost (decode_window (window)) ? Qt : Qnil; | |
1456 } | |
1457 | |
1458 DEFUN ("window-rightmost-p", Fwindow_rightmost_p, 1, 1, 0, /* | |
1459 Return non-nil if WINDOW is along the right edge of its frame. | |
1460 */ | |
1461 (window)) | |
1462 { | |
1463 return window_is_rightmost (decode_window (window)) ? Qt : Qnil; | |
1464 } | |
1465 | |
1708 | 1466 DEFUN ("pos-visible-in-window-p", Fpos_visible_in_window_p, 0, 3, 0, /* |
1467 Returns t if position POS is currently on the frame in WINDOW. | |
428 | 1468 Returns nil if that position is scrolled vertically out of view. |
1708 | 1469 If a character is only partially visible, nil is returned, unless the |
1470 optional argument PARTIALLY is non-nil. | |
428 | 1471 POS defaults to point in WINDOW's buffer; WINDOW, to the selected window. |
1472 */ | |
1708 | 1473 (pos, window, partially)) |
428 | 1474 { |
1475 struct window *w = decode_window (window); | |
665 | 1476 Charbpos top = marker_position (w->start[CURRENT_DISP]); |
1477 Charbpos posint; | |
428 | 1478 struct buffer *buf = XBUFFER (w->buffer); |
1479 | |
1480 if (NILP (pos)) | |
1481 posint = BUF_PT (buf); | |
1482 else | |
1483 { | |
1484 CHECK_INT_COERCE_MARKER (pos); | |
1485 posint = XINT (pos); | |
1486 } | |
1487 | |
1488 if (posint < top || posint > BUF_ZV (buf)) | |
1489 return Qnil; | |
1490 | |
1491 /* w->start can be out of range. If it is, do something reasonable. */ | |
1492 if (top < BUF_BEGV (buf) || top > BUF_ZV (buf)) | |
1493 return Qnil; | |
1494 | |
1708 | 1495 return point_would_be_visible (w, top, posint, !NILP (partially)) |
1496 ? Qt : Qnil; | |
428 | 1497 } |
1498 | |
1499 | |
1500 struct window * | |
1501 decode_window (Lisp_Object window) | |
1502 { | |
1503 if (NILP (window)) | |
1504 return XWINDOW (Fselected_window (Qnil)); | |
1505 | |
1506 CHECK_LIVE_WINDOW (window); | |
1507 return XWINDOW (window); | |
1508 } | |
1509 | |
872 | 1510 int |
1511 window_live_p (struct window *w) | |
1512 { | |
1513 return WINDOW_LIVE_P (w); | |
1514 } | |
1515 | |
1516 Lisp_Object | |
1517 window_frame (struct window *w) | |
1518 { | |
1519 return WINDOW_FRAME (w); | |
1520 } | |
1521 | |
1522 Lisp_Object | |
1523 window_buffer (struct window *w) | |
1524 { | |
1525 return WINDOW_BUFFER (w); | |
1526 } | |
1527 | |
428 | 1528 DEFUN ("window-buffer", Fwindow_buffer, 0, 1, 0, /* |
1529 Return the buffer that WINDOW is displaying. | |
1530 */ | |
1531 (window)) | |
1532 { | |
1533 return decode_window (window)->buffer; | |
1534 } | |
1535 | |
1536 DEFUN ("window-frame", Fwindow_frame, 0, 1, 0, /* | |
1537 Return the frame that window WINDOW is on. | |
1538 */ | |
1539 (window)) | |
1540 { | |
1541 return decode_window (window)->frame; | |
1542 } | |
1543 | |
1544 DEFUN ("window-height", Fwindow_height, 0, 1, 0, /* | |
1545 Return the number of default lines in WINDOW. | |
1546 This actually works by dividing the window's pixel height (including | |
1547 the modeline and horizontal scrollbar, if any) by the height of the | |
1548 default font; therefore, the number of displayed lines will probably | |
1549 be different. | |
1550 Use `window-height' to get consistent results in geometry calculations. | |
1551 Use `window-displayed-height' to get the actual number of lines | |
1552 currently displayed in a window. | |
442 | 1553 |
1554 The names are somewhat confusing; here's a table to help out: | |
1555 | |
1556 width height | |
1557 ------------------------------------------------------------------------- | |
1558 w/o gutters | |
1559 (rows/columns) window-width window-text-area-height | |
1560 (pixels) window-text-area-pixel-width window-text-area-pixel-height | |
1561 | |
1562 with gutters | |
1563 (rows/columns) window-full-width window-height | |
1564 (pixels) window-pixel-width window-pixel-height | |
1565 | |
1566 actually displayed | |
1567 (rows/columns) ---- window-displayed-height | |
1568 (pixels) ---- window-displayed-text-pixel-height | |
428 | 1569 */ |
1570 (window)) | |
1571 { | |
1572 return make_int (window_char_height (decode_window (window), 1)); | |
1573 } | |
1574 | |
1575 DEFUN ("window-displayed-height", Fwindow_displayed_height, 0, 1, 0, /* | |
1576 Return the number of lines currently displayed in WINDOW. | |
1577 This counts the actual number of lines displayed in WINDOW | |
1578 \(as opposed to `window-height'). The modeline and horizontal | |
1579 scrollbar do not count as lines. If there is some blank space | |
1580 between the end of the buffer and the end of the window, this | |
1581 function pretends that there are lines of text in the default | |
1582 font there. | |
1583 */ | |
1584 (window)) | |
1585 { | |
1586 return make_int (window_displayed_height (decode_window (window))); | |
1587 } | |
1588 | |
1589 DEFUN ("window-pixel-height", Fwindow_pixel_height, 0, 1, 0, /* | |
1590 Return the height of WINDOW in pixels. Defaults to current window. | |
1591 This includes the window's modeline and horizontal scrollbar (if any). | |
1592 */ | |
1593 (window)) | |
1594 { | |
442 | 1595 return make_int (window_pixel_height (decode_window (window))); |
1596 } | |
1597 | |
1598 DEFUN ("window-text-area-height", Fwindow_text_area_height, 0, 1, 0, /* | |
1599 Return the number of default lines in the text area of WINDOW. | |
1600 This actually works by dividing the window's text area pixel height (i.e. | |
1601 excluding the modeline and horizontal scrollbar, if any) by the height of the | |
1602 default font; therefore, the number of displayed lines will probably | |
1603 be different. | |
1604 See also `window-height' and `window-displayed-height'. | |
1605 */ | |
1606 (window)) | |
1607 { | |
1608 return make_int (window_char_height (decode_window (window), 0)); | |
428 | 1609 } |
1610 | |
1611 DEFUN ("window-text-area-pixel-height", | |
1612 Fwindow_text_area_pixel_height, 0, 1, 0, /* | |
1613 Return the height in pixels of the text-displaying portion of WINDOW. | |
1614 Unlike `window-pixel-height', the space occupied by the modeline and | |
1615 horizontal scrollbar, if any, is not counted. | |
1616 */ | |
1617 (window)) | |
1618 { | |
1619 struct window *w = decode_window (window); | |
1620 | |
1621 return make_int (WINDOW_TEXT_HEIGHT (w)); | |
1622 } | |
1623 | |
1624 DEFUN ("window-displayed-text-pixel-height", | |
1625 Fwindow_displayed_text_pixel_height, 0, 2, 0, /* | |
1626 Return the height in pixels of the text displayed in WINDOW. | |
1627 Unlike `window-text-area-pixel-height', any blank space below the | |
1628 end of the buffer is not included. If optional argument NOCLIPPED | |
1629 is non-nil, do not include space occupied by clipped lines. | |
1630 */ | |
1631 (window, noclipped)) | |
1632 { | |
1633 struct window *w; | |
665 | 1634 Charbpos start, eobuf; |
428 | 1635 int defheight; |
1636 int hlimit, height, prev_height = -1; | |
1637 int line; | |
1638 int elt, nelt, i; | |
1639 int needed; | |
1640 line_start_cache_dynarr *cache; | |
1641 | |
1642 if (NILP (window)) | |
1643 window = Fselected_window (Qnil); | |
1644 | |
1645 CHECK_LIVE_WINDOW (window); | |
1646 w = XWINDOW (window); | |
1647 | |
1648 start = marker_position (w->start[CURRENT_DISP]); | |
1649 hlimit = WINDOW_TEXT_HEIGHT (w); | |
1650 eobuf = BUF_ZV (XBUFFER (w->buffer)); | |
1651 | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
1652 default_face_width_and_height (window, NULL, &defheight); |
428 | 1653 |
1654 /* guess lines needed in line start cache + a few extra */ | |
1655 needed = (hlimit + defheight-1) / defheight + 3; | |
1656 | |
1657 while (1) { | |
1658 elt = point_in_line_start_cache (w, start, needed); | |
1659 assert (elt >= 0); /* in the cache */ | |
1660 | |
1661 cache = w->line_start_cache; | |
1662 nelt = Dynarr_length (cache); | |
1663 | |
1664 height = 0; | |
1665 for (i = elt; i < nelt; i++) { | |
1666 line = Dynarr_atp (cache, i)->height; | |
1667 | |
1668 if (height + line > hlimit) | |
1669 return make_int (!NILP (noclipped) ? height : hlimit); | |
1670 | |
1671 height += line; | |
1672 | |
1673 if (height == hlimit || Dynarr_atp (cache, i)->end >= eobuf) | |
1674 return make_int (height); | |
1675 } | |
1676 | |
1677 /* get here => need more cache lines. try again. */ | |
1678 assert(height > prev_height); /* progress? */ | |
1679 prev_height = height; | |
1680 | |
1681 needed += ((hlimit - height)*(nelt - elt) + height-1)/height + 3; | |
1682 } | |
1683 | |
1204 | 1684 RETURN_NOT_REACHED(make_int (0)); /* shut up compiler */ |
428 | 1685 } |
1686 | |
1687 DEFUN ("window-width", Fwindow_width, 0, 1, 0, /* | |
1688 Return the number of display columns in WINDOW. | |
442 | 1689 This is the width that is usable columns available for text in WINDOW, |
1690 and does not include vertical scrollbars, dividers, or the like. See also | |
1691 `window-full-width' and `window-height'. | |
428 | 1692 */ |
1693 (window)) | |
1694 { | |
1695 return make_int (window_char_width (decode_window (window), 0)); | |
1696 } | |
1697 | |
442 | 1698 DEFUN ("window-full-width", Fwindow_full_width, 0, 1, 0, /* |
1699 Return the total number of columns in WINDOW. | |
1700 This is like `window-width' but includes vertical scrollbars, dividers, | |
1701 etc. | |
1702 */ | |
1703 (window)) | |
1704 { | |
1705 return make_int (window_char_width (decode_window (window), 1)); | |
1706 } | |
1707 | |
428 | 1708 DEFUN ("window-pixel-width", Fwindow_pixel_width, 0, 1, 0, /* |
1709 Return the width of WINDOW in pixels. Defaults to current window. | |
1710 */ | |
1711 (window)) | |
1712 { | |
1713 return make_int (decode_window (window)->pixel_width); | |
1714 } | |
1715 | |
1716 DEFUN ("window-text-area-pixel-width", | |
1717 Fwindow_text_area_pixel_width, 0, 1, 0, /* | |
1718 Return the width in pixels of the text-displaying portion of WINDOW. | |
1719 Unlike `window-pixel-width', the space occupied by the vertical | |
1720 scrollbar or divider, if any, is not counted. | |
1721 */ | |
1722 (window)) | |
1723 { | |
1724 struct window *w = decode_window (window); | |
1725 | |
1726 return make_int (WINDOW_TEXT_WIDTH (w)); | |
1727 } | |
1728 | |
1729 DEFUN ("window-hscroll", Fwindow_hscroll, 0, 1, 0, /* | |
1730 Return the number of columns by which WINDOW is scrolled from left margin. | |
1731 */ | |
1732 (window)) | |
1733 { | |
1734 return make_int (decode_window (window)->hscroll); | |
1735 } | |
1736 | |
1737 DEFUN ("modeline-hscroll", Fmodeline_hscroll, 0, 1, 0, /* | |
442 | 1738 Return the horizontal scrolling amount of WINDOW's modeline. |
438 | 1739 If the window has no modeline, return nil. |
428 | 1740 */ |
1741 (window)) | |
1742 { | |
1743 struct window *w = decode_window (window); | |
1744 | |
438 | 1745 return (WINDOW_HAS_MODELINE_P (w)) ? make_int ((int) w->modeline_hscroll) : |
1746 Qnil; | |
428 | 1747 } |
1748 | |
1749 DEFUN ("set-modeline-hscroll", Fset_modeline_hscroll, 2, 2, 0, /* | |
442 | 1750 Set the horizontal scrolling amount of WINDOW's modeline to NCOL. |
438 | 1751 If NCOL is negative, it will silently be forced to 0. |
1752 If the window has no modeline, return nil. Otherwise, return the actual | |
1753 value that was set. | |
428 | 1754 */ |
1755 (window, ncol)) | |
1756 { | |
1757 struct window *w = decode_window (window); | |
1758 | |
1759 if (WINDOW_HAS_MODELINE_P (w)) | |
1760 { | |
438 | 1761 Charcount ncols; |
1762 | |
428 | 1763 CHECK_INT (ncol); |
438 | 1764 ncols = (XINT (ncol) <= 0) ? 0 : (Charcount) XINT (ncol); |
1765 if (ncols != w->modeline_hscroll) | |
1766 { | |
1767 MARK_MODELINE_CHANGED; | |
1768 w->modeline_hscroll = ncols; | |
1769 } | |
1770 return make_int ((int) ncols); | |
428 | 1771 } |
438 | 1772 |
428 | 1773 return Qnil; |
1774 } | |
1775 | |
1776 DEFUN ("set-window-hscroll", Fset_window_hscroll, 2, 2, 0, /* | |
1777 Set number of columns WINDOW is scrolled from left margin to NCOL. | |
1778 NCOL should be zero or positive. | |
1779 */ | |
1780 (window, ncol)) | |
1781 { | |
1782 struct window *w; | |
1783 int ncols; | |
1784 | |
1785 CHECK_INT (ncol); | |
1786 ncols = XINT (ncol); | |
1787 if (ncols < 0) ncols = 0; | |
1788 w = decode_window (window); | |
1789 if (w->hscroll != ncols) | |
1790 MARK_CLIP_CHANGED; /* FSF marks differently but we aren't FSF. */ | |
1791 w->hscroll = ncols; | |
1792 return ncol; | |
1793 } | |
1794 | |
1795 DEFUN ("window-pixel-edges", Fwindow_pixel_edges, 0, 1, 0, /* | |
1796 Return a list of the pixel edge coordinates of WINDOW. | |
444 | 1797 The returned list is of the form (LEFT TOP RIGHT BOTTOM), |
1798 all relative to 0, 0 at the top left corner of WINDOW's frame. | |
1799 The frame toolbars, menubars and gutters are considered to be outside | |
1800 of this area, while the scrollbars are considered to be inside. | |
428 | 1801 */ |
1802 (window)) | |
1803 { | |
1804 struct window *w = decode_window (window); | |
1805 struct frame *f = XFRAME (w->frame); | |
1806 | |
5090 | 1807 int left = w->pixel_left - FRAME_PANED_LEFT_EDGE (f); |
1808 int top = w->pixel_top - FRAME_PANED_TOP_EDGE (f); | |
428 | 1809 |
1810 return list4 (make_int (left), | |
1811 make_int (top), | |
1812 make_int (left + w->pixel_width), | |
1813 make_int (top + w->pixel_height)); | |
1814 } | |
1815 | |
1816 DEFUN ("window-text-area-pixel-edges", | |
1817 Fwindow_text_area_pixel_edges, 0, 1, 0, /* | |
1818 Return a list of the pixel edge coordinates of the text area of WINDOW. | |
444 | 1819 The returned list is of the form (LEFT TOP RIGHT BOTTOM), |
1820 all relative to 0, 0 at the top left corner of the total area allocated | |
1821 to the window, which includes the scrollbars. | |
428 | 1822 */ |
1823 (window)) | |
1824 { | |
1825 struct window *w = decode_window (window); | |
1826 | |
1827 int left = window_left_gutter_width (w, /* modeline = */ 0); | |
1828 int top = window_top_gutter_height (w); | |
1829 int right = WINDOW_WIDTH (w) - window_right_gutter_width (w, 0); | |
1830 int bottom = WINDOW_HEIGHT (w) - window_bottom_gutter_height (w); | |
1831 | |
1832 return list4 (make_int (left), | |
1833 make_int (top), | |
1834 make_int (right), | |
1835 make_int (bottom)); | |
1836 } | |
1837 | |
1838 DEFUN ("window-point", Fwindow_point, 0, 1, 0, /* | |
1839 Return current value of point in WINDOW. | |
442 | 1840 For a non-selected window, this is the value point would have |
428 | 1841 if that window were selected. |
1842 | |
1843 Note that, when WINDOW is the selected window and its buffer | |
1844 is also currently selected, the value returned is the same as (point). | |
1845 It would be more strictly correct to return the `top-level' value | |
1846 of point, outside of any save-excursion forms. | |
444 | 1847 But that value is hard to find. |
428 | 1848 */ |
1849 (window)) | |
1850 { | |
1851 struct window *w = decode_window (window); | |
1852 | |
1853 /* The special check for current buffer is necessary for this | |
1854 function to work as defined when called within an excursion. */ | |
1855 if (w == XWINDOW (Fselected_window (XFRAME (w->frame)->device)) | |
1856 && current_buffer == XBUFFER (w->buffer)) | |
1857 return Fpoint (Qnil); | |
1858 return Fmarker_position (w->pointm[CURRENT_DISP]); | |
1859 } | |
1860 | |
1861 DEFUN ("window-start", Fwindow_start, 0, 1, 0, /* | |
1862 Return position at which display currently starts in WINDOW. | |
1863 This is updated by redisplay or by calling `set-window-start'. | |
1864 */ | |
1865 (window)) | |
1866 { | |
1867 return Fmarker_position (decode_window (window)->start[CURRENT_DISP]); | |
1868 } | |
1869 | |
1870 DEFUN ("window-end", Fwindow_end, 0, 2, 0, /* | |
1871 Return position at which display currently ends in WINDOW. | |
1872 This is updated by redisplay, when it runs to completion. | |
444 | 1873 Simply changing the buffer text or setting `window-start' does not |
1874 update this value. WINDOW defaults to the selected window. | |
1875 | |
1876 If optional arg GUARANTEE is non-nil, the return value is guaranteed | |
1877 to be the same value as this function would return at the end of the | |
1878 next full redisplay assuming nothing else changes in the meantime. | |
1879 This function is potentially much slower with this flag set. | |
428 | 1880 */ |
1881 (window, guarantee)) | |
1882 { | |
1883 struct window *w = decode_window (window); | |
1884 | |
1885 if (NILP (guarantee)) | |
1886 { | |
1887 Lisp_Object buf; | |
1888 buf = w->buffer; | |
1889 CHECK_BUFFER (buf); | |
1890 return make_int (BUF_Z (XBUFFER (buf)) - w->window_end_pos[CURRENT_DISP]); | |
1891 } | |
1892 else | |
1893 { | |
665 | 1894 Charbpos startp = marker_position (w->start[CURRENT_DISP]); |
428 | 1895 return make_int (end_of_last_line (w, startp)); |
1896 } | |
1897 } | |
1898 | |
442 | 1899 DEFUN ("window-last-line-visible-height", Fwindow_last_line_visible_height, 0, 1, 0, /* |
1900 Return pixel height of visible part of last window line if it is clipped. | |
1901 If the last line is not clipped, return nil. | |
1902 */ | |
1903 (window)) | |
1904 { | |
1905 struct window *w = decode_window (window); | |
1906 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
1907 int num_lines = Dynarr_length (dla); | |
1908 struct display_line *dl; | |
1909 | |
1910 /* No lines - no clipped lines */ | |
4967 | 1911 if (num_lines == 0 || (num_lines == 1 && Dynarr_begin (dla)->modeline)) |
442 | 1912 return Qnil; |
1913 | |
1914 dl = Dynarr_atp (dla, num_lines - 1); | |
1915 if (dl->clip == 0) | |
1916 return Qnil; | |
1917 | |
1918 return make_int (dl->ascent + dl->descent - dl->clip); | |
1919 } | |
1920 | |
428 | 1921 DEFUN ("set-window-point", Fset_window_point, 2, 2, 0, /* |
1922 Make point value in WINDOW be at position POS in WINDOW's buffer. | |
1161 | 1923 If WINDOW is the selected window, and window's buffer is the current |
1924 buffer, this actually changes the buffer's point instead of the window's | |
1925 point. (The equivalence of the selected window's point with its buffer's | |
1926 point is maintained throughout XEmacs. However, enforcing the additional | |
1927 restriction on the current buffer is "bug compatible" with FSF and is | |
1928 perhaps more logical.) | |
428 | 1929 */ |
1930 (window, pos)) | |
1931 { | |
1932 struct window *w = decode_window (window); | |
1933 | |
1934 CHECK_INT_COERCE_MARKER (pos); | |
1161 | 1935 |
844 | 1936 /* Don't dereference selected-window because there may not |
1937 be one -- e.g. at startup */ | |
1161 | 1938 if (EQ (wrap_window (w), Fselected_window (Qnil)) |
1939 && EQ (w->buffer, Fcurrent_buffer ())) | |
1940 Fgoto_char (pos, Qnil); | |
428 | 1941 else |
1942 set_marker_restricted (w->pointm[CURRENT_DISP], pos, w->buffer); | |
1943 | |
1944 MARK_POINT_CHANGED; | |
1945 return pos; | |
1946 } | |
1947 | |
1948 DEFUN ("set-window-start", Fset_window_start, 2, 3, 0, /* | |
1949 Make display in WINDOW start at position POS in WINDOW's buffer. | |
1950 Optional third arg NOFORCE non-nil inhibits next redisplay | |
1951 from overriding motion of point in order to display at this exact start. | |
1952 */ | |
1953 (window, pos, noforce)) | |
1954 { | |
1955 struct window *w = decode_window (window); | |
1956 | |
1957 CHECK_INT_COERCE_MARKER (pos); | |
1958 set_marker_restricted (w->start[CURRENT_DISP], pos, w->buffer); | |
1959 /* this is not right, but much easier than doing what is right. */ | |
1960 /* w->start_at_line_beg = 0; */ | |
1961 /* WTF is the above supposed to mean? GE */ | |
1962 w->start_at_line_beg = beginning_of_line_p (XBUFFER (w->buffer), | |
1963 marker_position (w->start[CURRENT_DISP])); | |
1964 if (NILP (noforce)) | |
1965 w->force_start = 1; | |
1966 w->redo_modeline = 1; | |
1967 SET_LAST_MODIFIED (w, 0); | |
1968 SET_LAST_FACECHANGE (w); | |
1969 | |
1970 MARK_WINDOWS_CHANGED (w); | |
1971 | |
1972 return pos; | |
1973 } | |
1974 | |
1975 DEFUN ("window-dedicated-p", Fwindow_dedicated_p, 1, 1, 0, /* | |
1976 Return WINDOW's dedicated object, usually t or nil. | |
1977 See also `set-window-dedicated-p'. | |
1978 */ | |
1979 (window)) | |
1980 { | |
1981 return decode_window (window)->dedicated; | |
1982 } | |
1983 | |
1984 DEFUN ("set-window-dedicated-p", Fset_window_dedicated_p, 2, 2, 0, /* | |
1985 Control whether WINDOW is dedicated to the buffer it displays. | |
1986 If it is dedicated, Emacs will not automatically change | |
1987 which buffer appears in it. | |
1988 The second argument is the new value for the dedication flag; | |
1989 non-nil means yes. | |
1990 */ | |
1991 (window, arg)) | |
1992 { | |
1993 struct window *w = decode_window (window); | |
1994 | |
1995 w->dedicated = NILP (arg) ? Qnil : Qt; | |
1996 | |
1997 return w->dedicated; | |
1998 } | |
1999 | |
2000 /* FSFmacs has window-display-table here. We have display table as a | |
2001 specifier. */ | |
2002 | |
2003 | |
2004 /* Record info on buffer window w is displaying | |
2005 when it is about to cease to display that buffer. */ | |
2006 static void | |
2007 unshow_buffer (struct window *w) | |
2008 { | |
2009 Lisp_Object buf = w->buffer; | |
844 | 2010 struct buffer *b = XBUFFER (buf); |
2011 | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
2012 assert (b == XMARKER (w->pointm[CURRENT_DISP])->buffer); |
428 | 2013 |
2014 /* FSF disables this check, so I'll do it too. I hope it won't | |
2015 break things. --ben */ | |
2016 #if 0 | |
2017 if (w == XWINDOW (Fselected_window (Qnil)) | |
2018 || ! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer)) | |
2019 /* Do this except when the selected window's buffer | |
2020 is being removed from some other window. */ | |
2021 #endif | |
2022 /* last_window_start records the start position that this buffer | |
2023 had in the last window to be disconnected from it. | |
2024 Now that this statement is unconditional, | |
2025 it is possible for the buffer to be displayed in the | |
2026 selected window, while last_window_start reflects another | |
2027 window which was recently showing the same buffer. | |
2028 Some people might say that might be a good thing. Let's see. */ | |
2029 XBUFFER (buf)->last_window_start = | |
2030 marker_position (w->start[CURRENT_DISP]); | |
2031 | |
2032 /* Point in the selected window's buffer | |
2033 is actually stored in that buffer, and the window's pointm isn't used. | |
2034 So don't clobber point in that buffer. */ | |
2035 if (! EQ (buf, XWINDOW (Fselected_window (Qnil))->buffer)) | |
844 | 2036 BUF_SET_PT (b, |
2037 charbpos_clip_to_bounds | |
2038 (BUF_BEGV (b), | |
2039 marker_position (w->pointm[CURRENT_DISP]), | |
2040 BUF_ZV (b))); | |
2041 | |
2042 { | |
2043 Lisp_Object marker = Fgethash (buf, w->saved_point_cache, Qnil); | |
2044 int selected = EQ (wrap_window (w), Fselected_window (Qnil)); | |
2045 | |
2046 if (NILP (marker)) | |
2047 { | |
2048 marker = Fmake_marker (); | |
2049 Fputhash (buf, marker, w->saved_point_cache); | |
2050 } | |
2051 Fset_marker (marker, | |
2052 selected ? make_int (BUF_PT (b)) : w->pointm[CURRENT_DISP], | |
2053 buf); | |
2054 | |
2055 marker = Fgethash (buf, w->saved_last_window_start_cache, Qnil); | |
2056 | |
2057 if (NILP (marker)) | |
2058 { | |
2059 marker = Fmake_marker (); | |
2060 Fputhash (buf, marker, w->saved_last_window_start_cache); | |
2061 } | |
2062 Fset_marker (marker, w->start[CURRENT_DISP], buf); | |
2063 } | |
428 | 2064 } |
2065 | |
2066 /* Put REPLACEMENT into the window structure in place of OLD. */ | |
2067 static void | |
2068 replace_window (Lisp_Object old, Lisp_Object replacement) | |
2069 { | |
2070 Lisp_Object tem; | |
2071 struct window *o = XWINDOW (old), *p = XWINDOW (replacement); | |
2072 | |
2073 /* If OLD is its frame's root_window, then replacement is the new | |
2074 root_window for that frame. */ | |
2075 | |
2076 if (EQ (old, FRAME_ROOT_WINDOW (XFRAME (o->frame)))) | |
2077 FRAME_ROOT_WINDOW (XFRAME (o->frame)) = replacement; | |
2078 | |
2079 WINDOW_LEFT (p) = WINDOW_LEFT (o); | |
2080 WINDOW_TOP (p) = WINDOW_TOP (o); | |
2081 WINDOW_WIDTH (p) = WINDOW_WIDTH (o); | |
2082 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o); | |
2083 | |
2084 p->next = tem = o->next; | |
2085 if (!NILP (tem)) | |
2086 XWINDOW (tem)->prev = replacement; | |
2087 | |
2088 p->prev = tem = o->prev; | |
2089 if (!NILP (tem)) | |
2090 XWINDOW (tem)->next = replacement; | |
2091 | |
2092 p->parent = tem = o->parent; | |
2093 if (!NILP (tem)) | |
2094 { | |
2095 if (EQ (XWINDOW (tem)->vchild, old)) | |
2096 XWINDOW (tem)->vchild = replacement; | |
2097 if (EQ (XWINDOW (tem)->hchild, old)) | |
2098 XWINDOW (tem)->hchild = replacement; | |
2099 } | |
2100 | |
2101 /* #### Here, if replacement is a vertical combination | |
2102 and so is its new parent, we should make replacement's | |
2103 children be children of that parent instead. */ | |
442 | 2104 |
2105 ERROR_CHECK_SUBWINDOW_CACHE (p); | |
2106 } | |
2107 | |
2108 static void | |
2109 window_unmap_subwindows (struct window* w) | |
2110 { | |
2111 assert (!NILP (w->subwindow_instance_cache)); | |
2112 elisp_maphash (unmap_subwindow_instance_cache_mapper, | |
2113 w->subwindow_instance_cache, (void*)1); | |
428 | 2114 } |
2115 | |
2116 /* we're deleting W; set the structure of W to indicate this. */ | |
2117 | |
2118 static void | |
2119 mark_window_as_deleted (struct window *w) | |
2120 { | |
442 | 2121 /* The window instance cache is going away now, so need to get the |
2122 cachels reset by redisplay. */ | |
2123 MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (WINDOW_FRAME (w))); | |
2124 | |
2125 /* The cache is going away. If we leave unmapping to | |
2126 reset_subwindow_cachels then we get in a situation where the | |
2127 domain (the window) has been deleted but we still need access to | |
2128 its attributes in order to unmap windows properly. Since the | |
2129 subwindows are going to get GC'd anyway as a result of the domain | |
2130 going away, it is safer to just unmap them all while we know the | |
2131 domain is still valid. */ | |
2132 ERROR_CHECK_SUBWINDOW_CACHE (w); | |
2133 window_unmap_subwindows (w); | |
2134 | |
617 | 2135 /* Free the extra data structures attached to windows immediately so |
2136 they don't sit around consuming excess space. They will be | |
2137 reinitialized by the window-configuration code as necessary. */ | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
2138 finalize_window (wrap_window (w)); |
617 | 2139 |
1149 | 2140 /* Nobody should be accessing anything in this object any more, |
618 | 2141 and making them Qnil allows for better GC'ing in case a pointer |
2142 to the dead window continues to hang around. Zero all other | |
2143 structs in case someone tries to access something through them. | |
2144 | |
2145 (So, in point of fact, we zero out all of the "saved" slots, | |
2146 which are obviously restored from the window config, plus the | |
2147 slots which were already zeroed.) | |
617 | 2148 |
2149 As an example of why setting the values to Qnil is good, here | |
2150 is an old comment: | |
2151 | |
2152 In the loop | |
428 | 2153 (while t (split-window) (delete-window)) |
2154 we end up with a tree of deleted windows which are all connected | |
2155 through the `next' slot. This might not seem so bad, as they're | |
2156 deleted, and will presumably be GCed - but if even *one* of those | |
2157 windows is still being pointed to, by the user, or by a window | |
1149 | 2158 configuration, then *all* of those windows stick around. */ |
617 | 2159 |
618 | 2160 #define WINDOW_SLOT(slot) |
2161 #define WINDOW_SAVED_SLOT(slot, compare) w->slot = Qnil; | |
617 | 2162 #include "winslots.h" |
428 | 2163 |
618 | 2164 w->next = Qnil; |
2165 w->prev = Qnil; | |
2166 w->hchild = Qnil; | |
2167 w->vchild = Qnil; | |
2168 w->parent = Qnil; | |
2169 w->subwindow_instance_cache = Qnil; | |
2170 | |
428 | 2171 w->dead = 1; |
853 | 2172 note_object_deleted (wrap_window (w)); |
428 | 2173 } |
2174 | |
1207 | 2175 /* Check if window contains pwindow. */ |
2176 | |
2177 static int | |
2178 contains_window (Lisp_Object window, Lisp_Object pwindow) | |
2179 { | |
2180 while (!NILP (pwindow)) | |
2181 { | |
2182 if (EQ (window, pwindow)) | |
2183 return 1; | |
2184 pwindow = XWINDOW (pwindow)->parent; | |
2185 } | |
2186 return 0; | |
2187 } | |
2188 | |
428 | 2189 DEFUN ("delete-window", Fdelete_window, 0, 2, "", /* |
2190 Remove WINDOW from the display. Default is selected window. | |
444 | 2191 If window is the only one on its frame, the frame is deleted as well. |
428 | 2192 Normally, you cannot delete the last non-minibuffer-only frame (you must |
2193 use `save-buffers-kill-emacs' or `kill-emacs'). However, if optional | |
2194 second argument FORCE is non-nil, you can delete the last frame. (This | |
2195 will automatically call `save-buffers-kill-emacs'.) | |
2196 */ | |
2197 (window, force)) | |
2198 { | |
2199 /* This function can GC if this is the only window in the frame */ | |
2200 struct window *w; | |
2201 Lisp_Object parent; | |
2202 struct window *par; | |
2203 Lisp_Object frame; | |
2204 struct frame *f; | |
2205 struct device *d; | |
2206 | |
2207 /* Note: this function is called by other C code on non-leaf | |
2208 windows. */ | |
2209 | |
2210 /* Do the equivalent of decode_window() but don't error out on | |
2211 deleted window; it's OK to delete an already-deleted window. */ | |
2212 if (NILP (window)) | |
2213 window = Fselected_window (Qnil); | |
2214 else | |
2215 CHECK_WINDOW (window); | |
442 | 2216 |
428 | 2217 w = XWINDOW (window); |
2218 | |
2219 /* It's okay to delete an already-deleted window. */ | |
2220 if (! WINDOW_LIVE_P (w)) | |
2221 return Qnil; | |
2222 | |
853 | 2223 check_allowed_operation (OPERATION_DELETE_OBJECT, window, Qnil); |
2224 | |
428 | 2225 frame = WINDOW_FRAME (w); |
2226 f = XFRAME (frame); | |
2227 d = XDEVICE (FRAME_DEVICE (f)); | |
2228 | |
2229 if (TOP_LEVEL_WINDOW_P (w)) | |
2230 { | |
2231 if (NILP (memq_no_quit (frame, DEVICE_FRAME_LIST (d)))) | |
2232 /* this frame isn't fully initialized yet; don't blow up. */ | |
2233 return Qnil; | |
2234 | |
2235 if (MINI_WINDOW_P (XWINDOW (window))) | |
563 | 2236 signal_error (Qinvalid_operation, "Attempt to delete the minibuffer window", Qunbound); |
428 | 2237 |
2238 /* It has been suggested that it's a good thing for C-x 0 to have this | |
2239 behavior, but not such a good idea for #'delete-window to have it. | |
2240 Maybe C-x 0 should be bound to something else, or maybe frame | |
2241 deletion should only happen when this is called interactively. | |
2242 */ | |
2243 delete_frame_internal (f, !NILP (force), 0, 0); | |
2244 return Qnil; | |
2245 } | |
2246 | |
2247 /* At this point, we know the window has a parent. */ | |
2248 parent = w->parent; | |
2249 par = XWINDOW (parent); | |
2250 | |
2251 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); | |
430 | 2252 /* It's quite likely that deleting a window will result in |
2253 subwindows needing to be deleted also (since they are cached | |
2254 per-window). So we mark them as changed, so that the cachels will | |
2255 get reset by redisplay and thus deleted subwindows can get | |
2256 GC'd. */ | |
2257 MARK_FRAME_SUBWINDOWS_CHANGED (f); | |
428 | 2258 |
2259 /* Are we trying to delete any frame's selected window? | |
2260 Note that we could be dealing with a non-leaf window | |
2261 where the selected window is one of our children. | |
2262 So, we check by scanning all the ancestors of the | |
2263 frame's selected window and comparing each one with | |
2264 WINDOW. */ | |
1207 | 2265 if (contains_window (window, FRAME_SELECTED_WINDOW (f))) |
2266 { | |
2267 Lisp_Object alternative; | |
2268 alternative = Fnext_window (window, Qlambda, Qnil, Qnil); | |
2269 | |
2270 /* #### */ | |
2271 /* If we're about to delete the selected window on the | |
2272 selected frame, then we should use Fselect_window to select | |
2273 the new window. On the other hand, if we're about to | |
2274 delete the selected window on any other frame, we shouldn't do | |
2275 anything but set the frame's selected_window slot. */ | |
2276 if (EQ (frame, Fselected_frame (Qnil))) | |
2277 Fselect_window (alternative, Qnil); | |
2278 else | |
2279 set_frame_selected_window (f, alternative); | |
2280 } | |
2281 | |
2282 /* Some display parameters (gutter display specifically) depend on | |
2283 FRAME_LAST_NONMINIBUF (f) to be set to a live window. Ensure that. */ | |
2284 if (contains_window (window, FRAME_LAST_NONMINIBUF_WINDOW (f))) | |
2285 f->last_nonminibuf_window = Fnext_window (window, Qlambda, Qnil, Qnil); | |
428 | 2286 |
2287 /* w->buffer is nil in a non-leaf window; in this case, | |
2288 get rid of the markers we maintain that point into that buffer. */ | |
2289 if (!NILP (w->buffer)) | |
2290 { | |
2291 unshow_buffer (w); | |
2292 unchain_marker (w->pointm[CURRENT_DISP]); | |
2293 unchain_marker (w->pointm[DESIRED_DISP]); | |
2294 unchain_marker (w->pointm[CMOTION_DISP]); | |
2295 unchain_marker (w->start[CURRENT_DISP]); | |
2296 unchain_marker (w->start[DESIRED_DISP]); | |
2297 unchain_marker (w->start[CMOTION_DISP]); | |
2298 unchain_marker (w->sb_point); | |
1149 | 2299 w->buffer = Qnil; |
428 | 2300 } |
2301 | |
2302 /* close up the hole in the sibling list */ | |
2303 if (!NILP (w->next)) | |
2304 XWINDOW (w->next)->prev = w->prev; | |
2305 if (!NILP (w->prev)) | |
2306 XWINDOW (w->prev)->next = w->next; | |
2307 if (EQ (window, par->hchild)) | |
2308 par->hchild = w->next; | |
2309 if (EQ (window, par->vchild)) | |
2310 par->vchild = w->next; | |
2311 | |
2312 /* Find one of our siblings to give our space to. */ | |
2313 { | |
2314 Lisp_Object sib = w->prev; | |
2315 if (NILP (sib)) | |
2316 { | |
2317 /* If w gives its space to its next sibling, that sibling needs | |
2318 to have its top/left side pulled back to where w's is. | |
2319 set_window_{height,width} will re-position the sibling's | |
2320 children. */ | |
2321 sib = w->next; | |
2322 WINDOW_TOP (XWINDOW (sib)) = WINDOW_TOP (w); | |
2323 WINDOW_LEFT (XWINDOW (sib)) = WINDOW_LEFT (w); | |
2324 } | |
2325 | |
2326 /* Stretch that sibling. */ | |
2327 if (!NILP (par->vchild)) | |
2328 set_window_pixheight | |
2329 (sib, (WINDOW_HEIGHT (XWINDOW (sib)) + WINDOW_HEIGHT (w)), 1); | |
2330 if (!NILP (par->hchild)) | |
2331 set_window_pixwidth | |
2332 (sib, (WINDOW_WIDTH (XWINDOW (sib)) + WINDOW_WIDTH (w)), 1); | |
2333 } | |
2334 | |
2335 /* If parent now has only one child, | |
2336 put the child into the parent's place. */ | |
2337 { | |
2338 Lisp_Object parchild = par->hchild; | |
2339 if (NILP (parchild)) | |
2340 parchild = par->vchild; | |
2341 if (NILP (XWINDOW (parchild)->next)) | |
2342 { | |
2343 replace_window (parent, parchild); | |
2344 mark_window_as_deleted (XWINDOW (parent)); | |
2345 } | |
2346 } | |
2347 | |
2348 /* Since we may be deleting combination windows, we must make sure that | |
2349 not only W but all its children have been marked as deleted. */ | |
2350 if (!NILP (w->hchild)) | |
2351 delete_all_subwindows (XWINDOW (w->hchild)); | |
2352 else if (!NILP (w->vchild)) | |
2353 delete_all_subwindows (XWINDOW (w->vchild)); | |
2354 | |
1752 | 2355 /* Warning: mark_window_as_deleted calls window_unmap_subwindows and |
2356 therefore redisplay, so it requires the mirror structure to be | |
2357 correct. We must dirty the mirror before it is called. */ | |
2358 f->mirror_dirty = 1; | |
2359 | |
428 | 2360 mark_window_as_deleted (w); |
2361 | |
2362 return Qnil; | |
2363 } | |
2364 | |
2365 | |
2366 DEFUN ("next-window", Fnext_window, 0, 4, 0, /* | |
442 | 2367 Return the next window after WINDOW in the canonical ordering of windows. |
428 | 2368 If omitted, WINDOW defaults to the selected window. |
2369 | |
2370 Optional second arg MINIBUF t means count the minibuffer window even | |
2371 if not active. MINIBUF nil or omitted means count the minibuffer iff | |
2372 it is active. MINIBUF neither t nor nil means not to count the | |
2373 minibuffer even if it is active. | |
2374 | |
2375 Several frames may share a single minibuffer; if the minibuffer | |
2376 counts, all windows on all frames that share that minibuffer count | |
2377 too. Therefore, `next-window' can be used to iterate through the | |
2378 set of windows even when the minibuffer is on another frame. If the | |
2379 minibuffer does not count, only windows from WINDOW's frame count. | |
2380 | |
444 | 2381 By default, only the windows in the selected frame are considered. |
2382 The optional argument WHICH-FRAMES changes this behavior: | |
2383 WHICH-FRAMES = `visible' means search windows on all visible frames. | |
448 | 2384 WHICH-FRAMES = 0 means search windows on all visible and iconified frames. |
444 | 2385 WHICH-FRAMES = t means search windows on all frames including invisible frames. |
2386 WHICH-FRAMES = a frame means search only windows on that frame. | |
2387 Anything else means restrict to the selected frame. | |
2388 | |
2389 The optional fourth argument WHICH-DEVICES further clarifies on which | |
2390 devices to search for frames as specified by WHICH-FRAMES. This value | |
2391 is only meaningful if WHICH-FRAMES is non-nil. | |
2392 If nil or omitted, search all devices on the selected console. | |
2393 If a device, only search that device. | |
2394 If a console, search all devices on that console. | |
2395 If a device type, search all devices of that type. | |
2396 If `window-system', search all window-system devices. | |
2397 Any other non-nil value means search all devices. | |
2398 | |
2399 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES, | |
2400 you can use `next-window' to iterate through the entire cycle of | |
2401 acceptable windows, eventually ending up back at the window you started with. | |
428 | 2402 `previous-window' traverses the same cycle, in the reverse order. |
2403 */ | |
444 | 2404 (window, minibuf, which_frames, which_devices)) |
428 | 2405 { |
2406 Lisp_Object tem; | |
2407 Lisp_Object start_window; | |
2408 | |
2409 if (NILP (window)) | |
2410 window = Fselected_window (Qnil); | |
2411 else | |
2412 CHECK_LIVE_WINDOW (window); | |
2413 | |
2414 start_window = window; | |
2415 | |
2416 /* minibuf == nil may or may not include minibuffers. | |
2417 Decide if it does. */ | |
2418 if (NILP (minibuf)) | |
2419 minibuf = (minibuf_level ? minibuf_window : Qlambda); | |
2420 else if (! EQ (minibuf, Qt)) | |
2421 minibuf = Qlambda; | |
442 | 2422 /* Now `minibuf' is one of: |
2423 t => count all minibuffer windows | |
2424 lambda => count none of them | |
428 | 2425 or a specific minibuffer window (the active one) to count. */ |
2426 | |
444 | 2427 /* which_frames == nil doesn't specify which frames to include. */ |
2428 if (NILP (which_frames)) | |
2429 which_frames = (! EQ (minibuf, Qlambda) | |
428 | 2430 ? (FRAME_MINIBUF_WINDOW |
2431 (XFRAME | |
2432 (WINDOW_FRAME | |
2433 (XWINDOW (window))))) | |
2434 : Qnil); | |
444 | 2435 else if (EQ (which_frames, Qvisible)) |
428 | 2436 ; |
444 | 2437 else if (ZEROP (which_frames)) |
428 | 2438 ; |
444 | 2439 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window))) |
2440 /* If which_frames is a frame and window arg isn't on that frame, just | |
428 | 2441 return the first window on the frame. */ |
444 | 2442 return frame_first_window (XFRAME (which_frames)); |
2443 else if (! EQ (which_frames, Qt)) | |
2444 which_frames = Qnil; | |
2445 /* Now `which_frames' is one of: | |
442 | 2446 t => search all frames |
2447 nil => search just the current frame | |
2448 visible => search just visible frames | |
2449 0 => search visible and iconified frames | |
2450 a window => search the frame that window belongs to. */ | |
428 | 2451 |
2452 /* Do this loop at least once, to get the next window, and perhaps | |
2453 again, if we hit the minibuffer and that is not acceptable. */ | |
2454 do | |
2455 { | |
2456 /* Find a window that actually has a next one. This loop | |
2457 climbs up the tree. */ | |
2458 while (tem = XWINDOW (window)->next, NILP (tem)) | |
2459 if (tem = XWINDOW (window)->parent, !NILP (tem)) | |
2460 window = tem; | |
2461 else /* window must be minibuffer window now */ | |
2462 { | |
2463 /* We've reached the end of this frame. | |
2464 Which other frames are acceptable? */ | |
2465 tem = WINDOW_FRAME (XWINDOW (window)); | |
2466 | |
444 | 2467 if (! NILP (which_frames)) |
428 | 2468 { |
442 | 2469 Lisp_Object tem1 = tem; |
444 | 2470 tem = next_frame (tem, which_frames, which_devices); |
442 | 2471 |
428 | 2472 /* In the case where the minibuffer is active, |
2473 and we include its frame as well as the selected one, | |
2474 next_frame may get stuck in that frame. | |
2475 If that happens, go back to the selected frame | |
2476 so we can complete the cycle. */ | |
2477 if (EQ (tem, tem1)) | |
793 | 2478 tem = wrap_frame (selected_frame ()); |
428 | 2479 } |
2480 | |
2481 tem = FRAME_ROOT_WINDOW (XFRAME (tem)); | |
2482 break; | |
2483 } | |
2484 | |
2485 window = tem; | |
2486 | |
2487 /* If we're in a combination window, find its first child and | |
2488 recurse on that. Otherwise, we've found the window we want. */ | |
2489 while (1) | |
2490 { | |
2491 if (!NILP (XWINDOW (window)->hchild)) | |
2492 window = XWINDOW (window)->hchild; | |
2493 else if (!NILP (XWINDOW (window)->vchild)) | |
2494 window = XWINDOW (window)->vchild; | |
2495 else break; | |
2496 } | |
2497 } | |
2498 /* Which windows are acceptable? | |
2499 Exit the loop and accept this window if | |
2500 this isn't a minibuffer window, | |
2501 or we're accepting all minibuffer windows, | |
2502 or this is the active minibuffer and we are accepting that one, or | |
2503 we've come all the way around and we're back at the original window. */ | |
2504 while (MINI_WINDOW_P (XWINDOW (window)) | |
2505 && ! EQ (minibuf, Qt) | |
2506 && ! EQ (minibuf, window) | |
2507 && ! EQ (window, start_window)); | |
2508 | |
2509 return window; | |
2510 } | |
2511 | |
2512 DEFUN ("previous-window", Fprevious_window, 0, 4, 0, /* | |
442 | 2513 Return the window preceding WINDOW in the canonical ordering of windows. |
428 | 2514 If omitted, WINDOW defaults to the selected window. |
2515 | |
2516 Optional second arg MINIBUF t means count the minibuffer window even | |
2517 if not active. MINIBUF nil or omitted means count the minibuffer iff | |
2518 it is active. MINIBUF neither t nor nil means not to count the | |
2519 minibuffer even if it is active. | |
2520 | |
2521 Several frames may share a single minibuffer; if the minibuffer | |
2522 counts, all windows on all frames that share that minibuffer count | |
2523 too. Therefore, `previous-window' can be used to iterate through | |
2524 the set of windows even when the minibuffer is on another frame. If | |
442 | 2525 the minibuffer does not count, only windows from WINDOW's frame count. |
2526 | |
444 | 2527 By default, only the windows in the selected frame are considered. |
2528 The optional argument WHICH-FRAMES changes this behavior: | |
2529 WHICH-FRAMES = `visible' means search windows on all visible frames. | |
448 | 2530 WHICH-FRAMES = 0 means search windows on all visible and iconified frames. |
444 | 2531 WHICH-FRAMES = t means search windows on all frames including invisible frames. |
2532 WHICH-FRAMES = a frame means search only windows on that frame. | |
2533 Anything else means restrict to the selected frame. | |
2534 | |
2535 The optional fourth argument WHICH-DEVICES further clarifies on which | |
2536 devices to search for frames as specified by WHICH-FRAMES. This value | |
2537 is only meaningful if WHICH-FRAMES is non-nil. | |
2538 If nil or omitted, search all devices on the selected console. | |
2539 If a device, only search that device. | |
2540 If a console, search all devices on that console. | |
2541 If a device type, search all devices of that type. | |
2542 If `window-system', search all window-system devices. | |
2543 Any other non-nil value means search all devices. | |
2544 | |
2545 If you use consistent values for MINIBUF, WHICH-FRAMES, and WHICH-DEVICES, | |
2546 you can use `previous-window' to iterate through the entire cycle of | |
2547 acceptable windows, eventually ending up back at the window you started with. | |
428 | 2548 `next-window' traverses the same cycle, in the reverse order. |
2549 */ | |
444 | 2550 (window, minibuf, which_frames, devices)) |
428 | 2551 { |
2552 Lisp_Object tem; | |
2553 Lisp_Object start_window; | |
2554 | |
2555 if (NILP (window)) | |
2556 window = Fselected_window (Qnil); | |
2557 else | |
2558 CHECK_LIVE_WINDOW (window); | |
2559 | |
2560 start_window = window; | |
2561 | |
2562 /* minibuf == nil may or may not include minibuffers. | |
2563 Decide if it does. */ | |
2564 if (NILP (minibuf)) | |
2565 minibuf = (minibuf_level ? minibuf_window : Qlambda); | |
2566 else if (! EQ (minibuf, Qt)) | |
2567 minibuf = Qlambda; | |
442 | 2568 /* Now `minibuf' is one of: |
2569 t => count all minibuffer windows | |
2570 lambda => count none of them | |
428 | 2571 or a specific minibuffer window (the active one) to count. */ |
2572 | |
444 | 2573 /* which_frames == nil doesn't specify which frames to include. |
428 | 2574 Decide which frames it includes. */ |
444 | 2575 if (NILP (which_frames)) |
2576 which_frames = (! EQ (minibuf, Qlambda) | |
428 | 2577 ? (FRAME_MINIBUF_WINDOW |
2578 (XFRAME | |
2579 (WINDOW_FRAME | |
2580 (XWINDOW (window))))) | |
2581 : Qnil); | |
444 | 2582 else if (EQ (which_frames, Qvisible)) |
428 | 2583 ; |
444 | 2584 else if (ZEROP (which_frames)) |
428 | 2585 ; |
444 | 2586 else if (FRAMEP (which_frames) && ! EQ (which_frames, Fwindow_frame (window))) |
2587 /* If which_frames is a frame and window arg isn't on that frame, just | |
428 | 2588 return the first window on the frame. */ |
444 | 2589 return frame_first_window (XFRAME (which_frames)); |
2590 else if (! EQ (which_frames, Qt)) | |
2591 which_frames = Qnil; | |
2592 /* Now `which_frames' is one of: | |
442 | 2593 t => search all frames |
2594 nil => search just the current frame | |
2595 visible => search just visible frames | |
2596 0 => search visible and iconified frames | |
2597 a window => search the frame that window belongs to. */ | |
428 | 2598 |
2599 /* Do this loop at least once, to get the next window, and perhaps | |
2600 again, if we hit the minibuffer and that is not acceptable. */ | |
2601 do | |
2602 { | |
2603 /* Find a window that actually has a next one. This loop | |
2604 climbs up the tree. */ | |
2605 while (tem = XWINDOW (window)->prev, NILP (tem)) | |
2606 if (tem = XWINDOW (window)->parent, !NILP (tem)) | |
2607 window = tem; | |
2608 else /* window must be minibuffer window now */ | |
2609 { | |
2610 /* We have found the top window on the frame. | |
2611 Which frames are acceptable? */ | |
2612 tem = WINDOW_FRAME (XWINDOW (window)); | |
2613 | |
444 | 2614 if (! NILP (which_frames)) |
442 | 2615 /* It's actually important that we use previous_frame here, |
428 | 2616 rather than next_frame. All the windows acceptable |
2617 according to the given parameters should form a ring; | |
2618 Fnext_window and Fprevious_window should go back and | |
2619 forth around the ring. If we use next_frame here, | |
2620 then Fnext_window and Fprevious_window take different | |
2621 paths through the set of acceptable windows. | |
2622 window_loop assumes that these `ring' requirement are | |
2623 met. */ | |
2624 { | |
442 | 2625 Lisp_Object tem1 = tem; |
444 | 2626 tem = previous_frame (tem, which_frames, devices); |
428 | 2627 /* In the case where the minibuffer is active, |
2628 and we include its frame as well as the selected one, | |
2629 next_frame may get stuck in that frame. | |
2630 If that happens, go back to the selected frame | |
2631 so we can complete the cycle. */ | |
2632 if (EQ (tem, tem1)) | |
793 | 2633 tem = wrap_frame (selected_frame ()); |
428 | 2634 } |
2635 | |
2636 /* If this frame has a minibuffer, find that window first, | |
2637 because it is conceptually the last window in that frame. */ | |
2638 if (FRAME_HAS_MINIBUF_P (XFRAME (tem))) | |
2639 tem = FRAME_MINIBUF_WINDOW (XFRAME (tem)); | |
2640 else | |
2641 tem = FRAME_ROOT_WINDOW (XFRAME (tem)); | |
2642 | |
2643 break; | |
2644 } | |
2645 | |
2646 window = tem; | |
2647 | |
2648 /* If we're in a combination window, find its first child and | |
2649 recurse on that. Otherwise, we've found the window we want. */ | |
2650 while (1) | |
2651 { | |
2652 if (!NILP (XWINDOW (window)->hchild)) | |
2653 window = XWINDOW (window)->hchild; | |
2654 else if (!NILP (XWINDOW (window)->vchild)) | |
2655 window = XWINDOW (window)->vchild; | |
2656 else break; | |
2657 while (tem = XWINDOW (window)->next, !NILP (tem)) | |
2658 window = tem; | |
2659 } | |
2660 } | |
2661 /* Which windows are acceptable? | |
2662 Exit the loop and accept this window if | |
2663 this isn't a minibuffer window, | |
2664 or we're accepting all minibuffer windows, | |
2665 or this is the active minibuffer and we are accepting that one, or | |
2666 we've come all the way around and we're back at the original window. */ | |
2667 while (MINI_WINDOW_P (XWINDOW (window)) | |
2668 && ! EQ (minibuf, Qt) | |
2669 && ! EQ (minibuf, window) | |
2670 && ! EQ (window, start_window)); | |
2671 | |
2672 return window; | |
2673 } | |
2674 | |
2675 DEFUN ("next-vertical-window", Fnext_vertical_window, 0, 1, 0, /* | |
2676 Return the next window which is vertically after WINDOW. | |
2677 */ | |
2678 (window)) | |
2679 { | |
2680 Lisp_Object root; | |
2681 struct window *w = decode_window (window); | |
793 | 2682 window = wrap_window (w); |
428 | 2683 |
2684 if (MINI_WINDOW_P (XWINDOW (window))) | |
2685 return Qnil; | |
2686 | |
2687 root = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (XWINDOW (window)))); | |
2688 | |
2689 if (EQ (window, root)) | |
2690 { | |
2691 while (1) | |
2692 if (!NILP (XWINDOW (window)->hchild)) | |
2693 window = XWINDOW (window)->hchild; | |
2694 else if (!NILP (XWINDOW (window)->vchild)) | |
2695 window = XWINDOW (window)->vchild; | |
2696 else | |
2697 return window; | |
2698 } | |
2699 | |
2700 do | |
2701 { | |
2702 if (!NILP (XWINDOW (window)->parent) && | |
2703 !NILP (XWINDOW (XWINDOW (window)->parent)->vchild)) | |
2704 { | |
2705 if (!NILP (XWINDOW (window)->next)) | |
2706 return XWINDOW (window)->next; | |
2707 else | |
2708 window = XWINDOW (window)->parent; | |
2709 } | |
2710 else | |
2711 window = XWINDOW (window)->parent; | |
2712 } | |
2713 while (!EQ (window, root)); | |
2714 | |
2715 while (1) | |
2716 if (!NILP (XWINDOW (window)->hchild)) | |
2717 window = XWINDOW (window)->hchild; | |
2718 else if (!NILP (XWINDOW (window)->vchild)) | |
2719 window = XWINDOW (window)->vchild; | |
2720 else | |
2721 return window; | |
2722 } | |
2723 | |
2724 DEFUN ("other-window", Fother_window, 1, 3, "p", /* | |
444 | 2725 Select the COUNT'th different window on this frame. |
428 | 2726 All windows on current frame are arranged in a cyclic order. |
444 | 2727 This command selects the window COUNT steps away in that order. |
2728 A negative COUNT moves in the opposite order. | |
2729 | |
2730 By default, only the windows in the selected frame are considered. | |
2731 The optional argument WHICH-FRAMES changes this behavior: | |
2732 WHICH-FRAMES = `visible' means search windows on all visible frames. | |
448 | 2733 WHICH-FRAMES = 0 means search windows on all visible and iconified frames. |
444 | 2734 WHICH-FRAMES = t means search windows on all frames including invisible frames. |
2735 WHICH-FRAMES = a frame means search only windows on that frame. | |
2736 Anything else means restrict to the selected frame. | |
2737 | |
2738 The optional argument WHICH-DEVICES further clarifies on which devices | |
2739 to search for frames as specified by WHICH-FRAMES. This value is only | |
2740 meaningful if WHICH-FRAMES is non-nil. | |
2741 If nil or omitted, search all devices on the selected console. | |
2742 If a device, only search that device. | |
2743 If a console, search all devices on that console. | |
2744 If a device type, search all devices of that type. | |
2745 If `window-system', search all window-system devices. | |
2746 Any other non-nil value means search all devices. | |
428 | 2747 */ |
444 | 2748 (count, which_frames, which_devices)) |
428 | 2749 { |
2750 int i; | |
2751 Lisp_Object w; | |
2752 | |
444 | 2753 CHECK_INT (count); |
428 | 2754 w = Fselected_window (Qnil); |
444 | 2755 i = XINT (count); |
428 | 2756 |
2757 while (i > 0) | |
2758 { | |
444 | 2759 w = Fnext_window (w, Qnil, which_frames, which_devices); |
428 | 2760 i--; |
2761 } | |
2762 while (i < 0) | |
2763 { | |
444 | 2764 w = Fprevious_window (w, Qnil, which_frames, which_devices); |
428 | 2765 i++; |
2766 } | |
2767 Fselect_window (w, Qnil); | |
2768 return Qnil; | |
2769 } | |
2770 | |
2771 | |
2772 /* Look at all windows, performing an operation specified by TYPE | |
2773 with argument OBJ. | |
2774 | |
2775 If FRAMES is Qt, look at all frames, if Qnil, look at just the selected | |
2776 frame. If FRAMES is a frame, just look at windows on that frame. | |
2777 If MINI is non-zero, perform the operation on minibuffer windows too. | |
2778 */ | |
2779 | |
2780 enum window_loop | |
2781 { | |
2782 WINDOW_LOOP_UNUSED, | |
2783 GET_BUFFER_WINDOW, /* Arg is buffer */ | |
2784 GET_LRU_WINDOW, /* Arg is t for full-width windows only */ | |
2785 DELETE_OTHER_WINDOWS, /* Arg is window not to delete */ | |
2786 DELETE_BUFFER_WINDOWS, /* Arg is buffer */ | |
2787 GET_LARGEST_WINDOW, | |
2788 GET_BUFFER_WINDOW_COUNT, /* Arg is buffer */ | |
2789 GET_BUFFER_MRU_WINDOW /* Arg is buffer */ | |
2790 }; | |
2791 | |
2792 static Lisp_Object | |
2793 window_loop (enum window_loop type, | |
2794 Lisp_Object obj, | |
2795 int mini, | |
444 | 2796 Lisp_Object which_frames, |
428 | 2797 int dedicated_too, |
444 | 2798 Lisp_Object which_devices) |
428 | 2799 { |
448 | 2800 /* This function can GC if type == DELETE_BUFFER_WINDOWS */ |
428 | 2801 Lisp_Object w; |
2802 Lisp_Object best_window = Qnil; | |
2803 Lisp_Object next_window; | |
2804 Lisp_Object last_window; | |
2805 struct frame *frame; | |
2806 Lisp_Object frame_arg = Qt; | |
2807 int count = 0; /* for GET_BUFFER_WINDOW_COUNT */ | |
2808 /* #### I think the change of "precomputing" last_window and next_window | |
2809 * #### catch the lossage this is meant(?) to punt on... | |
2810 */ | |
2811 int lose_lose = 0; | |
2812 Lisp_Object devcons, concons; | |
2813 | |
2814 /* If we're only looping through windows on a particular frame, | |
2815 FRAME points to that frame. If we're looping through windows | |
2816 on all frames, FRAME is 0. */ | |
444 | 2817 if (FRAMEP (which_frames)) |
2818 frame = XFRAME (which_frames); | |
2819 else if (NILP (which_frames)) | |
428 | 2820 frame = selected_frame (); |
2821 else | |
2822 frame = 0; | |
442 | 2823 |
2824 /* FRAME_ARG is Qlambda to stick to one frame, | |
2825 Qvisible to consider all visible frames, | |
2826 or Qt otherwise. */ | |
428 | 2827 if (frame) |
2828 frame_arg = Qlambda; | |
444 | 2829 else if (ZEROP (which_frames)) |
2830 frame_arg = which_frames; | |
2831 else if (EQ (which_frames, Qvisible)) | |
2832 frame_arg = which_frames; | |
428 | 2833 |
2834 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
2835 { | |
2836 Lisp_Object device = XCAR (devcons); | |
2837 Lisp_Object the_frame; | |
2838 | |
2839 if (frame) | |
793 | 2840 the_frame = wrap_frame (frame); |
428 | 2841 else |
2842 the_frame = DEVICE_SELECTED_FRAME (XDEVICE (device)); | |
2843 | |
2844 if (NILP (the_frame)) | |
2845 continue; | |
2846 | |
444 | 2847 if (!device_matches_device_spec (device, |
2848 NILP (which_devices) ? | |
2849 FRAME_CONSOLE (XFRAME (the_frame)) : | |
2850 which_devices)) | |
428 | 2851 continue; |
2852 | |
2853 /* Pick a window to start with. */ | |
2854 if (WINDOWP (obj)) | |
2855 w = obj; | |
2856 else | |
2857 w = FRAME_SELECTED_WINDOW (XFRAME (the_frame)); | |
2858 | |
2859 /* Figure out the last window we're going to mess with. Since | |
2860 Fnext_window, given the same options, is guaranteed to go in a | |
2861 ring, we can just use Fprevious_window to find the last one. | |
2862 | |
2863 We can't just wait until we hit the first window again, | |
2864 because it might be deleted. */ | |
2865 | |
707 | 2866 last_window = Fprevious_window (w, mini ? Qt : Qnil, frame_arg, device); |
428 | 2867 |
2868 best_window = Qnil; | |
2869 for (;;) | |
2870 { | |
2871 struct window *p = XWINDOW (w); | |
2872 | |
2873 /* Pick the next window now, since some operations will delete | |
2874 the current window. */ | |
442 | 2875 next_window = Fnext_window (w, mini ? Qt : Qnil, frame_arg, device); |
428 | 2876 |
2877 /* #### Still needed ?? */ | |
2878 /* Given the outstanding quality of the rest of this code, | |
2879 I feel no shame about putting this piece of shit in. */ | |
2880 if (++lose_lose >= 500) | |
707 | 2881 { |
2500 | 2882 /* Call to ABORT() added by Darryl Okahata (16 Nov. 2001), |
707 | 2883 at Ben's request, to catch any remaining bugs. |
2884 | |
2885 If you find that XEmacs is aborting here, and you | |
2886 need to be up and running ASAP, it should be safe to | |
2500 | 2887 comment out the following ABORT(), as long as you |
707 | 2888 leave the "break;" alone. */ |
2500 | 2889 ABORT(); |
707 | 2890 break; /* <--- KEEP THIS HERE! Do not delete! */ |
2891 } | |
428 | 2892 |
2893 /* Note that we do not pay attention here to whether | |
2894 the frame is visible, since Fnext_window skips non-visible frames | |
2895 if that is desired, under the control of frame_arg. */ | |
2896 if (! MINI_WINDOW_P (p) | |
2897 || (mini && minibuf_level > 0)) | |
2898 switch (type) | |
2899 { | |
2900 case GET_BUFFER_WINDOW: | |
2901 { | |
2902 if (XBUFFER (p->buffer) == XBUFFER (obj)) | |
2903 return w; | |
2904 break; | |
2905 } | |
2906 | |
2907 case GET_BUFFER_WINDOW_COUNT: | |
2908 { | |
2909 if (XBUFFER (p->buffer) == XBUFFER (obj)) | |
2910 count++; | |
2911 break; | |
2912 } | |
2913 | |
2914 case GET_LRU_WINDOW: | |
2915 { | |
2916 /* t as arg means consider only full-width windows */ | |
2917 if (!NILP (obj) | |
2918 && !window_full_width_p (p)) | |
2919 break; | |
2920 /* Ignore dedicated windows and minibuffers. */ | |
2921 if (MINI_WINDOW_P (p) | |
2922 || (dedicated_too ? 0 : !NILP (p->dedicated))) | |
2923 break; | |
2924 if (NILP (best_window) | |
2925 || (XINT (XWINDOW (best_window)->use_time) | |
2926 > XINT (p->use_time))) | |
2927 best_window = w; | |
2928 break; | |
2929 } | |
2930 | |
2931 case GET_BUFFER_MRU_WINDOW: | |
2932 { | |
2933 /* #### what about the first check in GET_LRU_WINDOW? */ | |
2934 /* Ignore dedicated windows and minibuffers. */ | |
2935 if (MINI_WINDOW_P (p) | |
2936 || (dedicated_too ? 0 : !NILP (p->dedicated))) | |
2937 break; | |
2938 | |
2939 if (XBUFFER (p->buffer) == XBUFFER (obj)) | |
2940 { | |
2941 if (NILP (best_window) | |
2942 || (XINT (XWINDOW (best_window)->use_time) | |
2943 < XINT (p->use_time))) | |
2944 best_window = w; | |
2945 } | |
2946 break; | |
2947 } | |
2948 | |
2949 case DELETE_OTHER_WINDOWS: | |
2950 { | |
2951 /* Don't delete the last window on a frame; this can | |
2952 happen when the minibuffer is selected, and would | |
2953 cause the frame to be deleted. */ | |
2954 if (p != XWINDOW (obj) && !TOP_LEVEL_WINDOW_P (XWINDOW (w))) | |
2955 Fdelete_window (w, Qnil); | |
2956 break; | |
2957 } | |
2958 | |
2959 case DELETE_BUFFER_WINDOWS: | |
2960 { | |
2961 if (EQ (p->buffer, obj)) | |
2962 { | |
2963 struct frame *f = XFRAME (WINDOW_FRAME (p)); | |
2964 | |
2965 /* If this window is dedicated, and in a frame | |
2966 of its own, kill the frame. */ | |
2967 if (EQ (w, FRAME_ROOT_WINDOW (f)) | |
2968 && !NILP (p->dedicated) | |
1979 | 2969 && (allow_deletion_of_last_visible_frame |
2970 || other_visible_frames (f))) | |
428 | 2971 { |
2972 /* Skip the other windows on this frame. | |
2973 There might be one, the minibuffer! */ | |
2974 if (! EQ (w, last_window)) | |
2975 while (f == XFRAME (WINDOW_FRAME | |
2976 (XWINDOW (next_window)))) | |
2977 { | |
2978 /* As we go, check for the end of the | |
2979 loop. We mustn't start going | |
2980 around a second time. */ | |
2981 if (EQ (next_window, last_window)) | |
2982 { | |
2983 last_window = w; | |
2984 break; | |
2985 } | |
2986 next_window = Fnext_window (next_window, | |
2987 mini ? Qt : Qnil, | |
2988 frame_arg, Qt); | |
2989 } | |
2990 /* Now we can safely delete the frame. */ | |
2991 Fdelete_frame (WINDOW_FRAME (p), Qnil); | |
2992 } | |
2993 else | |
2994 /* If we're deleting the buffer displayed in | |
2995 the only window on the frame, find a new | |
2996 buffer to display there. */ | |
2997 if (NILP (p->parent)) | |
2998 { | |
2999 Lisp_Object new_buffer; | |
3000 new_buffer = Fother_buffer (obj, Qnil, Qnil); | |
3001 if (NILP (new_buffer)) | |
3002 new_buffer = Fget_buffer_create (QSscratch); | |
440 | 3003 Fset_window_buffer (w, new_buffer, Qnil); |
428 | 3004 if (EQ (w, Fselected_window (Qnil))) |
3005 Fset_buffer (p->buffer); | |
3006 } | |
3007 else | |
3008 Fdelete_window (w, Qnil); | |
3009 } | |
3010 break; | |
3011 } | |
3012 | |
3013 case GET_LARGEST_WINDOW: | |
3014 { | |
3015 /* Ignore dedicated windows and minibuffers. */ | |
3016 if (MINI_WINDOW_P (p) | |
3017 || (dedicated_too ? 0 : !NILP (p->dedicated))) | |
3018 break; | |
3019 { | |
3020 /* write the check as follows to avoid tripping | |
3021 error_check_window() --ben */ | |
3022 struct window *b = NILP (best_window) ? 0 : | |
3023 XWINDOW (best_window); | |
3024 if (NILP (best_window) | |
3025 || ((WINDOW_HEIGHT (p) * WINDOW_WIDTH (p)) | |
3026 > (WINDOW_HEIGHT (b) * WINDOW_WIDTH (b)))) | |
3027 best_window = w; | |
3028 } | |
3029 break; | |
3030 } | |
3031 | |
3032 default: | |
2500 | 3033 ABORT (); |
428 | 3034 } |
3035 | |
3036 if (EQ (w, last_window)) | |
3037 break; | |
3038 | |
3039 w = next_window; | |
3040 } | |
3041 } | |
3042 | |
3043 return type == GET_BUFFER_WINDOW_COUNT ? make_int (count) : best_window; | |
3044 } | |
3045 | |
3046 #if 0 /* not currently used */ | |
3047 | |
3048 int | |
3049 buffer_window_count (struct buffer *b, struct frame *f) | |
3050 { | |
3051 Lisp_Object buffer, frame; | |
3052 | |
793 | 3053 frame = wrap_frame (f); |
3054 buffer = wrap_buffer (b); | |
428 | 3055 |
3056 return XINT (window_loop (GET_BUFFER_WINDOW_COUNT, buffer, 0, frame, 1, | |
3057 Qnil)); | |
3058 } | |
3059 | |
3060 int | |
3061 buffer_window_mru (struct window *w) | |
3062 { | |
3063 Lisp_Object window = | |
3064 window_loop (GET_BUFFER_MRU_WINDOW, w->buffer, 0, w->frame, 1, Qnil); | |
3065 | |
3066 if (NILP (window)) | |
3067 return 0; | |
3068 else if (XWINDOW (window) == w) | |
3069 return 1; | |
3070 else | |
3071 return 0; | |
3072 } | |
3073 | |
3074 #endif | |
3075 | |
3076 | |
3077 DEFUN ("get-lru-window", Fget_lru_window, 0, 2, 0, /* | |
3078 Return the window least recently selected or used for display. | |
444 | 3079 |
3080 By default, only the windows in the selected frame are considered. | |
3081 The optional argument WHICH-FRAMES changes this behavior: | |
3082 If optional argument WHICH-FRAMES is `visible', search all visible frames. | |
3083 If WHICH-FRAMES is 0, search all visible and iconified frames. | |
3084 If WHICH-FRAMES is t, search all frames. | |
3085 If WHICH-FRAMES is nil, search only the selected frame. | |
3086 If WHICH-FRAMES is a frame, search only that frame. | |
3087 | |
3088 The optional argument WHICH-DEVICES further clarifies on which devices | |
3089 to search for frames as specified by WHICH-FRAMES. This value is only | |
3090 meaningful if WHICH-FRAMES is non-nil. | |
3091 If nil or omitted, search all devices on the selected console. | |
3092 If a device, only search that device. | |
3093 If a console, search all devices on that console. | |
3094 If a device type, search all devices of that type. | |
3095 If `window-system', search all devices on window-system consoles. | |
3096 Any other non-nil value means search all devices. | |
428 | 3097 */ |
444 | 3098 (which_frames, which_devices)) |
428 | 3099 { |
3100 Lisp_Object w; | |
3101 /* First try for a non-dedicated window that is full-width */ | |
444 | 3102 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 0, which_devices); |
428 | 3103 if (!NILP (w) && !EQ (w, Fselected_window (Qnil))) |
3104 return w; | |
3105 | |
3106 /* Then try for any non-dedicated window */ | |
444 | 3107 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 0, which_devices); |
428 | 3108 if (!NILP (w) && !EQ (w, Fselected_window (Qnil))) |
3109 return w; | |
3110 | |
3111 #if 0 | |
3112 /* FSFmacs never returns a dedicated window here. If we do, | |
3113 it makes `display-buffer' not work right. #### All of this | |
3114 shit is so disgusting and awful that it needs to be rethought | |
3115 from scratch. */ | |
3116 /* then try for a dedicated window that is full-width */ | |
444 | 3117 w = window_loop (GET_LRU_WINDOW, Qt, 0, which_frames, 1, which_devices); |
428 | 3118 if (!NILP (w) && !EQ (w, Fselected_window (Qnil))) |
3119 return w; | |
3120 | |
3121 /* If none of them, then all windows, dedicated or not. */ | |
444 | 3122 w = window_loop (GET_LRU_WINDOW, Qnil, 0, which_frames, 1, which_devices); |
428 | 3123 |
3124 /* At this point we damn well better have found something. */ | |
5050
6f2158fa75ed
Fix quick-build, use asserts() in place of ABORT()
Ben Wing <ben@xemacs.org>
parents:
4967
diff
changeset
|
3125 assert (!NILP (w)); |
428 | 3126 #endif |
3127 | |
3128 return w; | |
3129 } | |
3130 | |
3131 DEFUN ("get-largest-window", Fget_largest_window, 0, 2, 0, /* | |
3132 Return the window largest in area. | |
444 | 3133 |
3134 By default, only the windows in the selected frame are considered. | |
3135 The optional argument WHICH-FRAMES changes this behavior: | |
3136 If optional argument WHICH-FRAMES is `visible', search all visible frames. | |
3137 If WHICH-FRAMES is 0, search all visible and iconified frames. | |
3138 If WHICH-FRAMES is t, search all frames. | |
3139 If WHICH-FRAMES is nil, search only the selected frame. | |
3140 If WHICH-FRAMES is a frame, search only that frame. | |
3141 | |
3142 The optional argument WHICH-DEVICES further clarifies on which devices | |
3143 to search for frames as specified by WHICH-FRAMES. This value is only | |
3144 meaningful if WHICH-FRAMES is non-nil. | |
3145 If nil or omitted, search all devices on the selected console. | |
3146 If a device, only search that device. | |
3147 If a console, search all devices on that console. | |
3148 If a device type, search all devices of that type. | |
3149 If `window-system', search all devices on window-system consoles. | |
3150 Any other non-nil value means search all devices. | |
428 | 3151 */ |
444 | 3152 (which_frames, which_devices)) |
428 | 3153 { |
3154 /* Don't search dedicated windows because FSFmacs doesn't. | |
3155 This stuff is all black magic so don't try to apply common | |
3156 sense to it. */ | |
444 | 3157 return window_loop (GET_LARGEST_WINDOW, Qnil, 0, |
3158 which_frames, 0, which_devices); | |
428 | 3159 } |
3160 | |
3161 DEFUN ("get-buffer-window", Fget_buffer_window, 1, 3, 0, /* | |
3162 Return a window currently displaying BUFFER, or nil if none. | |
444 | 3163 |
3164 By default, only the windows in the selected frame are considered. | |
3165 The optional argument WHICH-FRAMES changes this behavior: | |
3166 If optional argument WHICH-FRAMES is `visible', search all visible frames. | |
3167 If WHICH-FRAMES is 0, search all visible and iconified frames. | |
3168 If WHICH-FRAMES is t, search all frames. | |
3169 If WHICH-FRAMES is nil, search only the selected frame. | |
3170 If WHICH-FRAMES is a frame, search only that frame. | |
3171 | |
3172 The optional argument WHICH-DEVICES further clarifies on which devices | |
3173 to search for frames as specified by WHICH-FRAMES. This value is only | |
3174 meaningful if WHICH-FRAMES is non-nil. | |
3175 If nil or omitted, search all devices on the selected console. | |
3176 If a device, only search that device. | |
3177 If a console, search all devices on that console. | |
3178 If a device type, search all devices of that type. | |
3179 If `window-system', search all devices on window-system consoles. | |
3180 Any other non-nil value means search all devices. | |
428 | 3181 */ |
444 | 3182 (buffer, which_frames, which_devices)) |
428 | 3183 { |
3184 buffer = Fget_buffer (buffer); | |
3185 if (BUFFERP (buffer)) | |
3186 /* Search dedicated windows too. (Doesn't matter here anyway.) */ | |
444 | 3187 return window_loop (GET_BUFFER_WINDOW, buffer, 1, |
3188 which_frames, 1, which_devices); | |
428 | 3189 else |
3190 return Qnil; | |
3191 } | |
3192 | |
3193 /* These functions used to be `buffer-left-margin-pixel-width', etc. | |
3194 but there is no sensible way to implement those functions, since | |
3195 you can't in general derive a window from a buffer. */ | |
3196 | |
3197 DEFUN ("window-left-margin-pixel-width", Fwindow_left_margin_pixel_width, | |
3198 0, 1, 0, /* | |
3199 Return the width in pixels of the left outside margin of window WINDOW. | |
3200 If WINDOW is nil, the selected window is assumed. | |
3201 */ | |
3202 (window)) | |
3203 { | |
3204 return make_int (window_left_margin_width (decode_window (window))); | |
3205 } | |
3206 | |
3207 DEFUN ("window-right-margin-pixel-width", Fwindow_right_margin_pixel_width, | |
3208 0, 1, 0, /* | |
3209 Return the width in pixels of the right outside margin of window WINDOW. | |
3210 If WINDOW is nil, the selected window is assumed. | |
3211 */ | |
3212 (window)) | |
3213 { | |
3214 return make_int (window_right_margin_width (decode_window (window))); | |
3215 } | |
3216 | |
3217 DEFUN ("delete-other-windows", Fdelete_other_windows, 0, 1, "", /* | |
3218 Make WINDOW (or the selected window) fill its frame. | |
3219 Only the frame WINDOW is on is affected. | |
3220 This function tries to reduce display jumps | |
3221 by keeping the text previously visible in WINDOW | |
3222 in the same place on the frame. Doing this depends on | |
3223 the value of (window-start WINDOW), so if calling this function | |
3224 in a program gives strange scrolling, make sure the window-start | |
3225 value is reasonable when this function is called. | |
3226 */ | |
3227 (window)) | |
3228 { | |
3229 struct window *w = decode_window (window); | |
1207 | 3230 struct buffer *b; |
665 | 3231 Charbpos start_pos; |
428 | 3232 int old_top = WINDOW_TOP (w); |
3233 | |
1207 | 3234 if (NILP (WINDOW_BUFFER (w))) |
3235 invalid_operation ("Can't delete other windows of combination", window); | |
3236 | |
793 | 3237 window = wrap_window (w); |
1207 | 3238 b = XBUFFER (WINDOW_BUFFER (w)); |
428 | 3239 |
3240 if (MINI_WINDOW_P (w) && old_top > 0) | |
563 | 3241 invalid_operation ("Can't expand minibuffer to full frame", Qunbound); |
428 | 3242 |
3243 /* Ignore dedicated windows. */ | |
3244 window_loop (DELETE_OTHER_WINDOWS, window, 0, w->frame, 0, Qnil); | |
3245 | |
3246 start_pos = marker_position (w->start[CURRENT_DISP]); | |
3247 | |
3248 /* Try to minimize scrolling, by setting the window start to the | |
3249 point which will cause the text at the old window start to be at | |
3250 the same place on the frame. But don't try to do this if the | |
3251 window start is outside the visible portion (as might happen when | |
3252 the display is not current, due to typeahead). */ | |
3253 if (start_pos >= BUF_BEGV (b) && start_pos <= BUF_ZV (b) | |
3254 && !MINI_WINDOW_P (w)) | |
3255 { | |
665 | 3256 Charbpos new_start = start_with_line_at_pixpos (w, start_pos, old_top); |
428 | 3257 |
3258 if (new_start >= BUF_BEGV (b) && new_start <= BUF_ZV (b)) | |
3259 { | |
3260 Fset_marker (w->start[CURRENT_DISP], make_int (new_start), | |
3261 w->buffer); | |
3262 w->start_at_line_beg = beginning_of_line_p (b, new_start); | |
3263 } | |
3264 /* We need to do this, so that the window-scroll-functions | |
3265 get called. */ | |
3266 w->force_start = 1; | |
3267 } | |
3268 | |
3269 return Qnil; | |
3270 } | |
3271 | |
3272 DEFUN ("delete-windows-on", Fdelete_windows_on, 1, 3, | |
3273 "bDelete windows on (buffer): ", /* | |
3274 Delete all windows showing BUFFER. | |
444 | 3275 |
3276 Optional second argument WHICH-FRAMES controls which frames are affected. | |
428 | 3277 If nil or omitted, delete all windows showing BUFFER in any frame. |
3278 If t, delete only windows showing BUFFER in the selected frame. | |
3279 If `visible', delete all windows showing BUFFER in any visible frame. | |
3280 If a frame, delete only windows showing BUFFER in that frame. | |
444 | 3281 Warning: WHICH-FRAMES has the same meaning as with `next-window', |
3282 except that the meanings of nil and t are reversed. | |
3283 | |
3284 The optional third argument WHICH-DEVICES further clarifies on which | |
3285 devices to search for frames as specified by WHICH-FRAMES. This value | |
3286 is only meaningful if WHICH-FRAMES is not t. | |
3287 If nil or omitted, search only the selected console. | |
3288 If a device, only search that device. | |
3289 If a console, search all devices on that console. | |
3290 If a device type, search all devices of that type. | |
3291 If `window-system', search all devices on a window system. | |
3292 Any other non-nil value means search all devices. | |
428 | 3293 */ |
444 | 3294 (buffer, which_frames, which_devices)) |
428 | 3295 { |
3296 /* This function can GC */ | |
444 | 3297 buffer = Fget_buffer (buffer); |
3298 CHECK_BUFFER (buffer); | |
3299 | |
3300 /* WHICH-FRAMES values t and nil mean the opposite of what | |
3301 window_loop expects. */ | |
3302 if (EQ (which_frames, Qnil)) | |
3303 which_frames = Qt; | |
3304 else if (EQ (which_frames, Qt)) | |
3305 which_frames = Qnil; | |
3306 | |
3307 /* Ignore dedicated windows. */ | |
3308 window_loop (DELETE_BUFFER_WINDOWS, buffer, 0, | |
3309 which_frames, 0, which_devices); | |
428 | 3310 return Qnil; |
3311 } | |
3312 | |
448 | 3313 static Lisp_Object |
3314 list_windows (struct window *w, Lisp_Object value) | |
3315 { | |
3316 for (;;) | |
3317 { | |
3318 if (!NILP (w->hchild)) | |
3319 value = list_windows (XWINDOW (w->hchild), value); | |
3320 else if (!NILP (w->vchild)) | |
3321 value = list_windows (XWINDOW (w->vchild), value); | |
3322 else | |
3323 { | |
793 | 3324 Lisp_Object window = wrap_window (w); |
3325 | |
448 | 3326 value = Fcons (window, value); |
3327 } | |
3328 if (NILP (w->next)) | |
3329 break; | |
3330 w = XWINDOW (w->next); | |
3331 } | |
3332 return value; | |
3333 } | |
3334 | |
3335 static Lisp_Object | |
3336 list_all_windows (Lisp_Object frame_spec, Lisp_Object device_spec) | |
3337 { | |
3338 Lisp_Object devcons, concons; | |
3339 Lisp_Object retval = Qnil; | |
3340 | |
3341 DEVICE_LOOP_NO_BREAK (devcons, concons) | |
3342 { | |
3343 Lisp_Object frame_list, the_window; | |
3344 Lisp_Object device, tail; | |
3345 | |
3346 device = XCAR (devcons); | |
3347 frame_list = DEVICE_FRAME_LIST (XDEVICE (device)); | |
3348 | |
3349 LIST_LOOP (tail, frame_list) | |
3350 { | |
3351 if ((NILP (frame_spec) | |
3352 && !EQ (XCAR (tail), DEVICE_SELECTED_FRAME (XDEVICE (device)))) | |
3353 || (EQ (frame_spec, Qvisible) | |
3354 && !FRAME_VISIBLE_P (XFRAME (XCAR (tail)))) | |
3355 || (FRAMEP (frame_spec) | |
3356 && !EQ (frame_spec, XCAR (tail))) | |
3357 || (!NILP (frame_spec) | |
3358 && !device_matches_device_spec (device, | |
3359 NILP (device_spec) ? | |
3360 Vselected_console : | |
3361 device_spec))) | |
3362 continue; | |
3363 the_window = FRAME_ROOT_WINDOW (XFRAME (XCAR (tail))); | |
3364 retval = list_windows (XWINDOW (the_window), retval); | |
3365 } | |
3366 } | |
3367 return Fnreverse (retval); | |
3368 } | |
3369 | |
444 | 3370 DEFUN ("replace-buffer-in-windows", Freplace_buffer_in_windows, 1, 3, |
428 | 3371 "bReplace buffer in windows: ", /* |
3372 Replace BUFFER with some other buffer in all windows showing it. | |
444 | 3373 |
3374 Optional second argument WHICH-FRAMES controls which frames are affected. | |
3375 If nil or omitted, all frames are affected. | |
3376 If t, only the selected frame is affected. | |
3377 If `visible', all visible frames are affected. | |
3378 If a frame, only that frame is affected. | |
3379 Warning: WHICH-FRAMES has the same meaning as with `next-window', | |
3380 except that the meanings of nil and t are reversed. | |
3381 | |
3382 The optional third argument WHICH-DEVICES further clarifies on which | |
3383 devices to search for frames as specified by WHICH-FRAMES. This value | |
3384 is only meaningful if WHICH-FRAMES is not t. | |
3385 If nil or omitted, search only the selected console. | |
3386 If a device, only search that device. | |
3387 If a console, search all devices on that console. | |
3388 If a device type, search all devices of that type. | |
3389 If `window-system', search all devices on a window system. | |
3390 Any other non-nil value means search all devices. | |
428 | 3391 */ |
444 | 3392 (buffer, which_frames, which_devices)) |
428 | 3393 { |
3394 /* This function can GC */ | |
448 | 3395 Lisp_Object window_list; |
3396 Lisp_Object tail; | |
3397 struct gcpro gcpro1, gcpro2; | |
3398 | |
444 | 3399 if (EQ (which_frames, Qnil)) |
3400 which_frames = Qt; | |
3401 else if (EQ (which_frames, Qt)) | |
3402 which_frames = Qnil; | |
448 | 3403 window_list = list_all_windows (which_frames, which_devices); |
3404 | |
3405 buffer = Fget_buffer (buffer); | |
3406 CHECK_BUFFER (buffer); | |
3407 | |
3408 GCPRO2 (window_list, buffer); | |
3409 LIST_LOOP (tail, window_list) | |
3410 { | |
3411 Lisp_Object window = XCAR (tail); | |
3412 if (!MINI_WINDOW_P (XWINDOW (window)) | |
3413 && EQ (XWINDOW (window)->buffer, buffer)) | |
3414 { | |
3415 Lisp_Object another_buffer = Fother_buffer (buffer, Qnil, Qnil); | |
3416 Lisp_Object frame = WINDOW_FRAME (XWINDOW (window)); | |
3417 if (NILP (another_buffer)) | |
3418 another_buffer = Fget_buffer_create (QSscratch); | |
3419 if (!NILP (XWINDOW (window)->dedicated) | |
3420 && EQ (window, | |
3421 FRAME_ROOT_WINDOW (XFRAME (frame))) | |
1979 | 3422 && (allow_deletion_of_last_visible_frame |
3423 || other_visible_frames (XFRAME (frame)))) | |
448 | 3424 { |
3425 delete_frame_internal (XFRAME (frame), 0, 0, 0); /* GC */ | |
3426 } | |
3427 else | |
3428 { | |
3429 Fset_window_buffer (window, another_buffer, Qnil); | |
3430 if (EQ (window, Fselected_window (Qnil))) | |
3431 Fset_buffer (XWINDOW (window)->buffer); | |
3432 } | |
3433 } | |
3434 } | |
3435 UNGCPRO; | |
428 | 3436 return Qnil; |
3437 } | |
3438 | |
3439 /* The smallest acceptable dimensions for a window. Anything smaller | |
3440 might crash Emacs. */ | |
3441 #define MIN_SAFE_WINDOW_WIDTH (2) | |
3442 #define MIN_SAFE_WINDOW_HEIGHT (2) | |
3443 | |
3444 /* Make sure that window_min_height and window_min_width are | |
3445 not too small; if they are, set them to safe minima. */ | |
3446 | |
3447 static void | |
3448 check_min_window_sizes (void) | |
3449 { | |
3450 /* Smaller values might permit a crash. */ | |
3451 if (window_min_width < MIN_SAFE_WINDOW_WIDTH) | |
3452 window_min_width = MIN_SAFE_WINDOW_WIDTH; | |
3453 if (window_min_height < MIN_SAFE_WINDOW_HEIGHT) | |
3454 window_min_height = MIN_SAFE_WINDOW_HEIGHT; | |
3455 } | |
3456 | |
440 | 3457 static int |
3458 frame_min_height (struct frame *frame) | |
3459 { | |
3460 /* For height, we have to see whether the frame has a minibuffer, and | |
3461 whether it wants a modeline. */ | |
3462 return (FRAME_MINIBUF_ONLY_P (frame) ? MIN_SAFE_WINDOW_HEIGHT - 1 | |
3463 : (! FRAME_HAS_MINIBUF_P (frame)) ? MIN_SAFE_WINDOW_HEIGHT | |
3464 : 2 * MIN_SAFE_WINDOW_HEIGHT - 1); | |
3465 } | |
3466 | |
3467 /* Return non-zero if both frame sizes are less than or equal to | |
3468 minimal allowed values. ROWS and COLS are in characters */ | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
3469 static int |
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
3470 frame_size_valid_p (struct frame *frame, int cols, int rows) |
440 | 3471 { |
3472 return (rows >= frame_min_height (frame) | |
3473 && cols >= MIN_SAFE_WINDOW_WIDTH); | |
3474 } | |
3475 | |
3476 /* Return non-zero if both frame sizes are less than or equal to | |
3477 minimal allowed values. WIDTH and HEIGHT are in pixels */ | |
3478 int | |
3479 frame_pixsize_valid_p (struct frame *frame, int width, int height) | |
3480 { | |
3481 int rows, cols; | |
5043 | 3482 pixel_to_char_size (frame, width, height, &cols, &rows); |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
3483 return frame_size_valid_p (frame, cols, rows); |
440 | 3484 } |
3485 | |
428 | 3486 /* If *ROWS or *COLS are too small a size for FRAME, set them to the |
3487 minimum allowable size. */ | |
3488 void | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
3489 check_frame_size (struct frame *frame, int *cols, int *rows) |
428 | 3490 { |
440 | 3491 int min_height = frame_min_height (frame); |
5043 | 3492 int min_pixwidth, min_pixheight; |
3493 int min_geomwidth, min_geomheight; | |
3494 | |
3495 /* There is no char_to_frame_unit_size(). This can be done with | |
3496 frame_conversion_internal(), but that's currently static, and we can | |
3497 do it fine with two steps, as follows. */ | |
3498 char_to_pixel_size (frame, MIN_SAFE_WINDOW_WIDTH, min_height, | |
3499 &min_pixwidth, &min_pixheight); | |
3500 pixel_to_frame_unit_size (frame, min_pixwidth, min_pixheight, | |
3501 &min_geomwidth, &min_geomheight); | |
3502 if (*rows < min_geomheight) | |
3503 *rows = min_geomheight; | |
3504 if (*cols < min_geomwidth) | |
3505 *cols = min_geomwidth; | |
428 | 3506 } |
3507 | |
3508 /* Normally the window is deleted if it gets too small. | |
3509 nodelete nonzero means do not do this. | |
3510 (The caller should check later and do so if appropriate) */ | |
3511 static void | |
3512 set_window_pixsize (Lisp_Object window, int new_pixsize, int nodelete, | |
3513 int set_height) | |
3514 { | |
3515 struct window *w = XWINDOW (window); | |
3516 struct frame *f = XFRAME (w->frame); | |
3517 struct window *c; | |
3518 int old_pixsize = (set_height ? WINDOW_HEIGHT (w) : WINDOW_WIDTH (w)); | |
3519 Lisp_Object child, minor_kid, major_kid; | |
3520 int minsize; | |
3521 int line_size; | |
3522 int defheight, defwidth; | |
3523 | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
3524 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 3525 line_size = (set_height ? defheight : defwidth); |
3526 | |
3527 check_min_window_sizes (); | |
3528 | |
3529 minsize = (set_height ? window_min_height : window_min_width); | |
3530 minsize *= line_size; | |
3531 | |
3532 if (!nodelete | |
3533 && !TOP_LEVEL_WINDOW_P (w) | |
4375
74e0e1131e01
Update window-size computation.
Mike Sperber <sperber@deinprogramm.de>
parents:
3707
diff
changeset
|
3534 && (new_pixsize + window_modeline_height (w)) < minsize) |
428 | 3535 { |
3536 Fdelete_window (window, Qnil); | |
3537 return; | |
3538 } | |
3539 | |
3540 SET_LAST_MODIFIED (w, 0); | |
3541 SET_LAST_FACECHANGE (w); | |
3542 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* multiple windows affected */ | |
3543 if (set_height) | |
3544 { | |
3545 WINDOW_HEIGHT (w) = new_pixsize; | |
3546 major_kid = w->vchild; | |
3547 minor_kid = w->hchild; | |
3548 } | |
3549 else | |
3550 { | |
3551 WINDOW_WIDTH (w) = new_pixsize; | |
3552 major_kid = w->hchild; | |
3553 minor_kid = w->vchild; | |
3554 } | |
3555 | |
3556 if (!NILP (minor_kid)) | |
3557 { | |
3558 for (child = minor_kid; !NILP (child); child = XWINDOW (child)->next) | |
3559 { | |
3560 if (set_height) | |
3561 WINDOW_TOP (XWINDOW (child)) = WINDOW_TOP (w); | |
3562 else | |
3563 WINDOW_LEFT (XWINDOW (child)) = WINDOW_LEFT (w); | |
3564 | |
3565 set_window_pixsize (child, new_pixsize, nodelete, set_height); | |
3566 } | |
3567 } | |
3568 else if (!NILP (major_kid)) | |
3569 { | |
3570 int last_pos, last_old_pos, pos, old_pos, first; | |
3571 int pixel_adj_left = new_pixsize - old_pixsize; | |
3572 int div_val = old_pixsize << 1; | |
3573 | |
3574 /* | |
3575 * Previously we bailed out here if there was no size change. | |
3576 * (pixel_adj_left == 0) But this broke toolbar updates. If a | |
3577 * toolbar appears or disappears, windows may not change size, | |
3578 * but their top and left coordinates need to be updated. | |
3579 * | |
3580 * So we don't bail until after the loop below. | |
3581 */ | |
3582 | |
3583 last_pos = first = (set_height ? WINDOW_TOP (w) : WINDOW_LEFT (w)); | |
3584 last_old_pos = 0; | |
3585 | |
3586 for (child = major_kid; !NILP (child); child = c->next) | |
3587 { | |
3588 c = XWINDOW (child); | |
3589 | |
3590 if (set_height) | |
3591 { | |
3592 old_pos = last_old_pos + WINDOW_HEIGHT (c); | |
3593 WINDOW_TOP (c) = last_pos; | |
3594 } | |
3595 else | |
3596 { | |
3597 old_pos = last_old_pos + WINDOW_WIDTH (c); | |
3598 WINDOW_LEFT (c) = last_pos; | |
3599 } | |
3600 | |
3601 pos = (((old_pos * new_pixsize) << 1) + old_pixsize) / div_val; | |
3602 /* All but the last window should have a height which is | |
3603 a multiple of the default line height. */ | |
3604 if (!NILP (c->next)) | |
4446
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3605 { |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3606 /* |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3607 * Round up when we're shrinking, down when we're growing |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3608 * to make sure that pairs of grow / shrink meant to |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3609 * cancel out actually do cancel out. |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3610 */ |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3611 if (pixel_adj_left < 0) |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3612 pos = ((pos + line_size -1) / line_size) * line_size; |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3613 else |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3614 pos = (pos / line_size) * line_size; |
c32b3d10c56b
Fix problem with `resize-minibuffer-mode'.
Mike Sperber <sperber@deinprogramm.de>
parents:
4375
diff
changeset
|
3615 } |
428 | 3616 |
3617 /* Avoid confusion: don't delete child if it becomes too small */ | |
3618 set_window_pixsize (child, pos + first - last_pos, 1, set_height); | |
3619 | |
3620 last_pos = pos + first; | |
3621 last_old_pos = old_pos; | |
3622 } | |
3623 | |
3624 /* Sometimes we may get called with our old size. In that case | |
3625 we don't need to do anything else. */ | |
3626 if (!pixel_adj_left) | |
3627 return; | |
3628 | |
3629 /* Now delete any children that became too small. */ | |
3630 if (!nodelete) | |
3631 for (child = major_kid; !NILP (child); child = XWINDOW (child)->next) | |
3632 { | |
3633 if (set_height) | |
3634 set_window_pixheight (child, WINDOW_HEIGHT (XWINDOW (child)), 0); | |
3635 else | |
3636 set_window_pixwidth (child, WINDOW_WIDTH (XWINDOW (child)), 0); | |
3637 } | |
3638 } | |
3639 } | |
3640 | |
3641 /* Set the height of WINDOW and all its inferiors. */ | |
3642 void | |
3643 set_window_pixheight (Lisp_Object window, int new_pixheight, int nodelete) | |
3644 { | |
3645 set_window_pixsize (window, new_pixheight, nodelete, 1); | |
3646 } | |
3647 | |
3648 /* Recursively set width of WINDOW and its inferiors. */ | |
3649 void | |
3650 set_window_pixwidth (Lisp_Object window, int new_pixwidth, int nodelete) | |
3651 { | |
3652 set_window_pixsize (window, new_pixwidth, nodelete, 0); | |
3653 } | |
3654 | |
3655 | |
3656 static int window_select_count; | |
3657 | |
440 | 3658 DEFUN ("set-window-buffer", Fset_window_buffer, 2, 3, 0, /* |
428 | 3659 Make WINDOW display BUFFER as its contents. |
3660 BUFFER can be a buffer or buffer name. | |
440 | 3661 |
442 | 3662 With non-nil optional argument NORECORD, do not modify the |
440 | 3663 global or per-frame buffer ordering. |
428 | 3664 */ |
440 | 3665 (window, buffer, norecord)) |
428 | 3666 { |
3667 Lisp_Object tem; | |
3668 struct window *w = decode_window (window); | |
448 | 3669 int old_buffer_local_face_property = 0; |
428 | 3670 |
3671 buffer = Fget_buffer (buffer); | |
3672 CHECK_BUFFER (buffer); | |
3673 | |
3674 if (!BUFFER_LIVE_P (XBUFFER (buffer))) | |
563 | 3675 invalid_operation ("Attempt to display deleted buffer", Qunbound); |
428 | 3676 |
3677 tem = w->buffer; | |
3678 if (NILP (tem)) | |
563 | 3679 invalid_operation ("Window is deleted", Qunbound); |
428 | 3680 else if (EQ (tem, buffer)) |
3681 return Qnil; | |
3682 else if (! EQ (tem, Qt)) /* w->buffer is t when the window | |
3683 is first being set up. */ | |
3684 { | |
3685 if (!NILP (w->dedicated) && !EQ (tem, buffer)) | |
563 | 3686 signal_error (Qinvalid_operation, "Window is dedicated to buffer", tem); |
428 | 3687 |
448 | 3688 old_buffer_local_face_property = |
3689 XBUFFER (w->buffer)->buffer_local_face_property; | |
428 | 3690 unshow_buffer (w); |
3691 } | |
3692 | |
3693 w->buffer = buffer; | |
3694 w->window_end_pos[CURRENT_DISP] = 0; | |
3695 w->hscroll = 0; | |
3696 w->modeline_hscroll = 0; | |
844 | 3697 #if 0 /* pre point caches */ |
428 | 3698 Fset_marker (w->pointm[CURRENT_DISP], |
3699 make_int (BUF_PT (XBUFFER (buffer))), | |
3700 buffer); | |
3701 set_marker_restricted (w->start[CURRENT_DISP], | |
3702 make_int (XBUFFER (buffer)->last_window_start), | |
3703 buffer); | |
844 | 3704 #else |
3705 { | |
3706 Lisp_Object marker = Fgethash (buffer, w->saved_point_cache, Qnil); | |
3707 Lisp_Object newpoint = | |
3708 !NILP (marker) ? make_int (marker_position (marker)) : | |
3709 make_int (BUF_PT (XBUFFER (buffer))); | |
3710 /* Previously, we had in here set-window-point, which did one of the | |
3711 following two, but not both. However, that could result in pointm | |
3712 being in a different buffer from the window's buffer! Probably | |
3713 not a travesty since it always occurred when the window was | |
3714 selected, meaning its value of point was ignored in favor of the | |
3715 buffer's; but it tripped an assert() in unshow_buffer(). */ | |
3716 set_marker_restricted (w->pointm[CURRENT_DISP], newpoint, buffer); | |
3717 if (EQ (wrap_window (w), Fselected_window (Qnil))) | |
3718 Fgoto_char (newpoint, buffer); /* this will automatically clip to | |
3719 accessible */ | |
3720 marker = Fgethash (buffer, w->saved_last_window_start_cache, Qnil); | |
3721 set_marker_restricted (w->start[CURRENT_DISP], | |
3722 !NILP (marker) ? | |
3723 make_int (marker_position (marker)) : | |
3724 make_int (XBUFFER (buffer)->last_window_start), | |
3725 buffer); | |
3726 } | |
3727 #endif | |
3728 | |
428 | 3729 Fset_marker (w->sb_point, w->start[CURRENT_DISP], buffer); |
3730 /* set start_at_line_beg correctly. GE */ | |
844 | 3731 w->start_at_line_beg = |
3732 beginning_of_line_p (XBUFFER (buffer), | |
3733 marker_position (w->start[CURRENT_DISP])); | |
3734 w->force_start = 0; /* XEmacs fix */ | |
428 | 3735 SET_LAST_MODIFIED (w, 1); |
3736 SET_LAST_FACECHANGE (w); | |
3737 MARK_WINDOWS_CHANGED (w); | |
448 | 3738 { |
3739 int new_buffer_local_face_property = | |
3740 XBUFFER (w->buffer)->buffer_local_face_property; | |
3741 | |
3742 if (new_buffer_local_face_property | |
3743 || new_buffer_local_face_property != old_buffer_local_face_property) | |
3744 MARK_WINDOW_FACES_CHANGED (w); | |
3745 } | |
428 | 3746 recompute_all_cached_specifiers_in_window (w); |
3747 if (EQ (window, Fselected_window (Qnil))) | |
3748 { | |
440 | 3749 if (NILP (norecord)) |
3750 Frecord_buffer (buffer); | |
3751 | |
428 | 3752 Fset_buffer (buffer); |
3753 } | |
3754 return Qnil; | |
3755 } | |
3756 | |
3757 DEFUN ("select-window", Fselect_window, 1, 2, 0, /* | |
3758 Select WINDOW. Most editing will apply to WINDOW's buffer. | |
3759 The main editor command loop selects the buffer of the selected window | |
3760 before each command. | |
3761 | |
442 | 3762 With non-nil optional argument NORECORD, do not modify the |
428 | 3763 global or per-frame buffer ordering. |
3764 */ | |
3765 (window, norecord)) | |
3766 { | |
3767 struct window *w; | |
3768 Lisp_Object old_selected_window = Fselected_window (Qnil); | |
3769 | |
3770 CHECK_LIVE_WINDOW (window); | |
3771 w = XWINDOW (window); | |
3772 | |
3773 /* we have already caught dead-window errors */ | |
3774 if (!NILP (w->hchild) || !NILP (w->vchild)) | |
563 | 3775 invalid_operation ("Trying to select non-leaf window", Qunbound); |
428 | 3776 |
3777 w->use_time = make_int (++window_select_count); | |
442 | 3778 |
428 | 3779 if (EQ (window, old_selected_window)) |
3780 return window; | |
3781 | |
3782 /* deselect the old window, if it exists (it might not exist if | |
3783 the selected device has no frames, which occurs at startup) */ | |
3784 if (!NILP (old_selected_window)) | |
3785 { | |
3786 struct window *ow = XWINDOW (old_selected_window); | |
3787 | |
3788 Fset_marker (ow->pointm[CURRENT_DISP], | |
3789 make_int (BUF_PT (XBUFFER (ow->buffer))), | |
3790 ow->buffer); | |
3791 | |
3792 MARK_WINDOWS_CHANGED (ow); | |
3793 } | |
3794 | |
3795 /* now select the window's frame */ | |
3796 set_frame_selected_window (XFRAME (WINDOW_FRAME (w)), window); | |
3797 | |
3798 select_frame_1 (WINDOW_FRAME (w)); | |
3799 | |
3800 /* also select the window's buffer */ | |
3801 if (NILP (norecord)) | |
3802 Frecord_buffer (w->buffer); | |
3803 Fset_buffer (w->buffer); | |
3804 | |
3805 /* Go to the point recorded in the window. | |
3806 This is important when the buffer is in more | |
3807 than one window. It also matters when | |
3808 redisplay_window has altered point after scrolling, | |
3809 because it makes the change only in the window. */ | |
3810 { | |
665 | 3811 Charbpos new_point = marker_position (w->pointm[CURRENT_DISP]); |
428 | 3812 if (new_point < BUF_BEGV (current_buffer)) |
3813 new_point = BUF_BEGV (current_buffer); | |
3814 else if (new_point > BUF_ZV (current_buffer)) | |
3815 new_point = BUF_ZV (current_buffer); | |
3816 | |
3817 BUF_SET_PT (current_buffer, new_point); | |
3818 } | |
3819 | |
3820 MARK_WINDOWS_CHANGED (w); | |
3821 | |
3822 return window; | |
3823 } | |
3824 | |
3825 Lisp_Object | |
3826 display_buffer (Lisp_Object buffer, Lisp_Object not_this_window_p, | |
3827 Lisp_Object override_frame) | |
3828 { | |
3829 return call3 (Qdisplay_buffer, buffer, not_this_window_p, override_frame); | |
3830 } | |
3831 | |
3832 void | |
3833 temp_output_buffer_show (Lisp_Object buf, Lisp_Object same_frame) | |
3834 { | |
3835 /* This function can GC */ | |
3836 Lisp_Object window; | |
3837 struct window *w; | |
3838 struct buffer *b = XBUFFER (buf); | |
3839 | |
3840 BUF_SAVE_MODIFF (XBUFFER (buf)) = BUF_MODIFF (b); | |
3841 widen_buffer (b, 0); | |
3842 BUF_SET_PT (b, BUF_BEG (b)); | |
3843 | |
3844 if (!NILP (Vtemp_buffer_show_function)) | |
3845 call1 (Vtemp_buffer_show_function, buf); | |
3846 else | |
3847 { | |
3848 window = display_buffer (buf, Qnil, same_frame); | |
3849 | |
3850 if (!EQ (XWINDOW (window)->frame, Fselected_frame (Qnil))) | |
3851 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (window))); | |
3852 | |
3853 Vminibuffer_scroll_window = window; | |
3854 w = XWINDOW (window); | |
3855 w->hscroll = 0; | |
3856 w->modeline_hscroll = 0; | |
3857 set_marker_restricted (w->start[CURRENT_DISP], make_int (1), buf); | |
3858 set_marker_restricted (w->pointm[CURRENT_DISP], make_int (1), buf); | |
3859 set_marker_restricted (w->sb_point, make_int (1), buf); | |
3860 } | |
3861 } | |
3862 | |
3863 static void | |
3864 make_dummy_parent (Lisp_Object window) | |
3865 { | |
3866 struct window *o = XWINDOW (window); | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
3867 Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (window); |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
3868 struct window *p = XWINDOW (obj); |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
3869 |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
3870 copy_lisp_object (obj, window); |
428 | 3871 |
3872 /* Don't copy the pointers to the line start cache or the face | |
3873 instances. */ | |
3874 p->line_start_cache = Dynarr_new (line_start_cache); | |
3092 | 3875 #ifdef NEW_GC |
3876 p->face_cachels = Dynarr_lisp_new (face_cachel, | |
3877 &lrecord_face_cachel_dynarr, | |
3878 &lrecord_face_cachel); | |
3879 p->glyph_cachels = Dynarr_lisp_new (glyph_cachel, | |
3880 &lrecord_glyph_cachel_dynarr, | |
3881 &lrecord_glyph_cachel); | |
3882 #else /* not NEW_GC */ | |
428 | 3883 p->face_cachels = Dynarr_new (face_cachel); |
3884 p->glyph_cachels = Dynarr_new (glyph_cachel); | |
3092 | 3885 #endif /* not NEW_GC */ |
442 | 3886 p->subwindow_instance_cache = |
450 | 3887 make_image_instance_cache_hash_table (); |
428 | 3888 |
3889 /* Put new into window structure in place of window */ | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
3890 replace_window (window, obj); |
428 | 3891 |
3892 o->next = Qnil; | |
3893 o->prev = Qnil; | |
3894 o->vchild = Qnil; | |
3895 o->hchild = Qnil; | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
3896 o->parent = obj; |
428 | 3897 |
3898 p->start[CURRENT_DISP] = Qnil; | |
3899 p->start[DESIRED_DISP] = Qnil; | |
3900 p->start[CMOTION_DISP] = Qnil; | |
3901 p->pointm[CURRENT_DISP] = Qnil; | |
3902 p->pointm[DESIRED_DISP] = Qnil; | |
3903 p->pointm[CMOTION_DISP] = Qnil; | |
3904 p->sb_point = Qnil; | |
844 | 3905 p->saved_point_cache = make_saved_buffer_point_cache (); |
3906 p->saved_last_window_start_cache = make_saved_buffer_point_cache (); | |
428 | 3907 p->buffer = Qnil; |
3908 } | |
3909 | |
3910 DEFUN ("split-window", Fsplit_window, 0, 3, "", /* | |
3911 Split WINDOW, putting SIZE lines in the first of the pair. | |
444 | 3912 WINDOW defaults to the selected one and SIZE to half its size. |
707 | 3913 If optional third arg HORFLAG is non-nil, split side by side and put |
3914 SIZE columns in the first of the pair. The newly created window is | |
3915 returned. | |
428 | 3916 */ |
444 | 3917 (window, size, horflag)) |
428 | 3918 { |
3025 | 3919 Lisp_Object new_; |
428 | 3920 struct window *o, *p; |
3921 struct frame *f; | |
444 | 3922 int csize; |
428 | 3923 int psize; |
3924 | |
3925 if (NILP (window)) | |
3926 window = Fselected_window (Qnil); | |
3927 else | |
3928 CHECK_LIVE_WINDOW (window); | |
3929 | |
3930 o = XWINDOW (window); | |
3931 f = XFRAME (WINDOW_FRAME (o)); | |
3932 | |
444 | 3933 if (NILP (size)) |
428 | 3934 { |
3935 if (!NILP (horflag)) | |
3936 /* In the new scheme, we are symmetric with respect to separators | |
3937 so there is no need to do weird things here. */ | |
3938 { | |
956 | 3939 psize = (WINDOW_WIDTH (o) + window_divider_width (o)) >> 1; |
444 | 3940 csize = window_pixel_width_to_char_width (o, psize, 0); |
428 | 3941 } |
3942 else | |
3943 { | |
3944 psize = WINDOW_HEIGHT (o) >> 1; | |
444 | 3945 csize = window_pixel_height_to_char_height (o, psize, 1); |
428 | 3946 } |
3947 } | |
3948 else | |
3949 { | |
444 | 3950 CHECK_INT (size); |
3951 csize = XINT (size); | |
428 | 3952 if (!NILP (horflag)) |
444 | 3953 psize = window_char_width_to_pixel_width (o, csize, 0); |
428 | 3954 else |
444 | 3955 psize = window_char_height_to_pixel_height (o, csize, 1); |
428 | 3956 } |
3957 | |
3958 if (MINI_WINDOW_P (o)) | |
563 | 3959 invalid_operation ("Attempt to split minibuffer window", Qunbound); |
428 | 3960 else if (FRAME_NO_SPLIT_P (XFRAME (WINDOW_FRAME (o)))) |
563 | 3961 invalid_operation ("Attempt to split unsplittable frame", Qunbound); |
428 | 3962 |
3963 check_min_window_sizes (); | |
3964 | |
3965 if (NILP (horflag)) | |
3966 { | |
444 | 3967 if (csize < window_min_height) |
563 | 3968 signal_error (Qinvalid_operation, "Window height too small (after splitting)", make_int (csize)); |
444 | 3969 if (csize + window_min_height > window_char_height (o, 1)) |
563 | 3970 signal_error (Qinvalid_operation, "Window height too small (after splitting)", |
3971 make_int (window_char_height (o, 1) - csize)); | |
428 | 3972 if (NILP (o->parent) |
3973 || NILP (XWINDOW (o->parent)->vchild)) | |
3974 { | |
3975 make_dummy_parent (window); | |
448 | 3976 #if 0 |
3977 /* #### I can't understand why you have to reset face | |
3978 cachels here. This can cause crash so let's disable it | |
3979 and see the difference. See redisplay-tests.el --yh */ | |
428 | 3980 reset_face_cachels (XWINDOW (window)); |
448 | 3981 #endif |
3025 | 3982 new_ = o->parent; |
3983 XWINDOW (new_)->vchild = window; | |
428 | 3984 XFRAME (o->frame)->mirror_dirty = 1; |
3985 } | |
3986 } | |
3987 else | |
3988 { | |
444 | 3989 if (csize < window_min_width) |
563 | 3990 signal_error (Qinvalid_operation, "Window width too small (after splitting)", make_int (csize)); |
444 | 3991 if (csize + window_min_width > window_char_width (o, 0)) |
563 | 3992 signal_error (Qinvalid_operation, "Window width too small (after splitting)", |
3993 make_int (window_char_width (o, 0) - csize)); | |
428 | 3994 if (NILP (o->parent) |
3995 || NILP (XWINDOW (o->parent)->hchild)) | |
3996 { | |
3997 make_dummy_parent (window); | |
448 | 3998 #if 0 |
3999 /* #### See above. */ | |
428 | 4000 reset_face_cachels (XWINDOW (window)); |
448 | 4001 #endif |
3025 | 4002 new_ = o->parent; |
4003 XWINDOW (new_)->hchild = window; | |
428 | 4004 XFRAME (o->frame)->mirror_dirty = 1; |
4005 } | |
4006 } | |
4007 | |
4008 /* Now we know that window's parent is a vertical combination | |
4009 if we are dividing vertically, or a horizontal combination | |
4010 if we are making side-by-side windows */ | |
4011 | |
4012 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); | |
3025 | 4013 new_ = allocate_window (); |
4014 p = XWINDOW (new_); | |
428 | 4015 |
4016 p->frame = o->frame; | |
4017 p->next = o->next; | |
4018 if (!NILP (p->next)) | |
3025 | 4019 XWINDOW (p->next)->prev = new_; |
428 | 4020 p->prev = window; |
3025 | 4021 o->next = new_; |
428 | 4022 p->parent = o->parent; |
4023 p->buffer = Qt; | |
4024 | |
4025 reset_face_cachels (p); | |
4026 reset_glyph_cachels (p); | |
4027 | |
4028 | |
4029 /* Apportion the available frame space among the two new windows */ | |
4030 | |
4031 if (!NILP (horflag)) | |
4032 { | |
4033 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o); | |
4034 WINDOW_TOP (p) = WINDOW_TOP (o); | |
4035 WINDOW_WIDTH (p) = WINDOW_WIDTH (o) - psize; | |
4036 WINDOW_WIDTH (o) = psize; | |
4037 WINDOW_LEFT (p) = WINDOW_LEFT (o) + psize; | |
4038 } | |
4039 else | |
4040 { | |
4041 WINDOW_LEFT (p) = WINDOW_LEFT (o); | |
4042 WINDOW_WIDTH (p) = WINDOW_WIDTH (o); | |
4043 WINDOW_HEIGHT (p) = WINDOW_HEIGHT (o) - psize; | |
4044 WINDOW_HEIGHT (o) = psize; | |
4045 WINDOW_TOP (p) = WINDOW_TOP (o) + psize; | |
4046 } | |
4047 | |
4048 XFRAME (p->frame)->mirror_dirty = 1; | |
853 | 4049 |
3025 | 4050 note_object_created (new_); |
853 | 4051 |
428 | 4052 /* do this last (after the window is completely initialized and |
4053 the mirror-dirty flag is set) so that specifier recomputation | |
4054 caused as a result of this will work properly and not abort. */ | |
3025 | 4055 Fset_window_buffer (new_, o->buffer, Qt); |
4056 return new_; | |
428 | 4057 } |
4058 | |
4059 | |
4060 DEFUN ("enlarge-window", Fenlarge_window, 1, 3, "_p", /* | |
444 | 4061 Make the selected window COUNT lines taller. |
4062 From program, optional second arg HORIZONTALP non-nil means grow | |
4063 sideways COUNT columns, and optional third arg WINDOW specifies the | |
4064 window to change instead of the selected window. | |
428 | 4065 */ |
444 | 4066 (count, horizontalp, window)) |
4067 { | |
4068 CHECK_INT (count); | |
4069 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 0); | |
428 | 4070 return Qnil; |
4071 } | |
4072 | |
4073 DEFUN ("enlarge-window-pixels", Fenlarge_window_pixels, 1, 3, "_p", /* | |
444 | 4074 Make the selected window COUNT pixels taller. |
4075 From program, optional second arg HORIZONTALP non-nil means grow | |
4076 sideways COUNT pixels, and optional third arg WINDOW specifies the | |
4077 window to change instead of the selected window. | |
428 | 4078 */ |
444 | 4079 (count, horizontalp, window)) |
4080 { | |
4081 CHECK_INT (count); | |
4082 change_window_height (window, XINT (count), horizontalp, /* inpixels */ 1); | |
428 | 4083 return Qnil; |
4084 } | |
4085 | |
4086 DEFUN ("shrink-window", Fshrink_window, 1, 3, "_p", /* | |
444 | 4087 Make the selected window COUNT lines shorter. |
4088 From program, optional second arg HORIZONTALP non-nil means shrink | |
4089 sideways COUNT columns, and optional third arg WINDOW specifies the | |
4090 window to change instead of the selected window. | |
428 | 4091 */ |
444 | 4092 (count, horizontalp, window)) |
4093 { | |
4094 CHECK_INT (count); | |
4095 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 0); | |
428 | 4096 return Qnil; |
4097 } | |
4098 | |
4099 DEFUN ("shrink-window-pixels", Fshrink_window_pixels, 1, 3, "_p", /* | |
444 | 4100 Make the selected window COUNT pixels smaller. |
4101 From program, optional second arg HORIZONTALP non-nil means shrink | |
4102 sideways COUNT pixels, and optional third arg WINDOW specifies the | |
4103 window to change instead of the selected window. | |
428 | 4104 */ |
444 | 4105 (count, horizontalp, window)) |
4106 { | |
4107 CHECK_INT (count); | |
4108 change_window_height (window, -XINT (count), horizontalp, /* inpixels */ 1); | |
428 | 4109 return Qnil; |
4110 } | |
4111 | |
4112 static int | |
4113 window_pixel_height_to_char_height (struct window *w, int pixel_height, | |
4114 int include_gutters_p) | |
4115 { | |
4116 int avail_height; | |
4117 int defheight, defwidth; | |
3687 | 4118 int char_height = 0; |
793 | 4119 Lisp_Object window = wrap_window (w); |
4120 | |
428 | 4121 |
4122 avail_height = (pixel_height - | |
4123 (include_gutters_p ? 0 : | |
442 | 4124 window_top_window_gutter_height (w) + |
4125 window_bottom_window_gutter_height (w))); | |
428 | 4126 |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4127 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4128 |
3687 | 4129 if (defheight) |
4130 char_height = avail_height / defheight; | |
428 | 4131 |
4132 /* It's the calling function's responsibility to check these values | |
4133 and make sure they're not out of range. | |
4134 | |
4135 #### We need to go through the calling functions and actually | |
4136 do this. */ | |
4137 return max (0, char_height); | |
4138 } | |
4139 | |
4140 static int | |
4141 window_char_height_to_pixel_height (struct window *w, int char_height, | |
4142 int include_gutters_p) | |
4143 { | |
4144 int avail_height; | |
4145 int defheight, defwidth; | |
4146 int pixel_height; | |
4147 | |
793 | 4148 Lisp_Object window = wrap_window (w); |
4149 | |
428 | 4150 |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4151 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4152 |
4153 avail_height = char_height * defheight; | |
4154 pixel_height = (avail_height + | |
4155 (include_gutters_p ? 0 : | |
442 | 4156 window_top_window_gutter_height (w) + |
4157 window_bottom_window_gutter_height (w))); | |
428 | 4158 |
4159 /* It's the calling function's responsibility to check these values | |
4160 and make sure they're not out of range. | |
4161 | |
4162 #### We need to go through the calling functions and actually | |
4163 do this. */ | |
4164 return max (0, pixel_height); | |
4165 } | |
4166 | |
4167 /* Return number of default lines of text can fit in the window W. | |
4168 If INCLUDE_GUTTERS_P is 1, include "gutter" space (modeline plus | |
4169 horizontal scrollbar) in the space that is used for the calculation. | |
442 | 4170 This doesn't include space used by the frame gutters. |
428 | 4171 */ |
4172 int | |
4173 window_char_height (struct window *w, int include_gutters_p) | |
4174 { | |
442 | 4175 return window_pixel_height_to_char_height (w, window_pixel_height (w), |
428 | 4176 include_gutters_p); |
4177 } | |
4178 | |
4179 /* | |
4180 * Return number of lines currently displayed in window w. If | |
4181 * end-of-buffer is displayed then the area below end-of-buffer is assume | |
4182 * to be blank lines of default height. | |
4183 * Does not include the modeline. | |
4184 */ | |
4185 int | |
4186 window_displayed_height (struct window *w) | |
4187 { | |
4188 struct buffer *b = XBUFFER (w->buffer); | |
4189 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
4190 int num_lines; | |
4191 Charcount end_pos = (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b) | |
4192 ? -1 | |
4193 : w->window_end_pos[CURRENT_DISP]); | |
4194 | |
4195 if (!Dynarr_length (dla)) | |
4196 return window_char_height (w, 0); | |
4197 | |
4198 num_lines = Dynarr_length (dla); | |
4199 | |
4200 /* #### Document and assert somewhere that w->window_end_pos == -1 | |
4201 indicates that end-of-buffer is being displayed. */ | |
4202 if (end_pos == -1) | |
4203 { | |
4967 | 4204 struct display_line *dl = Dynarr_begin (dla); |
428 | 4205 int ypos1 = dl->ypos + dl->descent; |
4206 int ypos2 = WINDOW_TEXT_BOTTOM (w); | |
4207 Lisp_Object window; | |
4208 int defheight, defwidth; | |
4209 | |
793 | 4210 window = wrap_window (w); |
428 | 4211 |
4212 if (dl->modeline) | |
4213 { | |
4214 num_lines--; | |
4215 | |
4216 if (Dynarr_length (dla) == 1) | |
4217 ypos1 = WINDOW_TEXT_TOP (w); | |
4218 else | |
4219 { | |
4220 dl = Dynarr_atp (dla, Dynarr_length (dla) - 1); | |
4221 /* If this line is clipped then we know that there is no | |
4222 blank room between eob and the modeline. If we are | |
4223 scrolling on clipped lines just know off the clipped | |
4224 line and return .*/ | |
4225 if (scroll_on_clipped_lines && dl->clip) | |
4226 return num_lines - 1; | |
4227 ypos1 = dl->ypos + dl->descent - dl->clip; | |
4228 } | |
4229 } | |
4230 | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4231 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4232 /* #### This probably needs to know about the clipping area once a |
4233 final definition is decided on. */ | |
3707 | 4234 if (defheight) |
4235 num_lines += ((ypos2 - ypos1) / defheight); | |
428 | 4236 } |
4237 else | |
4238 { | |
4967 | 4239 if (num_lines > 1 && Dynarr_begin (dla)->modeline) |
428 | 4240 num_lines--; |
4241 | |
4242 if (scroll_on_clipped_lines | |
4243 && Dynarr_atp (dla, Dynarr_length (dla) - 1)->clip) | |
4244 num_lines--; | |
4245 } | |
4246 | |
4247 return num_lines; | |
4248 } | |
4249 | |
4250 static int | |
4251 window_pixel_width (Lisp_Object window) | |
4252 { | |
4253 return WINDOW_WIDTH (XWINDOW (window)); | |
4254 } | |
4255 | |
442 | 4256 /* Calculate the pixel of a window, optionally including margin space |
4257 but no vertical gutters. */ | |
428 | 4258 static int |
4259 window_pixel_width_to_char_width (struct window *w, int pixel_width, | |
4260 int include_margins_p) | |
4261 { | |
4262 int avail_width; | |
3676 | 4263 int char_width = 0; |
428 | 4264 int defheight, defwidth; |
793 | 4265 Lisp_Object window = wrap_window (w); |
4266 | |
428 | 4267 |
4268 avail_width = (pixel_width - | |
4269 window_left_gutter_width (w, 0) - | |
4270 window_right_gutter_width (w, 0) - | |
4271 (include_margins_p ? 0 : window_left_margin_width (w)) - | |
4272 (include_margins_p ? 0 : window_right_margin_width (w))); | |
4273 | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4274 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4275 |
3676 | 4276 if (defwidth) |
4277 char_width = (avail_width / defwidth); | |
428 | 4278 |
4279 /* It's the calling function's responsibility to check these values | |
4280 and make sure they're not out of range. | |
4281 | |
4282 #### We need to go through the calling functions and actually | |
4283 do this. */ | |
4284 return max (0, char_width); | |
4285 } | |
4286 | |
4287 static int | |
4288 window_char_width_to_pixel_width (struct window *w, int char_width, | |
4289 int include_margins_p) | |
4290 { | |
4291 int avail_width; | |
4292 int pixel_width; | |
4293 int defheight, defwidth; | |
793 | 4294 Lisp_Object window = wrap_window (w); |
4295 | |
428 | 4296 |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4297 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4298 |
4299 avail_width = char_width * defwidth; | |
4300 pixel_width = (avail_width + | |
442 | 4301 window_left_window_gutter_width (w, 0) + |
4302 window_right_window_gutter_width (w, 0) + | |
428 | 4303 (include_margins_p ? 0 : window_left_margin_width (w)) + |
4304 (include_margins_p ? 0 : window_right_margin_width (w))); | |
4305 | |
4306 /* It's the calling function's responsibility to check these values | |
4307 and make sure they're not out of range. | |
4308 | |
4309 #### We need to go through the calling functions and actually | |
4310 do this. */ | |
4311 return max (0, pixel_width); | |
4312 } | |
4313 | |
4314 /* This returns the usable space which doesn't include space needed by | |
4315 scrollbars or divider lines. */ | |
4316 int | |
4317 window_char_width (struct window *w, int include_margins_p) | |
4318 { | |
4319 return window_pixel_width_to_char_width (w, WINDOW_WIDTH (w), | |
4320 include_margins_p); | |
4321 } | |
4322 | |
4323 #define MINSIZE(w) \ | |
4324 (widthflag \ | |
4325 ? window_min_width * defwidth \ | |
4326 : (defheight * (MINI_WINDOW_P (XWINDOW (w)) ? 1 : window_min_height))) | |
4327 | |
4328 #define CURBEG(w) \ | |
4329 *(widthflag ? (int *) &WINDOW_LEFT (w) : (int *) &WINDOW_TOP (w)) | |
4330 | |
4331 #define CURSIZE(w) \ | |
4332 *(widthflag ? (int *) &WINDOW_WIDTH (w) : (int *) &WINDOW_HEIGHT (w)) | |
4333 | |
4334 #define CURCHARSIZE(w) \ | |
4335 (widthflag ? window_char_width (w, 0) : window_char_height (w, 1)) | |
4336 | |
4337 #define MINCHARSIZE(window) \ | |
4338 (widthflag ? window_min_width : MINI_WINDOW_P (XWINDOW (window)) \ | |
4339 ? 1 : window_min_height) | |
4340 | |
442 | 4341 static int |
4342 window_pixheight (Lisp_Object w) | |
4343 { | |
4344 return window_pixel_height (XWINDOW (w)); | |
4345 } | |
4346 | |
428 | 4347 /* Unlike set_window_pixheight, this function |
4348 also changes the heights of the siblings so as to | |
4349 keep everything consistent. */ | |
4350 | |
4351 static void | |
444 | 4352 change_window_height (Lisp_Object window, int delta, Lisp_Object horizontalp, |
428 | 4353 int inpixels) |
4354 { | |
444 | 4355 struct window *win = decode_window (window); |
4356 int widthflag = !NILP (horizontalp); | |
428 | 4357 Lisp_Object parent; |
4358 struct window *w; | |
4359 struct frame *f; | |
4360 int *sizep; | |
4361 int (*sizefun) (Lisp_Object) = (widthflag | |
4362 ? window_pixel_width | |
442 | 4363 : window_pixheight); |
428 | 4364 void (*setsizefun) (Lisp_Object, int, int) = (widthflag |
4365 ? set_window_pixwidth | |
4366 : set_window_pixheight); | |
4367 int dim; | |
4368 int defheight, defwidth; | |
4369 | |
4370 if (delta == 0) | |
4371 return; | |
4372 | |
4373 check_min_window_sizes (); | |
4374 | |
793 | 4375 window = wrap_window (win); |
428 | 4376 f = XFRAME (win->frame); |
4377 if (EQ (window, FRAME_ROOT_WINDOW (f))) | |
563 | 4378 invalid_operation ("Won't change only window", Qunbound); |
428 | 4379 |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4380 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 4381 |
4382 while (1) | |
4383 { | |
4384 w = XWINDOW (window); | |
4385 parent = w->parent; | |
4386 if (NILP (parent)) | |
4387 { | |
4388 if (widthflag) | |
3078 | 4389 { |
4390 int new_pixsize; | |
4391 sizep = &CURSIZE (w); | |
3466 | 4392 dim = CURCHARSIZE (w); |
3078 | 4393 new_pixsize = inpixels?(*sizep + delta):(dim+delta); |
4394 set_window_pixsize (window, new_pixsize, 0, 0); | |
4395 return; | |
4396 } | |
428 | 4397 break; |
4398 } | |
4399 if (widthflag | |
4400 ? !NILP (XWINDOW (parent)->hchild) | |
4401 : !NILP (XWINDOW (parent)->vchild)) | |
4402 break; | |
4403 window = parent; | |
4404 } | |
4405 | |
4406 sizep = &CURSIZE (w); | |
4407 dim = CURCHARSIZE (w); | |
4408 | |
4409 if ((inpixels && (*sizep + delta) < MINSIZE (window)) || | |
4410 (!inpixels && (dim + delta) < MINCHARSIZE (window))) | |
4411 { | |
4412 if (MINI_WINDOW_P (XWINDOW (window))) | |
4413 return; | |
4414 else if (!NILP (parent)) | |
4415 { | |
4416 Fdelete_window (window, Qnil); | |
4417 return; | |
4418 } | |
4419 } | |
4420 | |
4421 if (!inpixels) | |
4422 delta *= (widthflag ? defwidth : defheight); | |
4423 | |
4424 { | |
4425 int maxdelta; | |
4426 | |
4427 maxdelta = ((!NILP (parent)) | |
4428 ? (*sizefun) (parent) - *sizep | |
4429 : ((!NILP (w->next)) | |
4430 ? (*sizefun) (w->next) - MINSIZE (w->next) | |
4431 : ((!NILP (w->prev)) | |
4432 ? (*sizefun) (w->prev) - MINSIZE (w->prev) | |
4433 /* This is a frame with only one window, | |
4434 a minibuffer-only or a minibufferless frame. */ | |
4435 : (delta = 0)))); | |
4436 | |
4437 if (delta > maxdelta) | |
4438 /* This case traps trying to make the minibuffer | |
4439 the full frame, or make the only window aside from the | |
4440 minibuffer the full frame. */ | |
4441 delta = maxdelta; | |
4442 | |
4443 if (delta == 0) | |
4444 return; | |
4445 | |
4446 #if 0 /* FSFmacs */ | |
4447 /* #### Chuck: is this correct? */ | |
4448 if (*sizep + delta < MINSIZE (window)) | |
4449 { | |
4450 Fdelete_window (window); | |
4451 return; | |
4452 } | |
4453 #endif | |
4454 } | |
4455 | |
4456 if (!NILP (w->next) && | |
4457 (*sizefun) (w->next) - delta >= (int) MINSIZE (w->next)) | |
4458 { | |
4459 CURBEG (XWINDOW (w->next)) += delta; | |
4460 (*setsizefun) (w->next, (*sizefun) (w->next) - delta, 0); | |
4461 (*setsizefun) (window, *sizep + delta, 0); | |
4462 } | |
4463 else if (!NILP (w->prev) && | |
4464 (*sizefun) (w->prev) - delta >= (int) MINSIZE (w->prev)) | |
4465 { | |
4466 (*setsizefun) (w->prev, (*sizefun) (w->prev) - delta, 0); | |
4467 CURBEG (w) -= delta; | |
4468 (*setsizefun) (window, *sizep + delta, 0); | |
4469 } | |
4470 else | |
4471 { | |
4472 int delta1; | |
4473 int opht = (*sizefun) (parent); | |
4474 | |
4475 /* If trying to grow this window to or beyond size of the parent, | |
4476 make delta1 so big that, on shrinking back down, | |
4477 all the siblings end up with less than one line and are deleted. */ | |
4478 if (opht <= *sizep + delta) | |
4479 delta1 = opht * opht * 2; | |
4480 /* Otherwise, make delta1 just right so that if we add delta1 | |
4481 lines to this window and to the parent, and then shrink | |
4482 the parent back to its original size, the new proportional | |
4483 size of this window will increase by delta. */ | |
4484 else | |
4485 delta1 = (delta * opht * 100) / ((opht - *sizep - delta) * 100); | |
4486 | |
4487 /* Add delta1 lines or columns to this window, and to the parent, | |
4488 keeping things consistent while not affecting siblings. */ | |
4489 CURSIZE (XWINDOW (parent)) = opht + delta1; | |
4490 (*setsizefun) (window, *sizep + delta1, 0); | |
4491 | |
4492 /* Squeeze out delta1 lines or columns from our parent, | |
4493 shrinking this window and siblings proportionately. | |
4494 This brings parent back to correct size. | |
4495 Delta1 was calculated so this makes this window the desired size, | |
4496 taking it all out of the siblings. */ | |
4497 (*setsizefun) (parent, opht, 0); | |
4498 } | |
4499 | |
4500 SET_LAST_MODIFIED (w, 0); | |
4501 SET_LAST_FACECHANGE (w); | |
4502 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); | |
4503 /* overkill maybe, but better to be correct */ | |
4504 MARK_FRAME_GUTTERS_CHANGED (f); | |
4505 } | |
4506 #undef MINSIZE | |
4507 #undef CURBEG | |
4508 #undef CURSIZE | |
4509 #undef CURCHARSIZE | |
4510 #undef MINCHARSIZE | |
4511 | |
4512 | |
4513 | |
444 | 4514 /* Scroll contents of window WINDOW up COUNT lines. |
4515 If COUNT < (top line height / average line height) then we just adjust | |
4516 the top clip. */ | |
428 | 4517 void |
444 | 4518 window_scroll (Lisp_Object window, Lisp_Object count, int direction, |
578 | 4519 Error_Behavior errb) |
428 | 4520 { |
4521 struct window *w = XWINDOW (window); | |
4522 struct buffer *b = XBUFFER (w->buffer); | |
4523 int selected = EQ (window, Fselected_window (Qnil)); | |
4524 int value = 0; | |
4525 Lisp_Object point, tem; | |
4526 display_line_dynarr *dla; | |
4527 int fheight, fwidth, modeline = 0; | |
4528 struct display_line* dl; | |
4529 | |
4530 if (selected) | |
4531 point = make_int (BUF_PT (b)); | |
4532 else | |
4533 { | |
665 | 4534 Charbpos pos = marker_position (w->pointm[CURRENT_DISP]); |
428 | 4535 |
4536 if (pos < BUF_BEGV (b)) | |
4537 pos = BUF_BEGV (b); | |
4538 else if (pos > BUF_ZV (b)) | |
4539 pos = BUF_ZV (b); | |
4540 | |
4541 point = make_int (pos); | |
4542 } | |
4543 | |
4544 /* Always set force_start so that redisplay_window will run | |
4545 the window-scroll-functions. */ | |
4546 w->force_start = 1; | |
4547 | |
4548 /* #### When the fuck does this happen? I'm so glad that history has | |
4549 completely documented the behavior of the scrolling functions under | |
4550 all circumstances. */ | |
1708 | 4551 tem = Fpos_visible_in_window_p (point, window, Qnil); |
428 | 4552 if (NILP (tem)) |
4553 { | |
4554 Fvertical_motion (make_int (-window_char_height (w, 0) / 2), | |
4555 window, Qnil); | |
4556 Fset_marker (w->start[CURRENT_DISP], point, w->buffer); | |
4557 w->start_at_line_beg = beginning_of_line_p (b, XINT (point)); | |
4558 WINDOW_TEXT_TOP_CLIP (w) = 0; | |
4559 MARK_WINDOWS_CHANGED (w); | |
4560 } | |
4561 | |
444 | 4562 if (!NILP (count)) |
428 | 4563 { |
444 | 4564 if (EQ (count, Qminus)) |
428 | 4565 direction *= -1; |
4566 else | |
4567 { | |
444 | 4568 count = Fprefix_numeric_value (count); |
4569 value = XINT (count) * direction; | |
428 | 4570 |
4571 if (!value) | |
4572 return; /* someone just made a pointless call */ | |
4573 } | |
4574 } | |
4575 | |
4576 /* If the user didn't specify how far to scroll then we have to figure it | |
4577 out by ourselves. */ | |
444 | 4578 if (NILP (count) || EQ (count, Qminus)) |
428 | 4579 { |
4580 /* Going forwards is easy. If that is what we are doing then just | |
4581 set value and the section which handles the user specifying a | |
4582 positive value will work. */ | |
4583 if (direction == 1) | |
4584 { | |
4585 value = window_displayed_height (w) - next_screen_context_lines; | |
4586 value = (value < 1 ? 1 : value); | |
4587 } | |
4588 | |
4589 /* Going backwards is hard. We can't use the same loop used if the | |
4590 user specified a negative value because we care about | |
4591 next_screen_context_lines. In a variable height world you don't | |
4592 know how many lines above you can actually be displayed and still | |
4593 have the context lines appear. So we leave value set to 0 and add | |
4594 a separate section to deal with this. */ | |
4595 | |
4596 } | |
4597 | |
4598 if (direction == 1 && !value) | |
4599 { | |
4600 return; | |
4601 } | |
4602 | |
4603 /* Determine parameters to test for partial line scrolling with. */ | |
4604 dla = window_display_lines (w, CURRENT_DISP); | |
4605 | |
4606 if (INTP (Vwindow_pixel_scroll_increment)) | |
4607 fheight = XINT (Vwindow_pixel_scroll_increment); | |
440 | 4608 else if (!NILP (Vwindow_pixel_scroll_increment)) |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
4609 default_face_width_and_height (window, &fwidth, &fheight); |
438 | 4610 |
428 | 4611 if (Dynarr_length (dla) >= 1) |
4967 | 4612 modeline = Dynarr_begin (dla)->modeline; |
428 | 4613 |
4614 dl = Dynarr_atp (dla, modeline); | |
438 | 4615 |
428 | 4616 if (value > 0) |
4617 { | |
4618 /* Go for partial display line scrolling. This just means bumping | |
4619 the clip by a reasonable amount and redisplaying, everything else | |
4620 remains unchanged. */ | |
4621 if (!NILP (Vwindow_pixel_scroll_increment) | |
4622 && | |
4623 Dynarr_length (dla) >= (1 + modeline) | |
4624 && | |
458 | 4625 (dl->ascent - dl->top_clip) > fheight * value) |
428 | 4626 { |
4627 WINDOW_TEXT_TOP_CLIP (w) += value * fheight; | |
4628 MARK_WINDOWS_CHANGED (w); | |
4629 } | |
4630 else | |
4631 { | |
4632 int vtarget; | |
665 | 4633 Charbpos startp, old_start; |
438 | 4634 |
428 | 4635 if (WINDOW_TEXT_TOP_CLIP (w)) |
4636 { | |
4637 WINDOW_TEXT_TOP_CLIP (w) = 0; | |
4638 MARK_WINDOWS_CHANGED (w); | |
4639 } | |
4640 | |
4641 old_start = marker_position (w->start[CURRENT_DISP]); | |
4642 startp = vmotion (w, old_start, value, &vtarget); | |
438 | 4643 |
428 | 4644 if (vtarget < value && |
4645 (w->window_end_pos[CURRENT_DISP] == -1 | |
4646 || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)))) | |
4647 { | |
563 | 4648 maybe_signal_error_1 (Qend_of_buffer, Qnil, Qwindow, errb); |
428 | 4649 return; |
4650 } | |
4651 else | |
4652 { | |
4653 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), | |
4654 w->buffer); | |
4655 w->force_start = 1; | |
4656 w->start_at_line_beg = beginning_of_line_p (b, startp); | |
4657 MARK_WINDOWS_CHANGED (w); | |
438 | 4658 |
1708 | 4659 if (!point_would_be_visible (w, startp, XINT (point), 0)) |
844 | 4660 Fset_window_point (wrap_window (w), make_int (startp)); |
428 | 4661 } |
4662 } | |
4663 } | |
4664 else if (value < 0) | |
4665 { | |
4666 /* Go for partial display line scrolling. This just means bumping | |
4667 the clip by a reasonable amount and redisplaying, everything else | |
4668 remains unchanged. */ | |
4669 if (!NILP (Vwindow_pixel_scroll_increment) | |
4670 && | |
4671 Dynarr_length (dla) >= (1 + modeline) | |
4672 && | |
4673 (dl->ascent - dl->top_clip) - fheight * value < | |
4674 (dl->ascent + dl->descent - dl->clip) | |
4675 && | |
4676 WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0) | |
4677 { | |
4678 WINDOW_TEXT_TOP_CLIP (w) += value * fheight; | |
4679 MARK_WINDOWS_CHANGED (w); | |
4680 } | |
4681 else | |
4682 { | |
4683 int vtarget; | |
665 | 4684 Charbpos startp, old_start; |
438 | 4685 |
428 | 4686 if (WINDOW_TEXT_TOP_CLIP (w)) |
4687 { | |
4688 WINDOW_TEXT_TOP_CLIP (w) = 0; | |
4689 MARK_WINDOWS_CHANGED (w); | |
4690 } | |
438 | 4691 |
428 | 4692 old_start = marker_position (w->start[CURRENT_DISP]); |
4693 startp = vmotion (w, old_start, value, &vtarget); | |
438 | 4694 |
428 | 4695 if (vtarget > value |
4696 && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b)) | |
4697 { | |
563 | 4698 maybe_signal_error_1 (Qbeginning_of_buffer, Qnil, Qwindow, errb); |
428 | 4699 return; |
4700 } | |
4701 else | |
4702 { | |
4703 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), | |
4704 w->buffer); | |
4705 w->force_start = 1; | |
4706 w->start_at_line_beg = beginning_of_line_p (b, startp); | |
4707 MARK_WINDOWS_CHANGED (w); | |
438 | 4708 |
440 | 4709 /* #### Scroll back by less than a line. This code was |
4710 originally for scrolling over large pixmaps and it | |
4711 loses when a line being *exposed* at the top of the | |
4712 window is bigger than the current one. However, for | |
4713 pixel based scrolling in general we can guess that | |
4714 the line we are going to display is probably the same | |
4715 size as the one we are on. In that instance we can | |
4716 have a reasonable stab at a suitable top clip. Fixing | |
4717 this properly is hard (and probably slow) as we would | |
4718 have to call redisplay to figure out the exposed line | |
4719 size. */ | |
4720 if (!NILP (Vwindow_pixel_scroll_increment) | |
4721 && Dynarr_length (dla) >= (1 + modeline) | |
4722 && dl->ascent + fheight * value > 0) | |
4723 { | |
4724 WINDOW_TEXT_TOP_CLIP (w) = (dl->ascent + fheight * value); | |
4725 } | |
4726 | |
1708 | 4727 if (!point_would_be_visible (w, startp, XINT (point), 0)) |
428 | 4728 { |
665 | 4729 Charbpos new_point; |
438 | 4730 |
428 | 4731 if (MINI_WINDOW_P (w)) |
4732 new_point = startp; | |
4733 else | |
4734 new_point = start_of_last_line (w, startp); | |
438 | 4735 |
844 | 4736 Fset_window_point (wrap_window (w), make_int (new_point)); |
428 | 4737 } |
4738 } | |
4739 } | |
4740 } | |
4741 else /* value == 0 && direction == -1 */ | |
4742 { | |
4743 if (WINDOW_TEXT_TOP_CLIP (w)) | |
4744 { | |
4745 WINDOW_TEXT_TOP_CLIP (w) = 0; | |
4746 MARK_WINDOWS_CHANGED (w); | |
4747 } | |
4748 if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b)) | |
4749 { | |
563 | 4750 maybe_signal_error_1 (Qbeginning_of_buffer, Qnil, Qwindow, errb); |
428 | 4751 return; |
4752 } | |
4753 else | |
4754 { | |
4755 int vtarget; | |
4756 int movement = next_screen_context_lines - 1; | |
665 | 4757 Charbpos old_startp = marker_position (w->start[CURRENT_DISP]); |
4758 Charbpos bottom = vmotion (w, old_startp, movement, &vtarget); | |
4759 Charbpos startp = | |
428 | 4760 start_with_point_on_display_line (w, bottom, |
4761 -1 - (movement - vtarget)); | |
4762 | |
4763 if (startp >= old_startp) | |
4764 startp = vmotion (w, old_startp, -1, NULL); | |
4765 | |
4766 set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), | |
4767 w->buffer); | |
4768 w->force_start = 1; | |
4769 w->start_at_line_beg = beginning_of_line_p (b, startp); | |
4770 MARK_WINDOWS_CHANGED (w); | |
4771 | |
1708 | 4772 if (!point_would_be_visible (w, startp, XINT (point), 0)) |
428 | 4773 { |
665 | 4774 Charbpos new_point = start_of_last_line (w, startp); |
428 | 4775 |
844 | 4776 Fset_window_point (wrap_window (w), make_int (new_point)); |
428 | 4777 } |
4778 } | |
4779 } | |
4780 } | |
4781 | |
4782 DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /* | |
444 | 4783 Scroll text of current window up COUNT lines; or near full screen if no arg. |
428 | 4784 A near full screen is `next-screen-context-lines' less than a full screen. |
444 | 4785 Negative COUNT means scroll downward. |
428 | 4786 When calling from a program, supply an integer as argument or nil. |
4787 On attempt to scroll past end of buffer, `end-of-buffer' is signaled. | |
4788 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is | |
4789 signaled. | |
462 | 4790 |
4791 The characters that are moved over may be added to the current selection | |
4792 \(i.e. active region) if the Shift key is held down, a motion key is used | |
4793 to invoke this command, and `shifted-motion-keys-select-region' is t; see | |
4794 the documentation for this variable for more details. | |
428 | 4795 */ |
444 | 4796 (count)) |
4797 { | |
4798 window_scroll (Fselected_window (Qnil), count, 1, ERROR_ME); | |
428 | 4799 return Qnil; |
4800 } | |
4801 | |
4802 DEFUN ("scroll-down", Fscroll_down, 0, 1, "_P", /* | |
444 | 4803 Scroll text of current window down COUNT lines; or near full screen if no arg. |
428 | 4804 A near full screen is `next-screen-context-lines' less than a full screen. |
444 | 4805 Negative COUNT means scroll upward. |
428 | 4806 When calling from a program, supply a number as argument or nil. |
4807 On attempt to scroll past end of buffer, `end-of-buffer' is signaled. | |
4808 On attempt to scroll past beginning of buffer, `beginning-of-buffer' is | |
4809 signaled. | |
462 | 4810 |
4811 The characters that are moved over may be added to the current selection | |
4812 \(i.e. active region) if the Shift key is held down, a motion key is used | |
4813 to invoke this command, and `shifted-motion-keys-select-region' is t; see | |
4814 the documentation for this variable for more details. | |
428 | 4815 */ |
444 | 4816 (count)) |
4817 { | |
4818 window_scroll (Fselected_window (Qnil), count, -1, ERROR_ME); | |
428 | 4819 return Qnil; |
4820 } | |
4821 | |
4822 DEFUN ("other-window-for-scrolling", Fother_window_for_scrolling, 0, 0, 0, /* | |
4823 Return the other window for "other window scroll" commands. | |
4824 If in the minibuffer, `minibuffer-scroll-window' if non-nil | |
4825 specifies the window. | |
4826 If `other-window-scroll-buffer' is non-nil, a window | |
4827 showing that buffer is used. | |
4828 */ | |
4829 ()) | |
4830 { | |
4831 Lisp_Object window; | |
4832 Lisp_Object selected_window = Fselected_window (Qnil); | |
4833 | |
4834 if (MINI_WINDOW_P (XWINDOW (selected_window)) | |
4835 && !NILP (Vminibuffer_scroll_window)) | |
4836 window = Vminibuffer_scroll_window; | |
4837 /* If buffer is specified, scroll that buffer. */ | |
4838 else if (!NILP (Vother_window_scroll_buffer)) | |
4839 { | |
4840 window = Fget_buffer_window (Vother_window_scroll_buffer, Qnil, Qnil); | |
4841 if (NILP (window)) | |
4842 window = display_buffer (Vother_window_scroll_buffer, Qt, Qnil); | |
4843 } | |
4844 else | |
4845 { | |
4846 /* Nothing specified; look for a neighboring window on the same | |
4847 frame. */ | |
4848 window = Fnext_window (selected_window, Qnil, Qnil, Qnil); | |
4849 | |
4850 if (EQ (window, selected_window)) | |
4851 /* That didn't get us anywhere; look for a window on another | |
4852 visible frame. */ | |
4853 do | |
4854 window = Fnext_window (window, Qnil, Qt, Qnil); | |
4855 while (! FRAME_VISIBLE_P (XFRAME (WINDOW_FRAME (XWINDOW (window)))) | |
4856 && ! EQ (window, selected_window)); | |
4857 } | |
4858 | |
4859 CHECK_LIVE_WINDOW (window); | |
4860 | |
4861 if (EQ (window, selected_window)) | |
563 | 4862 invalid_operation ("There is no other window", Qunbound); |
428 | 4863 |
4864 return window; | |
4865 } | |
4866 | |
4867 DEFUN ("scroll-other-window", Fscroll_other_window, 0, 1, "_P", /* | |
444 | 4868 Scroll next window upward COUNT lines; or near full frame if no arg. |
428 | 4869 The next window is the one below the current one; or the one at the top |
444 | 4870 if the current one is at the bottom. Negative COUNT means scroll downward. |
428 | 4871 When calling from a program, supply a number as argument or nil. |
4872 | |
4873 If in the minibuffer, `minibuffer-scroll-window' if non-nil | |
4874 specifies the window to scroll. | |
4875 If `other-window-scroll-buffer' is non-nil, scroll the window | |
4876 showing that buffer, popping the buffer up if necessary. | |
4877 */ | |
444 | 4878 (count)) |
4879 { | |
4880 window_scroll (Fother_window_for_scrolling (), count, 1, ERROR_ME); | |
428 | 4881 return Qnil; |
4882 } | |
4883 | |
4884 DEFUN ("scroll-left", Fscroll_left, 0, 1, "_P", /* | |
444 | 4885 Scroll selected window display COUNT columns left. |
4886 Default for COUNT is window width minus 2. | |
462 | 4887 |
4888 The characters that are moved over may be added to the current selection | |
4889 \(i.e. active region) if the Shift key is held down, a motion key is used | |
4890 to invoke this command, and `shifted-motion-keys-select-region' is t; see | |
4891 the documentation for this variable for more details. | |
428 | 4892 */ |
444 | 4893 (count)) |
428 | 4894 { |
4895 Lisp_Object window = Fselected_window (Qnil); | |
4896 struct window *w = XWINDOW (window); | |
444 | 4897 int n = (NILP (count) ? |
4898 window_char_width (w, 0) - 2 : | |
4899 XINT (Fprefix_numeric_value (count))); | |
4900 | |
4901 return Fset_window_hscroll (window, make_int (w->hscroll + n)); | |
428 | 4902 } |
4903 | |
4904 DEFUN ("scroll-right", Fscroll_right, 0, 1, "_P", /* | |
444 | 4905 Scroll selected window display COUNT columns right. |
4906 Default for COUNT is window width minus 2. | |
462 | 4907 |
4908 The characters that are moved over may be added to the current selection | |
4909 \(i.e. active region) if the Shift key is held down, a motion key is used | |
4910 to invoke this command, and `shifted-motion-keys-select-region' is t; see | |
4911 the documentation for this variable for more details. | |
428 | 4912 */ |
444 | 4913 (count)) |
428 | 4914 { |
4915 Lisp_Object window = Fselected_window (Qnil); | |
4916 struct window *w = XWINDOW (window); | |
444 | 4917 int n = (NILP (count) ? |
4918 window_char_width (w, 0) - 2 : | |
4919 XINT (Fprefix_numeric_value (count))); | |
4920 | |
4921 return Fset_window_hscroll (window, make_int (w->hscroll - n)); | |
428 | 4922 } |
4923 | |
4924 DEFUN ("center-to-window-line", Fcenter_to_window_line, 0, 2, "_P", /* | |
4925 Center point in WINDOW. With N, put point on line N. | |
4926 The desired position of point is always relative to the window. | |
4927 If WINDOW is nil, the selected window is used. | |
4928 */ | |
4929 (n, window)) | |
4930 { | |
4931 struct window *w = decode_window (window); | |
4932 struct buffer *b = XBUFFER (w->buffer); | |
665 | 4933 Charbpos opoint = BUF_PT (b); |
4934 Charbpos startp; | |
428 | 4935 |
4936 if (NILP (n)) | |
4937 startp = start_with_line_at_pixpos (w, opoint, window_half_pixpos (w)); | |
4938 else | |
4939 { | |
4940 n = Fprefix_numeric_value (n); | |
4941 CHECK_INT (n); | |
4942 startp = start_with_point_on_display_line (w, opoint, XINT (n)); | |
4943 } | |
4944 | |
4945 Fset_marker (w->start[CURRENT_DISP], make_int (startp), w->buffer); | |
4946 | |
4947 w->start_at_line_beg = beginning_of_line_p (b, startp); | |
4948 w->force_start = 1; | |
4949 MARK_WINDOWS_CHANGED (w); | |
4950 return Qnil; | |
4951 } | |
4952 | |
4953 DEFUN ("move-to-window-line", Fmove_to_window_line, 1, 2, "_P", /* | |
4954 Position point relative to WINDOW. | |
4955 With no argument, position text at center of window. | |
4956 An argument specifies window line; zero means top of window, | |
4957 negative means relative to bottom of window. | |
4958 If WINDOW is nil, the selected window is used. | |
4959 */ | |
4960 (arg, window)) | |
4961 { | |
4962 struct window *w; | |
4963 struct buffer *b; | |
4964 int height; | |
665 | 4965 Charbpos start, new_point; |
428 | 4966 int selected; |
4967 | |
4968 /* Don't use decode_window() because we need the new value of | |
4969 WINDOW. */ | |
4970 if (NILP (window)) | |
4971 window = Fselected_window (Qnil); | |
4972 else | |
4973 CHECK_LIVE_WINDOW (window); | |
4974 w = XWINDOW (window); | |
4975 b = XBUFFER (w->buffer); | |
4976 | |
4977 height = window_displayed_height (w); | |
4978 selected = EQ (window, Fselected_window (w->frame)); | |
4979 | |
4980 if (NILP (arg)) | |
4981 { | |
4982 int retval; | |
4983 | |
4984 if (XINT (w->last_modified[CURRENT_DISP]) >= BUF_MODIFF (b) | |
4985 && XINT (w->last_facechange[CURRENT_DISP]) >= BUF_FACECHANGE (b)) | |
4986 { | |
4987 new_point = point_at_center (w, CURRENT_DISP, 0, 0); | |
4988 | |
844 | 4989 /* #### Here we are checking the selected window of the frame |
4990 instead of the selected window period. Elsewhere we check | |
4991 the selected window of the device. What a mess! */ | |
428 | 4992 if (selected) |
4993 BUF_SET_PT (b, new_point); | |
4994 else | |
4995 Fset_window_point (window, make_int (new_point)); | |
4996 | |
4997 retval = line_at_center (w, CURRENT_DISP, 0, 0); | |
4998 } | |
4999 else | |
5000 { | |
5001 start = marker_position (w->start[CURRENT_DISP]); | |
5002 if (start < BUF_BEGV (b)) | |
5003 start = BUF_BEGV (b); | |
5004 else if (start > BUF_ZV (b)) | |
5005 start = BUF_ZV (b); | |
5006 | |
5007 if (selected) | |
5008 new_point = BUF_PT (b); | |
5009 else | |
5010 new_point = marker_position (w->pointm[CURRENT_DISP]); | |
5011 | |
5012 new_point = point_at_center (w, CMOTION_DISP, start, BUF_PT (b)); | |
5013 | |
5014 if (selected) | |
5015 BUF_SET_PT (b, new_point); | |
5016 else | |
5017 Fset_window_point (window, make_int (new_point)); | |
5018 | |
5019 retval = line_at_center (w, CMOTION_DISP, start, BUF_PT (b)); | |
5020 } | |
5021 | |
5022 return make_int (retval); | |
5023 } | |
5024 else | |
5025 { | |
5026 /* #### Is this going to work right when at eob? */ | |
5027 arg = Fprefix_numeric_value (arg); | |
5028 if (XINT (arg) < 0) | |
793 | 5029 arg = make_int (XINT (arg) + height); |
428 | 5030 } |
5031 | |
5032 start = marker_position (w->start[CURRENT_DISP]); | |
5033 if (start < BUF_BEGV (b) || start > BUF_ZV (b)) | |
5034 { | |
5035 if (selected) | |
5036 new_point = BUF_PT (b); | |
5037 else | |
5038 new_point = marker_position (w->pointm[CURRENT_DISP]); | |
5039 | |
5040 new_point = vmotion (XWINDOW (window), new_point, -height / 2, 0); | |
5041 | |
5042 if (selected) | |
5043 BUF_SET_PT (b, new_point); | |
5044 else | |
5045 Fset_window_point (window, make_int (new_point)); | |
5046 | |
5047 Fset_marker (w->start[CURRENT_DISP], make_int (new_point), | |
5048 w->buffer); | |
5049 w->start_at_line_beg = beginning_of_line_p (b, new_point); | |
5050 w->force_start = 1; | |
5051 } | |
5052 else | |
5053 { | |
5054 if (selected) | |
5055 BUF_SET_PT (b, start); | |
5056 else | |
5057 Fset_window_point (window, make_int (start)); | |
5058 } | |
5059 | |
5060 if (selected) | |
5061 return Fvertical_motion (arg, window, Qnil); | |
5062 else | |
5063 { | |
5064 int vpos; | |
5065 new_point = vmotion (XWINDOW (window), | |
5066 marker_position (w->pointm[CURRENT_DISP]), | |
5067 XINT (arg), &vpos); | |
5068 Fset_window_point (window, make_int (new_point)); | |
5069 return make_int (vpos); | |
5070 } | |
5071 } | |
5072 | |
5073 | |
5074 static int | |
5075 map_windows_1 (Lisp_Object window, | |
5076 int (*mapfun) (struct window *w, void *closure), | |
5077 void *closure) | |
5078 { | |
5079 for (; !NILP (window); window = XWINDOW (window)->next) | |
5080 { | |
5081 int retval; | |
5082 struct window *w = XWINDOW (window); | |
5083 | |
5084 if (!NILP (w->vchild)) | |
5085 retval = map_windows_1 (w->vchild, mapfun, closure); | |
5086 else if (!NILP (w->hchild)) | |
5087 retval = map_windows_1 (w->hchild, mapfun, closure); | |
5088 else | |
5089 retval = (mapfun) (w, closure); | |
5090 | |
5091 if (retval) | |
5092 return retval; | |
5093 } | |
5094 | |
5095 return 0; | |
5096 } | |
5097 | |
5098 /* Map MAPFUN over the windows in F. CLOSURE is passed to each | |
5099 invocation of MAPFUN. If any invocation of MAPFUN returns | |
5100 non-zero, the mapping is halted. Otherwise, map_windows() maps | |
5101 over all windows in F. | |
5102 | |
800 | 5103 If F is null, map over all frames on all devices and consoles. |
5104 | |
428 | 5105 If MAPFUN creates or deletes windows, the behavior is undefined. */ |
5106 | |
5107 int | |
5108 map_windows (struct frame *f, int (*mapfun) (struct window *w, void *closure), | |
5109 void *closure) | |
5110 { | |
5111 if (f) | |
5112 return map_windows_1 (FRAME_ROOT_WINDOW (f), mapfun, closure); | |
5113 else | |
5114 { | |
5115 Lisp_Object frmcons, devcons, concons; | |
5116 | |
5117 FRAME_LOOP_NO_BREAK(frmcons, devcons, concons) | |
5118 { | |
5119 int v = map_windows_1 (FRAME_ROOT_WINDOW (XFRAME (XCAR (frmcons))), | |
5120 mapfun, closure); | |
5121 if (v) | |
5122 return v; | |
5123 } | |
5124 } | |
5125 | |
5126 return 0; | |
5127 } | |
5128 | |
5129 | |
5130 static void | |
2286 | 5131 modeline_shadow_thickness_changed (Lisp_Object UNUSED (specifier), |
5132 struct window *w, | |
5133 Lisp_Object UNUSED (oldval)) | |
428 | 5134 { |
5135 w->shadow_thickness_changed = 1; | |
5136 MARK_WINDOWS_CHANGED (w); | |
5137 } | |
5138 | |
5139 static void | |
2286 | 5140 vertical_divider_changed_in_window (Lisp_Object UNUSED (specifier), |
428 | 5141 struct window *w, |
2286 | 5142 Lisp_Object UNUSED (oldval)) |
428 | 5143 { |
5144 MARK_WINDOWS_CHANGED (w); | |
5145 MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (XFRAME (WINDOW_FRAME (w))); | |
5146 } | |
5147 | |
5148 /* also used in scrollbar.c */ | |
5149 void | |
2286 | 5150 some_window_value_changed (Lisp_Object UNUSED (specifier), |
5151 struct window *w, | |
5152 Lisp_Object UNUSED (oldval)) | |
428 | 5153 { |
5154 MARK_WINDOWS_CHANGED (w); | |
5155 } | |
5156 | |
5157 #ifdef MEMORY_USAGE_STATS | |
5158 | |
5159 struct window_stats | |
5160 { | |
5161 int face; | |
5162 int glyph; | |
5163 #ifdef HAVE_SCROLLBARS | |
5164 int scrollbar; | |
5165 #endif | |
5166 int line_start; | |
5167 int other_redisplay; | |
5168 int other; | |
5169 }; | |
5170 | |
5171 static void | |
5172 compute_window_mirror_usage (struct window_mirror *mir, | |
5173 struct window_stats *stats, | |
5174 struct overhead_stats *ovstats) | |
5175 { | |
5176 if (!mir) | |
5177 return; | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
5178 stats->other += lisp_object_storage_size (wrap_window_mirror (mir), ovstats); |
428 | 5179 #ifdef HAVE_SCROLLBARS |
5180 { | |
5181 struct device *d = XDEVICE (FRAME_DEVICE (mir->frame)); | |
5182 | |
5183 stats->scrollbar += | |
5184 compute_scrollbar_instance_usage (d, mir->scrollbar_vertical_instance, | |
5185 ovstats); | |
5186 stats->scrollbar += | |
5187 compute_scrollbar_instance_usage (d, mir->scrollbar_horizontal_instance, | |
5188 ovstats); | |
5189 } | |
5190 #endif /* HAVE_SCROLLBARS */ | |
5191 stats->other_redisplay += | |
5192 compute_display_line_dynarr_usage (mir->current_display_lines, ovstats); | |
5193 stats->other_redisplay += | |
5194 compute_display_line_dynarr_usage (mir->desired_display_lines, ovstats); | |
5195 } | |
5196 | |
5197 static void | |
5198 compute_window_usage (struct window *w, struct window_stats *stats, | |
5199 struct overhead_stats *ovstats) | |
5200 { | |
5201 xzero (*stats); | |
5127
a9c41067dd88
more cleanups, terminology clarification, lots of doc work
Ben Wing <ben@xemacs.org>
parents:
5126
diff
changeset
|
5202 stats->other += lisp_object_storage_size (wrap_window (w), ovstats); |
428 | 5203 stats->face += compute_face_cachel_usage (w->face_cachels, ovstats); |
5204 stats->glyph += compute_glyph_cachel_usage (w->glyph_cachels, ovstats); | |
5205 stats->line_start += | |
5206 compute_line_start_cache_dynarr_usage (w->line_start_cache, ovstats); | |
5207 compute_window_mirror_usage (find_window_mirror (w), stats, ovstats); | |
5208 } | |
5209 | |
5210 DEFUN ("window-memory-usage", Fwindow_memory_usage, 1, 1, 0, /* | |
5211 Return stats about the memory usage of window WINDOW. | |
5212 The values returned are in the form of an alist of usage types and byte | |
5213 counts. The byte counts attempt to encompass all the memory used | |
5214 by the window (separate from the memory logically associated with a | |
5215 buffer or frame), including internal structures and any malloc() | |
5216 overhead associated with them. In practice, the byte counts are | |
5217 underestimated because certain memory usage is very hard to determine | |
5218 \(e.g. the amount of memory used inside the Xt library or inside the | |
5219 X server) and because there is other stuff that might logically | |
5220 be associated with a window, buffer, or frame (e.g. window configurations, | |
5221 glyphs) but should not obviously be included in the usage counts. | |
5222 | |
5223 Multiple slices of the total memory usage may be returned, separated | |
5224 by a nil. Each slice represents a particular view of the memory, a | |
5225 particular way of partitioning it into groups. Within a slice, there | |
5226 is no overlap between the groups of memory, and each slice collectively | |
5227 represents all the memory concerned. | |
5228 */ | |
5229 (window)) | |
5230 { | |
5231 struct window_stats stats; | |
5232 struct overhead_stats ovstats; | |
5233 Lisp_Object val = Qnil; | |
5234 | |
5235 CHECK_WINDOW (window); /* dead windows should be allowed, no? */ | |
5236 xzero (ovstats); | |
5237 compute_window_usage (XWINDOW (window), &stats, &ovstats); | |
5238 | |
5239 val = acons (Qface_cache, make_int (stats.face), val); | |
5240 val = acons (Qglyph_cache, make_int (stats.glyph), val); | |
5241 #ifdef HAVE_SCROLLBARS | |
5242 val = acons (Qscrollbar_instances, make_int (stats.scrollbar), val); | |
5243 #endif | |
5244 val = acons (Qline_start_cache, make_int (stats.line_start), val); | |
5245 val = acons (Qother_redisplay, make_int (stats.other_redisplay), val); | |
5246 val = acons (Qother, make_int (stats.other), val); | |
5247 val = Fcons (Qnil, val); | |
5248 val = acons (Qactually_requested, make_int (ovstats.was_requested), val); | |
5249 val = acons (Qmalloc_overhead, make_int (ovstats.malloc_overhead), val); | |
5250 val = acons (Qdynarr_overhead, make_int (ovstats.dynarr_overhead), val); | |
5251 | |
5252 return Fnreverse (val); | |
5253 } | |
5254 | |
5255 #endif /* MEMORY_USAGE_STATS */ | |
5256 | |
5257 /* Mark all subwindows of a window as deleted. The argument | |
5258 W is actually the subwindow tree of the window in question. */ | |
5259 | |
5260 void | |
5261 delete_all_subwindows (struct window *w) | |
5262 { | |
5263 if (!NILP (w->next)) delete_all_subwindows (XWINDOW (w->next)); | |
5264 if (!NILP (w->vchild)) delete_all_subwindows (XWINDOW (w->vchild)); | |
5265 if (!NILP (w->hchild)) delete_all_subwindows (XWINDOW (w->hchild)); | |
5266 | |
5267 mark_window_as_deleted (w); | |
5268 } | |
5269 | |
1149 | 5270 |
2289 | 5271 static int |
5272 get_current_pixel_pos (Lisp_Object window, Lisp_Object pos, | |
5273 struct window **w, | |
5274 struct rune **rb, struct display_line **dl) | |
428 | 5275 { |
2289 | 5276 display_line_dynarr *dla; |
5277 struct display_block *db = NULL; | |
5278 int x, y; | |
5279 | |
5280 *rb = NULL; | |
5281 *dl = NULL; | |
5282 *w = decode_window (window); | |
5283 dla = window_display_lines (*w, CURRENT_DISP); | |
5284 x = (*w)->last_point_x[CURRENT_DISP]; | |
5285 y = (*w)->last_point_y[CURRENT_DISP]; | |
5286 if (MINI_WINDOW_P (*w)) | |
5287 return 0; | |
428 | 5288 |
5289 if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos)) | |
5290 { | |
5291 int first_line, i; | |
665 | 5292 Charbpos point; |
428 | 5293 |
5294 if (NILP (pos)) | |
5295 pos = Fwindow_point (window); | |
438 | 5296 |
428 | 5297 CHECK_INT (pos); |
5298 point = XINT (pos); | |
5299 | |
4967 | 5300 if (Dynarr_length (dla) && Dynarr_begin (dla)->modeline) |
428 | 5301 first_line = 1; |
5302 else | |
5303 first_line = 0; | |
5304 | |
5305 for (i = first_line; i < Dynarr_length (dla); i++) | |
5306 { | |
2289 | 5307 *dl = Dynarr_atp (dla, i); |
428 | 5308 /* find the vertical location first */ |
2289 | 5309 if (point >= (*dl)->charpos && point <= (*dl)->end_charpos) |
428 | 5310 { |
2289 | 5311 db = get_display_block_from_line (*dl, TEXT); |
428 | 5312 for (i = 0; i < Dynarr_length (db->runes); i++) |
5313 { | |
2289 | 5314 *rb = Dynarr_atp (db->runes, i); |
2290 | 5315 if (point <= (*rb)->charpos) |
826 | 5316 goto found_charpos; |
428 | 5317 } |
2289 | 5318 return 0; |
428 | 5319 } |
5320 } | |
2289 | 5321 return 0; |
826 | 5322 found_charpos: |
428 | 5323 ; |
5324 } | |
5325 else | |
5326 { | |
442 | 5327 /* optimized case */ |
2289 | 5328 *dl = Dynarr_atp (dla, y); |
5329 db = get_display_block_from_line (*dl, TEXT); | |
428 | 5330 |
5331 if (x >= Dynarr_length (db->runes)) | |
2289 | 5332 return 0; |
5333 | |
5334 *rb = Dynarr_atp (db->runes, x); | |
428 | 5335 } |
5336 | |
2289 | 5337 return 1; |
5338 } | |
5339 | |
5340 DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /* | |
5341 Return the horizontal pixel position of point POS in window. | |
5342 Beginning of line is column 0. If WINDOW is nil, the current window | |
5343 is assumed. If POS is nil, point is assumed. Note that POS must be | |
5344 visible for a non-nil result to be returned. This is calculated using | |
5345 the redisplay display tables; because of this, the returned value will | |
5346 only be correct if the redisplay tables are up-to-date. Use | |
5347 \"(sit-for 0)\" to insure that they are; however, if WINDOW is part of | |
5348 a new frame, use the following instead: | |
5349 (while (not (frame-visible-p frame)) (sleep-for .5)) | |
5350 */ | |
5351 (window, pos)) | |
5352 { | |
5353 struct window* w; | |
5354 struct display_line *dl; | |
5355 struct rune* rb; | |
5356 | |
5357 if (!get_current_pixel_pos(window, pos, &w, &rb, &dl)) | |
5358 return Qnil; | |
5359 | |
428 | 5360 return make_int (rb->xpos - WINDOW_LEFT (w)); |
5361 } | |
5362 | |
2289 | 5363 DEFUN ("current-pixel-row", Fcurrent_pixel_row, 0, 2, 0, /* |
5364 Return the vertical pixel position of point POS in window. Top of | |
5365 window is row 0. If WINDOW is nil, the current window is assumed. If | |
5366 POS is nil, point is assumed. Note that POS must be visible for a | |
5367 non-nil result to be returned. This is calculated using the redisplay | |
5368 display tables; because of this, the returned value will only be | |
5369 correct if the redisplay tables are up-to-date. Use \"(sit-for 0)\" | |
5370 to insure that they are; however, if WINDOW is part of a new frame, | |
5371 use the following instead: | |
5372 (while (not (frame-visible-p frame)) (sleep-for .5)) | |
5373 */ | |
5374 (window, pos)) | |
5375 { | |
5376 struct window* w; | |
5377 struct display_line *dl; | |
5378 struct rune* rb; | |
5379 | |
5380 if (!get_current_pixel_pos(window, pos, &w, &rb, &dl)) | |
5381 return Qnil; | |
5382 | |
5383 return make_int (dl->ypos - dl->ascent - WINDOW_TOP (w)); | |
5384 } | |
5385 | |
428 | 5386 |
5387 #ifdef DEBUG_XEMACS | |
5388 /* This is short and simple in elisp, but... it was written to debug | |
5389 problems purely on the C side. That is where we need to call it so | |
5390 here it is. */ | |
5391 static void | |
5392 debug_print_window (Lisp_Object window, int level) | |
5393 { | |
5394 int i; | |
5395 Lisp_Object child = Fwindow_first_vchild (window); | |
5396 | |
5397 if (NILP (child)) | |
5398 child = Fwindow_first_hchild (window); | |
5399 | |
5400 for (i = level; i > 0; i--) | |
442 | 5401 stderr_out ("\t"); |
5402 | |
5403 stderr_out ("#<window"); | |
428 | 5404 { |
5405 Lisp_Object buffer = XWINDOW (window)->buffer; | |
5406 if (!NILP (buffer) && BUFFERP (buffer)) | |
442 | 5407 stderr_out (" on %s", XSTRING_DATA (XBUFFER (buffer)->name)); |
428 | 5408 } |
5146
88bd4f3ef8e4
make lrecord UID's have a separate UID space for each object, resurrect debug SOE code in extents.c
Ben Wing <ben@xemacs.org>
parents:
5142
diff
changeset
|
5409 stderr_out (" 0x%x>", LISP_OBJECT_UID (window)); |
428 | 5410 |
5411 while (!NILP (child)) | |
5412 { | |
5413 debug_print_window (child, level + 1); | |
5414 child = Fwindow_next_child (child); | |
5415 } | |
5416 } | |
5417 | |
5418 void debug_print_windows (struct frame *f); | |
5419 void | |
5420 debug_print_windows (struct frame *f) | |
5421 { | |
5422 debug_print_window (f->root_window, 0); | |
5423 putc ('\n', stderr); | |
5424 } | |
5425 #endif /* DEBUG_XEMACS */ | |
5426 | |
5427 | |
5428 /************************************************************************/ | |
5429 /* initialization */ | |
5430 /************************************************************************/ | |
5431 | |
5432 void | |
5433 syms_of_window (void) | |
5434 { | |
5117
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
5435 INIT_LISP_OBJECT (window); |
3742ea8250b5
Checking in final CVS version of workspace 'ben-lisp-object'
Ben Wing <ben@xemacs.org>
parents:
3078
diff
changeset
|
5436 INIT_LISP_OBJECT (window_mirror); |
3092 | 5437 #ifdef NEW_GC |
5118
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
5438 INIT_LISP_OBJECT (face_cachel); |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
5439 INIT_LISP_OBJECT (face_cachel_dynarr); |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
5440 INIT_LISP_OBJECT (glyph_cachel); |
e0db3c197671
merge up to latest default branch, doesn't compile yet
Ben Wing <ben@xemacs.org>
diff
changeset
|
5441 INIT_LISP_OBJECT (glyph_cachel_dynarr); |
3092 | 5442 #endif /* NEW_GC */ |
442 | 5443 |
563 | 5444 DEFSYMBOL (Qwindowp); |
5445 DEFSYMBOL (Qwindow_live_p); | |
5446 DEFSYMBOL (Qdisplay_buffer); | |
428 | 5447 |
5448 #ifdef MEMORY_USAGE_STATS | |
563 | 5449 DEFSYMBOL (Qface_cache); |
5450 DEFSYMBOL (Qglyph_cache); | |
5451 DEFSYMBOL (Qline_start_cache); | |
428 | 5452 #ifdef HAVE_SCROLLBARS |
563 | 5453 DEFSYMBOL (Qscrollbar_instances); |
428 | 5454 #endif |
563 | 5455 DEFSYMBOL (Qother_redisplay); |
428 | 5456 /* Qother in general.c */ |
5457 #endif | |
5458 | |
707 | 5459 DEFSYMBOL (Qtruncate_partial_width_windows); |
1149 | 5460 DEFSYMBOL (Qcurrent_window_configuration); |
5461 DEFSYMBOL (Qset_window_configuration); | |
707 | 5462 |
428 | 5463 DEFSUBR (Fselected_window); |
5464 DEFSUBR (Flast_nonminibuf_window); | |
5465 DEFSUBR (Fminibuffer_window); | |
5466 DEFSUBR (Fwindow_minibuffer_p); | |
5467 DEFSUBR (Fwindowp); | |
5468 DEFSUBR (Fwindow_live_p); | |
5469 DEFSUBR (Fwindow_first_hchild); | |
5470 DEFSUBR (Fwindow_first_vchild); | |
5471 DEFSUBR (Fwindow_next_child); | |
5472 DEFSUBR (Fwindow_previous_child); | |
5473 DEFSUBR (Fwindow_parent); | |
5474 DEFSUBR (Fwindow_lowest_p); | |
5475 DEFSUBR (Fwindow_truncated_p); | |
5476 DEFSUBR (Fwindow_highest_p); | |
5477 DEFSUBR (Fwindow_leftmost_p); | |
5478 DEFSUBR (Fwindow_rightmost_p); | |
5479 DEFSUBR (Fpos_visible_in_window_p); | |
5480 DEFSUBR (Fwindow_buffer); | |
5481 DEFSUBR (Fwindow_frame); | |
5482 DEFSUBR (Fwindow_height); | |
5483 DEFSUBR (Fwindow_displayed_height); | |
5484 DEFSUBR (Fwindow_width); | |
442 | 5485 DEFSUBR (Fwindow_full_width); |
428 | 5486 DEFSUBR (Fwindow_pixel_height); |
5487 DEFSUBR (Fwindow_pixel_width); | |
442 | 5488 DEFSUBR (Fwindow_text_area_height); |
428 | 5489 DEFSUBR (Fwindow_text_area_pixel_height); |
5490 DEFSUBR (Fwindow_displayed_text_pixel_height); | |
5491 DEFSUBR (Fwindow_text_area_pixel_width); | |
5492 DEFSUBR (Fwindow_hscroll); | |
438 | 5493 DEFSUBR (Fset_window_hscroll); |
428 | 5494 DEFSUBR (Fmodeline_hscroll); |
5495 DEFSUBR (Fset_modeline_hscroll); | |
5496 DEFSUBR (Fwindow_pixel_edges); | |
5497 DEFSUBR (Fwindow_text_area_pixel_edges); | |
5498 DEFSUBR (Fwindow_point); | |
5499 DEFSUBR (Fwindow_start); | |
5500 DEFSUBR (Fwindow_end); | |
442 | 5501 DEFSUBR (Fwindow_last_line_visible_height); |
428 | 5502 DEFSUBR (Fset_window_point); |
5503 DEFSUBR (Fset_window_start); | |
5504 DEFSUBR (Fwindow_dedicated_p); | |
5505 DEFSUBR (Fset_window_dedicated_p); | |
5506 DEFSUBR (Fnext_window); | |
5507 DEFSUBR (Fprevious_window); | |
5508 DEFSUBR (Fnext_vertical_window); | |
5509 DEFSUBR (Fother_window); | |
5510 DEFSUBR (Fget_lru_window); | |
5511 DEFSUBR (Fget_largest_window); | |
5512 DEFSUBR (Fget_buffer_window); | |
5513 DEFSUBR (Fwindow_left_margin_pixel_width); | |
5514 DEFSUBR (Fwindow_right_margin_pixel_width); | |
5515 DEFSUBR (Fdelete_other_windows); | |
5516 DEFSUBR (Fdelete_windows_on); | |
5517 DEFSUBR (Freplace_buffer_in_windows); | |
5518 DEFSUBR (Fdelete_window); | |
5519 DEFSUBR (Fset_window_buffer); | |
5520 DEFSUBR (Fselect_window); | |
5521 DEFSUBR (Fsplit_window); | |
5522 DEFSUBR (Fenlarge_window); | |
5523 DEFSUBR (Fenlarge_window_pixels); | |
5524 DEFSUBR (Fshrink_window); | |
5525 DEFSUBR (Fshrink_window_pixels); | |
5526 DEFSUBR (Fscroll_up); | |
5527 DEFSUBR (Fscroll_down); | |
5528 DEFSUBR (Fscroll_left); | |
5529 DEFSUBR (Fscroll_right); | |
5530 DEFSUBR (Fother_window_for_scrolling); | |
5531 DEFSUBR (Fscroll_other_window); | |
5532 DEFSUBR (Fcenter_to_window_line); | |
5533 DEFSUBR (Fmove_to_window_line); | |
5534 #ifdef MEMORY_USAGE_STATS | |
5535 DEFSUBR (Fwindow_memory_usage); | |
5536 #endif | |
5537 DEFSUBR (Fcurrent_pixel_column); | |
2289 | 5538 DEFSUBR (Fcurrent_pixel_row); |
428 | 5539 } |
5540 | |
5541 void | |
5542 reinit_vars_of_window (void) | |
5543 { | |
5544 /* Make sure all windows get marked */ | |
5545 minibuf_window = Qnil; | |
5546 staticpro_nodump (&minibuf_window); | |
5547 } | |
5548 | |
5549 void | |
5550 vars_of_window (void) | |
5551 { | |
5552 DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /* | |
5553 *Non-nil means to scroll if point lands on a line which is clipped. | |
5554 */ ); | |
5555 scroll_on_clipped_lines = 1; | |
5556 | |
5557 DEFVAR_LISP ("temp-buffer-show-function", &Vtemp_buffer_show_function /* | |
5558 Non-nil means call as function to display a help buffer. | |
5559 The function is called with one argument, the buffer to be displayed. | |
5560 Used by `with-output-to-temp-buffer'. | |
5561 If this function is used, then it must do the entire job of showing | |
5562 the buffer; `temp-buffer-show-hook' is not run unless this function runs it. | |
442 | 5563 \(`temp-buffer-show-hook' is obsolete. Do not use in new code.) |
428 | 5564 */ ); |
5565 Vtemp_buffer_show_function = Qnil; | |
5566 | |
5567 DEFVAR_LISP ("minibuffer-scroll-window", &Vminibuffer_scroll_window /* | |
5568 Non-nil means it is the window that \\<minibuffer-local-map>\\[scroll-other-window] in minibuffer should scroll. | |
5569 */ ); | |
5570 Vminibuffer_scroll_window = Qnil; | |
5571 | |
5572 DEFVAR_LISP ("other-window-scroll-buffer", &Vother_window_scroll_buffer /* | |
5573 If non-nil, this is a buffer and \\[scroll-other-window] should scroll its window. | |
5574 */ ); | |
5575 Vother_window_scroll_buffer = Qnil; | |
5576 | |
5577 DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /* | |
5578 *Number of pixels to scroll by per requested line. | |
5579 If nil then normal line scrolling occurs regardless of line height. | |
5580 If t then scrolling is done in increments equal to the height of the default face. | |
5581 */ ); | |
5582 Vwindow_pixel_scroll_increment = Qt; | |
5583 | |
5584 DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /* | |
5585 *Number of lines of continuity when scrolling by screenfuls. | |
5586 */ ); | |
5587 next_screen_context_lines = 2; | |
5588 | |
5589 DEFVAR_INT ("window-min-height", &window_min_height /* | |
5590 *Delete any window less than this tall (including its modeline). | |
5591 */ ); | |
5592 window_min_height = 4; | |
5593 | |
5594 DEFVAR_INT ("window-min-width", &window_min_width /* | |
5595 *Delete any window less than this wide. | |
5596 */ ); | |
5597 window_min_width = 10; | |
5598 } | |
5599 | |
5600 void | |
5601 specifier_vars_of_window (void) | |
5602 { | |
5603 DEFVAR_SPECIFIER ("modeline-shadow-thickness", &Vmodeline_shadow_thickness /* | |
5604 *How thick to draw 3D shadows around modelines. | |
5605 If this is set to 0, modelines will be the traditional 2D. Sizes above | |
5606 10 will be accepted but the maximum thickness that will be drawn is 10. | |
5607 This is a specifier; use `set-specifier' to change it. | |
5608 */ ); | |
5609 Vmodeline_shadow_thickness = Fmake_specifier (Qinteger); | |
5610 /* The initial value for modeline-shadow-thickness is 2, but if the | |
5611 user removes all specifications we provide a fallback value of 0, | |
5612 which is probably what was expected. */ | |
5613 set_specifier_fallback (Vmodeline_shadow_thickness, | |
5614 list1 (Fcons (Qnil, Qzero))); | |
5615 Fadd_spec_to_specifier (Vmodeline_shadow_thickness, make_int (2), | |
5616 Qnil, Qnil, Qnil); | |
5617 set_specifier_caching (Vmodeline_shadow_thickness, | |
438 | 5618 offsetof (struct window, modeline_shadow_thickness), |
428 | 5619 modeline_shadow_thickness_changed, |
444 | 5620 0, 0, 0); |
428 | 5621 |
5622 DEFVAR_SPECIFIER ("has-modeline-p", &Vhas_modeline_p /* | |
5623 *Whether the modeline should be displayed. | |
5624 This is a specifier; use `set-specifier' to change it. | |
5625 */ ); | |
5626 Vhas_modeline_p = Fmake_specifier (Qboolean); | |
5627 set_specifier_fallback (Vhas_modeline_p, | |
5628 list1 (Fcons (Qnil, Qt))); | |
5629 set_specifier_caching (Vhas_modeline_p, | |
438 | 5630 offsetof (struct window, has_modeline_p), |
428 | 5631 /* #### It's strange that we need a special |
5632 flag to indicate that the shadow-thickness | |
5633 has changed, but not one to indicate that | |
5634 the modeline has been turned off or on. */ | |
5635 some_window_value_changed, | |
444 | 5636 0, 0, 0); |
428 | 5637 |
5638 DEFVAR_SPECIFIER ("vertical-divider-always-visible-p", | |
5639 &Vvertical_divider_always_visible_p /* | |
5640 *Should XEmacs always display vertical dividers between windows. | |
5641 | |
5642 When this is non-nil, vertical dividers are always shown, and are | |
5643 draggable. When it is nil, vertical dividers are shown only when | |
5644 there are no scrollbars in between windows, and are not draggable. | |
5645 | |
5646 This is a specifier; use `set-specifier' to change it. | |
5647 */ ); | |
5648 Vvertical_divider_always_visible_p = Fmake_specifier (Qboolean); | |
5649 set_specifier_fallback (Vvertical_divider_always_visible_p, | |
5650 list1 (Fcons (Qnil, Qt))); | |
5651 set_specifier_caching (Vvertical_divider_always_visible_p, | |
438 | 5652 offsetof (struct window, |
5653 vertical_divider_always_visible_p), | |
428 | 5654 vertical_divider_changed_in_window, |
444 | 5655 0, 0, 0); |
428 | 5656 |
5657 DEFVAR_SPECIFIER ("vertical-divider-shadow-thickness", &Vvertical_divider_shadow_thickness /* | |
5658 *How thick to draw 3D shadows around vertical dividers. | |
5659 This is a specifier; use `set-specifier' to change it. | |
5660 */ ); | |
5661 Vvertical_divider_shadow_thickness = Fmake_specifier (Qinteger); | |
5662 set_specifier_fallback (Vvertical_divider_shadow_thickness, | |
5663 list1 (Fcons (Qnil, Qzero))); | |
5664 Fadd_spec_to_specifier (Vvertical_divider_shadow_thickness, make_int (2), | |
5665 Qnil, Qnil, Qnil); | |
5666 set_specifier_caching (Vvertical_divider_shadow_thickness, | |
438 | 5667 offsetof (struct window, |
5668 vertical_divider_shadow_thickness), | |
428 | 5669 vertical_divider_changed_in_window, |
444 | 5670 0, 0, 0); |
428 | 5671 DEFVAR_SPECIFIER ("vertical-divider-line-width", &Vvertical_divider_line_width /* |
5672 *The width of the vertical dividers, not including shadows. | |
5673 | |
5674 For TTY windows, divider line is always one character wide. When | |
5675 instance of this specifier is zero in a TTY window, no divider is | |
5676 drawn at all between windows. When non-zero, a one character wide | |
5677 divider is displayed. | |
5678 | |
5679 This is a specifier; use `set-specifier' to change it. | |
5680 */ ); | |
5681 | |
5682 Vvertical_divider_line_width = Fmake_specifier (Qnatnum); | |
5683 { | |
5684 Lisp_Object fb = Qnil; | |
5685 #ifdef HAVE_TTY | |
5686 fb = Fcons (Fcons (list1 (Qtty), make_int (1)), fb); | |
5687 #endif | |
462 | 5688 #ifdef HAVE_GTK |
5689 fb = Fcons (Fcons (list1 (Qgtk), make_int (3)), fb); | |
5690 #endif | |
428 | 5691 #ifdef HAVE_X_WINDOWS |
5692 fb = Fcons (Fcons (list1 (Qx), make_int (3)), fb); | |
5693 #endif | |
5694 #ifdef HAVE_MS_WINDOWS | |
5695 /* #### This should be made magic and made to obey system settings */ | |
5696 fb = Fcons (Fcons (list1 (Qmswindows), make_int (3)), fb); | |
5697 #endif | |
5698 set_specifier_fallback (Vvertical_divider_line_width, fb); | |
5699 } | |
5700 set_specifier_caching (Vvertical_divider_line_width, | |
438 | 5701 offsetof (struct window, |
5702 vertical_divider_line_width), | |
428 | 5703 vertical_divider_changed_in_window, |
444 | 5704 0, 0, 0); |
428 | 5705 |
5706 DEFVAR_SPECIFIER ("vertical-divider-spacing", &Vvertical_divider_spacing /* | |
5707 *How much space to leave around the vertical dividers. | |
5708 | |
5709 In TTY windows, spacing is always zero, and the value of this | |
5710 specifier is ignored. | |
5711 | |
5712 This is a specifier; use `set-specifier' to change it. | |
5713 */ ); | |
5714 Vvertical_divider_spacing = Fmake_specifier (Qnatnum); | |
5715 { | |
5716 Lisp_Object fb = Qnil; | |
5717 #ifdef HAVE_TTY | |
5718 fb = Fcons (Fcons (list1 (Qtty), Qzero), fb); | |
5719 #endif | |
5720 #ifdef HAVE_X_WINDOWS | |
5721 /* #### 3D dividers look great on MS Windows with spacing = 0. | |
5722 Should not the same value be the fallback under X? - kkm */ | |
5723 fb = Fcons (Fcons (list1 (Qx), make_int (2)), fb); | |
5724 #endif | |
462 | 5725 #ifdef HAVE_GTK |
5726 fb = Fcons (Fcons (list1 (Qgtk), Qzero), fb); | |
5727 #endif | |
428 | 5728 #ifdef HAVE_MS_WINDOWS |
5729 fb = Fcons (Fcons (list1 (Qmswindows), Qzero), fb); | |
5730 #endif | |
5731 set_specifier_fallback (Vvertical_divider_spacing, fb); | |
5732 } | |
5733 set_specifier_caching (Vvertical_divider_spacing, | |
438 | 5734 offsetof (struct window, vertical_divider_spacing), |
428 | 5735 vertical_divider_changed_in_window, |
444 | 5736 0, 0, 0); |
5737 } |