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 ((XFRAME (w->frame)->glyphs_changed &&
237 XGLYPH_DIRTYP (crb->object.dglyph.glyph)) ||
238 crb->findex != drb->findex))
240 /* We need some way of telling redisplay_output_layout () that the
241 only reason we are outputting it is because something has
242 changed internally. That way we can optimize whether we need
243 to clear the layout first and also only output the components
244 that have changed. The image_instance dirty flag and
245 display_hash are no good to us because these will invariably
246 have been set anyway if the layout has changed. So it looks
247 like we need yet another change flag that we can set here and
248 then clear in redisplay_output_layout (). */
249 Lisp_Object window, image;
250 Lisp_Image_Instance* ii;
251 XSETWINDOW (window, w);
252 image = glyph_image_instance (crb->object.dglyph.glyph,
253 window, ERROR_ME_NOT, 1);
254 ii = XIMAGE_INSTANCE (image);
256 if (TEXT_IMAGE_INSTANCEP (image) &&
257 (crb->findex != drb->findex ||
258 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
261 /* It is quite common of the two glyphs to be EQ since in many
262 cases they will actually be the same object. This does not
263 mean, however, that nothing has changed. We therefore need to
264 check the current hash of the glyph against the last recorded
265 display hash. See update_subwindow (). */
266 if (IMAGE_INSTANCE_DISPLAY_HASH (ii) == 0 ||
267 IMAGE_INSTANCE_DISPLAY_HASH (ii) !=
268 internal_hash (image, IMAGE_INSTANCE_HASH_DEPTH) ||
269 crb->findex != drb->findex ||
270 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
272 /* We now now we are going to re-output the glyph, but since
273 this is for some internal reason not related to geometry
274 changes, send a hint to the output routines that they can
275 take some short cuts. This is most useful for
276 layouts. This flag should get reset by the output
279 #### It is possible for us to get here when the
280 face_cachel is dirty. I do not know what the implications
282 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (ii) = 1;
288 /* We now do this last so that glyph checks can do their own thing
289 for face changes. Face changes quite often happen when we are
290 trying to output something in the gutter, this would normally
291 lead to a lot of flashing. The indices can quite often be
292 different and yet the faces are the same, we do not want to
293 re-output in this instance. */
294 else if (crb->findex != drb->findex ||
295 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
301 /*****************************************************************************
302 get_next_display_block
304 Return the next display starting at or overlapping START_POS. Return
305 the start of the next region in NEXT_START.
306 ****************************************************************************/
308 get_next_display_block (layout_bounds bounds, display_block_dynarr *dba,
309 int start_pos, int *next_start)
311 int next_display_block = NO_BLOCK;
315 /* If we don't find a display block covering or starting at
316 start_pos, then we return the starting point of the next display
317 block or the next division boundary, whichever is closer to
321 if (start_pos >= bounds.left_out && start_pos < bounds.left_in)
322 *next_start = bounds.left_in;
323 else if (start_pos < bounds.left_white)
324 *next_start = bounds.left_white;
325 else if (start_pos < bounds.right_white)
326 *next_start = bounds.right_white;
327 else if (start_pos < bounds.right_in)
328 *next_start = bounds.right_in;
329 else if (start_pos <= bounds.right_out)
330 *next_start = bounds.right_out;
335 for (block = 0; block < Dynarr_length (dba); block++)
337 struct display_block *db = Dynarr_atp (dba, block);
339 if (db->start_pos <= start_pos && db->end_pos > start_pos)
341 if ((int) db->type > priority)
344 next_display_block = block;
346 *next_start = db->end_pos;
349 else if (next_start && db->start_pos > start_pos)
351 if (db->start_pos < *next_start)
352 *next_start = db->start_pos;
356 return next_display_block;
359 /*****************************************************************************
360 get_cursor_size_and_location
362 Return the information defining the pixel location of the cursor.
363 ****************************************************************************/
365 get_cursor_size_and_location (struct window *w, struct display_block *db,
367 int *cursor_start, int *cursor_width,
372 int defheight, defwidth;
374 if (Dynarr_length (db->runes) <= cursor_location)
377 XSETWINDOW (window, w);
379 rb = Dynarr_atp (db->runes, cursor_location);
380 *cursor_start = rb->xpos;
382 default_face_height_and_width (window, &defheight, &defwidth);
383 *cursor_height = defheight;
385 if (rb->type == RUNE_BLANK)
386 *cursor_width = defwidth;
388 *cursor_width = rb->width;
391 /*****************************************************************************
392 compare_display_blocks
394 Given two display blocks, output only those areas where they differ.
395 ****************************************************************************/
397 compare_display_blocks (struct window *w, struct display_line *cdl,
398 struct display_line *ddl, int c_block, int d_block,
399 int start_pixpos, int cursor_start, int cursor_width,
402 struct frame *f = XFRAME (w->frame);
403 struct display_block *cdb, *ddb;
409 cdb = Dynarr_atp (cdl->display_blocks, c_block);
410 ddb = Dynarr_atp (ddl->display_blocks, d_block);
412 assert (cdb->type == ddb->type);
415 stop_pos = min (Dynarr_length (cdb->runes), Dynarr_length (ddb->runes));
418 (!Dynarr_length (ddb->runes)
420 : (Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->xpos +
421 Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->width));
423 /* If the new block type is not text and the cursor status is
424 changing and it overlaps the position of this block then force a
425 full redraw of the block in order to make sure that the cursor is
427 if (ddb->type != TEXT
429 /* I'm not sure exactly what this code wants to do, but it's
430 * not right--it doesn't update when cursor_elt changes from, e.g.,
431 * 0 to 8, and the new or old cursor loc overlaps this block.
432 * I've replaced it with the more conservative test below.
433 * -dkindred@cs.cmu.edu 23-Mar-1997 */
434 && ((cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
435 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1))
436 && (ddl->cursor_elt == -1 ||
439 && (cursor_start + cursor_width) >= start_pixpos
440 && cursor_start <= block_end))
442 && (cdl->cursor_elt != ddl->cursor_elt)
447 if (f->windows_structure_changed ||
448 /* #### Why is this so? We have face cachels so that we don't
449 have to recalculate all the display blocks when faces
450 change. I have fixed this for glyphs and am inclined to think
451 that faces should "Just Work", but I'm not feeling brave
452 today. Maybe its because the face cachels represent merged
453 faces rather than simply instantiations in a particular
456 cdl->ypos != ddl->ypos ||
457 cdl->ascent != ddl->ascent ||
458 cdl->descent != ddl->descent ||
459 cdl->clip != ddl->clip ||
469 while (start_pos < 0 && elt < stop_pos)
471 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
472 Dynarr_atp (ddb->runes, elt)))
482 /* If nothing has changed in the area where the blocks overlap, but
483 there are new blocks in the desired block, then adjust the start
484 point accordingly. */
485 if (elt == stop_pos && stop_pos < Dynarr_length (ddb->runes))
486 start_pos = stop_pos;
491 if ((Dynarr_length (ddb->runes) != Dynarr_length (cdb->runes))
494 stop_pos = Dynarr_length (ddb->runes);
498 /* If the lines have the same number of runes and we are not
499 forcing a full redraw because the display line has
500 changed position then we try and optimize how much of the
501 line we actually redraw by scanning backwards from the
502 end for the first changed rune. This optimization is
503 almost always triggered by face changes. */
505 int elt = Dynarr_length (ddb->runes) - 1;
507 while (elt > start_pos)
509 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
510 Dynarr_atp (ddb->runes, elt)))
518 redisplay_output_display_block (w, ddl, d_block, start_pos,
519 stop_pos, start_pixpos,
520 cursor_start, cursor_width,
528 /*****************************************************************************
531 Clear the lefthand outside border.
532 ****************************************************************************/
534 clear_left_border (struct window *w, int y, int height)
536 struct frame *f = XFRAME (w->frame);
539 XSETWINDOW (window, w);
540 redisplay_clear_region (window, DEFAULT_INDEX,
541 FRAME_LEFT_BORDER_START (f), y,
542 FRAME_BORDER_WIDTH (f), height);
545 /*****************************************************************************
548 Clear the righthand outside border.
549 ****************************************************************************/
551 clear_right_border (struct window *w, int y, int height)
553 struct frame *f = XFRAME (w->frame);
556 XSETWINDOW (window, w);
557 redisplay_clear_region (window, DEFAULT_INDEX,
558 FRAME_RIGHT_BORDER_START (f),
559 y, FRAME_BORDER_WIDTH (f), height);
562 /*****************************************************************************
565 Ensure that the contents of the given display line is correct
566 on-screen. The force_ parameters are used by redisplay_move_cursor
567 to correctly update cursor locations and only cursor locations.
568 ****************************************************************************/
570 output_display_line (struct window *w, display_line_dynarr *cdla,
571 display_line_dynarr *ddla, int line, int force_start,
575 struct frame *f = XFRAME (w->frame);
576 struct buffer *b = XBUFFER (w->buffer);
577 struct buffer *old_b = window_display_buffer (w);
578 struct display_line *cdl, *ddl;
579 display_block_dynarr *cdba, *ddba;
580 int start_pixpos, end_pixpos;
581 int cursor_start, cursor_width, cursor_height;
583 int force = (force_start >= 0 || force_end >= 0);
584 int clear_border = 0;
587 if (cdla && line < Dynarr_length (cdla))
589 cdl = Dynarr_atp (cdla, line);
590 cdba = cdl->display_blocks;
598 ddl = Dynarr_atp (ddla, line); /* assert line < Dynarr_length (ddla) */
599 ddba = ddl->display_blocks;
601 if (force_start >= 0 && force_start >= ddl->bounds.left_out)
602 start_pixpos = force_start;
604 start_pixpos = ddl->bounds.left_out;
606 if (force_end >= 0 && force_end < ddl->bounds.right_out)
607 end_pixpos = force_end;
609 end_pixpos = ddl->bounds.right_out;
611 /* Get the cursor parameters. */
612 if (ddl->cursor_elt != -1)
614 struct display_block *db;
616 /* If the lines cursor parameter is not -1 then it indicates
617 which rune in the TEXT block contains the cursor. This means
618 that there must be at least one display block. The TEXT
619 block, if present, must always be the first display block. */
620 assert (Dynarr_length (ddba) != 0);
622 db = Dynarr_atp (ddba, 0);
623 assert (db->type == TEXT);
625 get_cursor_size_and_location (w, db, ddl->cursor_elt, &cursor_start,
626 &cursor_width, &cursor_height);
630 cursor_start = cursor_width = cursor_height = 0;
633 /* The modeline should only have a single block and it had better be
637 /* The shadow thickness check is necessary if only the sign of
639 if (cdba && !w->shadow_thickness_changed)
641 must_sync |= compare_display_blocks (w, cdl, ddl, 0, 0,
642 start_pixpos, 0, 0, 0);
646 redisplay_output_display_block (w, ddl, 0, 0, -1, start_pixpos,
655 while (!ddl->modeline && start_pixpos < end_pixpos)
658 int next_start_pixpos;
660 block = get_next_display_block (ddl->bounds, ddba, start_pixpos,
663 /* If we didn't find a block then we should blank the area
664 between start_pos and next_start if necessary. */
665 if (block == NO_BLOCK)
667 /* We only erase those areas which were actually previously
668 covered by a display block unless the window structure
669 changed. In that case we clear all areas since the current
670 structures may actually represent a different buffer. */
671 while (start_pixpos < next_start_pixpos)
677 old_block = get_next_display_block (ddl->bounds, cdba,
678 start_pixpos, &block_end);
681 old_block = NO_BLOCK;
682 block_end = next_start_pixpos;
685 if (!cdba || old_block != NO_BLOCK || b != old_b ||
686 f->windows_structure_changed ||
689 (cdl && (cdl->ypos != ddl->ypos ||
690 cdl->ascent != ddl->ascent ||
691 cdl->descent != ddl->descent ||
692 cdl->top_clip != ddl->top_clip ||
693 cdl->clip != ddl->clip)))
695 int x, y, width, height;
700 y = DISPLAY_LINE_YPOS (ddl);
701 width = min (next_start_pixpos, block_end) - x;
702 height = DISPLAY_LINE_HEIGHT (ddl);
704 if (x < ddl->bounds.left_in)
706 findex = ddl->left_margin_findex ?
707 ddl->left_margin_findex
708 : get_builtin_face_cache_index (w, Vleft_margin_face);
710 else if (x < ddl->bounds.right_in)
712 /* no check here because DEFAULT_INDEX == 0 anyway */
713 findex = ddl->default_findex;
715 else if (x < ddl->bounds.right_out)
717 findex = ddl->right_margin_findex ?
718 ddl->right_margin_findex
719 : get_builtin_face_cache_index (w, Vright_margin_face);
722 findex = (face_index) -1;
724 if (findex != (face_index) -1)
728 XSETWINDOW (window, w);
730 /* Clear the empty area. */
731 redisplay_clear_region (window, findex, x, y, width, height);
733 /* Mark that we should clear the border. This is
734 necessary because italic fonts may leave
735 droppings in the border. */
740 start_pixpos = min (next_start_pixpos, block_end);
745 struct display_block *cdb, *ddb;
750 old_block = get_next_display_block (ddl->bounds, cdba,
751 start_pixpos, &block_end);
753 old_block = NO_BLOCK;
755 ddb = Dynarr_atp (ddba, block);
756 cdb = (old_block != NO_BLOCK ? Dynarr_atp (cdba, old_block) : 0);
758 /* If there was formerly no block over the current
759 region or if it was a block of a different type, then
760 output the entire ddb. Otherwise, compare cdb and
761 ddb and output only the changed region. */
762 if (!force && cdb && ddb->type == cdb->type
763 /* If there was no buffer being display before the
764 compare anyway as we might be outputting a gutter. */
766 (b == old_b || !old_b))
768 must_sync |= compare_display_blocks (w, cdl, ddl, old_block,
770 cursor_start, cursor_width,
779 for (elt = 0; elt < Dynarr_length (ddb->runes); elt++)
781 struct rune *rb = Dynarr_atp (ddb->runes, elt);
783 if (start_pixpos >= rb->xpos
784 && start_pixpos < rb->xpos + rb->width)
787 if (end_pixpos > rb->xpos
788 && end_pixpos <= rb->xpos + rb->width)
791 if (last_elt > Dynarr_length (ddb->runes))
792 last_elt = Dynarr_length (ddb->runes);
798 redisplay_output_display_block (w, ddl, block, first_elt,
801 cursor_start, cursor_width,
805 start_pixpos = next_start_pixpos;
809 /* Clear the internal border if we are next to it and the window
810 structure or frame size has changed or if something caused
811 clear_border to be tripped. */
812 /* #### Doing this on f->clear sucks but is necessary because of
813 window-local background values. */
814 if (f->windows_structure_changed || f->faces_changed || clear_border
817 int y = DISPLAY_LINE_YPOS (ddl);
818 int height = DISPLAY_LINE_HEIGHT (ddl);
820 /* If we are in the gutter then we musn't clear the borders. */
821 if (y >= WINDOW_TEXT_TOP (w) && (y + height) <= WINDOW_TEXT_BOTTOM (w))
825 y -= MODELINE_SHADOW_THICKNESS (w);
826 height += (2 * MODELINE_SHADOW_THICKNESS (w));
829 if (window_is_leftmost (w))
830 clear_left_border (w, y, height);
831 if (window_is_rightmost (w))
832 clear_right_border (w, y, height);
837 sync_display_line_structs (w, line, must_sync, cdla, ddla);
840 /*****************************************************************************
841 redisplay_move_cursor
843 For the given window W, move the cursor to NEW_POINT. Returns a
844 boolean indicating success or failure.
845 ****************************************************************************/
847 #define ADJ_BUFPOS (rb->bufpos + dl->offset)
848 #define ADJ_ENDPOS (rb->endpos + dl->offset)
851 redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
853 struct frame *f = XFRAME (w->frame);
854 struct device *d = XDEVICE (f->device);
856 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
857 struct display_line *dl;
858 struct display_block *db;
860 int x = w->last_point_x[CURRENT_DISP];
861 int y = w->last_point_y[CURRENT_DISP];
864 * Bail if cursor_in_echo_area is non-zero and we're fiddling with
865 * the cursor in a non-active minibuffer window, since that is a
866 * special case that is handled elsewhere and this function need
867 * not handle it. Return 1 so the caller will assume we
870 if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
871 w != XWINDOW (FRAME_SELECTED_WINDOW (f)))
874 if (y < 0 || y >= Dynarr_length (cla))
877 dl = Dynarr_atp (cla, y);
878 db = get_display_block_from_line (dl, TEXT);
880 if (x < 0 || x >= Dynarr_length (db->runes))
883 rb = Dynarr_atp (db->runes, x);
885 if (rb->cursor_type == CURSOR_OFF)
887 else if (ADJ_BUFPOS == new_point
888 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
889 && (new_point <= ADJ_ENDPOS)))
891 w->last_point_x[CURRENT_DISP] = x;
892 w->last_point_y[CURRENT_DISP] = y;
893 Fset_marker (w->last_point[CURRENT_DISP], make_int (ADJ_BUFPOS),
900 DEVMETH (d, output_begin, (d));
902 /* #### This is a gross kludge. Cursor handling is such a royal
904 if (rb->type == RUNE_DGLYPH &&
905 (EQ (rb->object.dglyph.glyph, Vtruncation_glyph) ||
906 EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)))
907 rb->cursor_type = NO_CURSOR;
909 rb->cursor_type = CURSOR_OFF;
911 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
914 w->last_point_x[CURRENT_DISP] = -1;
915 w->last_point_y[CURRENT_DISP] = -1;
916 Fset_marker (w->last_point[CURRENT_DISP], Qnil, w->buffer);
918 /* If this isn't the selected frame, then erasing the old cursor is
919 all we actually had to do. */
920 if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d))))
923 DEVMETH (d, output_end, (d));
928 /* This should only occur in the minibuffer. */
931 w->last_point_x[CURRENT_DISP] = 0;
932 w->last_point_y[CURRENT_DISP] = y;
933 Fset_marker (w->last_point[CURRENT_DISP], Qzero, w->buffer);
935 rb = Dynarr_atp (db->runes, 0);
936 rb->cursor_type = CURSOR_ON;
939 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
942 DEVMETH (d, output_end, (d));
951 if (ADJ_BUFPOS < new_point)
957 else /* (rb->bufpos + dl->offset) > new_point */
974 while (up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0))
976 dl = Dynarr_atp (cla, cur_dl);
977 db = get_display_block_from_line (dl, TEXT);
980 cur_rb = Dynarr_length (db->runes) - 1;
982 while ((!scroll_on_clipped_lines || !dl->clip) &&
983 (up ? (cur_rb < Dynarr_length (db->runes)) : (cur_rb >= 0)))
985 rb = Dynarr_atp (db->runes, cur_rb);
987 if (rb->cursor_type != IGNORE_CURSOR
988 && rb->cursor_type != NO_CURSOR &&
989 (ADJ_BUFPOS == new_point
990 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
991 && (new_point <= ADJ_BUFPOS))))
993 rb->cursor_type = CURSOR_ON;
994 dl->cursor_elt = cur_rb;
997 output_display_line (w, 0, cla, cur_dl, rb->xpos,
998 rb->xpos + rb->width);
1000 w->last_point_x[CURRENT_DISP] = cur_rb;
1001 w->last_point_y[CURRENT_DISP] = cur_dl;
1002 Fset_marker (w->last_point[CURRENT_DISP],
1003 make_int (ADJ_BUFPOS), w->buffer);
1006 DEVMETH (d, output_end, (d));
1010 (up ? cur_rb++ : cur_rb--);
1013 (up ? (cur_rb = 0) : (first = 0));
1014 (up ? cur_dl++ : cur_dl--);
1019 DEVMETH (d, output_end, (d));
1025 /*****************************************************************************
1026 redraw_cursor_in_window
1028 For the given window W, redraw the cursor if it is contained within
1030 ****************************************************************************/
1032 redraw_cursor_in_window (struct window *w, int run_end_begin_meths)
1034 struct frame *f = XFRAME (w->frame);
1035 struct device *d = XDEVICE (f->device);
1037 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
1038 struct display_line *dl;
1039 struct display_block *db;
1042 int x = w->last_point_x[CURRENT_DISP];
1043 int y = w->last_point_y[CURRENT_DISP];
1045 if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
1046 !echo_area_active (f) && minibuf_level == 0)
1048 MAYBE_DEVMETH (d, set_final_cursor_coords, (f, w->pixel_top, 0));
1051 if (y < 0 || y >= Dynarr_length (dla))
1054 if (MINI_WINDOW_P (w) && f != device_selected_frame (d) &&
1055 !is_surrogate_for_selected_frame (f))
1058 dl = Dynarr_atp (dla, y);
1059 db = get_display_block_from_line (dl, TEXT);
1061 if (x < 0 || x >= Dynarr_length (db->runes))
1064 rb = Dynarr_atp (db->runes, x);
1066 /* Don't call the output routine if the block isn't actually the
1068 if (rb->cursor_type == CURSOR_ON)
1070 MAYBE_DEVMETH (d, set_final_cursor_coords,
1071 (f, dl->ypos - 1, rb->xpos));
1073 if (run_end_begin_meths)
1074 DEVMETH (d, output_begin, (d));
1076 output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width);
1078 if (run_end_begin_meths)
1079 DEVMETH (d, output_end, (d));
1083 /*****************************************************************************
1084 redisplay_redraw_cursor
1086 For the given frame F, redraw the cursor on the selected window.
1087 This is used to update the cursor after focus changes.
1088 ****************************************************************************/
1090 redisplay_redraw_cursor (struct frame *f, int run_end_begin_meths)
1094 if (!cursor_in_echo_area)
1095 window = FRAME_SELECTED_WINDOW (f);
1096 else if (FRAME_HAS_MINIBUF_P (f))
1097 window = FRAME_MINIBUF_WINDOW (f);
1101 redraw_cursor_in_window (XWINDOW (window), run_end_begin_meths);
1104 /****************************************************************************
1105 redisplay_output_display_block
1107 Given a display line, a block number for that start line, output all
1108 runes between start and end in the specified display block.
1109 ****************************************************************************/
1111 redisplay_output_display_block (struct window *w, struct display_line *dl, int block,
1112 int start, int end, int start_pixpos, int cursor_start,
1113 int cursor_width, int cursor_height)
1115 struct frame *f = XFRAME (w->frame);
1116 struct device *d = XDEVICE (f->device);
1117 /* Temporarily disabled until generalization is done. */
1119 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
1120 rune_dynarr *rba = db->runes;
1123 rb = Dynarr_atp (rba, start);
1126 /* Nothing to do so don't do anything. */
1129 xpos = max (start_pixpos, rb->xpos);
1132 end = Dynarr_length (rba);
1134 rb = Dynarr_atp (rba, end - 1);
1135 width = rb->xpos + rb->width - xpos;
1137 /* now actually output the block. */
1138 DEVMETH (d, output_display_block, (w, dl, block, start,
1140 cursor_start, cursor_width,
1144 /****************************************************************************
1145 redisplay_unmap_subwindows
1147 Remove subwindows from the area in the box defined by the given
1149 ****************************************************************************/
1150 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height,
1151 Lisp_Object ignored_window)
1155 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
1157 struct subwindow_cachel *cachel =
1158 Dynarr_atp (f->subwindow_cachels, elt);
1160 if (cachel->being_displayed
1162 cachel->x + cachel->width > x && cachel->x < x + width
1164 cachel->y + cachel->height > y && cachel->y < y + height
1166 !EQ (cachel->subwindow, ignored_window))
1168 unmap_subwindow (cachel->subwindow);
1173 /****************************************************************************
1174 redisplay_unmap_subwindows_maybe
1176 Potentially subwindows from the area in the box defined by the given
1178 ****************************************************************************/
1179 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height)
1181 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1183 redisplay_unmap_subwindows (f, x, y, width, height, Qnil);
1187 static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width,
1188 int height, Lisp_Object subwindow)
1190 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1192 redisplay_unmap_subwindows (f, x, y, width, height, subwindow);
1196 /****************************************************************************
1197 redisplay_output_subwindow
1199 output a subwindow. This code borrows heavily from the pixmap stuff,
1200 although is much simpler not needing to account for partial
1201 pixmaps, backgrounds etc.
1202 ****************************************************************************/
1204 redisplay_output_subwindow (struct window *w,
1205 Lisp_Object image_instance,
1206 struct display_box* db, struct display_glyph_area* dga,
1207 face_index findex, int cursor_start, int cursor_width,
1210 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1212 struct display_glyph_area sdga;
1214 dga->height = IMAGE_INSTANCE_HEIGHT (p);
1215 dga->width = IMAGE_INSTANCE_WIDTH (p);
1217 /* The first thing we are going to do is update the display
1218 characteristics of the subwindow. This also clears the dirty
1219 flags as a side effect. */
1220 update_subwindow (image_instance);
1222 /* This makes the glyph area fit into the display area. */
1223 if (!redisplay_normalize_glyph_area (db, dga))
1226 XSETWINDOW (window, w);
1228 /* Clear the area the subwindow is going into. */
1229 redisplay_clear_clipped_region (window, findex,
1230 db, dga, 0, image_instance);
1232 /* This shrinks the display box to exactly enclose the glyph
1234 redisplay_normalize_display_box (db, dga);
1236 /* if we can't view the whole window we can't view any of it. We
1237 have to be careful here since we may be being asked to display
1238 part of a subwindow, the rest of which is on-screen as well. We
1239 need to allow this case and map the entire subwindow. We also
1240 need to be careful since the subwindow could be outside the
1241 window in the gutter or modeline - we also need to allow these
1243 sdga.xoffset = -dga->xoffset;
1244 sdga.yoffset = -dga->yoffset;
1245 sdga.height = IMAGE_INSTANCE_HEIGHT (p);
1246 sdga.width = IMAGE_INSTANCE_WIDTH (p);
1248 if (redisplay_display_boxes_in_window_p (w, db, &sdga) < 0)
1250 map_subwindow (image_instance, db->xpos, db->ypos, dga);
1254 sdga.xoffset = sdga.yoffset = 0;
1255 map_subwindow (image_instance, db->xpos - dga->xoffset,
1256 db->ypos - dga->yoffset, &sdga);
1260 /****************************************************************************
1261 redisplay_output_layout
1263 Output a widget hierarchy. This can safely call itself recursively.
1265 The complexity of outputting layouts is deciding whether to do it or
1266 not. Consider a layout enclosing some text, the text changes and is
1267 marked as dirty, but the enclosing layout has not been marked as
1268 dirty so no updates occur and the text will potentially be truncated.
1269 Alternatively we hold a back pointer in the image instance to the
1270 parent and mark the parent as dirty. But the layout code assumes that
1271 if the layout is dirty then the whole layout should be redisplayed,
1272 so we then get lots of flashing even though only the text has changed
1273 size. Of course if the text shrinks in size then we do actually need
1274 to redisplay the layout to repaint the exposed area. So what happens
1275 if we make a non-structural change like changing color? Either we
1276 redisplay everything, or we redisplay nothing. These are exactly the
1277 issues lwlib has to grapple with. We really need to know what has
1278 actually changed and make a layout decision based on that. We also
1279 really need to know what has changed so that we can only make the
1280 neccessary changes in update_subwindow. This has all now been
1281 implemented, Viva la revolution!
1282 ****************************************************************************/
1284 redisplay_output_layout (struct window *w,
1285 Lisp_Object image_instance,
1286 struct display_box* db, struct display_glyph_area* dga,
1287 face_index findex, int cursor_start, int cursor_width,
1290 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1291 Lisp_Object window, rest;
1292 Emchar_dynarr *buf = Dynarr_new (Emchar);
1293 struct frame *f = XFRAME (w->frame);
1294 struct device *d = XDEVICE (f->device);
1295 int layout_height, layout_width;
1297 XSETWINDOW (window, w);
1299 layout_height = glyph_height (image_instance, window);
1300 layout_width = glyph_width (image_instance, window);
1302 dga->height = layout_height;
1303 dga->width = layout_width;
1305 /* This makes the glyph area fit into the display area. */
1306 if (!redisplay_normalize_glyph_area (db, dga))
1309 /* Highly dodgy optimization. We want to only output the whole
1310 layout if we really have to. */
1311 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p)
1312 || IMAGE_INSTANCE_LAYOUT_CHANGED (p)
1313 || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
1314 || IMAGE_INSTANCE_SIZE_CHANGED (p)
1315 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
1317 /* First clear the area we are drawing into. This is the easiest
1318 thing to do since we have many gaps that we have to make sure are
1320 redisplay_clear_clipped_region (window, findex, db, dga, 1, Qnil);
1322 /* Output a border if required */
1323 if (!NILP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1326 enum edge_style style;
1327 int ypos = db->ypos;
1328 int height = dga->height;
1330 if (dga->xoffset >= 0)
1332 if (dga->width - dga->xoffset == layout_width)
1333 edges |= EDGE_RIGHT;
1334 if (dga->yoffset >= 0)
1336 if (dga->height - dga->yoffset == layout_height)
1337 edges |= EDGE_BOTTOM;
1339 if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in))
1340 style = EDGE_ETCHED_IN;
1341 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out))
1342 style = EDGE_ETCHED_OUT;
1343 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qbevel_in))
1344 style = EDGE_BEVEL_IN;
1345 else if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1347 style = EDGE_ETCHED_IN;
1348 if (edges & EDGE_TOP)
1350 ypos += XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1351 height -= XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1355 style = EDGE_BEVEL_OUT;
1357 MAYBE_DEVMETH (d, bevel_area,
1358 (w, findex, db->xpos,
1360 dga->width, height, 2, edges, style));
1364 /* This shrinks the display box to exactly enclose the glyph
1366 redisplay_normalize_display_box (db, dga);
1368 /* Flip through the widgets in the layout displaying as necessary */
1369 LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p))
1371 Lisp_Object child = XCAR (rest);
1373 struct display_box cdb;
1374 /* For losing HP-UX */
1375 cdb.xpos = db->xpos;
1376 cdb.ypos = db->ypos;
1377 cdb.width = db->width;
1378 cdb.height = db->height;
1380 /* First determine if the image is visible at all */
1381 if (IMAGE_INSTANCEP (child))
1383 Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child);
1385 /* The enclosing layout offsets are +ve at this point */
1386 struct display_glyph_area cdga;
1387 cdga.xoffset = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset;
1388 cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset;
1389 cdga.width = glyph_width (child, window);
1390 cdga.height = glyph_height (child, window);
1392 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) =
1393 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p);
1395 /* Although normalization is done by the output routines
1396 we have to do it here so that they don't try and
1397 clear all of db. This is true below also. */
1398 if (redisplay_normalize_glyph_area (&cdb, &cdga))
1400 redisplay_normalize_display_box (&cdb, &cdga);
1401 /* Since the display boxes will now be totally in the
1402 window if they are visible at all we can now check this easily. */
1403 if (cdb.xpos < db->xpos || cdb.ypos < db->ypos
1404 || cdb.xpos + cdb.width > db->xpos + db->width
1405 || cdb.ypos + cdb.height > db->ypos + db->height)
1407 /* We have to invert the offset here as normalization
1408 will have made them positive which the output
1409 routines will treat as a truely +ve offset. */
1410 cdga.xoffset = -cdga.xoffset;
1411 cdga.yoffset = -cdga.yoffset;
1413 switch (IMAGE_INSTANCE_TYPE (childii))
1417 /* #### This is well hacked and could use some
1419 if (redisplay_normalize_glyph_area (&cdb, &cdga)
1421 (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
1422 IMAGE_INSTANCE_DIRTYP (childii)))
1424 struct display_line dl; /* this is fake */
1425 Lisp_Object string =
1426 IMAGE_INSTANCE_TEXT_STRING (childii);
1427 convert_bufbyte_string_into_emchar_dynarr
1428 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
1430 redisplay_normalize_display_box (&cdb, &cdga);
1431 /* Offsets are now +ve again so be careful
1432 when fixing up the display line. */
1434 /* Munge boxes into display lines. */
1435 dl.ypos = (cdb.ypos - cdga.yoffset)
1436 + glyph_ascent (child, window);
1437 dl.ascent = glyph_ascent (child, window);
1438 dl.descent = glyph_descent (child, window);
1439 dl.top_clip = cdga.yoffset;
1440 dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height);
1441 /* output_string doesn't understand offsets in
1442 the same way as other routines - we have to
1443 add the offset to the width so that we
1444 output the full string. */
1445 MAYBE_DEVMETH (d, output_string, (w, &dl, buf, cdb.xpos,
1446 cdga.xoffset, cdb.xpos,
1447 cdga.width + cdga.xoffset,
1448 findex, 0, 0, 0, 0));
1454 case IMAGE_MONO_PIXMAP:
1455 case IMAGE_COLOR_PIXMAP:
1456 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii)
1457 || IMAGE_INSTANCE_DIRTYP (childii))
1458 redisplay_output_pixmap (w, child, &cdb, &cdga, findex,
1463 case IMAGE_SUBWINDOW:
1464 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
1465 IMAGE_INSTANCE_DIRTYP (childii))
1466 redisplay_output_subwindow (w, child, &cdb, &cdga, findex,
1471 redisplay_output_layout (w, child, &cdb, &cdga, findex,
1476 /* nothing is as nothing does */
1484 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 0;
1488 /* Update any display properties. I'm not sure whether this actually
1489 does anything for layouts except clear the changed flags. */
1490 update_subwindow (image_instance);
1495 /****************************************************************************
1496 redisplay_output_pixmap
1500 ****************************************************************************/
1502 redisplay_output_pixmap (struct window *w,
1503 Lisp_Object image_instance,
1504 struct display_box* db, struct display_glyph_area* dga,
1505 face_index findex, int cursor_start, int cursor_width,
1506 int cursor_height, int offset_bitmap)
1508 struct frame *f = XFRAME (w->frame);
1509 struct device *d = XDEVICE (f->device);
1510 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1512 XSETWINDOW (window, w);
1514 dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
1515 dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
1517 /* This makes the glyph area fit into the display area. */
1518 if (!redisplay_normalize_glyph_area (db, dga))
1521 /* Clear the area the pixmap is going into. The pixmap itself will
1522 always take care of the full width. We don't want to clear where
1523 it is going to go in order to avoid flicker. So, all we have to
1524 take care of is any area above or below the pixmap. If the pixmap
1525 has a mask in which case we have to clear the whole damn thing
1526 since we can't yet clear just the area not included in the
1530 redisplay_clear_clipped_region (window, findex,
1532 (int)IMAGE_INSTANCE_PIXMAP_MASK (p),
1535 /* This shrinks the display box to exactly enclose the glyph
1537 redisplay_normalize_display_box (db, dga);
1539 assert (db->xpos >= 0 && db->ypos >= 0);
1541 MAYBE_DEVMETH (d, output_pixmap, (w, image_instance,
1543 findex, cursor_start,
1544 cursor_width, cursor_height,
1548 /****************************************************************************
1549 redisplay_clear_region
1551 Clear the area in the box defined by the given parameters using the
1552 given face. This has been generalised so that subwindows can be
1553 coped with effectively.
1554 ****************************************************************************/
1556 redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y,
1557 int width, int height)
1559 struct window *w = NULL;
1560 struct frame *f = NULL;
1562 Lisp_Object background_pixmap = Qunbound;
1563 Lisp_Object fcolor = Qnil, bcolor = Qnil;
1565 if (!width || !height)
1568 if (WINDOWP (locale))
1570 w = XWINDOW (locale);
1571 f = XFRAME (w->frame);
1573 else if (FRAMEP (locale))
1576 f = XFRAME (locale);
1581 d = XDEVICE (f->device);
1583 /* if we have subwindows in the region we have to unmap them */
1584 redisplay_unmap_subwindows_maybe (f, x, y, width, height);
1586 /* #### This isn't quite right for when this function is called
1587 from the toolbar code. */
1589 /* Don't use a backing pixmap in the border area */
1590 if (x >= FRAME_LEFT_BORDER_END (f)
1591 && x < FRAME_RIGHT_BORDER_START (f)
1592 && y >= FRAME_TOP_BORDER_END (f)
1593 && y < FRAME_BOTTOM_BORDER_START (f))
1599 temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
1601 if (IMAGE_INSTANCEP (temp)
1602 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1604 /* #### maybe we could implement such that a string
1605 can be a background pixmap? */
1606 background_pixmap = temp;
1611 temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
1613 if (IMAGE_INSTANCEP (temp)
1614 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1616 background_pixmap = temp;
1621 if (!UNBOUNDP (background_pixmap) &&
1622 XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
1626 fcolor = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1627 bcolor = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1631 fcolor = FACE_FOREGROUND (Vdefault_face, locale);
1632 bcolor = FACE_BACKGROUND (Vdefault_face, locale);
1638 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
1639 FACE_BACKGROUND (Vdefault_face, locale));
1643 if (UNBOUNDP (background_pixmap))
1644 background_pixmap = Qnil;
1646 DEVMETH (d, clear_region,
1647 (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1650 /****************************************************************************
1651 redisplay_clear_clipped_region
1653 Clear the area in the dest display_box not covered by the src
1654 display_glyph_area using the given face. This is a common occurance
1655 for images shorter than the display line. Clipping can be played
1656 around with by altering these. glyphsrc should be normalized.
1657 ****************************************************************************/
1659 redisplay_clear_clipped_region (Lisp_Object window, face_index findex,
1660 struct display_box* dest, struct display_glyph_area* glyphsrc,
1661 int fullheight_p, Lisp_Object ignored_subwindow)
1663 /* assume dest->xpos >= 0 */
1665 struct frame* f = XFRAME (XWINDOW (window)->frame);
1667 if (glyphsrc->xoffset > 0)
1669 clear_x = dest->xpos + glyphsrc->xoffset;
1673 clear_x = dest->xpos;
1676 /* If we need the whole height cleared then just do it. */
1679 redisplay_clear_region (window, findex, clear_x, dest->ypos,
1680 glyphsrc->width, dest->height);
1684 int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0);
1686 /* We need to make sure that subwindows are unmapped from the
1688 redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos,
1689 glyphsrc->width, dest->height,
1691 /* first the top box */
1694 redisplay_clear_region (window, findex, clear_x, dest->ypos,
1695 glyphsrc->width, yoffset);
1698 /* Then the bottom box */
1699 if (yoffset + glyphsrc->height < dest->height)
1701 redisplay_clear_region (window, findex, clear_x,
1702 dest->ypos + yoffset + glyphsrc->height,
1704 dest->height - (yoffset + glyphsrc->height));
1710 /*****************************************************************************
1711 redisplay_normalize_glyph_area
1712 redisplay_normalize_display_box
1714 Calculate the visible box for displaying src in dest.
1715 ****************************************************************************/
1717 redisplay_normalize_glyph_area (struct display_box* dest,
1718 struct display_glyph_area* glyphsrc)
1720 if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width
1722 dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height
1724 -glyphsrc->xoffset >= glyphsrc->width
1726 -glyphsrc->yoffset >= glyphsrc->height)
1728 /* It's all clipped out */
1732 /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */
1733 if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width)
1735 if (glyphsrc->xoffset > 0)
1736 glyphsrc->width = dest->width - glyphsrc->xoffset;
1738 glyphsrc->width = dest->width;
1741 if (glyphsrc->xoffset < 0)
1742 glyphsrc->width += glyphsrc->xoffset;
1744 /* Vertical offsets. This works because yoffset can be -ve as well as +ve */
1745 if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height)
1747 if (glyphsrc->yoffset > 0)
1748 glyphsrc->height = dest->height - glyphsrc->yoffset;
1750 glyphsrc->height = dest->height;
1753 if (glyphsrc->yoffset < 0)
1754 glyphsrc->height += glyphsrc->yoffset;
1760 redisplay_normalize_display_box (struct display_box* dest,
1761 struct display_glyph_area* glyphsrc)
1763 /* Adjust the destination area. At the end of this the destination
1764 area will exactly enclose the glyph area. The only remaining
1765 adjustment will be offsets into the glyph area. */
1767 /* Horizontal adjustment. */
1768 if (glyphsrc->xoffset > 0)
1770 dest->xpos += glyphsrc->xoffset;
1771 dest->width -= glyphsrc->xoffset;
1772 glyphsrc->xoffset = 0;
1775 glyphsrc->xoffset = -glyphsrc->xoffset;
1777 if (glyphsrc->width < dest->width)
1778 dest->width = glyphsrc->width;
1780 /* Vertical adjustment. */
1781 if (glyphsrc->yoffset > 0)
1783 dest->ypos += glyphsrc->yoffset;
1784 dest->height -= glyphsrc->yoffset;
1785 glyphsrc->yoffset = 0;
1788 glyphsrc->yoffset = -glyphsrc->yoffset;
1790 if (glyphsrc->height < dest->height)
1791 dest->height = glyphsrc->height;
1794 /*****************************************************************************
1795 redisplay_display_boxes_in_window_p
1797 Determine whether the require display_glyph_area is completely inside
1798 the window. 0 means the display_box is not in the window. 1 means the
1799 display_box and the display_glyph_area are in the window. -1 means
1800 the display_box is in the window but the display_glyph_area is not.
1801 ****************************************************************************/
1803 redisplay_display_boxes_in_window_p (struct window* w,
1804 struct display_box* db,
1805 struct display_glyph_area* dga)
1807 int left = WINDOW_TEXT_LEFT (w);
1808 int right = WINDOW_TEXT_RIGHT (w);
1809 int top = WINDOW_TEXT_TOP (w);
1810 int bottom = WINDOW_TEXT_BOTTOM (w);
1812 if (db->xpos < left || db->ypos < top
1813 || db->xpos + db->width > right
1814 || db->ypos + db->height > bottom)
1815 /* We are not displaying in a window at all */
1818 if (db->xpos + dga->xoffset >= left
1820 db->ypos + dga->yoffset >= top
1822 db->xpos + dga->xoffset + dga->width <= right
1824 db->ypos + dga->yoffset + dga->height <= bottom)
1830 /*****************************************************************************
1831 redisplay_calculate_display_boxes
1833 Convert from rune/display_line co-ordinates to display_box
1835 ****************************************************************************/
1837 redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
1838 int xoffset, int start_pixpos, int width,
1839 struct display_box* dest,
1840 struct display_glyph_area* src)
1843 dest->ypos = DISPLAY_LINE_YPOS (dl);
1844 dest->width = width;
1845 dest->height = DISPLAY_LINE_HEIGHT (dl);
1847 src->xoffset = -xoffset;
1848 src->yoffset = -dl->top_clip;
1852 if (start_pixpos >=0 && start_pixpos > xpos)
1854 /* Oops, we're asking for a start outside of the displayable
1856 if (start_pixpos > xpos + width)
1858 dest->xpos = start_pixpos;
1859 dest->width -= (start_pixpos - xpos);
1860 /* Offsets are -ve when we want to clip pixels off the displayed
1862 src->xoffset -= (start_pixpos - xpos);
1868 /*****************************************************************************
1869 redisplay_clear_top_of_window
1871 If window is topmost, clear the internal border above it.
1872 ****************************************************************************/
1874 redisplay_clear_top_of_window (struct window *w)
1877 XSETWINDOW (window, w);
1879 if (!NILP (Fwindow_highest_p (window)))
1881 struct frame *f = XFRAME (w->frame);
1882 int x, y, width, height;
1885 width = w->pixel_width;
1887 if (window_is_leftmost (w))
1889 x -= FRAME_BORDER_WIDTH (f);
1890 width += FRAME_BORDER_WIDTH (f);
1892 if (window_is_rightmost (w))
1893 width += FRAME_BORDER_WIDTH (f);
1895 y = FRAME_TOP_BORDER_START (f) - 1;
1896 height = FRAME_BORDER_HEIGHT (f) + 1;
1898 redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
1902 /*****************************************************************************
1903 redisplay_clear_to_window_end
1905 Clear the area between ypos1 and ypos2. Each margin area and the
1906 text area is handled separately since they may each have their own
1908 ****************************************************************************/
1910 redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1912 struct frame *f = XFRAME (w->frame);
1913 struct device *d = XDEVICE (f->device);
1915 if (HAS_DEVMETH_P (d, clear_to_window_end))
1916 DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1919 int height = ypos2 - ypos1;
1924 int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/
1925 layout_bounds bounds;
1927 bounds = calculate_display_line_boundaries (w, bflag);
1928 XSETWINDOW (window, w);
1930 if (window_is_leftmost (w))
1931 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1932 ypos1, FRAME_BORDER_WIDTH (f), height);
1934 if (bounds.left_in - bounds.left_out > 0)
1935 redisplay_clear_region (window,
1936 get_builtin_face_cache_index (w, Vleft_margin_face),
1937 bounds.left_out, ypos1,
1938 bounds.left_in - bounds.left_out, height);
1940 if (bounds.right_in - bounds.left_in > 0)
1941 redisplay_clear_region (window,
1943 bounds.left_in, ypos1,
1944 bounds.right_in - bounds.left_in, height);
1946 if (bounds.right_out - bounds.right_in > 0)
1947 redisplay_clear_region (window,
1948 get_builtin_face_cache_index (w, Vright_margin_face),
1949 bounds.right_in, ypos1,
1950 bounds.right_out - bounds.right_in, height);
1952 if (window_is_rightmost (w))
1953 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1954 ypos1, FRAME_BORDER_WIDTH (f), height);
1959 /*****************************************************************************
1960 redisplay_clear_bottom_of_window
1962 Clear window from right below the last display line to right above
1963 the modeline. The calling function can limit the area actually
1964 erased by setting min_start and/or max_end to positive values.
1965 ****************************************************************************/
1967 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1968 int min_start, int max_end)
1970 struct frame *f = XFRAME (w->frame);
1972 int ddla_len = Dynarr_length (ddla);
1974 ypos2 = WINDOW_TEXT_BOTTOM (w);
1975 #ifdef HAVE_SCROLLBARS
1976 /* This adjustment is to catch the intersection of any scrollbars. */
1977 if (f->windows_structure_changed && NILP (w->scrollbar_on_top_p))
1978 ypos2 += window_scrollbar_height (w);
1983 if (ddla_len == 1 && Dynarr_atp (ddla, 0)->modeline)
1985 ypos1 = WINDOW_TEXT_TOP (w);
1986 #ifdef HAVE_SCROLLBARS
1987 /* This adjustment is to catch the intersection of any scrollbars. */
1988 if (f->windows_structure_changed && !NILP (w->scrollbar_on_top_p))
1989 ypos1 -= window_scrollbar_height (w);
1994 struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1);
1995 ypos1 = dl->ypos + dl->descent - dl->clip;
1999 ypos1 = WINDOW_TEXT_TOP (w);
2001 /* #### See if this can be made conditional on the frame
2003 if (MINI_WINDOW_P (w))
2004 ypos2 += FRAME_BORDER_HEIGHT (f);
2006 if (min_start >= 0 && ypos1 < min_start)
2008 if (max_end >= 0 && ypos2 > max_end)
2014 redisplay_clear_to_window_end (w, ypos1, ypos2);
2017 /*****************************************************************************
2018 redisplay_update_line
2020 This is used during incremental updates to update a single line and
2021 correct the offsets on all lines below it. At the moment
2022 update_values is false if we are only updating the modeline.
2023 ****************************************************************************/
2025 redisplay_update_line (struct window *w, int first_line, int last_line,
2028 struct frame *f = XFRAME (w->frame);
2029 struct device *d = XDEVICE (f->device);
2031 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2032 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2034 DEVMETH (d, output_begin, (d));
2036 while (first_line <= last_line)
2038 Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos -
2039 Dynarr_atp (cdla, first_line)->bufpos);
2040 Charcount new_len = (Dynarr_atp (ddla, first_line)->end_bufpos -
2041 Dynarr_atp (ddla, first_line)->bufpos);
2043 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
2045 /* Output the changes. */
2046 output_display_line (w, cdla, ddla, first_line, -1, -1);
2048 /* Update the offsets. */
2051 int cur_line = first_line + 1;
2052 while (cur_line < Dynarr_length (cdla))
2054 Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len);
2055 Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len);
2060 /* Update the window_end_pos and other settings. */
2063 w->window_end_pos[CURRENT_DISP] -= (new_len - old_len);
2065 if (Dynarr_atp (ddla, first_line)->cursor_elt != -1)
2067 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2068 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2075 /* Update the window max line length. We have to scan the entire
2076 set of display lines otherwise we might not detect if the max is
2077 supposed to shrink. */
2082 w->max_line_len = 0;
2083 while (line < Dynarr_length (ddla))
2085 struct display_line *dl = Dynarr_atp (ddla, line);
2088 w->max_line_len = max (dl->num_chars, w->max_line_len);
2094 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2095 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2096 Fset_marker (w->last_point[CURRENT_DISP],
2097 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2098 Fset_marker (w->last_start[CURRENT_DISP],
2099 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2101 /* We don't bother updating the vertical scrollbars here. This
2102 gives us a performance increase while having minimal loss of
2103 quality to the scrollbar slider size and position since when this
2104 function is called we know that the changes to the buffer were
2105 very localized. We have to update the horizontal scrollbars,
2106 though, because this routine could cause a change which has a
2107 larger impact on their sizing. */
2108 /* #### See if we can get away with only calling this if
2109 max_line_len is greater than the window_char_width. */
2110 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS)
2112 extern int stupid_vertical_scrollbar_drag_hack;
2114 update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack);
2115 stupid_vertical_scrollbar_drag_hack = 1;
2119 /* This has to be done after we've updated the values. We don't
2120 call output_end for tty frames. Redisplay will do this after all
2121 tty windows have been updated. This cuts down on cursor
2123 if (FRAME_TTY_P (f))
2124 redisplay_redraw_cursor (f, 0);
2126 DEVMETH (d, output_end, (d));
2129 /*****************************************************************************
2130 redisplay_output_window
2132 For the given window W, ensure that the current display lines are
2133 equal to the desired display lines, outputing changes as necessary.
2135 #### Fuck me. This just isn't going to cut it for tty's. The output
2136 decisions for them must be based on the contents of the entire frame
2137 because that is how the available output capabilities think. The
2138 solution is relatively simple. Create redisplay_output_frame. This
2139 will basically merge all of the separate window display structs into
2140 a single one for the frame. This combination structure will be able
2141 to be passed to the same output_display_line which works for windows
2142 on X frames and the right things will happen. It just takes time to
2144 ****************************************************************************/
2146 redisplay_output_window (struct window *w)
2148 struct frame *f = XFRAME (w->frame);
2149 struct device *d = XDEVICE (f->device);
2151 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2152 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2154 int cdla_len = Dynarr_length (cdla);
2155 int ddla_len = Dynarr_length (ddla);
2158 int need_to_clear_bottom = 0;
2159 int need_to_clear_start = -1;
2160 int need_to_clear_end = -1;
2162 /* Backgrounds may have changed or windows may have gone away
2163 leaving dividers lying around. */
2164 if (f->faces_changed
2165 || f->windows_structure_changed
2166 || w->shadow_thickness_changed)
2167 need_to_clear_bottom = 1;
2169 /* The first thing we do is determine if we are going to need to
2170 clear the bottom of the window. We only need to do this if the
2171 bottom of the current display lines is below the bottom of the
2172 desired display lines. Note that the number of lines is
2173 irrelevant. Only the position matters. We also clear to the
2174 bottom of the window if the modeline has shifted position. */
2175 /* #### We can't blindly not clear the bottom if f->clear is true
2176 since there might be a window-local background. However, for
2177 those cases where there isn't, clearing the end of the window in
2179 if (!need_to_clear_bottom)
2181 struct display_line *cdl, *ddl;
2183 /* If the modeline has changed position or size, clear the bottom
2185 if (!need_to_clear_bottom)
2190 cdl = Dynarr_atp (cdla, 0);
2192 ddl = Dynarr_atp (ddla, 0);
2195 need_to_clear_bottom = 1;
2196 else if ((!cdl->modeline && ddl->modeline)
2197 || (cdl->modeline && !ddl->modeline))
2198 need_to_clear_bottom = 1;
2199 else if (cdl->ypos != ddl->ypos ||
2200 cdl->ascent != ddl->ascent ||
2201 cdl->descent != ddl->descent ||
2202 cdl->clip != ddl->clip)
2203 need_to_clear_bottom = 1;
2205 /* #### This kludge is to make sure the modeline shadows get
2206 redrawn if the modeline position shifts. */
2207 if (need_to_clear_bottom)
2208 w->shadow_thickness_changed = 1;
2211 if (!need_to_clear_bottom)
2216 cdl = Dynarr_atp (cdla, cdla_len - 1);
2218 ddl = Dynarr_atp (ddla, ddla_len - 1);
2221 need_to_clear_bottom = 1;
2224 int cdl_bottom, ddl_bottom;
2226 cdl_bottom = cdl->ypos + cdl->descent;
2227 ddl_bottom = ddl->ypos + ddl->descent;
2229 if (cdl_bottom > ddl_bottom)
2231 need_to_clear_bottom = 1;
2232 need_to_clear_start = ddl_bottom;
2233 need_to_clear_end = cdl_bottom;
2239 /* Perform any output initialization. */
2240 DEVMETH (d, output_begin, (d));
2242 /* If the window's structure has changed clear the internal border
2243 above it if it is topmost (the function will check). */
2244 if (f->windows_structure_changed)
2245 redisplay_clear_top_of_window (w);
2247 /* Output each line. */
2248 for (line = 0; line < Dynarr_length (ddla); line++)
2250 output_display_line (w, cdla, ddla, line, -1, -1);
2253 /* If the number of display lines has shrunk, adjust. */
2254 if (cdla_len > ddla_len)
2256 Dynarr_length (cdla) = ddla_len;
2259 /* Output a vertical divider between windows, if necessary. */
2260 if (window_needs_vertical_divider (w)
2261 && (f->windows_structure_changed || f->clear))
2263 DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
2266 /* Clear the rest of the window, if necessary. */
2267 if (need_to_clear_bottom)
2269 redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start,
2273 w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP];
2274 Fset_marker (w->start[CURRENT_DISP],
2275 make_int (marker_position (w->start[DESIRED_DISP])),
2277 Fset_marker (w->pointm[CURRENT_DISP],
2278 make_int (marker_position (w->pointm[DESIRED_DISP])),
2280 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
2281 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
2282 Fset_marker (w->last_start[CURRENT_DISP],
2283 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
2284 Fset_marker (w->last_point[CURRENT_DISP],
2285 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
2286 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
2287 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
2288 w->shadow_thickness_changed = 0;
2290 set_window_display_buffer (w, XBUFFER (w->buffer));
2291 find_window_mirror (w)->truncate_win = window_truncation_on (w);
2293 /* Overkill on invalidating the cache. It is very bad for it to not
2294 get invalidated when it should be. */
2295 INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
2297 /* We don't call output_end for tty frames. Redisplay will do this
2298 after all tty windows have been updated. This cuts down on
2300 if (FRAME_TTY_P (f))
2301 redisplay_redraw_cursor (f, 0);
2303 DEVMETH (d, output_end, (d));
2305 #ifdef HAVE_SCROLLBARS
2306 update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);
2310 /*****************************************************************************
2313 Draw a 3d border around the modeline on window W.
2314 ****************************************************************************/
2316 bevel_modeline (struct window *w, struct display_line *dl)
2318 struct frame *f = XFRAME (w->frame);
2319 struct device *d = XDEVICE (f->device);
2320 int x, y, width, height;
2321 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
2322 enum edge_style style;
2324 x = WINDOW_MODELINE_LEFT (w);
2325 width = WINDOW_MODELINE_RIGHT (w) - x;
2326 y = dl->ypos - dl->ascent - shadow_thickness;
2327 height = dl->ascent + dl->descent + 2 * shadow_thickness;
2329 if (XINT (w->modeline_shadow_thickness) < 0)
2331 style = EDGE_BEVEL_IN;
2335 style = EDGE_BEVEL_OUT;
2338 MAYBE_DEVMETH (d, bevel_area,
2339 (w, MODELINE_INDEX, x, y, width, height, shadow_thickness,