Fix another crash due to incorrect hash value of glyph rows, bug #10035.
authorEli Zaretskii <eliz@gnu.org>
Fri, 18 Nov 2011 12:21:42 +0000 (14:21 +0200)
committerEli Zaretskii <eliz@gnu.org>
Fri, 18 Nov 2011 12:21:42 +0000 (14:21 +0200)
 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.

src/ChangeLog
src/dispextern.h
src/dispnew.c
src/xdisp.c

index 81f7fbb..b394c37 100644 (file)
@@ -1,3 +1,20 @@
+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
index 5c60a54..486aa4f 100644 (file)
@@ -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
index 6ba834b..07843d3 100644 (file)
@@ -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;
 }
 
 
index 6b9270b..ae19e11 100644 (file)
@@ -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;