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