aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2011-11-18 14:21:42 +0200
committerEli Zaretskii2011-11-18 14:21:42 +0200
commit015137db608f0678112ae9a69a1a52889d56161d (patch)
tree08d432ad5df33dd7158a331d9dcebcebf0a11b88 /src
parenta2addb04643c0631c1c3a79116b5e54f9f302afc (diff)
downloademacs-015137db608f0678112ae9a69a1a52889d56161d.tar.gz
emacs-015137db608f0678112ae9a69a1a52889d56161d.zip
Fix another crash due to incorrect hash value of glyph rows, bug #10035.
src/dispnew.c (swap_glyph_pointers): Swap the used[] arrays and the hash values of the two rows. (copy_row_except_pointers): Preserve the used[] arrays and the hash values of the two rows. src/xdisp.c (row_hash): New function, body extracted from compute_line_metrics. (compute_line_metrics): Call row_hash, instead of computing the hash code inline. src/dispnew.c (verify_row_hash): Call row_hash for computing the hash code of a row, instead of duplicating code from xdisp.c. src/dispextern.h (row_hash): Add prototype.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog17
-rw-r--r--src/dispextern.h3
-rw-r--r--src/dispnew.c35
-rw-r--r--src/xdisp.c29
4 files changed, 59 insertions, 25 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 81f7fbbdc29..b394c37354f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,20 @@
12011-11-18 Eli Zaretskii <eliz@gnu.org>
2
3 * dispnew.c (swap_glyph_pointers): Swap the used[] arrays and the
4 hash values of the two rows.
5 (copy_row_except_pointers): Preserve the used[] arrays and the
6 hash values of the two rows. (Bug#10035)
7
8 * xdisp.c (row_hash): New function, body extracted from
9 compute_line_metrics.
10 (compute_line_metrics): Call row_hash, instead of computing the
11 hash code inline.
12
13 * dispnew.c (verify_row_hash): Call row_hash for computing the
14 hash code of a row, instead of duplicating code from xdisp.c.
15
16 * dispextern.h (row_hash): Add prototype.
17
12011-11-18 Tassilo Horn <tassilo@member.fsf.org> 182011-11-18 Tassilo Horn <tassilo@member.fsf.org>
2 19
3 * frame.c (delete_frame): Don't delete the terminal when the last 20 * frame.c (delete_frame): Don't delete the terminal when the last
diff --git a/src/dispextern.h b/src/dispextern.h
index 5c60a5499da..486aa4f7a40 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3126,6 +3126,9 @@ void compute_fringe_widths (struct frame *, int);
3126void w32_init_fringe (struct redisplay_interface *); 3126void w32_init_fringe (struct redisplay_interface *);
3127void w32_reset_fringes (void); 3127void w32_reset_fringes (void);
3128#endif 3128#endif
3129
3130extern unsigned row_hash (struct glyph_row *);
3131
3129/* Defined in image.c */ 3132/* Defined in image.c */
3130 3133
3131#ifdef HAVE_WINDOW_SYSTEM 3134#ifdef HAVE_WINDOW_SYSTEM
diff --git a/src/dispnew.c b/src/dispnew.c
index 6ba834ba339..07843d3e214 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -434,18 +434,7 @@ margin_glyphs_to_reserve (struct window *w, int total_glyphs, Lisp_Object margin
434int 434int
435verify_row_hash (struct glyph_row *row) 435verify_row_hash (struct glyph_row *row)
436{ 436{
437 int area, k; 437 return row->hash == row_hash (row);
438 unsigned row_hash = 0;
439
440 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
441 for (k = 0; k < row->used[area]; ++k)
442 row_hash = ((((row_hash << 4) + (row_hash >> 24)) & 0x0fffffff)
443 + row->glyphs[area][k].u.val
444 + row->glyphs[area][k].face_id
445 + row->glyphs[area][k].padding_p
446 + (row->glyphs[area][k].type << 2));
447
448 return row_hash == row->hash;
449} 438}
450#endif 439#endif
451 440
@@ -1083,37 +1072,55 @@ swap_glyphs_in_rows (struct glyph_row *a, struct glyph_row *b)
1083 1072
1084#endif /* 0 */ 1073#endif /* 0 */
1085 1074
1086/* Exchange pointers to glyph memory between glyph rows A and B. */ 1075/* Exchange pointers to glyph memory between glyph rows A and B. Also
1076 exchange the used[] array and the hash values of the rows, because
1077 these should all go together for the row's hash value to be
1078 correct. */
1087 1079
1088static inline void 1080static inline void
1089swap_glyph_pointers (struct glyph_row *a, struct glyph_row *b) 1081swap_glyph_pointers (struct glyph_row *a, struct glyph_row *b)
1090{ 1082{
1091 int i; 1083 int i;
1084 unsigned hash_tem = a->hash;
1085
1092 for (i = 0; i < LAST_AREA + 1; ++i) 1086 for (i = 0; i < LAST_AREA + 1; ++i)
1093 { 1087 {
1094 struct glyph *temp = a->glyphs[i]; 1088 struct glyph *temp = a->glyphs[i];
1089 short used_tem = a->used[i];
1090
1095 a->glyphs[i] = b->glyphs[i]; 1091 a->glyphs[i] = b->glyphs[i];
1096 b->glyphs[i] = temp; 1092 b->glyphs[i] = temp;
1093 a->used[i] = b->used[i];
1094 b->used[i] = used_tem;
1097 } 1095 }
1096 a->hash = b->hash;
1097 b->hash = hash_tem;
1098} 1098}
1099 1099
1100 1100
1101/* Copy glyph row structure FROM to glyph row structure TO, except 1101/* Copy glyph row structure FROM to glyph row structure TO, except
1102 that glyph pointers in the structures are left unchanged. */ 1102 that glyph pointers, the `used' counts, and the hash values in the
1103 structures are left unchanged. */
1103 1104
1104static inline void 1105static inline void
1105copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from) 1106copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from)
1106{ 1107{
1107 struct glyph *pointers[1 + LAST_AREA]; 1108 struct glyph *pointers[1 + LAST_AREA];
1109 short used[1 + LAST_AREA];
1110 unsigned hashval;
1108 1111
1109 /* Save glyph pointers of TO. */ 1112 /* Save glyph pointers of TO. */
1110 memcpy (pointers, to->glyphs, sizeof to->glyphs); 1113 memcpy (pointers, to->glyphs, sizeof to->glyphs);
1114 memcpy (used, to->used, sizeof to->used);
1115 hashval = to->hash;
1111 1116
1112 /* Do a structure assignment. */ 1117 /* Do a structure assignment. */
1113 *to = *from; 1118 *to = *from;
1114 1119
1115 /* Restore original pointers of TO. */ 1120 /* Restore original pointers of TO. */
1116 memcpy (to->glyphs, pointers, sizeof to->glyphs); 1121 memcpy (to->glyphs, pointers, sizeof to->glyphs);
1122 memcpy (to->used, used, sizeof to->used);
1123 to->hash = hashval;
1117} 1124}
1118 1125
1119 1126
diff --git a/src/xdisp.c b/src/xdisp.c
index 6b9270b7e80..ae19e11565b 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -17949,6 +17949,23 @@ insert_left_trunc_glyphs (struct it *it)
17949 } 17949 }
17950} 17950}
17951 17951
17952/* Compute the hash code for ROW. */
17953unsigned
17954row_hash (struct glyph_row *row)
17955{
17956 int area, k;
17957 unsigned hashval = 0;
17958
17959 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
17960 for (k = 0; k < row->used[area]; ++k)
17961 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
17962 + row->glyphs[area][k].u.val
17963 + row->glyphs[area][k].face_id
17964 + row->glyphs[area][k].padding_p
17965 + (row->glyphs[area][k].type << 2));
17966
17967 return hashval;
17968}
17952 17969
17953/* Compute the pixel height and width of IT->glyph_row. 17970/* Compute the pixel height and width of IT->glyph_row.
17954 17971
@@ -18035,17 +18052,7 @@ compute_line_metrics (struct it *it)
18035 } 18052 }
18036 18053
18037 /* Compute a hash code for this row. */ 18054 /* Compute a hash code for this row. */
18038 { 18055 row->hash = row_hash (row);
18039 int area, i;
18040 row->hash = 0;
18041 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
18042 for (i = 0; i < row->used[area]; ++i)
18043 row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
18044 + row->glyphs[area][i].u.val
18045 + row->glyphs[area][i].face_id
18046 + row->glyphs[area][i].padding_p
18047 + (row->glyphs[area][i].type << 2));
18048 }
18049 18056
18050 it->max_ascent = it->max_descent = 0; 18057 it->max_ascent = it->max_descent = 0;
18051 it->max_phys_ascent = it->max_phys_descent = 0; 18058 it->max_phys_ascent = it->max_phys_descent = 0;