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