Mercurial > hg > xemacs-beta
annotate src/redisplay-output.c @ 5090:0ca81354c4c7
Further frame-geometry cleanups
-------------------- ChangeLog entries follow: --------------------
man/ChangeLog addition:
2010-03-03 Ben Wing <ben@xemacs.org>
* internals/internals.texi (Intro to Window and Frame Geometry):
* internals/internals.texi (The Paned Area):
* internals/internals.texi (The Displayable Area):
Update to make note of e.g. the fact that the bottom gutter is
actually above the minibuffer.
src/ChangeLog addition:
2010-03-03 Ben Wing <ben@xemacs.org>
* emacs.c:
* emacs.c (assert_equal_failed):
* lisp.h:
* lisp.h (assert_equal):
New fun assert_equal, asserting that two values == each other, and
printing out both values upon failure.
* frame-gtk.c (gtk_initialize_frame_size):
* frame-impl.h:
* frame-impl.h (FRAME_TOP_INTERNAL_BORDER_START):
* frame-impl.h (FRAME_BOTTOM_INTERNAL_BORDER_START):
* frame-impl.h (FRAME_LEFT_INTERNAL_BORDER_START):
* frame-impl.h (FRAME_PANED_TOP_EDGE):
* frame-impl.h (FRAME_NONPANED_SIZE):
* frame-x.c (x_initialize_frame_size):
* frame.c:
* gutter.c (get_gutter_coords):
* gutter.c (calculate_gutter_size):
* gutter.h:
* gutter.h (WINDOW_REAL_TOP_GUTTER_BOUNDS):
* gutter.h (FRAME_TOP_GUTTER_BOUNDS):
* input-method-xlib.c:
* input-method-xlib.c (XIM_SetGeometry):
* redisplay-output.c (clear_left_border):
* redisplay-output.c (clear_right_border):
* redisplay-output.c (redisplay_output_pixmap):
* redisplay-output.c (redisplay_clear_region):
* redisplay-output.c (redisplay_clear_top_of_window):
* redisplay-output.c (redisplay_clear_to_window_end):
* redisplay-xlike-inc.c (XLIKE_clear_frame):
* redisplay.c:
* redisplay.c (UPDATE_CACHE_RETURN):
* redisplay.c (pixel_to_glyph_translation):
* toolbar.c (update_frame_toolbars_geometry):
* window.c (Fwindow_pixel_edges):
Get rid of some redundant macros. Consistently use the
FRAME_TOP_*_START, FRAME_RIGHT_*_END, etc. format. Rename
FRAME_*_BORDER_* to FRAME_*_INTERNAL_BORDER_*. Comment out
FRAME_BOTTOM_* for gutters and the paned area due to the
uncertainty over where the paned area actually begins. (Eventually
we should probably move the gutters outside the minibuffer so that
the paned area is contiguous.) Use FRAME_PANED_* more often in the
code to make things clearer.
Update the diagram to show that the bottom gutter is inside the
minibuffer (!) and that there are "junk boxes" when you have left
and/or right gutters (dead boxes that are mistakenly left uncleared,
unlike the corresponding scrollbar dead boxes). Update the text
appropriately to cover the bottom gutter position, etc.
Rewrite gutter-geometry code to use the FRAME_*_GUTTER_* in place of
equivalent expressions referencing other frame elements, to make the
code more portable in case we move around the gutter location.
Cleanup FRAME_*_GUTTER_BOUNDS() in gutter.h.
Add some #### GEOM! comments where I think code is incorrect --
typically, it wasn't fixed up properly when the gutter was added.
Some cosmetic changes.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Wed, 03 Mar 2010 05:07:47 -0600 |
parents | 5502045ec510 |
children | 308d34e9f07d |
rev | line source |
---|---|
428 | 1 /* Synchronize redisplay structures and output changes. |
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. | |
1318 | 3 Copyright (C) 1995, 1996, 2002, 2003 Ben Wing. |
428 | 4 Copyright (C) 1996 Chuck Thompson. |
863 | 5 Copyright (C) 1999, 2002 Andy Piper. |
5080
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5074
diff
changeset
|
6 Copyright (C) 2010 Didier Verna |
428 | 7 |
8 This file is part of XEmacs. | |
9 | |
10 XEmacs is free software; you can redistribute it and/or modify it | |
11 under the terms of the GNU General Public License as published by the | |
12 Free Software Foundation; either version 2, or (at your option) any | |
13 later version. | |
14 | |
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 for more details. | |
19 | |
20 You should have received a copy of the GNU General Public License | |
21 along with XEmacs; see the file COPYING. If not, write to | |
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
23 Boston, MA 02111-1307, USA. */ | |
24 | |
25 /* Synched up with: Not in FSF. */ | |
26 | |
27 /* This file has been Mule-ized. */ | |
28 | |
29 /* Author: Chuck Thompson */ | |
30 | |
31 /* Heavily hacked for modularity, gutter and subwindow support by Andy | |
32 Piper. */ | |
33 | |
34 #include <config.h> | |
35 #include "lisp.h" | |
36 | |
37 #include "buffer.h" | |
38 #include "window.h" | |
872 | 39 #include "frame-impl.h" |
40 #include "device-impl.h" | |
428 | 41 #include "glyphs.h" |
42 #include "redisplay.h" | |
43 #include "faces.h" | |
446 | 44 #include "gutter.h" |
428 | 45 |
46 static int compare_runes (struct window *w, struct rune *crb, | |
47 struct rune *drb); | |
48 static void redraw_cursor_in_window (struct window *w, | |
49 int run_end_begin_glyphs); | |
50 static void redisplay_output_display_block (struct window *w, struct display_line *dl, | |
51 int block, int start, int end, int start_pixpos, | |
434 | 52 int cursor_start, int cursor_width, |
428 | 53 int cursor_height); |
434 | 54 static void redisplay_normalize_display_box (struct display_box* dest, |
428 | 55 struct display_glyph_area* src); |
56 static int redisplay_display_boxes_in_window_p (struct window* w, | |
57 struct display_box* db, | |
58 struct display_glyph_area* dga); | |
434 | 59 static void redisplay_clear_clipped_region (Lisp_Object locale, face_index findex, |
60 struct display_box* dest, | |
61 struct display_glyph_area* glyphsrc, | |
428 | 62 int fullheight_p, Lisp_Object); |
1318 | 63 static void redisplay_redraw_exposed_windows (Lisp_Object window, int x, |
64 int y, int width, int height); | |
428 | 65 |
66 /***************************************************************************** | |
67 sync_rune_structs | |
68 | |
69 Synchronize the given rune blocks. | |
70 ****************************************************************************/ | |
71 static void | |
2286 | 72 sync_rune_structs (struct window *UNUSED (w), rune_dynarr *cra, |
73 rune_dynarr *dra) | |
428 | 74 { |
75 int rune_elt; | |
76 int max_move = ((Dynarr_length (dra) > Dynarr_largest (cra)) | |
77 ? Dynarr_largest (cra) | |
78 : Dynarr_length (dra)); | |
79 | |
80 if (max_move) | |
81 { | |
82 /* #### Doing this directly breaks the encapsulation. But, the | |
4187 | 83 running time of this function has a measurable impact on |
84 redisplay performance so avoiding all excess overhead is a | |
85 good thing. Is all of this true? */ | |
428 | 86 memcpy (cra->base, dra->base, sizeof (struct rune) * max_move); |
5038 | 87 Dynarr_set_lengthr (cra, max_move); |
428 | 88 } |
89 else | |
90 Dynarr_reset (cra); | |
91 | |
92 for (rune_elt = max_move; rune_elt < Dynarr_length (dra); rune_elt++) | |
93 { | |
94 struct rune rb, *crb; | |
95 struct rune *drb = Dynarr_atp (dra, rune_elt); | |
96 | |
97 crb = &rb; | |
98 memcpy (crb, drb, sizeof (struct rune)); | |
99 Dynarr_add (cra, *crb); | |
100 } | |
101 } | |
102 | |
103 /***************************************************************************** | |
104 sync_display_line_structs | |
105 | |
106 For the given LINE in window W, make the current display line equal | |
107 the desired display line. | |
108 ****************************************************************************/ | |
442 | 109 void |
428 | 110 sync_display_line_structs (struct window *w, int line, int do_blocks, |
111 display_line_dynarr *cdla, | |
112 display_line_dynarr *ddla) | |
113 { | |
114 struct display_line dl, *clp, *dlp; | |
115 int db_elt; | |
800 | 116 int local = 0; |
428 | 117 |
4207 | 118 /* #### NOTE: practically, this is not needed because of the memcpy below. |
119 #### However, it's cleaner and bugs-in-the-future proof. -- dvl */ | |
120 DISPLAY_LINE_INIT (dl); | |
428 | 121 dlp = Dynarr_atp (ddla, line); |
122 if (line >= Dynarr_largest (cdla)) | |
123 { | |
124 clp = &dl; | |
125 clp->display_blocks = Dynarr_new (display_block); | |
800 | 126 local = 1; |
428 | 127 } |
128 else | |
129 { | |
130 clp = Dynarr_atp (cdla, line); | |
131 if (clp->display_blocks) | |
132 Dynarr_reset (clp->display_blocks); | |
133 if (clp->left_glyphs) | |
134 { | |
135 Dynarr_free (clp->left_glyphs); | |
136 clp->left_glyphs = 0; | |
137 } | |
138 if (clp->right_glyphs) | |
139 { | |
140 Dynarr_free (clp->right_glyphs); | |
141 clp->right_glyphs = 0; | |
142 } | |
143 } | |
144 { | |
145 display_block_dynarr *tdb = clp->display_blocks; | |
146 | |
147 memcpy (clp, dlp, sizeof (struct display_line)); | |
148 clp->display_blocks = tdb; | |
149 clp->left_glyphs = 0; | |
150 clp->right_glyphs = 0; | |
151 } | |
152 | |
800 | 153 if (do_blocks || line < Dynarr_length (cdla)) |
428 | 154 { |
800 | 155 for (db_elt = 0; db_elt < Dynarr_length (dlp->display_blocks); db_elt++) |
156 { | |
157 struct display_block db, *cdb; | |
158 struct display_block *ddb = Dynarr_atp (dlp->display_blocks, db_elt); | |
159 | |
160 if (db_elt >= Dynarr_largest (clp->display_blocks)) | |
161 { | |
162 cdb = &db; | |
163 memcpy (cdb, ddb, sizeof (struct display_block)); | |
164 cdb->runes = Dynarr_new (rune); | |
165 Dynarr_add (clp->display_blocks, *cdb); | |
166 } | |
167 else | |
168 { | |
169 rune_dynarr *tr; | |
170 | |
171 cdb = Dynarr_atp (clp->display_blocks, db_elt); | |
172 tr = cdb->runes; | |
173 memcpy (cdb, ddb, sizeof (struct display_block)); | |
174 cdb->runes = tr; | |
5038 | 175 Dynarr_incrementr (clp->display_blocks); |
800 | 176 } |
177 | |
178 sync_rune_structs (w, cdb->runes, ddb->runes); | |
179 } | |
428 | 180 } |
181 | |
800 | 182 if (local) |
183 Dynarr_add (cdla, *clp); | |
184 else if (line >= Dynarr_length (cdla)) | |
428 | 185 { |
800 | 186 assert (line == Dynarr_length (cdla)); |
5038 | 187 Dynarr_incrementr (cdla); |
428 | 188 } |
189 } | |
190 | |
191 /***************************************************************************** | |
192 compare_runes | |
193 | |
448 | 194 Compare two runes to see if each of their fields is equal. If so, |
428 | 195 return true otherwise return false. |
196 ****************************************************************************/ | |
197 static int | |
198 compare_runes (struct window *w, struct rune *crb, struct rune *drb) | |
199 { | |
665 | 200 /* Do not compare the values of charbpos and endpos. They do not |
428 | 201 affect the display characteristics. */ |
202 | |
203 /* Note: (hanoi 6) spends 95% of its time in redisplay, and about | |
204 30% here. Not using bitfields for rune.type alone gives a redisplay | |
205 speed up of 10%. | |
206 | |
207 #### In profile arcs run of a normal Gnus session this function | |
208 is run 6.76 million times, only to return 1 in 6.73 million of | |
209 those. | |
210 | |
211 In addition a quick look GCC sparc assembly shows that GCC is not | |
212 doing a good job here. | |
213 1. The function is not inlined (too complicated?) | |
214 2. It seems to be reloading the crb and drb variables all the | |
215 time. | |
216 3. It doesn't seem to notice that the second half of these if's | |
217 are really a switch statement. | |
218 | |
219 So I (JV) conjecture | |
220 | |
221 #### It would really be worth it to arrange for this function to | |
222 be (almost) a single call to memcmp. */ | |
434 | 223 |
442 | 224 if (crb->xpos != drb->xpos) |
428 | 225 return 0; |
226 else if (crb->width != drb->width) | |
227 return 0; | |
228 else if (crb->cursor_type != drb->cursor_type) | |
229 return 0; | |
230 else if (crb->type != drb->type) | |
231 return 0; | |
232 else if (crb->type == RUNE_CHAR && | |
233 (crb->object.chr.ch != drb->object.chr.ch)) | |
234 return 0; | |
235 else if (crb->type == RUNE_HLINE && | |
236 (crb->object.hline.thickness != drb->object.hline.thickness || | |
237 crb->object.hline.yoffset != drb->object.hline.yoffset)) | |
238 return 0; | |
434 | 239 else if (crb->type == RUNE_DGLYPH && |
428 | 240 (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) || |
241 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) || | |
819 | 242 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset || |
243 crb->object.dglyph.yoffset != drb->object.dglyph.yoffset || | |
4187 | 244 crb->object.dglyph.ascent != drb->object.dglyph.ascent || |
245 crb->object.dglyph.descent != drb->object.dglyph.descent)) | |
428 | 246 return 0; |
247 /* Only check dirtiness if we know something has changed. */ | |
248 else if (crb->type == RUNE_DGLYPH && | |
442 | 249 (XGLYPH_DIRTYP (crb->object.dglyph.glyph) || |
250 crb->findex != drb->findex)) | |
428 | 251 { |
442 | 252 /* We need some way of telling redisplay_output_layout () that the |
4187 | 253 only reason we are outputting it is because something has |
254 changed internally. That way we can optimize whether we need | |
255 to clear the layout first and also only output the components | |
256 that have changed. The image_instance dirty flag and | |
257 display_hash are no good to us because these will invariably | |
258 have been set anyway if the layout has changed. So it looks | |
259 like we need yet another change flag that we can set here and | |
260 then clear in redisplay_output_layout (). */ | |
442 | 261 Lisp_Object window, image; |
262 Lisp_Image_Instance* ii; | |
793 | 263 window = wrap_window (w); |
442 | 264 image = glyph_image_instance (crb->object.dglyph.glyph, |
793 | 265 window, ERROR_ME_DEBUG_WARN, 1); |
442 | 266 |
267 if (!IMAGE_INSTANCEP (image)) | |
268 return 0; | |
269 ii = XIMAGE_INSTANCE (image); | |
270 | |
271 if (TEXT_IMAGE_INSTANCEP (image) && | |
272 (crb->findex != drb->findex || | |
273 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))) | |
428 | 274 return 0; |
442 | 275 |
276 /* It is quite common for the two glyphs to be EQ since in many | |
277 cases they will actually be the same object. This does not | |
278 mean, however, that nothing has changed. We therefore need to | |
279 check the current hash of the glyph against the last recorded | |
280 display hash and the pending display items. See | |
281 update_subwindow (). */ | |
282 if (image_instance_changed (image) || | |
283 crb->findex != drb->findex || | |
284 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)) | |
285 { | |
638 | 286 /* Now we are going to re-output the glyph, but since |
442 | 287 this is for some internal reason not related to geometry |
288 changes, send a hint to the output routines that they can | |
289 take some short cuts. This is most useful for | |
290 layouts. This flag should get reset by the output | |
291 routines. | |
292 | |
293 #### It is possible for us to get here when the | |
294 face_cachel is dirty. I do not know what the implications | |
295 of this are.*/ | |
296 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (ii) = 1; | |
297 return 0; | |
298 } | |
434 | 299 else |
428 | 300 return 1; |
301 } | |
442 | 302 /* We now do this last so that glyph checks can do their own thing |
303 for face changes. Face changes quite often happen when we are | |
304 trying to output something in the gutter, this would normally | |
305 lead to a lot of flashing. The indices can quite often be | |
306 different and yet the faces are the same, we do not want to | |
307 re-output in this instance. */ | |
308 else if (crb->findex != drb->findex || | |
309 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)) | |
310 return 0; | |
428 | 311 else |
312 return 1; | |
313 } | |
314 | |
851 | 315 #if 0 |
316 void | |
317 compare_runes_2 (struct window *w, struct rune *crb, struct rune *drb) | |
318 { | |
319 if (crb->type == DGLYPH) | |
320 { | |
321 if (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) || | |
322 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) || | |
323 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset || | |
324 crb->object.dglyph.yoffset != drb->object.dglyph.yoffset || | |
325 crb->object.dglyph.ascent != drb->object.dglyph.ascent || | |
326 crb->object.dglyph.descent != drb->object.dglyph.descent) | |
327 return 0; | |
328 /* Only check dirtiness if we know something has changed. */ | |
329 else if (XGLYPH_DIRTYP (crb->object.dglyph.glyph) || | |
330 crb->findex != drb->findex) | |
331 { | |
332 /* We need some way of telling redisplay_output_layout () that the | |
333 only reason we are outputting it is because something has | |
334 changed internally. That way we can optimize whether we need | |
335 to clear the layout first and also only output the components | |
336 that have changed. The image_instance dirty flag and | |
337 display_hash are no good to us because these will invariably | |
338 have been set anyway if the layout has changed. So it looks | |
339 like we need yet another change flag that we can set here and | |
340 then clear in redisplay_output_layout (). */ | |
341 Lisp_Object window, image; | |
342 Lisp_Image_Instance* ii; | |
343 window = wrap_window (w); | |
344 image = glyph_image_instance (crb->object.dglyph.glyph, | |
345 window, crb->object.dglyph.matchspec, | |
346 ERROR_ME_DEBUG_WARN, 1); | |
4187 | 347 |
851 | 348 if (!IMAGE_INSTANCEP (image)) |
349 return 0; | |
350 ii = XIMAGE_INSTANCE (image); | |
4187 | 351 |
851 | 352 if (TEXT_IMAGE_INSTANCEP (image) && |
353 (crb->findex != drb->findex || | |
354 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))) | |
355 return 0; | |
4187 | 356 |
851 | 357 /* It is quite common for the two glyphs to be EQ since in many |
358 cases they will actually be the same object. This does not | |
359 mean, however, that nothing has changed. We therefore need to | |
360 check the current hash of the glyph against the last recorded | |
361 display hash and the pending display items. See | |
362 update_widget () ^^#### which function?. */ | |
363 if (image_instance_changed (image) || | |
364 crb->findex != drb->findex || | |
365 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)) | |
366 { | |
367 /* Now we are going to re-output the glyph, but since | |
368 this is for some internal reason not related to geometry | |
369 changes, send a hint to the output routines that they can | |
370 take some short cuts. This is most useful for | |
371 layouts. This flag should get reset by the output | |
372 routines. | |
4187 | 373 |
851 | 374 #### It is possible for us to get here when the |
375 face_cachel is dirty. I do not know what the implications | |
376 of this are.*/ | |
377 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (ii) = 1; | |
378 return 0; | |
379 } | |
380 else | |
381 return 1; | |
382 } | |
383 else if (crb->findex != drb->findex || | |
384 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)) | |
385 return 0; | |
386 else | |
387 return 1; | |
388 } | |
389 else return !(memcmp (crb, drb, sizeof (*crb)) || | |
390 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)); | |
391 } | |
392 #endif | |
393 | |
394 | |
428 | 395 /***************************************************************************** |
396 get_next_display_block | |
397 | |
398 Return the next display starting at or overlapping START_POS. Return | |
399 the start of the next region in NEXT_START. | |
400 ****************************************************************************/ | |
401 int | |
402 get_next_display_block (layout_bounds bounds, display_block_dynarr *dba, | |
403 int start_pos, int *next_start) | |
404 { | |
405 int next_display_block = NO_BLOCK; | |
406 int priority = -1; | |
407 int block; | |
408 | |
409 /* If we don't find a display block covering or starting at | |
410 start_pos, then we return the starting point of the next display | |
411 block or the next division boundary, whichever is closer to | |
412 start_pos. */ | |
413 if (next_start) | |
414 { | |
415 if (start_pos >= bounds.left_out && start_pos < bounds.left_in) | |
416 *next_start = bounds.left_in; | |
417 else if (start_pos < bounds.left_white) | |
418 *next_start = bounds.left_white; | |
419 else if (start_pos < bounds.right_white) | |
420 *next_start = bounds.right_white; | |
421 else if (start_pos < bounds.right_in) | |
422 *next_start = bounds.right_in; | |
423 else if (start_pos <= bounds.right_out) | |
424 *next_start = bounds.right_out; | |
425 else | |
4932 | 426 { |
427 ABORT (); | |
428 *next_start = 0; | |
429 } | |
428 | 430 } |
431 | |
432 for (block = 0; block < Dynarr_length (dba); block++) | |
433 { | |
434 struct display_block *db = Dynarr_atp (dba, block); | |
435 | |
436 if (db->start_pos <= start_pos && db->end_pos > start_pos) | |
437 { | |
438 if ((int) db->type > priority) | |
439 { | |
440 priority = db->type; | |
441 next_display_block = block; | |
442 if (next_start) | |
443 *next_start = db->end_pos; | |
444 } | |
445 } | |
446 else if (next_start && db->start_pos > start_pos) | |
447 { | |
448 if (db->start_pos < *next_start) | |
449 *next_start = db->start_pos; | |
450 } | |
451 } | |
452 | |
453 return next_display_block; | |
454 } | |
455 | |
456 /***************************************************************************** | |
457 get_cursor_size_and_location | |
458 | |
459 Return the information defining the pixel location of the cursor. | |
460 ****************************************************************************/ | |
461 static void | |
462 get_cursor_size_and_location (struct window *w, struct display_block *db, | |
463 int cursor_location, | |
464 int *cursor_start, int *cursor_width, | |
465 int *cursor_height) | |
466 { | |
467 struct rune *rb; | |
468 Lisp_Object window; | |
469 int defheight, defwidth; | |
470 | |
471 if (Dynarr_length (db->runes) <= cursor_location) | |
2500 | 472 ABORT (); |
428 | 473 |
793 | 474 window = wrap_window (w); |
428 | 475 |
476 rb = Dynarr_atp (db->runes, cursor_location); | |
477 *cursor_start = rb->xpos; | |
478 | |
5047
07dcc7000bbf
put width before height consistently, fix a real bug found in the process
Ben Wing <ben@xemacs.org>
parents:
5045
diff
changeset
|
479 default_face_width_and_height (window, &defwidth, &defheight); |
428 | 480 *cursor_height = defheight; |
481 | |
482 if (rb->type == RUNE_BLANK) | |
483 *cursor_width = defwidth; | |
484 else | |
485 *cursor_width = rb->width; | |
486 } | |
487 | |
488 /***************************************************************************** | |
489 compare_display_blocks | |
490 | |
491 Given two display blocks, output only those areas where they differ. | |
492 ****************************************************************************/ | |
493 static int | |
494 compare_display_blocks (struct window *w, struct display_line *cdl, | |
495 struct display_line *ddl, int c_block, int d_block, | |
496 int start_pixpos, int cursor_start, int cursor_width, | |
497 int cursor_height) | |
498 { | |
499 struct frame *f = XFRAME (w->frame); | |
500 struct display_block *cdb, *ddb; | |
501 int start_pos; | |
502 int stop_pos; | |
503 int force = 0; | |
2286 | 504 #if 0 |
428 | 505 int block_end; |
2286 | 506 #endif |
428 | 507 |
508 cdb = Dynarr_atp (cdl->display_blocks, c_block); | |
509 ddb = Dynarr_atp (ddl->display_blocks, d_block); | |
510 | |
511 assert (cdb->type == ddb->type); | |
512 | |
513 start_pos = -1; | |
514 stop_pos = min (Dynarr_length (cdb->runes), Dynarr_length (ddb->runes)); | |
515 | |
2286 | 516 #if 0 |
428 | 517 block_end = |
518 (!Dynarr_length (ddb->runes) | |
519 ? 0 | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4207
diff
changeset
|
520 : (Dynarr_lastp (ddb->runes)->xpos + |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4207
diff
changeset
|
521 Dynarr_lastp (ddb->runes)->width)); |
2286 | 522 #endif |
428 | 523 |
524 /* If the new block type is not text and the cursor status is | |
525 changing and it overlaps the position of this block then force a | |
526 full redraw of the block in order to make sure that the cursor is | |
527 updated properly. */ | |
528 if (ddb->type != TEXT | |
529 #if 0 | |
530 /* I'm not sure exactly what this code wants to do, but it's | |
531 * not right--it doesn't update when cursor_elt changes from, e.g., | |
532 * 0 to 8, and the new or old cursor loc overlaps this block. | |
533 * I've replaced it with the more conservative test below. | |
534 * -dkindred@cs.cmu.edu 23-Mar-1997 */ | |
535 && ((cdl->cursor_elt == -1 && ddl->cursor_elt != -1) | |
536 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)) | |
537 && (ddl->cursor_elt == -1 || | |
538 (cursor_start | |
539 && cursor_width | |
540 && (cursor_start + cursor_width) >= start_pixpos | |
541 && cursor_start <= block_end)) | |
542 #else | |
543 && (cdl->cursor_elt != ddl->cursor_elt) | |
544 #endif | |
545 ) | |
546 force = 1; | |
547 | |
548 if (f->windows_structure_changed || | |
549 /* #### Why is this so? We have face cachels so that we don't | |
4187 | 550 have to recalculate all the display blocks when faces |
551 change. I have fixed this for glyphs and am inclined to think | |
552 that faces should "Just Work", but I'm not feeling brave | |
553 today. Maybe its because the face cachels represent merged | |
554 faces rather than simply instantiations in a particular | |
555 domain. */ | |
428 | 556 f->faces_changed || |
557 cdl->ypos != ddl->ypos || | |
558 cdl->ascent != ddl->ascent || | |
559 cdl->descent != ddl->descent || | |
560 cdl->clip != ddl->clip || | |
561 force) | |
562 { | |
563 start_pos = 0; | |
564 force = 1; | |
565 } | |
566 else | |
567 { | |
568 int elt = 0; | |
569 | |
570 while (start_pos < 0 && elt < stop_pos) | |
571 { | |
572 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt), | |
573 Dynarr_atp (ddb->runes, elt))) | |
574 { | |
575 start_pos = elt; | |
576 } | |
577 else | |
578 { | |
579 elt++; | |
580 } | |
581 } | |
582 | |
583 /* If nothing has changed in the area where the blocks overlap, but | |
584 there are new blocks in the desired block, then adjust the start | |
585 point accordingly. */ | |
586 if (elt == stop_pos && stop_pos < Dynarr_length (ddb->runes)) | |
587 start_pos = stop_pos; | |
588 } | |
589 | |
590 if (start_pos >= 0) | |
591 { | |
592 if ((Dynarr_length (ddb->runes) != Dynarr_length (cdb->runes)) | |
593 || force) | |
594 { | |
595 stop_pos = Dynarr_length (ddb->runes); | |
596 } | |
597 else | |
598 { | |
599 /* If the lines have the same number of runes and we are not | |
600 forcing a full redraw because the display line has | |
601 changed position then we try and optimize how much of the | |
602 line we actually redraw by scanning backwards from the | |
603 end for the first changed rune. This optimization is | |
604 almost always triggered by face changes. */ | |
605 | |
606 int elt = Dynarr_length (ddb->runes) - 1; | |
607 | |
608 while (elt > start_pos) | |
609 { | |
610 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt), | |
611 Dynarr_atp (ddb->runes, elt))) | |
612 break; | |
613 else | |
614 elt--; | |
615 } | |
616 stop_pos = elt + 1; | |
617 } | |
618 | |
619 redisplay_output_display_block (w, ddl, d_block, start_pos, | |
620 stop_pos, start_pixpos, | |
621 cursor_start, cursor_width, | |
622 cursor_height); | |
623 return 1; | |
624 } | |
625 | |
626 return 0; | |
627 } | |
628 | |
629 /***************************************************************************** | |
630 clear_left_border | |
631 | |
632 Clear the lefthand outside border. | |
633 ****************************************************************************/ | |
634 static void | |
635 clear_left_border (struct window *w, int y, int height) | |
636 { | |
637 struct frame *f = XFRAME (w->frame); | |
793 | 638 Lisp_Object window = wrap_window (w); |
428 | 639 |
640 redisplay_clear_region (window, DEFAULT_INDEX, | |
5090 | 641 FRAME_LEFT_INTERNAL_BORDER_START (f), y, |
642 FRAME_INTERNAL_BORDER_WIDTH (f), height); | |
428 | 643 } |
644 | |
645 /***************************************************************************** | |
646 clear_right_border | |
647 | |
648 Clear the righthand outside border. | |
649 ****************************************************************************/ | |
650 static void | |
651 clear_right_border (struct window *w, int y, int height) | |
652 { | |
653 struct frame *f = XFRAME (w->frame); | |
793 | 654 Lisp_Object window = wrap_window (w); |
428 | 655 |
656 redisplay_clear_region (window, DEFAULT_INDEX, | |
5090 | 657 FRAME_RIGHT_INTERNAL_BORDER_START (f), |
658 y, FRAME_INTERNAL_BORDER_WIDTH (f), height); | |
428 | 659 } |
660 | |
661 /***************************************************************************** | |
662 output_display_line | |
663 | |
664 Ensure that the contents of the given display line is correct | |
665 on-screen. The force_ parameters are used by redisplay_move_cursor | |
666 to correctly update cursor locations and only cursor locations. | |
667 ****************************************************************************/ | |
668 void | |
669 output_display_line (struct window *w, display_line_dynarr *cdla, | |
670 display_line_dynarr *ddla, int line, int force_start, | |
671 int force_end) | |
672 | |
673 { | |
674 struct frame *f = XFRAME (w->frame); | |
675 struct buffer *b = XBUFFER (w->buffer); | |
676 struct buffer *old_b = window_display_buffer (w); | |
677 struct display_line *cdl, *ddl; | |
678 display_block_dynarr *cdba, *ddba; | |
679 int start_pixpos, end_pixpos; | |
680 int cursor_start, cursor_width, cursor_height; | |
681 | |
682 int force = (force_start >= 0 || force_end >= 0); | |
683 int clear_border = 0; | |
684 int must_sync = 0; | |
685 | |
686 if (cdla && line < Dynarr_length (cdla)) | |
687 { | |
688 cdl = Dynarr_atp (cdla, line); | |
689 cdba = cdl->display_blocks; | |
690 } | |
691 else | |
692 { | |
693 cdl = NULL; | |
694 cdba = NULL; | |
695 } | |
696 | |
4844
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4207
diff
changeset
|
697 /* The following will assert line < Dynarr_length (ddla) */ |
91b3d00e717f
Various cleanups for Dynarr code, from Unicode-internal ws
Ben Wing <ben@xemacs.org>
parents:
4207
diff
changeset
|
698 ddl = Dynarr_atp (ddla, line); |
428 | 699 ddba = ddl->display_blocks; |
700 | |
701 if (force_start >= 0 && force_start >= ddl->bounds.left_out) | |
702 start_pixpos = force_start; | |
703 else | |
704 start_pixpos = ddl->bounds.left_out; | |
705 | |
706 if (force_end >= 0 && force_end < ddl->bounds.right_out) | |
707 end_pixpos = force_end; | |
708 else | |
709 end_pixpos = ddl->bounds.right_out; | |
710 | |
711 /* Get the cursor parameters. */ | |
712 if (ddl->cursor_elt != -1) | |
713 { | |
714 struct display_block *db; | |
715 | |
716 /* If the lines cursor parameter is not -1 then it indicates | |
4187 | 717 which rune in the TEXT block contains the cursor. This means |
718 that there must be at least one display block. The TEXT | |
719 block, if present, must always be the first display block. */ | |
428 | 720 assert (Dynarr_length (ddba) != 0); |
721 | |
4967 | 722 db = Dynarr_begin (ddba); |
428 | 723 assert (db->type == TEXT); |
724 | |
725 get_cursor_size_and_location (w, db, ddl->cursor_elt, &cursor_start, | |
726 &cursor_width, &cursor_height); | |
727 } | |
728 else | |
729 { | |
730 cursor_start = cursor_width = cursor_height = 0; | |
731 } | |
732 | |
733 /* The modeline should only have a single block and it had better be | |
734 a TEXT block. */ | |
735 if (ddl->modeline) | |
736 { | |
737 /* The shadow thickness check is necessary if only the sign of | |
4187 | 738 the size changed. */ |
428 | 739 if (cdba && !w->shadow_thickness_changed) |
740 { | |
741 must_sync |= compare_display_blocks (w, cdl, ddl, 0, 0, | |
742 start_pixpos, 0, 0, 0); | |
743 } | |
744 else | |
745 { | |
746 redisplay_output_display_block (w, ddl, 0, 0, -1, start_pixpos, | |
747 0, 0, 0); | |
748 must_sync = 1; | |
749 } | |
750 | |
751 if (must_sync) | |
752 clear_border = 1; | |
753 } | |
754 | |
755 while (!ddl->modeline && start_pixpos < end_pixpos) | |
756 { | |
757 int block; | |
758 int next_start_pixpos; | |
759 | |
760 block = get_next_display_block (ddl->bounds, ddba, start_pixpos, | |
761 &next_start_pixpos); | |
762 | |
763 /* If we didn't find a block then we should blank the area | |
4187 | 764 between start_pos and next_start if necessary. */ |
428 | 765 if (block == NO_BLOCK) |
766 { | |
767 /* We only erase those areas which were actually previously | |
4187 | 768 covered by a display block unless the window structure |
769 changed. In that case we clear all areas since the current | |
770 structures may actually represent a different buffer. */ | |
428 | 771 while (start_pixpos < next_start_pixpos) |
772 { | |
773 int block_end; | |
774 int old_block; | |
775 | |
776 if (cdba) | |
777 old_block = get_next_display_block (ddl->bounds, cdba, | |
778 start_pixpos, &block_end); | |
779 else | |
780 { | |
781 old_block = NO_BLOCK; | |
782 block_end = next_start_pixpos; | |
783 } | |
784 | |
785 if (!cdba || old_block != NO_BLOCK || b != old_b || | |
786 f->windows_structure_changed || | |
787 f->faces_changed || | |
788 force || | |
789 (cdl && (cdl->ypos != ddl->ypos || | |
790 cdl->ascent != ddl->ascent || | |
791 cdl->descent != ddl->descent || | |
792 cdl->top_clip != ddl->top_clip || | |
793 cdl->clip != ddl->clip))) | |
794 { | |
795 int x, y, width, height; | |
796 face_index findex; | |
797 | |
798 must_sync = 1; | |
799 x = start_pixpos; | |
800 y = DISPLAY_LINE_YPOS (ddl); | |
801 width = min (next_start_pixpos, block_end) - x; | |
802 height = DISPLAY_LINE_HEIGHT (ddl); | |
803 | |
804 if (x < ddl->bounds.left_in) | |
805 { | |
4187 | 806 findex = (ddl->left_margin_findex > DEFAULT_INDEX) ? |
434 | 807 ddl->left_margin_findex |
428 | 808 : get_builtin_face_cache_index (w, Vleft_margin_face); |
809 } | |
810 else if (x < ddl->bounds.right_in) | |
811 { | |
4187 | 812 findex = (ddl->default_findex >= DEFAULT_INDEX) ? |
813 ddl->default_findex | |
814 : DEFAULT_INDEX; | |
428 | 815 } |
816 else if (x < ddl->bounds.right_out) | |
817 { | |
4187 | 818 findex = (ddl->right_margin_findex > DEFAULT_INDEX) ? |
434 | 819 ddl->right_margin_findex |
428 | 820 : get_builtin_face_cache_index (w, Vright_margin_face); |
821 } | |
822 else | |
823 findex = (face_index) -1; | |
824 | |
825 if (findex != (face_index) -1) | |
826 { | |
793 | 827 Lisp_Object window = wrap_window (w); |
428 | 828 |
829 | |
830 /* Clear the empty area. */ | |
831 redisplay_clear_region (window, findex, x, y, width, height); | |
832 | |
833 /* Mark that we should clear the border. This is | |
834 necessary because italic fonts may leave | |
835 droppings in the border. */ | |
836 clear_border = 1; | |
837 } | |
838 } | |
839 | |
840 start_pixpos = min (next_start_pixpos, block_end); | |
841 } | |
842 } | |
843 else | |
844 { | |
845 struct display_block *cdb, *ddb; | |
846 int block_end; | |
847 int old_block; | |
848 | |
849 if (cdba) | |
850 old_block = get_next_display_block (ddl->bounds, cdba, | |
851 start_pixpos, &block_end); | |
852 else | |
853 old_block = NO_BLOCK; | |
854 | |
855 ddb = Dynarr_atp (ddba, block); | |
856 cdb = (old_block != NO_BLOCK ? Dynarr_atp (cdba, old_block) : 0); | |
857 | |
858 /* If there was formerly no block over the current | |
859 region or if it was a block of a different type, then | |
860 output the entire ddb. Otherwise, compare cdb and | |
861 ddb and output only the changed region. */ | |
434 | 862 if (!force && cdb && ddb->type == cdb->type |
428 | 863 /* If there was no buffer being display before the |
4187 | 864 compare anyway as we might be outputting a gutter. */ |
434 | 865 && |
428 | 866 (b == old_b || !old_b)) |
867 { | |
868 must_sync |= compare_display_blocks (w, cdl, ddl, old_block, | |
869 block, start_pixpos, | |
870 cursor_start, cursor_width, | |
871 cursor_height); | |
872 } | |
873 else | |
874 { | |
875 int elt; | |
876 int first_elt = 0; | |
877 int last_elt = -1; | |
878 | |
879 for (elt = 0; elt < Dynarr_length (ddb->runes); elt++) | |
880 { | |
881 struct rune *rb = Dynarr_atp (ddb->runes, elt); | |
882 | |
883 if (start_pixpos >= rb->xpos | |
884 && start_pixpos < rb->xpos + rb->width) | |
885 first_elt = elt; | |
886 | |
887 if (end_pixpos > rb->xpos | |
888 && end_pixpos <= rb->xpos + rb->width) | |
889 { | |
890 last_elt = elt + 1; | |
891 if (last_elt > Dynarr_length (ddb->runes)) | |
892 last_elt = Dynarr_length (ddb->runes); | |
893 break; | |
894 } | |
895 } | |
896 | |
897 must_sync = 1; | |
898 redisplay_output_display_block (w, ddl, block, first_elt, | |
899 last_elt, | |
900 start_pixpos, | |
901 cursor_start, cursor_width, | |
902 cursor_height); | |
903 } | |
434 | 904 |
428 | 905 start_pixpos = next_start_pixpos; |
906 } | |
907 } | |
908 | |
909 /* Clear the internal border if we are next to it and the window | |
910 structure or frame size has changed or if something caused | |
911 clear_border to be tripped. */ | |
912 /* #### Doing this on f->clear sucks but is necessary because of | |
913 window-local background values. */ | |
914 if (f->windows_structure_changed || f->faces_changed || clear_border | |
915 || f->clear) | |
916 { | |
917 int y = DISPLAY_LINE_YPOS (ddl); | |
918 int height = DISPLAY_LINE_HEIGHT (ddl); | |
919 | |
920 /* If we are in the gutter then we musn't clear the borders. */ | |
921 if (y >= WINDOW_TEXT_TOP (w) && (y + height) <= WINDOW_TEXT_BOTTOM (w)) | |
922 { | |
923 if (ddl->modeline) | |
924 { | |
925 y -= MODELINE_SHADOW_THICKNESS (w); | |
926 height += (2 * MODELINE_SHADOW_THICKNESS (w)); | |
927 } | |
434 | 928 |
428 | 929 if (window_is_leftmost (w)) |
930 clear_left_border (w, y, height); | |
931 if (window_is_rightmost (w)) | |
932 clear_right_border (w, y, height); | |
933 } | |
934 } | |
935 | |
936 if (cdla) | |
937 sync_display_line_structs (w, line, must_sync, cdla, ddla); | |
938 } | |
939 | |
940 /***************************************************************************** | |
941 redisplay_move_cursor | |
942 | |
943 For the given window W, move the cursor to NEW_POINT. Returns a | |
944 boolean indicating success or failure. | |
945 ****************************************************************************/ | |
946 | |
826 | 947 #define ADJ_CHARPOS (rb->charpos + dl->offset) |
428 | 948 #define ADJ_ENDPOS (rb->endpos + dl->offset) |
949 | |
950 int | |
665 | 951 redisplay_move_cursor (struct window *w, Charbpos new_point, int no_output_end) |
428 | 952 { |
953 struct frame *f = XFRAME (w->frame); | |
954 struct device *d = XDEVICE (f->device); | |
955 | |
956 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP); | |
957 struct display_line *dl; | |
958 struct display_block *db; | |
959 struct rune *rb; | |
960 int x = w->last_point_x[CURRENT_DISP]; | |
961 int y = w->last_point_y[CURRENT_DISP]; | |
962 | |
963 /* | |
964 * Bail if cursor_in_echo_area is non-zero and we're fiddling with | |
965 * the cursor in a non-active minibuffer window, since that is a | |
966 * special case that is handled elsewhere and this function need | |
967 * not handle it. Return 1 so the caller will assume we | |
968 * succeeded. | |
969 */ | |
970 if (cursor_in_echo_area && MINI_WINDOW_P (w) && | |
971 w != XWINDOW (FRAME_SELECTED_WINDOW (f))) | |
972 return 1; | |
973 | |
974 if (y < 0 || y >= Dynarr_length (cla)) | |
975 return 0; | |
976 | |
977 dl = Dynarr_atp (cla, y); | |
978 db = get_display_block_from_line (dl, TEXT); | |
979 | |
980 if (x < 0 || x >= Dynarr_length (db->runes)) | |
981 return 0; | |
982 | |
983 rb = Dynarr_atp (db->runes, x); | |
984 | |
985 if (rb->cursor_type == CURSOR_OFF) | |
986 return 0; | |
826 | 987 else if (ADJ_CHARPOS == new_point |
988 || (ADJ_ENDPOS && (new_point >= ADJ_CHARPOS) | |
428 | 989 && (new_point <= ADJ_ENDPOS))) |
990 { | |
991 w->last_point_x[CURRENT_DISP] = x; | |
992 w->last_point_y[CURRENT_DISP] = y; | |
826 | 993 Fset_marker (w->last_point[CURRENT_DISP], make_int (ADJ_CHARPOS), |
428 | 994 w->buffer); |
995 dl->cursor_elt = x; | |
996 return 1; | |
997 } | |
998 else | |
999 { | |
442 | 1000 { |
1001 MAYBE_DEVMETH (d, frame_output_begin, (f)); | |
1002 MAYBE_DEVMETH (d, window_output_begin, (w)); | |
1003 } | |
1004 rb->cursor_type = CURSOR_OFF; | |
428 | 1005 dl->cursor_elt = -1; |
1006 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width); | |
1007 } | |
1008 | |
1009 w->last_point_x[CURRENT_DISP] = -1; | |
1010 w->last_point_y[CURRENT_DISP] = -1; | |
1011 Fset_marker (w->last_point[CURRENT_DISP], Qnil, w->buffer); | |
1012 | |
1013 /* If this isn't the selected frame, then erasing the old cursor is | |
1014 all we actually had to do. */ | |
1015 if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d)))) | |
1016 { | |
1017 if (!no_output_end) | |
442 | 1018 { |
1019 MAYBE_DEVMETH (d, window_output_end, (w)); | |
1020 MAYBE_DEVMETH (d, frame_output_end, (f)); | |
1021 } | |
428 | 1022 |
1023 return 1; | |
1024 } | |
1025 | |
1026 /* This should only occur in the minibuffer. */ | |
1027 if (new_point == 0) | |
1028 { | |
1029 w->last_point_x[CURRENT_DISP] = 0; | |
1030 w->last_point_y[CURRENT_DISP] = y; | |
1031 Fset_marker (w->last_point[CURRENT_DISP], Qzero, w->buffer); | |
1032 | |
4967 | 1033 rb = Dynarr_begin (db->runes); |
428 | 1034 rb->cursor_type = CURSOR_ON; |
1035 dl->cursor_elt = 0; | |
1036 | |
1037 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width); | |
1038 | |
1039 if (!no_output_end) | |
442 | 1040 { |
1041 MAYBE_DEVMETH (d, window_output_end, (w)); | |
1042 MAYBE_DEVMETH (d, frame_output_end, (f)); | |
1043 } | |
428 | 1044 return 1; |
1045 } | |
1046 else | |
1047 { | |
1048 int cur_rb = 0; | |
1049 int first = 0; | |
1050 int cur_dl, up; | |
1051 | |
826 | 1052 if (ADJ_CHARPOS < new_point) |
428 | 1053 { |
1054 up = 1; | |
1055 cur_rb = x + 1; | |
1056 cur_dl = y; | |
1057 } | |
665 | 1058 else /* (rb->charbpos + dl->offset) > new_point */ |
428 | 1059 { |
1060 up = 0; | |
1061 | |
1062 if (!x) | |
1063 { | |
1064 cur_dl = y - 1; | |
1065 first = 0; | |
1066 } | |
1067 else | |
1068 { | |
1069 cur_rb = x - 1; | |
1070 cur_dl = y; | |
1071 first = 1; | |
1072 } | |
1073 } | |
1074 | |
434 | 1075 while (up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0)) |
428 | 1076 { |
1077 dl = Dynarr_atp (cla, cur_dl); | |
1078 db = get_display_block_from_line (dl, TEXT); | |
1079 | |
1080 if (!up && !first) | |
1081 cur_rb = Dynarr_length (db->runes) - 1; | |
1082 | |
1083 while ((!scroll_on_clipped_lines || !dl->clip) && | |
1084 (up ? (cur_rb < Dynarr_length (db->runes)) : (cur_rb >= 0))) | |
1085 { | |
1086 rb = Dynarr_atp (db->runes, cur_rb); | |
1087 | |
1088 if (rb->cursor_type != IGNORE_CURSOR | |
1089 && rb->cursor_type != NO_CURSOR && | |
826 | 1090 (ADJ_CHARPOS == new_point |
1091 || (ADJ_ENDPOS && (new_point >= ADJ_CHARPOS) | |
1092 && (new_point <= ADJ_CHARPOS)))) | |
428 | 1093 { |
1094 rb->cursor_type = CURSOR_ON; | |
1095 dl->cursor_elt = cur_rb; | |
1096 | |
1097 | |
1098 output_display_line (w, 0, cla, cur_dl, rb->xpos, | |
1099 rb->xpos + rb->width); | |
1100 | |
1101 w->last_point_x[CURRENT_DISP] = cur_rb; | |
1102 w->last_point_y[CURRENT_DISP] = cur_dl; | |
1103 Fset_marker (w->last_point[CURRENT_DISP], | |
826 | 1104 make_int (ADJ_CHARPOS), w->buffer); |
428 | 1105 |
1106 if (!no_output_end) | |
442 | 1107 { |
1108 MAYBE_DEVMETH (d, window_output_end, (w)); | |
1109 MAYBE_DEVMETH (d, frame_output_end, (f)); | |
1110 } | |
428 | 1111 return 1; |
1112 } | |
1113 | |
1114 (up ? cur_rb++ : cur_rb--); | |
1115 } | |
1116 | |
1117 (up ? (cur_rb = 0) : (first = 0)); | |
1118 (up ? cur_dl++ : cur_dl--); | |
1119 } | |
1120 } | |
1121 | |
1122 if (!no_output_end) | |
442 | 1123 { |
1124 MAYBE_DEVMETH (d, window_output_end, (w)); | |
1125 MAYBE_DEVMETH (d, frame_output_end, (f)); | |
1126 } | |
428 | 1127 return 0; |
1128 } | |
826 | 1129 #undef ADJ_CHARPOS |
428 | 1130 #undef ADJ_ENDPOS |
1131 | |
1132 /***************************************************************************** | |
1133 redraw_cursor_in_window | |
1134 | |
1135 For the given window W, redraw the cursor if it is contained within | |
1136 the window. | |
1137 ****************************************************************************/ | |
1138 static void | |
1139 redraw_cursor_in_window (struct window *w, int run_end_begin_meths) | |
1140 { | |
1141 struct frame *f = XFRAME (w->frame); | |
1142 struct device *d = XDEVICE (f->device); | |
1143 | |
1144 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
1145 struct display_line *dl; | |
1146 struct display_block *db; | |
1147 struct rune *rb; | |
1148 | |
1149 int x = w->last_point_x[CURRENT_DISP]; | |
1150 int y = w->last_point_y[CURRENT_DISP]; | |
1151 | |
1152 if (cursor_in_echo_area && MINI_WINDOW_P (w) && | |
1153 !echo_area_active (f) && minibuf_level == 0) | |
1154 { | |
1155 MAYBE_DEVMETH (d, set_final_cursor_coords, (f, w->pixel_top, 0)); | |
1156 } | |
1157 | |
1158 if (y < 0 || y >= Dynarr_length (dla)) | |
1159 return; | |
1160 | |
1161 if (MINI_WINDOW_P (w) && f != device_selected_frame (d) && | |
1162 !is_surrogate_for_selected_frame (f)) | |
1163 return; | |
1164 | |
1165 dl = Dynarr_atp (dla, y); | |
1166 db = get_display_block_from_line (dl, TEXT); | |
1167 | |
1168 if (x < 0 || x >= Dynarr_length (db->runes)) | |
1169 return; | |
1170 | |
1171 rb = Dynarr_atp (db->runes, x); | |
1172 | |
1173 /* Don't call the output routine if the block isn't actually the | |
1174 cursor. */ | |
1175 if (rb->cursor_type == CURSOR_ON) | |
1176 { | |
1177 MAYBE_DEVMETH (d, set_final_cursor_coords, | |
1178 (f, dl->ypos - 1, rb->xpos)); | |
1179 | |
1180 if (run_end_begin_meths) | |
442 | 1181 { |
1182 MAYBE_DEVMETH (d, frame_output_begin, (f)); | |
1183 MAYBE_DEVMETH (d, window_output_begin, (w)); | |
1184 } | |
428 | 1185 |
1186 output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width); | |
1187 | |
1188 if (run_end_begin_meths) | |
442 | 1189 { |
1190 MAYBE_DEVMETH (d, window_output_end, (w)); | |
1191 MAYBE_DEVMETH (d, frame_output_end, (f)); | |
1192 } | |
428 | 1193 } |
1194 } | |
1195 | |
1196 /***************************************************************************** | |
1197 redisplay_redraw_cursor | |
1198 | |
1199 For the given frame F, redraw the cursor on the selected window. | |
1200 This is used to update the cursor after focus changes. | |
1201 ****************************************************************************/ | |
1202 void | |
1203 redisplay_redraw_cursor (struct frame *f, int run_end_begin_meths) | |
1204 { | |
1205 Lisp_Object window; | |
1206 | |
1207 if (!cursor_in_echo_area) | |
1208 window = FRAME_SELECTED_WINDOW (f); | |
1209 else if (FRAME_HAS_MINIBUF_P (f)) | |
1210 window = FRAME_MINIBUF_WINDOW (f); | |
1211 else | |
1212 return; | |
1213 | |
1214 redraw_cursor_in_window (XWINDOW (window), run_end_begin_meths); | |
1215 } | |
1216 | |
1217 /**************************************************************************** | |
1218 redisplay_output_display_block | |
1219 | |
1220 Given a display line, a block number for that start line, output all | |
1221 runes between start and end in the specified display block. | |
1222 ****************************************************************************/ | |
1223 static void | |
1224 redisplay_output_display_block (struct window *w, struct display_line *dl, int block, | |
1225 int start, int end, int start_pixpos, int cursor_start, | |
1226 int cursor_width, int cursor_height) | |
1227 { | |
1228 struct frame *f = XFRAME (w->frame); | |
1229 struct device *d = XDEVICE (f->device); | |
442 | 1230 /* Temporarily disabled until generalization is done. */ |
1231 #if 0 | |
428 | 1232 struct display_block *db = Dynarr_atp (dl->display_blocks, block); |
1233 rune_dynarr *rba = db->runes; | |
1234 struct rune *rb; | |
1235 int xpos, width; | |
1236 rb = Dynarr_atp (rba, start); | |
1237 | |
1238 if (!rb) | |
1239 /* Nothing to do so don't do anything. */ | |
1240 return; | |
1241 | |
1242 xpos = max (start_pixpos, rb->xpos); | |
1243 | |
1244 if (end < 0) | |
1245 end = Dynarr_length (rba); | |
1246 | |
1247 rb = Dynarr_atp (rba, end - 1); | |
1248 width = rb->xpos + rb->width - xpos; | |
442 | 1249 #endif |
428 | 1250 /* now actually output the block. */ |
1251 DEVMETH (d, output_display_block, (w, dl, block, start, | |
1252 end, start_pixpos, | |
1253 cursor_start, cursor_width, | |
1254 cursor_height)); | |
1255 } | |
1256 | |
1257 /**************************************************************************** | |
1258 redisplay_unmap_subwindows | |
1259 | |
1260 Remove subwindows from the area in the box defined by the given | |
1261 parameters. | |
1262 ****************************************************************************/ | |
448 | 1263 static void |
1264 redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height, | |
1265 Lisp_Object ignored_window) | |
428 | 1266 { |
442 | 1267 Lisp_Object rest; |
428 | 1268 |
442 | 1269 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))) |
1270 { | |
1271 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest)); | |
1272 if (IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) | |
428 | 1273 && |
442 | 1274 IMAGE_INSTANCE_DISPLAY_X (ii) |
1275 + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) > x | |
428 | 1276 && |
442 | 1277 IMAGE_INSTANCE_DISPLAY_X (ii) < x + width |
1278 && | |
1279 IMAGE_INSTANCE_DISPLAY_Y (ii) | |
1280 + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) > y | |
434 | 1281 && |
442 | 1282 IMAGE_INSTANCE_DISPLAY_Y (ii) < y + height |
1283 && | |
1284 !EQ (XCAR (rest), ignored_window)) | |
428 | 1285 { |
442 | 1286 unmap_subwindow (XCAR (rest)); |
428 | 1287 } |
1288 } | |
1289 } | |
1290 | |
1291 /**************************************************************************** | |
1292 redisplay_unmap_subwindows_maybe | |
1293 | |
1294 Potentially subwindows from the area in the box defined by the given | |
1295 parameters. | |
1296 ****************************************************************************/ | |
1279 | 1297 void |
1298 redisplay_unmap_subwindows_maybe (struct frame *f, int x, int y, int width, | |
1299 int height) | |
428 | 1300 { |
442 | 1301 if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))) |
428 | 1302 { |
1303 redisplay_unmap_subwindows (f, x, y, width, height, Qnil); | |
1304 } | |
1305 } | |
1306 | |
1279 | 1307 static void |
1308 redisplay_unmap_subwindows_except_us (struct frame *f, int x, int y, int width, | |
1309 int height, Lisp_Object subwindow) | |
428 | 1310 { |
442 | 1311 if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))) |
428 | 1312 { |
1313 redisplay_unmap_subwindows (f, x, y, width, height, subwindow); | |
1314 } | |
1315 } | |
1316 | |
1317 /**************************************************************************** | |
1318 redisplay_output_subwindow | |
1319 | |
1320 output a subwindow. This code borrows heavily from the pixmap stuff, | |
1321 although is much simpler not needing to account for partial | |
1322 pixmaps, backgrounds etc. | |
1323 ****************************************************************************/ | |
1324 void | |
434 | 1325 redisplay_output_subwindow (struct window *w, |
428 | 1326 Lisp_Object image_instance, |
1327 struct display_box* db, struct display_glyph_area* dga, | |
2286 | 1328 face_index findex, int UNUSED (cursor_start), |
1329 int UNUSED (cursor_width), | |
1330 int UNUSED (cursor_height)) | |
428 | 1331 { |
440 | 1332 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); |
428 | 1333 Lisp_Object window; |
1334 struct display_glyph_area sdga; | |
1335 | |
442 | 1336 dga->height = IMAGE_INSTANCE_HEIGHT (p); |
1337 dga->width = IMAGE_INSTANCE_WIDTH (p); | |
1338 | |
1339 /* The first thing we are going to do is update the display | |
1340 characteristics of the subwindow. This also clears the dirty | |
1341 flags as a side effect. */ | |
1342 redisplay_subwindow (image_instance); | |
428 | 1343 |
1344 /* This makes the glyph area fit into the display area. */ | |
1345 if (!redisplay_normalize_glyph_area (db, dga)) | |
1346 return; | |
1347 | |
793 | 1348 window = wrap_window (w); |
428 | 1349 |
1350 /* Clear the area the subwindow is going into. */ | |
1351 redisplay_clear_clipped_region (window, findex, | |
1352 db, dga, 0, image_instance); | |
1353 | |
1354 /* This shrinks the display box to exactly enclose the glyph | |
1355 area. */ | |
1356 redisplay_normalize_display_box (db, dga); | |
1357 | |
1358 /* if we can't view the whole window we can't view any of it. We | |
1359 have to be careful here since we may be being asked to display | |
1360 part of a subwindow, the rest of which is on-screen as well. We | |
1361 need to allow this case and map the entire subwindow. We also | |
1362 need to be careful since the subwindow could be outside the | |
1363 window in the gutter or modeline - we also need to allow these | |
1364 cases.*/ | |
1365 sdga.xoffset = -dga->xoffset; | |
1366 sdga.yoffset = -dga->yoffset; | |
442 | 1367 sdga.height = IMAGE_INSTANCE_HEIGHT (p); |
1368 sdga.width = IMAGE_INSTANCE_WIDTH (p); | |
434 | 1369 |
446 | 1370 if (redisplay_display_boxes_in_window_p (w, db, &sdga) == 0 |
1371 || | |
1372 /* We only want to do full subwindow display for windows that | |
1373 are completely in the gutter, otherwise we must clip to be | |
1374 safe. */ | |
1375 display_boxes_in_gutter_p (XFRAME (w->frame), db, &sdga) <= 0) | |
428 | 1376 { |
1377 map_subwindow (image_instance, db->xpos, db->ypos, dga); | |
1378 } | |
1379 else | |
1380 { | |
1381 sdga.xoffset = sdga.yoffset = 0; | |
434 | 1382 map_subwindow (image_instance, db->xpos - dga->xoffset, |
428 | 1383 db->ypos - dga->yoffset, &sdga); |
1384 } | |
1385 } | |
1386 | |
1387 /**************************************************************************** | |
1388 redisplay_output_layout | |
1389 | |
1390 Output a widget hierarchy. This can safely call itself recursively. | |
442 | 1391 |
1392 The complexity of outputting layouts is deciding whether to do it or | |
1393 not. Consider a layout enclosing some text, the text changes and is | |
1394 marked as dirty, but the enclosing layout has not been marked as | |
1395 dirty so no updates occur and the text will potentially be truncated. | |
1396 Alternatively we hold a back pointer in the image instance to the | |
1397 parent and mark the parent as dirty. But the layout code assumes that | |
1398 if the layout is dirty then the whole layout should be redisplayed, | |
1399 so we then get lots of flashing even though only the text has changed | |
1400 size. Of course if the text shrinks in size then we do actually need | |
1401 to redisplay the layout to repaint the exposed area. So what happens | |
1402 if we make a non-structural change like changing color? Either we | |
1403 redisplay everything, or we redisplay nothing. These are exactly the | |
1404 issues lwlib has to grapple with. We really need to know what has | |
1405 actually changed and make a layout decision based on that. We also | |
1406 really need to know what has changed so that we can only make the | |
1407 necessary changes in update_subwindow. This has all now been | |
1408 implemented, Viva la revolution! | |
428 | 1409 ****************************************************************************/ |
1410 void | |
442 | 1411 redisplay_output_layout (Lisp_Object domain, |
428 | 1412 Lisp_Object image_instance, |
1413 struct display_box* db, struct display_glyph_area* dga, | |
2286 | 1414 face_index findex, int UNUSED (cursor_start), |
1415 int UNUSED (cursor_width), int UNUSED (cursor_height)) | |
428 | 1416 { |
440 | 1417 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); |
442 | 1418 Lisp_Object rest, window = DOMAIN_WINDOW (domain); |
3479 | 1419 Ichar_dynarr *buf; |
442 | 1420 struct window *w = XWINDOW (window); |
1421 struct device *d = DOMAIN_XDEVICE (domain); | |
428 | 1422 int layout_height, layout_width; |
1423 | |
442 | 1424 layout_height = glyph_height (image_instance, domain); |
1425 layout_width = glyph_width (image_instance, domain); | |
428 | 1426 |
1427 dga->height = layout_height; | |
1428 dga->width = layout_width; | |
442 | 1429 #ifdef DEBUG_WIDGET_OUTPUT |
1430 printf ("outputing layout glyph %p\n", p); | |
1431 #endif | |
428 | 1432 /* This makes the glyph area fit into the display area. */ |
1433 if (!redisplay_normalize_glyph_area (db, dga)) | |
1434 return; | |
1435 | |
3479 | 1436 buf = Dynarr_new (Ichar); |
1437 | |
428 | 1438 /* Highly dodgy optimization. We want to only output the whole |
1439 layout if we really have to. */ | |
442 | 1440 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p) |
1441 || IMAGE_INSTANCE_LAYOUT_CHANGED (p) | |
1442 || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p) | |
1443 || IMAGE_INSTANCE_SIZE_CHANGED (p) | |
1444 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) | |
428 | 1445 { |
1446 /* First clear the area we are drawing into. This is the easiest | |
1447 thing to do since we have many gaps that we have to make sure are | |
1448 filled in. */ | |
1449 redisplay_clear_clipped_region (window, findex, db, dga, 1, Qnil); | |
434 | 1450 |
428 | 1451 /* Output a border if required */ |
1452 if (!NILP (IMAGE_INSTANCE_LAYOUT_BORDER (p))) | |
1453 { | |
1454 int edges = 0; | |
1455 enum edge_style style; | |
1456 int ypos = db->ypos; | |
863 | 1457 int xpos = db->xpos; |
428 | 1458 int height = dga->height; |
863 | 1459 int width = dga->width; |
434 | 1460 |
863 | 1461 /* The bevel_area routines always draw in from the specified |
1462 area so there is no need to adjust the displayed area to | |
1463 make sure that the lines are visible. */ | |
4187 | 1464 if (dga->xoffset >= 0) |
428 | 1465 edges |= EDGE_LEFT; |
4187 | 1466 if (dga->width - dga->xoffset == layout_width) |
428 | 1467 edges |= EDGE_RIGHT; |
4187 | 1468 if (dga->yoffset >= 0) |
428 | 1469 edges |= EDGE_TOP; |
1470 if (dga->height - dga->yoffset == layout_height) | |
1471 edges |= EDGE_BOTTOM; | |
4187 | 1472 |
428 | 1473 if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in)) |
1474 style = EDGE_ETCHED_IN; | |
1475 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out)) | |
1476 style = EDGE_ETCHED_OUT; | |
1477 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qbevel_in)) | |
1478 style = EDGE_BEVEL_IN; | |
1479 else if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (p))) | |
1480 { | |
1481 style = EDGE_ETCHED_IN; | |
1482 if (edges & EDGE_TOP) | |
1483 { | |
1484 ypos += XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p)); | |
1485 height -= XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p)); | |
1486 } | |
1487 } | |
1488 else | |
1489 style = EDGE_BEVEL_OUT; | |
1490 | |
434 | 1491 MAYBE_DEVMETH (d, bevel_area, |
863 | 1492 (w, findex, xpos, ypos, width, height, |
1493 DEFAULT_WIDGET_SHADOW_WIDTH, edges, style)); | |
428 | 1494 } |
1495 } | |
434 | 1496 |
428 | 1497 /* This shrinks the display box to exactly enclose the glyph |
1498 area. */ | |
1499 redisplay_normalize_display_box (db, dga); | |
1500 | |
1501 /* Flip through the widgets in the layout displaying as necessary */ | |
1502 LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p)) | |
1503 { | |
442 | 1504 Lisp_Object child = glyph_image_instance (XCAR (rest), image_instance, |
793 | 1505 ERROR_ME_DEBUG_WARN, 1); |
428 | 1506 |
1507 struct display_box cdb; | |
1508 /* For losing HP-UX */ | |
1509 cdb.xpos = db->xpos; | |
1510 cdb.ypos = db->ypos; | |
1511 cdb.width = db->width; | |
1512 cdb.height = db->height; | |
1513 | |
1514 /* First determine if the image is visible at all */ | |
1515 if (IMAGE_INSTANCEP (child)) | |
1516 { | |
440 | 1517 Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child); |
442 | 1518 |
428 | 1519 /* The enclosing layout offsets are +ve at this point */ |
1520 struct display_glyph_area cdga; | |
1521 cdga.xoffset = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset; | |
1522 cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset; | |
442 | 1523 cdga.width = glyph_width (child, image_instance); |
1524 cdga.height = glyph_height (child, image_instance); | |
1525 | |
1526 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = | |
1527 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p); | |
428 | 1528 |
4207 | 1529 /* Although normalization is done by the output routines we have to |
1530 do it here so that they don't try and clear all of db. This is | |
1531 true below also. */ | |
428 | 1532 if (redisplay_normalize_glyph_area (&cdb, &cdga)) |
1533 { | |
1534 redisplay_normalize_display_box (&cdb, &cdga); | |
4207 | 1535 /* Since the display boxes will now be totally in the window if |
1536 they are visible at all we can now check this easily. */ | |
428 | 1537 if (cdb.xpos < db->xpos || cdb.ypos < db->ypos |
1538 || cdb.xpos + cdb.width > db->xpos + db->width | |
1539 || cdb.ypos + cdb.height > db->ypos + db->height) | |
1540 continue; | |
4207 | 1541 /* We have to invert the offset here as normalization will have |
1542 made them positive which the output routines will treat as a | |
1543 truly +ve offset. */ | |
428 | 1544 cdga.xoffset = -cdga.xoffset; |
1545 cdga.yoffset = -cdga.yoffset; | |
1546 | |
1547 switch (IMAGE_INSTANCE_TYPE (childii)) | |
1548 { | |
1549 case IMAGE_TEXT: | |
1550 { | |
1551 /* #### This is well hacked and could use some | |
1552 generalisation.*/ | |
434 | 1553 if (redisplay_normalize_glyph_area (&cdb, &cdga) |
1554 && | |
442 | 1555 (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) || |
1556 IMAGE_INSTANCE_DIRTYP (childii))) | |
428 | 1557 { |
1558 struct display_line dl; /* this is fake */ | |
1559 Lisp_Object string = | |
1560 IMAGE_INSTANCE_TEXT_STRING (childii); | |
442 | 1561 unsigned char charsets[NUM_LEADING_BYTES]; |
4207 | 1562 struct face_cachel *cachel |
1563 = WINDOW_FACE_CACHEL (w, findex); | |
1564 | |
1565 DISPLAY_LINE_INIT (dl); | |
442 | 1566 |
867 | 1567 find_charsets_in_ibyte_string (charsets, |
4207 | 1568 XSTRING_DATA (string), |
1569 XSTRING_LENGTH (string)); | |
442 | 1570 ensure_face_cachel_complete (cachel, window, charsets); |
1571 | |
867 | 1572 convert_ibyte_string_into_ichar_dynarr |
4207 | 1573 (XSTRING_DATA (string), XSTRING_LENGTH (string), |
1574 buf); | |
434 | 1575 |
428 | 1576 redisplay_normalize_display_box (&cdb, &cdga); |
1577 /* Offsets are now +ve again so be careful | |
1578 when fixing up the display line. */ | |
1579 /* Munge boxes into display lines. */ | |
1580 dl.ypos = (cdb.ypos - cdga.yoffset) | |
442 | 1581 + glyph_ascent (child, image_instance); |
1582 dl.ascent = glyph_ascent (child, image_instance); | |
1583 dl.descent = glyph_descent (child, image_instance); | |
428 | 1584 dl.top_clip = cdga.yoffset; |
4207 | 1585 dl.clip = (dl.ypos + dl.descent) |
1586 - (cdb.ypos + cdb.height); | |
428 | 1587 /* output_string doesn't understand offsets in |
1588 the same way as other routines - we have to | |
1589 add the offset to the width so that we | |
1590 output the full string. */ | |
4207 | 1591 MAYBE_DEVMETH (d, output_string, |
1592 (w, &dl, buf, cdb.xpos, | |
1593 cdga.xoffset, cdb.xpos, | |
1594 cdga.width + cdga.xoffset, | |
1595 findex, 0, 0, 0, 0)); | |
428 | 1596 Dynarr_reset (buf); |
1597 } | |
1598 } | |
1599 break; | |
434 | 1600 |
428 | 1601 case IMAGE_MONO_PIXMAP: |
1602 case IMAGE_COLOR_PIXMAP: | |
442 | 1603 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) |
1604 || IMAGE_INSTANCE_DIRTYP (childii)) | |
428 | 1605 redisplay_output_pixmap (w, child, &cdb, &cdga, findex, |
1606 0, 0, 0, 0); | |
1607 break; | |
434 | 1608 |
428 | 1609 case IMAGE_WIDGET: |
442 | 1610 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (childii), Qlayout)) |
1611 { | |
1612 redisplay_output_layout (image_instance, child, &cdb, &cdga, findex, | |
1613 0, 0, 0); | |
1614 break; | |
1615 } | |
428 | 1616 case IMAGE_SUBWINDOW: |
442 | 1617 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) || |
1618 IMAGE_INSTANCE_DIRTYP (childii)) | |
428 | 1619 redisplay_output_subwindow (w, child, &cdb, &cdga, findex, |
1620 0, 0, 0); | |
1621 break; | |
434 | 1622 |
428 | 1623 case IMAGE_NOTHING: |
1624 /* nothing is as nothing does */ | |
1625 break; | |
434 | 1626 |
428 | 1627 case IMAGE_POINTER: |
1628 default: | |
2500 | 1629 ABORT (); |
428 | 1630 } |
1631 } | |
442 | 1632 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 0; |
428 | 1633 } |
1634 } | |
442 | 1635 |
1636 /* Update any display properties. I'm not sure whether this actually | |
1637 does anything for layouts except clear the changed flags. */ | |
1638 redisplay_subwindow (image_instance); | |
1639 | |
428 | 1640 Dynarr_free (buf); |
1641 } | |
1642 | |
1643 /**************************************************************************** | |
1644 redisplay_output_pixmap | |
1645 | |
1646 | |
1647 output a pixmap. | |
1648 ****************************************************************************/ | |
1649 void | |
434 | 1650 redisplay_output_pixmap (struct window *w, |
428 | 1651 Lisp_Object image_instance, |
1652 struct display_box* db, struct display_glyph_area* dga, | |
1653 face_index findex, int cursor_start, int cursor_width, | |
1654 int cursor_height, int offset_bitmap) | |
1655 { | |
1656 struct frame *f = XFRAME (w->frame); | |
1657 struct device *d = XDEVICE (f->device); | |
440 | 1658 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); |
793 | 1659 Lisp_Object window = wrap_window (w); |
1660 | |
428 | 1661 |
1662 dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p); | |
1663 dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p); | |
1664 | |
819 | 1665 #ifdef DEBUG_REDISPLAY |
5090 | 1666 printf ("redisplay_output_pixmap(request) [%dx%d@%d+%d] in [%dx%d@%d+%d]\n", |
819 | 1667 db->width, db->height, db->xpos, db->ypos, |
1668 dga->width, dga->height, dga->xoffset, dga->yoffset); | |
1669 #endif | |
1670 | |
428 | 1671 /* This makes the glyph area fit into the display area. */ |
1672 if (!redisplay_normalize_glyph_area (db, dga)) | |
1673 return; | |
1674 | |
819 | 1675 #ifdef DEBUG_REDISPLAY |
5090 | 1676 printf ("redisplay_output_pixmap(normalized) [%dx%d@%d+%d] in [%dx%d@%d+%d]\n", |
819 | 1677 db->width, db->height, db->xpos, db->ypos, |
1678 dga->width, dga->height, dga->xoffset, dga->yoffset); | |
1679 #endif | |
1680 | |
428 | 1681 /* Clear the area the pixmap is going into. The pixmap itself will |
1682 always take care of the full width. We don't want to clear where | |
1683 it is going to go in order to avoid flicker. So, all we have to | |
1684 take care of is any area above or below the pixmap. If the pixmap | |
1685 has a mask in which case we have to clear the whole damn thing | |
1686 since we can't yet clear just the area not included in the | |
1687 mask. */ | |
1688 if (!offset_bitmap) | |
1689 { | |
1690 redisplay_clear_clipped_region (window, findex, | |
434 | 1691 db, dga, |
442 | 1692 (IMAGE_INSTANCE_PIXMAP_MASK (p) != 0), |
428 | 1693 Qnil); |
1694 | |
1695 /* This shrinks the display box to exactly enclose the glyph | |
1696 area. */ | |
1697 redisplay_normalize_display_box (db, dga); | |
1698 } | |
1699 assert (db->xpos >= 0 && db->ypos >= 0); | |
1700 | |
1701 MAYBE_DEVMETH (d, output_pixmap, (w, image_instance, | |
1702 db, dga, | |
1703 findex, cursor_start, | |
1704 cursor_width, cursor_height, | |
1705 offset_bitmap)); | |
1706 } | |
1707 | |
1708 /**************************************************************************** | |
1709 redisplay_clear_region | |
1710 | |
1711 Clear the area in the box defined by the given parameters using the | |
1712 given face. This has been generalised so that subwindows can be | |
1713 coped with effectively. | |
1714 ****************************************************************************/ | |
1715 void | |
1716 redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y, | |
1717 int width, int height) | |
1718 { | |
1719 struct window *w = NULL; | |
1720 struct frame *f = NULL; | |
1721 struct device *d; | |
1722 Lisp_Object background_pixmap = Qunbound; | |
5080
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5074
diff
changeset
|
1723 Lisp_Object background_placement = Qunbound; |
428 | 1724 Lisp_Object fcolor = Qnil, bcolor = Qnil; |
1725 | |
1726 if (!width || !height) | |
1727 return; | |
1728 | |
1729 if (WINDOWP (locale)) | |
1730 { | |
1731 w = XWINDOW (locale); | |
1732 f = XFRAME (w->frame); | |
1733 } | |
1734 else if (FRAMEP (locale)) | |
1735 { | |
1736 w = NULL; | |
1737 f = XFRAME (locale); | |
1738 } | |
1739 else | |
2500 | 1740 ABORT (); |
428 | 1741 |
1742 d = XDEVICE (f->device); | |
1743 | |
1744 /* if we have subwindows in the region we have to unmap them */ | |
1745 redisplay_unmap_subwindows_maybe (f, x, y, width, height); | |
1746 | |
1747 /* #### This isn't quite right for when this function is called | |
1748 from the toolbar code. */ | |
434 | 1749 |
5090 | 1750 /* #### GEOM! This uses a backing pixmap in the gutter. Correct? */ |
428 | 1751 /* Don't use a backing pixmap in the border area */ |
5090 | 1752 if (x >= FRAME_LEFT_INTERNAL_BORDER_END (f) |
1753 && x < FRAME_RIGHT_INTERNAL_BORDER_START (f) | |
1754 && y >= FRAME_TOP_INTERNAL_BORDER_END (f) | |
1755 && y < FRAME_BOTTOM_INTERNAL_BORDER_START (f)) | |
428 | 1756 { |
1757 Lisp_Object temp; | |
434 | 1758 |
428 | 1759 if (w) |
1760 { | |
1761 temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex); | |
434 | 1762 |
428 | 1763 if (IMAGE_INSTANCEP (temp) |
1764 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp))) | |
1765 { | |
1766 /* #### maybe we could implement such that a string | |
1767 can be a background pixmap? */ | |
1768 background_pixmap = temp; | |
5080
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5074
diff
changeset
|
1769 background_placement |
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5074
diff
changeset
|
1770 = WINDOW_FACE_CACHEL_BACKGROUND_PLACEMENT (w, findex); |
428 | 1771 } |
1772 } | |
1773 else | |
1774 { | |
1775 temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale); | |
5080
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5074
diff
changeset
|
1776 |
428 | 1777 if (IMAGE_INSTANCEP (temp) |
1778 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp))) | |
1779 { | |
1780 background_pixmap = temp; | |
5080
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5074
diff
changeset
|
1781 background_placement |
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5074
diff
changeset
|
1782 = FACE_BACKGROUND_PLACEMENT (Vdefault_face, locale); |
428 | 1783 } |
1784 } | |
434 | 1785 } |
428 | 1786 |
5080
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5074
diff
changeset
|
1787 if (!UNBOUNDP (background_pixmap) |
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5074
diff
changeset
|
1788 && XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0) |
428 | 1789 { |
1790 if (w) | |
1791 { | |
1792 fcolor = WINDOW_FACE_CACHEL_FOREGROUND (w, findex); | |
1793 bcolor = WINDOW_FACE_CACHEL_BACKGROUND (w, findex); | |
1794 } | |
1795 else | |
1796 { | |
1797 fcolor = FACE_FOREGROUND (Vdefault_face, locale); | |
1798 bcolor = FACE_BACKGROUND (Vdefault_face, locale); | |
1799 } | |
1800 } | |
1801 else | |
1802 { | |
1803 fcolor = (w ? | |
1804 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) : | |
1805 FACE_BACKGROUND (Vdefault_face, locale)); | |
434 | 1806 |
428 | 1807 } |
434 | 1808 |
428 | 1809 if (UNBOUNDP (background_pixmap)) |
1810 background_pixmap = Qnil; | |
434 | 1811 |
5074
8af6a32b170d
Modify XLIKE_get_gc's prototype
Didier Verna <didier@lrde.epita.fr>
parents:
5049
diff
changeset
|
1812 DEVMETH (d, clear_region, (locale, d, f, findex, x, y, width, height, |
5080
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5074
diff
changeset
|
1813 fcolor, bcolor, |
5502045ec510
The background-placement face property.
Didier Verna <didier@lrde.epita.fr>
parents:
5074
diff
changeset
|
1814 background_pixmap, background_placement)); |
428 | 1815 } |
1816 | |
1817 /**************************************************************************** | |
1818 redisplay_clear_clipped_region | |
1819 | |
1820 Clear the area in the dest display_box not covered by the src | |
442 | 1821 display_glyph_area using the given face. This is a common occurrence |
428 | 1822 for images shorter than the display line. Clipping can be played |
1823 around with by altering these. glyphsrc should be normalized. | |
1824 ****************************************************************************/ | |
1825 static void | |
434 | 1826 redisplay_clear_clipped_region (Lisp_Object window, face_index findex, |
1827 struct display_box* dest, struct display_glyph_area* glyphsrc, | |
428 | 1828 int fullheight_p, Lisp_Object ignored_subwindow) |
1829 { | |
1830 /* assume dest->xpos >= 0 */ | |
1831 int clear_x; | |
1832 struct frame* f = XFRAME (XWINDOW (window)->frame); | |
1833 | |
1834 if (glyphsrc->xoffset > 0) | |
1835 { | |
1836 clear_x = dest->xpos + glyphsrc->xoffset; | |
1837 } | |
1838 else | |
1839 { | |
1840 clear_x = dest->xpos; | |
1841 } | |
1842 | |
1843 /* If we need the whole height cleared then just do it. */ | |
1844 if (fullheight_p) | |
1845 { | |
1846 redisplay_clear_region (window, findex, clear_x, dest->ypos, | |
1847 glyphsrc->width, dest->height); | |
1848 } | |
1849 else | |
1850 { | |
434 | 1851 int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0); |
1852 | |
428 | 1853 /* We need to make sure that subwindows are unmapped from the |
4187 | 1854 whole area. */ |
428 | 1855 redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos, |
1856 glyphsrc->width, dest->height, | |
1857 ignored_subwindow); | |
1858 /* first the top box */ | |
1859 if (yoffset > 0) | |
1860 { | |
1861 redisplay_clear_region (window, findex, clear_x, dest->ypos, | |
1862 glyphsrc->width, yoffset); | |
434 | 1863 |
428 | 1864 } |
1865 /* Then the bottom box */ | |
1866 if (yoffset + glyphsrc->height < dest->height) | |
1867 { | |
1868 redisplay_clear_region (window, findex, clear_x, | |
1869 dest->ypos + yoffset + glyphsrc->height, | |
434 | 1870 glyphsrc->width, |
428 | 1871 dest->height - (yoffset + glyphsrc->height)); |
1872 | |
1873 } | |
1874 } | |
1875 } | |
1876 | |
1877 /***************************************************************************** | |
1878 redisplay_normalize_glyph_area | |
1879 redisplay_normalize_display_box | |
1880 | |
819 | 1881 Calculate the visible box for displaying glyphsrc in dest. |
1882 | |
1883 display_box and display_glyph_area are used to represent an area to | |
1884 displayed and where to display it. Using these two structures all | |
1885 combinations of clipping and position can be accommodated. | |
1886 | |
1887 dest - display_box | |
1888 | |
1889 xpos - absolute horizontal position of area. | |
1890 | |
4187 | 1891 ypos - absolute vertical position of area. |
819 | 1892 |
1893 glyphsrc - display_glyph_area | |
1894 | |
1895 xoffset - horizontal offset of the glyph, +ve means display | |
1896 the glyph with the x position offset by xoffset, -ve means | |
1897 display starting xoffset into the glyph. | |
1898 | |
1899 yoffset - vertical offset of the glyph, +ve means display the | |
1900 glyph with y position offset by yoffset, -ve means display | |
1901 starting xoffset into the glyph. | |
1902 | |
428 | 1903 ****************************************************************************/ |
1904 int | |
434 | 1905 redisplay_normalize_glyph_area (struct display_box* dest, |
428 | 1906 struct display_glyph_area* glyphsrc) |
1907 { | |
1908 if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width | |
1909 || | |
1910 dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height | |
1911 || | |
1912 -glyphsrc->xoffset >= glyphsrc->width | |
1913 || | |
448 | 1914 -glyphsrc->yoffset >= glyphsrc->height |
1915 || | |
1916 /* #### Not sure why this wasn't coped with before but normalizing | |
1917 to zero width or height is definitely wrong. */ | |
1918 (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width | |
1919 && | |
1920 dest->width - glyphsrc->xoffset <= 0) | |
1921 || | |
1922 (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height | |
1923 && | |
1924 dest->height - glyphsrc->yoffset <= 0)) | |
428 | 1925 { |
1926 /* It's all clipped out */ | |
1927 return 0; | |
1928 } | |
1929 | |
819 | 1930 /* Horizontal offsets. This works because xoffset can be -ve as well |
1931 as +ve. When we enter this function the glyphsrc width and | |
1932 height are set to the actual glyph width and height irrespective | |
1933 of how much can be displayed. We are trying to clip both the | |
1934 offset into the image and the rightmost bounding box. Its | |
1935 possible for the glyph width to be much larger than the area we | |
1936 are displaying into (e.g. a large glyph in a small frame). */ | |
428 | 1937 if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width) |
1938 { | |
819 | 1939 /* glyphsrc offset is +ve we are trying to display offset from the |
1940 origin (the bounding box contains some space and then the | |
1941 glyph). At most the width we want to display is dest->width - | |
1942 glyphsrc->xoffset. */ | |
428 | 1943 if (glyphsrc->xoffset > 0) |
1944 glyphsrc->width = dest->width - glyphsrc->xoffset; | |
819 | 1945 /* glyphsrc offset is -ve we are trying to display hard up |
1946 against the dest corner inset into the glyphsrc by | |
1947 xoffset.*/ | |
4187 | 1948 else if (glyphsrc->xoffset < 0) |
819 | 1949 { |
1950 glyphsrc->width += glyphsrc->xoffset; | |
1951 glyphsrc->width = min (glyphsrc->width, dest->width); | |
1952 } | |
428 | 1953 else |
1954 glyphsrc->width = dest->width; | |
1955 } | |
1956 | |
4187 | 1957 else if (glyphsrc->xoffset < 0) |
428 | 1958 glyphsrc->width += glyphsrc->xoffset; |
1959 | |
1960 /* Vertical offsets. This works because yoffset can be -ve as well as +ve */ | |
1961 if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height) | |
1962 { | |
819 | 1963 if ((glyphsrc->yoffset > 0) && (dest->height > glyphsrc->yoffset)) |
428 | 1964 glyphsrc->height = dest->height - glyphsrc->yoffset; |
4187 | 1965 else if (glyphsrc->yoffset < 0) |
819 | 1966 { |
1967 glyphsrc->height += glyphsrc->yoffset; | |
1968 glyphsrc->height = min (glyphsrc->height, dest->height); | |
1969 } | |
428 | 1970 else |
1971 glyphsrc->height = dest->height; | |
1972 } | |
1973 | |
819 | 1974 else if (glyphsrc->yoffset < 0) |
428 | 1975 glyphsrc->height += glyphsrc->yoffset; |
1976 | |
1977 return 1; | |
1978 } | |
1979 | |
1980 static void | |
434 | 1981 redisplay_normalize_display_box (struct display_box* dest, |
428 | 1982 struct display_glyph_area* glyphsrc) |
1983 { | |
1984 /* Adjust the destination area. At the end of this the destination | |
1985 area will exactly enclose the glyph area. The only remaining | |
1986 adjustment will be offsets into the glyph area. */ | |
1987 | |
1988 /* Horizontal adjustment. */ | |
1989 if (glyphsrc->xoffset > 0) | |
1990 { | |
1991 dest->xpos += glyphsrc->xoffset; | |
1992 dest->width -= glyphsrc->xoffset; | |
1993 glyphsrc->xoffset = 0; | |
1994 } | |
1995 else | |
1996 glyphsrc->xoffset = -glyphsrc->xoffset; | |
1997 | |
1998 if (glyphsrc->width < dest->width) | |
1999 dest->width = glyphsrc->width; | |
2000 | |
2001 /* Vertical adjustment. */ | |
2002 if (glyphsrc->yoffset > 0) | |
2003 { | |
2004 dest->ypos += glyphsrc->yoffset; | |
2005 dest->height -= glyphsrc->yoffset; | |
2006 glyphsrc->yoffset = 0; | |
2007 } | |
2008 else | |
2009 glyphsrc->yoffset = -glyphsrc->yoffset; | |
2010 | |
2011 if (glyphsrc->height < dest->height) | |
2012 dest->height = glyphsrc->height; | |
2013 } | |
2014 | |
2015 /***************************************************************************** | |
2016 redisplay_display_boxes_in_window_p | |
2017 | |
446 | 2018 Determine whether the required display_glyph_area is completely inside |
2019 the window. -1 means the display_box is not in the window. 1 means the | |
2020 display_box and the display_glyph_area are in the window. 0 means | |
428 | 2021 the display_box is in the window but the display_glyph_area is not. |
2022 ****************************************************************************/ | |
2023 static int | |
2024 redisplay_display_boxes_in_window_p (struct window* w, | |
2025 struct display_box* db, | |
2026 struct display_glyph_area* dga) | |
2027 { | |
2028 int left = WINDOW_TEXT_LEFT (w); | |
2029 int right = WINDOW_TEXT_RIGHT (w); | |
2030 int top = WINDOW_TEXT_TOP (w); | |
2031 int bottom = WINDOW_TEXT_BOTTOM (w); | |
2032 | |
2033 if (db->xpos < left || db->ypos < top | |
2034 || db->xpos + db->width > right | |
2035 || db->ypos + db->height > bottom) | |
446 | 2036 /* We are not displaying in a window at all */ |
2037 return -1; | |
434 | 2038 |
428 | 2039 if (db->xpos + dga->xoffset >= left |
2040 && | |
2041 db->ypos + dga->yoffset >= top | |
2042 && | |
2043 db->xpos + dga->xoffset + dga->width <= right | |
2044 && | |
2045 db->ypos + dga->yoffset + dga->height <= bottom) | |
2046 return 1; | |
2047 | |
446 | 2048 return 0; |
428 | 2049 } |
2050 | |
2051 /***************************************************************************** | |
2052 redisplay_calculate_display_boxes | |
2053 | |
2054 Convert from rune/display_line co-ordinates to display_box | |
2055 co-ordinates. | |
2056 ****************************************************************************/ | |
2057 int | |
2058 redisplay_calculate_display_boxes (struct display_line *dl, int xpos, | |
819 | 2059 int xoffset, int yoffset, int start_pixpos, |
4187 | 2060 int width, struct display_box* dest, |
428 | 2061 struct display_glyph_area* src) |
2062 { | |
2063 dest->xpos = xpos; | |
2064 dest->ypos = DISPLAY_LINE_YPOS (dl); | |
2065 dest->width = width; | |
2066 dest->height = DISPLAY_LINE_HEIGHT (dl); | |
2067 | |
2068 src->xoffset = -xoffset; | |
2069 src->width = 0; | |
2070 src->height = 0; | |
2071 | |
819 | 2072 src->yoffset = -dl->top_clip + yoffset; |
2073 | |
428 | 2074 if (start_pixpos >=0 && start_pixpos > xpos) |
2075 { | |
2076 /* Oops, we're asking for a start outside of the displayable | |
4187 | 2077 area. */ |
428 | 2078 if (start_pixpos > xpos + width) |
2079 return 0; | |
2080 dest->xpos = start_pixpos; | |
2081 dest->width -= (start_pixpos - xpos); | |
2082 /* Offsets are -ve when we want to clip pixels off the displayed | |
4187 | 2083 glyph. */ |
428 | 2084 src->xoffset -= (start_pixpos - xpos); |
2085 } | |
2086 | |
2087 return 1; | |
2088 } | |
2089 | |
2090 /***************************************************************************** | |
2091 redisplay_clear_top_of_window | |
2092 | |
2093 If window is topmost, clear the internal border above it. | |
2094 ****************************************************************************/ | |
448 | 2095 void |
428 | 2096 redisplay_clear_top_of_window (struct window *w) |
2097 { | |
793 | 2098 Lisp_Object window = wrap_window (w); |
2099 | |
5090 | 2100 /* #### GEOM! FIXME #### This is definitely wrong. It was clearly not |
2101 fixed up to accommodate the gutter. The internal border width is now | |
2102 no longer adjacent to the leftmost window, since the gutter | |
2103 intervenes. */ | |
428 | 2104 if (!NILP (Fwindow_highest_p (window))) |
2105 { | |
2106 struct frame *f = XFRAME (w->frame); | |
2107 int x, y, width, height; | |
2108 | |
2109 x = w->pixel_left; | |
2110 width = w->pixel_width; | |
2111 | |
2112 if (window_is_leftmost (w)) | |
2113 { | |
5045 | 2114 x -= FRAME_INTERNAL_BORDER_WIDTH (f); |
2115 width += FRAME_INTERNAL_BORDER_WIDTH (f); | |
428 | 2116 } |
2117 if (window_is_rightmost (w)) | |
5045 | 2118 width += FRAME_INTERNAL_BORDER_WIDTH (f); |
428 | 2119 |
5090 | 2120 /* #### This off-by-one stuff also occurs in XLIKE_clear_frame(). */ |
2121 y = FRAME_TOP_INTERNAL_BORDER_START (f) - 1; | |
5045 | 2122 height = FRAME_INTERNAL_BORDER_HEIGHT (f) + 1; |
428 | 2123 |
2124 redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height); | |
2125 } | |
2126 } | |
2127 | |
2128 /***************************************************************************** | |
2129 redisplay_clear_to_window_end | |
2130 | |
2131 Clear the area between ypos1 and ypos2. Each margin area and the | |
2132 text area is handled separately since they may each have their own | |
2133 background color. | |
2134 ****************************************************************************/ | |
2135 void | |
2136 redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2) | |
2137 { | |
2138 struct frame *f = XFRAME (w->frame); | |
2139 struct device *d = XDEVICE (f->device); | |
2140 | |
2141 if (HAS_DEVMETH_P (d, clear_to_window_end)) | |
2142 DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2)); | |
2143 else | |
2144 { | |
2145 int height = ypos2 - ypos1; | |
434 | 2146 |
428 | 2147 if (height) |
2148 { | |
2149 Lisp_Object window; | |
2150 int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/ | |
2151 layout_bounds bounds; | |
434 | 2152 |
428 | 2153 bounds = calculate_display_line_boundaries (w, bflag); |
793 | 2154 window = wrap_window (w); |
428 | 2155 |
2156 if (window_is_leftmost (w)) | |
5090 | 2157 redisplay_clear_region (window, DEFAULT_INDEX, |
2158 FRAME_LEFT_INTERNAL_BORDER_START (f), | |
2159 ypos1, FRAME_INTERNAL_BORDER_WIDTH (f), | |
2160 height); | |
434 | 2161 |
428 | 2162 if (bounds.left_in - bounds.left_out > 0) |
2163 redisplay_clear_region (window, | |
5090 | 2164 get_builtin_face_cache_index |
2165 (w, Vleft_margin_face), | |
428 | 2166 bounds.left_out, ypos1, |
2167 bounds.left_in - bounds.left_out, height); | |
434 | 2168 |
428 | 2169 if (bounds.right_in - bounds.left_in > 0) |
434 | 2170 redisplay_clear_region (window, |
428 | 2171 DEFAULT_INDEX, |
2172 bounds.left_in, ypos1, | |
2173 bounds.right_in - bounds.left_in, height); | |
434 | 2174 |
428 | 2175 if (bounds.right_out - bounds.right_in > 0) |
2176 redisplay_clear_region (window, | |
5090 | 2177 get_builtin_face_cache_index |
2178 (w, Vright_margin_face), | |
428 | 2179 bounds.right_in, ypos1, |
5090 | 2180 bounds.right_out - bounds.right_in, |
2181 height); | |
434 | 2182 |
428 | 2183 if (window_is_rightmost (w)) |
5090 | 2184 redisplay_clear_region (window, DEFAULT_INDEX, |
2185 FRAME_RIGHT_INTERNAL_BORDER_START (f), | |
2186 ypos1, FRAME_INTERNAL_BORDER_WIDTH (f), | |
2187 height); | |
428 | 2188 } |
2189 } | |
2190 } | |
2191 | |
2192 /***************************************************************************** | |
2193 redisplay_clear_bottom_of_window | |
2194 | |
2195 Clear window from right below the last display line to right above | |
2196 the modeline. The calling function can limit the area actually | |
2197 erased by setting min_start and/or max_end to positive values. | |
2198 ****************************************************************************/ | |
2199 void | |
2200 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla, | |
2201 int min_start, int max_end) | |
2202 { | |
2203 struct frame *f = XFRAME (w->frame); | |
2204 int ypos1, ypos2; | |
2205 int ddla_len = Dynarr_length (ddla); | |
2206 | |
2207 ypos2 = WINDOW_TEXT_BOTTOM (w); | |
2208 #ifdef HAVE_SCROLLBARS | |
2209 /* This adjustment is to catch the intersection of any scrollbars. */ | |
2210 if (f->windows_structure_changed && NILP (w->scrollbar_on_top_p)) | |
2211 ypos2 += window_scrollbar_height (w); | |
2212 #endif | |
2213 | |
2214 if (ddla_len) | |
2215 { | |
4967 | 2216 if (ddla_len == 1 && Dynarr_begin (ddla)->modeline) |
428 | 2217 { |
2218 ypos1 = WINDOW_TEXT_TOP (w); | |
2219 #ifdef HAVE_SCROLLBARS | |
2220 /* This adjustment is to catch the intersection of any scrollbars. */ | |
2221 if (f->windows_structure_changed && !NILP (w->scrollbar_on_top_p)) | |
2222 ypos1 -= window_scrollbar_height (w); | |
2223 #endif | |
2224 } | |
2225 else | |
2226 { | |
2227 struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1); | |
2228 ypos1 = dl->ypos + dl->descent - dl->clip; | |
2229 } | |
2230 } | |
2231 else | |
2232 ypos1 = WINDOW_TEXT_TOP (w); | |
2233 | |
2234 /* #### See if this can be made conditional on the frame | |
2235 changing size. */ | |
2236 if (MINI_WINDOW_P (w)) | |
5045 | 2237 ypos2 += FRAME_INTERNAL_BORDER_HEIGHT (f); |
428 | 2238 |
2239 if (min_start >= 0 && ypos1 < min_start) | |
2240 ypos1 = min_start; | |
2241 if (max_end >= 0 && ypos2 > max_end) | |
2242 ypos2 = max_end; | |
2243 | |
2244 if (ypos2 <= ypos1) | |
2245 return; | |
2246 | |
2247 redisplay_clear_to_window_end (w, ypos1, ypos2); | |
2248 } | |
2249 | |
2250 /***************************************************************************** | |
2251 redisplay_update_line | |
2252 | |
2253 This is used during incremental updates to update a single line and | |
2254 correct the offsets on all lines below it. At the moment | |
2255 update_values is false if we are only updating the modeline. | |
2256 ****************************************************************************/ | |
2257 void | |
2258 redisplay_update_line (struct window *w, int first_line, int last_line, | |
2259 int update_values) | |
2260 { | |
2261 struct frame *f = XFRAME (w->frame); | |
2262 struct device *d = XDEVICE (f->device); | |
2263 | |
2264 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
2265 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
2266 | |
442 | 2267 MAYBE_DEVMETH (d, window_output_begin, (w)); |
428 | 2268 |
2269 while (first_line <= last_line) | |
2270 { | |
826 | 2271 Charcount old_len = (Dynarr_atp (cdla, first_line)->end_charpos - |
2272 Dynarr_atp (cdla, first_line)->charpos); | |
2273 Charcount new_len = (Dynarr_atp (ddla, first_line)->end_charpos - | |
2274 Dynarr_atp (ddla, first_line)->charpos); | |
428 | 2275 |
2276 assert (Dynarr_length (cdla) == Dynarr_length (ddla)); | |
2277 | |
2278 /* Output the changes. */ | |
2279 output_display_line (w, cdla, ddla, first_line, -1, -1); | |
2280 | |
2281 /* Update the offsets. */ | |
2282 if (update_values) | |
2283 { | |
2284 int cur_line = first_line + 1; | |
2285 while (cur_line < Dynarr_length (cdla)) | |
2286 { | |
2287 Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len); | |
2288 Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len); | |
2289 cur_line++; | |
2290 } | |
2291 } | |
2292 | |
2293 /* Update the window_end_pos and other settings. */ | |
2294 if (update_values) | |
2295 { | |
2296 w->window_end_pos[CURRENT_DISP] -= (new_len - old_len); | |
2297 | |
2298 if (Dynarr_atp (ddla, first_line)->cursor_elt != -1) | |
2299 { | |
2300 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP]; | |
2301 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP]; | |
2302 } | |
2303 } | |
2304 | |
2305 first_line++; | |
2306 } | |
2307 | |
2308 /* Update the window max line length. We have to scan the entire | |
2309 set of display lines otherwise we might not detect if the max is | |
2310 supposed to shrink. */ | |
2311 if (update_values) | |
2312 { | |
2313 int line = 0; | |
2314 | |
2315 w->max_line_len = 0; | |
2316 while (line < Dynarr_length (ddla)) | |
2317 { | |
2318 struct display_line *dl = Dynarr_atp (ddla, line); | |
2319 | |
2320 if (!dl->modeline) | |
2321 w->max_line_len = max (dl->num_chars, w->max_line_len); | |
2322 | |
2323 line++; | |
2324 } | |
2325 } | |
2326 | |
2327 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP]; | |
2328 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP]; | |
2329 Fset_marker (w->last_point[CURRENT_DISP], | |
2330 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer); | |
2331 Fset_marker (w->last_start[CURRENT_DISP], | |
2332 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer); | |
2333 | |
2334 /* We don't bother updating the vertical scrollbars here. This | |
2335 gives us a performance increase while having minimal loss of | |
2336 quality to the scrollbar slider size and position since when this | |
2337 function is called we know that the changes to the buffer were | |
2338 very localized. We have to update the horizontal scrollbars, | |
2339 though, because this routine could cause a change which has a | |
2340 larger impact on their sizing. */ | |
2341 /* #### See if we can get away with only calling this if | |
2342 max_line_len is greater than the window_char_width. */ | |
462 | 2343 /* #### BILL!!! Should we do this for GTK as well? */ |
428 | 2344 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS) |
2345 { | |
2346 extern int stupid_vertical_scrollbar_drag_hack; | |
2347 | |
2348 update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack); | |
2349 stupid_vertical_scrollbar_drag_hack = 1; | |
2350 } | |
2351 #endif | |
2352 | |
442 | 2353 redisplay_redraw_cursor (f, 0); |
2354 MAYBE_DEVMETH (d, window_output_end, (w)); | |
428 | 2355 } |
2356 | |
2357 /***************************************************************************** | |
2358 redisplay_output_window | |
2359 | |
2360 For the given window W, ensure that the current display lines are | |
2361 equal to the desired display lines, outputing changes as necessary. | |
2362 | |
2363 #### Fuck me. This just isn't going to cut it for tty's. The output | |
2364 decisions for them must be based on the contents of the entire frame | |
2365 because that is how the available output capabilities think. The | |
2366 solution is relatively simple. Create redisplay_output_frame. This | |
2367 will basically merge all of the separate window display structs into | |
2368 a single one for the frame. This combination structure will be able | |
2369 to be passed to the same output_display_line which works for windows | |
2370 on X frames and the right things will happen. It just takes time to | |
2371 do. | |
2372 ****************************************************************************/ | |
2373 void | |
2374 redisplay_output_window (struct window *w) | |
2375 { | |
2376 struct frame *f = XFRAME (w->frame); | |
2377 struct device *d = XDEVICE (f->device); | |
2378 | |
2379 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
2380 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
2381 | |
2382 int cdla_len = Dynarr_length (cdla); | |
2383 int ddla_len = Dynarr_length (ddla); | |
2384 | |
2385 int line; | |
2386 int need_to_clear_bottom = 0; | |
2387 int need_to_clear_start = -1; | |
2388 int need_to_clear_end = -1; | |
2389 | |
2390 /* Backgrounds may have changed or windows may have gone away | |
2391 leaving dividers lying around. */ | |
2392 if (f->faces_changed | |
2393 || f->windows_structure_changed | |
2394 || w->shadow_thickness_changed) | |
2395 need_to_clear_bottom = 1; | |
2396 | |
2397 /* The first thing we do is determine if we are going to need to | |
2398 clear the bottom of the window. We only need to do this if the | |
2399 bottom of the current display lines is below the bottom of the | |
2400 desired display lines. Note that the number of lines is | |
2401 irrelevant. Only the position matters. We also clear to the | |
2402 bottom of the window if the modeline has shifted position. */ | |
2403 /* #### We can't blindly not clear the bottom if f->clear is true | |
2404 since there might be a window-local background. However, for | |
2405 those cases where there isn't, clearing the end of the window in | |
2406 this case sucks. */ | |
2407 if (!need_to_clear_bottom) | |
2408 { | |
2409 struct display_line *cdl, *ddl; | |
2410 | |
2411 /* If the modeline has changed position or size, clear the bottom | |
2412 of the window. */ | |
2413 if (!need_to_clear_bottom) | |
2414 { | |
2415 cdl = ddl = 0; | |
2416 | |
2417 if (cdla_len) | |
4967 | 2418 cdl = Dynarr_begin (cdla); |
428 | 2419 if (ddla_len) |
4967 | 2420 ddl = Dynarr_begin (ddla); |
428 | 2421 |
2422 if (!cdl || !ddl) | |
2423 need_to_clear_bottom = 1; | |
2424 else if ((!cdl->modeline && ddl->modeline) | |
2425 || (cdl->modeline && !ddl->modeline)) | |
2426 need_to_clear_bottom = 1; | |
2427 else if (cdl->ypos != ddl->ypos || | |
2428 cdl->ascent != ddl->ascent || | |
2429 cdl->descent != ddl->descent || | |
2430 cdl->clip != ddl->clip) | |
2431 need_to_clear_bottom = 1; | |
2432 | |
2433 /* #### This kludge is to make sure the modeline shadows get | |
2434 redrawn if the modeline position shifts. */ | |
2435 if (need_to_clear_bottom) | |
2436 w->shadow_thickness_changed = 1; | |
2437 } | |
2438 | |
2439 if (!need_to_clear_bottom) | |
2440 { | |
2441 cdl = ddl = 0; | |
2442 | |
2443 if (cdla_len) | |
2444 cdl = Dynarr_atp (cdla, cdla_len - 1); | |
2445 if (ddla_len) | |
2446 ddl = Dynarr_atp (ddla, ddla_len - 1); | |
2447 | |
2448 if (!cdl || !ddl) | |
2449 need_to_clear_bottom = 1; | |
2450 else | |
2451 { | |
2452 int cdl_bottom, ddl_bottom; | |
2453 | |
2454 cdl_bottom = cdl->ypos + cdl->descent; | |
2455 ddl_bottom = ddl->ypos + ddl->descent; | |
2456 | |
2457 if (cdl_bottom > ddl_bottom) | |
2458 { | |
2459 need_to_clear_bottom = 1; | |
2460 need_to_clear_start = ddl_bottom; | |
2461 need_to_clear_end = cdl_bottom; | |
2462 } | |
2463 } | |
2464 } | |
2465 } | |
2466 | |
2467 /* Perform any output initialization. */ | |
442 | 2468 MAYBE_DEVMETH (d, window_output_begin, (w)); |
428 | 2469 |
2470 /* If the window's structure has changed clear the internal border | |
2471 above it if it is topmost (the function will check). */ | |
448 | 2472 if (f->windows_structure_changed || f->faces_changed) |
428 | 2473 redisplay_clear_top_of_window (w); |
2474 | |
2475 /* Output each line. */ | |
2476 for (line = 0; line < Dynarr_length (ddla); line++) | |
2477 { | |
2478 output_display_line (w, cdla, ddla, line, -1, -1); | |
2479 } | |
2480 | |
2481 /* If the number of display lines has shrunk, adjust. */ | |
2482 if (cdla_len > ddla_len) | |
2483 { | |
5038 | 2484 Dynarr_set_lengthr (cdla, ddla_len); |
428 | 2485 } |
2486 | |
2487 /* Output a vertical divider between windows, if necessary. */ | |
2488 if (window_needs_vertical_divider (w) | |
2489 && (f->windows_structure_changed || f->clear)) | |
2490 { | |
442 | 2491 MAYBE_DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed)); |
428 | 2492 } |
2493 | |
2494 /* Clear the rest of the window, if necessary. */ | |
2495 if (need_to_clear_bottom) | |
2496 { | |
2497 redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start, | |
2498 need_to_clear_end); | |
2499 } | |
2500 | |
2501 w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP]; | |
2502 Fset_marker (w->start[CURRENT_DISP], | |
2503 make_int (marker_position (w->start[DESIRED_DISP])), | |
2504 w->buffer); | |
2505 Fset_marker (w->pointm[CURRENT_DISP], | |
2506 make_int (marker_position (w->pointm[DESIRED_DISP])), | |
2507 w->buffer); | |
2508 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP]; | |
2509 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP]; | |
2510 Fset_marker (w->last_start[CURRENT_DISP], | |
2511 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer); | |
2512 Fset_marker (w->last_point[CURRENT_DISP], | |
2513 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer); | |
2514 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP]; | |
2515 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP]; | |
2516 w->shadow_thickness_changed = 0; | |
2517 | |
2518 set_window_display_buffer (w, XBUFFER (w->buffer)); | |
2519 find_window_mirror (w)->truncate_win = window_truncation_on (w); | |
2520 | |
2521 /* Overkill on invalidating the cache. It is very bad for it to not | |
2522 get invalidated when it should be. */ | |
2523 INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d); | |
2524 | |
442 | 2525 redisplay_redraw_cursor (f, 0); |
2526 MAYBE_DEVMETH (d, window_output_end, (w)); | |
428 | 2527 |
2528 #ifdef HAVE_SCROLLBARS | |
2529 update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0); | |
2530 #endif | |
2531 } | |
2532 | |
2533 /***************************************************************************** | |
1318 | 2534 redisplay_redraw_exposed_window |
2535 | |
2536 Given a bounding box for an area that needs to be redrawn, determine | |
2537 what parts of what lines are contained within and re-output their | |
2538 contents. | |
2539 ****************************************************************************/ | |
2540 static void | |
2541 redisplay_redraw_exposed_window (struct window *w, int x, int y, int width, | |
2542 int height) | |
2543 { | |
2544 struct frame *f = XFRAME (w->frame); | |
2545 int line; | |
2546 int start_x, start_y, end_x, end_y; | |
2547 int orig_windows_structure_changed; | |
2548 | |
2549 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
2550 | |
2551 if (!NILP (w->vchild)) | |
2552 { | |
2553 redisplay_redraw_exposed_windows (w->vchild, x, y, width, height); | |
2554 return; | |
2555 } | |
2556 else if (!NILP (w->hchild)) | |
2557 { | |
2558 redisplay_redraw_exposed_windows (w->hchild, x, y, width, height); | |
2559 return; | |
2560 } | |
2561 | |
2562 /* If the window doesn't intersect the exposed region, we're done here. */ | |
2563 if (x >= WINDOW_RIGHT (w) || (x + width) <= WINDOW_LEFT (w) | |
2564 || y >= WINDOW_BOTTOM (w) || (y + height) <= WINDOW_TOP (w)) | |
2565 { | |
2566 return; | |
2567 } | |
2568 else | |
2569 { | |
2570 start_x = max (WINDOW_LEFT (w), x); | |
2571 end_x = min (WINDOW_RIGHT (w), (x + width)); | |
2572 start_y = max (WINDOW_TOP (w), y); | |
2573 end_y = min (WINDOW_BOTTOM (w), y + height); | |
2574 | |
2575 /* We do this to make sure that the 3D modelines get redrawn if | |
4187 | 2576 they are in the exposed region. */ |
1318 | 2577 orig_windows_structure_changed = f->windows_structure_changed; |
2578 f->windows_structure_changed = 1; | |
2579 } | |
2580 | |
2581 /* #### Not in GTK or MS Windows. I think is because of toolbars, which | |
2582 are handled as widgets in GTK and MS Windows, but drawn ourselves in | |
2583 X. For the moment I'm leaving this in, if it causes problems we have | |
2584 some device method indicating whether we're drawing our own | |
2585 toolbars. */ | |
2586 redisplay_clear_top_of_window (w); | |
2587 if (window_needs_vertical_divider (w)) | |
2588 { | |
2589 FRAMEMETH (f, output_vertical_divider, (w, 0)); | |
2590 } | |
2591 | |
2592 for (line = 0; line < Dynarr_length (cdla); line++) | |
2593 { | |
2594 struct display_line *cdl = Dynarr_atp (cdla, line); | |
2595 int top_y = DISPLAY_LINE_YPOS (cdl); | |
2596 int bottom_y = DISPLAY_LINE_YPOS (cdl) + DISPLAY_LINE_HEIGHT (cdl); | |
2597 | |
2598 if (bottom_y >= start_y) | |
2599 { | |
2600 if (top_y > end_y) | |
2601 { | |
2602 if (line == 0) | |
2603 continue; | |
2604 else | |
2605 break; | |
2606 } | |
2607 else | |
2608 { | |
2609 output_display_line (w, 0, cdla, line, start_x, end_x); | |
2610 } | |
2611 } | |
2612 } | |
2613 | |
2614 f->windows_structure_changed = orig_windows_structure_changed; | |
2615 | |
2616 /* If there have never been any face cache_elements created, then this | |
2617 expose event doesn't actually have anything to do. */ | |
2618 if (Dynarr_largest (w->face_cachels)) | |
2619 redisplay_clear_bottom_of_window (w, cdla, start_y, end_y); | |
2620 | |
2621 #ifdef HAVE_SCROLLBARS | |
2622 MAYBE_FRAMEMETH (f, redisplay_deadbox, (w, x, y, width, height)); | |
2623 #endif | |
2624 } | |
2625 | |
2626 | |
2627 /***************************************************************************** | |
2628 redisplay_redraw_exposed_windows | |
2629 | |
2630 For each window beneath the given window in the window hierarchy, | |
2631 ensure that it is redrawn if necessary after an Expose event. | |
2632 ****************************************************************************/ | |
2633 static void | |
2634 redisplay_redraw_exposed_windows (Lisp_Object window, int x, int y, int width, | |
2635 int height) | |
2636 { | |
2637 for (; !NILP (window); window = XWINDOW (window)->next) | |
2638 redisplay_redraw_exposed_window (XWINDOW (window), x, y, width, height); | |
2639 } | |
2640 | |
2641 static void | |
2642 redisplay_redraw_exposed_area_1 (Lisp_Object arg) | |
2643 { | |
2644 assert (!in_display); | |
2645 redisplay_redraw_exposed_area (XFRAME (X1ST (arg)), | |
2646 XINT (X2ND (arg)), | |
2647 XINT (X3RD (arg)), | |
2648 XINT (X4TH (arg)), | |
2649 XINT (X5TH (arg))); | |
2650 free_list (arg); | |
2651 } | |
2652 | |
2653 /***************************************************************************** | |
2654 redisplay_redraw_exposed_area | |
2655 | |
2656 For each window on the given frame, ensure that any area in the | |
2657 Exposed area is redrawn. | |
2658 ****************************************************************************/ | |
2659 void | |
2660 redisplay_redraw_exposed_area (struct frame *f, int x, int y, int width, | |
2661 int height) | |
2662 { | |
2663 int depth; | |
2664 | |
2665 if (in_display) | |
2666 { | |
2667 /* Not safe to do it now, so delay it */ | |
2668 register_post_redisplay_action (redisplay_redraw_exposed_area_1, | |
2669 list5 (wrap_frame (f), make_int (x), | |
2670 make_int (y), make_int (width), | |
2671 make_int (height))); | |
2672 return; | |
2673 } | |
2674 | |
2675 depth = enter_redisplay_critical_section (); | |
2676 | |
2677 MAYBE_FRAMEMETH (f, frame_output_begin, (f)); | |
2678 | |
2679 /* If any window on the frame has had its face cache reset then the | |
2680 redisplay structures are effectively invalid. If we attempt to | |
2681 use them we'll blow up. We mark the frame as changed to ensure | |
2682 that redisplay will do a full update. This probably isn't | |
2683 necessary but it can't hurt. */ | |
2684 #ifdef HAVE_TOOLBARS | |
2685 /* #### We would rather put these off as well but there is currently | |
2686 no combination of flags which will force an unchanged toolbar to | |
2687 redraw anyhow. */ | |
2688 MAYBE_FRAMEMETH (f, redraw_exposed_toolbars, (f, x, y, width, height)); | |
2689 #endif | |
2690 redraw_exposed_gutters (f, x, y, width, height); | |
2691 | |
2692 if (!f->window_face_cache_reset) | |
2693 { | |
2694 redisplay_redraw_exposed_windows (f->root_window, x, y, width, height); | |
2695 /* #### Why not call this always? */ | |
2696 MAYBE_FRAMEMETH (f, frame_output_end, (f)); | |
2697 } | |
2698 else | |
2699 MARK_FRAME_CHANGED (f); | |
2700 | |
2701 exit_redisplay_critical_section (depth); | |
2702 } | |
2703 | |
2704 /***************************************************************************** | |
428 | 2705 bevel_modeline |
2706 | |
2707 Draw a 3d border around the modeline on window W. | |
2708 ****************************************************************************/ | |
2709 void | |
2710 bevel_modeline (struct window *w, struct display_line *dl) | |
2711 { | |
2712 struct frame *f = XFRAME (w->frame); | |
2713 struct device *d = XDEVICE (f->device); | |
2714 int x, y, width, height; | |
2715 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); | |
2716 enum edge_style style; | |
2717 | |
2718 x = WINDOW_MODELINE_LEFT (w); | |
2719 width = WINDOW_MODELINE_RIGHT (w) - x; | |
2720 y = dl->ypos - dl->ascent - shadow_thickness; | |
2721 height = dl->ascent + dl->descent + 2 * shadow_thickness; | |
2722 | |
2723 if (XINT (w->modeline_shadow_thickness) < 0) | |
2724 { | |
2725 style = EDGE_BEVEL_IN; | |
2726 } | |
2727 else | |
2728 { | |
2729 style = EDGE_BEVEL_OUT; | |
2730 } | |
2731 | |
434 | 2732 MAYBE_DEVMETH (d, bevel_area, |
428 | 2733 (w, MODELINE_INDEX, x, y, width, height, shadow_thickness, |
2734 EDGE_ALL, style)); | |
2735 } |