aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2010-07-05 18:58:31 +0900
committerYAMAMOTO Mitsuharu2010-07-05 18:58:31 +0900
commit5a874e95ef18724f1658e10785baddaf6761cfd7 (patch)
tree749c731920e335a40ac88dc0ac3037eb99df3e23 /src
parent0682186e3a4c8d1806e75fb357f2bc244a526183 (diff)
downloademacs-5a874e95ef18724f1658e10785baddaf6761cfd7.tar.gz
emacs-5a874e95ef18724f1658e10785baddaf6761cfd7.zip
Fix ghost buffer boundary indicators in fringes (Bug#5634, Bug#6325).
* dispextern.h (FRINGE_HEIGHT_BITS): New define. (struct glyph_row): New members left_fringe_offset and right_fringe_offset. * xterm.c (x_draw_fringe_bitmap): Don't clip bottom aligned bitmap specially. * w32term.c (w32_draw_fringe_bitmap): Likewise. * nsterm.m (ns_draw_fringe_bitmap): Likewise. * fringe.c (draw_fringe_bitmap_1): Don't clip bitmap here. Take account of bitmap offset. (draw_window_fringes): Take account of window vscroll. (update_window_fringes): Likewise. Extend top-aligned top indicator or bottom-aligned bottom indicator to adjacent rows if it doesn't fit in one row. Don't set redraw_fringe_bitmaps_p outside row comparison. Set left_fringe_offset and right_fringe_offset (Bug#5634, Bug#6325).
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog19
-rw-r--r--src/dispextern.h8
-rw-r--r--src/fringe.c275
-rw-r--r--src/nsterm.m15
-rw-r--r--src/w32term.c17
-rw-r--r--src/xterm.c17
6 files changed, 244 insertions, 107 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index dd896d27746..ce190e745e0 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,22 @@
12010-07-05 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
2
3 * dispextern.h (FRINGE_HEIGHT_BITS): New define.
4 (struct glyph_row): New members left_fringe_offset and
5 right_fringe_offset.
6
7 * xterm.c (x_draw_fringe_bitmap): Don't clip bottom aligned bitmap
8 specially.
9 * w32term.c (w32_draw_fringe_bitmap): Likewise.
10 * nsterm.m (ns_draw_fringe_bitmap): Likewise.
11
12 * fringe.c (draw_fringe_bitmap_1): Don't clip bitmap here.
13 Take account of bitmap offset.
14 (draw_window_fringes): Take account of window vscroll.
15 (update_window_fringes): Likewise. Extend top-aligned top indicator
16 or bottom-aligned bottom indicator to adjacent rows if it doesn't fit
17 in one row. Don't set redraw_fringe_bitmaps_p outside row comparison.
18 Set left_fringe_offset and right_fringe_offset (Bug#5634, Bug#6325).
19
12010-07-04 Juanma Barranquero <lekktu@gmail.com> 202010-07-04 Juanma Barranquero <lekktu@gmail.com>
2 21
3 * w32fns.c (Qtooltip): Declare. 22 * w32fns.c (Qtooltip): Declare.
diff --git a/src/dispextern.h b/src/dispextern.h
index 22d44fc9083..6b73a2573ac 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -105,6 +105,8 @@ enum window_part
105/* Number of bits allocated to store fringe bitmap numbers. */ 105/* Number of bits allocated to store fringe bitmap numbers. */
106#define FRINGE_ID_BITS 16 106#define FRINGE_ID_BITS 16
107 107
108/* Number of bits allocated to store fringe bitmap height. */
109#define FRINGE_HEIGHT_BITS 8
108 110
109 111
110/*********************************************************************** 112/***********************************************************************
@@ -778,6 +780,12 @@ struct glyph_row
778 /* Face of the right fringe glyph. */ 780 /* Face of the right fringe glyph. */
779 unsigned right_fringe_face_id : FACE_ID_BITS; 781 unsigned right_fringe_face_id : FACE_ID_BITS;
780 782
783 /* Vertical offset of the left fringe bitmap. */
784 signed left_fringe_offset : FRINGE_HEIGHT_BITS;
785
786 /* Vertical offset of the right fringe bitmap. */
787 signed right_fringe_offset : FRINGE_HEIGHT_BITS;
788
781 /* 1 means that we must draw the bitmaps of this row. */ 789 /* 1 means that we must draw the bitmaps of this row. */
782 unsigned redraw_fringe_bitmaps_p : 1; 790 unsigned redraw_fringe_bitmaps_p : 1;
783 791
diff --git a/src/fringe.c b/src/fringe.c
index ded19933e5e..2425e236b98 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -561,23 +561,26 @@ draw_fringe_bitmap_1 (w, row, left_p, overlay, which)
561 struct fringe_bitmap *fb; 561 struct fringe_bitmap *fb;
562 int period; 562 int period;
563 int face_id = DEFAULT_FACE_ID; 563 int face_id = DEFAULT_FACE_ID;
564 int offset, header_line_height;
564 565
565 p.cursor_p = 0;
566 p.overlay_p = (overlay & 1) == 1; 566 p.overlay_p = (overlay & 1) == 1;
567 p.cursor_p = (overlay & 2) == 2; 567 p.cursor_p = (overlay & 2) == 2;
568 568
569 if (which != NO_FRINGE_BITMAP) 569 if (which != NO_FRINGE_BITMAP)
570 { 570 {
571 offset = 0;
571 } 572 }
572 else if (left_p) 573 else if (left_p)
573 { 574 {
574 which = row->left_fringe_bitmap; 575 which = row->left_fringe_bitmap;
575 face_id = row->left_fringe_face_id; 576 face_id = row->left_fringe_face_id;
577 offset = row->left_fringe_offset;
576 } 578 }
577 else 579 else
578 { 580 {
579 which = row->right_fringe_bitmap; 581 which = row->right_fringe_bitmap;
580 face_id = row->right_fringe_face_id; 582 face_id = row->right_fringe_face_id;
583 offset = row->right_fringe_offset;
581 } 584 }
582 585
583 if (face_id == DEFAULT_FACE_ID) 586 if (face_id == DEFAULT_FACE_ID)
@@ -598,7 +601,7 @@ draw_fringe_bitmap_1 (w, row, left_p, overlay, which)
598 period = fb->period; 601 period = fb->period;
599 602
600 /* Convert row to frame coordinates. */ 603 /* Convert row to frame coordinates. */
601 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); 604 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y) + offset;
602 605
603 p.which = which; 606 p.which = which;
604 p.bits = fb->bits; 607 p.bits = fb->bits;
@@ -607,9 +610,19 @@ draw_fringe_bitmap_1 (w, row, left_p, overlay, which)
607 p.h = fb->height; 610 p.h = fb->height;
608 p.dh = (period > 0 ? (p.y % period) : 0); 611 p.dh = (period > 0 ? (p.y % period) : 0);
609 p.h -= p.dh; 612 p.h -= p.dh;
610 /* Clip bitmap if too high. */ 613
611 if (p.h > row->height) 614 /* Adjust y to the offset in the row to start drawing the bitmap. */
612 p.h = row->height; 615 switch (fb->align)
616 {
617 case ALIGN_BITMAP_CENTER:
618 p.y += (row->height - p.h) / 2;
619 break;
620 case ALIGN_BITMAP_BOTTOM:
621 p.y += (row->visible_height - p.h);
622 break;
623 case ALIGN_BITMAP_TOP:
624 break;
625 }
613 626
614 p.face = FACE_FROM_ID (f, face_id); 627 p.face = FACE_FROM_ID (f, face_id);
615 628
@@ -625,6 +638,9 @@ draw_fringe_bitmap_1 (w, row, left_p, overlay, which)
625 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill 638 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
626 the fringe. */ 639 the fringe. */
627 p.bx = -1; 640 p.bx = -1;
641 header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
642 p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
643 p.ny = row->visible_height;
628 if (left_p) 644 if (left_p)
629 { 645 {
630 int wd = WINDOW_LEFT_FRINGE_WIDTH (w); 646 int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
@@ -635,7 +651,7 @@ draw_fringe_bitmap_1 (w, row, left_p, overlay, which)
635 p.wd = wd; 651 p.wd = wd;
636 p.x = x - p.wd - (wd - p.wd) / 2; 652 p.x = x - p.wd - (wd - p.wd) / 2;
637 653
638 if (p.wd < wd || row->height > p.h) 654 if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
639 { 655 {
640 /* If W has a vertical border to its left, don't draw over it. */ 656 /* If W has a vertical border to its left, don't draw over it. */
641 wd -= ((!WINDOW_LEFTMOST_P (w) 657 wd -= ((!WINDOW_LEFTMOST_P (w)
@@ -657,35 +673,13 @@ draw_fringe_bitmap_1 (w, row, left_p, overlay, which)
657 p.x = x + (wd - p.wd) / 2; 673 p.x = x + (wd - p.wd) / 2;
658 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill 674 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
659 the fringe. */ 675 the fringe. */
660 if (p.wd < wd || row->height > p.h) 676 if (p.wd < wd || p.y > p.by || p.y + p.h < p.by + p.ny)
661 { 677 {
662 p.bx = x; 678 p.bx = x;
663 p.nx = wd; 679 p.nx = wd;
664 } 680 }
665 } 681 }
666 682
667 if (p.bx >= 0)
668 {
669 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
670
671 p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
672 p.ny = row->visible_height;
673 }
674
675 /* Adjust y to the offset in the row to start drawing the bitmap. */
676 switch (fb->align)
677 {
678 case ALIGN_BITMAP_CENTER:
679 p.y += (row->height - p.h) / 2;
680 break;
681 case ALIGN_BITMAP_BOTTOM:
682 p.h = fb->height;
683 p.y += (row->visible_height - p.h);
684 break;
685 case ALIGN_BITMAP_TOP:
686 break;
687 }
688
689 FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p); 683 FRAME_RIF (f)->draw_fringe_bitmap (w, row, &p);
690} 684}
691 685
@@ -911,7 +905,7 @@ draw_window_fringes (w, no_fringe)
911 struct glyph_row *row; 905 struct glyph_row *row;
912 int yb = window_text_bottom_y (w); 906 int yb = window_text_bottom_y (w);
913 int nrows = w->current_matrix->nrows; 907 int nrows = w->current_matrix->nrows;
914 int y = 0, rn; 908 int y, rn;
915 int updated = 0; 909 int updated = 0;
916 910
917 if (w->pseudo_window_p) 911 if (w->pseudo_window_p)
@@ -923,7 +917,7 @@ draw_window_fringes (w, no_fringe)
923 || WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)) 917 || WINDOW_RIGHT_FRINGE_WIDTH (w) == 0))
924 updated++; 918 updated++;
925 919
926 for (y = 0, rn = 0, row = w->current_matrix->rows; 920 for (y = w->vscroll, rn = 0, row = w->current_matrix->rows;
927 y < yb && rn < nrows; 921 y < yb && rn < nrows;
928 y += row->height, ++row, ++rn) 922 y += row->height, ++row, ++rn)
929 { 923 {
@@ -959,6 +953,9 @@ update_window_fringes (w, keep_current_p)
959 Lisp_Object ind = Qnil; 953 Lisp_Object ind = Qnil;
960#define MAX_BITMAP_CACHE (8*4) 954#define MAX_BITMAP_CACHE (8*4)
961 int bitmap_cache[MAX_BITMAP_CACHE]; 955 int bitmap_cache[MAX_BITMAP_CACHE];
956 int top_ind_rn, bot_ind_rn;
957 int top_ind_min_y, bot_ind_max_y;
958 int top_row_ends_at_zv_p, bot_row_ends_at_zv_p;
962 959
963 if (w->pseudo_window_p) 960 if (w->pseudo_window_p)
964 return 0; 961 return 0;
@@ -987,11 +984,10 @@ update_window_fringes (w, keep_current_p)
987 boundary_top = boundary_bot = Qleft; 984 boundary_top = boundary_bot = Qleft;
988 } 985 }
989 986
987 top_ind_rn = bot_ind_rn = -1;
990 if (!NILP (ind)) 988 if (!NILP (ind))
991 { 989 {
992 int done_top = 0, done_bot = 0; 990 for (y = w->vscroll, rn = 0;
993
994 for (y = 0, rn = 0;
995 y < yb && rn < nrows; 991 y < yb && rn < nrows;
996 y += row->height, ++rn) 992 y += row->height, ++rn)
997 { 993 {
@@ -1012,31 +1008,25 @@ update_window_fringes (w, keep_current_p)
1012 1008
1013 if (!row->mode_line_p) 1009 if (!row->mode_line_p)
1014 { 1010 {
1015 if (!done_top) 1011 if (top_ind_rn < 0 && row->visible_height > 0)
1016 { 1012 {
1017 if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)) 1013 if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer))
1018 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row)) 1014 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
1019 row->indicate_bob_p = !NILP (boundary_top); 1015 row->indicate_bob_p = !NILP (boundary_top);
1020 else 1016 else
1021 row->indicate_top_line_p = !NILP (arrow_top); 1017 row->indicate_top_line_p = !NILP (arrow_top);
1022 done_top = 1; 1018 top_ind_rn = rn;
1023 } 1019 }
1024 1020
1025 if (!done_bot) 1021 if (bot_ind_rn < 0)
1026 { 1022 {
1027 if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)) 1023 if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer))
1028 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)) 1024 && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row))
1029 row->indicate_eob_p = !NILP (boundary_bot), done_bot = 1; 1025 row->indicate_eob_p = !NILP (boundary_bot), bot_ind_rn = rn;
1030 else if (y + row->height >= yb) 1026 else if (y + row->height >= yb)
1031 row->indicate_bottom_line_p = !NILP (arrow_bot), done_bot = 1; 1027 row->indicate_bottom_line_p = !NILP (arrow_bot), bot_ind_rn = rn;
1032 } 1028 }
1033 } 1029 }
1034
1035 if (indicate_bob_p != row->indicate_bob_p
1036 || indicate_top_line_p != row->indicate_top_line_p
1037 || indicate_eob_p != row->indicate_eob_p
1038 || indicate_bottom_line_p != row->indicate_bottom_line_p)
1039 row->redraw_fringe_bitmaps_p = 1;
1040 } 1030 }
1041 } 1031 }
1042 1032
@@ -1060,12 +1050,139 @@ update_window_fringes (w, keep_current_p)
1060 get_logical_fringe_bitmap (w, which, 1, partial_p))) 1050 get_logical_fringe_bitmap (w, which, 1, partial_p)))
1061 1051
1062 1052
1063 for (y = 0, rn = 0; 1053 /* Extend top-aligned top indicator (or bottom-aligned bottom
1054 indicator) to adjacent rows if it doesn't fit in one row. */
1055 top_ind_min_y = bot_ind_max_y = -1;
1056 if (top_ind_rn >= 0)
1057 {
1058 int bn = NO_FRINGE_BITMAP;
1059
1060 row = w->desired_matrix->rows + top_ind_rn;
1061 if (!row->enabled_p)
1062 row = w->current_matrix->rows + top_ind_rn;
1063
1064 top_row_ends_at_zv_p = row->ends_at_zv_p;
1065 if (row->indicate_bob_p)
1066 {
1067 if (EQ (boundary_top, Qleft))
1068 bn = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
1069 ? LEFT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
1070 : LEFT_FRINGE (2, Qtop, 0));
1071 else
1072 bn = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
1073 ? RIGHT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p)
1074 : RIGHT_FRINGE (2, Qtop, 0));
1075 }
1076 else if (row->indicate_top_line_p)
1077 {
1078 if (EQ (arrow_top, Qleft))
1079 bn = LEFT_FRINGE (6, Qup, 0);
1080 else
1081 bn = RIGHT_FRINGE (6, Qup, 0);
1082 }
1083
1084 if (bn != NO_FRINGE_BITMAP)
1085 {
1086 struct fringe_bitmap *fb;
1087
1088 fb = fringe_bitmaps[bn];
1089 if (fb == NULL)
1090 fb = &standard_bitmaps[bn < MAX_STANDARD_FRINGE_BITMAPS
1091 ? bn : UNDEF_FRINGE_BITMAP];
1092 if (fb->align == ALIGN_BITMAP_TOP && fb->period == 0)
1093 {
1094 struct glyph_row *row1;
1095 int top_ind_max_y;
1096
1097 top_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w);
1098 top_ind_max_y = top_ind_min_y + fb->height;
1099 if (top_ind_max_y > yb)
1100 top_ind_max_y = yb;
1101
1102 for (y = row->y + row->height, rn = top_ind_rn + 1;
1103 y < top_ind_max_y && rn < nrows;
1104 y += row1->height, rn++)
1105 {
1106 if (bot_ind_rn >= 0 && rn >= bot_ind_rn)
1107 break;
1108
1109 row1 = w->desired_matrix->rows + rn;
1110 if (!row1->enabled_p)
1111 row1 = w->current_matrix->rows + rn;
1112
1113 row1->indicate_bob_p = row->indicate_bob_p;
1114 row1->indicate_top_line_p = row->indicate_top_line_p;
1115 }
1116 }
1117 }
1118 }
1119 if (bot_ind_rn >= 0)
1120 {
1121 int bn = NO_FRINGE_BITMAP;
1122
1123 row = w->desired_matrix->rows + bot_ind_rn;
1124 if (!row->enabled_p)
1125 row = w->current_matrix->rows + bot_ind_rn;
1126
1127 bot_row_ends_at_zv_p = row->ends_at_zv_p;
1128 if (row->indicate_eob_p)
1129 {
1130 if (EQ (boundary_bot, Qleft))
1131 bn = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p);
1132 else
1133 bn = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p);
1134 }
1135 else if (row->indicate_bottom_line_p)
1136 {
1137 if (EQ (arrow_bot, Qleft))
1138 bn = LEFT_FRINGE (7, Qdown, 0);
1139 else
1140 bn = RIGHT_FRINGE (7, Qdown, 0);
1141 }
1142
1143 if (bn != NO_FRINGE_BITMAP)
1144 {
1145 struct fringe_bitmap *fb;
1146
1147 fb = fringe_bitmaps[bn];
1148 if (fb == NULL)
1149 fb = &standard_bitmaps[bn < MAX_STANDARD_FRINGE_BITMAPS
1150 ? bn : UNDEF_FRINGE_BITMAP];
1151 if (fb->align == ALIGN_BITMAP_BOTTOM && fb->period == 0)
1152 {
1153 struct glyph_row *row1;
1154 int bot_ind_min_y;
1155
1156 bot_ind_max_y = row->y + row->visible_height;
1157 bot_ind_min_y = bot_ind_max_y - fb->height;
1158 if (bot_ind_min_y < WINDOW_HEADER_LINE_HEIGHT (w))
1159 bot_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w);
1160
1161 for (y = row->y, rn = bot_ind_rn - 1;
1162 y >= bot_ind_min_y && rn >= 0;
1163 y -= row1->height, rn--)
1164 {
1165 if (top_ind_rn >= 0 && rn <= top_ind_rn)
1166 break;
1167
1168 row1 = w->desired_matrix->rows + rn;
1169 if (!row1->enabled_p)
1170 row1 = w->current_matrix->rows + rn;
1171
1172 row1->indicate_eob_p = row->indicate_eob_p;
1173 row1->indicate_bottom_line_p = row->indicate_bottom_line_p;
1174 }
1175 }
1176 }
1177 }
1178
1179 for (y = w->vscroll, rn = 0;
1064 y < yb && rn < nrows; 1180 y < yb && rn < nrows;
1065 y += row->height, rn++) 1181 y += row->height, rn++)
1066 { 1182 {
1067 int left, right; 1183 int left, right;
1068 unsigned left_face_id, right_face_id; 1184 unsigned left_face_id, right_face_id;
1185 int left_offset, right_offset;
1069 1186
1070 row = w->desired_matrix->rows + rn; 1187 row = w->desired_matrix->rows + rn;
1071 cur = w->current_matrix->rows + rn; 1188 cur = w->current_matrix->rows + rn;
@@ -1073,6 +1190,7 @@ update_window_fringes (w, keep_current_p)
1073 row = cur; 1190 row = cur;
1074 1191
1075 left_face_id = right_face_id = DEFAULT_FACE_ID; 1192 left_face_id = right_face_id = DEFAULT_FACE_ID;
1193 left_offset = right_offset = 0;
1076 1194
1077 /* Decide which bitmap to draw in the left fringe. */ 1195 /* Decide which bitmap to draw in the left fringe. */
1078 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0) 1196 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
@@ -1085,19 +1203,35 @@ update_window_fringes (w, keep_current_p)
1085 else if (row->truncated_on_left_p) 1203 else if (row->truncated_on_left_p)
1086 left = LEFT_FRINGE(0, Qtruncation, 0); 1204 left = LEFT_FRINGE(0, Qtruncation, 0);
1087 else if (row->indicate_bob_p && EQ (boundary_top, Qleft)) 1205 else if (row->indicate_bob_p && EQ (boundary_top, Qleft))
1088 left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft)) 1206 {
1089 ? LEFT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p) 1207 left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft))
1090 : LEFT_FRINGE (2, Qtop, 0)); 1208 ? LEFT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
1209 : LEFT_FRINGE (2, Qtop, 0));
1210 if (top_ind_min_y >= 0)
1211 left_offset = top_ind_min_y - row->y;
1212 }
1091 else if (row->indicate_eob_p && EQ (boundary_bot, Qleft)) 1213 else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
1092 left = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p); 1214 {
1215 left = LEFT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
1216 if (bot_ind_max_y >= 0)
1217 left_offset = bot_ind_max_y - (row->y + row->visible_height);
1218 }
1093 else if (MATRIX_ROW_CONTINUATION_LINE_P (row)) 1219 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1094 left = LEFT_FRINGE (4, Qcontinuation, 0); 1220 left = LEFT_FRINGE (4, Qcontinuation, 0);
1095 else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft)) 1221 else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
1096 left = LEFT_FRINGE (5, Qempty_line, 0); 1222 left = LEFT_FRINGE (5, Qempty_line, 0);
1097 else if (row->indicate_top_line_p && EQ (arrow_top, Qleft)) 1223 else if (row->indicate_top_line_p && EQ (arrow_top, Qleft))
1098 left = LEFT_FRINGE (6, Qup, 0); 1224 {
1225 left = LEFT_FRINGE (6, Qup, 0);
1226 if (top_ind_min_y >= 0)
1227 left_offset = top_ind_min_y - row->y;
1228 }
1099 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft)) 1229 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft))
1100 left = LEFT_FRINGE (7, Qdown, 0); 1230 {
1231 left = LEFT_FRINGE (7, Qdown, 0);
1232 if (bot_ind_max_y >= 0)
1233 left_offset = bot_ind_max_y - (row->y + row->visible_height);
1234 }
1101 else 1235 else
1102 left = NO_FRINGE_BITMAP; 1236 left = NO_FRINGE_BITMAP;
1103 1237
@@ -1112,17 +1246,33 @@ update_window_fringes (w, keep_current_p)
1112 else if (row->truncated_on_right_p) 1246 else if (row->truncated_on_right_p)
1113 right = RIGHT_FRINGE (0, Qtruncation, 0); 1247 right = RIGHT_FRINGE (0, Qtruncation, 0);
1114 else if (row->indicate_bob_p && EQ (boundary_top, Qright)) 1248 else if (row->indicate_bob_p && EQ (boundary_top, Qright))
1115 right = ((row->indicate_eob_p && EQ (boundary_bot, Qright)) 1249 {
1116 ? RIGHT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p) 1250 right = ((row->indicate_eob_p && EQ (boundary_bot, Qright))
1117 : RIGHT_FRINGE (2, Qtop, 0)); 1251 ? RIGHT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p)
1252 : RIGHT_FRINGE (2, Qtop, 0));
1253 if (top_ind_min_y >= 0)
1254 right_offset = top_ind_min_y - row->y;
1255 }
1118 else if (row->indicate_eob_p && EQ (boundary_bot, Qright)) 1256 else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
1119 right = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p); 1257 {
1258 right = RIGHT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p);
1259 if (bot_ind_max_y >= 0)
1260 right_offset = bot_ind_max_y - (row->y + row->visible_height);
1261 }
1120 else if (row->continued_p) 1262 else if (row->continued_p)
1121 right = RIGHT_FRINGE (4, Qcontinuation, 0); 1263 right = RIGHT_FRINGE (4, Qcontinuation, 0);
1122 else if (row->indicate_top_line_p && EQ (arrow_top, Qright)) 1264 else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
1123 right = RIGHT_FRINGE (6, Qup, 0); 1265 {
1266 right = RIGHT_FRINGE (6, Qup, 0);
1267 if (top_ind_min_y >= 0)
1268 right_offset = top_ind_min_y - row->y;
1269 }
1124 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright)) 1270 else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright))
1125 right = RIGHT_FRINGE (7, Qdown, 0); 1271 {
1272 right = RIGHT_FRINGE (7, Qdown, 0);
1273 if (bot_ind_max_y >= 0)
1274 right_offset = bot_ind_max_y - (row->y + row->visible_height);
1275 }
1126 else if (row->indicate_empty_line_p && EQ (empty_pos, Qright)) 1276 else if (row->indicate_empty_line_p && EQ (empty_pos, Qright))
1127 right = RIGHT_FRINGE (5, Qempty_line, 0); 1277 right = RIGHT_FRINGE (5, Qempty_line, 0);
1128 else 1278 else
@@ -1135,6 +1285,8 @@ update_window_fringes (w, keep_current_p)
1135 || right != cur->right_fringe_bitmap 1285 || right != cur->right_fringe_bitmap
1136 || left_face_id != cur->left_fringe_face_id 1286 || left_face_id != cur->left_fringe_face_id
1137 || right_face_id != cur->right_fringe_face_id 1287 || right_face_id != cur->right_fringe_face_id
1288 || left_offset != cur->left_fringe_offset
1289 || right_offset != cur->right_fringe_offset
1138 || cur->redraw_fringe_bitmaps_p) 1290 || cur->redraw_fringe_bitmaps_p)
1139 { 1291 {
1140 redraw_p = row->redraw_fringe_bitmaps_p = 1; 1292 redraw_p = row->redraw_fringe_bitmaps_p = 1;
@@ -1145,6 +1297,8 @@ update_window_fringes (w, keep_current_p)
1145 cur->right_fringe_bitmap = right; 1297 cur->right_fringe_bitmap = right;
1146 cur->left_fringe_face_id = left_face_id; 1298 cur->left_fringe_face_id = left_face_id;
1147 cur->right_fringe_face_id = right_face_id; 1299 cur->right_fringe_face_id = right_face_id;
1300 cur->left_fringe_offset = left_offset;
1301 cur->right_fringe_offset = right_offset;
1148 } 1302 }
1149 } 1303 }
1150 1304
@@ -1161,9 +1315,8 @@ update_window_fringes (w, keep_current_p)
1161 row->right_fringe_bitmap = right; 1315 row->right_fringe_bitmap = right;
1162 row->left_fringe_face_id = left_face_id; 1316 row->left_fringe_face_id = left_face_id;
1163 row->right_fringe_face_id = right_face_id; 1317 row->right_fringe_face_id = right_face_id;
1164 1318 row->left_fringe_offset = left_offset;
1165 if (rn > 0 && row->redraw_fringe_bitmaps_p) 1319 row->right_fringe_offset = right_offset;
1166 row[-1].redraw_fringe_bitmaps_p = cur[-1].redraw_fringe_bitmaps_p = 1;
1167 } 1320 }
1168 1321
1169 return redraw_p && !keep_current_p; 1322 return redraw_p && !keep_current_p;
diff --git a/src/nsterm.m b/src/nsterm.m
index 7bc82e96104..7c70b2ae698 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2177,20 +2177,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2177 2177
2178 /* Must clip because of partially visible lines. */ 2178 /* Must clip because of partially visible lines. */
2179 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); 2179 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2180 if (p->y < rowY) 2180 ns_clip_to_row (w, row, -1, YES);
2181 {
2182 /* Adjust position of "bottom aligned" bitmap on partially
2183 visible last row. */
2184 int oldY = row->y;
2185 int oldVH = row->visible_height;
2186 row->visible_height = p->h;
2187 row->y -= rowY - p->y;
2188 ns_clip_to_row (w, row, -1, NO);
2189 row->y = oldY;
2190 row->visible_height = oldVH;
2191 }
2192 else
2193 ns_clip_to_row (w, row, -1, YES);
2194 2181
2195 if (p->bx >= 0 && !p->overlay_p) 2182 if (p->bx >= 0 && !p->overlay_p)
2196 { 2183 {
diff --git a/src/w32term.c b/src/w32term.c
index 4ed7beda233..801c56bf994 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -761,7 +761,6 @@ w32_draw_fringe_bitmap (w, row, p)
761 struct frame *f = XFRAME (WINDOW_FRAME (w)); 761 struct frame *f = XFRAME (WINDOW_FRAME (w));
762 HDC hdc; 762 HDC hdc;
763 struct face *face = p->face; 763 struct face *face = p->face;
764 int rowY;
765 764
766 hdc = get_frame_dc (f); 765 hdc = get_frame_dc (f);
767 766
@@ -820,21 +819,7 @@ w32_draw_fringe_bitmap (w, row, p)
820 } 819 }
821 820
822 /* Must clip because of partially visible lines. */ 821 /* Must clip because of partially visible lines. */
823 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); 822 w32_clip_to_row (w, row, -1, hdc);
824 if (p->y < rowY)
825 {
826 /* Adjust position of "bottom aligned" bitmap on partially
827 visible last row. */
828 int oldY = row->y;
829 int oldVH = row->visible_height;
830 row->visible_height = p->h;
831 row->y -= rowY - p->y;
832 w32_clip_to_row (w, row, -1, hdc);
833 row->y = oldY;
834 row->visible_height = oldVH;
835 }
836 else
837 w32_clip_to_row (w, row, -1, hdc);
838 823
839 if (p->which && p->which < max_fringe_bmp) 824 if (p->which && p->which < max_fringe_bmp)
840 { 825 {
diff --git a/src/xterm.c b/src/xterm.c
index 69940685ace..2f84b776ee8 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -774,24 +774,9 @@ x_draw_fringe_bitmap (w, row, p)
774 Window window = FRAME_X_WINDOW (f); 774 Window window = FRAME_X_WINDOW (f);
775 GC gc = f->output_data.x->normal_gc; 775 GC gc = f->output_data.x->normal_gc;
776 struct face *face = p->face; 776 struct face *face = p->face;
777 int rowY;
778 777
779 /* Must clip because of partially visible lines. */ 778 /* Must clip because of partially visible lines. */
780 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); 779 x_clip_to_row (w, row, -1, gc);
781 if (p->y < rowY)
782 {
783 /* Adjust position of "bottom aligned" bitmap on partially
784 visible last row. */
785 int oldY = row->y;
786 int oldVH = row->visible_height;
787 row->visible_height = p->h;
788 row->y -= rowY - p->y;
789 x_clip_to_row (w, row, -1, gc);
790 row->y = oldY;
791 row->visible_height = oldVH;
792 }
793 else
794 x_clip_to_row (w, row, -1, gc);
795 780
796 if (!p->overlay_p) 781 if (!p->overlay_p)
797 { 782 {