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