Mercurial > hg > xemacs-beta
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 } |