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 Copyright (C) 1999 Andy Piper.
7 This file is part of XEmacs.
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
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
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. */
24 /* Synched up with: Not in FSF. */
26 /* This file has been Mule-ized. */
28 /* Author: Chuck Thompson */
30 /* Heavily hacked for modularity, gutter and subwindow support by Andy
41 #include "redisplay.h"
44 static int compare_runes (struct window *w, struct rune *crb,
46 static void redraw_cursor_in_window (struct window *w,
47 int run_end_begin_glyphs);
48 static void redisplay_output_display_block (struct window *w, struct display_line *dl,
49 int block, int start, int end, int start_pixpos,
50 int cursor_start, int cursor_width,
52 static void redisplay_normalize_display_box (struct display_box* dest,
53 struct display_glyph_area* src);
54 static int redisplay_display_boxes_in_window_p (struct window* w,
55 struct display_box* db,
56 struct display_glyph_area* dga);
57 static void redisplay_clear_clipped_region (Lisp_Object locale, face_index findex,
58 struct display_box* dest,
59 struct display_glyph_area* glyphsrc,
60 int fullheight_p, Lisp_Object);
62 /*****************************************************************************
65 Synchronize the given rune blocks.
66 ****************************************************************************/
68 sync_rune_structs (struct window *w, rune_dynarr *cra, rune_dynarr *dra)
71 int max_move = ((Dynarr_length (dra) > Dynarr_largest (cra))
72 ? Dynarr_largest (cra)
73 : Dynarr_length (dra));
77 /* #### Doing this directly breaks the encapsulation. But, the
78 running time of this function has a measurable impact on
79 redisplay performance so avoiding all excess overhead is a
80 good thing. Is all of this true? */
81 memcpy (cra->base, dra->base, sizeof (struct rune) * max_move);
82 Dynarr_set_size (cra, max_move);
87 for (rune_elt = max_move; rune_elt < Dynarr_length (dra); rune_elt++)
90 struct rune *drb = Dynarr_atp (dra, rune_elt);
93 memcpy (crb, drb, sizeof (struct rune));
94 Dynarr_add (cra, *crb);
98 /*****************************************************************************
99 sync_display_line_structs
101 For the given LINE in window W, make the current display line equal
102 the desired display line.
103 ****************************************************************************/
105 sync_display_line_structs (struct window *w, int line, int do_blocks,
106 display_line_dynarr *cdla,
107 display_line_dynarr *ddla)
109 int cdla_len = Dynarr_length (cdla);
111 struct display_line dl, *clp, *dlp;
114 dlp = Dynarr_atp (ddla, line);
115 if (line >= Dynarr_largest (cdla))
118 clp->display_blocks = Dynarr_new (display_block);
122 clp = Dynarr_atp (cdla, line);
123 if (clp->display_blocks)
124 Dynarr_reset (clp->display_blocks);
125 if (clp->left_glyphs)
127 Dynarr_free (clp->left_glyphs);
128 clp->left_glyphs = 0;
130 if (clp->right_glyphs)
132 Dynarr_free (clp->right_glyphs);
133 clp->right_glyphs = 0;
137 display_block_dynarr *tdb = clp->display_blocks;
139 memcpy (clp, dlp, sizeof (struct display_line));
140 clp->display_blocks = tdb;
141 clp->left_glyphs = 0;
142 clp->right_glyphs = 0;
145 if (!do_blocks && line >= cdla_len)
147 Dynarr_add (cdla, *clp);
151 for (db_elt = 0; db_elt < Dynarr_length (dlp->display_blocks); db_elt++)
153 struct display_block db, *cdb;
154 struct display_block *ddb = Dynarr_atp (dlp->display_blocks, db_elt);
156 if (db_elt >= Dynarr_largest (clp->display_blocks))
159 memcpy (cdb, ddb, sizeof (struct display_block));
160 cdb->runes = Dynarr_new (rune);
161 Dynarr_add (clp->display_blocks, *cdb);
167 cdb = Dynarr_atp (clp->display_blocks, db_elt);
169 memcpy (cdb, ddb, sizeof (struct display_block));
171 Dynarr_increment (clp->display_blocks);
174 sync_rune_structs (w, cdb->runes, ddb->runes);
177 if (line >= cdla_len)
178 Dynarr_add (cdla, *clp);
181 /*****************************************************************************
184 Compare to runes to see if each of their fields is equal. If so,
185 return true otherwise return false.
186 ****************************************************************************/
188 compare_runes (struct window *w, struct rune *crb, struct rune *drb)
190 /* Do not compare the values of bufpos and endpos. They do not
191 affect the display characteristics. */
193 /* Note: (hanoi 6) spends 95% of its time in redisplay, and about
194 30% here. Not using bitfields for rune.type alone gives a redisplay
197 #### In profile arcs run of a normal Gnus session this function
198 is run 6.76 million times, only to return 1 in 6.73 million of
201 In addition a quick look GCC sparc assembly shows that GCC is not
202 doing a good job here.
203 1. The function is not inlined (too complicated?)
204 2. It seems to be reloading the crb and drb variables all the
206 3. It doesn't seem to notice that the second half of these if's
207 are really a switch statement.
211 #### It would really be worth it to arrange for this function to
212 be (almost) a single call to memcmp. */
214 if (crb->xpos != drb->xpos)
216 else if (crb->width != drb->width)
218 else if (crb->cursor_type != drb->cursor_type)
220 else if (crb->type != drb->type)
222 else if (crb->type == RUNE_CHAR &&
223 (crb->object.chr.ch != drb->object.chr.ch))
225 else if (crb->type == RUNE_HLINE &&
226 (crb->object.hline.thickness != drb->object.hline.thickness ||
227 crb->object.hline.yoffset != drb->object.hline.yoffset))
229 else if (crb->type == RUNE_DGLYPH &&
230 (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) ||
231 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) ||
232 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset))
234 /* Only check dirtiness if we know something has changed. */
235 else if (crb->type == RUNE_DGLYPH &&
236 (XGLYPH_DIRTYP (crb->object.dglyph.glyph) ||
237 crb->findex != drb->findex))
239 /* We need some way of telling redisplay_output_layout () that the
240 only reason we are outputting it is because something has
241 changed internally. That way we can optimize whether we need
242 to clear the layout first and also only output the components
243 that have changed. The image_instance dirty flag and
244 display_hash are no good to us because these will invariably
245 have been set anyway if the layout has changed. So it looks
246 like we need yet another change flag that we can set here and
247 then clear in redisplay_output_layout (). */
248 Lisp_Object window, image;
249 Lisp_Image_Instance* ii;
250 XSETWINDOW (window, w);
251 image = glyph_image_instance (crb->object.dglyph.glyph,
252 window, ERROR_ME_NOT, 1);
253 ii = XIMAGE_INSTANCE (image);
255 if (TEXT_IMAGE_INSTANCEP (image) &&
256 (crb->findex != drb->findex ||
257 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
260 /* It is quite common of the two glyphs to be EQ since in many
261 cases they will actually be the same object. This does not
262 mean, however, that nothing has changed. We therefore need to
263 check the current hash of the glyph against the last recorded
264 display hash and the pending display items. See
265 update_subwindow (). */
266 if (image_instance_changed (image) ||
267 crb->findex != drb->findex ||
268 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
270 /* We now now we are going to re-output the glyph, but since
271 this is for some internal reason not related to geometry
272 changes, send a hint to the output routines that they can
273 take some short cuts. This is most useful for
274 layouts. This flag should get reset by the output
277 #### It is possible for us to get here when the
278 face_cachel is dirty. I do not know what the implications
280 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (ii) = 1;
285 #ifdef DEBUG_WIDGET_OUTPUT
286 if (XIMAGE_INSTANCE_TYPE (image) == IMAGE_LAYOUT)
287 printf ("glyph layout %p considered unchanged\n", ii);
292 /* We now do this last so that glyph checks can do their own thing
293 for face changes. Face changes quite often happen when we are
294 trying to output something in the gutter, this would normally
295 lead to a lot of flashing. The indices can quite often be
296 different and yet the faces are the same, we do not want to
297 re-output in this instance. */
298 else if (crb->findex != drb->findex ||
299 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
305 /*****************************************************************************
306 get_next_display_block
308 Return the next display starting at or overlapping START_POS. Return
309 the start of the next region in NEXT_START.
310 ****************************************************************************/
312 get_next_display_block (layout_bounds bounds, display_block_dynarr *dba,
313 int start_pos, int *next_start)
315 int next_display_block = NO_BLOCK;
319 /* If we don't find a display block covering or starting at
320 start_pos, then we return the starting point of the next display
321 block or the next division boundary, whichever is closer to
325 if (start_pos >= bounds.left_out && start_pos < bounds.left_in)
326 *next_start = bounds.left_in;
327 else if (start_pos < bounds.left_white)
328 *next_start = bounds.left_white;
329 else if (start_pos < bounds.right_white)
330 *next_start = bounds.right_white;
331 else if (start_pos < bounds.right_in)
332 *next_start = bounds.right_in;
333 else if (start_pos <= bounds.right_out)
334 *next_start = bounds.right_out;
339 for (block = 0; block < Dynarr_length (dba); block++)
341 struct display_block *db = Dynarr_atp (dba, block);
343 if (db->start_pos <= start_pos && db->end_pos > start_pos)
345 if ((int) db->type > priority)
348 next_display_block = block;
350 *next_start = db->end_pos;
353 else if (next_start && db->start_pos > start_pos)
355 if (db->start_pos < *next_start)
356 *next_start = db->start_pos;
360 return next_display_block;
363 /*****************************************************************************
364 get_cursor_size_and_location
366 Return the information defining the pixel location of the cursor.
367 ****************************************************************************/
369 get_cursor_size_and_location (struct window *w, struct display_block *db,
371 int *cursor_start, int *cursor_width,
376 int defheight, defwidth;
378 if (Dynarr_length (db->runes) <= cursor_location)
381 XSETWINDOW (window, w);
383 rb = Dynarr_atp (db->runes, cursor_location);
384 *cursor_start = rb->xpos;
386 default_face_height_and_width (window, &defheight, &defwidth);
387 *cursor_height = defheight;
389 if (rb->type == RUNE_BLANK)
390 *cursor_width = defwidth;
392 *cursor_width = rb->width;
395 /*****************************************************************************
396 compare_display_blocks
398 Given two display blocks, output only those areas where they differ.
399 ****************************************************************************/
401 compare_display_blocks (struct window *w, struct display_line *cdl,
402 struct display_line *ddl, int c_block, int d_block,
403 int start_pixpos, int cursor_start, int cursor_width,
406 struct frame *f = XFRAME (w->frame);
407 struct display_block *cdb, *ddb;
413 cdb = Dynarr_atp (cdl->display_blocks, c_block);
414 ddb = Dynarr_atp (ddl->display_blocks, d_block);
416 assert (cdb->type == ddb->type);
419 stop_pos = min (Dynarr_length (cdb->runes), Dynarr_length (ddb->runes));
422 (!Dynarr_length (ddb->runes)
424 : (Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->xpos +
425 Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->width));
427 /* If the new block type is not text and the cursor status is
428 changing and it overlaps the position of this block then force a
429 full redraw of the block in order to make sure that the cursor is
431 if (ddb->type != TEXT
433 /* I'm not sure exactly what this code wants to do, but it's
434 * not right--it doesn't update when cursor_elt changes from, e.g.,
435 * 0 to 8, and the new or old cursor loc overlaps this block.
436 * I've replaced it with the more conservative test below.
437 * -dkindred@cs.cmu.edu 23-Mar-1997 */
438 && ((cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
439 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1))
440 && (ddl->cursor_elt == -1 ||
443 && (cursor_start + cursor_width) >= start_pixpos
444 && cursor_start <= block_end))
446 && (cdl->cursor_elt != ddl->cursor_elt)
451 if (f->windows_structure_changed ||
452 /* #### Why is this so? We have face cachels so that we don't
453 have to recalculate all the display blocks when faces
454 change. I have fixed this for glyphs and am inclined to think
455 that faces should "Just Work", but I'm not feeling brave
456 today. Maybe its because the face cachels represent merged
457 faces rather than simply instantiations in a particular
460 cdl->ypos != ddl->ypos ||
461 cdl->ascent != ddl->ascent ||
462 cdl->descent != ddl->descent ||
463 cdl->clip != ddl->clip ||
473 while (start_pos < 0 && elt < stop_pos)
475 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
476 Dynarr_atp (ddb->runes, elt)))
486 /* If nothing has changed in the area where the blocks overlap, but
487 there are new blocks in the desired block, then adjust the start
488 point accordingly. */
489 if (elt == stop_pos && stop_pos < Dynarr_length (ddb->runes))
490 start_pos = stop_pos;
495 if ((Dynarr_length (ddb->runes) != Dynarr_length (cdb->runes))
498 stop_pos = Dynarr_length (ddb->runes);
502 /* If the lines have the same number of runes and we are not
503 forcing a full redraw because the display line has
504 changed position then we try and optimize how much of the
505 line we actually redraw by scanning backwards from the
506 end for the first changed rune. This optimization is
507 almost always triggered by face changes. */
509 int elt = Dynarr_length (ddb->runes) - 1;
511 while (elt > start_pos)
513 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
514 Dynarr_atp (ddb->runes, elt)))
522 redisplay_output_display_block (w, ddl, d_block, start_pos,
523 stop_pos, start_pixpos,
524 cursor_start, cursor_width,
532 /*****************************************************************************
535 Clear the lefthand outside border.
536 ****************************************************************************/
538 clear_left_border (struct window *w, int y, int height)
540 struct frame *f = XFRAME (w->frame);
543 XSETWINDOW (window, w);
544 redisplay_clear_region (window, DEFAULT_INDEX,
545 FRAME_LEFT_BORDER_START (f), y,
546 FRAME_BORDER_WIDTH (f), height);
549 /*****************************************************************************
552 Clear the righthand outside border.
553 ****************************************************************************/
555 clear_right_border (struct window *w, int y, int height)
557 struct frame *f = XFRAME (w->frame);
560 XSETWINDOW (window, w);
561 redisplay_clear_region (window, DEFAULT_INDEX,
562 FRAME_RIGHT_BORDER_START (f),
563 y, FRAME_BORDER_WIDTH (f), height);
566 /*****************************************************************************
569 Ensure that the contents of the given display line is correct
570 on-screen. The force_ parameters are used by redisplay_move_cursor
571 to correctly update cursor locations and only cursor locations.
572 ****************************************************************************/
574 output_display_line (struct window *w, display_line_dynarr *cdla,
575 display_line_dynarr *ddla, int line, int force_start,
579 struct frame *f = XFRAME (w->frame);
580 struct buffer *b = XBUFFER (w->buffer);
581 struct buffer *old_b = window_display_buffer (w);
582 struct display_line *cdl, *ddl;
583 display_block_dynarr *cdba, *ddba;
584 int start_pixpos, end_pixpos;
585 int cursor_start, cursor_width, cursor_height;
587 int force = (force_start >= 0 || force_end >= 0);
588 int clear_border = 0;
591 if (cdla && line < Dynarr_length (cdla))
593 cdl = Dynarr_atp (cdla, line);
594 cdba = cdl->display_blocks;
602 ddl = Dynarr_atp (ddla, line); /* assert line < Dynarr_length (ddla) */
603 ddba = ddl->display_blocks;
605 if (force_start >= 0 && force_start >= ddl->bounds.left_out)
606 start_pixpos = force_start;
608 start_pixpos = ddl->bounds.left_out;
610 if (force_end >= 0 && force_end < ddl->bounds.right_out)
611 end_pixpos = force_end;
613 end_pixpos = ddl->bounds.right_out;
615 /* Get the cursor parameters. */
616 if (ddl->cursor_elt != -1)
618 struct display_block *db;
620 /* If the lines cursor parameter is not -1 then it indicates
621 which rune in the TEXT block contains the cursor. This means
622 that there must be at least one display block. The TEXT
623 block, if present, must always be the first display block. */
624 assert (Dynarr_length (ddba) != 0);
626 db = Dynarr_atp (ddba, 0);
627 assert (db->type == TEXT);
629 get_cursor_size_and_location (w, db, ddl->cursor_elt, &cursor_start,
630 &cursor_width, &cursor_height);
634 cursor_start = cursor_width = cursor_height = 0;
637 /* The modeline should only have a single block and it had better be
641 /* The shadow thickness check is necessary if only the sign of
643 if (cdba && !w->shadow_thickness_changed)
645 must_sync |= compare_display_blocks (w, cdl, ddl, 0, 0,
646 start_pixpos, 0, 0, 0);
650 redisplay_output_display_block (w, ddl, 0, 0, -1, start_pixpos,
659 while (!ddl->modeline && start_pixpos < end_pixpos)
662 int next_start_pixpos;
664 block = get_next_display_block (ddl->bounds, ddba, start_pixpos,
667 /* If we didn't find a block then we should blank the area
668 between start_pos and next_start if necessary. */
669 if (block == NO_BLOCK)
671 /* We only erase those areas which were actually previously
672 covered by a display block unless the window structure
673 changed. In that case we clear all areas since the current
674 structures may actually represent a different buffer. */
675 while (start_pixpos < next_start_pixpos)
681 old_block = get_next_display_block (ddl->bounds, cdba,
682 start_pixpos, &block_end);
685 old_block = NO_BLOCK;
686 block_end = next_start_pixpos;
689 if (!cdba || old_block != NO_BLOCK || b != old_b ||
690 f->windows_structure_changed ||
693 (cdl && (cdl->ypos != ddl->ypos ||
694 cdl->ascent != ddl->ascent ||
695 cdl->descent != ddl->descent ||
696 cdl->top_clip != ddl->top_clip ||
697 cdl->clip != ddl->clip)))
699 int x, y, width, height;
704 y = DISPLAY_LINE_YPOS (ddl);
705 width = min (next_start_pixpos, block_end) - x;
706 height = DISPLAY_LINE_HEIGHT (ddl);
708 if (x < ddl->bounds.left_in)
710 findex = ddl->left_margin_findex ?
711 ddl->left_margin_findex
712 : get_builtin_face_cache_index (w, Vleft_margin_face);
714 else if (x < ddl->bounds.right_in)
716 /* no check here because DEFAULT_INDEX == 0 anyway */
717 findex = ddl->default_findex;
719 else if (x < ddl->bounds.right_out)
721 findex = ddl->right_margin_findex ?
722 ddl->right_margin_findex
723 : get_builtin_face_cache_index (w, Vright_margin_face);
726 findex = (face_index) -1;
728 if (findex != (face_index) -1)
732 XSETWINDOW (window, w);
734 /* Clear the empty area. */
735 redisplay_clear_region (window, findex, x, y, width, height);
737 /* Mark that we should clear the border. This is
738 necessary because italic fonts may leave
739 droppings in the border. */
744 start_pixpos = min (next_start_pixpos, block_end);
749 struct display_block *cdb, *ddb;
754 old_block = get_next_display_block (ddl->bounds, cdba,
755 start_pixpos, &block_end);
757 old_block = NO_BLOCK;
759 ddb = Dynarr_atp (ddba, block);
760 cdb = (old_block != NO_BLOCK ? Dynarr_atp (cdba, old_block) : 0);
762 /* If there was formerly no block over the current
763 region or if it was a block of a different type, then
764 output the entire ddb. Otherwise, compare cdb and
765 ddb and output only the changed region. */
766 if (!force && cdb && ddb->type == cdb->type
767 /* If there was no buffer being display before the
768 compare anyway as we might be outputting a gutter. */
770 (b == old_b || !old_b))
772 must_sync |= compare_display_blocks (w, cdl, ddl, old_block,
774 cursor_start, cursor_width,
783 for (elt = 0; elt < Dynarr_length (ddb->runes); elt++)
785 struct rune *rb = Dynarr_atp (ddb->runes, elt);
787 if (start_pixpos >= rb->xpos
788 && start_pixpos < rb->xpos + rb->width)
791 if (end_pixpos > rb->xpos
792 && end_pixpos <= rb->xpos + rb->width)
795 if (last_elt > Dynarr_length (ddb->runes))
796 last_elt = Dynarr_length (ddb->runes);
802 redisplay_output_display_block (w, ddl, block, first_elt,
805 cursor_start, cursor_width,
809 start_pixpos = next_start_pixpos;
813 /* Clear the internal border if we are next to it and the window
814 structure or frame size has changed or if something caused
815 clear_border to be tripped. */
816 /* #### Doing this on f->clear sucks but is necessary because of
817 window-local background values. */
818 if (f->windows_structure_changed || f->faces_changed || clear_border
821 int y = DISPLAY_LINE_YPOS (ddl);
822 int height = DISPLAY_LINE_HEIGHT (ddl);
824 /* If we are in the gutter then we musn't clear the borders. */
825 if (y >= WINDOW_TEXT_TOP (w) && (y + height) <= WINDOW_TEXT_BOTTOM (w))
829 y -= MODELINE_SHADOW_THICKNESS (w);
830 height += (2 * MODELINE_SHADOW_THICKNESS (w));
833 if (window_is_leftmost (w))
834 clear_left_border (w, y, height);
835 if (window_is_rightmost (w))
836 clear_right_border (w, y, height);
841 sync_display_line_structs (w, line, must_sync, cdla, ddla);
844 /*****************************************************************************
845 redisplay_move_cursor
847 For the given window W, move the cursor to NEW_POINT. Returns a
848 boolean indicating success or failure.
849 ****************************************************************************/
851 #define ADJ_BUFPOS (rb->bufpos + dl->offset)
852 #define ADJ_ENDPOS (rb->endpos + dl->offset)
855 redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
857 struct frame *f = XFRAME (w->frame);
858 struct device *d = XDEVICE (f->device);
860 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
861 struct display_line *dl;
862 struct display_block *db;
864 int x = w->last_point_x[CURRENT_DISP];
865 int y = w->last_point_y[CURRENT_DISP];
868 * Bail if cursor_in_echo_area is non-zero and we're fiddling with
869 * the cursor in a non-active minibuffer window, since that is a
870 * special case that is handled elsewhere and this function need
871 * not handle it. Return 1 so the caller will assume we
874 if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
875 w != XWINDOW (FRAME_SELECTED_WINDOW (f)))
878 if (y < 0 || y >= Dynarr_length (cla))
881 dl = Dynarr_atp (cla, y);
882 db = get_display_block_from_line (dl, TEXT);
884 if (x < 0 || x >= Dynarr_length (db->runes))
887 rb = Dynarr_atp (db->runes, x);
889 if (rb->cursor_type == CURSOR_OFF)
891 else if (ADJ_BUFPOS == new_point
892 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
893 && (new_point <= ADJ_ENDPOS)))
895 w->last_point_x[CURRENT_DISP] = x;
896 w->last_point_y[CURRENT_DISP] = y;
897 Fset_marker (w->last_point[CURRENT_DISP], make_int (ADJ_BUFPOS),
904 DEVMETH (d, output_begin, (d));
905 rb->cursor_type = CURSOR_OFF;
907 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
910 w->last_point_x[CURRENT_DISP] = -1;
911 w->last_point_y[CURRENT_DISP] = -1;
912 Fset_marker (w->last_point[CURRENT_DISP], Qnil, w->buffer);
914 /* If this isn't the selected frame, then erasing the old cursor is
915 all we actually had to do. */
916 if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d))))
919 DEVMETH (d, output_end, (d));
924 /* This should only occur in the minibuffer. */
927 w->last_point_x[CURRENT_DISP] = 0;
928 w->last_point_y[CURRENT_DISP] = y;
929 Fset_marker (w->last_point[CURRENT_DISP], Qzero, w->buffer);
931 rb = Dynarr_atp (db->runes, 0);
932 rb->cursor_type = CURSOR_ON;
935 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
938 DEVMETH (d, output_end, (d));
947 if (ADJ_BUFPOS < new_point)
953 else /* (rb->bufpos + dl->offset) > new_point */
970 while (up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0))
972 dl = Dynarr_atp (cla, cur_dl);
973 db = get_display_block_from_line (dl, TEXT);
976 cur_rb = Dynarr_length (db->runes) - 1;
978 while ((!scroll_on_clipped_lines || !dl->clip) &&
979 (up ? (cur_rb < Dynarr_length (db->runes)) : (cur_rb >= 0)))
981 rb = Dynarr_atp (db->runes, cur_rb);
983 if (rb->cursor_type != IGNORE_CURSOR
984 && rb->cursor_type != NO_CURSOR &&
985 (ADJ_BUFPOS == new_point
986 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
987 && (new_point <= ADJ_BUFPOS))))
989 rb->cursor_type = CURSOR_ON;
990 dl->cursor_elt = cur_rb;
993 output_display_line (w, 0, cla, cur_dl, rb->xpos,
994 rb->xpos + rb->width);
996 w->last_point_x[CURRENT_DISP] = cur_rb;
997 w->last_point_y[CURRENT_DISP] = cur_dl;
998 Fset_marker (w->last_point[CURRENT_DISP],
999 make_int (ADJ_BUFPOS), w->buffer);
1002 DEVMETH (d, output_end, (d));
1006 (up ? cur_rb++ : cur_rb--);
1009 (up ? (cur_rb = 0) : (first = 0));
1010 (up ? cur_dl++ : cur_dl--);
1015 DEVMETH (d, output_end, (d));
1021 /*****************************************************************************
1022 redraw_cursor_in_window
1024 For the given window W, redraw the cursor if it is contained within
1026 ****************************************************************************/
1028 redraw_cursor_in_window (struct window *w, int run_end_begin_meths)
1030 struct frame *f = XFRAME (w->frame);
1031 struct device *d = XDEVICE (f->device);
1033 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
1034 struct display_line *dl;
1035 struct display_block *db;
1038 int x = w->last_point_x[CURRENT_DISP];
1039 int y = w->last_point_y[CURRENT_DISP];
1041 if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
1042 !echo_area_active (f) && minibuf_level == 0)
1044 MAYBE_DEVMETH (d, set_final_cursor_coords, (f, w->pixel_top, 0));
1047 if (y < 0 || y >= Dynarr_length (dla))
1050 if (MINI_WINDOW_P (w) && f != device_selected_frame (d) &&
1051 !is_surrogate_for_selected_frame (f))
1054 dl = Dynarr_atp (dla, y);
1055 db = get_display_block_from_line (dl, TEXT);
1057 if (x < 0 || x >= Dynarr_length (db->runes))
1060 rb = Dynarr_atp (db->runes, x);
1062 /* Don't call the output routine if the block isn't actually the
1064 if (rb->cursor_type == CURSOR_ON)
1066 MAYBE_DEVMETH (d, set_final_cursor_coords,
1067 (f, dl->ypos - 1, rb->xpos));
1069 if (run_end_begin_meths)
1070 DEVMETH (d, output_begin, (d));
1072 output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width);
1074 if (run_end_begin_meths)
1075 DEVMETH (d, output_end, (d));
1079 /*****************************************************************************
1080 redisplay_redraw_cursor
1082 For the given frame F, redraw the cursor on the selected window.
1083 This is used to update the cursor after focus changes.
1084 ****************************************************************************/
1086 redisplay_redraw_cursor (struct frame *f, int run_end_begin_meths)
1090 if (!cursor_in_echo_area)
1091 window = FRAME_SELECTED_WINDOW (f);
1092 else if (FRAME_HAS_MINIBUF_P (f))
1093 window = FRAME_MINIBUF_WINDOW (f);
1097 redraw_cursor_in_window (XWINDOW (window), run_end_begin_meths);
1100 /****************************************************************************
1101 redisplay_output_display_block
1103 Given a display line, a block number for that start line, output all
1104 runes between start and end in the specified display block.
1105 ****************************************************************************/
1107 redisplay_output_display_block (struct window *w, struct display_line *dl, int block,
1108 int start, int end, int start_pixpos, int cursor_start,
1109 int cursor_width, int cursor_height)
1111 struct frame *f = XFRAME (w->frame);
1112 struct device *d = XDEVICE (f->device);
1113 /* Temporarily disabled until generalization is done. */
1115 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
1116 rune_dynarr *rba = db->runes;
1119 rb = Dynarr_atp (rba, start);
1122 /* Nothing to do so don't do anything. */
1125 xpos = max (start_pixpos, rb->xpos);
1128 end = Dynarr_length (rba);
1130 rb = Dynarr_atp (rba, end - 1);
1131 width = rb->xpos + rb->width - xpos;
1133 /* now actually output the block. */
1134 DEVMETH (d, output_display_block, (w, dl, block, start,
1136 cursor_start, cursor_width,
1140 /****************************************************************************
1141 redisplay_unmap_subwindows
1143 Remove subwindows from the area in the box defined by the given
1145 ****************************************************************************/
1146 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height,
1147 Lisp_Object ignored_window)
1151 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
1153 struct subwindow_cachel *cachel =
1154 Dynarr_atp (f->subwindow_cachels, elt);
1156 if (cachel->being_displayed
1158 cachel->x + cachel->width > x && cachel->x < x + width
1160 cachel->y + cachel->height > y && cachel->y < y + height
1162 !EQ (cachel->subwindow, ignored_window))
1164 unmap_subwindow (cachel->subwindow);
1169 /****************************************************************************
1170 redisplay_unmap_subwindows_maybe
1172 Potentially subwindows from the area in the box defined by the given
1174 ****************************************************************************/
1175 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height)
1177 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1179 redisplay_unmap_subwindows (f, x, y, width, height, Qnil);
1183 static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width,
1184 int height, Lisp_Object subwindow)
1186 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1188 redisplay_unmap_subwindows (f, x, y, width, height, subwindow);
1192 /****************************************************************************
1193 redisplay_output_subwindow
1195 output a subwindow. This code borrows heavily from the pixmap stuff,
1196 although is much simpler not needing to account for partial
1197 pixmaps, backgrounds etc.
1198 ****************************************************************************/
1200 redisplay_output_subwindow (struct window *w,
1201 Lisp_Object image_instance,
1202 struct display_box* db, struct display_glyph_area* dga,
1203 face_index findex, int cursor_start, int cursor_width,
1206 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1208 struct display_glyph_area sdga;
1210 dga->height = IMAGE_INSTANCE_HEIGHT (p);
1211 dga->width = IMAGE_INSTANCE_WIDTH (p);
1213 /* The first thing we are going to do is update the display
1214 characteristics of the subwindow. This also clears the dirty
1215 flags as a side effect. */
1216 update_subwindow (image_instance);
1218 /* This makes the glyph area fit into the display area. */
1219 if (!redisplay_normalize_glyph_area (db, dga))
1222 XSETWINDOW (window, w);
1224 /* Clear the area the subwindow is going into. */
1225 redisplay_clear_clipped_region (window, findex,
1226 db, dga, 0, image_instance);
1228 /* This shrinks the display box to exactly enclose the glyph
1230 redisplay_normalize_display_box (db, dga);
1232 /* if we can't view the whole window we can't view any of it. We
1233 have to be careful here since we may be being asked to display
1234 part of a subwindow, the rest of which is on-screen as well. We
1235 need to allow this case and map the entire subwindow. We also
1236 need to be careful since the subwindow could be outside the
1237 window in the gutter or modeline - we also need to allow these
1239 sdga.xoffset = -dga->xoffset;
1240 sdga.yoffset = -dga->yoffset;
1241 sdga.height = IMAGE_INSTANCE_HEIGHT (p);
1242 sdga.width = IMAGE_INSTANCE_WIDTH (p);
1244 if (redisplay_display_boxes_in_window_p (w, db, &sdga) < 0)
1246 map_subwindow (image_instance, db->xpos, db->ypos, dga);
1250 sdga.xoffset = sdga.yoffset = 0;
1251 map_subwindow (image_instance, db->xpos - dga->xoffset,
1252 db->ypos - dga->yoffset, &sdga);
1256 /****************************************************************************
1257 redisplay_output_layout
1259 Output a widget hierarchy. This can safely call itself recursively.
1261 The complexity of outputting layouts is deciding whether to do it or
1262 not. Consider a layout enclosing some text, the text changes and is
1263 marked as dirty, but the enclosing layout has not been marked as
1264 dirty so no updates occur and the text will potentially be truncated.
1265 Alternatively we hold a back pointer in the image instance to the
1266 parent and mark the parent as dirty. But the layout code assumes that
1267 if the layout is dirty then the whole layout should be redisplayed,
1268 so we then get lots of flashing even though only the text has changed
1269 size. Of course if the text shrinks in size then we do actually need
1270 to redisplay the layout to repaint the exposed area. So what happens
1271 if we make a non-structural change like changing color? Either we
1272 redisplay everything, or we redisplay nothing. These are exactly the
1273 issues lwlib has to grapple with. We really need to know what has
1274 actually changed and make a layout decision based on that. We also
1275 really need to know what has changed so that we can only make the
1276 neccessary changes in update_subwindow. This has all now been
1277 implemented, Viva la revolution!
1278 ****************************************************************************/
1280 redisplay_output_layout (struct window *w,
1281 Lisp_Object image_instance,
1282 struct display_box* db, struct display_glyph_area* dga,
1283 face_index findex, int cursor_start, int cursor_width,
1286 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1287 Lisp_Object window, rest;
1288 Emchar_dynarr *buf = Dynarr_new (Emchar);
1289 struct frame *f = XFRAME (w->frame);
1290 struct device *d = XDEVICE (f->device);
1291 int layout_height, layout_width;
1293 XSETWINDOW (window, w);
1295 layout_height = glyph_height (image_instance, window);
1296 layout_width = glyph_width (image_instance, window);
1298 dga->height = layout_height;
1299 dga->width = layout_width;
1300 #ifdef DEBUG_WIDGET_OUTPUT
1301 printf ("outputing layout glyph %p\n", p);
1303 /* This makes the glyph area fit into the display area. */
1304 if (!redisplay_normalize_glyph_area (db, dga))
1307 /* Highly dodgy optimization. We want to only output the whole
1308 layout if we really have to. */
1309 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p)
1310 || IMAGE_INSTANCE_LAYOUT_CHANGED (p)
1311 || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
1312 || IMAGE_INSTANCE_SIZE_CHANGED (p)
1313 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
1315 /* First clear the area we are drawing into. This is the easiest
1316 thing to do since we have many gaps that we have to make sure are
1318 redisplay_clear_clipped_region (window, findex, db, dga, 1, Qnil);
1320 /* Output a border if required */
1321 if (!NILP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1324 enum edge_style style;
1325 int ypos = db->ypos;
1326 int height = dga->height;
1328 if (dga->xoffset >= 0)
1330 if (dga->width - dga->xoffset == layout_width)
1331 edges |= EDGE_RIGHT;
1332 if (dga->yoffset >= 0)
1334 if (dga->height - dga->yoffset == layout_height)
1335 edges |= EDGE_BOTTOM;
1337 if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in))
1338 style = EDGE_ETCHED_IN;
1339 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out))
1340 style = EDGE_ETCHED_OUT;
1341 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qbevel_in))
1342 style = EDGE_BEVEL_IN;
1343 else if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1345 style = EDGE_ETCHED_IN;
1346 if (edges & EDGE_TOP)
1348 ypos += XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1349 height -= XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1353 style = EDGE_BEVEL_OUT;
1355 MAYBE_DEVMETH (d, bevel_area,
1356 (w, findex, db->xpos,
1358 dga->width, height, 2, edges, style));
1362 /* This shrinks the display box to exactly enclose the glyph
1364 redisplay_normalize_display_box (db, dga);
1366 /* Flip through the widgets in the layout displaying as necessary */
1367 LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p))
1369 Lisp_Object child = XCAR (rest);
1371 struct display_box cdb;
1372 /* For losing HP-UX */
1373 cdb.xpos = db->xpos;
1374 cdb.ypos = db->ypos;
1375 cdb.width = db->width;
1376 cdb.height = db->height;
1378 /* First determine if the image is visible at all */
1379 if (IMAGE_INSTANCEP (child))
1381 Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child);
1383 /* The enclosing layout offsets are +ve at this point */
1384 struct display_glyph_area cdga;
1385 cdga.xoffset = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset;
1386 cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset;
1387 cdga.width = glyph_width (child, window);
1388 cdga.height = glyph_height (child, window);
1390 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) =
1391 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p);
1393 /* Although normalization is done by the output routines
1394 we have to do it here so that they don't try and
1395 clear all of db. This is true below also. */
1396 if (redisplay_normalize_glyph_area (&cdb, &cdga))
1398 redisplay_normalize_display_box (&cdb, &cdga);
1399 /* Since the display boxes will now be totally in the
1400 window if they are visible at all we can now check this easily. */
1401 if (cdb.xpos < db->xpos || cdb.ypos < db->ypos
1402 || cdb.xpos + cdb.width > db->xpos + db->width
1403 || cdb.ypos + cdb.height > db->ypos + db->height)
1405 /* We have to invert the offset here as normalization
1406 will have made them positive which the output
1407 routines will treat as a truly +ve offset. */
1408 cdga.xoffset = -cdga.xoffset;
1409 cdga.yoffset = -cdga.yoffset;
1411 switch (IMAGE_INSTANCE_TYPE (childii))
1415 /* #### This is well hacked and could use some
1417 if (redisplay_normalize_glyph_area (&cdb, &cdga)
1419 (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
1420 IMAGE_INSTANCE_DIRTYP (childii)))
1422 struct display_line dl; /* this is fake */
1423 Lisp_Object string =
1424 IMAGE_INSTANCE_TEXT_STRING (childii);
1425 unsigned char charsets[NUM_LEADING_BYTES];
1426 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
1428 find_charsets_in_bufbyte_string (charsets,
1429 XSTRING_DATA (string),
1430 XSTRING_LENGTH (string));
1431 ensure_face_cachel_complete (cachel, window, charsets);
1433 convert_bufbyte_string_into_emchar_dynarr
1434 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
1436 redisplay_normalize_display_box (&cdb, &cdga);
1437 /* Offsets are now +ve again so be careful
1438 when fixing up the display line. */
1440 /* Munge boxes into display lines. */
1441 dl.ypos = (cdb.ypos - cdga.yoffset)
1442 + glyph_ascent (child, window);
1443 dl.ascent = glyph_ascent (child, window);
1444 dl.descent = glyph_descent (child, window);
1445 dl.top_clip = cdga.yoffset;
1446 dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height);
1447 /* output_string doesn't understand offsets in
1448 the same way as other routines - we have to
1449 add the offset to the width so that we
1450 output the full string. */
1451 MAYBE_DEVMETH (d, output_string, (w, &dl, buf, cdb.xpos,
1452 cdga.xoffset, cdb.xpos,
1453 cdga.width + cdga.xoffset,
1454 findex, 0, 0, 0, 0));
1460 case IMAGE_MONO_PIXMAP:
1461 case IMAGE_COLOR_PIXMAP:
1462 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii)
1463 || IMAGE_INSTANCE_DIRTYP (childii))
1464 redisplay_output_pixmap (w, child, &cdb, &cdga, findex,
1469 case IMAGE_SUBWINDOW:
1470 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
1471 IMAGE_INSTANCE_DIRTYP (childii))
1472 redisplay_output_subwindow (w, child, &cdb, &cdga, findex,
1477 redisplay_output_layout (w, child, &cdb, &cdga, findex,
1482 /* nothing is as nothing does */
1490 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 0;
1494 /* Update any display properties. I'm not sure whether this actually
1495 does anything for layouts except clear the changed flags. */
1496 update_subwindow (image_instance);
1501 /****************************************************************************
1502 redisplay_output_pixmap
1506 ****************************************************************************/
1508 redisplay_output_pixmap (struct window *w,
1509 Lisp_Object image_instance,
1510 struct display_box* db, struct display_glyph_area* dga,
1511 face_index findex, int cursor_start, int cursor_width,
1512 int cursor_height, int offset_bitmap)
1514 struct frame *f = XFRAME (w->frame);
1515 struct device *d = XDEVICE (f->device);
1516 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1518 XSETWINDOW (window, w);
1520 dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
1521 dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
1523 /* This makes the glyph area fit into the display area. */
1524 if (!redisplay_normalize_glyph_area (db, dga))
1527 /* Clear the area the pixmap is going into. The pixmap itself will
1528 always take care of the full width. We don't want to clear where
1529 it is going to go in order to avoid flicker. So, all we have to
1530 take care of is any area above or below the pixmap. If the pixmap
1531 has a mask in which case we have to clear the whole damn thing
1532 since we can't yet clear just the area not included in the
1536 redisplay_clear_clipped_region (window, findex,
1538 (int)IMAGE_INSTANCE_PIXMAP_MASK (p),
1541 /* This shrinks the display box to exactly enclose the glyph
1543 redisplay_normalize_display_box (db, dga);
1545 assert (db->xpos >= 0 && db->ypos >= 0);
1547 MAYBE_DEVMETH (d, output_pixmap, (w, image_instance,
1549 findex, cursor_start,
1550 cursor_width, cursor_height,
1554 /****************************************************************************
1555 redisplay_clear_region
1557 Clear the area in the box defined by the given parameters using the
1558 given face. This has been generalised so that subwindows can be
1559 coped with effectively.
1560 ****************************************************************************/
1562 redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y,
1563 int width, int height)
1565 struct window *w = NULL;
1566 struct frame *f = NULL;
1568 Lisp_Object background_pixmap = Qunbound;
1569 Lisp_Object fcolor = Qnil, bcolor = Qnil;
1571 if (!width || !height)
1574 if (WINDOWP (locale))
1576 w = XWINDOW (locale);
1577 f = XFRAME (w->frame);
1579 else if (FRAMEP (locale))
1582 f = XFRAME (locale);
1587 d = XDEVICE (f->device);
1589 /* if we have subwindows in the region we have to unmap them */
1590 redisplay_unmap_subwindows_maybe (f, x, y, width, height);
1592 /* #### This isn't quite right for when this function is called
1593 from the toolbar code. */
1595 /* Don't use a backing pixmap in the border area */
1596 if (x >= FRAME_LEFT_BORDER_END (f)
1597 && x < FRAME_RIGHT_BORDER_START (f)
1598 && y >= FRAME_TOP_BORDER_END (f)
1599 && y < FRAME_BOTTOM_BORDER_START (f))
1605 temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
1607 if (IMAGE_INSTANCEP (temp)
1608 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1610 /* #### maybe we could implement such that a string
1611 can be a background pixmap? */
1612 background_pixmap = temp;
1617 temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
1619 if (IMAGE_INSTANCEP (temp)
1620 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1622 background_pixmap = temp;
1627 if (!UNBOUNDP (background_pixmap) &&
1628 XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
1632 fcolor = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1633 bcolor = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1637 fcolor = FACE_FOREGROUND (Vdefault_face, locale);
1638 bcolor = FACE_BACKGROUND (Vdefault_face, locale);
1644 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
1645 FACE_BACKGROUND (Vdefault_face, locale));
1649 if (UNBOUNDP (background_pixmap))
1650 background_pixmap = Qnil;
1652 DEVMETH (d, clear_region,
1653 (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1656 /****************************************************************************
1657 redisplay_clear_clipped_region
1659 Clear the area in the dest display_box not covered by the src
1660 display_glyph_area using the given face. This is a common occurance
1661 for images shorter than the display line. Clipping can be played
1662 around with by altering these. glyphsrc should be normalized.
1663 ****************************************************************************/
1665 redisplay_clear_clipped_region (Lisp_Object window, face_index findex,
1666 struct display_box* dest, struct display_glyph_area* glyphsrc,
1667 int fullheight_p, Lisp_Object ignored_subwindow)
1669 /* assume dest->xpos >= 0 */
1671 struct frame* f = XFRAME (XWINDOW (window)->frame);
1673 if (glyphsrc->xoffset > 0)
1675 clear_x = dest->xpos + glyphsrc->xoffset;
1679 clear_x = dest->xpos;
1682 /* If we need the whole height cleared then just do it. */
1685 redisplay_clear_region (window, findex, clear_x, dest->ypos,
1686 glyphsrc->width, dest->height);
1690 int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0);
1692 /* We need to make sure that subwindows are unmapped from the
1694 redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos,
1695 glyphsrc->width, dest->height,
1697 /* first the top box */
1700 redisplay_clear_region (window, findex, clear_x, dest->ypos,
1701 glyphsrc->width, yoffset);
1704 /* Then the bottom box */
1705 if (yoffset + glyphsrc->height < dest->height)
1707 redisplay_clear_region (window, findex, clear_x,
1708 dest->ypos + yoffset + glyphsrc->height,
1710 dest->height - (yoffset + glyphsrc->height));
1716 /*****************************************************************************
1717 redisplay_normalize_glyph_area
1718 redisplay_normalize_display_box
1720 Calculate the visible box for displaying src in dest.
1721 ****************************************************************************/
1723 redisplay_normalize_glyph_area (struct display_box* dest,
1724 struct display_glyph_area* glyphsrc)
1726 if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width
1728 dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height
1730 -glyphsrc->xoffset >= glyphsrc->width
1732 -glyphsrc->yoffset >= glyphsrc->height)
1734 /* It's all clipped out */
1738 /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */
1739 if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width)
1741 if (glyphsrc->xoffset > 0)
1742 glyphsrc->width = dest->width - glyphsrc->xoffset;
1744 glyphsrc->width = dest->width;
1747 if (glyphsrc->xoffset < 0)
1748 glyphsrc->width += glyphsrc->xoffset;
1750 /* Vertical offsets. This works because yoffset can be -ve as well as +ve */
1751 if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height)
1753 if (glyphsrc->yoffset > 0)
1754 glyphsrc->height = dest->height - glyphsrc->yoffset;
1756 glyphsrc->height = dest->height;
1759 if (glyphsrc->yoffset < 0)
1760 glyphsrc->height += glyphsrc->yoffset;
1766 redisplay_normalize_display_box (struct display_box* dest,
1767 struct display_glyph_area* glyphsrc)
1769 /* Adjust the destination area. At the end of this the destination
1770 area will exactly enclose the glyph area. The only remaining
1771 adjustment will be offsets into the glyph area. */
1773 /* Horizontal adjustment. */
1774 if (glyphsrc->xoffset > 0)
1776 dest->xpos += glyphsrc->xoffset;
1777 dest->width -= glyphsrc->xoffset;
1778 glyphsrc->xoffset = 0;
1781 glyphsrc->xoffset = -glyphsrc->xoffset;
1783 if (glyphsrc->width < dest->width)
1784 dest->width = glyphsrc->width;
1786 /* Vertical adjustment. */
1787 if (glyphsrc->yoffset > 0)
1789 dest->ypos += glyphsrc->yoffset;
1790 dest->height -= glyphsrc->yoffset;
1791 glyphsrc->yoffset = 0;
1794 glyphsrc->yoffset = -glyphsrc->yoffset;
1796 if (glyphsrc->height < dest->height)
1797 dest->height = glyphsrc->height;
1800 /*****************************************************************************
1801 redisplay_display_boxes_in_window_p
1803 Determine whether the require display_glyph_area is completely inside
1804 the window. 0 means the display_box is not in the window. 1 means the
1805 display_box and the display_glyph_area are in the window. -1 means
1806 the display_box is in the window but the display_glyph_area is not.
1807 ****************************************************************************/
1809 redisplay_display_boxes_in_window_p (struct window* w,
1810 struct display_box* db,
1811 struct display_glyph_area* dga)
1813 int left = WINDOW_TEXT_LEFT (w);
1814 int right = WINDOW_TEXT_RIGHT (w);
1815 int top = WINDOW_TEXT_TOP (w);
1816 int bottom = WINDOW_TEXT_BOTTOM (w);
1818 if (db->xpos < left || db->ypos < top
1819 || db->xpos + db->width > right
1820 || db->ypos + db->height > bottom)
1821 /* We are not displaying in a window at all */
1824 if (db->xpos + dga->xoffset >= left
1826 db->ypos + dga->yoffset >= top
1828 db->xpos + dga->xoffset + dga->width <= right
1830 db->ypos + dga->yoffset + dga->height <= bottom)
1836 /*****************************************************************************
1837 redisplay_calculate_display_boxes
1839 Convert from rune/display_line co-ordinates to display_box
1841 ****************************************************************************/
1843 redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
1844 int xoffset, int start_pixpos, int width,
1845 struct display_box* dest,
1846 struct display_glyph_area* src)
1849 dest->ypos = DISPLAY_LINE_YPOS (dl);
1850 dest->width = width;
1851 dest->height = DISPLAY_LINE_HEIGHT (dl);
1853 src->xoffset = -xoffset;
1854 src->yoffset = -dl->top_clip;
1858 if (start_pixpos >=0 && start_pixpos > xpos)
1860 /* Oops, we're asking for a start outside of the displayable
1862 if (start_pixpos > xpos + width)
1864 dest->xpos = start_pixpos;
1865 dest->width -= (start_pixpos - xpos);
1866 /* Offsets are -ve when we want to clip pixels off the displayed
1868 src->xoffset -= (start_pixpos - xpos);
1874 /*****************************************************************************
1875 redisplay_clear_top_of_window
1877 If window is topmost, clear the internal border above it.
1878 ****************************************************************************/
1880 redisplay_clear_top_of_window (struct window *w)
1883 XSETWINDOW (window, w);
1885 if (!NILP (Fwindow_highest_p (window)))
1887 struct frame *f = XFRAME (w->frame);
1888 int x, y, width, height;
1891 width = w->pixel_width;
1893 if (window_is_leftmost (w))
1895 x -= FRAME_BORDER_WIDTH (f);
1896 width += FRAME_BORDER_WIDTH (f);
1898 if (window_is_rightmost (w))
1899 width += FRAME_BORDER_WIDTH (f);
1901 y = FRAME_TOP_BORDER_START (f) - 1;
1902 height = FRAME_BORDER_HEIGHT (f) + 1;
1904 redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
1908 /*****************************************************************************
1909 redisplay_clear_to_window_end
1911 Clear the area between ypos1 and ypos2. Each margin area and the
1912 text area is handled separately since they may each have their own
1914 ****************************************************************************/
1916 redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1918 struct frame *f = XFRAME (w->frame);
1919 struct device *d = XDEVICE (f->device);
1921 if (HAS_DEVMETH_P (d, clear_to_window_end))
1922 DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1925 int height = ypos2 - ypos1;
1930 int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/
1931 layout_bounds bounds;
1933 bounds = calculate_display_line_boundaries (w, bflag);
1934 XSETWINDOW (window, w);
1936 if (window_is_leftmost (w))
1937 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1938 ypos1, FRAME_BORDER_WIDTH (f), height);
1940 if (bounds.left_in - bounds.left_out > 0)
1941 redisplay_clear_region (window,
1942 get_builtin_face_cache_index (w, Vleft_margin_face),
1943 bounds.left_out, ypos1,
1944 bounds.left_in - bounds.left_out, height);
1946 if (bounds.right_in - bounds.left_in > 0)
1947 redisplay_clear_region (window,
1949 bounds.left_in, ypos1,
1950 bounds.right_in - bounds.left_in, height);
1952 if (bounds.right_out - bounds.right_in > 0)
1953 redisplay_clear_region (window,
1954 get_builtin_face_cache_index (w, Vright_margin_face),
1955 bounds.right_in, ypos1,
1956 bounds.right_out - bounds.right_in, height);
1958 if (window_is_rightmost (w))
1959 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1960 ypos1, FRAME_BORDER_WIDTH (f), height);
1965 /*****************************************************************************
1966 redisplay_clear_bottom_of_window
1968 Clear window from right below the last display line to right above
1969 the modeline. The calling function can limit the area actually
1970 erased by setting min_start and/or max_end to positive values.
1971 ****************************************************************************/
1973 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1974 int min_start, int max_end)
1976 struct frame *f = XFRAME (w->frame);
1978 int ddla_len = Dynarr_length (ddla);
1980 ypos2 = WINDOW_TEXT_BOTTOM (w);
1981 #ifdef HAVE_SCROLLBARS
1982 /* This adjustment is to catch the intersection of any scrollbars. */
1983 if (f->windows_structure_changed && NILP (w->scrollbar_on_top_p))
1984 ypos2 += window_scrollbar_height (w);
1989 if (ddla_len == 1 && Dynarr_atp (ddla, 0)->modeline)
1991 ypos1 = WINDOW_TEXT_TOP (w);
1992 #ifdef HAVE_SCROLLBARS
1993 /* This adjustment is to catch the intersection of any scrollbars. */
1994 if (f->windows_structure_changed && !NILP (w->scrollbar_on_top_p))
1995 ypos1 -= window_scrollbar_height (w);
2000 struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1);
2001 ypos1 = dl->ypos + dl->descent - dl->clip;
2005 ypos1 = WINDOW_TEXT_TOP (w);
2007 /* #### See if this can be made conditional on the frame
2009 if (MINI_WINDOW_P (w))
2010 ypos2 += FRAME_BORDER_HEIGHT (f);
2012 if (min_start >= 0 && ypos1 < min_start)
2014 if (max_end >= 0 && ypos2 > max_end)
2020 redisplay_clear_to_window_end (w, ypos1, ypos2);
2023 /*****************************************************************************
2024 redisplay_update_line
2026 This is used during incremental updates to update a single line and
2027 correct the offsets on all lines below it. At the moment
2028 update_values is false if we are only updating the modeline.
2029 ****************************************************************************/
2031 redisplay_update_line (struct window *w, int first_line, int last_line,
2034 struct frame *f = XFRAME (w->frame);
2035 struct device *d = XDEVICE (f->device);
2037 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2038 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2040 DEVMETH (d, output_begin, (d));
2042 while (first_line <= last_line)
2044 Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos -
2045 Dynarr_atp (cdla, first_line)->bufpos);
2046 Charcount new_len = (Dynarr_atp (ddla, first_line)->end_bufpos -
2047 Dynarr_atp (ddla, first_line)->bufpos);
2049 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
2051 /* Output the changes. */
2052 output_display_line (w, cdla, ddla, first_line, -1, -1);
2054 /* Update the offsets. */
2057 int cur_line = first_line + 1;
2058 while (cur_line < Dynarr_length (cdla))
2060 Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len);
2061 Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len);
2066 /* Update the window_end_pos and other settings. */
2069 w->window_end_pos[CURRENT_DISP] -= (new_len - old_len);
2071 if (Dynarr_atp (ddla, first_line)->cursor_elt != -1)
2073 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2074 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2081 /* Update the window max line length. We have to scan the entire
2082 set of display lines otherwise we might not detect if the max is
2083 supposed to shrink. */
2088 w->max_line_len = 0;
2089 while (line < Dynarr_length (ddla))
2091 struct display_line *dl = Dynarr_atp (ddla, line);
2094 w->max_line_len = max (dl->num_chars, w->max_line_len);
2100 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2101 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2102 Fset_marker (w->last_point[CURRENT_DISP],
2103 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2104 Fset_marker (w->last_start[CURRENT_DISP],
2105 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2107 /* We don't bother updating the vertical scrollbars here. This
2108 gives us a performance increase while having minimal loss of
2109 quality to the scrollbar slider size and position since when this
2110 function is called we know that the changes to the buffer were
2111 very localized. We have to update the horizontal scrollbars,
2112 though, because this routine could cause a change which has a
2113 larger impact on their sizing. */
2114 /* #### See if we can get away with only calling this if
2115 max_line_len is greater than the window_char_width. */
2116 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS)
2118 extern int stupid_vertical_scrollbar_drag_hack;
2120 update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack);
2121 stupid_vertical_scrollbar_drag_hack = 1;
2125 /* This has to be done after we've updated the values. We don't
2126 call output_end for tty frames. Redisplay will do this after all
2127 tty windows have been updated. This cuts down on cursor
2129 if (FRAME_TTY_P (f))
2130 redisplay_redraw_cursor (f, 0);
2132 DEVMETH (d, output_end, (d));
2135 /*****************************************************************************
2136 redisplay_output_window
2138 For the given window W, ensure that the current display lines are
2139 equal to the desired display lines, outputing changes as necessary.
2141 #### Fuck me. This just isn't going to cut it for tty's. The output
2142 decisions for them must be based on the contents of the entire frame
2143 because that is how the available output capabilities think. The
2144 solution is relatively simple. Create redisplay_output_frame. This
2145 will basically merge all of the separate window display structs into
2146 a single one for the frame. This combination structure will be able
2147 to be passed to the same output_display_line which works for windows
2148 on X frames and the right things will happen. It just takes time to
2150 ****************************************************************************/
2152 redisplay_output_window (struct window *w)
2154 struct frame *f = XFRAME (w->frame);
2155 struct device *d = XDEVICE (f->device);
2157 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2158 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2160 int cdla_len = Dynarr_length (cdla);
2161 int ddla_len = Dynarr_length (ddla);
2164 int need_to_clear_bottom = 0;
2165 int need_to_clear_start = -1;
2166 int need_to_clear_end = -1;
2168 /* Backgrounds may have changed or windows may have gone away
2169 leaving dividers lying around. */
2170 if (f->faces_changed
2171 || f->windows_structure_changed
2172 || w->shadow_thickness_changed)
2173 need_to_clear_bottom = 1;
2175 /* The first thing we do is determine if we are going to need to
2176 clear the bottom of the window. We only need to do this if the
2177 bottom of the current display lines is below the bottom of the
2178 desired display lines. Note that the number of lines is
2179 irrelevant. Only the position matters. We also clear to the
2180 bottom of the window if the modeline has shifted position. */
2181 /* #### We can't blindly not clear the bottom if f->clear is true
2182 since there might be a window-local background. However, for
2183 those cases where there isn't, clearing the end of the window in
2185 if (!need_to_clear_bottom)
2187 struct display_line *cdl, *ddl;
2189 /* If the modeline has changed position or size, clear the bottom
2191 if (!need_to_clear_bottom)
2196 cdl = Dynarr_atp (cdla, 0);
2198 ddl = Dynarr_atp (ddla, 0);
2201 need_to_clear_bottom = 1;
2202 else if ((!cdl->modeline && ddl->modeline)
2203 || (cdl->modeline && !ddl->modeline))
2204 need_to_clear_bottom = 1;
2205 else if (cdl->ypos != ddl->ypos ||
2206 cdl->ascent != ddl->ascent ||
2207 cdl->descent != ddl->descent ||
2208 cdl->clip != ddl->clip)
2209 need_to_clear_bottom = 1;
2211 /* #### This kludge is to make sure the modeline shadows get
2212 redrawn if the modeline position shifts. */
2213 if (need_to_clear_bottom)
2214 w->shadow_thickness_changed = 1;
2217 if (!need_to_clear_bottom)
2222 cdl = Dynarr_atp (cdla, cdla_len - 1);
2224 ddl = Dynarr_atp (ddla, ddla_len - 1);
2227 need_to_clear_bottom = 1;
2230 int cdl_bottom, ddl_bottom;
2232 cdl_bottom = cdl->ypos + cdl->descent;
2233 ddl_bottom = ddl->ypos + ddl->descent;
2235 if (cdl_bottom > ddl_bottom)
2237 need_to_clear_bottom = 1;
2238 need_to_clear_start = ddl_bottom;
2239 need_to_clear_end = cdl_bottom;
2245 /* Perform any output initialization. */
2246 DEVMETH (d, output_begin, (d));
2248 /* If the window's structure has changed clear the internal border
2249 above it if it is topmost (the function will check). */
2250 if (f->windows_structure_changed)
2251 redisplay_clear_top_of_window (w);
2253 /* Output each line. */
2254 for (line = 0; line < Dynarr_length (ddla); line++)
2256 output_display_line (w, cdla, ddla, line, -1, -1);
2259 /* If the number of display lines has shrunk, adjust. */
2260 if (cdla_len > ddla_len)
2262 Dynarr_length (cdla) = ddla_len;
2265 /* Output a vertical divider between windows, if necessary. */
2266 if (window_needs_vertical_divider (w)
2267 && (f->windows_structure_changed || f->clear))
2269 DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
2272 /* Clear the rest of the window, if necessary. */
2273 if (need_to_clear_bottom)
2275 redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start,
2279 w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP];
2280 Fset_marker (w->start[CURRENT_DISP],
2281 make_int (marker_position (w->start[DESIRED_DISP])),
2283 Fset_marker (w->pointm[CURRENT_DISP],
2284 make_int (marker_position (w->pointm[DESIRED_DISP])),
2286 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2287 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2288 Fset_marker (w->last_start[CURRENT_DISP],
2289 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2290 Fset_marker (w->last_point[CURRENT_DISP],
2291 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2292 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2293 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2294 w->shadow_thickness_changed = 0;
2296 set_window_display_buffer (w, XBUFFER (w->buffer));
2297 find_window_mirror (w)->truncate_win = window_truncation_on (w);
2299 /* Overkill on invalidating the cache. It is very bad for it to not
2300 get invalidated when it should be. */
2301 INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
2303 /* We don't call output_end for tty frames. Redisplay will do this
2304 after all tty windows have been updated. This cuts down on
2306 if (FRAME_TTY_P (f))
2307 redisplay_redraw_cursor (f, 0);
2309 DEVMETH (d, output_end, (d));
2311 #ifdef HAVE_SCROLLBARS
2312 update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);
2316 /*****************************************************************************
2319 Draw a 3d border around the modeline on window W.
2320 ****************************************************************************/
2322 bevel_modeline (struct window *w, struct display_line *dl)
2324 struct frame *f = XFRAME (w->frame);
2325 struct device *d = XDEVICE (f->device);
2326 int x, y, width, height;
2327 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
2328 enum edge_style style;
2330 x = WINDOW_MODELINE_LEFT (w);
2331 width = WINDOW_MODELINE_RIGHT (w) - x;
2332 y = dl->ypos - dl->ascent - shadow_thickness;
2333 height = dl->ascent + dl->descent + 2 * shadow_thickness;
2335 if (XINT (w->modeline_shadow_thickness) < 0)
2337 style = EDGE_BEVEL_IN;
2341 style = EDGE_BEVEL_OUT;
2344 MAYBE_DEVMETH (d, bevel_area,
2345 (w, MODELINE_INDEX, x, y, width, height, shadow_thickness,