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