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)
605 findex = ddl->left_margin_findex ?
606 ddl->left_margin_findex
607 : get_builtin_face_cache_index (w, Vleft_margin_face);
609 else if (x < ddl->bounds.right_in)
611 /* no check here because DEFAULT_INDEX == 0 anyway */
612 findex = ddl->default_findex;
614 else if (x < ddl->bounds.right_out)
616 findex = ddl->right_margin_findex ?
617 ddl->right_margin_findex
618 : get_builtin_face_cache_index (w, Vright_margin_face);
621 findex = (face_index) -1;
623 if (findex != (face_index) -1)
627 XSETWINDOW (window, w);
629 /* Clear the empty area. */
630 redisplay_clear_region (window, findex, x, y, width, height);
632 /* Mark that we should clear the border. This is
633 necessary because italic fonts may leave
634 droppings in the border. */
639 start_pixpos = min (next_start_pixpos, block_end);
644 struct display_block *cdb, *ddb;
649 old_block = get_next_display_block (ddl->bounds, cdba,
650 start_pixpos, &block_end);
652 old_block = NO_BLOCK;
654 ddb = Dynarr_atp (ddba, block);
655 cdb = (old_block != NO_BLOCK ? Dynarr_atp (cdba, old_block) : 0);
657 /* If there was formerly no block over the current
658 region or if it was a block of a different type, then
659 output the entire ddb. Otherwise, compare cdb and
660 ddb and output only the changed region. */
661 if (!force && cdb && ddb->type == cdb->type && b == old_b)
663 must_sync |= compare_display_blocks (w, cdl, ddl, old_block,
665 cursor_start, cursor_width,
674 for (elt = 0; elt < Dynarr_length (ddb->runes); elt++)
676 struct rune *rb = Dynarr_atp (ddb->runes, elt);
678 if (start_pixpos >= rb->xpos
679 && start_pixpos < rb->xpos + rb->width)
682 if (end_pixpos > rb->xpos
683 && end_pixpos <= rb->xpos + rb->width)
686 if (last_elt > Dynarr_length (ddb->runes))
687 last_elt = Dynarr_length (ddb->runes);
693 redisplay_output_display_block (w, ddl, block, first_elt,
696 cursor_start, cursor_width,
700 start_pixpos = next_start_pixpos;
704 /* Clear the internal border if we are next to it and the window
705 structure or frame size has changed or if something caused
706 clear_border to be tripped. */
707 /* #### Doing this on f->clear sucks but is necessary because of
708 window-local background values. */
709 if (f->windows_structure_changed || f->faces_changed || clear_border
712 int y = ddl->ypos - ddl->ascent;
713 int height = ddl->ascent + ddl->descent - ddl->clip;
717 y -= MODELINE_SHADOW_THICKNESS (w);
718 height += (2 * MODELINE_SHADOW_THICKNESS (w));
721 if (window_is_leftmost (w))
722 clear_left_border (w, y, height);
723 if (window_is_rightmost (w))
724 clear_right_border (w, y, height);
728 sync_display_line_structs (w, line, must_sync, cdla, ddla);
731 /*****************************************************************************
732 redisplay_move_cursor
734 For the given window W, move the cursor to NEW_POINT. Returns a
735 boolean indicating success or failure.
736 ****************************************************************************/
738 #define ADJ_BUFPOS (rb->bufpos + dl->offset)
739 #define ADJ_ENDPOS (rb->endpos + dl->offset)
742 redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
744 struct frame *f = XFRAME (w->frame);
745 struct device *d = XDEVICE (f->device);
747 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
748 struct display_line *dl;
749 struct display_block *db;
751 int x = w->last_point_x[CURRENT_DISP];
752 int y = w->last_point_y[CURRENT_DISP];
755 * Bail if cursor_in_echo_area is non-zero and we're fiddling with
756 * the cursor in a non-active minibuffer window, since that is a
757 * special case that is handled elsewhere and this function need
758 * not handle it. Return 1 so the caller will assume we
761 if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
762 w != XWINDOW (FRAME_SELECTED_WINDOW (f)))
765 if (y < 0 || y >= Dynarr_length (cla))
768 dl = Dynarr_atp (cla, y);
769 db = get_display_block_from_line (dl, TEXT);
771 if (x < 0 || x >= Dynarr_length (db->runes))
774 rb = Dynarr_atp (db->runes, x);
776 if (rb->cursor_type == CURSOR_OFF)
778 else if (ADJ_BUFPOS == new_point
779 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
780 && (new_point <= ADJ_ENDPOS)))
782 w->last_point_x[CURRENT_DISP] = x;
783 w->last_point_y[CURRENT_DISP] = y;
784 Fset_marker (w->last_point[CURRENT_DISP], make_int (ADJ_BUFPOS),
791 DEVMETH (d, output_begin, (d));
793 /* #### This is a gross kludge. Cursor handling is such a royal
795 if (rb->type == RUNE_DGLYPH &&
796 (EQ (rb->object.dglyph.glyph, Vtruncation_glyph) ||
797 EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)))
798 rb->cursor_type = NO_CURSOR;
800 rb->cursor_type = CURSOR_OFF;
802 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
805 w->last_point_x[CURRENT_DISP] = -1;
806 w->last_point_y[CURRENT_DISP] = -1;
807 Fset_marker (w->last_point[CURRENT_DISP], Qnil, w->buffer);
809 /* If this isn't the selected frame, then erasing the old cursor is
810 all we actually had to do. */
811 if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d))))
814 DEVMETH (d, output_end, (d));
819 /* This should only occur in the minibuffer. */
822 w->last_point_x[CURRENT_DISP] = 0;
823 w->last_point_y[CURRENT_DISP] = y;
824 Fset_marker (w->last_point[CURRENT_DISP], Qzero, w->buffer);
826 rb = Dynarr_atp (db->runes, 0);
827 rb->cursor_type = CURSOR_ON;
830 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
833 DEVMETH (d, output_end, (d));
842 if (ADJ_BUFPOS < new_point)
848 else /* (rb->bufpos + dl->offset) > new_point */
865 while ((up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0)))
867 dl = Dynarr_atp (cla, cur_dl);
868 db = get_display_block_from_line (dl, TEXT);
871 cur_rb = Dynarr_length (db->runes) - 1;
873 while ((!scroll_on_clipped_lines || !dl->clip) &&
874 (up ? (cur_rb < Dynarr_length (db->runes)) : (cur_rb >= 0)))
876 rb = Dynarr_atp (db->runes, cur_rb);
878 if (rb->cursor_type != IGNORE_CURSOR
879 && rb->cursor_type != NO_CURSOR &&
880 (ADJ_BUFPOS == new_point
881 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
882 && (new_point <= ADJ_BUFPOS))))
884 rb->cursor_type = CURSOR_ON;
885 dl->cursor_elt = cur_rb;
888 output_display_line (w, 0, cla, cur_dl, rb->xpos,
889 rb->xpos + rb->width);
891 w->last_point_x[CURRENT_DISP] = cur_rb;
892 w->last_point_y[CURRENT_DISP] = cur_dl;
893 Fset_marker (w->last_point[CURRENT_DISP],
894 make_int (ADJ_BUFPOS), w->buffer);
897 DEVMETH (d, output_end, (d));
901 (up ? cur_rb++ : cur_rb--);
904 (up ? (cur_rb = 0) : (first = 0));
905 (up ? cur_dl++ : cur_dl--);
910 DEVMETH (d, output_end, (d));
916 /*****************************************************************************
917 redraw_cursor_in_window
919 For the given window W, redraw the cursor if it is contained within
921 ****************************************************************************/
923 redraw_cursor_in_window (struct window *w, int run_end_begin_meths)
925 struct frame *f = XFRAME (w->frame);
926 struct device *d = XDEVICE (f->device);
928 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
929 struct display_line *dl;
930 struct display_block *db;
933 int x = w->last_point_x[CURRENT_DISP];
934 int y = w->last_point_y[CURRENT_DISP];
936 if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
937 !echo_area_active (f) && minibuf_level == 0)
939 MAYBE_DEVMETH (d, set_final_cursor_coords, (f, w->pixel_top, 0));
942 if (y < 0 || y >= Dynarr_length (dla))
945 if (MINI_WINDOW_P (w) && f != device_selected_frame (d) &&
946 !is_surrogate_for_selected_frame (f))
949 dl = Dynarr_atp (dla, y);
950 db = get_display_block_from_line (dl, TEXT);
952 if (x < 0 || x >= Dynarr_length (db->runes))
955 rb = Dynarr_atp (db->runes, x);
957 /* Don't call the output routine if the block isn't actually the
959 if (rb->cursor_type == CURSOR_ON)
961 MAYBE_DEVMETH (d, set_final_cursor_coords,
962 (f, dl->ypos - 1, rb->xpos));
964 if (run_end_begin_meths)
965 DEVMETH (d, output_begin, (d));
967 output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width);
969 if (run_end_begin_meths)
970 DEVMETH (d, output_end, (d));
974 /*****************************************************************************
975 redisplay_redraw_cursor
977 For the given frame F, redraw the cursor on the selected window.
978 This is used to update the cursor after focus changes.
979 ****************************************************************************/
981 redisplay_redraw_cursor (struct frame *f, int run_end_begin_meths)
985 if (!cursor_in_echo_area)
986 window = FRAME_SELECTED_WINDOW (f);
987 else if (FRAME_HAS_MINIBUF_P (f))
988 window = FRAME_MINIBUF_WINDOW (f);
992 redraw_cursor_in_window (XWINDOW (window), run_end_begin_meths);
995 /****************************************************************************
996 redisplay_output_display_block
998 Given a display line, a block number for that start line, output all
999 runes between start and end in the specified display block.
1000 ****************************************************************************/
1002 redisplay_output_display_block (struct window *w, struct display_line *dl, int block,
1003 int start, int end, int start_pixpos, int cursor_start,
1004 int cursor_width, int cursor_height)
1006 struct frame *f = XFRAME (w->frame);
1007 struct device *d = XDEVICE (f->device);
1009 DEVMETH (d, output_display_block, (w, dl, block, start,
1011 cursor_start, cursor_width,
1015 /****************************************************************************
1016 redisplay_unmap_subwindows
1018 Remove subwindows from the area in the box defined by the given
1020 ****************************************************************************/
1021 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height)
1025 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
1027 struct subwindow_cachel *cachel =
1028 Dynarr_atp (f->subwindow_cachels, elt);
1030 if (cachel->being_displayed
1032 cachel->x + cachel->width > x && cachel->x < x + width
1034 cachel->y + cachel->height > y && cachel->y < y + height)
1036 unmap_subwindow (cachel->subwindow);
1041 /****************************************************************************
1042 redisplay_unmap_subwindows_maybe
1044 Potentially subwindows from the area in the box defined by the given
1046 ****************************************************************************/
1047 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height)
1049 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1051 redisplay_unmap_subwindows (f, x, y, width, height);
1055 /****************************************************************************
1056 redisplay_output_subwindow
1059 output a subwindow. This code borrows heavily from the pixmap stuff,
1060 although is much simpler not needing to account for partial
1061 pixmaps, backgrounds etc.
1062 ****************************************************************************/
1064 redisplay_output_subwindow (struct window *w, struct display_line *dl,
1065 Lisp_Object image_instance, int xpos, int xoffset,
1066 int start_pixpos, int width, face_index findex,
1067 int cursor_start, int cursor_width, int cursor_height)
1069 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1072 int lheight = dl->ascent + dl->descent - dl->clip;
1073 int pheight = ((int) IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight ? lheight :
1074 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p));
1076 XSETWINDOW (window, w);
1078 /* Clear the area the subwindow is going into. The subwindow itself
1079 will always take care of the full width. We don't want to clear
1080 where it is going to go in order to avoid flicker. So, all we
1081 have to take care of is any area above or below the subwindow. Of
1082 course this is rubbish if the subwindow has transparent areas
1083 (for instance with frames). */
1084 /* #### We take a shortcut for now. We know that since we have
1085 subwindow_offset hardwired to 0 that the subwindow is against the top
1086 edge so all we have to worry about is below it. */
1087 if ((int) (dl->ypos - dl->ascent + pheight) <
1088 (int) (dl->ypos + dl->descent - dl->clip))
1090 int clear_x, clear_width;
1092 int clear_y = dl->ypos - dl->ascent + pheight;
1093 int clear_height = lheight - pheight;
1095 if (start_pixpos >= 0 && start_pixpos > xpos)
1097 clear_x = start_pixpos;
1098 clear_width = xpos + width - start_pixpos;
1103 clear_width = width;
1106 redisplay_clear_region (window, findex, clear_x, clear_y,
1107 clear_width, clear_height);
1110 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent,
1113 /* if we can't view the whole window we can't view any of it */
1114 if (IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight
1116 IMAGE_INSTANCE_SUBWINDOW_WIDTH (p) > width)
1118 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent,
1120 unmap_subwindow (image_instance);
1123 map_subwindow (image_instance, xpos - xoffset, dl->ypos - dl->ascent);
1126 /****************************************************************************
1127 redisplay_clear_region
1129 Clear the area in the box defined by the given parameters using the
1130 given face. This has been generalised so that subwindows can be
1131 coped with effectively.
1132 ****************************************************************************/
1134 redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y,
1135 int width, int height)
1137 struct window *w = NULL;
1138 struct frame *f = NULL;
1140 Lisp_Object background_pixmap = Qunbound;
1141 Lisp_Object fcolor = Qnil, bcolor = Qnil;
1143 if (!width || !height)
1146 if (WINDOWP (locale))
1148 w = XWINDOW (locale);
1149 f = XFRAME (w->frame);
1151 else if (FRAMEP (locale))
1154 f = XFRAME (locale);
1159 d = XDEVICE (f->device);
1161 /* if we have subwindows in the region we have to unmap them */
1162 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1164 redisplay_unmap_subwindows (f, x, y, width, height);
1167 /* #### This isn't quite right for when this function is called
1168 from the toolbar code. */
1170 /* Don't use a backing pixmap in the border area */
1171 if (x >= FRAME_LEFT_BORDER_END (f)
1172 && x < FRAME_RIGHT_BORDER_START (f)
1173 && y >= FRAME_TOP_BORDER_END (f)
1174 && y < FRAME_BOTTOM_BORDER_START (f))
1180 temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
1182 if (IMAGE_INSTANCEP (temp)
1183 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1185 /* #### maybe we could implement such that a string
1186 can be a background pixmap? */
1187 background_pixmap = temp;
1192 temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
1194 if (IMAGE_INSTANCEP (temp)
1195 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1197 background_pixmap = temp;
1202 if (!UNBOUNDP (background_pixmap) &&
1203 XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
1207 fcolor = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1208 bcolor = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1212 fcolor = FACE_FOREGROUND (Vdefault_face, locale);
1213 bcolor = FACE_BACKGROUND (Vdefault_face, locale);
1219 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
1220 FACE_BACKGROUND (Vdefault_face, locale));
1224 if (UNBOUNDP (background_pixmap))
1225 background_pixmap = Qnil;
1227 DEVMETH (d, clear_region,
1228 (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1231 /*****************************************************************************
1232 redisplay_clear_top_of_window
1234 If window is topmost, clear the internal border above it.
1235 ****************************************************************************/
1237 redisplay_clear_top_of_window (struct window *w)
1240 XSETWINDOW (window, w);
1242 if (!NILP (Fwindow_highest_p (window)))
1244 struct frame *f = XFRAME (w->frame);
1245 int x, y, width, height;
1248 width = w->pixel_width;
1250 if (window_is_leftmost (w))
1252 x -= FRAME_BORDER_WIDTH (f);
1253 width += FRAME_BORDER_WIDTH (f);
1255 if (window_is_rightmost (w))
1256 width += FRAME_BORDER_WIDTH (f);
1258 y = FRAME_TOP_BORDER_START (f) - 1;
1259 height = FRAME_BORDER_HEIGHT (f) + 1;
1261 redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
1265 /*****************************************************************************
1266 redisplay_clear_to_window_end
1268 Clear the area between ypos1 and ypos2. Each margin area and the
1269 text area is handled separately since they may each have their own
1271 ****************************************************************************/
1273 redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1275 struct frame *f = XFRAME (w->frame);
1276 struct device *d = XDEVICE (f->device);
1278 if (HAS_DEVMETH_P (d, clear_to_window_end))
1279 DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1282 int height = ypos2 - ypos1;
1286 struct frame *f = XFRAME (w->frame);
1288 int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/
1289 layout_bounds bounds;
1291 bounds = calculate_display_line_boundaries (w, bflag);
1292 XSETWINDOW (window, w);
1294 if (window_is_leftmost (w))
1295 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1296 ypos1, FRAME_BORDER_WIDTH (f), height);
1298 if (bounds.left_in - bounds.left_out > 0)
1299 redisplay_clear_region (window,
1300 get_builtin_face_cache_index (w, Vleft_margin_face),
1301 bounds.left_out, ypos1,
1302 bounds.left_in - bounds.left_out, height);
1304 if (bounds.right_in - bounds.left_in > 0)
1305 redisplay_clear_region (window,
1307 bounds.left_in, ypos1,
1308 bounds.right_in - bounds.left_in, height);
1310 if (bounds.right_out - bounds.right_in > 0)
1311 redisplay_clear_region (window,
1312 get_builtin_face_cache_index (w, Vright_margin_face),
1313 bounds.right_in, ypos1,
1314 bounds.right_out - bounds.right_in, height);
1316 if (window_is_rightmost (w))
1317 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1318 ypos1, FRAME_BORDER_WIDTH (f), height);
1323 /*****************************************************************************
1324 redisplay_clear_bottom_of_window
1326 Clear window from right below the last display line to right above
1327 the modeline. The calling function can limit the area actually
1328 erased by setting min_start and/or max_end to positive values.
1329 ****************************************************************************/
1331 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1332 int min_start, int max_end)
1334 struct frame *f = XFRAME (w->frame);
1335 struct device *d = XDEVICE (f->device);
1337 int ddla_len = Dynarr_length (ddla);
1339 ypos2 = WINDOW_TEXT_BOTTOM (w);
1340 #ifdef HAVE_SCROLLBARS
1341 /* This adjustment is to catch the intersection of any scrollbars. */
1342 if (f->windows_structure_changed && NILP (w->scrollbar_on_top_p))
1343 ypos2 += window_scrollbar_height (w);
1348 if (ddla_len == 1 && Dynarr_atp (ddla, 0)->modeline)
1350 ypos1 = WINDOW_TEXT_TOP (w);
1351 #ifdef HAVE_SCROLLBARS
1352 /* This adjustment is to catch the intersection of any scrollbars. */
1353 if (f->windows_structure_changed && !NILP (w->scrollbar_on_top_p))
1354 ypos1 -= window_scrollbar_height (w);
1359 struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1);
1360 ypos1 = dl->ypos + dl->descent - dl->clip;
1364 ypos1 = WINDOW_TEXT_TOP (w);
1366 /* #### See if this can be made conditional on the frame
1368 if (MINI_WINDOW_P (w))
1369 ypos2 += FRAME_BORDER_HEIGHT (f);
1371 if (min_start >= 0 && ypos1 < min_start)
1373 if (max_end >= 0 && ypos2 > max_end)
1379 redisplay_clear_to_window_end (w, ypos1, ypos2);
1382 /*****************************************************************************
1383 redisplay_update_line
1385 This is used during incremental updates to update a single line and
1386 correct the offsets on all lines below it. At the moment
1387 update_values is false if we are only updating the modeline.
1388 ****************************************************************************/
1390 redisplay_update_line (struct window *w, int first_line, int last_line,
1393 struct frame *f = XFRAME (w->frame);
1394 struct device *d = XDEVICE (f->device);
1396 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1397 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
1399 DEVMETH (d, output_begin, (d));
1401 while (first_line <= last_line)
1403 Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos -
1404 Dynarr_atp (cdla, first_line)->bufpos);
1405 Charcount new_len = (Dynarr_atp (ddla, first_line)->end_bufpos -
1406 Dynarr_atp (ddla, first_line)->bufpos);
1408 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
1410 /* Output the changes. */
1411 output_display_line (w, cdla, ddla, first_line, -1, -1);
1413 /* Update the offsets. */
1416 int cur_line = first_line + 1;
1417 while (cur_line < Dynarr_length (cdla))
1419 Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len);
1420 Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len);
1425 /* Update the window_end_pos and other settings. */
1428 w->window_end_pos[CURRENT_DISP] -= (new_len - old_len);
1430 if (Dynarr_atp (ddla, first_line)->cursor_elt != -1)
1432 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
1433 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
1440 /* Update the window max line length. We have to scan the entire
1441 set of display lines otherwise we might not detect if the max is
1442 supposed to shrink. */
1447 w->max_line_len = 0;
1448 while (line < Dynarr_length (ddla))
1450 struct display_line *dl = Dynarr_atp (ddla, line);
1453 w->max_line_len = max (dl->num_chars, w->max_line_len);
1459 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
1460 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
1461 Fset_marker (w->last_point[CURRENT_DISP],
1462 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
1463 Fset_marker (w->last_start[CURRENT_DISP],
1464 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
1466 /* We don't bother updating the vertical scrollbars here. This
1467 gives us a performance increase while having minimal loss of
1468 quality to the scrollbar slider size and position since when this
1469 function is called we know that the changes to the buffer were
1470 very localized. We have to update the horizontal scrollbars,
1471 though, because this routine could cause a change which has a
1472 larger impact on their sizing. */
1473 /* #### See if we can get away with only calling this if
1474 max_line_len is greater than the window_char_width. */
1475 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS)
1477 extern int stupid_vertical_scrollbar_drag_hack;
1479 update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack);
1480 stupid_vertical_scrollbar_drag_hack = 1;
1484 /* This has to be done after we've updated the values. We don't
1485 call output_end for tty frames. Redisplay will do this after all
1486 tty windows have been updated. This cuts down on cursor
1488 if (FRAME_TTY_P (f))
1489 redisplay_redraw_cursor (f, 0);
1491 DEVMETH (d, output_end, (d));
1494 /*****************************************************************************
1495 redisplay_output_window
1497 For the given window W, ensure that the current display lines are
1498 equal to the desired display lines, outputing changes as necessary.
1500 #### Fuck me. This just isn't going to cut it for tty's. The output
1501 decisions for them must be based on the contents of the entire frame
1502 because that is how the available output capabilities think. The
1503 solution is relatively simple. Create redisplay_output_frame. This
1504 will basically merge all of the separate window display structs into
1505 a single one for the frame. This combination structure will be able
1506 to be passed to the same output_display_line which works for windows
1507 on X frames and the right things will happen. It just takes time to
1509 ****************************************************************************/
1511 redisplay_output_window (struct window *w)
1513 struct frame *f = XFRAME (w->frame);
1514 struct device *d = XDEVICE (f->device);
1516 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1517 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
1519 int cdla_len = Dynarr_length (cdla);
1520 int ddla_len = Dynarr_length (ddla);
1523 int need_to_clear_bottom = 0;
1524 int need_to_clear_start = -1;
1525 int need_to_clear_end = -1;
1527 /* Backgrounds may have changed or windows may have gone away
1528 leaving dividers lying around. */
1529 if (f->faces_changed
1530 || f->windows_structure_changed
1531 || w->shadow_thickness_changed)
1532 need_to_clear_bottom = 1;
1534 /* The first thing we do is determine if we are going to need to
1535 clear the bottom of the window. We only need to do this if the
1536 bottom of the current display lines is below the bottom of the
1537 desired display lines. Note that the number of lines is
1538 irrelevant. Only the position matters. We also clear to the
1539 bottom of the window if the modeline has shifted position. */
1540 /* #### We can't blindly not clear the bottom if f->clear is true
1541 since there might be a window-local background. However, for
1542 those cases where there isn't, clearing the end of the window in
1544 if (!need_to_clear_bottom)
1546 struct display_line *cdl, *ddl;
1548 /* If the modeline has changed position or size, clear the bottom
1550 if (!need_to_clear_bottom)
1555 cdl = Dynarr_atp (cdla, 0);
1557 ddl = Dynarr_atp (ddla, 0);
1560 need_to_clear_bottom = 1;
1561 else if ((!cdl->modeline && ddl->modeline)
1562 || (cdl->modeline && !ddl->modeline))
1563 need_to_clear_bottom = 1;
1564 else if (cdl->ypos != ddl->ypos ||
1565 cdl->ascent != ddl->ascent ||
1566 cdl->descent != ddl->descent ||
1567 cdl->clip != ddl->clip)
1568 need_to_clear_bottom = 1;
1570 /* #### This kludge is to make sure the modeline shadows get
1571 redrawn if the modeline position shifts. */
1572 if (need_to_clear_bottom)
1573 w->shadow_thickness_changed = 1;
1576 if (!need_to_clear_bottom)
1581 cdl = Dynarr_atp (cdla, cdla_len - 1);
1583 ddl = Dynarr_atp (ddla, ddla_len - 1);
1586 need_to_clear_bottom = 1;
1589 int cdl_bottom, ddl_bottom;
1591 cdl_bottom = cdl->ypos + cdl->descent;
1592 ddl_bottom = ddl->ypos + ddl->descent;
1594 if (cdl_bottom > ddl_bottom)
1596 need_to_clear_bottom = 1;
1597 need_to_clear_start = ddl_bottom;
1598 need_to_clear_end = cdl_bottom;
1604 /* Perform any output initialization. */
1605 DEVMETH (d, output_begin, (d));
1607 /* If the window's structure has changed clear the internal border
1608 above it if it is topmost (the function will check). */
1609 if (f->windows_structure_changed)
1610 redisplay_clear_top_of_window (w);
1612 /* Output each line. */
1613 for (line = 0; line < Dynarr_length (ddla); line++)
1615 output_display_line (w, cdla, ddla, line, -1, -1);
1618 /* If the number of display lines has shrunk, adjust. */
1619 if (cdla_len > ddla_len)
1621 Dynarr_length (cdla) = ddla_len;
1624 /* Output a vertical divider between windows, if necessary. */
1625 if (window_needs_vertical_divider (w)
1626 && (f->windows_structure_changed || f->clear))
1628 DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
1631 /* Clear the rest of the window, if necessary. */
1632 if (need_to_clear_bottom)
1634 redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start,
1638 w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP];
1639 Fset_marker (w->start[CURRENT_DISP],
1640 make_int (marker_position (w->start[DESIRED_DISP])),
1642 Fset_marker (w->pointm[CURRENT_DISP],
1643 make_int (marker_position (w->pointm[DESIRED_DISP])),
1645 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
1646 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
1647 Fset_marker (w->last_start[CURRENT_DISP],
1648 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
1649 Fset_marker (w->last_point[CURRENT_DISP],
1650 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
1651 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
1652 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
1653 w->shadow_thickness_changed = 0;
1655 set_window_display_buffer (w, XBUFFER (w->buffer));
1656 find_window_mirror (w)->truncate_win = window_truncation_on (w);
1658 /* Overkill on invalidating the cache. It is very bad for it to not
1659 get invalidated when it should be. */
1660 INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
1662 /* We don't call output_end for tty frames. Redisplay will do this
1663 after all tty windows have been updated. This cuts down on
1665 if (FRAME_TTY_P (f))
1666 redisplay_redraw_cursor (f, 0);
1668 DEVMETH (d, output_end, (d));
1670 #ifdef HAVE_SCROLLBARS
1671 update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);
1675 /*****************************************************************************
1678 Draw a 3d border around the modeline on window W.
1679 ****************************************************************************/
1681 bevel_modeline (struct window *w, struct display_line *dl)
1683 struct frame *f = XFRAME (w->frame);
1684 struct device *d = XDEVICE (f->device);
1685 int x, y, width, height;
1686 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
1688 x = WINDOW_MODELINE_LEFT (w);
1689 width = WINDOW_MODELINE_RIGHT (w) - x;
1690 y = dl->ypos - dl->ascent - shadow_thickness;
1691 height = dl->ascent + dl->descent + 2 * shadow_thickness;
1693 if (XINT (w->modeline_shadow_thickness) < 0)
1694 shadow_thickness = - shadow_thickness;
1696 MAYBE_DEVMETH (d, bevel_area,
1697 (w, MODELINE_INDEX, x, y, width, height, shadow_thickness));