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