comparison src/redisplay-output.c @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents 501cfd01ee6d
children 95016f13131a
comparison
equal deleted inserted replaced
411:12e008d41344 412:697ef44129c6
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.
6 5
7 This file is part of XEmacs. 6 This file is part of XEmacs.
8 7
9 XEmacs is free software; you can redistribute it and/or modify it 8 XEmacs is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the 9 under the terms of the GNU General Public License as published by the
24 /* Synched up with: Not in FSF. */ 23 /* Synched up with: Not in FSF. */
25 24
26 /* This file has been Mule-ized. */ 25 /* This file has been Mule-ized. */
27 26
28 /* Author: Chuck Thompson */ 27 /* Author: Chuck Thompson */
29
30 /* Heavily hacked for modularity, gutter and subwindow support by Andy
31 Piper. */
32 28
33 #include <config.h> 29 #include <config.h>
34 #include "lisp.h" 30 #include "lisp.h"
35 31
36 #include "buffer.h" 32 #include "buffer.h"
45 struct rune *drb); 41 struct rune *drb);
46 static void redraw_cursor_in_window (struct window *w, 42 static void redraw_cursor_in_window (struct window *w,
47 int run_end_begin_glyphs); 43 int run_end_begin_glyphs);
48 static void redisplay_output_display_block (struct window *w, struct display_line *dl, 44 static void redisplay_output_display_block (struct window *w, struct display_line *dl,
49 int block, int start, int end, int start_pixpos, 45 int block, int start, int end, int start_pixpos,
50 int cursor_start, int cursor_width, 46 int cursor_start, int cursor_width,
51 int cursor_height); 47 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);
61 48
62 /***************************************************************************** 49 /*****************************************************************************
63 sync_rune_structs 50 sync_rune_structs
64 51
65 Synchronize the given rune blocks. 52 Synchronize the given rune blocks.
99 sync_display_line_structs 86 sync_display_line_structs
100 87
101 For the given LINE in window W, make the current display line equal 88 For the given LINE in window W, make the current display line equal
102 the desired display line. 89 the desired display line.
103 ****************************************************************************/ 90 ****************************************************************************/
104 void 91 static void
105 sync_display_line_structs (struct window *w, int line, int do_blocks, 92 sync_display_line_structs (struct window *w, int line, int do_blocks,
106 display_line_dynarr *cdla, 93 display_line_dynarr *cdla,
107 display_line_dynarr *ddla) 94 display_line_dynarr *ddla)
108 { 95 {
109 int cdla_len = Dynarr_length (cdla); 96 int cdla_len = Dynarr_length (cdla);
188 compare_runes (struct window *w, struct rune *crb, struct rune *drb) 175 compare_runes (struct window *w, struct rune *crb, struct rune *drb)
189 { 176 {
190 /* Do not compare the values of bufpos and endpos. They do not 177 /* Do not compare the values of bufpos and endpos. They do not
191 affect the display characteristics. */ 178 affect the display characteristics. */
192 179
193 /* Note: (hanoi 6) spends 95% of its time in redisplay, and about 180 if ((crb->findex != drb->findex) ||
194 30% here. Not using bitfields for rune.type alone gives a redisplay 181 (WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
195 speed up of 10%. 182 return 0;
196 183 else if (crb->xpos != drb->xpos)
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. */
213
214 if (crb->xpos != drb->xpos)
215 return 0; 184 return 0;
216 else if (crb->width != drb->width) 185 else if (crb->width != drb->width)
217 return 0; 186 return 0;
218 else if (crb->cursor_type != drb->cursor_type) 187 else if (crb->cursor_type != drb->cursor_type)
219 return 0; 188 return 0;
220 else if (crb->type != drb->type) 189 else if (crb->type != drb->type)
221 return 0; 190 return 0;
222 else if (crb->type == RUNE_CHAR && 191 else if (crb->type == RUNE_CHAR &&
223 (crb->object.chr.ch != drb->object.chr.ch)) 192 (crb->object.chr.ch != drb->object.chr.ch))
224 return 0; 193 return 0;
225 else if (crb->type == RUNE_HLINE &&
226 (crb->object.hline.thickness != drb->object.hline.thickness ||
227 crb->object.hline.yoffset != drb->object.hline.yoffset))
228 return 0;
229 else if (crb->type == RUNE_DGLYPH && 194 else if (crb->type == RUNE_DGLYPH &&
230 (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) || 195 (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) ||
231 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) || 196 !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) ||
232 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset)) 197 crb->object.dglyph.xoffset != drb->object.dglyph.xoffset))
233 return 0; 198 return 0;
234 /* Only check dirtiness if we know something has changed. */ 199 else if (crb->type == RUNE_HLINE &&
235 else if (crb->type == RUNE_DGLYPH && 200 (crb->object.hline.thickness != drb->object.hline.thickness ||
236 (XGLYPH_DIRTYP (crb->object.dglyph.glyph) || 201 crb->object.hline.yoffset != drb->object.hline.yoffset))
237 crb->findex != drb->findex))
238 {
239 /* We need some way of telling redisplay_output_layout () that the
240 only reason we are outputting it is because something has
241 changed internally. That way we can optimize whether we need
242 to clear the layout first and also only output the components
243 that have changed. The image_instance dirty flag and
244 display_hash are no good to us because these will invariably
245 have been set anyway if the layout has changed. So it looks
246 like we need yet another change flag that we can set here and
247 then clear in redisplay_output_layout (). */
248 Lisp_Object window, image;
249 Lisp_Image_Instance* ii;
250 XSETWINDOW (window, w);
251 image = glyph_image_instance (crb->object.dglyph.glyph,
252 window, ERROR_ME_NOT, 1);
253
254 if (!IMAGE_INSTANCEP (image))
255 return 0;
256 ii = XIMAGE_INSTANCE (image);
257
258 if (TEXT_IMAGE_INSTANCEP (image) &&
259 (crb->findex != drb->findex ||
260 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
261 return 0;
262
263 /* It is quite common of the two glyphs to be EQ since in many
264 cases they will actually be the same object. This does not
265 mean, however, that nothing has changed. We therefore need to
266 check the current hash of the glyph against the last recorded
267 display hash and the pending display items. See
268 update_subwindow (). */
269 if (image_instance_changed (image) ||
270 crb->findex != drb->findex ||
271 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
272 {
273 /* We now now we are going to re-output the glyph, but since
274 this is for some internal reason not related to geometry
275 changes, send a hint to the output routines that they can
276 take some short cuts. This is most useful for
277 layouts. This flag should get reset by the output
278 routines.
279
280 #### It is possible for us to get here when the
281 face_cachel is dirty. I do not know what the implications
282 of this are.*/
283 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (ii) = 1;
284 return 0;
285 }
286 else
287 return 1;
288 }
289 /* We now do this last so that glyph checks can do their own thing
290 for face changes. Face changes quite often happen when we are
291 trying to output something in the gutter, this would normally
292 lead to a lot of flashing. The indices can quite often be
293 different and yet the faces are the same, we do not want to
294 re-output in this instance. */
295 else if (crb->findex != drb->findex ||
296 WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
297 return 0; 202 return 0;
298 else 203 else
299 return 1; 204 return 1;
300 } 205 }
301 206
444 #endif 349 #endif
445 ) 350 )
446 force = 1; 351 force = 1;
447 352
448 if (f->windows_structure_changed || 353 if (f->windows_structure_changed ||
449 /* #### Why is this so? We have face cachels so that we don't
450 have to recalculate all the display blocks when faces
451 change. I have fixed this for glyphs and am inclined to think
452 that faces should "Just Work", but I'm not feeling brave
453 today. Maybe its because the face cachels represent merged
454 faces rather than simply instantiations in a particular
455 domain. */
456 f->faces_changed || 354 f->faces_changed ||
355 f->glyphs_changed ||
457 cdl->ypos != ddl->ypos || 356 cdl->ypos != ddl->ypos ||
458 cdl->ascent != ddl->ascent || 357 cdl->ascent != ddl->ascent ||
459 cdl->descent != ddl->descent || 358 cdl->descent != ddl->descent ||
460 cdl->clip != ddl->clip || 359 cdl->clip != ddl->clip ||
461 force) 360 force)
688 f->faces_changed || 587 f->faces_changed ||
689 force || 588 force ||
690 (cdl && (cdl->ypos != ddl->ypos || 589 (cdl && (cdl->ypos != ddl->ypos ||
691 cdl->ascent != ddl->ascent || 590 cdl->ascent != ddl->ascent ||
692 cdl->descent != ddl->descent || 591 cdl->descent != ddl->descent ||
693 cdl->top_clip != ddl->top_clip ||
694 cdl->clip != ddl->clip))) 592 cdl->clip != ddl->clip)))
695 { 593 {
696 int x, y, width, height; 594 int x, y, width, height;
697 face_index findex; 595 Lisp_Object face;
698 596
699 must_sync = 1; 597 must_sync = 1;
700 x = start_pixpos; 598 x = start_pixpos;
701 y = DISPLAY_LINE_YPOS (ddl); 599 y = ddl->ypos - ddl->ascent;
702 width = min (next_start_pixpos, block_end) - x; 600 width = min (next_start_pixpos, block_end) - x;
703 height = DISPLAY_LINE_HEIGHT (ddl); 601 height = ddl->ascent + ddl->descent - ddl->clip;
704 602
705 if (x < ddl->bounds.left_in) 603 if (x < ddl->bounds.left_in)
706 { 604 face = Vleft_margin_face;
707 findex = ddl->left_margin_findex ?
708 ddl->left_margin_findex
709 : get_builtin_face_cache_index (w, Vleft_margin_face);
710 }
711 else if (x < ddl->bounds.right_in) 605 else if (x < ddl->bounds.right_in)
712 { 606 face = Vdefault_face;
713 /* no check here because DEFAULT_INDEX == 0 anyway */
714 findex = ddl->default_findex;
715 }
716 else if (x < ddl->bounds.right_out) 607 else if (x < ddl->bounds.right_out)
717 { 608 face = Vright_margin_face;
718 findex = ddl->right_margin_findex ?
719 ddl->right_margin_findex
720 : get_builtin_face_cache_index (w, Vright_margin_face);
721 }
722 else 609 else
723 findex = (face_index) -1; 610 face = Qnil;
724 611
725 if (findex != (face_index) -1) 612 if (!NILP (face))
726 { 613 {
727 Lisp_Object window; 614 Lisp_Object window;
728 615
729 XSETWINDOW (window, w); 616 XSETWINDOW (window, w);
730 617
731 /* Clear the empty area. */ 618 /* Clear the empty area. */
732 redisplay_clear_region (window, findex, x, y, width, height); 619 redisplay_clear_region (window, get_builtin_face_cache_index (w, face),
620 x, y, width, height);
733 621
734 /* Mark that we should clear the border. This is 622 /* Mark that we should clear the border. This is
735 necessary because italic fonts may leave 623 necessary because italic fonts may leave
736 droppings in the border. */ 624 droppings in the border. */
737 clear_border = 1; 625 clear_border = 1;
758 646
759 /* If there was formerly no block over the current 647 /* If there was formerly no block over the current
760 region or if it was a block of a different type, then 648 region or if it was a block of a different type, then
761 output the entire ddb. Otherwise, compare cdb and 649 output the entire ddb. Otherwise, compare cdb and
762 ddb and output only the changed region. */ 650 ddb and output only the changed region. */
763 if (!force && cdb && ddb->type == cdb->type 651 if (!force && cdb && ddb->type == cdb->type && b == old_b)
764 /* If there was no buffer being display before the
765 compare anyway as we might be outputting a gutter. */
766 &&
767 (b == old_b || !old_b))
768 { 652 {
769 must_sync |= compare_display_blocks (w, cdl, ddl, old_block, 653 must_sync |= compare_display_blocks (w, cdl, ddl, old_block,
770 block, start_pixpos, 654 block, start_pixpos,
771 cursor_start, cursor_width, 655 cursor_start, cursor_width,
772 cursor_height); 656 cursor_height);
800 last_elt, 684 last_elt,
801 start_pixpos, 685 start_pixpos,
802 cursor_start, cursor_width, 686 cursor_start, cursor_width,
803 cursor_height); 687 cursor_height);
804 } 688 }
805 689
806 start_pixpos = next_start_pixpos; 690 start_pixpos = next_start_pixpos;
807 } 691 }
808 } 692 }
809 693
810 /* Clear the internal border if we are next to it and the window 694 /* Clear the internal border if we are next to it and the window
813 /* #### Doing this on f->clear sucks but is necessary because of 697 /* #### Doing this on f->clear sucks but is necessary because of
814 window-local background values. */ 698 window-local background values. */
815 if (f->windows_structure_changed || f->faces_changed || clear_border 699 if (f->windows_structure_changed || f->faces_changed || clear_border
816 || f->clear) 700 || f->clear)
817 { 701 {
818 int y = DISPLAY_LINE_YPOS (ddl); 702 int y = ddl->ypos - ddl->ascent;
819 int height = DISPLAY_LINE_HEIGHT (ddl); 703 int height = ddl->ascent + ddl->descent - ddl->clip;
820 704
821 /* If we are in the gutter then we musn't clear the borders. */ 705 if (ddl->modeline)
822 if (y >= WINDOW_TEXT_TOP (w) && (y + height) <= WINDOW_TEXT_BOTTOM (w)) 706 {
823 { 707 y -= MODELINE_SHADOW_THICKNESS (w);
824 if (ddl->modeline) 708 height += (2 * MODELINE_SHADOW_THICKNESS (w));
825 { 709 }
826 y -= MODELINE_SHADOW_THICKNESS (w); 710
827 height += (2 * MODELINE_SHADOW_THICKNESS (w)); 711 if (window_is_leftmost (w))
828 } 712 clear_left_border (w, y, height);
829 713 if (window_is_rightmost (w))
830 if (window_is_leftmost (w)) 714 clear_right_border (w, y, height);
831 clear_left_border (w, y, height);
832 if (window_is_rightmost (w))
833 clear_right_border (w, y, height);
834 }
835 } 715 }
836 716
837 if (cdla) 717 if (cdla)
838 sync_display_line_structs (w, line, must_sync, cdla, ddla); 718 sync_display_line_structs (w, line, must_sync, cdla, ddla);
839 } 719 }
896 dl->cursor_elt = x; 776 dl->cursor_elt = x;
897 return 1; 777 return 1;
898 } 778 }
899 else 779 else
900 { 780 {
901 { 781 DEVMETH (d, output_begin, (d));
902 MAYBE_DEVMETH (d, frame_output_begin, (f)); 782
903 MAYBE_DEVMETH (d, window_output_begin, (w)); 783 /* #### This is a gross kludge. Cursor handling is such a royal
904 } 784 pain in the ass. */
905 rb->cursor_type = CURSOR_OFF; 785 if (rb->type == RUNE_DGLYPH &&
786 (EQ (rb->object.dglyph.glyph, Vtruncation_glyph) ||
787 EQ (rb->object.dglyph.glyph, Vcontinuation_glyph)))
788 rb->cursor_type = NO_CURSOR;
789 else
790 rb->cursor_type = CURSOR_OFF;
906 dl->cursor_elt = -1; 791 dl->cursor_elt = -1;
907 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width); 792 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
908 } 793 }
909 794
910 w->last_point_x[CURRENT_DISP] = -1; 795 w->last_point_x[CURRENT_DISP] = -1;
914 /* If this isn't the selected frame, then erasing the old cursor is 799 /* If this isn't the selected frame, then erasing the old cursor is
915 all we actually had to do. */ 800 all we actually had to do. */
916 if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d)))) 801 if (w != XWINDOW (FRAME_SELECTED_WINDOW (device_selected_frame (d))))
917 { 802 {
918 if (!no_output_end) 803 if (!no_output_end)
919 { 804 DEVMETH (d, output_end, (d));
920 MAYBE_DEVMETH (d, window_output_end, (w));
921 MAYBE_DEVMETH (d, frame_output_end, (f));
922 }
923 805
924 return 1; 806 return 1;
925 } 807 }
926 808
927 /* This should only occur in the minibuffer. */ 809 /* This should only occur in the minibuffer. */
936 dl->cursor_elt = 0; 818 dl->cursor_elt = 0;
937 819
938 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width); 820 output_display_line (w, 0, cla, y, rb->xpos, rb->xpos + rb->width);
939 821
940 if (!no_output_end) 822 if (!no_output_end)
941 { 823 DEVMETH (d, output_end, (d));
942 MAYBE_DEVMETH (d, window_output_end, (w));
943 MAYBE_DEVMETH (d, frame_output_end, (f));
944 }
945 return 1; 824 return 1;
946 } 825 }
947 else 826 else
948 { 827 {
949 int cur_rb = 0; 828 int cur_rb = 0;
971 cur_dl = y; 850 cur_dl = y;
972 first = 1; 851 first = 1;
973 } 852 }
974 } 853 }
975 854
976 while (up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0)) 855 while ((up ? (cur_dl < Dynarr_length (cla)) : (cur_dl >= 0)))
977 { 856 {
978 dl = Dynarr_atp (cla, cur_dl); 857 dl = Dynarr_atp (cla, cur_dl);
979 db = get_display_block_from_line (dl, TEXT); 858 db = get_display_block_from_line (dl, TEXT);
980 859
981 if (!up && !first) 860 if (!up && !first)
1003 w->last_point_y[CURRENT_DISP] = cur_dl; 882 w->last_point_y[CURRENT_DISP] = cur_dl;
1004 Fset_marker (w->last_point[CURRENT_DISP], 883 Fset_marker (w->last_point[CURRENT_DISP],
1005 make_int (ADJ_BUFPOS), w->buffer); 884 make_int (ADJ_BUFPOS), w->buffer);
1006 885
1007 if (!no_output_end) 886 if (!no_output_end)
1008 { 887 DEVMETH (d, output_end, (d));
1009 MAYBE_DEVMETH (d, window_output_end, (w));
1010 MAYBE_DEVMETH (d, frame_output_end, (f));
1011 }
1012 return 1; 888 return 1;
1013 } 889 }
1014 890
1015 (up ? cur_rb++ : cur_rb--); 891 (up ? cur_rb++ : cur_rb--);
1016 } 892 }
1019 (up ? cur_dl++ : cur_dl--); 895 (up ? cur_dl++ : cur_dl--);
1020 } 896 }
1021 } 897 }
1022 898
1023 if (!no_output_end) 899 if (!no_output_end)
1024 { 900 DEVMETH (d, output_end, (d));
1025 MAYBE_DEVMETH (d, window_output_end, (w));
1026 MAYBE_DEVMETH (d, frame_output_end, (f));
1027 }
1028 return 0; 901 return 0;
1029 } 902 }
1030 #undef ADJ_BUFPOS 903 #undef ADJ_BUFPOS
1031 #undef ADJ_ENDPOS 904 #undef ADJ_ENDPOS
1032 905
1077 { 950 {
1078 MAYBE_DEVMETH (d, set_final_cursor_coords, 951 MAYBE_DEVMETH (d, set_final_cursor_coords,
1079 (f, dl->ypos - 1, rb->xpos)); 952 (f, dl->ypos - 1, rb->xpos));
1080 953
1081 if (run_end_begin_meths) 954 if (run_end_begin_meths)
1082 { 955 DEVMETH (d, output_begin, (d));
1083 MAYBE_DEVMETH (d, frame_output_begin, (f));
1084 MAYBE_DEVMETH (d, window_output_begin, (w));
1085 }
1086 956
1087 output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width); 957 output_display_line (w, 0, dla, y, rb->xpos, rb->xpos + rb->width);
1088 958
1089 if (run_end_begin_meths) 959 if (run_end_begin_meths)
1090 { 960 DEVMETH (d, output_end, (d));
1091 MAYBE_DEVMETH (d, window_output_end, (w));
1092 MAYBE_DEVMETH (d, frame_output_end, (f));
1093 }
1094 } 961 }
1095 } 962 }
1096 963
1097 /***************************************************************************** 964 /*****************************************************************************
1098 redisplay_redraw_cursor 965 redisplay_redraw_cursor
1126 int start, int end, int start_pixpos, int cursor_start, 993 int start, int end, int start_pixpos, int cursor_start,
1127 int cursor_width, int cursor_height) 994 int cursor_width, int cursor_height)
1128 { 995 {
1129 struct frame *f = XFRAME (w->frame); 996 struct frame *f = XFRAME (w->frame);
1130 struct device *d = XDEVICE (f->device); 997 struct device *d = XDEVICE (f->device);
1131 /* Temporarily disabled until generalization is done. */ 998
1132 #if 0
1133 struct display_block *db = Dynarr_atp (dl->display_blocks, block);
1134 rune_dynarr *rba = db->runes;
1135 struct rune *rb;
1136 int xpos, width;
1137 rb = Dynarr_atp (rba, start);
1138
1139 if (!rb)
1140 /* Nothing to do so don't do anything. */
1141 return;
1142
1143 xpos = max (start_pixpos, rb->xpos);
1144
1145 if (end < 0)
1146 end = Dynarr_length (rba);
1147
1148 rb = Dynarr_atp (rba, end - 1);
1149 width = rb->xpos + rb->width - xpos;
1150 #endif
1151 /* now actually output the block. */
1152 DEVMETH (d, output_display_block, (w, dl, block, start, 999 DEVMETH (d, output_display_block, (w, dl, block, start,
1153 end, start_pixpos, 1000 end, start_pixpos,
1154 cursor_start, cursor_width, 1001 cursor_start, cursor_width,
1155 cursor_height)); 1002 cursor_height));
1156 } 1003 }
1157 1004
1158 /**************************************************************************** 1005 /****************************************************************************
1159 redisplay_unmap_subwindows 1006 redisplay_unmap_subwindows
1160 1007
1161 Remove subwindows from the area in the box defined by the given 1008 Remove subwindows from the area in the box defined by the given
1162 parameters. 1009 parameters.
1163 ****************************************************************************/ 1010 ****************************************************************************/
1164 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height, 1011 static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height)
1165 Lisp_Object ignored_window) 1012 {
1166 { 1013 int elt;
1167 Lisp_Object rest; 1014
1168 1015 for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
1169 LIST_LOOP (rest, XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))) 1016 {
1170 { 1017 struct subwindow_cachel *cachel =
1171 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (XCAR (rest)); 1018 Dynarr_atp (f->subwindow_cachels, elt);
1172 1019
1173 if (IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) 1020 if (cachel->being_displayed
1174 && 1021 &&
1175 IMAGE_INSTANCE_DISPLAY_X (ii) 1022 cachel->x + cachel->width > x && cachel->x < x + width
1176 + IMAGE_INSTANCE_DISPLAY_WIDTH (ii) > x
1177 &&
1178 IMAGE_INSTANCE_DISPLAY_X (ii) < x + width
1179 && 1023 &&
1180 IMAGE_INSTANCE_DISPLAY_Y (ii) 1024 cachel->y + cachel->height > y && cachel->y < y + height)
1181 + IMAGE_INSTANCE_DISPLAY_HEIGHT (ii) > y 1025 {
1182 && 1026 unmap_subwindow (cachel->subwindow);
1183 IMAGE_INSTANCE_DISPLAY_Y (ii) < y + height
1184 &&
1185 !EQ (XCAR (rest), ignored_window))
1186 {
1187 unmap_subwindow (XCAR (rest));
1188 } 1027 }
1189 } 1028 }
1190 } 1029 }
1191 1030
1192 /**************************************************************************** 1031 /****************************************************************************
1195 Potentially subwindows from the area in the box defined by the given 1034 Potentially subwindows from the area in the box defined by the given
1196 parameters. 1035 parameters.
1197 ****************************************************************************/ 1036 ****************************************************************************/
1198 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height) 1037 void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height)
1199 { 1038 {
1200 if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f)))) 1039 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1201 { 1040 {
1202 redisplay_unmap_subwindows (f, x, y, width, height, Qnil); 1041 redisplay_unmap_subwindows (f, x, y, width, height);
1203 }
1204 }
1205
1206 static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width,
1207 int height, Lisp_Object subwindow)
1208 {
1209 if (!NILP (XWEAK_LIST_LIST (FRAME_SUBWINDOW_CACHE (f))))
1210 {
1211 redisplay_unmap_subwindows (f, x, y, width, height, subwindow);
1212 } 1042 }
1213 } 1043 }
1214 1044
1215 /**************************************************************************** 1045 /****************************************************************************
1216 redisplay_output_subwindow 1046 redisplay_output_subwindow
1047
1217 1048
1218 output a subwindow. This code borrows heavily from the pixmap stuff, 1049 output a subwindow. This code borrows heavily from the pixmap stuff,
1219 although is much simpler not needing to account for partial 1050 although is much simpler not needing to account for partial
1220 pixmaps, backgrounds etc. 1051 pixmaps, backgrounds etc.
1221 ****************************************************************************/ 1052 ****************************************************************************/
1222 void 1053 void
1223 redisplay_output_subwindow (struct window *w, 1054 redisplay_output_subwindow (struct window *w, struct display_line *dl,
1224 Lisp_Object image_instance, 1055 Lisp_Object image_instance, int xpos, int xoffset,
1225 struct display_box* db, struct display_glyph_area* dga, 1056 int start_pixpos, int width, face_index findex,
1226 face_index findex, int cursor_start, int cursor_width, 1057 int cursor_start, int cursor_width, int cursor_height)
1227 int cursor_height) 1058 {
1228 { 1059 struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1229 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1230 Lisp_Object window; 1060 Lisp_Object window;
1231 struct display_glyph_area sdga; 1061
1232 1062 int lheight = dl->ascent + dl->descent - dl->clip;
1233 dga->height = IMAGE_INSTANCE_HEIGHT (p); 1063 int pheight = ((int) IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight ? lheight :
1234 dga->width = IMAGE_INSTANCE_WIDTH (p); 1064 IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p));
1235
1236 /* The first thing we are going to do is update the display
1237 characteristics of the subwindow. This also clears the dirty
1238 flags as a side effect. */
1239 update_subwindow (image_instance);
1240
1241 /* This makes the glyph area fit into the display area. */
1242 if (!redisplay_normalize_glyph_area (db, dga))
1243 return;
1244 1065
1245 XSETWINDOW (window, w); 1066 XSETWINDOW (window, w);
1246 1067
1247 /* Clear the area the subwindow is going into. */ 1068 /* Clear the area the subwindow is going into. The subwindow itself
1248 redisplay_clear_clipped_region (window, findex, 1069 will always take care of the full width. We don't want to clear
1249 db, dga, 0, image_instance); 1070 where it is going to go in order to avoid flicker. So, all we
1250 1071 have to take care of is any area above or below the subwindow. Of
1251 /* This shrinks the display box to exactly enclose the glyph 1072 course this is rubbish if the subwindow has transparent areas
1252 area. */ 1073 (for instance with frames). */
1253 redisplay_normalize_display_box (db, dga); 1074 /* #### We take a shortcut for now. We know that since we have
1254 1075 subwindow_offset hardwired to 0 that the subwindow is against the top
1255 /* if we can't view the whole window we can't view any of it. We 1076 edge so all we have to worry about is below it. */
1256 have to be careful here since we may be being asked to display 1077 if ((int) (dl->ypos - dl->ascent + pheight) <
1257 part of a subwindow, the rest of which is on-screen as well. We 1078 (int) (dl->ypos + dl->descent - dl->clip))
1258 need to allow this case and map the entire subwindow. We also 1079 {
1259 need to be careful since the subwindow could be outside the 1080 int clear_x, clear_width;
1260 window in the gutter or modeline - we also need to allow these 1081
1261 cases.*/ 1082 int clear_y = dl->ypos - dl->ascent + pheight;
1262 sdga.xoffset = -dga->xoffset; 1083 int clear_height = lheight - pheight;
1263 sdga.yoffset = -dga->yoffset; 1084
1264 sdga.height = IMAGE_INSTANCE_HEIGHT (p); 1085 if (start_pixpos >= 0 && start_pixpos > xpos)
1265 sdga.width = IMAGE_INSTANCE_WIDTH (p); 1086 {
1266 1087 clear_x = start_pixpos;
1267 if (redisplay_display_boxes_in_window_p (w, db, &sdga) < 0) 1088 clear_width = xpos + width - start_pixpos;
1268 { 1089 }
1269 map_subwindow (image_instance, db->xpos, db->ypos, dga); 1090 else
1270 } 1091 {
1271 else 1092 clear_x = xpos;
1272 { 1093 clear_width = width;
1273 sdga.xoffset = sdga.yoffset = 0; 1094 }
1274 map_subwindow (image_instance, db->xpos - dga->xoffset, 1095
1275 db->ypos - dga->yoffset, &sdga); 1096 redisplay_clear_region (window, findex, clear_x, clear_y,
1276 } 1097 clear_width, clear_height);
1277 } 1098 }
1278 1099 #if 0
1279 /**************************************************************************** 1100 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent,
1280 redisplay_output_layout 1101 width, lheight);
1281
1282 Output a widget hierarchy. This can safely call itself recursively.
1283
1284 The complexity of outputting layouts is deciding whether to do it or
1285 not. Consider a layout enclosing some text, the text changes and is
1286 marked as dirty, but the enclosing layout has not been marked as
1287 dirty so no updates occur and the text will potentially be truncated.
1288 Alternatively we hold a back pointer in the image instance to the
1289 parent and mark the parent as dirty. But the layout code assumes that
1290 if the layout is dirty then the whole layout should be redisplayed,
1291 so we then get lots of flashing even though only the text has changed
1292 size. Of course if the text shrinks in size then we do actually need
1293 to redisplay the layout to repaint the exposed area. So what happens
1294 if we make a non-structural change like changing color? Either we
1295 redisplay everything, or we redisplay nothing. These are exactly the
1296 issues lwlib has to grapple with. We really need to know what has
1297 actually changed and make a layout decision based on that. We also
1298 really need to know what has changed so that we can only make the
1299 neccessary changes in update_subwindow. This has all now been
1300 implemented, Viva la revolution!
1301 ****************************************************************************/
1302 void
1303 redisplay_output_layout (struct window *w,
1304 Lisp_Object image_instance,
1305 struct display_box* db, struct display_glyph_area* dga,
1306 face_index findex, int cursor_start, int cursor_width,
1307 int cursor_height)
1308 {
1309 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1310 Lisp_Object window, rest;
1311 Emchar_dynarr *buf = Dynarr_new (Emchar);
1312 struct frame *f = XFRAME (w->frame);
1313 struct device *d = XDEVICE (f->device);
1314 int layout_height, layout_width;
1315
1316 XSETWINDOW (window, w);
1317
1318 layout_height = glyph_height (image_instance, window);
1319 layout_width = glyph_width (image_instance, window);
1320
1321 dga->height = layout_height;
1322 dga->width = layout_width;
1323 #ifdef DEBUG_WIDGET_OUTPUT
1324 printf ("outputing layout glyph %p\n", p);
1325 #endif 1102 #endif
1326 /* This makes the glyph area fit into the display area. */ 1103 /* if we can't view the whole window we can't view any of it */
1327 if (!redisplay_normalize_glyph_area (db, dga)) 1104 if (IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight
1328 return; 1105 ||
1329 1106 IMAGE_INSTANCE_SUBWINDOW_WIDTH (p) > width)
1330 /* Highly dodgy optimization. We want to only output the whole 1107 {
1331 layout if we really have to. */ 1108 redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent,
1332 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p) 1109 width, lheight);
1333 || IMAGE_INSTANCE_LAYOUT_CHANGED (p) 1110 unmap_subwindow (image_instance);
1334 || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p) 1111 }
1335 || IMAGE_INSTANCE_SIZE_CHANGED (p) 1112 else
1336 || IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (p)) 1113 map_subwindow (image_instance, xpos - xoffset, dl->ypos - dl->ascent);
1337 {
1338 /* First clear the area we are drawing into. This is the easiest
1339 thing to do since we have many gaps that we have to make sure are
1340 filled in. */
1341 redisplay_clear_clipped_region (window, findex, db, dga, 1, Qnil);
1342
1343 /* Output a border if required */
1344 if (!NILP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1345 {
1346 int edges = 0;
1347 enum edge_style style;
1348 int ypos = db->ypos;
1349 int height = dga->height;
1350
1351 if (dga->xoffset >= 0)
1352 edges |= EDGE_LEFT;
1353 if (dga->width - dga->xoffset == layout_width)
1354 edges |= EDGE_RIGHT;
1355 if (dga->yoffset >= 0)
1356 edges |= EDGE_TOP;
1357 if (dga->height - dga->yoffset == layout_height)
1358 edges |= EDGE_BOTTOM;
1359
1360 if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in))
1361 style = EDGE_ETCHED_IN;
1362 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out))
1363 style = EDGE_ETCHED_OUT;
1364 else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qbevel_in))
1365 style = EDGE_BEVEL_IN;
1366 else if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (p)))
1367 {
1368 style = EDGE_ETCHED_IN;
1369 if (edges & EDGE_TOP)
1370 {
1371 ypos += XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1372 height -= XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p));
1373 }
1374 }
1375 else
1376 style = EDGE_BEVEL_OUT;
1377
1378 MAYBE_DEVMETH (d, bevel_area,
1379 (w, findex, db->xpos,
1380 ypos,
1381 dga->width, height, 2, edges, style));
1382 }
1383 }
1384
1385 /* This shrinks the display box to exactly enclose the glyph
1386 area. */
1387 redisplay_normalize_display_box (db, dga);
1388
1389 /* Flip through the widgets in the layout displaying as necessary */
1390 LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p))
1391 {
1392 Lisp_Object child = XCAR (rest);
1393
1394 struct display_box cdb;
1395 /* For losing HP-UX */
1396 cdb.xpos = db->xpos;
1397 cdb.ypos = db->ypos;
1398 cdb.width = db->width;
1399 cdb.height = db->height;
1400
1401 /* First determine if the image is visible at all */
1402 if (IMAGE_INSTANCEP (child))
1403 {
1404 Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child);
1405
1406 /* The enclosing layout offsets are +ve at this point */
1407 struct display_glyph_area cdga;
1408 cdga.xoffset = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset;
1409 cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset;
1410 cdga.width = glyph_width (child, window);
1411 cdga.height = glyph_height (child, window);
1412
1413 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) =
1414 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p);
1415
1416 /* Although normalization is done by the output routines
1417 we have to do it here so that they don't try and
1418 clear all of db. This is true below also. */
1419 if (redisplay_normalize_glyph_area (&cdb, &cdga))
1420 {
1421 redisplay_normalize_display_box (&cdb, &cdga);
1422 /* Since the display boxes will now be totally in the
1423 window if they are visible at all we can now check this easily. */
1424 if (cdb.xpos < db->xpos || cdb.ypos < db->ypos
1425 || cdb.xpos + cdb.width > db->xpos + db->width
1426 || cdb.ypos + cdb.height > db->ypos + db->height)
1427 continue;
1428 /* We have to invert the offset here as normalization
1429 will have made them positive which the output
1430 routines will treat as a truly +ve offset. */
1431 cdga.xoffset = -cdga.xoffset;
1432 cdga.yoffset = -cdga.yoffset;
1433
1434 switch (IMAGE_INSTANCE_TYPE (childii))
1435 {
1436 case IMAGE_TEXT:
1437 {
1438 /* #### This is well hacked and could use some
1439 generalisation.*/
1440 if (redisplay_normalize_glyph_area (&cdb, &cdga)
1441 &&
1442 (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
1443 IMAGE_INSTANCE_DIRTYP (childii)))
1444 {
1445 struct display_line dl; /* this is fake */
1446 Lisp_Object string =
1447 IMAGE_INSTANCE_TEXT_STRING (childii);
1448 unsigned char charsets[NUM_LEADING_BYTES];
1449 struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, findex);
1450
1451 find_charsets_in_bufbyte_string (charsets,
1452 XSTRING_DATA (string),
1453 XSTRING_LENGTH (string));
1454 ensure_face_cachel_complete (cachel, window, charsets);
1455
1456 convert_bufbyte_string_into_emchar_dynarr
1457 (XSTRING_DATA (string), XSTRING_LENGTH (string), buf);
1458
1459 redisplay_normalize_display_box (&cdb, &cdga);
1460 /* Offsets are now +ve again so be careful
1461 when fixing up the display line. */
1462 xzero (dl);
1463 /* Munge boxes into display lines. */
1464 dl.ypos = (cdb.ypos - cdga.yoffset)
1465 + glyph_ascent (child, window);
1466 dl.ascent = glyph_ascent (child, window);
1467 dl.descent = glyph_descent (child, window);
1468 dl.top_clip = cdga.yoffset;
1469 dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height);
1470 /* output_string doesn't understand offsets in
1471 the same way as other routines - we have to
1472 add the offset to the width so that we
1473 output the full string. */
1474 MAYBE_DEVMETH (d, output_string, (w, &dl, buf, cdb.xpos,
1475 cdga.xoffset, cdb.xpos,
1476 cdga.width + cdga.xoffset,
1477 findex, 0, 0, 0, 0));
1478 Dynarr_reset (buf);
1479 }
1480 }
1481 break;
1482
1483 case IMAGE_MONO_PIXMAP:
1484 case IMAGE_COLOR_PIXMAP:
1485 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii)
1486 || IMAGE_INSTANCE_DIRTYP (childii))
1487 redisplay_output_pixmap (w, child, &cdb, &cdga, findex,
1488 0, 0, 0, 0);
1489 break;
1490
1491 case IMAGE_WIDGET:
1492 if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (childii), Qlayout))
1493 {
1494 redisplay_output_layout (w, child, &cdb, &cdga, findex,
1495 0, 0, 0);
1496 break;
1497 }
1498 case IMAGE_SUBWINDOW:
1499 if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
1500 IMAGE_INSTANCE_DIRTYP (childii))
1501 redisplay_output_subwindow (w, child, &cdb, &cdga, findex,
1502 0, 0, 0);
1503 break;
1504
1505 case IMAGE_NOTHING:
1506 /* nothing is as nothing does */
1507 break;
1508
1509 case IMAGE_POINTER:
1510 default:
1511 abort ();
1512 }
1513 }
1514 IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 0;
1515 }
1516 }
1517
1518 /* Update any display properties. I'm not sure whether this actually
1519 does anything for layouts except clear the changed flags. */
1520 update_subwindow (image_instance);
1521
1522 Dynarr_free (buf);
1523 }
1524
1525 /****************************************************************************
1526 redisplay_output_pixmap
1527
1528
1529 output a pixmap.
1530 ****************************************************************************/
1531 void
1532 redisplay_output_pixmap (struct window *w,
1533 Lisp_Object image_instance,
1534 struct display_box* db, struct display_glyph_area* dga,
1535 face_index findex, int cursor_start, int cursor_width,
1536 int cursor_height, int offset_bitmap)
1537 {
1538 struct frame *f = XFRAME (w->frame);
1539 struct device *d = XDEVICE (f->device);
1540 Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance);
1541 Lisp_Object window;
1542 XSETWINDOW (window, w);
1543
1544 dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p);
1545 dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p);
1546
1547 /* This makes the glyph area fit into the display area. */
1548 if (!redisplay_normalize_glyph_area (db, dga))
1549 return;
1550
1551 /* Clear the area the pixmap is going into. The pixmap itself will
1552 always take care of the full width. We don't want to clear where
1553 it is going to go in order to avoid flicker. So, all we have to
1554 take care of is any area above or below the pixmap. If the pixmap
1555 has a mask in which case we have to clear the whole damn thing
1556 since we can't yet clear just the area not included in the
1557 mask. */
1558 if (!offset_bitmap)
1559 {
1560 redisplay_clear_clipped_region (window, findex,
1561 db, dga,
1562 (int)IMAGE_INSTANCE_PIXMAP_MASK (p),
1563 Qnil);
1564
1565 /* This shrinks the display box to exactly enclose the glyph
1566 area. */
1567 redisplay_normalize_display_box (db, dga);
1568 }
1569 assert (db->xpos >= 0 && db->ypos >= 0);
1570
1571 MAYBE_DEVMETH (d, output_pixmap, (w, image_instance,
1572 db, dga,
1573 findex, cursor_start,
1574 cursor_width, cursor_height,
1575 offset_bitmap));
1576 } 1114 }
1577 1115
1578 /**************************************************************************** 1116 /****************************************************************************
1579 redisplay_clear_region 1117 redisplay_clear_region
1580 1118
1609 abort (); 1147 abort ();
1610 1148
1611 d = XDEVICE (f->device); 1149 d = XDEVICE (f->device);
1612 1150
1613 /* if we have subwindows in the region we have to unmap them */ 1151 /* if we have subwindows in the region we have to unmap them */
1614 redisplay_unmap_subwindows_maybe (f, x, y, width, height); 1152 if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f)))
1153 {
1154 redisplay_unmap_subwindows (f, x, y, width, height);
1155 }
1615 1156
1616 /* #### This isn't quite right for when this function is called 1157 /* #### This isn't quite right for when this function is called
1617 from the toolbar code. */ 1158 from the toolbar code. */
1618 1159
1619 /* Don't use a backing pixmap in the border area */ 1160 /* Don't use a backing pixmap in the border area */
1620 if (x >= FRAME_LEFT_BORDER_END (f) 1161 if (x >= FRAME_LEFT_BORDER_END (f)
1621 && x < FRAME_RIGHT_BORDER_START (f) 1162 && x < FRAME_RIGHT_BORDER_START (f)
1622 && y >= FRAME_TOP_BORDER_END (f) 1163 && y >= FRAME_TOP_BORDER_END (f)
1623 && y < FRAME_BOTTOM_BORDER_START (f)) 1164 && y < FRAME_BOTTOM_BORDER_START (f))
1624 { 1165 {
1625 Lisp_Object temp; 1166 Lisp_Object temp;
1626 1167
1627 if (w) 1168 if (w)
1628 { 1169 {
1629 temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex); 1170 temp = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, findex);
1630 1171
1631 if (IMAGE_INSTANCEP (temp) 1172 if (IMAGE_INSTANCEP (temp)
1632 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp))) 1173 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1633 { 1174 {
1634 /* #### maybe we could implement such that a string 1175 /* #### maybe we could implement such that a string
1635 can be a background pixmap? */ 1176 can be a background pixmap? */
1637 } 1178 }
1638 } 1179 }
1639 else 1180 else
1640 { 1181 {
1641 temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale); 1182 temp = FACE_BACKGROUND_PIXMAP (Vdefault_face, locale);
1642 1183
1643 if (IMAGE_INSTANCEP (temp) 1184 if (IMAGE_INSTANCEP (temp)
1644 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp))) 1185 && IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (temp)))
1645 { 1186 {
1646 background_pixmap = temp; 1187 background_pixmap = temp;
1647 } 1188 }
1648 } 1189 }
1649 } 1190 }
1650 1191
1651 if (!UNBOUNDP (background_pixmap) && 1192 if (!UNBOUNDP (background_pixmap) &&
1652 XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0) 1193 XIMAGE_INSTANCE_PIXMAP_DEPTH (background_pixmap) == 0)
1653 { 1194 {
1654 if (w) 1195 if (w)
1665 else 1206 else
1666 { 1207 {
1667 fcolor = (w ? 1208 fcolor = (w ?
1668 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) : 1209 WINDOW_FACE_CACHEL_BACKGROUND (w, findex) :
1669 FACE_BACKGROUND (Vdefault_face, locale)); 1210 FACE_BACKGROUND (Vdefault_face, locale));
1670 1211
1671 } 1212 }
1672 1213
1673 if (UNBOUNDP (background_pixmap)) 1214 if (UNBOUNDP (background_pixmap))
1674 background_pixmap = Qnil; 1215 background_pixmap = Qnil;
1675 1216
1676 DEVMETH (d, clear_region, 1217 DEVMETH (d, clear_region,
1677 (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap)); 1218 (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap));
1678 }
1679
1680 /****************************************************************************
1681 redisplay_clear_clipped_region
1682
1683 Clear the area in the dest display_box not covered by the src
1684 display_glyph_area using the given face. This is a common occurance
1685 for images shorter than the display line. Clipping can be played
1686 around with by altering these. glyphsrc should be normalized.
1687 ****************************************************************************/
1688 static void
1689 redisplay_clear_clipped_region (Lisp_Object window, face_index findex,
1690 struct display_box* dest, struct display_glyph_area* glyphsrc,
1691 int fullheight_p, Lisp_Object ignored_subwindow)
1692 {
1693 /* assume dest->xpos >= 0 */
1694 int clear_x;
1695 struct frame* f = XFRAME (XWINDOW (window)->frame);
1696
1697 if (glyphsrc->xoffset > 0)
1698 {
1699 clear_x = dest->xpos + glyphsrc->xoffset;
1700 }
1701 else
1702 {
1703 clear_x = dest->xpos;
1704 }
1705
1706 /* If we need the whole height cleared then just do it. */
1707 if (fullheight_p)
1708 {
1709 redisplay_clear_region (window, findex, clear_x, dest->ypos,
1710 glyphsrc->width, dest->height);
1711 }
1712 else
1713 {
1714 int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0);
1715
1716 /* We need to make sure that subwindows are unmapped from the
1717 whole area. */
1718 redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos,
1719 glyphsrc->width, dest->height,
1720 ignored_subwindow);
1721 /* first the top box */
1722 if (yoffset > 0)
1723 {
1724 redisplay_clear_region (window, findex, clear_x, dest->ypos,
1725 glyphsrc->width, yoffset);
1726
1727 }
1728 /* Then the bottom box */
1729 if (yoffset + glyphsrc->height < dest->height)
1730 {
1731 redisplay_clear_region (window, findex, clear_x,
1732 dest->ypos + yoffset + glyphsrc->height,
1733 glyphsrc->width,
1734 dest->height - (yoffset + glyphsrc->height));
1735
1736 }
1737 }
1738 }
1739
1740 /*****************************************************************************
1741 redisplay_normalize_glyph_area
1742 redisplay_normalize_display_box
1743
1744 Calculate the visible box for displaying src in dest.
1745 ****************************************************************************/
1746 int
1747 redisplay_normalize_glyph_area (struct display_box* dest,
1748 struct display_glyph_area* glyphsrc)
1749 {
1750 if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width
1751 ||
1752 dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height
1753 ||
1754 -glyphsrc->xoffset >= glyphsrc->width
1755 ||
1756 -glyphsrc->yoffset >= glyphsrc->height)
1757 {
1758 /* It's all clipped out */
1759 return 0;
1760 }
1761
1762 /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */
1763 if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width)
1764 {
1765 if (glyphsrc->xoffset > 0)
1766 glyphsrc->width = dest->width - glyphsrc->xoffset;
1767 else
1768 glyphsrc->width = dest->width;
1769 }
1770
1771 if (glyphsrc->xoffset < 0)
1772 glyphsrc->width += glyphsrc->xoffset;
1773
1774 /* Vertical offsets. This works because yoffset can be -ve as well as +ve */
1775 if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height)
1776 {
1777 if (glyphsrc->yoffset > 0)
1778 glyphsrc->height = dest->height - glyphsrc->yoffset;
1779 else
1780 glyphsrc->height = dest->height;
1781 }
1782
1783 if (glyphsrc->yoffset < 0)
1784 glyphsrc->height += glyphsrc->yoffset;
1785
1786 return 1;
1787 }
1788
1789 static void
1790 redisplay_normalize_display_box (struct display_box* dest,
1791 struct display_glyph_area* glyphsrc)
1792 {
1793 /* Adjust the destination area. At the end of this the destination
1794 area will exactly enclose the glyph area. The only remaining
1795 adjustment will be offsets into the glyph area. */
1796
1797 /* Horizontal adjustment. */
1798 if (glyphsrc->xoffset > 0)
1799 {
1800 dest->xpos += glyphsrc->xoffset;
1801 dest->width -= glyphsrc->xoffset;
1802 glyphsrc->xoffset = 0;
1803 }
1804 else
1805 glyphsrc->xoffset = -glyphsrc->xoffset;
1806
1807 if (glyphsrc->width < dest->width)
1808 dest->width = glyphsrc->width;
1809
1810 /* Vertical adjustment. */
1811 if (glyphsrc->yoffset > 0)
1812 {
1813 dest->ypos += glyphsrc->yoffset;
1814 dest->height -= glyphsrc->yoffset;
1815 glyphsrc->yoffset = 0;
1816 }
1817 else
1818 glyphsrc->yoffset = -glyphsrc->yoffset;
1819
1820 if (glyphsrc->height < dest->height)
1821 dest->height = glyphsrc->height;
1822 }
1823
1824 /*****************************************************************************
1825 redisplay_display_boxes_in_window_p
1826
1827 Determine whether the require display_glyph_area is completely inside
1828 the window. 0 means the display_box is not in the window. 1 means the
1829 display_box and the display_glyph_area are in the window. -1 means
1830 the display_box is in the window but the display_glyph_area is not.
1831 ****************************************************************************/
1832 static int
1833 redisplay_display_boxes_in_window_p (struct window* w,
1834 struct display_box* db,
1835 struct display_glyph_area* dga)
1836 {
1837 int left = WINDOW_TEXT_LEFT (w);
1838 int right = WINDOW_TEXT_RIGHT (w);
1839 int top = WINDOW_TEXT_TOP (w);
1840 int bottom = WINDOW_TEXT_BOTTOM (w);
1841
1842 if (db->xpos < left || db->ypos < top
1843 || db->xpos + db->width > right
1844 || db->ypos + db->height > bottom)
1845 /* We are not displaying in a window at all */
1846 return 0;
1847
1848 if (db->xpos + dga->xoffset >= left
1849 &&
1850 db->ypos + dga->yoffset >= top
1851 &&
1852 db->xpos + dga->xoffset + dga->width <= right
1853 &&
1854 db->ypos + dga->yoffset + dga->height <= bottom)
1855 return 1;
1856
1857 return -1;
1858 }
1859
1860 /*****************************************************************************
1861 redisplay_calculate_display_boxes
1862
1863 Convert from rune/display_line co-ordinates to display_box
1864 co-ordinates.
1865 ****************************************************************************/
1866 int
1867 redisplay_calculate_display_boxes (struct display_line *dl, int xpos,
1868 int xoffset, int start_pixpos, int width,
1869 struct display_box* dest,
1870 struct display_glyph_area* src)
1871 {
1872 dest->xpos = xpos;
1873 dest->ypos = DISPLAY_LINE_YPOS (dl);
1874 dest->width = width;
1875 dest->height = DISPLAY_LINE_HEIGHT (dl);
1876
1877 src->xoffset = -xoffset;
1878 src->yoffset = -dl->top_clip;
1879 src->width = 0;
1880 src->height = 0;
1881
1882 if (start_pixpos >=0 && start_pixpos > xpos)
1883 {
1884 /* Oops, we're asking for a start outside of the displayable
1885 area. */
1886 if (start_pixpos > xpos + width)
1887 return 0;
1888 dest->xpos = start_pixpos;
1889 dest->width -= (start_pixpos - xpos);
1890 /* Offsets are -ve when we want to clip pixels off the displayed
1891 glyph. */
1892 src->xoffset -= (start_pixpos - xpos);
1893 }
1894
1895 return 1;
1896 } 1219 }
1897 1220
1898 /***************************************************************************** 1221 /*****************************************************************************
1899 redisplay_clear_top_of_window 1222 redisplay_clear_top_of_window
1900 1223
1924 1247
1925 y = FRAME_TOP_BORDER_START (f) - 1; 1248 y = FRAME_TOP_BORDER_START (f) - 1;
1926 height = FRAME_BORDER_HEIGHT (f) + 1; 1249 height = FRAME_BORDER_HEIGHT (f) + 1;
1927 1250
1928 redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height); 1251 redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
1929 }
1930 }
1931
1932 /*****************************************************************************
1933 redisplay_clear_to_window_end
1934
1935 Clear the area between ypos1 and ypos2. Each margin area and the
1936 text area is handled separately since they may each have their own
1937 background color.
1938 ****************************************************************************/
1939 void
1940 redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2)
1941 {
1942 struct frame *f = XFRAME (w->frame);
1943 struct device *d = XDEVICE (f->device);
1944
1945 if (HAS_DEVMETH_P (d, clear_to_window_end))
1946 DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
1947 else
1948 {
1949 int height = ypos2 - ypos1;
1950
1951 if (height)
1952 {
1953 Lisp_Object window;
1954 int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/
1955 layout_bounds bounds;
1956
1957 bounds = calculate_display_line_boundaries (w, bflag);
1958 XSETWINDOW (window, w);
1959
1960 if (window_is_leftmost (w))
1961 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
1962 ypos1, FRAME_BORDER_WIDTH (f), height);
1963
1964 if (bounds.left_in - bounds.left_out > 0)
1965 redisplay_clear_region (window,
1966 get_builtin_face_cache_index (w, Vleft_margin_face),
1967 bounds.left_out, ypos1,
1968 bounds.left_in - bounds.left_out, height);
1969
1970 if (bounds.right_in - bounds.left_in > 0)
1971 redisplay_clear_region (window,
1972 DEFAULT_INDEX,
1973 bounds.left_in, ypos1,
1974 bounds.right_in - bounds.left_in, height);
1975
1976 if (bounds.right_out - bounds.right_in > 0)
1977 redisplay_clear_region (window,
1978 get_builtin_face_cache_index (w, Vright_margin_face),
1979 bounds.right_in, ypos1,
1980 bounds.right_out - bounds.right_in, height);
1981
1982 if (window_is_rightmost (w))
1983 redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
1984 ypos1, FRAME_BORDER_WIDTH (f), height);
1985 }
1986 } 1252 }
1987 } 1253 }
1988 1254
1989 /***************************************************************************** 1255 /*****************************************************************************
1990 redisplay_clear_bottom_of_window 1256 redisplay_clear_bottom_of_window
1996 void 1262 void
1997 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla, 1263 redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla,
1998 int min_start, int max_end) 1264 int min_start, int max_end)
1999 { 1265 {
2000 struct frame *f = XFRAME (w->frame); 1266 struct frame *f = XFRAME (w->frame);
1267 struct device *d = XDEVICE (f->device);
2001 int ypos1, ypos2; 1268 int ypos1, ypos2;
2002 int ddla_len = Dynarr_length (ddla); 1269 int ddla_len = Dynarr_length (ddla);
2003 1270
2004 ypos2 = WINDOW_TEXT_BOTTOM (w); 1271 ypos2 = WINDOW_TEXT_BOTTOM (w);
2005 #ifdef HAVE_SCROLLBARS 1272 #ifdef HAVE_SCROLLBARS
2039 ypos2 = max_end; 1306 ypos2 = max_end;
2040 1307
2041 if (ypos2 <= ypos1) 1308 if (ypos2 <= ypos1)
2042 return; 1309 return;
2043 1310
2044 redisplay_clear_to_window_end (w, ypos1, ypos2); 1311 DEVMETH (d, clear_to_window_end, (w, ypos1, ypos2));
2045 } 1312 }
2046 1313
2047 /***************************************************************************** 1314 /*****************************************************************************
2048 redisplay_update_line 1315 redisplay_update_line
2049 1316
2059 struct device *d = XDEVICE (f->device); 1326 struct device *d = XDEVICE (f->device);
2060 1327
2061 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP); 1328 display_line_dynarr *cdla = window_display_lines (w, CURRENT_DISP);
2062 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP); 1329 display_line_dynarr *ddla = window_display_lines (w, DESIRED_DISP);
2063 1330
2064 MAYBE_DEVMETH (d, window_output_begin, (w)); 1331 DEVMETH (d, output_begin, (d));
2065 1332
2066 while (first_line <= last_line) 1333 while (first_line <= last_line)
2067 { 1334 {
2068 Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos - 1335 Charcount old_len = (Dynarr_atp (cdla, first_line)->end_bufpos -
2069 Dynarr_atp (cdla, first_line)->bufpos); 1336 Dynarr_atp (cdla, first_line)->bufpos);
2144 update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack); 1411 update_window_scrollbars (w, NULL, 1, stupid_vertical_scrollbar_drag_hack);
2145 stupid_vertical_scrollbar_drag_hack = 1; 1412 stupid_vertical_scrollbar_drag_hack = 1;
2146 } 1413 }
2147 #endif 1414 #endif
2148 1415
2149 redisplay_redraw_cursor (f, 0); 1416 /* This has to be done after we've updated the values. We don't
2150 MAYBE_DEVMETH (d, window_output_end, (w)); 1417 call output_end for tty frames. Redisplay will do this after all
1418 tty windows have been updated. This cuts down on cursor
1419 flicker. */
1420 if (FRAME_TTY_P (f))
1421 redisplay_redraw_cursor (f, 0);
1422 else
1423 DEVMETH (d, output_end, (d));
2151 } 1424 }
2152 1425
2153 /***************************************************************************** 1426 /*****************************************************************************
2154 redisplay_output_window 1427 redisplay_output_window
2155 1428
2259 } 1532 }
2260 } 1533 }
2261 } 1534 }
2262 1535
2263 /* Perform any output initialization. */ 1536 /* Perform any output initialization. */
2264 MAYBE_DEVMETH (d, window_output_begin, (w)); 1537 DEVMETH (d, output_begin, (d));
2265 1538
2266 /* If the window's structure has changed clear the internal border 1539 /* If the window's structure has changed clear the internal border
2267 above it if it is topmost (the function will check). */ 1540 above it if it is topmost (the function will check). */
2268 if (f->windows_structure_changed) 1541 if (f->windows_structure_changed)
2269 redisplay_clear_top_of_window (w); 1542 redisplay_clear_top_of_window (w);
2282 1555
2283 /* Output a vertical divider between windows, if necessary. */ 1556 /* Output a vertical divider between windows, if necessary. */
2284 if (window_needs_vertical_divider (w) 1557 if (window_needs_vertical_divider (w)
2285 && (f->windows_structure_changed || f->clear)) 1558 && (f->windows_structure_changed || f->clear))
2286 { 1559 {
2287 MAYBE_DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed)); 1560 DEVMETH (d, output_vertical_divider, (w, f->windows_structure_changed));
2288 } 1561 }
2289 1562
2290 /* Clear the rest of the window, if necessary. */ 1563 /* Clear the rest of the window, if necessary. */
2291 if (need_to_clear_bottom) 1564 if (need_to_clear_bottom)
2292 { 1565 {
2316 1589
2317 /* Overkill on invalidating the cache. It is very bad for it to not 1590 /* Overkill on invalidating the cache. It is very bad for it to not
2318 get invalidated when it should be. */ 1591 get invalidated when it should be. */
2319 INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d); 1592 INVALIDATE_DEVICE_PIXEL_TO_GLYPH_CACHE (d);
2320 1593
2321 redisplay_redraw_cursor (f, 0); 1594 /* We don't call output_end for tty frames. Redisplay will do this
2322 MAYBE_DEVMETH (d, window_output_end, (w)); 1595 after all tty windows have been updated. This cuts down on
1596 cursor flicker. */
1597 if (FRAME_TTY_P (f))
1598 redisplay_redraw_cursor (f, 0);
1599 else
1600 DEVMETH (d, output_end, (d));
2323 1601
2324 #ifdef HAVE_SCROLLBARS 1602 #ifdef HAVE_SCROLLBARS
2325 update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0); 1603 update_window_scrollbars (w, NULL, !MINI_WINDOW_P (w), 0);
2326 #endif 1604 #endif
2327 } 1605 }
2328
2329 /*****************************************************************************
2330 bevel_modeline
2331
2332 Draw a 3d border around the modeline on window W.
2333 ****************************************************************************/
2334 void
2335 bevel_modeline (struct window *w, struct display_line *dl)
2336 {
2337 struct frame *f = XFRAME (w->frame);
2338 struct device *d = XDEVICE (f->device);
2339 int x, y, width, height;
2340 int shadow_thickness = MODELINE_SHADOW_THICKNESS (w);
2341 enum edge_style style;
2342
2343 x = WINDOW_MODELINE_LEFT (w);
2344 width = WINDOW_MODELINE_RIGHT (w) - x;
2345 y = dl->ypos - dl->ascent - shadow_thickness;
2346 height = dl->ascent + dl->descent + 2 * shadow_thickness;
2347
2348 if (XINT (w->modeline_shadow_thickness) < 0)
2349 {
2350 style = EDGE_BEVEL_IN;
2351 }
2352 else
2353 {
2354 style = EDGE_BEVEL_OUT;
2355 }
2356
2357 MAYBE_DEVMETH (d, bevel_area,
2358 (w, MODELINE_INDEX, x, y, width, height, shadow_thickness,
2359 EDGE_ALL, style));
2360 }