Commit 015137db authored by Eli Zaretskii's avatar Eli Zaretskii
Browse files

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.
parent a2addb04
2011-11-18 Eli Zaretskii <eliz@gnu.org>
* 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 <tassilo@member.fsf.org>
* frame.c (delete_frame): Don't delete the terminal when the last
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment