comparison src/redisplay-output.c @ 398:74fd4e045ea6 r21-2-29

Import from CVS: tag r21-2-29
author cvs
date Mon, 13 Aug 2007 11:13:30 +0200
parents aabb7f5b1c81
children 2f8bb876ab1d
comparison
equal deleted inserted replaced
397:f4aeb21a5bad 398:74fd4e045ea6
1 /* Synchronize redisplay structures and output changes. 1 /* Synchronize redisplay structures and output changes.
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. 2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3 Copyright (C) 1995, 1996 Ben Wing. 3 Copyright (C) 1995, 1996 Ben Wing.
4 Copyright (C) 1996 Chuck Thompson. 4 Copyright (C) 1996 Chuck Thompson.
5 Copyright (C) 1999 Andy Piper.
5 6
6 This file is part of XEmacs. 7 This file is part of XEmacs.
7 8
8 XEmacs is free software; you can redistribute it and/or modify it 9 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 under the terms of the GNU General Public License as published by the
23 /* Synched up with: Not in FSF. */ 24 /* Synched up with: Not in FSF. */
24 25
25 /* This file has been Mule-ized. */ 26 /* This file has been Mule-ized. */
26 27
27 /* Author: Chuck Thompson */ 28 /* Author: Chuck Thompson */
29
30 /* Heavily hacked for modularity, gutter and subwindow support by Andy
31 Piper. */
28 32
29 #include <config.h> 33 #include <config.h>
30 #include "lisp.h" 34 #include "lisp.h"
31 35
32 #include "buffer.h" 36 #include "buffer.h"
41 struct rune *drb); 45 struct rune *drb);
42 static void redraw_cursor_in_window (struct window *w, 46 static void redraw_cursor_in_window (struct window *w,
43 int run_end_begin_glyphs); 47 int run_end_begin_glyphs);
44 static void redisplay_output_display_block (struct window *w, struct display_line *dl, 48 static void redisplay_output_display_block (struct window *w, struct display_line *dl,
45 int block, int start, int end, int start_pixpos, 49 int block, int start, int end, int start_pixpos,
46 int cursor_start, int cursor_width, 50 int cursor_start, int cursor_width,
47 int cursor_height); 51 int cursor_height);
52 static void redisplay_normalize_display_box (struct display_box* dest,
53 struct display_glyph_area* src);
54 static int redisplay_display_boxes_in_window_p (struct window* w,
55 struct display_box* db,
56 struct display_glyph_area* dga);
57 static void redisplay_clear_clipped_region (Lisp_Object locale, face_index findex,
58 struct display_box* dest,
59 struct display_glyph_area* glyphsrc,
60 int fullheight_p, Lisp_Object);
48 61
49 /***************************************************************************** 62 /*****************************************************************************
50 sync_rune_structs 63 sync_rune_structs
51 64
52 Synchronize the given rune blocks. 65 Synchronize the given rune blocks.
174 static int 187 static int
175 compare_runes (struct window *w, struct rune *crb, struct rune *drb) 188 compare_runes (struct window *w, struct rune *crb, struct rune *drb)
176 { 189 {
177 /* Do not compare the values of bufpos and endpos. They do not 190 /* Do not compare the values of bufpos and endpos. They do not
178 affect the display characteristics. */ 191 affect the display characteristics. */
192
193 /* Note: (hanoi 6) spends 95% of its time in redisplay, and about
194 30% here. Not using bitfields for rune.type alone gives a redisplay
195 speed up of 10%.
196
197 #### In profile arcs run of a normal Gnus session this function
198 is run 6.76 million times, only to return 1 in 6.73 million of
199 those.
200
201 In addition a quick look GCC sparc assembly shows that GCC is not
202 doing a good job here.
203 1. The function is not inlined (too complicated?)
204 2. It seems to be reloading the crb and drb variables all the
205 time.
206 3. It doesn't seem to notice that the second half of these if's
207 are really a switch statement.
208
209 So I (JV) conjecture
210
211 #### It would really be worth it to arrange for this function to
212 be (almost) a single call to memcmp. */
179 213
180 if ((crb->findex != drb->findex) || 214 if ((crb->findex != drb->findex) ||
181 (WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))) 215 (WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
182 return 0; 216 return 0;
183 else if (crb->xpos != drb->xpos) 217 else if (crb->xpos != drb->xpos)
189 else if (crb->type != drb->type) 223 else if (crb->type != drb->type)
190 return 0; 224 return 0;
191 else if (crb->type == RUNE_CHAR && 225 else if (crb->type == RUNE_CHAR &&
192 (crb->object.chr.ch != drb->object.chr.ch)) 226 (crb->object.chr.ch != drb->object.chr.ch))
193 return 0; 227 return 0;
228 else if (crb->type == RUNE_HLINE &&
229 (crb->object.hline.thickness != drb->object.hline.thickness ||
230 crb->object.hline.yoffset != drb->object.hline.yoffset))
231 return 0;
194 else if (crb->type == RUNE_DGLYPH && 232 else if (crb->type == RUNE_DGLYPH &&
195 (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) || 233 (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) ||
196 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) || 234 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) ||
197 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset)) 235 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset))
198 return 0; 236 return 0;
199 else if (crb->type == RUNE_HLINE && 237 /* Only check dirtiness if we know something has changed. */
200 (crb->object.hline.thickness != drb->object.hline.thickness || 238 else if (crb->type == RUNE_DGLYPH &&
201 crb->object.hline.yoffset != drb->object.hline.yoffset)) 239 XFRAME (w->frame)->glyphs_changed)
202 return 0; 240 {
241 glyph_index gindex = get_glyph_cachel_index (w, drb->object.dglyph.glyph);
242 /* Although doing the cachel lookup for every comparison is
243 very expensive.we have to do it to make sure the cache is
244 up-to-date. */
245 if (GLYPH_CACHEL_DIRTYP (w, gindex))
246 return 0;
247 else
248 return 1;
249 }
203 else 250 else
204 return 1; 251 return 1;
205 } 252 }
206 253
207 /***************************************************************************** 254 /*****************************************************************************
349 #endif 396 #endif
350 ) 397 )
351 force = 1; 398 force = 1;
352 399
353 if (f->windows_structure_changed || 400 if (f->windows_structure_changed ||
401 /* #### Why is this so? We have face cachels so that we don't
402 have to recalculate all the display blocks when faces
403 change. I have fixed this for glyphs and am inclined to think
404 that faces should "Just Work", but I'm not feeling brave
405 today. Maybe its because the face cachels represent merged
406 faces rather than simply instantiations in a particular
407 domain. */
354 f->faces_changed || 408 f->faces_changed ||
355 f->glyphs_changed ||
356 cdl->ypos != ddl->ypos || 409 cdl->ypos != ddl->ypos ||
357 cdl->ascent != ddl->ascent || 410 cdl->ascent != ddl->ascent ||
358 cdl->descent != ddl->descent || 411 cdl->descent != ddl->descent ||
359 cdl->clip != ddl->clip || 412 cdl->clip != ddl->clip ||
360 force) 413 force)
587 f->faces_changed || 640 f->faces_changed ||
588 force || 641 force ||
589 (cdl && (cdl->ypos != ddl->ypos || 642 (cdl && (cdl->ypos != ddl->ypos ||
590 cdl->ascent != ddl->ascent || 643 cdl->ascent != ddl->ascent ||
591 cdl->descent != ddl->descent || 644 cdl->descent != ddl->descent ||
645 cdl->top_clip != ddl->top_clip ||
592 cdl->clip != ddl->clip))) 646 cdl->clip != ddl->clip)))
593 { 647 {
594 int x, y, width, height; 648 int x, y, width, height;
595 Lisp_Object face; 649 face_index findex;
596 650
597 must_sync = 1; 651 must_sync = 1;
598 x = start_pixpos; 652 x = start_pixpos;
599 y = ddl->ypos - ddl->ascent; 653 y = DISPLAY_LINE_YPOS (ddl);
600 width = min (next_start_pixpos, block_end) - x; 654 width = min (next_start_pixpos, block_end) - x;
601 height = ddl->ascent + ddl->descent - ddl->clip; 655 height = DISPLAY_LINE_HEIGHT (ddl);
602 656
603 if (x < ddl->bounds.left_in) 657 if (x < ddl->bounds.left_in)
604 face = Vleft_margin_face; 658 {
659 findex = ddl->left_margin_findex ?
660 ddl->left_margin_findex
661 : get_builtin_face_cache_index (w, Vleft_margin_face);
662 }
605 else if (x < ddl->bounds.right_in) 663 else if (x < ddl->bounds.right_in)
606 face = Vdefault_face; 664 {
665 /* no check here because DEFAULT_INDEX == 0 anyway */
666 findex = ddl->default_findex;
667 }
607 else if (x < ddl->bounds.right_out) 668 else if (x < ddl->bounds.right_out)
608 face = Vright_margin_face; 669 {
670 findex = ddl->right_margin_findex ?
671 ddl->right_margin_findex
672 : get_builtin_face_cache_index (w, Vright_margin_face);
673 }
609 else 674 else
610 face = Qnil; 675 findex = (face_index) -1;
611 676
612 if (!NILP (face)) 677 if (findex != (face_index) -1)
613 { 678 {
614 Lisp_Object window; 679 Lisp_Object window;
615 680
616 XSETWINDOW (window, w); 681 XSETWINDOW (window, w);
617 682
618 /* Clear the empty area. */ 683 /* Clear the empty area. */
619 redisplay_clear_region (window, get_builtin_face_cache_index (w, face), 684 redisplay_clear_region (window, findex, x, y, width, height);
620 x, y, width, height);
621 685
622 /* Mark that we should clear the border. This is 686 /* Mark that we should clear the border. This is
623 necessary because italic fonts may leave 687 necessary because italic fonts may leave
624 droppings in the border. */ 688 droppings in the border. */
625 clear_border = 1; 689 clear_border = 1;
646 710
647 /* If there was formerly no block over the current 711 /* If there was formerly no block over the current
648 region or if it was a block of a different type, then 712 region or if it was a block of a different type, then
649 output the entire ddb. Otherwise, compare cdb and 713 output the entire ddb. Otherwise, compare cdb and
650 ddb and output only the changed region. */ 714 ddb and output only the changed region. */
651 if (!force && cdb && ddb->type == cdb->type && b == old_b) 715 if (!force && cdb && ddb->type == cdb->type
716 /* If there was no buffer being display before the
717 compare anyway as we might be outputting a gutter. */
718 &&
719 (b == old_b || !old_b))
652 { 720 {
653 must_sync |= compare_display_blocks (w, cdl, ddl, old_block, 721 must_sync |= compare_display_blocks (w, cdl, ddl, old_block,
654 block, start_pixpos, 722 block, start_pixpos,
655 cursor_start, cursor_width, 723 cursor_start, cursor_width,
656 cursor_height); 724 cursor_height);
684 last_elt, 752 last_elt,
685 start_pixpos, 753 start_pixpos,
686 cursor_start, cursor_width, 754 cursor_start, cursor_width,
687 cursor_height); 755 cursor_height);
688 } 756 }
689 757
690 start_pixpos = next_start_pixpos; 758 start_pixpos = next_start_pixpos;
691 } 759 }
692 } 760 }
693 761
694 /* Clear the internal border if we are next to it and the window 762 /* Clear the internal border if we are next to it and the window
697 /* #### Doing this on f->clear sucks but is necessary because of 765 /* #### Doing this on f->clear sucks but is necessary because of
698 window-local background values. */ 766 window-local background values. */
699 if (f->windows_structure_changed || f->faces_changed || clear_border 767 if (f->windows_structure_changed || f->faces_changed || clear_border
700 || f->clear) 768 || f->clear)
701 { 769 {
702 int y = ddl->ypos - ddl->ascent; 770 int y = DISPLAY_LINE_YPOS (ddl);
703 int height = ddl->ascent + ddl->descent - ddl->clip; 771 int height = DISPLAY_LINE_HEIGHT (ddl);
704 772
705 if (ddl->modeline) 773 /* If we are in the gutter then we musn't clear the borders. */
706 { 774 if (y >= WINDOW_TEXT_TOP (w) && (y + height) <= WINDOW_TEXT_BOTTOM (w))
707 y -= MODELINE_SHADOW_THICKNESS (w); 775 {
708 height += (2 * MODELINE_SHADOW_THICKNESS (w)); 776 if (ddl->modeline)
709 } 777 {
710 778 y -= MODELINE_SHADOW_THICKNESS (w);
711 if (window_is_leftmost (w)) 779 height += (2 * MODELINE_SHADOW_THICKNESS (w));
712 clear_left_border (w, y, height); 780 }
713 if (window_is_rightmost (w)) 781
714 clear_right_border (w, y, height); 782 if (window_is_leftmost (w))
783 clear_left_border (w, y, height);
784 if (window_is_rightmost (w))
785 clear_right_border (w, y, height);
786 }
715 } 787 }
716 788
717 if (cdla) 789 if (cdla)
718 sync_display_line_structs (w, line, must_sync, cdla, ddla); 790 sync_display_line_structs (w, line, must_sync, cdla, ddla);
719 } 791 }
850 cur_dl = y; 922 cur_dl = y;
851 first = 1; 923 first = 1;
852 } 924 }
853 } 925 }
854 926
855 while ((up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0))) 927 while (up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0))
856 { 928 {
857 dl = Dynarr_atp (cla, cur_dl); 929 dl = Dynarr_atp (cla, cur_dl);
858 db = get_display_block_from_line (dl, TEXT); 930 db = get_display_block_from_line (dl, TEXT);
859 931
860 if (!up && !first) 932 if (!up && !first)
993 int start, int end, int start_pixpos, int cursor_start, 1065 int start, int end, int start_pixpos, int cursor_start,
994 int cursor_width, int cursor_height) 1066 int cursor_width, int cursor_height)
995 { 1067 {
996 struct frame *f = XFRAME (w->frame); 1068 struct frame *f = XFRAME (w->frame);
997 struct device *d = XDEVICE (f->device); 1069 struct device *d = XDEVICE (f->device);
998 1070 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
1071 rune_dynarr *rba = db->runes;
1072 struct rune *rb;
1073 int xpos, width;
1074 rb = Dynarr_atp (rba, start);
1075
1076 if (!rb)
1077 /* Nothing to do so don't do anything. */
1078 return;
1079
1080 xpos = max (start_pixpos, rb->xpos);
1081
1082 if (end < 0)
1083 end = Dynarr_length (rba);
1084
1085 rb = Dynarr_atp (rba, end - 1);
1086 width = rb->xpos + rb->width - xpos;
1087 /* now actually output the block. */
999 DEVMETH (d, output_display_block, (w, dl, block, start, 1088 DEVMETH (d, output_display_block, (w, dl, block, start,
1000 end, start_pixpos, 1089 end, start_pixpos,
1001 cursor_start, cursor_width, 1090 cursor_start, cursor_width,
1002 cursor_height)); 1091 cursor_height));
1003 } 1092 }
1004 1093
1005 /**************************************************************************** 1094 /****************************************************************************
1006 redisplay_unmap_subwindows 1095 redisplay_unmap_subwindows
1007 1096
1008 Remove subwindows from the area in the box defined by the given 1097 Remove subwindows from the area in the box defined by the given
1009 parameters. 1098 parameters.
1010 ****************************************************************************/ 1099 ****************************************************************************/
1011 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height) 1100 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height,
1101 Lisp_Object ignored_window)
1012 { 1102 {
1013 int elt; 1103 int elt;
1014 1104
1015 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) 1105 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
1016 { 1106 {
1019 1109
1020 if (cachel->being_displayed 1110 if (cachel->being_displayed
1021 && 1111 &&
1022 cachel->x + cachel->width > x && cachel->x < x + width 1112 cachel->x + cachel->width > x && cachel->x < x + width
1023 && 1113 &&
1024 cachel->y + cachel->height > y && cachel->y < y + height) 1114 cachel->y + cachel->height > y && cachel->y < y + height
1115 &&
1116 !EQ (cachel->subwindow, ignored_window))
1025 { 1117 {
1026 unmap_subwindow (cachel->subwindow); 1118 unmap_subwindow (cachel->subwindow);
1027 } 1119 }
1028 } 1120 }
1029 } 1121 }
1036 ****************************************************************************/ 1128 ****************************************************************************/
1037 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height) 1129 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height)
1038 { 1130 {
1039 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f))) 1131 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1040 { 1132 {
1041 redisplay_unmap_subwindows (f, x, y, width, height); 1133 redisplay_unmap_subwindows (f, x, y, width, height, Qnil);
1134 }
1135 }
1136
1137 static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width,
1138 int height, Lisp_Object subwindow)
1139 {
1140 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1141 {
1142 redisplay_unmap_subwindows (f, x, y, width, height, subwindow);
1042 } 1143 }
1043 } 1144 }
1044 1145
1045 /**************************************************************************** 1146 /****************************************************************************
1046 redisplay_output_subwindow 1147 redisplay_output_subwindow
1047
1048 1148
1049 output a subwindow. This code borrows heavily from the pixmap stuff, 1149 output a subwindow. This code borrows heavily from the pixmap stuff,
1050 although is much simpler not needing to account for partial 1150 although is much simpler not needing to account for partial
1051 pixmaps, backgrounds etc. 1151 pixmaps, backgrounds etc.
1052 ****************************************************************************/ 1152 ****************************************************************************/
1053 void 1153 void
1054 redisplay_output_subwindow (struct window *w, struct display_line *dl, 1154 redisplay_output_subwindow (struct window *w,
1055 Lisp_Object image_instance, int xpos, int xoffset, 1155 Lisp_Object image_instance,
1056 int start_pixpos, int width, face_index findex, 1156 struct display_box* db, struct display_glyph_area* dga,
1057 int cursor_start, int cursor_width, int cursor_height) 1157 face_index findex, int cursor_start, int cursor_width,
1058 { 1158 int cursor_height)
1059 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); 1159 {
1160 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1060 Lisp_Object window; 1161 Lisp_Object window;
1061 1162 struct display_glyph_area sdga;
1062 int lheight = dl->ascent + dl->descent - dl->clip; 1163
1063 int pheight = ((int) IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight ? lheight : 1164 dga->height = IMAGE_INSTANCE_HEIGHT (p);
1064 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p)); 1165 dga->width = IMAGE_INSTANCE_WIDTH (p);
1166
1167 /* The first thing we are going to do is update the display
1168 characteristics of the subwindow. This also clears the dirty
1169 flags as a side effect. */
1170 update_subwindow (image_instance);
1171
1172 /* This makes the glyph area fit into the display area. */
1173 if (!redisplay_normalize_glyph_area (db, dga))
1174 return;
1065 1175
1066 XSETWINDOW (window, w); 1176 XSETWINDOW (window, w);
1067 1177
1068 /* Clear the area the subwindow is going into. The subwindow itself 1178 /* Clear the area the subwindow is going into. */
1069 will always take care of the full width. We don't want to clear 1179 redisplay_clear_clipped_region (window, findex,
1070 where it is going to go in order to avoid flicker. So, all we 1180 db, dga, 0, image_instance);
1071 have to take care of is any area above or below the subwindow. Of 1181
1072 course this is rubbish if the subwindow has transparent areas 1182 /* This shrinks the display box to exactly enclose the glyph
1073 (for instance with frames). */ 1183 area. */
1074 /* #### We take a shortcut for now. We know that since we have 1184 redisplay_normalize_display_box (db, dga);
1075 subwindow_offset hardwired to 0 that the subwindow is against the top 1185
1076 edge so all we have to worry about is below it. */ 1186 /* if we can't view the whole window we can't view any of it. We
1077 if ((int) (dl->ypos - dl->ascent + pheight) < 1187 have to be careful here since we may be being asked to display
1078 (int) (dl->ypos + dl->descent - dl->clip)) 1188 part of a subwindow, the rest of which is on-screen as well. We
1079 { 1189 need to allow this case and map the entire subwindow. We also
1080 int clear_x, clear_width; 1190 need to be careful since the subwindow could be outside the
1081 1191 window in the gutter or modeline - we also need to allow these
1082 int clear_y = dl->ypos - dl->ascent + pheight; 1192 cases.*/
1083 int clear_height = lheight - pheight; 1193 sdga.xoffset = -dga->xoffset;
1084 1194 sdga.yoffset = -dga->yoffset;
1085 if (start_pixpos >= 0 && start_pixpos > xpos) 1195 sdga.height = IMAGE_INSTANCE_HEIGHT (p);
1086 { 1196 sdga.width = IMAGE_INSTANCE_WIDTH (p);
1087 clear_x = start_pixpos; 1197
1088 clear_width = xpos + width - start_pixpos; 1198 if (redisplay_display_boxes_in_window_p (w, db, &sdga) < 0)
1089 } 1199 {
1090 else 1200 map_subwindow (image_instance, db->xpos, db->ypos, dga);
1091 { 1201 }
1092 clear_x = xpos; 1202 else
1093 clear_width = width; 1203 {
1094 } 1204 sdga.xoffset = sdga.yoffset = 0;
1095 1205 map_subwindow (image_instance, db->xpos - dga->xoffset,
1096 redisplay_clear_region (window, findex, clear_x, clear_y, 1206 db->ypos - dga->yoffset, &sdga);
1097 clear_width, clear_height); 1207 }
1098 } 1208 }
1099 #if 0 1209
1100 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent, 1210 /****************************************************************************
1101 width, lheight); 1211 redisplay_output_layout
1102 #endif 1212
1103 /* if we can't view the whole window we can't view any of it */ 1213 Output a widget hierarchy. This can safely call itself recursively.
1104 if (IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight 1214
1105 || 1215 The complexity of outputting layouts is deciding whether to do it or
1106 IMAGE_INSTANCE_SUBWINDOW_WIDTH (p) > width) 1216 not. Consider a layout enclosing some text, the text changes and is
1107 { 1217 marked as dirty, but the enclosing layout has not been marked as
1108 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent, 1218 dirty so no updates occur and the text will potentially be truncated.
1109 width, lheight); 1219 Alternatively we hold a back pointer in the image instance to the
1110 unmap_subwindow (image_instance); 1220 parent and mark the parent as dirty. But the layout code assumes that
1111 } 1221 if the layout is dirty then the whole layout should be redisplayed,
1112 else 1222 so we then get lots of flashing even though only the text has changed
1113 map_subwindow (image_instance, xpos - xoffset, dl->ypos - dl->ascent); 1223 size. Of course if the text shrinks in size then we do actually need
1224 to redisplay the layout to repaint the exposed area. So what happens
1225 if we make a non-structural change like changing color? Either we
1226 redisplay everything, or we redisplay nothing. These are exactly the
1227 issues lwlib has to grapple with. We really need to know what has
1228 actually changed and make a layout decision based on that. We also
1229 really need to know what has changed so that we can only make the
1230 neccessary changes in update_subwindow. This has all now been
1231 implemented, Viva la revolution!
1232 ****************************************************************************/
1233 void
1234 redisplay_output_layout (struct window *w,
1235 Lisp_Object image_instance,
1236 struct display_box* db, struct display_glyph_area* dga,
1237 face_index findex, int cursor_start, int cursor_width,
1238 int cursor_height)
1239 {
1240 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1241 Lisp_Object window, rest;
1242 Emchar_dynarr *buf = Dynarr_new (Emchar);
1243 struct frame *f = XFRAME (w->frame);
1244 struct device *d = XDEVICE (f->device);
1245 int layout_height, layout_width;
1246 /* We bogusly don't take f->extents_changed and f->glyphs_changed
1247 into account. This is because if we do we always redisplay the
1248 entire layout. So far I have seen no ill effects so we'll see. */
1249 int frame_really_changed = (f->buffers_changed ||
1250 f->clip_changed ||
1251 f->faces_changed ||
1252 f->frame_changed ||
1253 f->modeline_changed ||
1254 f->subwindows_changed ||
1255 f->windows_changed ||
1256 f->windows_structure_changed);
1257
1258 XSETWINDOW (window, w);
1259
1260 layout_height = glyph_height (image_instance, window);
1261 layout_width = glyph_width (image_instance, window);
1262
1263 dga->height = layout_height;
1264 dga->width = layout_width;
1265
1266 /* This makes the glyph area fit into the display area. */
1267 if (!redisplay_normalize_glyph_area (db, dga))
1268 return;
1269
1270 /* Highly dodgy optimization. We want to only output the whole
1271 layout if we really have to. */
1272 if (frame_really_changed
1273 || IMAGE_INSTANCE_LAYOUT_CHANGED (p)
1274 || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
1275 || IMAGE_INSTANCE_SIZE_CHANGED (p)
1276 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p))
1277 {
1278 /* First clear the area we are drawing into. This is the easiest
1279 thing to do since we have many gaps that we have to make sure are
1280 filled in. */
1281 redisplay_clear_clipped_region (window, findex, db, dga, 1, Qnil);
1282
1283 /* Output a border if required */
1284 if (!NILP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1285 {
1286 int edges = 0;
1287 enum edge_style style;
1288 int ypos = db->ypos;
1289 int height = dga->height;
1290
1291 if (dga->xoffset >= 0)
1292 edges |= EDGE_LEFT;
1293 if (dga->width - dga->xoffset == layout_width)
1294 edges |= EDGE_RIGHT;
1295 if (dga->yoffset >= 0)
1296 edges |= EDGE_TOP;
1297 if (dga->height - dga->yoffset == layout_height)
1298 edges |= EDGE_BOTTOM;
1299
1300 if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in))
1301 style = EDGE_ETCHED_IN;
1302 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out))
1303 style = EDGE_ETCHED_OUT;
1304 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qbevel_in))
1305 style = EDGE_BEVEL_IN;
1306 else if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1307 {
1308 style = EDGE_ETCHED_IN;
1309 if (edges & EDGE_TOP)
1310 {
1311 ypos += XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1312 height -= XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1313 }
1314 }
1315 else
1316 style = EDGE_BEVEL_OUT;
1317
1318 MAYBE_DEVMETH (d, bevel_area,
1319 (w, findex, db->xpos,
1320 ypos,
1321 dga->width, height, 2, edges, style));
1322 }
1323 }
1324
1325 /* This shrinks the display box to exactly enclose the glyph
1326 area. */
1327 redisplay_normalize_display_box (db, dga);
1328
1329 /* Flip through the widgets in the layout displaying as necessary */
1330 LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p))
1331 {
1332 Lisp_Object child = XCAR (rest);
1333
1334 struct display_box cdb;
1335 /* For losing HP-UX */
1336 cdb.xpos = db->xpos;
1337 cdb.ypos = db->ypos;
1338 cdb.width = db->width;
1339 cdb.height = db->height;
1340
1341 /* First determine if the image is visible at all */
1342 if (IMAGE_INSTANCEP (child))
1343 {
1344 Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child);
1345 /* The enclosing layout offsets are +ve at this point */
1346 struct display_glyph_area cdga;
1347 cdga.xoffset = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset;
1348 cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset;
1349 cdga.width = glyph_width (child, window);
1350 cdga.height = glyph_height (child, window);
1351
1352 /* Although normalization is done by the output routines
1353 we have to do it here so that they don't try and
1354 clear all of db. This is true below also. */
1355 if (redisplay_normalize_glyph_area (&cdb, &cdga))
1356 {
1357 redisplay_normalize_display_box (&cdb, &cdga);
1358 /* Since the display boxes will now be totally in the
1359 window if they are visible at all we can now check this easily. */
1360 if (cdb.xpos < db->xpos || cdb.ypos < db->ypos
1361 || cdb.xpos + cdb.width > db->xpos + db->width
1362 || cdb.ypos + cdb.height > db->ypos + db->height)
1363 continue;
1364 /* We have to invert the offset here as normalization
1365 will have made them positive which the output
1366 routines will treat as a truely +ve offset. */
1367 cdga.xoffset = -cdga.xoffset;
1368 cdga.yoffset = -cdga.yoffset;
1369
1370 switch (IMAGE_INSTANCE_TYPE (childii))
1371 {
1372 case IMAGE_TEXT:
1373 {
1374 /* #### This is well hacked and could use some
1375 generalisation.*/
1376 if (redisplay_normalize_glyph_area (&cdb, &cdga)
1377 &&
1378 (frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii)))
1379 {
1380 struct display_line dl; /* this is fake */
1381 Lisp_Object string =
1382 IMAGE_INSTANCE_TEXT_STRING (childii);
1383 convert_bufbyte_string_into_emchar_dynarr
1384 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
1385
1386 redisplay_normalize_display_box (&cdb, &cdga);
1387 /* Offsets are now +ve again so be careful
1388 when fixing up the display line. */
1389 xzero (dl);
1390 /* Munge boxes into display lines. */
1391 dl.ypos = (cdb.ypos - cdga.yoffset)
1392 + glyph_ascent (child, window);
1393 dl.ascent = glyph_ascent (child, window);
1394 dl.descent = glyph_descent (child, window);
1395 dl.top_clip = cdga.yoffset;
1396 dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height);
1397 /* output_string doesn't understand offsets in
1398 the same way as other routines - we have to
1399 add the offset to the width so that we
1400 output the full string. */
1401 MAYBE_DEVMETH (d, output_string, (w, &dl, buf, cdb.xpos,
1402 cdga.xoffset, cdb.xpos,
1403 cdga.width + cdga.xoffset,
1404 findex, 0, 0, 0, 0));
1405 Dynarr_reset (buf);
1406 }
1407 }
1408 break;
1409
1410 case IMAGE_MONO_PIXMAP:
1411 case IMAGE_COLOR_PIXMAP:
1412 if (frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii))
1413 redisplay_output_pixmap (w, child, &cdb, &cdga, findex,
1414 0, 0, 0, 0);
1415 break;
1416
1417 case IMAGE_WIDGET:
1418 case IMAGE_SUBWINDOW:
1419 if (frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii))
1420 redisplay_output_subwindow (w, child, &cdb, &cdga, findex,
1421 0, 0, 0);
1422 break;
1423
1424 case IMAGE_LAYOUT:
1425 redisplay_output_layout (w, child, &cdb, &cdga, findex,
1426 0, 0, 0);
1427 break;
1428
1429 case IMAGE_NOTHING:
1430 /* nothing is as nothing does */
1431 break;
1432
1433 case IMAGE_POINTER:
1434 default:
1435 abort ();
1436 }
1437 }
1438 }
1439 }
1440
1441 /* Update any display properties. I'm not sure whether this actually
1442 does anything for layouts except clear the changed flags. */
1443 update_subwindow (image_instance);
1444
1445 Dynarr_free (buf);
1446 }
1447
1448 /****************************************************************************
1449 redisplay_output_pixmap
1450
1451
1452 output a pixmap.
1453 ****************************************************************************/
1454 void
1455 redisplay_output_pixmap (struct window *w,
1456 Lisp_Object image_instance,
1457 struct display_box* db, struct display_glyph_area* dga,
1458 face_index findex, int cursor_start, int cursor_width,
1459 int cursor_height, int offset_bitmap)
1460 {
1461 struct frame *f = XFRAME (w->frame);
1462 struct device *d = XDEVICE (f->device);
1463 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1464 Lisp_Object window;
1465 XSETWINDOW (window, w);
1466
1467 dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
1468 dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
1469
1470 /* This makes the glyph area fit into the display area. */
1471 if (!redisplay_normalize_glyph_area (db, dga))
1472 return;
1473
1474 /* Clear the area the pixmap is going into. The pixmap itself will
1475 always take care of the full width. We don't want to clear where
1476 it is going to go in order to avoid flicker. So, all we have to
1477 take care of is any area above or below the pixmap. If the pixmap
1478 has a mask in which case we have to clear the whole damn thing
1479 since we can't yet clear just the area not included in the
1480 mask. */
1481 if (!offset_bitmap)
1482 {
1483 redisplay_clear_clipped_region (window, findex,
1484 db, dga,
1485 (int)IMAGE_INSTANCE_PIXMAP_MASK (p),
1486 Qnil);
1487
1488 /* This shrinks the display box to exactly enclose the glyph
1489 area. */
1490 redisplay_normalize_display_box (db, dga);
1491 }
1492 assert (db->xpos >= 0 && db->ypos >= 0);
1493
1494 MAYBE_DEVMETH (d, output_pixmap, (w, image_instance,
1495 db, dga,
1496 findex, cursor_start,
1497 cursor_width, cursor_height,
1498 offset_bitmap));
1114 } 1499 }
1115 1500
1116 /**************************************************************************** 1501 /****************************************************************************
1117 redisplay_clear_region 1502 redisplay_clear_region
1118 1503
1147 abort (); 1532 abort ();
1148 1533
1149 d = XDEVICE (f->device); 1534 d = XDEVICE (f->device);
1150 1535
1151 /* if we have subwindows in the region we have to unmap them */ 1536 /* if we have subwindows in the region we have to unmap them */
1152 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f))) 1537 redisplay_unmap_subwindows_maybe (f, x, y, width, height);
1153 {
1154 redisplay_unmap_subwindows (f, x, y, width, height);
1155 }
1156 1538
1157 /* #### This isn't quite right for when this function is called 1539 /* #### This isn't quite right for when this function is called
1158 from the toolbar code. */ 1540 from the toolbar code. */
1159 1541
1160 /* Don't use a backing pixmap in the border area */ 1542 /* Don't use a backing pixmap in the border area */
1161 if (x >= FRAME_LEFT_BORDER_END (f) 1543 if (x >= FRAME_LEFT_BORDER_END (f)
1162 && x < FRAME_RIGHT_BORDER_START (f) 1544 && x < FRAME_RIGHT_BORDER_START (f)
1163 && y >= FRAME_TOP_BORDER_END (f) 1545 && y >= FRAME_TOP_BORDER_END (f)
1164 && y < FRAME_BOTTOM_BORDER_START (f)) 1546 && y < FRAME_BOTTOM_BORDER_START (f))
1165 { 1547 {
1166 Lisp_Object temp; 1548 Lisp_Object temp;
1167 1549
1168 if (w) 1550 if (w)
1169 { 1551 {
1170 temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex); 1552 temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
1171 1553
1172 if (IMAGE_INSTANCEP (temp) 1554 if (IMAGE_INSTANCEP (temp)
1173 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp))) 1555 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1174 { 1556 {
1175 /* #### maybe we could implement such that a string 1557 /* #### maybe we could implement such that a string
1176 can be a background pixmap? */ 1558 can be a background pixmap? */
1178 } 1560 }
1179 } 1561 }
1180 else 1562 else
1181 { 1563 {
1182 temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale); 1564 temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
1183 1565
1184 if (IMAGE_INSTANCEP (temp) 1566 if (IMAGE_INSTANCEP (temp)
1185 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp))) 1567 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1186 { 1568 {
1187 background_pixmap = temp; 1569 background_pixmap = temp;
1188 } 1570 }
1189 } 1571 }
1190 } 1572 }
1191 1573
1192 if (!UNBOUNDP (background_pixmap) && 1574 if (!UNBOUNDP (background_pixmap) &&
1193 XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0) 1575 XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
1194 { 1576 {
1195 if (w) 1577 if (w)
1206 else 1588 else
1207 { 1589 {
1208 fcolor = (w ? 1590 fcolor = (w ?
1209 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) : 1591 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
1210 FACE_BACKGROUND (Vdefault_face, locale)); 1592 FACE_BACKGROUND (Vdefault_face, locale));
1211 1593
1212 } 1594 }
1213 1595
1214 if (UNBOUNDP (background_pixmap)) 1596 if (UNBOUNDP (background_pixmap))
1215 background_pixmap = Qnil; 1597 background_pixmap = Qnil;
1216 1598
1217 DEVMETH (d, clear_region, 1599 DEVMETH (d, clear_region,
1218 (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap)); 1600 (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1601 }
1602
1603 /****************************************************************************
1604 redisplay_clear_clipped_region
1605
1606 Clear the area in the dest display_box not covered by the src
1607 display_glyph_area using the given face. This is a common occurance
1608 for images shorter than the display line. Clipping can be played
1609 around with by altering these. glyphsrc should be normalized.
1610 ****************************************************************************/
1611 static void
1612 redisplay_clear_clipped_region (Lisp_Object window, face_index findex,
1613 struct display_box* dest, struct display_glyph_area* glyphsrc,
1614 int fullheight_p, Lisp_Object ignored_subwindow)
1615 {
1616 /* assume dest->xpos >= 0 */
1617 int clear_x;
1618 struct frame* f = XFRAME (XWINDOW (window)->frame);
1619
1620 if (glyphsrc->xoffset > 0)
1621 {
1622 clear_x = dest->xpos + glyphsrc->xoffset;
1623 }
1624 else
1625 {
1626 clear_x = dest->xpos;
1627 }
1628
1629 /* If we need the whole height cleared then just do it. */
1630 if (fullheight_p)
1631 {
1632 redisplay_clear_region (window, findex, clear_x, dest->ypos,
1633 glyphsrc->width, dest->height);
1634 }
1635 else
1636 {
1637 int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0);
1638
1639 /* We need to make sure that subwindows are unmapped from the
1640 whole area. */
1641 redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos,
1642 glyphsrc->width, dest->height,
1643 ignored_subwindow);
1644 /* first the top box */
1645 if (yoffset > 0)
1646 {
1647 redisplay_clear_region (window, findex, clear_x, dest->ypos,
1648 glyphsrc->width, yoffset);
1649
1650 }
1651 /* Then the bottom box */
1652 if (yoffset + glyphsrc->height < dest->height)
1653 {
1654 redisplay_clear_region (window, findex, clear_x,
1655 dest->ypos + yoffset + glyphsrc->height,
1656 glyphsrc->width,
1657 dest->height - (yoffset + glyphsrc->height));
1658
1659 }
1660 }
1661 }
1662
1663 /*****************************************************************************
1664 redisplay_normalize_glyph_area
1665 redisplay_normalize_display_box
1666
1667 Calculate the visible box for displaying src in dest.
1668 ****************************************************************************/
1669 int
1670 redisplay_normalize_glyph_area (struct display_box* dest,
1671 struct display_glyph_area* glyphsrc)
1672 {
1673 if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width
1674 ||
1675 dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height
1676 ||
1677 -glyphsrc->xoffset >= glyphsrc->width
1678 ||
1679 -glyphsrc->yoffset >= glyphsrc->height)
1680 {
1681 /* It's all clipped out */
1682 return 0;
1683 }
1684
1685 /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */
1686 if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width)
1687 {
1688 if (glyphsrc->xoffset > 0)
1689 glyphsrc->width = dest->width - glyphsrc->xoffset;
1690 else
1691 glyphsrc->width = dest->width;
1692 }
1693
1694 if (glyphsrc->xoffset < 0)
1695 glyphsrc->width += glyphsrc->xoffset;
1696
1697 /* Vertical offsets. This works because yoffset can be -ve as well as +ve */
1698 if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height)
1699 {
1700 if (glyphsrc->yoffset > 0)
1701 glyphsrc->height = dest->height - glyphsrc->yoffset;
1702 else
1703 glyphsrc->height = dest->height;
1704 }
1705
1706 if (glyphsrc->yoffset < 0)
1707 glyphsrc->height += glyphsrc->yoffset;
1708
1709 return 1;
1710 }
1711
1712 static void
1713 redisplay_normalize_display_box (struct display_box* dest,
1714 struct display_glyph_area* glyphsrc)
1715 {
1716 /* Adjust the destination area. At the end of this the destination
1717 area will exactly enclose the glyph area. The only remaining
1718 adjustment will be offsets into the glyph area. */
1719
1720 /* Horizontal adjustment. */
1721 if (glyphsrc->xoffset > 0)
1722 {
1723 dest->xpos += glyphsrc->xoffset;
1724 dest->width -= glyphsrc->xoffset;
1725 glyphsrc->xoffset = 0;
1726 }
1727 else
1728 glyphsrc->xoffset = -glyphsrc->xoffset;
1729
1730 if (glyphsrc->width < dest->width)
1731 dest->width = glyphsrc->width;
1732
1733 /* Vertical adjustment. */
1734 if (glyphsrc->yoffset > 0)
1735 {
1736 dest->ypos += glyphsrc->yoffset;
1737 dest->height -= glyphsrc->yoffset;
1738 glyphsrc->yoffset = 0;
1739 }
1740 else
1741 glyphsrc->yoffset = -glyphsrc->yoffset;
1742
1743 if (glyphsrc->height < dest->height)
1744 dest->height = glyphsrc->height;
1745 }
1746
1747 /*****************************************************************************
1748 redisplay_display_boxes_in_window_p
1749
1750 Determine whether the require display_glyph_area is completely inside
1751 the window. 0 means the display_box is not in the window. 1 means the
1752 display_box and the display_glyph_area are in the window. -1 means
1753 the display_box is in the window but the display_glyph_area is not.
1754 ****************************************************************************/
1755 static int
1756 redisplay_display_boxes_in_window_p (struct window* w,
1757 struct display_box* db,
1758 struct display_glyph_area* dga)
1759 {
1760 int left = WINDOW_TEXT_LEFT (w);
1761 int right = WINDOW_TEXT_RIGHT (w);
1762 int top = WINDOW_TEXT_TOP (w);
1763 int bottom = WINDOW_TEXT_BOTTOM (w);
1764
1765 if (db->xpos < left || db->ypos < top
1766 || db->xpos + db->width > right
1767 || db->ypos + db->height > bottom)
1768 /* We are not displaying in a window at all */
1769 return 0;
1770
1771 if (db->xpos + dga->xoffset >= left
1772 &&
1773 db->ypos + dga->yoffset >= top
1774 &&
1775 db->xpos + dga->xoffset + dga->width <= right
1776 &&
1777 db->ypos + dga->yoffset + dga->height <= bottom)
1778 return 1;
1779
1780 return -1;
1781 }
1782
1783 /*****************************************************************************
1784 redisplay_calculate_display_boxes
1785
1786 Convert from rune/display_line co-ordinates to display_box
1787 co-ordinates.
1788 ****************************************************************************/
1789 int
1790 redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
1791 int xoffset, int start_pixpos, int width,
1792 struct display_box* dest,
1793 struct display_glyph_area* src)
1794 {
1795 dest->xpos = xpos;
1796 dest->ypos = DISPLAY_LINE_YPOS (dl);
1797 dest->width = width;
1798 dest->height = DISPLAY_LINE_HEIGHT (dl);
1799
1800 src->xoffset = -xoffset;
1801 src->yoffset = -dl->top_clip;
1802 src->width = 0;
1803 src->height = 0;
1804
1805 if (start_pixpos >=0 && start_pixpos > xpos)
1806 {
1807 /* Oops, we're asking for a start outside of the displayable
1808 area. */
1809 if (start_pixpos > xpos + width)
1810 return 0;
1811 dest->xpos = start_pixpos;
1812 dest->width -= (start_pixpos - xpos);
1813 /* Offsets are -ve when we want to clip pixels off the displayed
1814 glyph. */
1815 src->xoffset -= (start_pixpos - xpos);
1816 }
1817
1818 return 1;
1219 } 1819 }
1220 1820
1221 /***************************************************************************** 1821 /*****************************************************************************
1222 redisplay_clear_top_of_window 1822 redisplay_clear_top_of_window
1223 1823
1247 1847
1248 y = FRAME_TOP_BORDER_START (f) - 1; 1848 y = FRAME_TOP_BORDER_START (f) - 1;
1249 height = FRAME_BORDER_HEIGHT (f) + 1; 1849 height = FRAME_BORDER_HEIGHT (f) + 1;
1250 1850
1251 redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height); 1851 redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
1852 }
1853 }
1854
1855 /*****************************************************************************
1856 redisplay_clear_to_window_end
1857
1858 Clear the area between ypos1 and ypos2. Each margin area and the
1859 text area is handled separately since they may each have their own
1860 background color.
1861 ****************************************************************************/
1862 void
1863 redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1864 {
1865 struct frame *f = XFRAME (w->frame);
1866 struct device *d = XDEVICE (f->device);
1867
1868 if (HAS_DEVMETH_P (d, clear_to_window_end))
1869 DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1870 else
1871 {
1872 int height = ypos2 - ypos1;
1873
1874 if (height)
1875 {
1876 Lisp_Object window;
1877 int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/
1878 layout_bounds bounds;
1879
1880 bounds = calculate_display_line_boundaries (w, bflag);
1881 XSETWINDOW (window, w);
1882
1883 if (window_is_leftmost (w))
1884 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1885 ypos1, FRAME_BORDER_WIDTH (f), height);
1886
1887 if (bounds.left_in - bounds.left_out > 0)
1888 redisplay_clear_region (window,
1889 get_builtin_face_cache_index (w, Vleft_margin_face),
1890 bounds.left_out, ypos1,
1891 bounds.left_in - bounds.left_out, height);
1892
1893 if (bounds.right_in - bounds.left_in > 0)
1894 redisplay_clear_region (window,
1895 DEFAULT_INDEX,
1896 bounds.left_in, ypos1,
1897 bounds.right_in - bounds.left_in, height);
1898
1899 if (bounds.right_out - bounds.right_in > 0)
1900 redisplay_clear_region (window,
1901 get_builtin_face_cache_index (w, Vright_margin_face),
1902 bounds.right_in, ypos1,
1903 bounds.right_out - bounds.right_in, height);
1904
1905 if (window_is_rightmost (w))
1906 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1907 ypos1, FRAME_BORDER_WIDTH (f), height);
1908 }
1252 } 1909 }
1253 } 1910 }
1254 1911
1255 /***************************************************************************** 1912 /*****************************************************************************
1256 redisplay_clear_bottom_of_window 1913 redisplay_clear_bottom_of_window
1262 void 1919 void
1263 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla, 1920 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1264 int min_start, int max_end) 1921 int min_start, int max_end)
1265 { 1922 {
1266 struct frame *f = XFRAME (w->frame); 1923 struct frame *f = XFRAME (w->frame);
1267 struct device *d = XDEVICE (f->device);
1268 int ypos1, ypos2; 1924 int ypos1, ypos2;
1269 int ddla_len = Dynarr_length (ddla); 1925 int ddla_len = Dynarr_length (ddla);
1270 1926
1271 ypos2 = WINDOW_TEXT_BOTTOM (w); 1927 ypos2 = WINDOW_TEXT_BOTTOM (w);
1272 #ifdef HAVE_SCROLLBARS 1928 #ifdef HAVE_SCROLLBARS
1306 ypos2 = max_end; 1962 ypos2 = max_end;
1307 1963
1308 if (ypos2 <= ypos1) 1964 if (ypos2 <= ypos1)
1309 return; 1965 return;
1310 1966
1311 DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2)); 1967 redisplay_clear_to_window_end (w, ypos1, ypos2);
1312 } 1968 }
1313 1969
1314 /***************************************************************************** 1970 /*****************************************************************************
1315 redisplay_update_line 1971 redisplay_update_line
1316 1972
1601 2257
1602 #ifdef HAVE_SCROLLBARS 2258 #ifdef HAVE_SCROLLBARS
1603 update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0); 2259 update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);
1604 #endif 2260 #endif
1605 } 2261 }
2262
2263 /*****************************************************************************
2264 bevel_modeline
2265
2266 Draw a 3d border around the modeline on window W.
2267 ****************************************************************************/
2268 void
2269 bevel_modeline (struct window *w, struct display_line *dl)
2270 {
2271 struct frame *f = XFRAME (w->frame);
2272 struct device *d = XDEVICE (f->device);
2273 int x, y, width, height;
2274 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
2275 enum edge_style style;
2276
2277 x = WINDOW_MODELINE_LEFT (w);
2278 width = WINDOW_MODELINE_RIGHT (w) - x;
2279 y = dl->ypos - dl->ascent - shadow_thickness;
2280 height = dl->ascent + dl->descent + 2 * shadow_thickness;
2281
2282 if (XINT (w->modeline_shadow_thickness) < 0)
2283 {
2284 style = EDGE_BEVEL_IN;
2285 }
2286 else
2287 {
2288 style = EDGE_BEVEL_OUT;
2289 }
2290
2291 MAYBE_DEVMETH (d, bevel_area,
2292 (w, MODELINE_INDEX, x, y, width, height, shadow_thickness,
2293 EDGE_ALL, style));
2294 }