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);
45 /*****************************************************************************
48 Synchronize the given rune blocks.
49 ****************************************************************************/
51 sync_rune_structs (struct window *w, rune_dynarr *cra, rune_dynarr *dra)
54 int max_move = ((Dynarr_length (dra) > Dynarr_largest (cra))
55 ? Dynarr_largest (cra)
56 : Dynarr_length (dra));
60 /* #### Doing this directly breaks the encapsulation. But, the
61 running time of this function has a measurable impact on
62 redisplay performance so avoiding all excess overhead is a
63 good thing. Is all of this true? */
64 memcpy (cra->base, dra->base, sizeof (struct rune) * max_move);
65 Dynarr_set_size (cra, max_move);
70 for (rune_elt = max_move; rune_elt < Dynarr_length (dra); rune_elt++)
73 struct rune *drb = Dynarr_atp (dra, rune_elt);
76 memcpy (crb, drb, sizeof (struct rune));
77 Dynarr_add (cra, *crb);
81 /*****************************************************************************
82 sync_display_line_structs
84 For the given LINE in window W, make the current display line equal
85 the desired display line.
86 ****************************************************************************/
88 sync_display_line_structs (struct window *w, int line, int do_blocks,
89 display_line_dynarr *cdla,
90 display_line_dynarr *ddla)
92 int cdla_len = Dynarr_length (cdla);
94 struct display_line dl, *clp, *dlp;
97 dlp = Dynarr_atp (ddla, line);
98 if (line >= Dynarr_largest (cdla))
101 clp->display_blocks = Dynarr_new (display_block);
105 clp = Dynarr_atp (cdla, line);
106 if (clp->display_blocks)
107 Dynarr_reset (clp->display_blocks);
108 if (clp->left_glyphs)
110 Dynarr_free (clp->left_glyphs);
111 clp->left_glyphs = 0;
113 if (clp->right_glyphs)
115 Dynarr_free (clp->right_glyphs);
116 clp->right_glyphs = 0;
120 display_block_dynarr *tdb = clp->display_blocks;
122 memcpy (clp, dlp, sizeof (struct display_line));
123 clp->display_blocks = tdb;
124 clp->left_glyphs = 0;
125 clp->right_glyphs = 0;
128 if (!do_blocks && line >= cdla_len)
130 Dynarr_add (cdla, *clp);
134 for (db_elt = 0; db_elt < Dynarr_length (dlp->display_blocks); db_elt++)
136 struct display_block db, *cdb;
137 struct display_block *ddb = Dynarr_atp (dlp->display_blocks, db_elt);
139 if (db_elt >= Dynarr_largest (clp->display_blocks))
142 memcpy (cdb, ddb, sizeof (struct display_block));
143 cdb->runes = Dynarr_new (rune);
144 Dynarr_add (clp->display_blocks, *cdb);
150 cdb = Dynarr_atp (clp->display_blocks, db_elt);
152 memcpy (cdb, ddb, sizeof (struct display_block));
154 Dynarr_increment (clp->display_blocks);
157 sync_rune_structs (w, cdb->runes, ddb->runes);
160 if (line >= cdla_len)
161 Dynarr_add (cdla, *clp);
164 /*****************************************************************************
167 Compare to runes to see if each of their fields is equal. If so,
168 return true otherwise return false.
169 ****************************************************************************/
171 compare_runes (struct window *w, struct rune *crb, struct rune *drb)
173 /* Do not compare the values of bufpos and endpos. They do not
174 affect the display characteristics. */
176 if ((crb->findex != drb->findex) ||
177 (WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
179 else if (crb->xpos != drb->xpos)
181 else if (crb->width != drb->width)
183 else if (crb->cursor_type != drb->cursor_type)
185 else if (crb->type != drb->type)
187 else if (crb->type == RUNE_CHAR &&
188 (crb->object.chr.ch != drb->object.chr.ch))
190 else if (crb->type == RUNE_DGLYPH &&
191 (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) ||
192 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) ||
193 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset))
195 else if (crb->type == RUNE_HLINE &&
196 (crb->object.hline.thickness != drb->object.hline.thickness ||
197 crb->object.hline.yoffset != drb->object.hline.yoffset))
203 /*****************************************************************************
204 get_next_display_block
206 Return the next display starting at or overlapping START_POS. Return
207 the start of the next region in NEXT_START.
208 ****************************************************************************/
210 get_next_display_block (layout_bounds bounds, display_block_dynarr *dba,
211 int start_pos, int *next_start)
213 int next_display_block = NO_BLOCK;
217 /* If we don't find a display block covering or starting at
218 start_pos, then we return the starting point of the next display
219 block or the next division boundary, whichever is closer to
223 if (start_pos >= bounds.left_out && start_pos < bounds.left_in)
224 *next_start = bounds.left_in;
225 else if (start_pos < bounds.left_white)
226 *next_start = bounds.left_white;
227 else if (start_pos < bounds.right_white)
228 *next_start = bounds.right_white;
229 else if (start_pos < bounds.right_in)
230 *next_start = bounds.right_in;
231 else if (start_pos <= bounds.right_out)
232 *next_start = bounds.right_out;
237 for (block = 0; block < Dynarr_length (dba); block++)
239 struct display_block *db = Dynarr_atp (dba, block);
241 if (db->start_pos <= start_pos && db->end_pos > start_pos)
243 if ((int) db->type > priority)
246 next_display_block = block;
248 *next_start = db->end_pos;
251 else if (next_start && db->start_pos > start_pos)
253 if (db->start_pos < *next_start)
254 *next_start = db->start_pos;
258 return next_display_block;
261 /*****************************************************************************
262 get_cursor_size_and_location
264 Return the information defining the pixel location of the cursor.
265 ****************************************************************************/
267 get_cursor_size_and_location (struct window *w, struct display_block *db,
269 int *cursor_start, int *cursor_width,
274 int defheight, defwidth;
276 if (Dynarr_length (db->runes) <= cursor_location)
279 XSETWINDOW (window, w);
281 rb = Dynarr_atp (db->runes, cursor_location);
282 *cursor_start = rb->xpos;
284 default_face_height_and_width (window, &defheight, &defwidth);
285 *cursor_height = defheight;
287 if (rb->type == RUNE_BLANK)
288 *cursor_width = defwidth;
290 *cursor_width = rb->width;
293 /*****************************************************************************
294 compare_display_blocks
296 Given two display blocks, output only those areas where they differ.
297 ****************************************************************************/
299 compare_display_blocks (struct window *w, struct display_line *cdl,
300 struct display_line *ddl, int c_block, int d_block,
301 int start_pixpos, int cursor_start, int cursor_width,
304 struct frame *f = XFRAME (w->frame);
305 struct device *d = XDEVICE (f->device);
307 struct display_block *cdb, *ddb;
313 cdb = Dynarr_atp (cdl->display_blocks, c_block);
314 ddb = Dynarr_atp (ddl->display_blocks, d_block);
316 assert (cdb->type == ddb->type);
319 stop_pos = min (Dynarr_length (cdb->runes), Dynarr_length (ddb->runes));
322 (!Dynarr_length (ddb->runes)
324 : (Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->xpos +
325 Dynarr_atp (ddb->runes, Dynarr_length (ddb->runes) - 1)->width));
327 /* If the new block type is not text and the cursor status is
328 changing and it overlaps the position of this block then force a
329 full redraw of the block in order to make sure that the cursor is
331 if (ddb->type != TEXT
333 /* I'm not sure exactly what this code wants to do, but it's
334 * not right--it doesn't update when cursor_elt changes from, e.g.,
335 * 0 to 8, and the new or old cursor loc overlaps this block.
336 * I've replaced it with the more conservative test below.
337 * -dkindred@cs.cmu.edu 23-Mar-1997 */
338 && ((cdl->cursor_elt == -1 && ddl->cursor_elt != -1)
339 || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1))
340 && (ddl->cursor_elt == -1 ||
343 && (cursor_start + cursor_width) >= start_pixpos
344 && cursor_start <= block_end))
346 && (cdl->cursor_elt != ddl->cursor_elt)
351 if (f->windows_structure_changed ||
354 cdl->ypos != ddl->ypos ||
355 cdl->ascent != ddl->ascent ||
356 cdl->descent != ddl->descent ||
357 cdl->clip != ddl->clip ||
367 while (start_pos < 0 && elt < stop_pos)
369 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
370 Dynarr_atp (ddb->runes, elt)))
380 /* If nothing has changed in the area where the blocks overlap, but
381 there are new blocks in the desired block, then adjust the start
382 point accordingly. */
383 if (elt == stop_pos && stop_pos < Dynarr_length (ddb->runes))
384 start_pos = stop_pos;
389 if ((Dynarr_length (ddb->runes) != Dynarr_length (cdb->runes))
392 stop_pos = Dynarr_length (ddb->runes);
396 /* If the lines have the same number of runes and we are not
397 forcing a full redraw because the display line has
398 changed position then we try and optimize how much of the
399 line we actually redraw by scanning backwards from the
400 end for the first changed rune. This optimization is
401 almost always triggered by face changes. */
403 int elt = Dynarr_length (ddb->runes) - 1;
405 while (elt > start_pos)
407 if (!compare_runes (w, Dynarr_atp (cdb->runes, elt),
408 Dynarr_atp (ddb->runes, elt)))
416 DEVMETH (d, output_display_block, (w, ddl, d_block, start_pos,
417 stop_pos, start_pixpos,
418 cursor_start, cursor_width,
426 /*****************************************************************************
429 Clear the lefthand outside border.
430 ****************************************************************************/
432 clear_left_border (struct window *w, int y, int height)
434 struct frame *f = XFRAME (w->frame);
437 XSETWINDOW (window, w);
438 redisplay_clear_region (window, DEFAULT_INDEX,
439 FRAME_LEFT_BORDER_START (f), y,
440 FRAME_BORDER_WIDTH (f), height);
443 /*****************************************************************************
446 Clear the righthand outside border.
447 ****************************************************************************/
449 clear_right_border (struct window *w, int y, int height)
451 struct frame *f = XFRAME (w->frame);
454 XSETWINDOW (window, w);
455 redisplay_clear_region (window, DEFAULT_INDEX,
456 FRAME_RIGHT_BORDER_START (f),
457 y, FRAME_BORDER_WIDTH (f), height);
460 /*****************************************************************************
463 Ensure that the contents of the given display line is correct
464 on-screen. The force_ parameters are used by redisplay_move_cursor
465 to correctly update cursor locations and only cursor locations.
466 ****************************************************************************/
468 output_display_line (struct window *w, display_line_dynarr *cdla,
469 display_line_dynarr *ddla, int line, int force_start,
473 struct frame *f = XFRAME (w->frame);
474 struct device *d = XDEVICE (f->device);
475 struct buffer *b = XBUFFER (w->buffer);
476 struct buffer *old_b = window_display_buffer (w);
477 struct display_line *cdl, *ddl;
478 display_block_dynarr *cdba, *ddba;
479 int start_pixpos, end_pixpos;
480 int cursor_start, cursor_width, cursor_height;
482 int force = (force_start >= 0 || force_end >= 0);
483 int clear_border = 0;
486 if (cdla && line < Dynarr_length (cdla))
488 cdl = Dynarr_atp (cdla, line);
489 cdba = cdl->display_blocks;
497 ddl = Dynarr_atp (ddla, line); /* assert line < Dynarr_length (ddla) */
498 ddba = ddl->display_blocks;
500 if (force_start >= 0 && force_start >= ddl->bounds.left_out)
501 start_pixpos = force_start;
503 start_pixpos = ddl->bounds.left_out;
505 if (force_end >= 0 && force_end < ddl->bounds.right_out)
506 end_pixpos = force_end;
508 end_pixpos = ddl->bounds.right_out;
510 /* Get the cursor parameters. */
511 if (ddl->cursor_elt != -1)
513 struct display_block *db;
515 /* If the lines cursor parameter is not -1 then it indicates
516 which rune in the TEXT block contains the cursor. This means
517 that there must be at least one display block. The TEXT
518 block, if present, must always be the first display block. */
519 assert (Dynarr_length (ddba) != 0);
521 db = Dynarr_atp (ddba, 0);
522 assert (db->type == TEXT);
524 get_cursor_size_and_location (w, db, ddl->cursor_elt, &cursor_start,
525 &cursor_width, &cursor_height);
529 cursor_start = cursor_width = cursor_height = 0;
532 /* The modeline should only have a single block and it had better be
536 /* The shadow thickness check is necessary if only the sign of
538 if (cdba && !w->shadow_thickness_changed)
540 must_sync |= compare_display_blocks (w, cdl, ddl, 0, 0,
541 start_pixpos, 0, 0, 0);
545 DEVMETH (d, output_display_block, (w, ddl, 0, 0, -1, start_pixpos,
554 while (!ddl->modeline && start_pixpos < end_pixpos)
557 int next_start_pixpos;
559 block = get_next_display_block (ddl->bounds, ddba, start_pixpos,
562 /* If we didn't find a block then we should blank the area
563 between start_pos and next_start if necessary. */
564 if (block == NO_BLOCK)
566 /* We only erase those areas which were actually previously
567 covered by a display block unless the window structure
568 changed. In that case we clear all areas since the current
569 structures may actually represent a different buffer. */
570 while (start_pixpos < next_start_pixpos)
576 old_block = get_next_display_block (ddl->bounds, cdba,
577 start_pixpos, &block_end);
580 old_block = NO_BLOCK;
581 block_end = next_start_pixpos;
584 if (!cdba || old_block != NO_BLOCK || b != old_b ||
585 f->windows_structure_changed ||
588 (cdl && (cdl->ypos != ddl->ypos ||
589 cdl->ascent != ddl->ascent ||
590 cdl->descent != ddl->descent ||
591 cdl->clip != ddl->clip)))
593 int x, y, width, height;
598 y = ddl->ypos - ddl->ascent;
599 width = min (next_start_pixpos, block_end) - x;
600 height = ddl->ascent + ddl->descent - ddl->clip;
602 if (x < ddl->bounds.left_in)
603 face = Vleft_margin_face;
604 else if (x < ddl->bounds.right_in)
605 face = Vdefault_face;
606 else if (x < ddl->bounds.right_out)
607 face = Vright_margin_face;
615 XSETWINDOW (window, w);
617 /* Clear the empty area. */
618 redisplay_clear_region (window, get_builtin_face_cache_index (w, face),
619 x, y, width, height);
621 /* Mark that we should clear the border. This is
622 necessary because italic fonts may leave
623 droppings in the border. */
628 start_pixpos = min (next_start_pixpos, block_end);
633 struct display_block *cdb, *ddb;
638 old_block = get_next_display_block (ddl->bounds, cdba,
639 start_pixpos, &block_end);
641 old_block = NO_BLOCK;
643 ddb = Dynarr_atp (ddba, block);
644 cdb = (old_block != NO_BLOCK ? Dynarr_atp (cdba, old_block) : 0);
646 /* If there was formerly no block over the current
647 region or if it was a block of a different type, then
648 output the entire ddb. Otherwise, compare cdb and
649 ddb and output only the changed region. */
650 if (!force && cdb && ddb->type == cdb->type && b == old_b)
652 must_sync |= compare_display_blocks (w, cdl, ddl, old_block,
654 cursor_start, cursor_width,
663 for (elt = 0; elt < Dynarr_length (ddb->runes); elt++)
665 struct rune *rb = Dynarr_atp (ddb->runes, elt);
667 if (start_pixpos >= rb->xpos
668 && start_pixpos < rb->xpos + rb->width)
671 if (end_pixpos > rb->xpos
672 && end_pixpos <= rb->xpos + rb->width)
675 if (last_elt > Dynarr_length (ddb->runes))
676 last_elt = Dynarr_length (ddb->runes);
682 DEVMETH (d, output_display_block, (w, ddl, block, first_elt,
685 cursor_start, cursor_width,
689 start_pixpos = next_start_pixpos;
693 /* Clear the internal border if we are next to it and the window
694 structure or frame size has changed or if something caused
695 clear_border to be tripped. */
696 /* #### Doing this on f->clear sucks but is necessary because of
697 window-local background values. */
698 if (f->windows_structure_changed || f->faces_changed || clear_border
701 int y = ddl->ypos - ddl->ascent;
702 int height = ddl->ascent + ddl->descent - ddl->clip;
706 y -= MODELINE_SHADOW_THICKNESS (w);
707 height += (2 * MODELINE_SHADOW_THICKNESS (w));
710 if (window_is_leftmost (w))
711 clear_left_border (w, y, height);
712 if (window_is_rightmost (w))
713 clear_right_border (w, y, height);
717 sync_display_line_structs (w, line, must_sync, cdla, ddla);
720 /*****************************************************************************
721 redisplay_move_cursor
723 For the given window W, move the cursor to NEW_POINT. Returns a
724 boolean indicating success or failure.
725 ****************************************************************************/
727 #define ADJ_BUFPOS (rb->bufpos + dl->offset)
728 #define ADJ_ENDPOS (rb->endpos + dl->offset)
731 redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end)
733 struct frame *f = XFRAME (w->frame);
734 struct device *d = XDEVICE (f->device);
736 display_line_dynarr *cla = window_display_lines (w, CURRENT_DISP);
737 struct display_line *dl;
738 struct display_block *db;
740 int x = w->last_point_x[CURRENT_DISP];
741 int y = w->last_point_y[CURRENT_DISP];
744 * Bail if cursor_in_echo_area is non-zero and we're fiddling with
745 * the cursor in a non-active minibuffer window, since that is a
746 * special case that is handled elsewhere and this function need
747 * not handle it. Return 1 so the caller will assume we
750 if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
751 w != XWINDOW (FRAME_SELECTED_WINDOW (f)))
754 if (y < 0 || y >= Dynarr_length (cla))
757 dl = Dynarr_atp (cla, y);
758 db = get_display_block_from_line (dl, TEXT);
760 if (x < 0 || x >= Dynarr_length (db->runes))
763 rb = Dynarr_atp (db->runes, x);
765 if (rb->cursor_type == CURSOR_OFF)
767 else if (ADJ_BUFPOS == new_point
768 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
769 && (new_point <= ADJ_ENDPOS)))
771 w->last_point_x[CURRENT_DISP] = x;
772 w->last_point_y[CURRENT_DISP] = y;
773 Fset_marker (w->last_point[CURRENT_DISP], make_int (ADJ_BUFPOS),
780 DEVMETH (d, output_begin, (d));
782 /* #### This is a gross kludge. Cursor handling is such a royal
784 if (rb->type == RUNE_DGLYPH &&
785 (EQ (rb->object.dglyph.glyph, Vtruncation_glyph) ||
786 EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)))
787 rb->cursor_type = NO_CURSOR;
789 rb->cursor_type = CURSOR_OFF;
791 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
794 w->last_point_x[CURRENT_DISP] = -1;
795 w->last_point_y[CURRENT_DISP] = -1;
796 Fset_marker (w->last_point[CURRENT_DISP], Qnil, w->buffer);
798 /* If this isn't the selected frame, then erasing the old cursor is
799 all we actually had to do. */
800 if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d))))
803 DEVMETH (d, output_end, (d));
808 /* This should only occur in the minibuffer. */
811 w->last_point_x[CURRENT_DISP] = 0;
812 w->last_point_y[CURRENT_DISP] = y;
813 Fset_marker (w->last_point[CURRENT_DISP], Qzero, w->buffer);
815 rb = Dynarr_atp (db->runes, 0);
816 rb->cursor_type = CURSOR_ON;
819 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
822 DEVMETH (d, output_end, (d));
831 if (ADJ_BUFPOS < new_point)
837 else /* (rb->bufpos + dl->offset) > new_point */
854 while ((up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0)))
856 dl = Dynarr_atp (cla, cur_dl);
857 db = get_display_block_from_line (dl, TEXT);
860 cur_rb = Dynarr_length (db->runes) - 1;
862 while ((!scroll_on_clipped_lines || !dl->clip) &&
863 (up ? (cur_rb < Dynarr_length (db->runes)) : (cur_rb >= 0)))
865 rb = Dynarr_atp (db->runes, cur_rb);
867 if (rb->cursor_type != IGNORE_CURSOR
868 && rb->cursor_type != NO_CURSOR &&
869 (ADJ_BUFPOS == new_point
870 || (ADJ_ENDPOS && (new_point >= ADJ_BUFPOS)
871 && (new_point <= ADJ_BUFPOS))))
873 rb->cursor_type = CURSOR_ON;
874 dl->cursor_elt = cur_rb;
877 output_display_line (w, 0, cla, cur_dl, rb->xpos,
878 rb->xpos + rb->width);
880 w->last_point_x[CURRENT_DISP] = cur_rb;
881 w->last_point_y[CURRENT_DISP] = cur_dl;
882 Fset_marker (w->last_point[CURRENT_DISP],
883 make_int (ADJ_BUFPOS), w->buffer);
886 DEVMETH (d, output_end, (d));
890 (up ? cur_rb++ : cur_rb--);
893 (up ? (cur_rb = 0) : (first = 0));
894 (up ? cur_dl++ : cur_dl--);
899 DEVMETH (d, output_end, (d));
905 /*****************************************************************************
906 redraw_cursor_in_window
908 For the given window W, redraw the cursor if it is contained within
910 ****************************************************************************/
912 redraw_cursor_in_window (struct window *w, int run_end_begin_meths)
914 struct frame *f = XFRAME (w->frame);
915 struct device *d = XDEVICE (f->device);
917 display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP);
918 struct display_line *dl;
919 struct display_block *db;
922 int x = w->last_point_x[CURRENT_DISP];
923 int y = w->last_point_y[CURRENT_DISP];
925 if (cursor_in_echo_area && MINI_WINDOW_P (w) &&
926 !echo_area_active (f) && minibuf_level == 0)
928 MAYBE_DEVMETH (d, set_final_cursor_coords, (f, w->pixel_top, 0));
931 if (y < 0 || y >= Dynarr_length (dla))
934 if (MINI_WINDOW_P (w) && f != device_selected_frame (d) &&
935 !is_surrogate_for_selected_frame (f))
938 dl = Dynarr_atp (dla, y);
939 db = get_display_block_from_line (dl, TEXT);
941 if (x < 0 || x >= Dynarr_length (db->runes))
944 rb = Dynarr_atp (db->runes, x);
946 /* Don't call the output routine if the block isn't actually the
948 if (rb->cursor_type == CURSOR_ON)
950 MAYBE_DEVMETH (d, set_final_cursor_coords,
951 (f, dl->ypos - 1, rb->xpos));
953 if (run_end_begin_meths)
954 DEVMETH (d, output_begin, (d));
956 output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width);
958 if (run_end_begin_meths)
959 DEVMETH (d, output_end, (d));
963 /*****************************************************************************
964 redisplay_redraw_cursor
966 For the given frame F, redraw the cursor on the selected window.
967 This is used to update the cursor after focus changes.
968 ****************************************************************************/
970 redisplay_redraw_cursor (struct frame *f, int run_end_begin_meths)
974 if (!cursor_in_echo_area)
975 window = FRAME_SELECTED_WINDOW (f);
976 else if (FRAME_HAS_MINIBUF_P (f))
977 window = FRAME_MINIBUF_WINDOW (f);
981 redraw_cursor_in_window (XWINDOW (window), run_end_begin_meths);
984 /****************************************************************************
985 redisplay_unmap_subwindows
987 Remove subwindows from the area in the box defined by the given
989 ****************************************************************************/
990 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height)
994 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
996 struct subwindow_cachel *cachel =
997 Dynarr_atp (f->subwindow_cachels, elt);
999 if (cachel->being_displayed
1001 cachel->x + cachel->width > x && cachel->x < x + width
1003 cachel->y + cachel->height > y && cachel->y < y + height)
1005 unmap_subwindow (cachel->subwindow);
1010 /****************************************************************************
1011 redisplay_output_subwindow
1014 output a subwindow. This code borrows heavily from the pixmap stuff,
1015 although is much simpler not needing to account for partial
1016 pixmaps, backgrounds etc.
1017 ****************************************************************************/
1019 redisplay_output_subwindow (struct window *w, struct display_line *dl,
1020 Lisp_Object image_instance, int xpos, int xoffset,
1021 int start_pixpos, int width, face_index findex,
1022 int cursor_start, int cursor_width, int cursor_height)
1024 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1027 int lheight = dl->ascent + dl->descent - dl->clip;
1028 int pheight = ((int) IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight ? lheight :
1029 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p));
1031 XSETWINDOW (window, w);
1033 /* Clear the area the subwindow is going into. The subwindow itself
1034 will always take care of the full width. We don't want to clear
1035 where it is going to go in order to avoid flicker. So, all we
1036 have to take care of is any area above or below the subwindow. Of
1037 course this is rubbish if the subwindow has transparent areas
1038 (for instance with frames). */
1039 /* #### We take a shortcut for now. We know that since we have
1040 subwindow_offset hardwired to 0 that the subwindow is against the top
1041 edge so all we have to worry about is below it. */
1042 if ((int) (dl->ypos - dl->ascent + pheight) <
1043 (int) (dl->ypos + dl->descent - dl->clip))
1045 int clear_x, clear_width;
1047 int clear_y = dl->ypos - dl->ascent + pheight;
1048 int clear_height = lheight - pheight;
1050 if (start_pixpos >= 0 && start_pixpos > xpos)
1052 clear_x = start_pixpos;
1053 clear_width = xpos + width - start_pixpos;
1058 clear_width = width;
1061 redisplay_clear_region (window, findex, clear_x, clear_y,
1062 clear_width, clear_height);
1065 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent,
1068 /* if we can't view the whole window we can't view any of it */
1069 if (IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight
1071 IMAGE_INSTANCE_SUBWINDOW_WIDTH (p) > width)
1073 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent,
1075 unmap_subwindow (image_instance);
1078 map_subwindow (image_instance, xpos - xoffset, dl->ypos - dl->ascent);
1081 /****************************************************************************
1082 redisplay_clear_region
1084 Clear the area in the box defined by the given parameters using the
1085 given face. This has been generalised so that subwindows can be
1086 coped with effectively.
1087 ****************************************************************************/
1089 redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y,
1090 int width, int height)
1092 struct window *w = NULL;
1093 struct frame *f = NULL;
1095 Lisp_Object background_pixmap = Qunbound;
1096 Lisp_Object fcolor = Qnil, bcolor = Qnil;
1098 if (!width || !height)
1101 if (WINDOWP (locale))
1103 w = XWINDOW (locale);
1104 f = XFRAME (w->frame);
1106 else if (FRAMEP (locale))
1109 f = XFRAME (locale);
1114 d = XDEVICE (f->device);
1116 /* if we have subwindows in the region we have to unmap them */
1117 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1119 redisplay_unmap_subwindows (f, x, y, width, height);
1122 /* #### This isn't quite right for when this function is called
1123 from the toolbar code. */
1125 /* Don't use a backing pixmap in the border area */
1126 if (x >= FRAME_LEFT_BORDER_END (f)
1127 && x < FRAME_RIGHT_BORDER_START (f)
1128 && y >= FRAME_TOP_BORDER_END (f)
1129 && y < FRAME_BOTTOM_BORDER_START (f))
1135 temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
1137 if (IMAGE_INSTANCEP (temp)
1138 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1140 /* #### maybe we could implement such that a string
1141 can be a background pixmap? */
1142 background_pixmap = temp;
1147 temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
1149 if (IMAGE_INSTANCEP (temp)
1150 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1152 background_pixmap = temp;
1157 if (!UNBOUNDP (background_pixmap) &&
1158 XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
1162 fcolor = WINDOW_FACE_CACHEL_FOREGROUND (w, findex);
1163 bcolor = WINDOW_FACE_CACHEL_BACKGROUND (w, findex);
1167 fcolor = FACE_FOREGROUND (Vdefault_face, locale);
1168 bcolor = FACE_BACKGROUND (Vdefault_face, locale);
1174 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
1175 FACE_BACKGROUND (Vdefault_face, locale));
1179 if (UNBOUNDP (background_pixmap))
1180 background_pixmap = Qnil;
1182 DEVMETH (d, clear_region,
1183 (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1186 /*****************************************************************************
1187 redisplay_clear_top_of_window
1189 If window is topmost, clear the internal border above it.
1190 ****************************************************************************/
1192 redisplay_clear_top_of_window (struct window *w)
1195 XSETWINDOW (window, w);
1197 if (!NILP (Fwindow_highest_p (window)))
1199 struct frame *f = XFRAME (w->frame);
1200 int x, y, width, height;
1203 width = w->pixel_width;
1205 if (window_is_leftmost (w))
1207 x -= FRAME_BORDER_WIDTH (f);
1208 width += FRAME_BORDER_WIDTH (f);
1210 if (window_is_rightmost (w))
1211 width += FRAME_BORDER_WIDTH (f);
1213 y = FRAME_TOP_BORDER_START (f) - 1;
1214 height = FRAME_BORDER_HEIGHT (f) + 1;
1216 redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
1220 /*****************************************************************************
1221 redisplay_clear_bottom_of_window
1223 Clear window from right below the last display line to right above
1224 the modeline. The calling function can limit the area actually
1225 erased by setting min_start and/or max_end to positive values.
1226 ****************************************************************************/
1228 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1229 int min_start, int max_end)
1231 struct frame *f = XFRAME (w->frame);
1232 struct device *d = XDEVICE (f->device);
1234 int ddla_len = Dynarr_length (ddla);
1236 ypos2 = WINDOW_TEXT_BOTTOM (w);
1237 #ifdef HAVE_SCROLLBARS
1238 /* This adjustment is to catch the intersection of any scrollbars. */
1239 if (f->windows_structure_changed && NILP (w->scrollbar_on_top_p))
1240 ypos2 += window_scrollbar_height (w);
1245 if (ddla_len == 1 && Dynarr_atp (ddla, 0)->modeline)
1247 ypos1 = WINDOW_TEXT_TOP (w);
1248 #ifdef HAVE_SCROLLBARS
1249 /* This adjustment is to catch the intersection of any scrollbars. */
1250 if (f->windows_structure_changed && !NILP (w->scrollbar_on_top_p))
1251 ypos1 -= window_scrollbar_height (w);
1256 struct display_line *dl = Dynarr_atp (ddla, ddla_len - 1);
1257 ypos1 = dl->ypos + dl->descent - dl->clip;
1261 ypos1 = WINDOW_TEXT_TOP (w);
1263 /* #### See if this can be made conditional on the frame
1265 if (MINI_WINDOW_P (w))
1266 ypos2 += FRAME_BORDER_HEIGHT (f);
1268 if (min_start >= 0 && ypos1 < min_start)
1270 if (max_end >= 0 && ypos2 > max_end)
1276 DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1279 /*****************************************************************************
1280 redisplay_update_line
1282 This is used during incremental updates to update a single line and
1283 correct the offsets on all lines below it. At the moment
1284 update_values is false if we are only updating the modeline.
1285 ****************************************************************************/
1287 redisplay_update_line (struct window *w, int first_line, int last_line,
1290 struct frame *f = XFRAME (w->frame);
1291 struct device *d = XDEVICE (f->device);
1293 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1294 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
1296 DEVMETH (d, output_begin, (d));
1298 while (first_line <= last_line)
1300 Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos -
1301 Dynarr_atp (cdla, first_line)->bufpos);
1302 Charcount new_len = (Dynarr_atp (ddla, first_line)->end_bufpos -
1303 Dynarr_atp (ddla, first_line)->bufpos);
1305 assert (Dynarr_length (cdla) == Dynarr_length (ddla));
1307 /* Output the changes. */
1308 output_display_line (w, cdla, ddla, first_line, -1, -1);
1310 /* Update the offsets. */
1313 int cur_line = first_line + 1;
1314 while (cur_line < Dynarr_length (cdla))
1316 Dynarr_atp (cdla, cur_line)->offset += (new_len - old_len);
1317 Dynarr_atp (ddla, cur_line)->offset += (new_len - old_len);
1322 /* Update the window_end_pos and other settings. */
1325 w->window_end_pos[CURRENT_DISP] -= (new_len - old_len);
1327 if (Dynarr_atp (ddla, first_line)->cursor_elt != -1)
1329 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
1330 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
1337 /* Update the window max line length. We have to scan the entire
1338 set of display lines otherwise we might not detect if the max is
1339 supposed to shrink. */
1344 w->max_line_len = 0;
1345 while (line < Dynarr_length (ddla))
1347 struct display_line *dl = Dynarr_atp (ddla, line);
1350 w->max_line_len = max (dl->num_chars, w->max_line_len);
1356 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
1357 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
1358 Fset_marker (w->last_point[CURRENT_DISP],
1359 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
1360 Fset_marker (w->last_start[CURRENT_DISP],
1361 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
1363 /* We don't bother updating the vertical scrollbars here. This
1364 gives us a performance increase while having minimal loss of
1365 quality to the scrollbar slider size and position since when this
1366 function is called we know that the changes to the buffer were
1367 very localized. We have to update the horizontal scrollbars,
1368 though, because this routine could cause a change which has a
1369 larger impact on their sizing. */
1370 /* #### See if we can get away with only calling this if
1371 max_line_len is greater than the window_char_width. */
1372 #if defined(HAVE_SCROLLBARS) && defined(HAVE_X_WINDOWS)
1374 extern int stupid_vertical_scrollbar_drag_hack;
1376 update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack);
1377 stupid_vertical_scrollbar_drag_hack = 1;
1381 /* This has to be done after we've updated the values. We don't
1382 call output_end for tty frames. Redisplay will do this after all
1383 tty windows have been updated. This cuts down on cursor
1385 if (FRAME_TTY_P (f))
1386 redisplay_redraw_cursor (f, 0);
1388 DEVMETH (d, output_end, (d));
1391 /*****************************************************************************
1392 redisplay_output_window
1394 For the given window W, ensure that the current display lines are
1395 equal to the desired display lines, outputing changes as necessary.
1397 #### Fuck me. This just isn't going to cut it for tty's. The output
1398 decisions for them must be based on the contents of the entire frame
1399 because that is how the available output capabilities think. The
1400 solution is relatively simple. Create redisplay_output_frame. This
1401 will basically merge all of the separate window display structs into
1402 a single one for the frame. This combination structure will be able
1403 to be passed to the same output_display_line which works for windows
1404 on X frames and the right things will happen. It just takes time to
1406 ****************************************************************************/
1408 redisplay_output_window (struct window *w)
1410 struct frame *f = XFRAME (w->frame);
1411 struct device *d = XDEVICE (f->device);
1413 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
1414 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
1416 int cdla_len = Dynarr_length (cdla);
1417 int ddla_len = Dynarr_length (ddla);
1420 int need_to_clear_bottom = 0;
1421 int need_to_clear_start = -1;
1422 int need_to_clear_end = -1;
1424 /* Backgrounds may have changed or windows may have gone away
1425 leaving dividers lying around. */
1426 if (f->faces_changed
1427 || f->windows_structure_changed
1428 || w->shadow_thickness_changed)
1429 need_to_clear_bottom = 1;
1431 /* The first thing we do is determine if we are going to need to
1432 clear the bottom of the window. We only need to do this if the
1433 bottom of the current display lines is below the bottom of the
1434 desired display lines. Note that the number of lines is
1435 irrelevant. Only the position matters. We also clear to the
1436 bottom of the window if the modeline has shifted position. */
1437 /* #### We can't blindly not clear the bottom if f->clear is true
1438 since there might be a window-local background. However, for
1439 those cases where there isn't, clearing the end of the window in
1441 if (!need_to_clear_bottom)
1443 struct display_line *cdl, *ddl;
1445 /* If the modeline has changed position or size, clear the bottom
1447 if (!need_to_clear_bottom)
1452 cdl = Dynarr_atp (cdla, 0);
1454 ddl = Dynarr_atp (ddla, 0);
1457 need_to_clear_bottom = 1;
1458 else if ((!cdl->modeline && ddl->modeline)
1459 || (cdl->modeline && !ddl->modeline))
1460 need_to_clear_bottom = 1;
1461 else if (cdl->ypos != ddl->ypos ||
1462 cdl->ascent != ddl->ascent ||
1463 cdl->descent != ddl->descent ||
1464 cdl->clip != ddl->clip)
1465 need_to_clear_bottom = 1;
1467 /* #### This kludge is to make sure the modeline shadows get
1468 redrawn if the modeline position shifts. */
1469 if (need_to_clear_bottom)
1470 w->shadow_thickness_changed = 1;
1473 if (!need_to_clear_bottom)
1478 cdl = Dynarr_atp (cdla, cdla_len - 1);
1480 ddl = Dynarr_atp (ddla, ddla_len - 1);
1483 need_to_clear_bottom = 1;
1486 int cdl_bottom, ddl_bottom;
1488 cdl_bottom = cdl->ypos + cdl->descent;
1489 ddl_bottom = ddl->ypos + ddl->descent;
1491 if (cdl_bottom > ddl_bottom)
1493 need_to_clear_bottom = 1;
1494 need_to_clear_start = ddl_bottom;
1495 need_to_clear_end = cdl_bottom;
1501 /* Perform any output initialization. */
1502 DEVMETH (d, output_begin, (d));
1504 /* If the window's structure has changed clear the internal border
1505 above it if it is topmost (the function will check). */
1506 if (f->windows_structure_changed)
1507 redisplay_clear_top_of_window (w);
1509 /* Output each line. */
1510 for (line = 0; line < Dynarr_length (ddla); line++)
1512 output_display_line (w, cdla, ddla, line, -1, -1);
1515 /* If the number of display lines has shrunk, adjust. */
1516 if (cdla_len > ddla_len)
1518 Dynarr_length (cdla) = ddla_len;
1521 /* Output a vertical divider between windows, if necessary. */
1522 if (window_needs_vertical_divider (w)
1523 && (f->windows_structure_changed || f->clear))
1525 DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
1528 /* Clear the rest of the window, if necessary. */
1529 if (need_to_clear_bottom)
1531 redisplay_clear_bottom_of_window (w, ddla, need_to_clear_start,
1535 w->window_end_pos[CURRENT_DISP] = w->window_end_pos[DESIRED_DISP];
1536 Fset_marker (w->start[CURRENT_DISP],
1537 make_int (marker_position (w->start[DESIRED_DISP])),
1539 Fset_marker (w->pointm[CURRENT_DISP],
1540 make_int (marker_position (w->pointm[DESIRED_DISP])),
1542 w->last_modified[CURRENT_DISP] = w->last_modified[DESIRED_DISP];
1543 w->last_facechange[CURRENT_DISP] = w->last_facechange[DESIRED_DISP];
1544 Fset_marker (w->last_start[CURRENT_DISP],
1545 Fmarker_position (w->last_start[DESIRED_DISP]), w->buffer);
1546 Fset_marker (w->last_point[CURRENT_DISP],
1547 Fmarker_position (w->last_point[DESIRED_DISP]), w->buffer);
1548 w->last_point_x[CURRENT_DISP] = w->last_point_x[DESIRED_DISP];
1549 w->last_point_y[CURRENT_DISP] = w->last_point_y[DESIRED_DISP];
1550 w->shadow_thickness_changed = 0;
1552 set_window_display_buffer (w, XBUFFER (w->buffer));
1553 find_window_mirror (w)->truncate_win = window_truncation_on (w);
1555 /* Overkill on invalidating the cache. It is very bad for it to not
1556 get invalidated when it should be. */
1557 INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
1559 /* We don't call output_end for tty frames. Redisplay will do this
1560 after all tty windows have been updated. This cuts down on
1562 if (FRAME_TTY_P (f))
1563 redisplay_redraw_cursor (f, 0);
1565 DEVMETH (d, output_end, (d));
1567 #ifdef HAVE_SCROLLBARS
1568 update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);