comparison src/redisplay-output.c @ 424:11054d720c21 r21-2-20

Import from CVS: tag r21-2-20
author cvs
date Mon, 13 Aug 2007 11:26:11 +0200
parents 95016f13131a
children
comparison
equal deleted inserted replaced
423:28d9c139be4c 424:11054d720c21
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"
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.
189 else if (crb->type != drb->type) 202 else if (crb->type != drb->type)
190 return 0; 203 return 0;
191 else if (crb->type == RUNE_CHAR && 204 else if (crb->type == RUNE_CHAR &&
192 (crb->object.chr.ch != drb->object.chr.ch)) 205 (crb->object.chr.ch != drb->object.chr.ch))
193 return 0; 206 return 0;
194 else if (crb->type == RUNE_DGLYPH && 207 else if (crb->type == RUNE_HLINE &&
208 (crb->object.hline.thickness != drb->object.hline.thickness ||
209 crb->object.hline.yoffset != drb->object.hline.yoffset))
210 return 0;
211 else if (crb->type == RUNE_DGLYPH &&
195 (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) || 212 (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) ||
196 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) || 213 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) ||
197 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset)) 214 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset))
198 return 0; 215 return 0;
199 else if (crb->type == RUNE_HLINE && 216 /* Only check dirtiness if we know something has changed. */
200 (crb->object.hline.thickness != drb->object.hline.thickness || 217 else if (crb->type == RUNE_DGLYPH &&
201 crb->object.hline.yoffset != drb->object.hline.yoffset)) 218 XFRAME (w->frame)->glyphs_changed)
202 return 0; 219 {
220 glyph_index gindex = get_glyph_cachel_index (w, drb->object.dglyph.glyph);
221 /* Although doing the cachel lookup for every comparison is
222 very expensive.we have to do it to make sure the cache is
223 up-to-date. */
224 if (GLYPH_CACHEL_DIRTYP (w, gindex))
225 return 0;
226 else
227 return 1;
228 }
203 else 229 else
204 return 1; 230 return 1;
205 } 231 }
206 232
207 /***************************************************************************** 233 /*****************************************************************************
349 #endif 375 #endif
350 ) 376 )
351 force = 1; 377 force = 1;
352 378
353 if (f->windows_structure_changed || 379 if (f->windows_structure_changed ||
380 /* #### Why is this so? We have face cachels so that we don't
381 have to recalculate all the display blocks when faces
382 change. I have fixed this for glyphs and am inclined to think
383 that faces should "Just Work", but I'm not feeling brave
384 today. Maybe its because the face cachels represent merged
385 faces rather than simply instantiations in a particular
386 domain. */
354 f->faces_changed || 387 f->faces_changed ||
355 f->glyphs_changed ||
356 cdl->ypos != ddl->ypos || 388 cdl->ypos != ddl->ypos ||
357 cdl->ascent != ddl->ascent || 389 cdl->ascent != ddl->ascent ||
358 cdl->descent != ddl->descent || 390 cdl->descent != ddl->descent ||
359 cdl->clip != ddl->clip || 391 cdl->clip != ddl->clip ||
360 force) 392 force)
587 f->faces_changed || 619 f->faces_changed ||
588 force || 620 force ||
589 (cdl && (cdl->ypos != ddl->ypos || 621 (cdl && (cdl->ypos != ddl->ypos ||
590 cdl->ascent != ddl->ascent || 622 cdl->ascent != ddl->ascent ||
591 cdl->descent != ddl->descent || 623 cdl->descent != ddl->descent ||
624 cdl->top_clip != ddl->top_clip ||
592 cdl->clip != ddl->clip))) 625 cdl->clip != ddl->clip)))
593 { 626 {
594 int x, y, width, height; 627 int x, y, width, height;
595 face_index findex; 628 face_index findex;
596 629
597 must_sync = 1; 630 must_sync = 1;
598 x = start_pixpos; 631 x = start_pixpos;
599 y = ddl->ypos - ddl->ascent; 632 y = DISPLAY_LINE_YPOS (ddl);
600 width = min (next_start_pixpos, block_end) - x; 633 width = min (next_start_pixpos, block_end) - x;
601 height = ddl->ascent + ddl->descent - ddl->clip; 634 height = DISPLAY_LINE_HEIGHT (ddl);
602 635
603 if (x < ddl->bounds.left_in) 636 if (x < ddl->bounds.left_in)
604 { 637 {
605 findex = ddl->left_margin_findex ? 638 findex = ddl->left_margin_findex ?
606 ddl->left_margin_findex 639 ddl->left_margin_findex
656 689
657 /* If there was formerly no block over the current 690 /* If there was formerly no block over the current
658 region or if it was a block of a different type, then 691 region or if it was a block of a different type, then
659 output the entire ddb. Otherwise, compare cdb and 692 output the entire ddb. Otherwise, compare cdb and
660 ddb and output only the changed region. */ 693 ddb and output only the changed region. */
661 if (!force && cdb && ddb->type == cdb->type && b == old_b) 694 if (!force && cdb && ddb->type == cdb->type
695 /* If there was no buffer being display before the
696 compare anyway as we might be outputting a gutter. */
697 &&
698 (b == old_b || !old_b))
662 { 699 {
663 must_sync |= compare_display_blocks (w, cdl, ddl, old_block, 700 must_sync |= compare_display_blocks (w, cdl, ddl, old_block,
664 block, start_pixpos, 701 block, start_pixpos,
665 cursor_start, cursor_width, 702 cursor_start, cursor_width,
666 cursor_height); 703 cursor_height);
707 /* #### Doing this on f->clear sucks but is necessary because of 744 /* #### Doing this on f->clear sucks but is necessary because of
708 window-local background values. */ 745 window-local background values. */
709 if (f->windows_structure_changed || f->faces_changed || clear_border 746 if (f->windows_structure_changed || f->faces_changed || clear_border
710 || f->clear) 747 || f->clear)
711 { 748 {
712 int y = ddl->ypos - ddl->ascent; 749 int y = DISPLAY_LINE_YPOS (ddl);
713 int height = ddl->ascent + ddl->descent - ddl->clip; 750 int height = DISPLAY_LINE_HEIGHT (ddl);
714 751
715 if (ddl->modeline) 752 /* If we are in the gutter then we musn't clear the borders. */
716 { 753 if (y >= WINDOW_TEXT_TOP (w) && (y + height) <= WINDOW_TEXT_BOTTOM (w))
717 y -= MODELINE_SHADOW_THICKNESS (w); 754 {
718 height += (2 * MODELINE_SHADOW_THICKNESS (w)); 755 if (ddl->modeline)
719 } 756 {
720 757 y -= MODELINE_SHADOW_THICKNESS (w);
721 if (window_is_leftmost (w)) 758 height += (2 * MODELINE_SHADOW_THICKNESS (w));
722 clear_left_border (w, y, height); 759 }
723 if (window_is_rightmost (w)) 760
724 clear_right_border (w, y, height); 761 if (window_is_leftmost (w))
762 clear_left_border (w, y, height);
763 if (window_is_rightmost (w))
764 clear_right_border (w, y, height);
765 }
725 } 766 }
726 767
727 if (cdla) 768 if (cdla)
728 sync_display_line_structs (w, line, must_sync, cdla, ddla); 769 sync_display_line_structs (w, line, must_sync, cdla, ddla);
729 } 770 }
1003 int start, int end, int start_pixpos, int cursor_start, 1044 int start, int end, int start_pixpos, int cursor_start,
1004 int cursor_width, int cursor_height) 1045 int cursor_width, int cursor_height)
1005 { 1046 {
1006 struct frame *f = XFRAME (w->frame); 1047 struct frame *f = XFRAME (w->frame);
1007 struct device *d = XDEVICE (f->device); 1048 struct device *d = XDEVICE (f->device);
1008 1049 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
1050 rune_dynarr *rba = db->runes;
1051 struct rune *rb;
1052 int xpos, width;
1053 rb = Dynarr_atp (rba, start);
1054
1055 if (!rb)
1056 /* Nothing to do so don't do anything. */
1057 return;
1058
1059 xpos = max (start_pixpos, rb->xpos);
1060
1061 if (end < 0)
1062 end = Dynarr_length (rba);
1063
1064 rb = Dynarr_atp (rba, end - 1);
1065 width = rb->xpos + rb->width - xpos;
1066 /* now actually output the block. */
1009 DEVMETH (d, output_display_block, (w, dl, block, start, 1067 DEVMETH (d, output_display_block, (w, dl, block, start,
1010 end, start_pixpos, 1068 end, start_pixpos,
1011 cursor_start, cursor_width, 1069 cursor_start, cursor_width,
1012 cursor_height)); 1070 cursor_height));
1013 } 1071 }
1014 1072
1015 /**************************************************************************** 1073 /****************************************************************************
1016 redisplay_unmap_subwindows 1074 redisplay_unmap_subwindows
1017 1075
1018 Remove subwindows from the area in the box defined by the given 1076 Remove subwindows from the area in the box defined by the given
1019 parameters. 1077 parameters.
1020 ****************************************************************************/ 1078 ****************************************************************************/
1021 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height) 1079 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height,
1080 Lisp_Object ignored_window)
1022 { 1081 {
1023 int elt; 1082 int elt;
1024 1083
1025 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) 1084 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
1026 { 1085 {
1029 1088
1030 if (cachel->being_displayed 1089 if (cachel->being_displayed
1031 && 1090 &&
1032 cachel->x + cachel->width > x && cachel->x < x + width 1091 cachel->x + cachel->width > x && cachel->x < x + width
1033 && 1092 &&
1034 cachel->y + cachel->height > y && cachel->y < y + height) 1093 cachel->y + cachel->height > y && cachel->y < y + height
1094 &&
1095 !EQ (cachel->subwindow, ignored_window))
1035 { 1096 {
1036 unmap_subwindow (cachel->subwindow); 1097 unmap_subwindow (cachel->subwindow);
1037 } 1098 }
1038 } 1099 }
1039 } 1100 }
1046 ****************************************************************************/ 1107 ****************************************************************************/
1047 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height) 1108 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height)
1048 { 1109 {
1049 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f))) 1110 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1050 { 1111 {
1051 redisplay_unmap_subwindows (f, x, y, width, height); 1112 redisplay_unmap_subwindows (f, x, y, width, height, Qnil);
1113 }
1114 }
1115
1116 static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width,
1117 int height, Lisp_Object subwindow)
1118 {
1119 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1120 {
1121 redisplay_unmap_subwindows (f, x, y, width, height, subwindow);
1052 } 1122 }
1053 } 1123 }
1054 1124
1055 /**************************************************************************** 1125 /****************************************************************************
1056 redisplay_output_subwindow 1126 redisplay_output_subwindow
1057
1058 1127
1059 output a subwindow. This code borrows heavily from the pixmap stuff, 1128 output a subwindow. This code borrows heavily from the pixmap stuff,
1060 although is much simpler not needing to account for partial 1129 although is much simpler not needing to account for partial
1061 pixmaps, backgrounds etc. 1130 pixmaps, backgrounds etc.
1062 ****************************************************************************/ 1131 ****************************************************************************/
1063 void 1132 void
1064 redisplay_output_subwindow (struct window *w, struct display_line *dl, 1133 redisplay_output_subwindow (struct window *w,
1065 Lisp_Object image_instance, int xpos, int xoffset, 1134 Lisp_Object image_instance,
1066 int start_pixpos, int width, face_index findex, 1135 struct display_box* db, struct display_glyph_area* dga,
1067 int cursor_start, int cursor_width, int cursor_height) 1136 face_index findex, int cursor_start, int cursor_width,
1137 int cursor_height)
1068 { 1138 {
1069 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); 1139 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1070 Lisp_Object window; 1140 Lisp_Object window;
1071 1141 struct display_glyph_area sdga;
1072 int lheight = dl->ascent + dl->descent - dl->clip; 1142
1073 int pheight = ((int) IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight ? lheight : 1143 dga->height = IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p);
1074 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p)); 1144 dga->width = IMAGE_INSTANCE_SUBWINDOW_WIDTH (p);
1145
1146 /* This makes the glyph area fit into the display area. */
1147 if (!redisplay_normalize_glyph_area (db, dga))
1148 return;
1075 1149
1076 XSETWINDOW (window, w); 1150 XSETWINDOW (window, w);
1077 1151
1078 /* Clear the area the subwindow is going into. The subwindow itself 1152 /* Clear the area the subwindow is going into. */
1079 will always take care of the full width. We don't want to clear 1153 redisplay_clear_clipped_region (window, findex,
1080 where it is going to go in order to avoid flicker. So, all we 1154 db, dga, 0, image_instance);
1081 have to take care of is any area above or below the subwindow. Of 1155
1082 course this is rubbish if the subwindow has transparent areas 1156 /* This shrinks the display box to exactly enclose the glyph
1083 (for instance with frames). */ 1157 area. */
1084 /* #### We take a shortcut for now. We know that since we have 1158 redisplay_normalize_display_box (db, dga);
1085 subwindow_offset hardwired to 0 that the subwindow is against the top 1159
1086 edge so all we have to worry about is below it. */ 1160 /* if we can't view the whole window we can't view any of it. We
1087 if ((int) (dl->ypos - dl->ascent + pheight) < 1161 have to be careful here since we may be being asked to display
1088 (int) (dl->ypos + dl->descent - dl->clip)) 1162 part of a subwindow, the rest of which is on-screen as well. We
1089 { 1163 need to allow this case and map the entire subwindow. We also
1090 int clear_x, clear_width; 1164 need to be careful since the subwindow could be outside the
1091 1165 window in the gutter or modeline - we also need to allow these
1092 int clear_y = dl->ypos - dl->ascent + pheight; 1166 cases.*/
1093 int clear_height = lheight - pheight; 1167 sdga.xoffset = -dga->xoffset;
1094 1168 sdga.yoffset = -dga->yoffset;
1095 if (start_pixpos >= 0 && start_pixpos > xpos) 1169 sdga.height = IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p);
1096 { 1170 sdga.width = IMAGE_INSTANCE_SUBWINDOW_WIDTH (p);
1097 clear_x = start_pixpos; 1171
1098 clear_width = xpos + width - start_pixpos; 1172 if (redisplay_display_boxes_in_window_p (w, db, &sdga) < 0)
1099 } 1173 {
1100 else 1174 map_subwindow (image_instance, db->xpos, db->ypos, dga);
1101 { 1175 }
1102 clear_x = xpos; 1176 else
1103 clear_width = width; 1177 {
1104 } 1178 sdga.xoffset = sdga.yoffset = 0;
1105 1179 map_subwindow (image_instance, db->xpos - dga->xoffset,
1106 redisplay_clear_region (window, findex, clear_x, clear_y, 1180 db->ypos - dga->yoffset, &sdga);
1107 clear_width, clear_height); 1181 }
1108 } 1182 }
1109 #if 0 1183
1110 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent, 1184 /****************************************************************************
1111 width, lheight); 1185 redisplay_output_layout
1112 #endif 1186
1113 /* if we can't view the whole window we can't view any of it */ 1187 Output a widget hierarchy. This can safely call itself recursively.
1114 if (IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight 1188 ****************************************************************************/
1115 || 1189 void
1116 IMAGE_INSTANCE_SUBWINDOW_WIDTH (p) > width) 1190 redisplay_output_layout (struct window *w,
1117 { 1191 Lisp_Object image_instance,
1118 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent, 1192 struct display_box* db, struct display_glyph_area* dga,
1119 width, lheight); 1193 face_index findex, int cursor_start, int cursor_width,
1120 unmap_subwindow (image_instance); 1194 int cursor_height)
1121 } 1195 {
1122 else 1196 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1123 map_subwindow (image_instance, xpos - xoffset, dl->ypos - dl->ascent); 1197 Lisp_Object window, rest;
1198 Emchar_dynarr *buf = Dynarr_new (Emchar);
1199 struct frame *f = XFRAME (w->frame);
1200 struct device *d = XDEVICE (f->device);
1201 int layout_height, layout_width;
1202 /* We bogusly don't take f->extents_changed and f->glyphs_changed
1203 into account. This is because if we do we always redisplay the
1204 entire layout. So far I have seen no ill effects to we'll see. */
1205 int frame_changed = (f->buffers_changed ||
1206 f->clip_changed ||
1207 f->faces_changed ||
1208 f->frame_changed ||
1209 f->modeline_changed ||
1210 f->subwindows_changed ||
1211 f->windows_changed ||
1212 f->windows_structure_changed);
1213
1214 XSETWINDOW (window, w);
1215
1216 layout_height = glyph_height (image_instance, Qnil, findex, window);
1217 layout_width = glyph_width (image_instance, Qnil, findex, window);
1218
1219 dga->height = layout_height;
1220 dga->width = layout_width;
1221
1222 /* This makes the glyph area fit into the display area. */
1223 if (!redisplay_normalize_glyph_area (db, dga))
1224 return;
1225
1226 /* Highly dodgy optimization. We want to only output the whole
1227 layout if we really have to. */
1228 if (frame_changed || IMAGE_INSTANCE_DIRTYP (p))
1229 {
1230 /* First clear the area we are drawing into. This is the easiest
1231 thing to do since we have many gaps that we have to make sure are
1232 filled in. */
1233 redisplay_clear_clipped_region (window, findex, db, dga, 1, Qnil);
1234
1235 /* Output a border if required */
1236 if (!NILP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1237 {
1238 int edges = 0;
1239 enum edge_style style;
1240 int ypos = db->ypos;
1241 int height = dga->height;
1242
1243 if (dga->xoffset >= 0)
1244 edges |= EDGE_LEFT;
1245 if (dga->width - dga->xoffset == layout_width)
1246 edges |= EDGE_RIGHT;
1247 if (dga->yoffset >= 0)
1248 edges |= EDGE_TOP;
1249 if (dga->height - dga->yoffset == layout_height)
1250 edges |= EDGE_BOTTOM;
1251
1252 if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in))
1253 style = EDGE_ETCHED_IN;
1254 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out))
1255 style = EDGE_ETCHED_OUT;
1256 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qbevel_in))
1257 style = EDGE_BEVEL_IN;
1258 else if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1259 {
1260 style = EDGE_ETCHED_IN;
1261 if (edges & EDGE_TOP)
1262 {
1263 ypos += XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1264 height -= XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1265 }
1266 }
1267 else
1268 style = EDGE_BEVEL_OUT;
1269
1270 MAYBE_DEVMETH (d, bevel_area,
1271 (w, findex, db->xpos,
1272 ypos,
1273 dga->width, height, 2, edges, style));
1274 }
1275 }
1276
1277 /* This shrinks the display box to exactly enclose the glyph
1278 area. */
1279 redisplay_normalize_display_box (db, dga);
1280
1281 /* Flip through the widgets in the layout displaying as necessary */
1282 LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p))
1283 {
1284 Lisp_Object child = XCAR (rest);
1285
1286 struct display_box cdb;
1287 /* For losing HP-UX */
1288 cdb.xpos = db->xpos;
1289 cdb.ypos = db->ypos;
1290 cdb.width = db->width;
1291 cdb.height = db->height;
1292
1293 /* First determine if the image is visible at all */
1294 if (IMAGE_INSTANCEP (child))
1295 {
1296 struct Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child);
1297 /* The enclosing layout offsets are +ve at this point */
1298 struct display_glyph_area cdga;
1299 cdga.xoffset = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset;
1300 cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset;
1301 cdga.width = glyph_width (child, Qnil, findex, window);
1302 cdga.height = glyph_height (child, Qnil, findex, window);
1303
1304 /* Although normalization is done by the output routines
1305 we have to do it here so that they don't try and
1306 clear all of db. This is true below also. */
1307 if (redisplay_normalize_glyph_area (&cdb, &cdga))
1308 {
1309 redisplay_normalize_display_box (&cdb, &cdga);
1310 /* Since the display boxes will now be totally in the
1311 window if they are visible at all we can now check this easily. */
1312 if (cdb.xpos < db->xpos || cdb.ypos < db->ypos
1313 || cdb.xpos + cdb.width > db->xpos + db->width
1314 || cdb.ypos + cdb.height > db->ypos + db->height)
1315 continue;
1316 /* We have to invert the offset here as normalization
1317 will have made them positive which the output
1318 routines will treat as a truely +ve offset. */
1319 cdga.xoffset = -cdga.xoffset;
1320 cdga.yoffset = -cdga.yoffset;
1321
1322 switch (IMAGE_INSTANCE_TYPE (childii))
1323 {
1324 case IMAGE_TEXT:
1325 {
1326 /* #### This is well hacked and could use some
1327 generalisation.*/
1328 if (redisplay_normalize_glyph_area (&cdb, &cdga)
1329 &&
1330 (frame_changed || IMAGE_INSTANCE_DIRTYP (childii)))
1331 {
1332 struct display_line dl; /* this is fake */
1333 Lisp_Object string =
1334 IMAGE_INSTANCE_TEXT_STRING (childii);
1335 convert_bufbyte_string_into_emchar_dynarr
1336 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
1337
1338 redisplay_normalize_display_box (&cdb, &cdga);
1339 /* Offsets are now +ve again so be careful
1340 when fixing up the display line. */
1341 xzero (dl);
1342 /* Munge boxes into display lines. */
1343 dl.ypos = (cdb.ypos - cdga.yoffset)
1344 + glyph_ascent (child, Qnil, findex, window);
1345 dl.ascent = glyph_ascent (child, Qnil, findex, window);
1346 dl.descent = glyph_descent (child, Qnil, findex, window);
1347 dl.top_clip = cdga.yoffset;
1348 dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height);
1349 /* output_string doesn't understand offsets in
1350 the same way as other routines - we have to
1351 add the offset to the width so that we
1352 output the full string. */
1353 MAYBE_DEVMETH (d, output_string, (w, &dl, buf, cdb.xpos,
1354 cdga.xoffset, cdb.xpos,
1355 cdga.width + cdga.xoffset,
1356 findex, 0, 0, 0, 0));
1357 Dynarr_reset (buf);
1358 }
1359 }
1360 break;
1361
1362 case IMAGE_MONO_PIXMAP:
1363 case IMAGE_COLOR_PIXMAP:
1364 if (frame_changed || IMAGE_INSTANCE_DIRTYP (childii))
1365 redisplay_output_pixmap (w, child, &cdb, &cdga, findex,
1366 0, 0, 0, 0);
1367 break;
1368
1369 case IMAGE_WIDGET:
1370 case IMAGE_SUBWINDOW:
1371 if (frame_changed || IMAGE_INSTANCE_DIRTYP (childii))
1372 redisplay_output_subwindow (w, child, &cdb, &cdga, findex,
1373 0, 0, 0);
1374 break;
1375
1376 case IMAGE_LAYOUT:
1377 redisplay_output_layout (w, child, &cdb, &cdga, findex,
1378 0, 0, 0);
1379 break;
1380
1381 case IMAGE_NOTHING:
1382 /* nothing is as nothing does */
1383 break;
1384
1385 case IMAGE_POINTER:
1386 default:
1387 abort ();
1388 }
1389 }
1390 }
1391 }
1392 Dynarr_free (buf);
1393 }
1394
1395 /****************************************************************************
1396 redisplay_output_pixmap
1397
1398
1399 output a pixmap.
1400 ****************************************************************************/
1401 void
1402 redisplay_output_pixmap (struct window *w,
1403 Lisp_Object image_instance,
1404 struct display_box* db, struct display_glyph_area* dga,
1405 face_index findex, int cursor_start, int cursor_width,
1406 int cursor_height, int offset_bitmap)
1407 {
1408 struct frame *f = XFRAME (w->frame);
1409 struct device *d = XDEVICE (f->device);
1410 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1411 Lisp_Object window;
1412 XSETWINDOW (window, w);
1413
1414 dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
1415 dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
1416
1417 /* This makes the glyph area fit into the display area. */
1418 if (!redisplay_normalize_glyph_area (db, dga))
1419 return;
1420
1421 /* Clear the area the pixmap is going into. The pixmap itself will
1422 always take care of the full width. We don't want to clear where
1423 it is going to go in order to avoid flicker. So, all we have to
1424 take care of is any area above or below the pixmap. If the pixmap
1425 has a mask in which case we have to clear the whole damn thing
1426 since we can't yet clear just the area not included in the
1427 mask. */
1428 if (!offset_bitmap)
1429 {
1430 redisplay_clear_clipped_region (window, findex,
1431 db, dga,
1432 (int)IMAGE_INSTANCE_PIXMAP_MASK (p),
1433 Qnil);
1434
1435 /* This shrinks the display box to exactly enclose the glyph
1436 area. */
1437 redisplay_normalize_display_box (db, dga);
1438 }
1439 assert (db->xpos >= 0 && db->ypos >= 0);
1440
1441 MAYBE_DEVMETH (d, output_pixmap, (w, image_instance,
1442 db, dga,
1443 findex, cursor_start,
1444 cursor_width, cursor_height,
1445 offset_bitmap));
1124 } 1446 }
1125 1447
1126 /**************************************************************************** 1448 /****************************************************************************
1127 redisplay_clear_region 1449 redisplay_clear_region
1128 1450
1157 abort (); 1479 abort ();
1158 1480
1159 d = XDEVICE (f->device); 1481 d = XDEVICE (f->device);
1160 1482
1161 /* if we have subwindows in the region we have to unmap them */ 1483 /* if we have subwindows in the region we have to unmap them */
1162 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f))) 1484 redisplay_unmap_subwindows_maybe (f, x, y, width, height);
1163 {
1164 redisplay_unmap_subwindows (f, x, y, width, height);
1165 }
1166 1485
1167 /* #### This isn't quite right for when this function is called 1486 /* #### This isn't quite right for when this function is called
1168 from the toolbar code. */ 1487 from the toolbar code. */
1169 1488
1170 /* Don't use a backing pixmap in the border area */ 1489 /* Don't use a backing pixmap in the border area */
1226 1545
1227 DEVMETH (d, clear_region, 1546 DEVMETH (d, clear_region,
1228 (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap)); 1547 (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1229 } 1548 }
1230 1549
1550 /****************************************************************************
1551 redisplay_clear_clipped_region
1552
1553 Clear the area in the dest display_box not covered by the src
1554 display_glyph_area using the given face. This is a common occurance
1555 for images shorter than the display line. Clipping can be played
1556 around with by altering these. glyphsrc should be normalized.
1557 ****************************************************************************/
1558 static void
1559 redisplay_clear_clipped_region (Lisp_Object window, face_index findex,
1560 struct display_box* dest, struct display_glyph_area* glyphsrc,
1561 int fullheight_p, Lisp_Object ignored_subwindow)
1562 {
1563 /* assume dest->xpos >= 0 */
1564 int clear_x;
1565 struct frame* f = XFRAME (XWINDOW (window)->frame);
1566
1567 if (glyphsrc->xoffset > 0)
1568 {
1569 clear_x = dest->xpos + glyphsrc->xoffset;
1570 }
1571 else
1572 {
1573 clear_x = dest->xpos;
1574 }
1575
1576 /* If we need the whole height cleared then just do it. */
1577 if (fullheight_p)
1578 {
1579 redisplay_clear_region (window, findex, clear_x, dest->ypos,
1580 glyphsrc->width, dest->height);
1581 }
1582 else
1583 {
1584 int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0);
1585
1586 /* We need to make sure that subwindows are unmapped from the
1587 whole area. */
1588 redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos,
1589 glyphsrc->width, dest->height,
1590 ignored_subwindow);
1591 /* first the top box */
1592 if (yoffset > 0)
1593 {
1594 redisplay_clear_region (window, findex, clear_x, dest->ypos,
1595 glyphsrc->width, yoffset);
1596
1597 }
1598 /* Then the bottom box */
1599 if (yoffset + glyphsrc->height < dest->height)
1600 {
1601 redisplay_clear_region (window, findex, clear_x,
1602 dest->ypos + yoffset + glyphsrc->height,
1603 glyphsrc->width,
1604 dest->height - (yoffset + glyphsrc->height));
1605
1606 }
1607 }
1608 }
1609
1610 /*****************************************************************************
1611 redisplay_normalize_glyph_area
1612 redisplay_normalize_display_box
1613
1614 Calculate the visible box for displaying src in dest.
1615 ****************************************************************************/
1616 int
1617 redisplay_normalize_glyph_area (struct display_box* dest,
1618 struct display_glyph_area* glyphsrc)
1619 {
1620 if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width
1621 ||
1622 dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height
1623 ||
1624 -glyphsrc->xoffset >= glyphsrc->width
1625 ||
1626 -glyphsrc->yoffset >= glyphsrc->height)
1627 {
1628 /* It's all clipped out */
1629 return 0;
1630 }
1631
1632 /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */
1633 if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width)
1634 {
1635 if (glyphsrc->xoffset > 0)
1636 glyphsrc->width = dest->width - glyphsrc->xoffset;
1637 else
1638 glyphsrc->width = dest->width;
1639 }
1640
1641 if (glyphsrc->xoffset < 0)
1642 glyphsrc->width += glyphsrc->xoffset;
1643
1644 /* Vertical offsets. This works because yoffset can be -ve as well as +ve */
1645 if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height)
1646 {
1647 if (glyphsrc->yoffset > 0)
1648 glyphsrc->height = dest->height - glyphsrc->yoffset;
1649 else
1650 glyphsrc->height = dest->height;
1651 }
1652
1653 if (glyphsrc->yoffset < 0)
1654 glyphsrc->height += glyphsrc->yoffset;
1655
1656 return 1;
1657 }
1658
1659 static void
1660 redisplay_normalize_display_box (struct display_box* dest,
1661 struct display_glyph_area* glyphsrc)
1662 {
1663 /* Adjust the destination area. At the end of this the destination
1664 area will exactly enclose the glyph area. The only remaining
1665 adjustment will be offsets into the glyph area. */
1666
1667 /* Horizontal adjustment. */
1668 if (glyphsrc->xoffset > 0)
1669 {
1670 dest->xpos += glyphsrc->xoffset;
1671 dest->width -= glyphsrc->xoffset;
1672 glyphsrc->xoffset = 0;
1673 }
1674 else
1675 glyphsrc->xoffset = -glyphsrc->xoffset;
1676
1677 if (glyphsrc->width < dest->width)
1678 dest->width = glyphsrc->width;
1679
1680 /* Vertical adjustment. */
1681 if (glyphsrc->yoffset > 0)
1682 {
1683 dest->ypos += glyphsrc->yoffset;
1684 dest->height -= glyphsrc->yoffset;
1685 glyphsrc->yoffset = 0;
1686 }
1687 else
1688 glyphsrc->yoffset = -glyphsrc->yoffset;
1689
1690 if (glyphsrc->height < dest->height)
1691 dest->height = glyphsrc->height;
1692 }
1693
1694 /*****************************************************************************
1695 redisplay_display_boxes_in_window_p
1696
1697 Determine whether the require display_glyph_area is completely inside
1698 the window. 0 means the display_box is not in the window. 1 means the
1699 display_box and the display_glyph_area are in the window. -1 means
1700 the display_box is in the window but the display_glyph_area is not.
1701 ****************************************************************************/
1702 static int
1703 redisplay_display_boxes_in_window_p (struct window* w,
1704 struct display_box* db,
1705 struct display_glyph_area* dga)
1706 {
1707 int left = WINDOW_TEXT_LEFT (w);
1708 int right = WINDOW_TEXT_RIGHT (w);
1709 int top = WINDOW_TEXT_TOP (w);
1710 int bottom = WINDOW_TEXT_BOTTOM (w);
1711
1712 if (db->xpos < left || db->ypos < top
1713 || db->xpos + db->width > right
1714 || db->ypos + db->height > bottom)
1715 /* We are not displaying in a window at all */
1716 return 0;
1717
1718 if (db->xpos + dga->xoffset >= left
1719 &&
1720 db->ypos + dga->yoffset >= top
1721 &&
1722 db->xpos + dga->xoffset + dga->width <= right
1723 &&
1724 db->ypos + dga->yoffset + dga->height <= bottom)
1725 return 1;
1726
1727 return -1;
1728 }
1729
1730 /*****************************************************************************
1731 redisplay_calculate_display_boxes
1732
1733 Convert from rune/display_line co-ordinates to display_box
1734 co-ordinates.
1735 ****************************************************************************/
1736 int
1737 redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
1738 int xoffset, int start_pixpos, int width,
1739 struct display_box* dest,
1740 struct display_glyph_area* src)
1741 {
1742 dest->xpos = xpos;
1743 dest->ypos = DISPLAY_LINE_YPOS (dl);
1744 dest->width = width;
1745 dest->height = DISPLAY_LINE_HEIGHT (dl);
1746
1747 src->xoffset = -xoffset;
1748 src->yoffset = -dl->top_clip;
1749 src->width = 0;
1750 src->height = 0;
1751
1752 if (start_pixpos >=0 && start_pixpos > xpos)
1753 {
1754 /* Oops, we're asking for a start outside of the displayable
1755 area. */
1756 if (start_pixpos > xpos + width)
1757 return 0;
1758 dest->xpos = start_pixpos;
1759 dest->width -= (start_pixpos - xpos);
1760 /* Offsets are -ve when we want to clip pixels off the displayed
1761 glyph. */
1762 src->xoffset -= (start_pixpos - xpos);
1763 }
1764
1765 return 1;
1766 }
1767
1231 /***************************************************************************** 1768 /*****************************************************************************
1232 redisplay_clear_top_of_window 1769 redisplay_clear_top_of_window
1233 1770
1234 If window is topmost, clear the internal border above it. 1771 If window is topmost, clear the internal border above it.
1235 ****************************************************************************/ 1772 ****************************************************************************/
1281 { 1818 {
1282 int height = ypos2 - ypos1; 1819 int height = ypos2 - ypos1;
1283 1820
1284 if (height) 1821 if (height)
1285 { 1822 {
1286 struct frame *f = XFRAME (w->frame);
1287 Lisp_Object window; 1823 Lisp_Object window;
1288 int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/ 1824 int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/
1289 layout_bounds bounds; 1825 layout_bounds bounds;
1290 1826
1291 bounds = calculate_display_line_boundaries (w, bflag); 1827 bounds = calculate_display_line_boundaries (w, bflag);
1330 void 1866 void
1331 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla, 1867 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1332 int min_start, int max_end) 1868 int min_start, int max_end)
1333 { 1869 {
1334 struct frame *f = XFRAME (w->frame); 1870 struct frame *f = XFRAME (w->frame);
1335 struct device *d = XDEVICE (f->device);
1336 int ypos1, ypos2; 1871 int ypos1, ypos2;
1337 int ddla_len = Dynarr_length (ddla); 1872 int ddla_len = Dynarr_length (ddla);
1338 1873
1339 ypos2 = WINDOW_TEXT_BOTTOM (w); 1874 ypos2 = WINDOW_TEXT_BOTTOM (w);
1340 #ifdef HAVE_SCROLLBARS 1875 #ifdef HAVE_SCROLLBARS
1682 { 2217 {
1683 struct frame *f = XFRAME (w->frame); 2218 struct frame *f = XFRAME (w->frame);
1684 struct device *d = XDEVICE (f->device); 2219 struct device *d = XDEVICE (f->device);
1685 int x, y, width, height; 2220 int x, y, width, height;
1686 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); 2221 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
2222 enum edge_style style;
1687 2223
1688 x = WINDOW_MODELINE_LEFT (w); 2224 x = WINDOW_MODELINE_LEFT (w);
1689 width = WINDOW_MODELINE_RIGHT (w) - x; 2225 width = WINDOW_MODELINE_RIGHT (w) - x;
1690 y = dl->ypos - dl->ascent - shadow_thickness; 2226 y = dl->ypos - dl->ascent - shadow_thickness;
1691 height = dl->ascent + dl->descent + 2 * shadow_thickness; 2227 height = dl->ascent + dl->descent + 2 * shadow_thickness;
1692 2228
1693 if (XINT (w->modeline_shadow_thickness) < 0) 2229 if (XINT (w->modeline_shadow_thickness) < 0)
1694 shadow_thickness = - shadow_thickness; 2230 {
2231 style = EDGE_BEVEL_IN;
2232 }
2233 else
2234 {
2235 style = EDGE_BEVEL_OUT;
2236 }
1695 2237
1696 MAYBE_DEVMETH (d, bevel_area, 2238 MAYBE_DEVMETH (d, bevel_area,
1697 (w, MODELINE_INDEX, x, y, width, height, shadow_thickness)); 2239 (w, MODELINE_INDEX, x, y, width, height, shadow_thickness,
1698 } 2240 EDGE_ALL, style));
2241 }