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