aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii <[email protected]>2011-11-18 14:21:42 +0200
committerEli Zaretskii <[email protected]>2011-11-18 14:21:42 +0200
commit015137db608f0678112ae9a69a1a52889d56161d (patch)
tree08d432ad5df33dd7158a331d9dcebcebf0a11b88 /src
parenta2addb04643c0631c1c3a79116b5e54f9f302afc (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/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 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;