Mercurial > hg > xemacs-beta
comparison src/redisplay-output.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 0293115a14e9 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 /* Synchronize redisplay structures and output changes. | |
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. | |
3 Copyright (C) 1995, 1996 Ben Wing. | |
4 Copyright (C) 1996 Chuck Thompson. | |
5 | |
6 This file is part of XEmacs. | |
7 | |
8 XEmacs is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
10 Free Software Foundation; either version 2, or (at your option) any | |
11 later version. | |
12 | |
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with XEmacs; see the file COPYING. If not, write to | |
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
21 Boston, MA 02111-1307, USA. */ | |
22 | |
23 /* Synched up with: Not in FSF. */ | |
24 | |
25 /* This file has been Mule-ized. */ | |
26 | |
27 /* Author: Chuck Thompson */ | |
28 | |
29 #include <config.h> | |
30 #include "lisp.h" | |
31 #include "debug.h" | |
32 | |
33 #include "buffer.h" | |
34 #include "window.h" | |
35 #include "frame.h" | |
36 #include "device.h" | |
37 #include "glyphs.h" | |
38 #include "redisplay.h" | |
39 #include "faces.h" | |
40 | |
41 #include "sysdep.h" | |
42 | |
43 static int compare_runes (struct window *w, struct rune *crb, | |
44 struct rune *drb); | |
45 static void redraw_cursor_in_window (struct window *w, | |
46 int run_end_begin_glyphs); | |
47 void redisplay_output_window (struct window *w); | |
48 | |
49 /***************************************************************************** | |
50 sync_rune_structs | |
51 | |
52 Synchronize the given rune blocks. | |
53 ****************************************************************************/ | |
54 static void | |
55 sync_rune_structs (struct window *w, rune_dynarr *cra, rune_dynarr *dra) | |
56 { | |
57 int rune_elt; | |
58 int max_move = ((Dynarr_length (dra) > Dynarr_largest (cra)) | |
59 ? Dynarr_largest (cra) | |
60 : Dynarr_length (dra)); | |
61 | |
62 if (max_move) | |
63 { | |
64 /* #### Doing this directly breaks the encapsulation. But, the | |
65 running time of this function has a measurable impact on | |
66 redisplay performance so avoiding all excess overhead is a | |
67 good thing. Is all of this true? */ | |
68 memcpy (cra->base, dra->base, sizeof (struct rune) * max_move); | |
69 Dynarr_set_size (cra, max_move); | |
70 } | |
71 else | |
72 Dynarr_reset (cra); | |
73 | |
74 for (rune_elt = max_move; rune_elt < Dynarr_length (dra); rune_elt++) | |
75 { | |
76 struct rune rb, *crb; | |
77 struct rune *drb = Dynarr_atp (dra, rune_elt); | |
78 | |
79 crb = &rb; | |
80 memcpy (crb, drb, sizeof (struct rune)); | |
81 Dynarr_add (cra, *crb); | |
82 } | |
83 } | |
84 | |
85 /***************************************************************************** | |
86 sync_display_line_structs | |
87 | |
88 For the given LINE in window W, make the current display line equal | |
89 the desired display line. | |
90 ****************************************************************************/ | |
91 static void | |
92 sync_display_line_structs (struct window *w, int line, int do_blocks, | |
93 display_line_dynarr *cdla, | |
94 display_line_dynarr *ddla) | |
95 { | |
96 int cdla_len = Dynarr_length (cdla); | |
97 | |
98 struct display_line dl, *clp, *dlp; | |
99 int db_elt; | |
100 | |
101 dlp = Dynarr_atp (ddla, line); | |
102 if (line >= Dynarr_largest (cdla)) | |
103 { | |
104 clp = &dl; | |
105 clp->display_blocks = Dynarr_new (struct display_block); | |
106 } | |
107 else | |
108 { | |
109 clp = Dynarr_atp (cdla, line); | |
110 if (clp->display_blocks) | |
111 Dynarr_reset (clp->display_blocks); | |
112 if (clp->left_glyphs) | |
113 { | |
114 Dynarr_free (clp->left_glyphs); | |
115 clp->left_glyphs = 0; | |
116 } | |
117 if (clp->right_glyphs) | |
118 { | |
119 Dynarr_free (clp->right_glyphs); | |
120 clp->right_glyphs = 0; | |
121 } | |
122 } | |
123 { | |
124 display_block_dynarr *tdb = clp->display_blocks; | |
125 | |
126 memcpy (clp, dlp, sizeof (struct display_line)); | |
127 clp->display_blocks = tdb; | |
128 clp->left_glyphs = 0; | |
129 clp->right_glyphs = 0; | |
130 } | |
131 | |
132 if (!do_blocks && line >= cdla_len) | |
133 { | |
134 Dynarr_add (cdla, *clp); | |
135 return; | |
136 } | |
137 | |
138 for (db_elt = 0; db_elt < Dynarr_length (dlp->display_blocks); db_elt++) | |
139 { | |
140 struct display_block db, *cdb; | |
141 struct display_block *ddb = Dynarr_atp (dlp->display_blocks, db_elt); | |
142 | |
143 if (db_elt >= Dynarr_largest (clp->display_blocks)) | |
144 { | |
145 cdb = &db; | |
146 memcpy (cdb, ddb, sizeof (struct display_block)); | |
147 cdb->runes = Dynarr_new (struct rune); | |
148 Dynarr_add (clp->display_blocks, *cdb); | |
149 } | |
150 else | |
151 { | |
152 rune_dynarr *tr; | |
153 | |
154 cdb = Dynarr_atp (clp->display_blocks, db_elt); | |
155 tr = cdb->runes; | |
156 memcpy (cdb, ddb, sizeof (struct display_block)); | |
157 cdb->runes = tr; | |
158 Dynarr_increment (clp->display_blocks); | |
159 } | |
160 | |
161 sync_rune_structs (w, cdb->runes, ddb->runes); | |
162 } | |
163 | |
164 if (line >= cdla_len) | |
165 Dynarr_add (cdla, *clp); | |
166 } | |
167 | |
168 /***************************************************************************** | |
169 compare_runes | |
170 | |
171 Compare to runes to see if each of their fields is equal. If so, | |
172 return true otherwise return false. | |
173 ****************************************************************************/ | |
174 static int | |
175 compare_runes (struct window *w, struct rune *crb, struct rune *drb) | |
176 { | |
177 /* Do not compare the values of bufpos and endpos. They do not | |
178 affect the display characteristics. */ | |
179 | |
180 if ((crb->findex != drb->findex) || | |
181 (WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))) | |
182 return 0; | |
183 else if (crb->xpos != drb->xpos) | |
184 return 0; | |
185 else if (crb->width != drb->width) | |
186 return 0; | |
187 else if (crb->cursor_type != drb->cursor_type) | |
188 return 0; | |
189 else if (crb->type != drb->type) | |
190 return 0; | |
191 else if (crb->type == RUNE_CHAR && | |
192 (crb->object.chr.ch != drb->object.chr.ch)) | |
193 return 0; | |
194 else if (crb->type == RUNE_DGLYPH && | |
195 (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) || | |
196 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) || | |
197 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset)) | |
198 return 0; | |
199 else if (crb->type == RUNE_HLINE && | |
200 (crb->object.hline.thickness != drb->object.hline.thickness || | |
201 crb->object.hline.yoffset != drb->object.hline.yoffset)) | |
202 return 0; | |
203 else | |
204 return 1; | |
205 } | |
206 | |
207 /***************************************************************************** | |
208 get_next_display_block | |
209 | |
210 Return the next display starting at or overlapping START_POS. Return | |
211 the start of the next region in NEXT_START. | |
212 ****************************************************************************/ | |
213 int | |
214 get_next_display_block (layout_bounds bounds, display_block_dynarr *dba, | |
215 int start_pos, int *next_start) | |
216 { | |
217 int next_display_block = NO_BLOCK; | |
218 int priority = -1; | |
219 int block; | |
220 | |
221 /* If we don't find a display block covering or starting at | |
222 start_pos, then we return the starting point of the next display | |
223 block or the next division boundary, whichever is closer to | |
224 start_pos. */ | |
225 if (next_start) | |
226 { | |
227 if (start_pos >= bounds.left_out && start_pos < bounds.left_in) | |
228 *next_start = bounds.left_in; | |
229 else if (start_pos < bounds.left_white) | |
230 *next_start = bounds.left_white; | |
231 else if (start_pos < bounds.right_white) | |
232 *next_start = bounds.right_white; | |
233 else if (start_pos < bounds.right_in) | |
234 *next_start = bounds.right_in; | |
235 else if (start_pos <= bounds.right_out) | |
236 *next_start = bounds.right_out; | |
237 else | |
238 abort (); | |
239 } | |
240 | |
241 for (block = 0; block < Dynarr_length (dba); block++) | |
242 { | |
243 struct display_block *db = Dynarr_atp (dba, block); | |
244 | |
245 if (db->start_pos <= start_pos && db->end_pos > start_pos) | |
246 { | |
247 if ((int) db->type > priority) | |
248 { | |
249 priority = db->type; | |
250 next_display_block = block; | |
251 if (next_start) | |
252 *next_start = db->end_pos; | |
253 } | |
254 } | |
255 else if (next_start && db->start_pos > start_pos) | |
256 { | |
257 if (db->start_pos < *next_start) | |
258 *next_start = db->start_pos; | |
259 } | |
260 } | |
261 | |
262 return next_display_block; | |
263 } | |
264 | |
265 /***************************************************************************** | |
266 get_cursor_size_and_location | |
267 | |
268 Return the information defining the pixel location of the cursor. | |
269 ****************************************************************************/ | |
270 static void | |
271 get_cursor_size_and_location (struct window *w, struct display_block *db, | |
272 int cursor_location, | |
273 int *cursor_start, int *cursor_width, | |
274 int *cursor_height) | |
275 { | |
276 struct rune *rb; | |
277 Lisp_Object window = Qnil; | |
278 int defheight, defwidth; | |
279 | |
280 if (Dynarr_length (db->runes) <= cursor_location) | |
281 abort (); | |
282 | |
283 XSETWINDOW (window, w); | |
284 | |
285 rb = Dynarr_atp (db->runes, cursor_location); | |
286 *cursor_start = rb->xpos; | |
287 | |
288 default_face_height_and_width (window, &defheight, &defwidth); | |
289 *cursor_height = defheight; | |
290 | |
291 if (rb->type == RUNE_BLANK) | |
292 *cursor_width = defwidth; | |
293 else | |
294 *cursor_width = rb->width; | |
295 } | |
296 | |
297 /***************************************************************************** | |
298 compare_display_blocks | |
299 | |
300 Given two display blocks, output only those areas where they differ. | |
301 ****************************************************************************/ | |
302 static int | |
303 compare_display_blocks (struct window *w, struct display_line *cdl, | |
304 struct display_line *ddl, int c_block, int d_block, | |
305 int start_pixpos, int cursor_start, int cursor_width, | |
306 int cursor_height) | |
307 { | |
308 struct frame *f = XFRAME (w->frame); | |
309 struct device *d = XDEVICE (f->device); | |
310 | |
311 struct display_block *cdb, *ddb; | |
312 int start_pos; | |
313 int stop_pos; | |
314 int force = 0; | |
315 int block_end; | |
316 | |
317 cdb = Dynarr_atp (cdl->display_blocks, c_block); | |
318 ddb = Dynarr_atp (ddl->display_blocks, d_block); | |
319 | |
320 assert (cdb->type == ddb->type); | |
321 | |
322 start_pos = -1; | |
323 stop_pos = min (Dynarr_length (cdb->runes), Dynarr_length (ddb->runes)); | |
324 | |
325 block_end = | |
326 (!Dynarr_length (ddb->runes) | |
327 ? 0 | |
328 : (Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->xpos + | |
329 Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->width)); | |
330 | |
331 /* If the new block type is not text and the cursor status is | |
332 changing and it overlaps the position of this block then force a | |
333 full redraw of the block in order to make sure that the cursor is | |
334 updated properly. */ | |
335 if (ddb->type != TEXT | |
336 && ((cdl->cursor_elt == -1 && ddl->cursor_elt != -1) | |
337 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1)) | |
338 && (ddl->cursor_elt == -1 || | |
339 (cursor_start | |
340 && cursor_width | |
341 && (cursor_start + cursor_width) >= start_pixpos | |
342 && cursor_start <= block_end))) | |
343 force = 1; | |
344 | |
345 if (f->windows_structure_changed || | |
346 f->faces_changed || | |
347 cdl->ypos != ddl->ypos || | |
348 cdl->ascent != ddl->ascent || | |
349 cdl->descent != ddl->descent || | |
350 cdl->clip != ddl->clip || | |
351 force) | |
352 { | |
353 start_pos = 0; | |
354 force = 1; | |
355 } | |
356 else | |
357 { | |
358 int elt = 0; | |
359 | |
360 while (start_pos < 0 && elt < stop_pos) | |
361 { | |
362 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt), | |
363 Dynarr_atp (ddb->runes, elt))) | |
364 { | |
365 start_pos = elt; | |
366 } | |
367 else | |
368 { | |
369 elt++; | |
370 } | |
371 } | |
372 | |
373 /* If nothing has changed in the area where the blocks overlap, but | |
374 there are new blocks in the desired block, then adjust the start | |
375 point accordingly. */ | |
376 if (elt == stop_pos && stop_pos < Dynarr_length (ddb->runes)) | |
377 start_pos = stop_pos; | |
378 } | |
379 | |
380 if (start_pos >= 0) | |
381 { | |
382 if ((Dynarr_length (ddb->runes) != Dynarr_length (cdb->runes)) | |
383 || force) | |
384 { | |
385 stop_pos = Dynarr_length (ddb->runes); | |
386 } | |
387 else | |
388 { | |
389 /* If the lines have the same number of runes and we are not | |
390 forcing a full redraw because the display line has | |
391 changed position then we try and optimize how much of the | |
392 line we actually redraw by scanning backwards from the | |
393 end for the first changed rune. This optimization is | |
394 almost always triggered by face changes. */ | |
395 | |
396 int elt = Dynarr_length (ddb->runes) - 1; | |
397 | |
398 while (elt > start_pos) | |
399 { | |
400 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt), | |
401 Dynarr_atp (ddb->runes, elt))) | |
402 break; | |
403 else | |
404 elt--; | |
405 } | |
406 stop_pos = elt + 1; | |
407 } | |
408 | |
409 DEVMETH (d, output_display_block, (w, ddl, d_block, start_pos, | |
410 stop_pos, start_pixpos, | |
411 cursor_start, cursor_width, | |
412 cursor_height)); | |
413 return 1; | |
414 } | |
415 | |
416 return 0; | |
417 } | |
418 | |
419 /***************************************************************************** | |
420 clear_left_border | |
421 | |
422 Clear the lefthand outside border. | |
423 ****************************************************************************/ | |
424 static void | |
425 clear_left_border (struct window *w, int y, int height) | |
426 { | |
427 struct frame *f = XFRAME (w->frame); | |
428 struct device *d = XDEVICE (f->device); | |
429 Lisp_Object window; | |
430 | |
431 XSETWINDOW (window, w); | |
432 DEVMETH (d, clear_region, (window, DEFAULT_INDEX, | |
433 FRAME_LEFT_BORDER_START (f), y, | |
434 FRAME_BORDER_WIDTH (f), height)); | |
435 } | |
436 | |
437 /***************************************************************************** | |
438 clear_right_border | |
439 | |
440 Clear the righthand outside border. | |
441 ****************************************************************************/ | |
442 static void | |
443 clear_right_border (struct window *w, int y, int height) | |
444 { | |
445 struct frame *f = XFRAME (w->frame); | |
446 struct device *d = XDEVICE (f->device); | |
447 Lisp_Object window; | |
448 | |
449 XSETWINDOW (window, w); | |
450 DEVMETH (d, clear_region, (window, DEFAULT_INDEX, | |
451 FRAME_RIGHT_BORDER_START (f), | |
452 y, FRAME_BORDER_WIDTH (f), height)); | |
453 } | |
454 | |
455 /***************************************************************************** | |
456 output_display_line | |
457 | |
458 Ensure that the contents of the given display line is correct | |
459 on-screen. The force_ parameters are used by redisplay_move_cursor | |
460 to correctly update cursor locations and only cursor locations. | |
461 ****************************************************************************/ | |
462 void | |
463 output_display_line (struct window *w, display_line_dynarr *cdla, | |
464 display_line_dynarr *ddla, int line, int force_start, | |
465 int force_end) | |
466 | |
467 { | |
468 struct frame *f = XFRAME (w->frame); | |
469 struct device *d = XDEVICE (f->device); | |
470 struct buffer *b = XBUFFER (w->buffer); | |
471 struct buffer *old_b = window_display_buffer (w); | |
472 struct display_line *cdl, *ddl; | |
473 display_block_dynarr *cdba, *ddba; | |
474 int start_pixpos, end_pixpos; | |
475 int cursor_start, cursor_width, cursor_height; | |
476 | |
477 int force = (force_start >= 0 || force_end >= 0); | |
478 int clear_border = 0; | |
479 int must_sync = 0; | |
480 | |
481 if (cdla && line < Dynarr_length (cdla)) | |
482 { | |
483 cdl = Dynarr_atp (cdla, line); | |
484 cdba = cdl->display_blocks; | |
485 } | |
486 else | |
487 { | |
488 cdl = NULL; | |
489 cdba = NULL; | |
490 } | |
491 | |
492 ddl = Dynarr_atp (ddla, line); /* assert line < Dynarr_length (ddla) */ | |
493 ddba = ddl->display_blocks; | |
494 | |
495 if (force_start >= 0 && force_start >= ddl->bounds.left_out) | |
496 start_pixpos = force_start; | |
497 else | |
498 start_pixpos = ddl->bounds.left_out; | |
499 | |
500 if (force_end >= 0 && force_end < ddl->bounds.right_out) | |
501 end_pixpos = force_end; | |
502 else | |
503 end_pixpos = ddl->bounds.right_out; | |
504 | |
505 /* Get the cursor parameters. */ | |
506 if (ddl->cursor_elt != -1) | |
507 { | |
508 struct display_block *db; | |
509 | |
510 /* If the lines cursor parameter is not -1 then it indicates | |
511 which rune in the TEXT block contains the cursor. This means | |
512 that there must be at least one display block. The TEXT | |
513 block, if present, must always be the first display block. */ | |
514 assert (Dynarr_length (ddba) != 0); | |
515 | |
516 db = Dynarr_atp (ddba, 0); | |
517 assert (db->type == TEXT); | |
518 | |
519 get_cursor_size_and_location (w, db, ddl->cursor_elt, &cursor_start, | |
520 &cursor_width, &cursor_height); | |
521 } | |
522 else | |
523 { | |
524 cursor_start = cursor_width = cursor_height = 0; | |
525 } | |
526 | |
527 /* The modeline should only have a single block and it had better be | |
528 a TEXT block. */ | |
529 if (ddl->modeline) | |
530 { | |
531 /* The shadow thickness check is necesssary if only the sign of | |
532 the size changed. */ | |
533 if (cdba && !w->shadow_thickness_changed) | |
534 { | |
535 must_sync |= compare_display_blocks (w, cdl, ddl, 0, 0, | |
536 start_pixpos, 0, 0, 0); | |
537 } | |
538 else | |
539 { | |
540 DEVMETH (d, output_display_block, (w, ddl, 0, 0, -1, start_pixpos, | |
541 0, 0, 0)); | |
542 must_sync = 1; | |
543 } | |
544 | |
545 if (must_sync) | |
546 clear_border = 1; | |
547 } | |
548 | |
549 while (!ddl->modeline && start_pixpos < end_pixpos) | |
550 { | |
551 int block; | |
552 int next_start_pixpos; | |
553 | |
554 block = get_next_display_block (ddl->bounds, ddba, start_pixpos, | |
555 &next_start_pixpos); | |
556 | |
557 /* If we didn't find a block then we should blank the area | |
558 between start_pos and next_start if necessary. */ | |
559 if (block == NO_BLOCK) | |
560 { | |
561 /* We only erase those areas which were actually previously | |
562 covered by a display block unless the window structure | |
563 changed. In that case we clear all areas since the current | |
564 structures may actually represent a different buffer. */ | |
565 while (start_pixpos < next_start_pixpos) | |
566 { | |
567 int block_end; | |
568 int old_block; | |
569 | |
570 if (cdba) | |
571 old_block = get_next_display_block (ddl->bounds, cdba, | |
572 start_pixpos, &block_end); | |
573 else | |
574 { | |
575 old_block = NO_BLOCK; | |
576 block_end = next_start_pixpos; | |
577 } | |
578 | |
579 if (!cdba || old_block != NO_BLOCK || b != old_b || | |
580 f->windows_structure_changed || | |
581 f->faces_changed || | |
582 force || | |
583 (cdl && (cdl->ypos != ddl->ypos || | |
584 cdl->ascent != ddl->ascent || | |
585 cdl->descent != ddl->descent || | |
586 cdl->clip != ddl->clip))) | |
587 { | |
588 int x, y, width, height; | |
589 Lisp_Object face; | |
590 | |
591 must_sync = 1; | |
592 x = start_pixpos; | |
593 y = ddl->ypos - ddl->ascent; | |
594 width = min (next_start_pixpos, block_end) - x; | |
595 height = ddl->ascent + ddl->descent - ddl->clip; | |
596 | |
597 if (x < ddl->bounds.left_in) | |
598 face = Vleft_margin_face; | |
599 else if (x < ddl->bounds.right_in) | |
600 face = Vdefault_face; | |
601 else if (x < ddl->bounds.right_out) | |
602 face = Vright_margin_face; | |
603 else | |
604 face = Qnil; | |
605 | |
606 if (!NILP (face)) | |
607 { | |
608 Lisp_Object window; | |
609 | |
610 XSETWINDOW (window, w); | |
611 | |
612 /* Clear the empty area. */ | |
613 DEVMETH (d, clear_region, | |
614 (window, get_builtin_face_cache_index (w, | |
615 face), | |
616 x, y, width, height)); | |
617 | |
618 /* Mark that we should clear the border. This is | |
619 necessary because italic fonts may leave | |
620 droppings in the border. */ | |
621 clear_border = 1; | |
622 } | |
623 } | |
624 | |
625 start_pixpos = min (next_start_pixpos, block_end); | |
626 } | |
627 } | |
628 else | |
629 { | |
630 struct display_block *cdb, *ddb; | |
631 int block_end; | |
632 int old_block; | |
633 | |
634 if (cdba) | |
635 old_block = get_next_display_block (ddl->bounds, cdba, | |
636 start_pixpos, &block_end); | |
637 else | |
638 old_block = NO_BLOCK; | |
639 | |
640 ddb = Dynarr_atp (ddba, block); | |
641 cdb = (old_block != NO_BLOCK ? Dynarr_atp (cdba, old_block) : 0); | |
642 | |
643 /* If there was formerly no block over the current | |
644 region or if it was a block of a different type, then | |
645 output the entire ddb. Otherwise, compare cdb and | |
646 ddb and output only the changed region. */ | |
647 if (!force && cdb && ddb->type == cdb->type && b == old_b) | |
648 { | |
649 must_sync |= compare_display_blocks (w, cdl, ddl, old_block, | |
650 block, start_pixpos, | |
651 cursor_start, cursor_width, | |
652 cursor_height); | |
653 } | |
654 else | |
655 { | |
656 int elt; | |
657 int first_elt = 0; | |
658 int last_elt = -1; | |
659 | |
660 for (elt = 0; elt < Dynarr_length (ddb->runes); elt++) | |
661 { | |
662 struct rune *rb = Dynarr_atp (ddb->runes, elt); | |
663 | |
664 if (start_pixpos >= rb->xpos | |
665 && start_pixpos < rb->xpos + rb->width) | |
666 first_elt = elt; | |
667 | |
668 if (end_pixpos > rb->xpos | |
669 && end_pixpos <= rb->xpos + rb->width) | |
670 { | |
671 last_elt = elt + 1; | |
672 if (last_elt > Dynarr_length (ddb->runes)) | |
673 last_elt = Dynarr_length (ddb->runes); | |
674 break; | |
675 } | |
676 } | |
677 | |
678 must_sync = 1; | |
679 DEVMETH (d, output_display_block, (w, ddl, block, first_elt, | |
680 last_elt, | |
681 start_pixpos, | |
682 cursor_start, cursor_width, | |
683 cursor_height)); | |
684 } | |
685 | |
686 start_pixpos = next_start_pixpos; | |
687 } | |
688 } | |
689 | |
690 /* Clear the internal border if we are next to it and the window | |
691 structure or frame size has changed or if something caused | |
692 clear_border to be tripped. */ | |
693 /* #### Doing this on f->clear sucks but is necessary because of | |
694 window-local background values. */ | |
695 if (f->windows_structure_changed || f->faces_changed || clear_border | |
696 || f->clear) | |
697 { | |
698 int y = ddl->ypos - ddl->ascent; | |
699 int height = ddl->ascent + ddl->descent - ddl->clip; | |
700 | |
701 if (ddl->modeline) | |
702 { | |
703 y -= MODELINE_SHADOW_THICKNESS (w); | |
704 height += (2 * MODELINE_SHADOW_THICKNESS (w)); | |
705 } | |
706 | |
707 if (window_is_leftmost (w)) | |
708 clear_left_border (w, y, height); | |
709 if (window_is_rightmost (w)) | |
710 clear_right_border (w, y, height); | |
711 } | |
712 | |
713 if (cdla) | |
714 sync_display_line_structs (w, line, must_sync, cdla, ddla); | |
715 } | |
716 | |
717 /***************************************************************************** | |
718 redisplay_move_cursor | |
719 | |
720 For the given window W, move the cursor to NEW_POINT. Returns a | |
721 boolean indicating success or failure. | |
722 ****************************************************************************/ | |
723 | |
724 #define ADJ_BUFPOS (rb->bufpos + dl->offset) | |
725 #define ADJ_ENDPOS (rb->endpos + dl->offset) | |
726 | |
727 int | |
728 redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end) | |
729 { | |
730 struct frame *f = XFRAME (w->frame); | |
731 struct device *d = XDEVICE (f->device); | |
732 | |
733 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP); | |
734 struct display_line *dl; | |
735 struct display_block *db; | |
736 struct rune *rb; | |
737 | |
738 int x = w->last_point_x[CURRENT_DISP]; | |
739 int y = w->last_point_y[CURRENT_DISP]; | |
740 | |
741 if (y < 0 || y >= Dynarr_length (cla)) | |
742 return 0; | |
743 | |
744 dl = Dynarr_atp (cla, y); | |
745 db = get_display_block_from_line (dl, TEXT); | |
746 | |
747 if (x < 0 || x >= Dynarr_length (db->runes)) | |
748 return 0; | |
749 | |
750 rb = Dynarr_atp (db->runes, x); | |
751 | |
752 if (rb->cursor_type == CURSOR_OFF) | |
753 return 0; | |
754 else if (ADJ_BUFPOS == new_point | |
755 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS) | |
756 && (new_point <= ADJ_ENDPOS))) | |
757 { | |
758 w->last_point_x[CURRENT_DISP] = x; | |
759 w->last_point_y[CURRENT_DISP] = y; | |
760 Fset_marker (w->last_point[CURRENT_DISP], make_int (ADJ_BUFPOS), | |
761 w->buffer); | |
762 dl->cursor_elt = x; | |
763 return 1; | |
764 } | |
765 else | |
766 { | |
767 DEVMETH (d, output_begin, (d)); | |
768 | |
769 /* #### This is a gross kludge. Cursor handling is such a royal | |
770 pain in the ass. */ | |
771 if (rb->type == RUNE_DGLYPH && | |
772 (EQ (rb->object.dglyph.glyph, Vtruncation_glyph) || | |
773 EQ (rb->object.dglyph.glyph, Vcontinuation_glyph))) | |
774 rb->cursor_type = NO_CURSOR; | |
775 else | |
776 rb->cursor_type = CURSOR_OFF; | |
777 dl->cursor_elt = -1; | |
778 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width); | |
779 } | |
780 | |
781 w->last_point_x[CURRENT_DISP] = -1; | |
782 w->last_point_y[CURRENT_DISP] = -1; | |
783 Fset_marker (w->last_point[CURRENT_DISP], Qnil, w->buffer); | |
784 | |
785 /* If this isn't the selected frame, then erasing the old cursor is | |
786 all we actually had to do. */ | |
787 if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d)))) | |
788 { | |
789 if (!no_output_end) | |
790 DEVMETH (d, output_end, (d)); | |
791 | |
792 return 1; | |
793 } | |
794 | |
795 /* This should only occur in the minibuffer. */ | |
796 if (new_point == 0) | |
797 { | |
798 w->last_point_x[CURRENT_DISP] = 0; | |
799 w->last_point_y[CURRENT_DISP] = y; | |
800 Fset_marker (w->last_point[CURRENT_DISP], Qzero, w->buffer); | |
801 | |
802 rb = Dynarr_atp (db->runes, 0); | |
803 rb->cursor_type = CURSOR_ON; | |
804 dl->cursor_elt = 0; | |
805 | |
806 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width); | |
807 | |
808 if (!no_output_end) | |
809 DEVMETH (d, output_end, (d)); | |
810 return 1; | |
811 } | |
812 else | |
813 { | |
814 int cur_rb = 0; | |
815 int first = 0; | |
816 int cur_dl, up; | |
817 | |
818 if (ADJ_BUFPOS < new_point) | |
819 { | |
820 up = 1; | |
821 cur_rb = x + 1; | |
822 cur_dl = y; | |
823 } | |
824 else /* (rb->bufpos + dl->offset) > new_point */ | |
825 { | |
826 up = 0; | |
827 | |
828 if (!x) | |
829 { | |
830 cur_dl = y - 1; | |
831 first = 0; | |
832 } | |
833 else | |
834 { | |
835 cur_rb = x - 1; | |
836 cur_dl = y; | |
837 first = 1; | |
838 } | |
839 } | |
840 | |
841 while ((up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0))) | |
842 { | |
843 dl = Dynarr_atp (cla, cur_dl); | |
844 db = get_display_block_from_line (dl, TEXT); | |
845 | |
846 if (!up && !first) | |
847 cur_rb = Dynarr_length (db->runes) - 1; | |
848 | |
849 while ((!scroll_on_clipped_lines || !dl->clip) && | |
850 (up ? (cur_rb < Dynarr_length (db->runes)) : (cur_rb >= 0))) | |
851 { | |
852 rb = Dynarr_atp (db->runes, cur_rb); | |
853 | |
854 if (rb->cursor_type != IGNORE_CURSOR | |
855 && rb->cursor_type != NO_CURSOR && | |
856 (ADJ_BUFPOS == new_point | |
857 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS) | |
858 && (new_point <= ADJ_BUFPOS)))) | |
859 { | |
860 rb->cursor_type = CURSOR_ON; | |
861 dl->cursor_elt = cur_rb; | |
862 | |
863 | |
864 output_display_line (w, 0, cla, cur_dl, rb->xpos, | |
865 rb->xpos + rb->width); | |
866 | |
867 w->last_point_x[CURRENT_DISP] = cur_rb; | |
868 w->last_point_y[CURRENT_DISP] = cur_dl; | |
869 Fset_marker (w->last_point[CURRENT_DISP], | |
870 make_int (ADJ_BUFPOS), w->buffer); | |
871 | |
872 if (!no_output_end) | |
873 DEVMETH (d, output_end, (d)); | |
874 return 1; | |
875 } | |
876 | |
877 (up ? cur_rb++ : cur_rb--); | |
878 } | |
879 | |
880 (up ? (cur_rb = 0) : (first = 0)); | |
881 (up ? cur_dl++ : cur_dl--); | |
882 } | |
883 } | |
884 | |
885 if (!no_output_end) | |
886 DEVMETH (d, output_end, (d)); | |
887 return 0; | |
888 } | |
889 #undef ADJ_BUFPOS | |
890 #undef ADJ_ENDPOS | |
891 | |
892 /***************************************************************************** | |
893 redraw_cursor_in_window | |
894 | |
895 For the given window W, redraw the cursor if it is contained within | |
896 the window. | |
897 ****************************************************************************/ | |
898 static void | |
899 redraw_cursor_in_window (struct window *w, int run_end_begin_meths) | |
900 { | |
901 struct frame *f = XFRAME (w->frame); | |
902 struct device *d = XDEVICE (f->device); | |
903 | |
904 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); | |
905 struct display_line *dl; | |
906 struct display_block *db; | |
907 struct rune *rb; | |
908 | |
909 int x = w->last_point_x[CURRENT_DISP]; | |
910 int y = w->last_point_y[CURRENT_DISP]; | |
911 | |
912 if (y < 0 || y >= Dynarr_length (dla)) | |
913 return; | |
914 | |
915 if (MINI_WINDOW_P (w) && f != device_selected_frame (d) && | |
916 !is_surrogate_for_selected_frame (f)) | |
917 return; | |
918 | |
919 dl = Dynarr_atp (dla, y); | |
920 db = get_display_block_from_line (dl, TEXT); | |
921 | |
922 if (x < 0 || x >= Dynarr_length (db->runes)) | |
923 return; | |
924 | |
925 rb = Dynarr_atp (db->runes, x); | |
926 | |
927 /* Don't call the output routine if the block isn't actually the | |
928 cursor. */ | |
929 if (rb->cursor_type == CURSOR_ON) | |
930 { | |
931 if (run_end_begin_meths) | |
932 DEVMETH (d, output_begin, (d)); | |
933 | |
934 output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width); | |
935 | |
936 if (run_end_begin_meths) | |
937 DEVMETH (d, output_end, (d)); | |
938 } | |
939 } | |
940 | |
941 /***************************************************************************** | |
942 redisplay_redraw_cursor | |
943 | |
944 For the given frame F, redraw the cursor on the selected window. | |
945 This is used to update the cursor after focus changes. | |
946 ****************************************************************************/ | |
947 void | |
948 redisplay_redraw_cursor (struct frame *f, int run_end_begin_meths) | |
949 { | |
950 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f)); | |
951 | |
952 redraw_cursor_in_window (w, run_end_begin_meths); | |
953 } | |
954 | |
955 /***************************************************************************** | |
956 redisplay_clear_top_of_window | |
957 | |
958 If window is topmost, clear the internal border above it. | |
959 ****************************************************************************/ | |
960 static void | |
961 redisplay_clear_top_of_window (struct window *w) | |
962 { | |
963 Lisp_Object window; | |
964 XSETWINDOW (window, w); | |
965 | |
966 if (!NILP (Fwindow_highest_p (window))) | |
967 { | |
968 struct frame *f = XFRAME (w->frame); | |
969 struct device *d = XDEVICE (f->device); | |
970 int x, y, width, height; | |
971 | |
972 x = w->pixel_left; | |
973 width = w->pixel_width; | |
974 | |
975 if (window_is_leftmost (w)) | |
976 { | |
977 x -= FRAME_BORDER_WIDTH (f); | |
978 width += FRAME_BORDER_WIDTH (f); | |
979 } | |
980 if (window_is_rightmost (w)) | |
981 width += FRAME_BORDER_WIDTH (f); | |
982 | |
983 y = FRAME_TOP_BORDER_START (f) - 1; | |
984 height = FRAME_BORDER_HEIGHT (f) + 1; | |
985 | |
986 DEVMETH (d, clear_region, (window, DEFAULT_INDEX, x, y, width, height)); | |
987 } | |
988 } | |
989 | |
990 /***************************************************************************** | |
991 redisplay_clear_bottom_of_window | |
992 | |
993 Clear window from right below the last display line to right above | |
994 the modeline. The calling function can limit the area actually | |
995 erased by setting min_start and/or max_end to positive values. | |
996 ****************************************************************************/ | |
997 void | |
998 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla, | |
999 int min_start, int max_end) | |
1000 { | |
1001 struct frame *f = XFRAME (w->frame); | |
1002 struct device *d = XDEVICE (f->device); | |
1003 int ypos1, ypos2; | |
1004 int ddla_len = Dynarr_length (ddla); | |
1005 | |
1006 ypos2 = WINDOW_TEXT_BOTTOM (w); | |
1007 #ifdef HAVE_SCROLLBARS | |
1008 /* This adjustment is to catch the intersection of any scrollbars. */ | |
1009 if (f->windows_structure_changed && !f->scrollbar_on_top) | |
1010 ypos2 += window_scrollbar_height (w); | |
1011 #endif | |
1012 | |
1013 if (ddla_len) | |
1014 { | |
1015 if (ddla_len == 1 && Dynarr_atp (ddla, 0)->modeline) | |
1016 { | |
1017 ypos1 = WINDOW_TEXT_TOP (w); | |
1018 #ifdef HAVE_SCROLLBARS | |
1019 /* This adjustment is to catch the intersection of any scrollbars. */ | |
1020 if (f->windows_structure_changed && f->scrollbar_on_top) | |
1021 ypos1 -= window_scrollbar_height (w); | |
1022 #endif | |
1023 } | |
1024 else | |
1025 { | |
1026 struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1); | |
1027 ypos1 = dl->ypos + dl->descent - dl->clip; | |
1028 } | |
1029 } | |
1030 else | |
1031 ypos1 = WINDOW_TEXT_TOP (w); | |
1032 | |
1033 /* #### See if this can be made conditional on the frame | |
1034 changing size. */ | |
1035 if (MINI_WINDOW_P (w)) | |
1036 ypos2 += FRAME_BORDER_HEIGHT (f); | |
1037 | |
1038 if (min_start >= 0 && ypos1 < min_start) | |
1039 ypos1 = min_start; | |
1040 if (max_end >= 0 && ypos2 > max_end) | |
1041 ypos2 = max_end; | |
1042 | |
1043 if (ypos2 <= ypos1) | |
1044 return; | |
1045 | |
1046 DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2)); | |
1047 } | |
1048 | |
1049 /***************************************************************************** | |
1050 redisplay_update_line | |
1051 | |
1052 This is used during incremental updates to update a single line and | |
1053 correct the offsets on all lines below it. At the moment | |
1054 update_values is false if we are only updating the modeline. | |
1055 ****************************************************************************/ | |
1056 void | |
1057 redisplay_update_line (struct window *w, int first_line, int last_line, | |
1058 int update_values) | |
1059 { | |
1060 struct frame *f = XFRAME (w->frame); | |
1061 struct device *d = XDEVICE (f->device); | |
1062 | |
1063 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
1064 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
1065 | |
1066 DEVMETH (d, output_begin, (d)); | |
1067 | |
1068 while (first_line <= last_line) | |
1069 { | |
1070 Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos - | |
1071 Dynarr_atp (cdla, first_line)->bufpos); | |
1072 Charcount new_len = (Dynarr_atp (ddla, first_line)->end_bufpos - | |
1073 Dynarr_atp (ddla, first_line)->bufpos); | |
1074 | |
1075 assert (Dynarr_length (cdla) == Dynarr_length (ddla)); | |
1076 | |
1077 /* Output the changes. */ | |
1078 output_display_line (w, cdla, ddla, first_line, -1, -1); | |
1079 | |
1080 /* Update the offsets. */ | |
1081 if (update_values) | |
1082 { | |
1083 int cur_line = first_line + 1; | |
1084 while (cur_line < Dynarr_length (cdla)) | |
1085 { | |
1086 Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len); | |
1087 Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len); | |
1088 cur_line++; | |
1089 } | |
1090 } | |
1091 | |
1092 /* Update the window_end_pos and other settings. */ | |
1093 if (update_values) | |
1094 { | |
1095 w->window_end_pos[CURRENT_DISP] -= (new_len - old_len); | |
1096 | |
1097 if (Dynarr_atp (ddla, first_line)->cursor_elt != -1) | |
1098 { | |
1099 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP]; | |
1100 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP]; | |
1101 } | |
1102 } | |
1103 | |
1104 first_line++; | |
1105 } | |
1106 | |
1107 /* Update the window max line length. We have to scan the entire | |
1108 set of display lines otherwise we might not detect if the max is | |
1109 supposed to shrink. */ | |
1110 if (update_values) | |
1111 { | |
1112 int line = 0; | |
1113 | |
1114 w->max_line_len = 0; | |
1115 while (line < Dynarr_length (ddla)) | |
1116 { | |
1117 struct display_line *dl = Dynarr_atp (ddla, line); | |
1118 | |
1119 if (!dl->modeline) | |
1120 w->max_line_len = max (dl->num_chars, w->max_line_len); | |
1121 | |
1122 line++; | |
1123 } | |
1124 } | |
1125 | |
1126 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP]; | |
1127 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP]; | |
1128 Fset_marker (w->last_point[CURRENT_DISP], | |
1129 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer); | |
1130 Fset_marker (w->last_start[CURRENT_DISP], | |
1131 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer); | |
1132 | |
1133 /* We don't bother updating the vertical scrollbars here. This | |
1134 gives us a performance increase while having minimal loss of | |
1135 quality to the scrollbar slider size and position since when this | |
1136 function is called we know that the changes to the buffer were | |
1137 very localized. We have to update the horizontal scrollbars, | |
1138 though, because this routine could cause a change which has a | |
1139 larger impact on their sizing. */ | |
1140 /* #### See if we can get away with only calling this if | |
1141 max_line_len is greater than the window_char_width. */ | |
1142 #ifdef HAVE_SCROLLBARS | |
1143 update_window_scrollbars (w, NULL, 1, 1); | |
1144 #endif | |
1145 | |
1146 /* This has to be done after we've updated the values. We don't | |
1147 call output_end for tty frames. Redisplay will do this after all | |
1148 tty windows have been updated. This cuts down on cursor | |
1149 flicker. */ | |
1150 if (FRAME_TTY_P (f)) | |
1151 redisplay_redraw_cursor (f, 0); | |
1152 else | |
1153 DEVMETH (d, output_end, (d)); | |
1154 } | |
1155 | |
1156 /***************************************************************************** | |
1157 redisplay_output_window | |
1158 | |
1159 For the given window W, ensure that the current display lines are | |
1160 equal to the desired display lines, outputing changes as necessary. | |
1161 | |
1162 #### Fuck me. This just isn't going to cut it for tty's. The output | |
1163 decisions for them must be based on the contents of the entire frame | |
1164 because that is how the available output capabilities think. The | |
1165 solution is relatively simple. Create redisplay_output_frame. This | |
1166 will basically merge all of the separate window display structs into | |
1167 a single one for the frame. This combination structure will be able | |
1168 to be passed to the same output_display_line which works for windows | |
1169 on X frames and the right things will happen. It just takes time to | |
1170 do. | |
1171 ****************************************************************************/ | |
1172 void | |
1173 redisplay_output_window (struct window *w) | |
1174 { | |
1175 struct frame *f = XFRAME (w->frame); | |
1176 struct device *d = XDEVICE (f->device); | |
1177 | |
1178 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); | |
1179 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); | |
1180 | |
1181 int cdla_len = Dynarr_length (cdla); | |
1182 int ddla_len = Dynarr_length (ddla); | |
1183 | |
1184 int line; | |
1185 int need_to_clear_bottom = 0; | |
1186 int need_to_clear_start = -1; | |
1187 int need_to_clear_end = -1; | |
1188 | |
1189 /* Backgrounds may have changed or windows may have gone away | |
1190 leaving dividers lying around. */ | |
1191 if (f->faces_changed | |
1192 || f->windows_structure_changed | |
1193 || w->shadow_thickness_changed) | |
1194 need_to_clear_bottom = 1; | |
1195 | |
1196 /* The first thing we do is determine if we are going to need to | |
1197 clear the bottom of the window. We only need to do this if the | |
1198 bottom of the current display lines is below the bottom of the | |
1199 desired display lines. Note that the number of lines is | |
1200 irrelevant. Only the position matters. We also clear to the | |
1201 bottom of the window if the modeline has shifted position. */ | |
1202 /* #### We can't blindly not clear the bottom if f->clear is true | |
1203 since there might be a window-local background. However, for | |
1204 those cases where there isn't, clearing the end of the window in | |
1205 this case sucks. */ | |
1206 if (!need_to_clear_bottom) | |
1207 { | |
1208 struct display_line *cdl, *ddl; | |
1209 | |
1210 /* If the modeline has changed position or size, clear the bottom | |
1211 of the window. */ | |
1212 if (!need_to_clear_bottom) | |
1213 { | |
1214 cdl = ddl = 0; | |
1215 | |
1216 if (cdla_len) | |
1217 cdl = Dynarr_atp (cdla, 0); | |
1218 if (ddla_len) | |
1219 ddl = Dynarr_atp (ddla, 0); | |
1220 | |
1221 if (!cdl || !ddl) | |
1222 need_to_clear_bottom = 1; | |
1223 else if ((!cdl->modeline && ddl->modeline) | |
1224 || (cdl->modeline && !ddl->modeline)) | |
1225 need_to_clear_bottom = 1; | |
1226 else if (cdl->ypos != ddl->ypos || | |
1227 cdl->ascent != ddl->ascent || | |
1228 cdl->descent != ddl->descent || | |
1229 cdl->clip != ddl->clip) | |
1230 need_to_clear_bottom = 1; | |
1231 | |
1232 /* #### This kludge is to make sure the modeline shadows get | |
1233 redrawn if the modeline position shifts. */ | |
1234 if (need_to_clear_bottom) | |
1235 w->shadow_thickness_changed = 1; | |
1236 } | |
1237 | |
1238 if (!need_to_clear_bottom) | |
1239 { | |
1240 cdl = ddl = 0; | |
1241 | |
1242 if (cdla_len) | |
1243 cdl = Dynarr_atp (cdla, cdla_len - 1); | |
1244 if (ddla_len) | |
1245 ddl = Dynarr_atp (ddla, ddla_len - 1); | |
1246 | |
1247 if (!cdl || !ddl) | |
1248 need_to_clear_bottom = 1; | |
1249 else | |
1250 { | |
1251 int cdl_bottom, ddl_bottom; | |
1252 | |
1253 cdl_bottom = cdl->ypos + cdl->descent; | |
1254 ddl_bottom = ddl->ypos + ddl->descent; | |
1255 | |
1256 if (cdl_bottom > ddl_bottom) | |
1257 { | |
1258 need_to_clear_bottom = 1; | |
1259 need_to_clear_start = ddl_bottom; | |
1260 need_to_clear_end = cdl_bottom; | |
1261 } | |
1262 } | |
1263 } | |
1264 } | |
1265 | |
1266 /* Perform any output initialization. */ | |
1267 DEVMETH (d, output_begin, (d)); | |
1268 | |
1269 /* If the window's structure has changed clear the internal border | |
1270 above it if it is topmost (the function will check). */ | |
1271 if (f->windows_structure_changed) | |
1272 redisplay_clear_top_of_window (w); | |
1273 | |
1274 /* Output each line. */ | |
1275 for (line = 0; line < Dynarr_length (ddla); line++) | |
1276 { | |
1277 output_display_line (w, cdla, ddla, line, -1, -1); | |
1278 } | |
1279 | |
1280 /* If the number of display lines has shrunk, adjust. */ | |
1281 if (cdla_len > ddla_len) | |
1282 { | |
1283 Dynarr_length (cdla) = ddla_len; | |
1284 } | |
1285 | |
1286 /* Output a vertical divider between windows, if necessary. */ | |
1287 if (window_needs_vertical_divider (w) | |
1288 && (f->windows_structure_changed || f->clear)) | |
1289 { | |
1290 DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed)); | |
1291 } | |
1292 | |
1293 /* Clear the rest of the window, if necessary. */ | |
1294 if (need_to_clear_bottom) | |
1295 { | |
1296 redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start, | |
1297 need_to_clear_end); | |
1298 } | |
1299 | |
1300 w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP]; | |
1301 Fset_marker (w->start[CURRENT_DISP], | |
1302 make_int (marker_position (w->start[DESIRED_DISP])), | |
1303 w->buffer); | |
1304 Fset_marker (w->pointm[CURRENT_DISP], | |
1305 make_int (marker_position (w->pointm[DESIRED_DISP])), | |
1306 w->buffer); | |
1307 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP]; | |
1308 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP]; | |
1309 Fset_marker (w->last_start[CURRENT_DISP], | |
1310 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer); | |
1311 Fset_marker (w->last_point[CURRENT_DISP], | |
1312 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer); | |
1313 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP]; | |
1314 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP]; | |
1315 w->shadow_thickness_changed = 0; | |
1316 | |
1317 set_window_display_buffer (w, XBUFFER (w->buffer)); | |
1318 find_window_mirror (w)->truncate_win = window_truncation_on (w); | |
1319 | |
1320 /* Overkill on invalidating the cache. It is very bad for it to not | |
1321 get invalidated when it should be. */ | |
1322 INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d); | |
1323 | |
1324 /* We don't call output_end for tty frames. Redisplay will do this | |
1325 after all tty windows have been updated. This cuts down on | |
1326 cursor flicker. */ | |
1327 if (FRAME_TTY_P (f)) | |
1328 redisplay_redraw_cursor (f, 0); | |
1329 else | |
1330 DEVMETH (d, output_end, (d)); | |
1331 | |
1332 #ifdef HAVE_SCROLLBARS | |
1333 update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0); | |
1334 #endif | |
1335 } |