diff options
author | Eli Zaretskii <[email protected]> | 2011-11-18 14:21:42 +0200 |
---|---|---|
committer | Eli Zaretskii <[email protected]> | 2011-11-18 14:21:42 +0200 |
commit | 015137db608f0678112ae9a69a1a52889d56161d (patch) | |
tree | 08d432ad5df33dd7158a331d9dcebcebf0a11b88 /src | |
parent | a2addb04643c0631c1c3a79116b5e54f9f302afc (diff) |
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 81f7fbbdc2..b394c37354 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,20 @@ +2011-11-18 Eli Zaretskii <[email protected]> + + * 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. (Bug#10035) + + * 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. + + * dispnew.c (verify_row_hash): Call row_hash for computing the + hash code of a row, instead of duplicating code from xdisp.c. + + * dispextern.h (row_hash): Add prototype. + 2011-11-18 Tassilo Horn <[email protected]> * frame.c (delete_frame): Don't delete the terminal when the last diff --git a/src/dispextern.h b/src/dispextern.h index 5c60a5499d..486aa4f7a4 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3126,6 +3126,9 @@ void compute_fringe_widths (struct frame *, int); void w32_init_fringe (struct redisplay_interface *); void w32_reset_fringes (void); #endif + +extern unsigned row_hash (struct glyph_row *); + /* Defined in image.c */ #ifdef HAVE_WINDOW_SYSTEM diff --git a/src/dispnew.c b/src/dispnew.c index 6ba834ba33..07843d3e21 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 int verify_row_hash (struct glyph_row *row) { - int area, k; - unsigned row_hash = 0; - - for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) - for (k = 0; k < row->used[area]; ++k) - row_hash = ((((row_hash << 4) + (row_hash >> 24)) & 0x0fffffff) - + row->glyphs[area][k].u.val - + row->glyphs[area][k].face_id - + row->glyphs[area][k].padding_p - + (row->glyphs[area][k].type << 2)); - - return row_hash == row->hash; + return row->hash == row_hash (row); } #endif @@ -1083,37 +1072,55 @@ swap_glyphs_in_rows (struct glyph_row *a, struct glyph_row *b) #endif /* 0 */ -/* Exchange pointers to glyph memory between glyph rows A and B. */ +/* Exchange pointers to glyph memory between glyph rows A and B. Also + exchange the used[] array and the hash values of the rows, because + these should all go together for the row's hash value to be + correct. */ static inline void swap_glyph_pointers (struct glyph_row *a, struct glyph_row *b) { int i; + unsigned hash_tem = a->hash; + for (i = 0; i < LAST_AREA + 1; ++i) { struct glyph *temp = a->glyphs[i]; + short used_tem = a->used[i]; + a->glyphs[i] = b->glyphs[i]; b->glyphs[i] = temp; + a->used[i] = b->used[i]; + b->used[i] = used_tem; } + a->hash = b->hash; + b->hash = hash_tem; } /* Copy glyph row structure FROM to glyph row structure TO, except - that glyph pointers in the structures are left unchanged. */ + that glyph pointers, the `used' counts, and the hash values in the + structures are left unchanged. */ static inline void copy_row_except_pointers (struct glyph_row *to, struct glyph_row *from) { struct glyph *pointers[1 + LAST_AREA]; + short used[1 + LAST_AREA]; + unsigned hashval; /* Save glyph pointers of TO. */ memcpy (pointers, to->glyphs, sizeof to->glyphs); + memcpy (used, to->used, sizeof to->used); + hashval = to->hash; /* Do a structure assignment. */ *to = *from; /* Restore original pointers of TO. */ memcpy (to->glyphs, pointers, sizeof to->glyphs); + memcpy (to->used, used, sizeof to->used); + to->hash = hashval; } diff --git a/src/xdisp.c b/src/xdisp.c index 6b9270b7e8..ae19e11565 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -17949,6 +17949,23 @@ insert_left_trunc_glyphs (struct it *it) } } +/* Compute the hash code for ROW. */ +unsigned +row_hash (struct glyph_row *row) +{ + int area, k; + unsigned hashval = 0; + + for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) + for (k = 0; k < row->used[area]; ++k) + hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff) + + row->glyphs[area][k].u.val + + row->glyphs[area][k].face_id + + row->glyphs[area][k].padding_p + + (row->glyphs[area][k].type << 2)); + + return hashval; +} /* Compute the pixel height and width of IT->glyph_row. @@ -18035,17 +18052,7 @@ compute_line_metrics (struct it *it) } /* Compute a hash code for this row. */ - { - int area, i; - row->hash = 0; - for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) - for (i = 0; i < row->used[area]; ++i) - row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff) - + row->glyphs[area][i].u.val - + row->glyphs[area][i].face_id - + row->glyphs[area][i].padding_p - + (row->glyphs[area][i].type << 2)); - } + row->hash = row_hash (row); it->max_ascent = it->max_descent = 0; it->max_phys_ascent = it->max_phys_descent = 0; |