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.
6 This file is part of XEmacs.
8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with XEmacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
23 /* Synched up with: Not in FSF. */
25 /* This file has been Mule-ized. */
27 /* Author: Chuck Thompson */
37 #include "redisplay.h"
40 static int compare_runes (struct window *w, struct rune *crb,
42 static void redraw_cursor_in_window (struct window *w,
43 int run_end_begin_glyphs);
44 static void redisplay_output_display_block (struct window *w, struct display_line *dl,
45 int block, int start, int end, int start_pixpos,
46 int cursor_start, int cursor_width,
49 /*****************************************************************************
52 Synchronize the given rune blocks.
53 ****************************************************************************/
55 sync_rune_structs (struct window *w, rune_dynarr *cra, rune_dynarr *dra)
58 int max_move = ((Dynarr_length (dra) > Dynarr_largest (cra))
59 ? Dynarr_largest (cra)
60 : Dynarr_length (dra));
64 /* #### Doing this directly breaks the encapsulation. But, the
65 running time of this function has a measurable impact on
66 redisplay performance so avoiding all excess overhead is a
67 good thing. Is all of this true? */
68 memcpy (cra->base, dra->base, sizeof (struct rune) * max_move);
69 Dynarr_set_size (cra, max_move);
74 for (rune_elt = max_move; rune_elt < Dynarr_length (dra); rune_elt++)
77 struct rune *drb = Dynarr_atp (dra, rune_elt);
80 memcpy (crb, drb, sizeof (struct rune));
81 Dynarr_add (cra, *crb);
85 /*****************************************************************************
86 sync_display_line_structs
88 For the given LINE in window W, make the current display line equal
89 the desired display line.
90 ****************************************************************************/
92 sync_display_line_structs (struct window *w, int line, int do_blocks,
93 display_line_dynarr *cdla,
94 display_line_dynarr *ddla)
96 int cdla_len = Dynarr_length (cdla);
98 struct display_line dl, *clp, *dlp;
101 dlp = Dynarr_atp (ddla, line);
102 if (line >= Dynarr_largest (cdla))
105 clp->display_blocks = Dynarr_new (display_block);
109 clp = Dynarr_atp (cdla, line);
110 if (clp->display_blocks)
111 Dynarr_reset (clp->display_blocks);
112 if (clp->left_glyphs)
114 Dynarr_free (clp->left_glyphs);
115 clp->left_glyphs = 0;
117 if (clp->right_glyphs)
119 Dynarr_free (clp->right_glyphs);
120 clp->right_glyphs = 0;
124 display_block_dynarr *tdb = clp->display_blocks;
126 memcpy (clp, dlp, sizeof (struct display_line));
127 clp->display_blocks = tdb;
128 clp->left_glyphs = 0;
129 clp->right_glyphs = 0;
132 if (!do_blocks && line >= cdla_len)
134 Dynarr_add (cdla, *clp);
138 for (db_elt = 0; db_elt < Dynarr_length (dlp->display_blocks); db_elt++)
140 struct display_block db, *cdb;
141 struct display_block *ddb = Dynarr_atp (dlp->display_blocks, db_elt);
143 if (db_elt >= Dynarr_largest (clp->display_blocks))
146 memcpy (cdb, ddb, sizeof (struct display_block));
147 cdb->runes = Dynarr_new (rune);
148 Dynarr_add (clp->display_blocks, *cdb);
154 cdb = Dynarr_atp (clp->display_blocks, db_elt);
156 memcpy (cdb, ddb, sizeof (struct display_block));
158 Dynarr_increment (clp->display_blocks);
161 sync_rune_structs (w, cdb->runes, ddb->runes);
164 if (line >= cdla_len)
165 Dynarr_add (cdla, *clp);
168 /*****************************************************************************
171 Compare to runes to see if each of their fields is equal. If so,
172 return true otherwise return false.
173 ****************************************************************************/
175 compare_runes (struct window *w, struct rune *crb, struct rune *drb)
177 /* Do not compare the values of bufpos and endpos. They do not
178 affect the display characteristics. */
180 if ((crb->findex != drb->findex) ||
181 (WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
183 else if (crb->xpos != drb->xpos)
185 else if (crb->width != drb->width)
187 else if (crb->cursor_type != drb->cursor_type)
189 else if (crb->type != drb->type)
191 else if (crb->type == RUNE_CHAR &&
192 (crb->object.chr.ch != drb->object.chr.ch))
194 else if (crb->type == RUNE_DGLYPH &&
195 (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) ||
196 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) ||
197 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset))
199 else if (crb->type == RUNE_HLINE &&
200 (crb->object.hline.thickness != drb->object.hline.thickness ||
201 crb->object.hline.yoffset != drb->object.hline.yoffset))
207 /*****************************************************************************
208 get_next_display_block
210 Return the next display starting at or overlapping START_POS. Return
211 the start of the next region in NEXT_START.
212 ****************************************************************************/
214 get_next_display_block (layout_bounds bounds, display_block_dynarr *dba,
215 int start_pos, int *next_start)
217 int next_display_block = NO_BLOCK;
221 /* If we don't find a display block covering or starting at
222 start_pos, then we return the starting point of the next display
223 block or the next division boundary, whichever is closer to
227 if (start_pos >= bounds.left_out && start_pos < bounds.left_in)
228 *next_start = bounds.left_in;
229 else if (start_pos < bounds.left_white)
230 *next_start = bounds.left_white;
231 else if (start_pos < bounds.right_white)
232 *next_start = bounds.right_white;
233 else if (start_pos < bounds.right_in)
234 *next_start = bounds.right_in;
235 else if (start_pos <= bounds.right_out)
236 *next_start = bounds.right_out;
241 for (block = 0; block < Dynarr_length (dba); block++)
243 struct display_block *db = Dynarr_atp (dba, block);
245 if (db->start_pos <= start_pos && db->end_pos > start_pos)
247 if ((int) db->type > priority)
250 next_display_block = block;
252 *next_start = db->end_pos;
255 else if (next_start && db->start_pos > start_pos)
257 if (db->start_pos < *next_start)
258 *next_start = db->start_pos;
262 return next_display_block;
265 /*****************************************************************************
266 get_cursor_size_and_location
268 Return the information defining the pixel location of the cursor.
269 ****************************************************************************/
271 get_cursor_size_and_location (struct window *w, struct display_block *db,
273 int *cursor_start, int *cursor_width,
278 int defheight, defwidth;
280 if (Dynarr_length (db->runes) <= cursor_location)
283 XSETWINDOW (window, w);
285 rb = Dynarr_atp (db->runes, cursor_location);
286 *cursor_start = rb->xpos;
288 default_face_height_and_width (window, &defheight, &defwidth);
289 *cursor_height = defheight;
291 if (rb->type == RUNE_BLANK)
292 *cursor_width = defwidth;
294 *cursor_width = rb->width;
297 /*****************************************************************************
298 compare_display_blocks
300 Given two display blocks, output only those areas where they differ.
301 ****************************************************************************/
303 compare_display_blocks (struct window *w, struct display_line *cdl,
304 struct display_line *ddl, int c_block, int d_block,
305 int start_pixpos, int cursor_start, int cursor_width,
308 struct frame *f = XFRAME (w->frame);
309 struct display_block *cdb, *ddb;
315 cdb = Dynarr_atp (cdl->display_blocks, c_block);
316 ddb = Dynarr_atp (ddl->display_blocks, d_block);
318 assert (cdb->type == ddb->type);
321 stop_pos = min (Dynarr_length (cdb->runes), Dynarr_length (ddb->runes));
324 (!Dynarr_length (ddb->runes)
326 : (Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->xpos +
327 Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->width));
329 /* If the new block type is not text and the cursor status is
330 changing and it overlaps the position of this block then force a
331 full redraw of the block in order to make sure that the cursor is
333 if (ddb->type != TEXT
335 /* I'm not sure exactly what this code wants to do, but it's
336 * not right--it doesn't update when cursor_elt changes from, e.g.,
337 * 0 to 8, and the new or old cursor loc overlaps this block.
338 * I've replaced it with the more conservative test below.
339 * -dkindred@cs.cmu.edu 23-Mar-1997 */
340 && ((cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
341 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1))
342 && (ddl->cursor_elt == -1 ||
345 && (cursor_start + cursor_width) >= start_pixpos
346 && cursor_start <= block_end))
348 && (cdl->cursor_elt != ddl->cursor_elt)
353 if (f->windows_structure_changed ||
356 cdl->ypos != ddl->ypos ||
357 cdl->ascent != ddl->ascent ||
358 cdl->descent != ddl->descent ||
359 cdl->clip != ddl->clip ||
369 while (start_pos < 0 && elt < stop_pos)
371 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
372 Dynarr_atp (ddb->runes, elt)))
382 /* If nothing has changed in the area where the blocks overlap, but
383 there are new blocks in the desired block, then adjust the start
384 point accordingly. */
385 if (elt == stop_pos && stop_pos < Dynarr_length (ddb->runes))
386 start_pos = stop_pos;
391 if ((Dynarr_length (ddb->runes) != Dynarr_length (cdb->runes))
394 stop_pos = Dynarr_length (ddb->runes);
398 /* If the lines have the same number of runes and we are not
399 forcing a full redraw because the display line has
400 changed position then we try and optimize how much of the
401 line we actually redraw by scanning backwards from the
402 end for the first changed rune. This optimization is
403 almost always triggered by face changes. */
405 int elt = Dynarr_length (ddb->runes) - 1;
407 while (elt > start_pos)
409 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
410 Dynarr_atp (ddb->runes, elt)))
418 redisplay_output_display_block (w, ddl, d_block, start_pos,
419 stop_pos, start_pixpos,
420 cursor_start, cursor_width,
428 /*****************************************************************************
431 Clear the lefthand outside border.
432 ****************************************************************************/
434 clear_left_border (struct window *w, int y, int height)
436 struct frame *f = XFRAME (w->frame);
439 XSETWINDOW (window, w);
440 redisplay_clear_region (window, DEFAULT_INDEX,
441 FRAME_LEFT_BORDER_START (f), y,
442 FRAME_BORDER_WIDTH (f), height);
445 /*****************************************************************************
448 Clear the righthand outside border.
449 ****************************************************************************/
451 clear_right_border (struct window *w, int y, int height)
453 struct frame *f = XFRAME (w->frame);
456 XSETWINDOW (window, w);
457 redisplay_clear_region (window, DEFAULT_INDEX,
458 FRAME_RIGHT_BORDER_START (f),
459 y, FRAME_BORDER_WIDTH (f), height);
462 /*****************************************************************************
465 Ensure that the contents of the given display line is correct
466 on-screen. The force_ parameters are used by redisplay_move_cursor
467 to correctly update cursor locations and only cursor locations.
468 ****************************************************************************/
470 output_display_line (struct window *w, display_line_dynarr *cdla,
471 display_line_dynarr *ddla, int line, int force_start,
475 struct frame *f = XFRAME (w->frame);
476 struct buffer *b = XBUFFER (w->buffer);
477 struct buffer *old_b = window_display_buffer (w);
478 struct display_line *cdl, *ddl;
479 display_block_dynarr *cdba, *ddba;
480 int start_pixpos, end_pixpos;
481 int cursor_start, cursor_width, cursor_height;
483 int force = (force_start >= 0 || force_end >= 0);
484 int clear_border = 0;
487 if (cdla && line < Dynarr_length (cdla))
489 cdl = Dynarr_atp (cdla, line);
490 cdba = cdl->display_blocks;
498 ddl = Dynarr_atp (ddla, line); /* assert line < Dynarr_length (ddla) */
499 ddba = ddl->display_blocks;
501 if (force_start >= 0 && force_start >= ddl->bounds.left_out)
502 start_pixpos = force_start;
504 start_pixpos = ddl->bounds.left_out;
506 if (force_end >= 0 && force_end < ddl->bounds.right_out)
507 end_pixpos = force_end;
509 end_pixpos = ddl->bounds.right_out;
511 /* Get the cursor parameters. */
512 if (ddl->cursor_elt != -1)
514 struct display_block *db;
516 /* If the lines cursor parameter is not -1 then it indicates
517 which rune in the TEXT block contains the cursor. This means
518 that there must be at least one display block. The TEXT
519 block, if present, must always be the first display block. */
520 assert (Dynarr_length (ddba) != 0);
522 db = Dynarr_atp (ddba, 0);
523 assert (db->type == TEXT);
525 get_cursor_size_and_location (w, db, ddl->cursor_elt, &cursor_start,
526 &cursor_width, &cursor_height);
530 cursor_start = cursor_width = cursor_height = 0;
533 /* The modeline should only have a single block and it had better be
537 /* The shadow thickness check is necessary if only the sign of
539 if (cdba && !w->shadow_thickness_changed)
541 must_sync |= compare_display_blocks (w, cdl, ddl, 0, 0,
542 start_pixpos, 0, 0, 0);
546 redisplay_output_display_block (w, ddl, 0, 0, -1, start_pixpos,
555 while (!ddl->modeline && start_pixpos < end_pixpos)
558 int next_start_pixpos;
560 block = get_next_display_block (ddl->bounds, ddba, start_pixpos,
563 /* If we didn't find a block then we should blank the area
564 between start_pos and next_start if necessary. */
565 if (block == NO_BLOCK)
567 /* We only erase those areas which were actually previously
568 covered by a display block unless the window structure
569 changed. In that case we clear all areas since the current
570 structures may actually represent a different buffer. */
571 while (start_pixpos < next_start_pixpos)
577 old_block = get_next_display_block (ddl->bounds, cdba,
578 start_pixpos, &block_end);
581 old_block = NO_BLOCK;
582 block_end = next_start_pixpos;
585 if (!cdba || old_block != NO_BLOCK || b != old_b ||
586 f->windows_structure_changed ||
589 (cdl && (cdl->ypos != ddl->ypos ||
590 cdl->ascent != ddl->ascent ||
591 cdl->descent != ddl->descent ||
592 cdl->clip != ddl->clip)))
594 int x, y, width, height;
599 y = ddl->ypos - ddl->ascent;
600 width = min (next_start_pixpos, block_end) - x;
601 height = ddl->ascent + ddl->descent - ddl->clip;
603 if (x < ddl->bounds.left_in)
604 face = Vleft_margin_face;
605 else if (x < ddl->bounds.right_in)
606 face = Vdefault_face;
607 else if (x < ddl->bounds.right_out)
608 face = Vright_margin_face;
616 XSETWINDOW (window, w);
618 /* Clear the empty area. */
619 redisplay_clear_region (window, get_builtin_face_cache_index (w, face),
620 x, y, width, height);
622 /* Mark that we should clear the border. This is
623 necessary because italic fonts may leave
624 droppings in the border. */
629 start_pixpos = min (next_start_pixpos, block_end);
634 struct display_block *cdb, *ddb;
639 old_block = get_next_display_block (ddl->bounds, cdba,
640 start_pixpos, &block_end);
642 old_block = NO_BLOCK;
644 ddb = Dynarr_atp (ddba, block);
645 cdb = (old_block != NO_BLOCK ? Dynarr_atp (cdba, old_block) : 0);
647 /* If there was formerly no block over the current
648 region or if it was a block of a different type, then
649 output the entire ddb. Otherwise, compare cdb and
650 ddb and output only the changed region. */
651 if (!force && cdb && ddb->type == cdb->type && b == old_b)
653 must_sync |= compare_display_blocks (w, cdl, ddl, old_block,
655 cursor_start, cursor_width,
664 for (elt = 0; elt < Dynarr_length (ddb->runes); elt++)
666 struct rune *rb = Dynarr_atp (ddb->runes, elt);
668 if (start_pixpos >= rb->xpos
669 && start_pixpos < rb->xpos + rb->width)
672 if (end_pixpos > rb->xpos
673 && end_pixpos <= rb->xpos + rb->width)
676 if (last_elt > Dynarr_length (ddb->runes))
677 last_elt = Dynarr_length (ddb->runes);
683 redisplay_output_display_block (w, ddl, block, first_elt,
686 cursor_start, cursor_width,
690 start_pixpos = next_start_pixpos;
694 /* Clear the internal border if we are next to it and the window
695 structure or frame size has changed or if something caused
696 clear_border to be tripped. */
697 /* #### Doing this on f->clear sucks but is necessary because of
698 window-local background values. */
699 if (f->windows_structure_changed || f->faces_changed || clear_border
702 int y = ddl->ypos - ddl->ascent;
703 int height = ddl->ascent + ddl->descent - ddl->clip;
707 y -= MODELINE_SHADOW_THICKNESS (w);
708 height += (2 * MODELINE_SHADOW_THICKNESS (w));
711 if (window_is_leftmost (w))
712 clear_left_border (w, y, height);
713 if (window_is_rightmost (w))
714 clear_right_border (w, y, height);
718 sync_display_line_structs (w, line, must_sync, cdla, ddla);
721 /*****************************************************************************
722 redisplay_move_cursor
724 For the given window W, move the cursor to NEW_POINT. Returns a
725 boolean indicating success or failure.
726 ****************************************************************************/
728 #define ADJ_BUFPOS (rb->bufpos + dl->offset)
729 #define ADJ_ENDPOS (rb->endpos + dl->offset)
732 redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
734 struct frame *f = XFRAME (w->frame);
735 struct device *d = XDEVICE (f->device);
737 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
738 struct display_line *dl;
739 struct display_block *db;
741 int x = w->last_point_x[CURRENT_DISP];
742 int y = w->last_point_y[CURRENT_DISP];
745 * Bail if cursor_in_echo_area is non-zero and we're fiddling with
746 * the cursor in a non-active minibuffer window, since that is a
747 * special case that is handled elsewhere and this function need
748 * not handle it. Return 1 so the caller will assume we
751 if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
752 w != XWINDOW (FRAME_SELECTED_WINDOW (f)))
755 if (y < 0 || y >= Dynarr_length (cla))
758 dl = Dynarr_atp (cla, y);
759 db = get_display_block_from_line (dl, TEXT);
761 if (x < 0 || x >= Dynarr_length (db->runes))
764 rb = Dynarr_atp (db->runes, x);
766 if (rb->cursor_type == CURSOR_OFF)
768 else if (ADJ_BUFPOS == new_point
769 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
770 && (new_point <= ADJ_ENDPOS)))
772 w->last_point_x[CURRENT_DISP] = x;
773 w->last_point_y[CURRENT_DISP] = y;
774 Fset_marker (w->last_point[CURRENT_DISP], make_int (ADJ_BUFPOS),
781 DEVMETH (d, output_begin, (d));
783 /* #### This is a gross kludge. Cursor handling is such a royal
785 if (rb->type == RUNE_DGLYPH &&
786 (EQ (rb->object.dglyph.glyph, Vtruncation_glyph) ||
787 EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)))
788 rb->cursor_type = NO_CURSOR;
790 rb->cursor_type = CURSOR_OFF;
792 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
795 w->last_point_x[CURRENT_DISP] = -1;
796 w->last_point_y[CURRENT_DISP] = -1;
797 Fset_marker (w->last_point[CURRENT_DISP], Qnil, w->buffer);
799 /* If this isn't the selected frame, then erasing the old cursor is
800 all we actually had to do. */
801 if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d))))
804 DEVMETH (d, output_end, (d));
809 /* This should only occur in the minibuffer. */
812 w->last_point_x[CURRENT_DISP] = 0;
813 w->last_point_y[CURRENT_DISP] = y;
814 Fset_marker (w->last_point[CURRENT_DISP], Qzero, w->buffer);
816 rb = Dynarr_atp (db->runes, 0);
817 rb->cursor_type = CURSOR_ON;
820 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
823 DEVMETH (d, output_end, (d));
832 if (ADJ_BUFPOS < new_point)
838 else /* (rb->bufpos + dl->offset) > new_point */
855 while ((up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0)))
857 dl = Dynarr_atp (cla, cur_dl);
858 db = get_display_block_from_line (dl, TEXT);
861 cur_rb = Dynarr_length (db->runes) - 1;
863 while ((!scroll_on_clipped_lines || !dl->clip) &&
864 (up ? (cur_rb < Dynarr_length (db->runes)) : (cur_rb >= 0)))
866 rb = Dynarr_atp (db->runes, cur_rb);
868 if (rb->cursor_type != IGNORE_CURSOR
869 && rb->cursor_type != NO_CURSOR &&
870 (ADJ_BUFPOS == new_point
871 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
872 && (new_point <= ADJ_BUFPOS))))
874 rb->cursor_type = CURSOR_ON;
875 dl->cursor_elt = cur_rb;
878 output_display_line (w, 0, cla, cur_dl, rb->xpos,
879 rb->xpos + rb->width);
881 w->last_point_x[CURRENT_DISP] = cur_rb;
882 w->last_point_y[CURRENT_DISP] = cur_dl;
883 Fset_marker (w->last_point[CURRENT_DISP],
884 make_int (ADJ_BUFPOS), w->buffer);
887 DEVMETH (d, output_end, (d));
891 (up ? cur_rb++ : cur_rb--);
894 (up ? (cur_rb = 0) : (first = 0));
895 (up ? cur_dl++ : cur_dl--);
900 DEVMETH (d, output_end, (d));
906 /*****************************************************************************
907 redraw_cursor_in_window
909 For the given window W, redraw the cursor if it is contained within
911 ****************************************************************************/
913 redraw_cursor_in_window (struct window *w, int run_end_begin_meths)
915 struct frame *f = XFRAME (w->frame);
916 struct device *d = XDEVICE (f->device);
918 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
919 struct display_line *dl;
920 struct display_block *db;
923 int x = w->last_point_x[CURRENT_DISP];
924 int y = w->last_point_y[CURRENT_DISP];
926 if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
927 !echo_area_active (f) && minibuf_level == 0)
929 MAYBE_DEVMETH (d, set_final_cursor_coords, (f, w->pixel_top, 0));
932 if (y < 0 || y >= Dynarr_length (dla))
935 if (MINI_WINDOW_P (w) && f != device_selected_frame (d) &&
936 !is_surrogate_for_selected_frame (f))
939 dl = Dynarr_atp (dla, y);
940 db = get_display_block_from_line (dl, TEXT);
942 if (x < 0 || x >= Dynarr_length (db->runes))
945 rb = Dynarr_atp (db->runes, x);
947 /* Don't call the output routine if the block isn't actually the
949 if (rb->cursor_type == CURSOR_ON)
951 MAYBE_DEVMETH (d, set_final_cursor_coords,
952 (f, dl->ypos - 1, rb->xpos));
954 if (run_end_begin_meths)
955 DEVMETH (d, output_begin, (d));
957 output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width);
959 if (run_end_begin_meths)
960 DEVMETH (d, output_end, (d));
964 /*****************************************************************************
965 redisplay_redraw_cursor
967 For the given frame F, redraw the cursor on the selected window.
968 This is used to update the cursor after focus changes.
969 ****************************************************************************/
971 redisplay_redraw_cursor (struct frame *f, int run_end_begin_meths)
975 if (!cursor_in_echo_area)
976 window = FRAME_SELECTED_WINDOW (f);
977 else if (FRAME_HAS_MINIBUF_P (f))
978 window = FRAME_MINIBUF_WINDOW (f);
982 redraw_cursor_in_window (XWINDOW (window), run_end_begin_meths);
985 /****************************************************************************
986 redisplay_output_display_block
988 Given a display line, a block number for that start line, output all
989 runes between start and end in the specified display block.
990 ****************************************************************************/
992 redisplay_output_display_block (struct window *w, struct display_line *dl, int block,
993 int start, int end, int start_pixpos, int cursor_start,
994 int cursor_width, int cursor_height)
996 struct frame *f = XFRAME (w->frame);
997 struct device *d = XDEVICE (f->device);
999 DEVMETH (d, output_display_block, (w, dl, block, start,
1001 cursor_start, cursor_width,
1005 /****************************************************************************
1006 redisplay_unmap_subwindows
1008 Remove subwindows from the area in the box defined by the given
1010 ****************************************************************************/
1011 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height)
1015 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
1017 struct subwindow_cachel *cachel =
1018 Dynarr_atp (f->subwindow_cachels, elt);
1020 if (cachel->being_displayed
1022 cachel->x + cachel->width > x && cachel->x < x + width
1024 cachel->y + cachel->height > y && cachel->y < y + height)
1026 unmap_subwindow (cachel->subwindow);
1031 /****************************************************************************
1032 redisplay_unmap_subwindows_maybe
1034 Potentially subwindows from the area in the box defined by the given
1036 ****************************************************************************/
1037 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height)
1039 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1041 redisplay_unmap_subwindows (f, x, y, width, height);
1045 /****************************************************************************
1046 redisplay_output_subwindow
1049 output a subwindow. This code borrows heavily from the pixmap stuff,
1050 although is much simpler not needing to account for partial
1051 pixmaps, backgrounds etc.
1052 ****************************************************************************/
1054 redisplay_output_subwindow (struct window *w, struct display_line *dl,
1055 Lisp_Object image_instance, int xpos, int xoffset,
1056 int start_pixpos, int width, face_index findex,
1057 int cursor_start, int cursor_width, int cursor_height)
1059 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1062 int lheight = dl->ascent + dl->descent - dl->clip;
1063 int pheight = ((int) IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight ? lheight :
1064 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p));
1066 XSETWINDOW (window, w);
1068 /* Clear the area the subwindow is going into. The subwindow itself
1069 will always take care of the full width. We don't want to clear
1070 where it is going to go in order to avoid flicker. So, all we
1071 have to take care of is any area above or below the subwindow. Of
1072 course this is rubbish if the subwindow has transparent areas
1073 (for instance with frames). */
1074 /* #### We take a shortcut for now. We know that since we have
1075 subwindow_offset hardwired to 0 that the subwindow is against the top
1076 edge so all we have to worry about is below it. */
1077 if ((int) (dl->ypos - dl->ascent + pheight) <
1078 (int) (dl->ypos + dl->descent - dl->clip))
1080 int clear_x, clear_width;
1082 int clear_y = dl->ypos - dl->ascent + pheight;
1083 int clear_height = lheight - pheight;
1085 if (start_pixpos >= 0 && start_pixpos > xpos)
1087 clear_x = start_pixpos;
1088 clear_width = xpos + width - start_pixpos;
1093 clear_width = width;
1096 redisplay_clear_region (window, findex, clear_x, clear_y,
1097 clear_width, clear_height);
1100 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent,
1103 /* if we can't view the whole window we can't view any of it */
1104 if (IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight
1106 IMAGE_INSTANCE_SUBWINDOW_WIDTH (p) > width)
1108 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent,
1110 unmap_subwindow (image_instance);
1113 map_subwindow (image_instance, xpos - xoffset, dl->ypos - dl->ascent);
1116 /****************************************************************************
1117 redisplay_clear_region
1119 Clear the area in the box defined by the given parameters using the
1120 given face. This has been generalised so that subwindows can be
1121 coped with effectively.
1122 ****************************************************************************/
1124 redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y,
1125 int width, int height)
1127 struct window *w = NULL;
1128 struct frame *f = NULL;
1130 Lisp_Object background_pixmap = Qunbound;
1131 Lisp_Object fcolor = Qnil, bcolor = Qnil;
1133 if (!width || !height)
1136 if (WINDOWP (locale))
1138 w = XWINDOW (locale);
1139 f = XFRAME (w->frame);
1141 else if (FRAMEP (locale))
1144 f = XFRAME (locale);
1149 d = XDEVICE (f->device);
1151 /* if we have subwindows in the region we have to unmap them */
1152 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1154 redisplay_unmap_subwindows (f, x, y, width, height);
1157 /* #### This isn't quite right for when this function is called
1158 from the toolbar code. */
1160 /* Don't use a backing pixmap in the border area */
1161 if (x >= FRAME_LEFT_BORDER_END (f)
1162 && x < FRAME_RIGHT_BORDER_START (f)
1163 && y >= FRAME_TOP_BORDER_END (f)
1164 && y < FRAME_BOTTOM_BORDER_START (f))
1170 temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
1172 if (IMAGE_INSTANCEP (temp)
1173 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1175 /* #### maybe we could implement such that a string
1176 can be a background pixmap? */
1177 background_pixmap = temp;
1182 temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
1184 if (IMAGE_INSTANCEP (temp)
1185 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1187 background_pixmap = temp;
1192 if (!UNBOUNDP (background_pixmap) &&
1193 XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
1197 fcolor = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1198 bcolor = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1202 fcolor = FACE_FOREGROUND (Vdefault_face, locale);
1203 bcolor = FACE_BACKGROUND (Vdefault_face, locale);
1209 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
1210 FACE_BACKGROUND (Vdefault_face, locale));
1214 if (UNBOUNDP (background_pixmap))
1215 background_pixmap = Qnil;
1217 DEVMETH (d, clear_region,
1218 (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1221 /*****************************************************************************
1222 redisplay_clear_top_of_window
1224 If window is topmost, clear the internal border above it.
1225 ****************************************************************************/
1227 redisplay_clear_top_of_window (struct window *w)
1230 XSETWINDOW (window, w);
1232 if (!NILP (Fwindow_highest_p (window)))
1234 struct frame *f = XFRAME (w->frame);
1235 int x, y, width, height;
1238 width = w->pixel_width;
1240 if (window_is_leftmost (w))
1242 x -= FRAME_BORDER_WIDTH (f);
1243 width += FRAME_BORDER_WIDTH (f);
1245 if (window_is_rightmost (w))
1246 width += FRAME_BORDER_WIDTH (f);
1248 y = FRAME_TOP_BORDER_START (f) - 1;
1249 height = FRAME_BORDER_HEIGHT (f) + 1;
1251 redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
1255 /*****************************************************************************
1256 redisplay_clear_bottom_of_window
1258 Clear window from right below the last display line to right above
1259 the modeline. The calling function can limit the area actually
1260 erased by setting min_start and/or max_end to positive values.
1261 ****************************************************************************/
1263 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1264 int min_start, int max_end)
1266 struct frame *f = XFRAME (w->frame);
1267 struct device *d = XDEVICE (f->device);
1269 int ddla_len = Dynarr_length (ddla);
1271 ypos2 = WINDOW_TEXT_BOTTOM (w);
1272 #ifdef HAVE_SCROLLBARS
1273 /* This adjustment is to catch the intersection of any scrollbars. */
1274 if (f->windows_structure_changed && NILP (w->scrollbar_on_top_p))
1275 ypos2 += window_scrollbar_height (w);
1280 if (ddla_len == 1 && Dynarr_atp (ddla, 0)->modeline)
1282 ypos1 = WINDOW_TEXT_TOP (w);
1283 #ifdef HAVE_SCROLLBARS
1284 /* This adjustment is to catch the intersection of any scrollbars. */
1285 if (f->windows_structure_changed && !NILP (w->scrollbar_on_top_p))
1286 ypos1 -= window_scrollbar_height (w);
1291 struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1);
1292 ypos1 = dl->ypos + dl->descent - dl->clip;
1296 ypos1 = WINDOW_TEXT_TOP (w);
1298 /* #### See if this can be made conditional on the frame
1300 if (MINI_WINDOW_P (w))
1301 ypos2 += FRAME_BORDER_HEIGHT (f);
1303 if (min_start >= 0 && ypos1 < min_start)
1305 if (max_end >= 0 && ypos2 > max_end)
1311 DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1314 /*****************************************************************************
1315 redisplay_update_line
1317 This is used during incremental updates to update a single line and
1318 correct the offsets on all lines below it. At the moment
1319 update_values is false if we are only updating the modeline.
1320 ****************************************************************************/
1322 redisplay_update_line (struct window *w, int first_line, int last_line,
1325 struct frame *f = XFRAME (w->frame);
1326 struct device *d = XDEVICE (f->device);
1328 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1329 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
1331 DEVMETH (d, output_begin, (d));
1333 while (first_line <= last_line)
1335 Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos -
1336 Dynarr_atp (cdla, first_line)->bufpos);
1337 Charcount new_len = (Dynarr_atp (ddla, first_line)->end_bufpos -
1338 Dynarr_atp (ddla, first_line)->bufpos);
1340 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
1342 /* Output the changes. */
1343 output_display_line (w, cdla, ddla, first_line, -1, -1);
1345 /* Update the offsets. */
1348 int cur_line = first_line + 1;
1349 while (cur_line < Dynarr_length (cdla))
1351 Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len);
1352 Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len);
1357 /* Update the window_end_pos and other settings. */
1360 w->window_end_pos[CURRENT_DISP] -= (new_len - old_len);
1362 if (Dynarr_atp (ddla, first_line)->cursor_elt != -1)
1364 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
1365 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
1372 /* Update the window max line length. We have to scan the entire
1373 set of display lines otherwise we might not detect if the max is
1374 supposed to shrink. */
1379 w->max_line_len = 0;
1380 while (line < Dynarr_length (ddla))
1382 struct display_line *dl = Dynarr_atp (ddla, line);
1385 w->max_line_len = max (dl->num_chars, w->max_line_len);
1391 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
1392 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
1393 Fset_marker (w->last_point[CURRENT_DISP],
1394 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
1395 Fset_marker (w->last_start[CURRENT_DISP],
1396 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
1398 /* We don't bother updating the vertical scrollbars here. This
1399 gives us a performance increase while having minimal loss of
1400 quality to the scrollbar slider size and position since when this
1401 function is called we know that the changes to the buffer were
1402 very localized. We have to update the horizontal scrollbars,
1403 though, because this routine could cause a change which has a
1404 larger impact on their sizing. */
1405 /* #### See if we can get away with only calling this if
1406 max_line_len is greater than the window_char_width. */
1407 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS)
1409 extern int stupid_vertical_scrollbar_drag_hack;
1411 update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack);
1412 stupid_vertical_scrollbar_drag_hack = 1;
1416 /* This has to be done after we've updated the values. We don't
1417 call output_end for tty frames. Redisplay will do this after all
1418 tty windows have been updated. This cuts down on cursor
1420 if (FRAME_TTY_P (f))
1421 redisplay_redraw_cursor (f, 0);
1423 DEVMETH (d, output_end, (d));
1426 /*****************************************************************************
1427 redisplay_output_window
1429 For the given window W, ensure that the current display lines are
1430 equal to the desired display lines, outputing changes as necessary.
1432 #### Fuck me. This just isn't going to cut it for tty's. The output
1433 decisions for them must be based on the contents of the entire frame
1434 because that is how the available output capabilities think. The
1435 solution is relatively simple. Create redisplay_output_frame. This
1436 will basically merge all of the separate window display structs into
1437 a single one for the frame. This combination structure will be able
1438 to be passed to the same output_display_line which works for windows
1439 on X frames and the right things will happen. It just takes time to
1441 ****************************************************************************/
1443 redisplay_output_window (struct window *w)
1445 struct frame *f = XFRAME (w->frame);
1446 struct device *d = XDEVICE (f->device);
1448 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1449 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
1451 int cdla_len = Dynarr_length (cdla);
1452 int ddla_len = Dynarr_length (ddla);
1455 int need_to_clear_bottom = 0;
1456 int need_to_clear_start = -1;
1457 int need_to_clear_end = -1;
1459 /* Backgrounds may have changed or windows may have gone away
1460 leaving dividers lying around. */
1461 if (f->faces_changed
1462 || f->windows_structure_changed
1463 || w->shadow_thickness_changed)
1464 need_to_clear_bottom = 1;
1466 /* The first thing we do is determine if we are going to need to
1467 clear the bottom of the window. We only need to do this if the
1468 bottom of the current display lines is below the bottom of the
1469 desired display lines. Note that the number of lines is
1470 irrelevant. Only the position matters. We also clear to the
1471 bottom of the window if the modeline has shifted position. */
1472 /* #### We can't blindly not clear the bottom if f->clear is true
1473 since there might be a window-local background. However, for
1474 those cases where there isn't, clearing the end of the window in
1476 if (!need_to_clear_bottom)
1478 struct display_line *cdl, *ddl;
1480 /* If the modeline has changed position or size, clear the bottom
1482 if (!need_to_clear_bottom)
1487 cdl = Dynarr_atp (cdla, 0);
1489 ddl = Dynarr_atp (ddla, 0);
1492 need_to_clear_bottom = 1;
1493 else if ((!cdl->modeline && ddl->modeline)
1494 || (cdl->modeline && !ddl->modeline))
1495 need_to_clear_bottom = 1;
1496 else if (cdl->ypos != ddl->ypos ||
1497 cdl->ascent != ddl->ascent ||
1498 cdl->descent != ddl->descent ||
1499 cdl->clip != ddl->clip)
1500 need_to_clear_bottom = 1;
1502 /* #### This kludge is to make sure the modeline shadows get
1503 redrawn if the modeline position shifts. */
1504 if (need_to_clear_bottom)
1505 w->shadow_thickness_changed = 1;
1508 if (!need_to_clear_bottom)
1513 cdl = Dynarr_atp (cdla, cdla_len - 1);
1515 ddl = Dynarr_atp (ddla, ddla_len - 1);
1518 need_to_clear_bottom = 1;
1521 int cdl_bottom, ddl_bottom;
1523 cdl_bottom = cdl->ypos + cdl->descent;
1524 ddl_bottom = ddl->ypos + ddl->descent;
1526 if (cdl_bottom > ddl_bottom)
1528 need_to_clear_bottom = 1;
1529 need_to_clear_start = ddl_bottom;
1530 need_to_clear_end = cdl_bottom;
1536 /* Perform any output initialization. */
1537 DEVMETH (d, output_begin, (d));
1539 /* If the window's structure has changed clear the internal border
1540 above it if it is topmost (the function will check). */
1541 if (f->windows_structure_changed)
1542 redisplay_clear_top_of_window (w);
1544 /* Output each line. */
1545 for (line = 0; line < Dynarr_length (ddla); line++)
1547 output_display_line (w, cdla, ddla, line, -1, -1);
1550 /* If the number of display lines has shrunk, adjust. */
1551 if (cdla_len > ddla_len)
1553 Dynarr_length (cdla) = ddla_len;
1556 /* Output a vertical divider between windows, if necessary. */
1557 if (window_needs_vertical_divider (w)
1558 && (f->windows_structure_changed || f->clear))
1560 DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
1563 /* Clear the rest of the window, if necessary. */
1564 if (need_to_clear_bottom)
1566 redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start,
1570 w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP];
1571 Fset_marker (w->start[CURRENT_DISP],
1572 make_int (marker_position (w->start[DESIRED_DISP])),
1574 Fset_marker (w->pointm[CURRENT_DISP],
1575 make_int (marker_position (w->pointm[DESIRED_DISP])),
1577 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
1578 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
1579 Fset_marker (w->last_start[CURRENT_DISP],
1580 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
1581 Fset_marker (w->last_point[CURRENT_DISP],
1582 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
1583 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
1584 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
1585 w->shadow_thickness_changed = 0;
1587 set_window_display_buffer (w, XBUFFER (w->buffer));
1588 find_window_mirror (w)->truncate_win = window_truncation_on (w);
1590 /* Overkill on invalidating the cache. It is very bad for it to not
1591 get invalidated when it should be. */
1592 INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
1594 /* We don't call output_end for tty frames. Redisplay will do this
1595 after all tty windows have been updated. This cuts down on
1597 if (FRAME_TTY_P (f))
1598 redisplay_redraw_cursor (f, 0);
1600 DEVMETH (d, output_end, (d));
1602 #ifdef HAVE_SCROLLBARS
1603 update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);