diff options
| author | Eli Zaretskii | 2011-11-18 14:21:42 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2011-11-18 14:21:42 +0200 |
| commit | 015137db608f0678112ae9a69a1a52889d56161d (patch) | |
| tree | 08d432ad5df33dd7158a331d9dcebcebf0a11b88 /src | |
| parent | a2addb04643c0631c1c3a79116b5e54f9f302afc (diff) | |
| download | emacs-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/ChangeLog | 17 | ||||
| -rw-r--r-- | src/dispextern.h | 3 | ||||
| -rw-r--r-- | src/dispnew.c | 35 | ||||
| -rw-r--r-- | src/xdisp.c | 29 |
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 @@ | |||
| 1 | 2011-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 | |||
| 1 | 2011-11-18 Tassilo Horn <tassilo@member.fsf.org> | 18 | 2011-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); | |||
| 3126 | void w32_init_fringe (struct redisplay_interface *); | 3126 | void w32_init_fringe (struct redisplay_interface *); |
| 3127 | void w32_reset_fringes (void); | 3127 | void w32_reset_fringes (void); |
| 3128 | #endif | 3128 | #endif |
| 3129 | |||
| 3130 | extern 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 | |||
| 434 | int | 434 | int |
| 435 | verify_row_hash (struct glyph_row *row) | 435 | verify_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 | ||
| 1088 | static inline void | 1080 | static inline void |
| 1089 | swap_glyph_pointers (struct glyph_row *a, struct glyph_row *b) | 1081 | swap_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 | ||
| 1104 | static inline void | 1105 | static inline void |
| 1105 | copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from) | 1106 | copy_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. */ | ||
| 17953 | unsigned | ||
| 17954 | row_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; |