Fix bug #9221 with memory leak in bidi display.
[bpt/emacs.git] / src / bidi.c
index ae5143b..00a6aee 100644 (file)
@@ -620,12 +620,15 @@ bidi_pop_it (struct bidi_it *bidi_it)
   bidi_cache_last_idx = -1;
 }
 
+ptrdiff_t bidi_cache_total_alloc;
+
 /* Stash away a copy of the cache and its control variables.  */
 void *
 bidi_shelve_cache (void)
 {
   unsigned char *databuf;
 
+  /* Empty cache.  */
   if (bidi_cache_idx == 0)
     return NULL;
 
@@ -634,6 +637,12 @@ bidi_shelve_cache (void)
                     + sizeof (bidi_cache_start_stack)
                     + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start)
                     + sizeof (bidi_cache_last_idx));
+  bidi_cache_total_alloc +=
+    sizeof (bidi_cache_idx) + bidi_cache_idx * sizeof (struct bidi_it)
+    + sizeof (bidi_cache_start_stack)
+    + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start)
+    + sizeof (bidi_cache_last_idx);
+
   memcpy (databuf, &bidi_cache_idx, sizeof (bidi_cache_idx));
   memcpy (databuf + sizeof (bidi_cache_idx),
          bidi_cache, bidi_cache_idx * sizeof (struct bidi_it));
@@ -659,7 +668,7 @@ bidi_shelve_cache (void)
 
 /* Restore the cache state from a copy stashed away by bidi_shelve_cache.  */
 void
-bidi_unshelve_cache (void *databuf)
+bidi_unshelve_cache (void *databuf, int just_free)
 {
   unsigned char *p = databuf;
 
@@ -672,30 +681,47 @@ bidi_unshelve_cache (void *databuf)
     }
   else
     {
-      memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx));
-      bidi_cache_ensure_space (bidi_cache_idx);
-      memcpy (bidi_cache, p + sizeof (bidi_cache_idx),
-             bidi_cache_idx * sizeof (struct bidi_it));
-      memcpy (bidi_cache_start_stack,
-             p + sizeof (bidi_cache_idx)
-             + bidi_cache_idx * sizeof (struct bidi_it),
-             sizeof (bidi_cache_start_stack));
-      memcpy (&bidi_cache_sp,
-             p + sizeof (bidi_cache_idx)
-             + bidi_cache_idx * sizeof (struct bidi_it)
-             + sizeof (bidi_cache_start_stack),
-             sizeof (bidi_cache_sp));
-      memcpy (&bidi_cache_start,
-             p + sizeof (bidi_cache_idx)
-             + bidi_cache_idx * sizeof (struct bidi_it)
-             + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp),
-             sizeof (bidi_cache_start));
-      memcpy (&bidi_cache_last_idx,
-             p + sizeof (bidi_cache_idx)
-             + bidi_cache_idx * sizeof (struct bidi_it)
-             + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
-             + sizeof (bidi_cache_start),
-             sizeof (bidi_cache_last_idx));
+      if (just_free)
+       {
+         ptrdiff_t idx;
+
+         memcpy (&idx, p, sizeof (bidi_cache_idx));
+         bidi_cache_total_alloc -=
+           sizeof (bidi_cache_idx) + idx * sizeof (struct bidi_it)
+           + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+           + sizeof (bidi_cache_start) + sizeof (bidi_cache_last_idx);
+       }
+      else
+       {
+         memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx));
+         bidi_cache_ensure_space (bidi_cache_idx);
+         memcpy (bidi_cache, p + sizeof (bidi_cache_idx),
+                 bidi_cache_idx * sizeof (struct bidi_it));
+         memcpy (bidi_cache_start_stack,
+                 p + sizeof (bidi_cache_idx)
+                 + bidi_cache_idx * sizeof (struct bidi_it),
+                 sizeof (bidi_cache_start_stack));
+         memcpy (&bidi_cache_sp,
+                 p + sizeof (bidi_cache_idx)
+                 + bidi_cache_idx * sizeof (struct bidi_it)
+                 + sizeof (bidi_cache_start_stack),
+                 sizeof (bidi_cache_sp));
+         memcpy (&bidi_cache_start,
+                 p + sizeof (bidi_cache_idx)
+                 + bidi_cache_idx * sizeof (struct bidi_it)
+                 + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp),
+                 sizeof (bidi_cache_start));
+         memcpy (&bidi_cache_last_idx,
+                 p + sizeof (bidi_cache_idx)
+                 + bidi_cache_idx * sizeof (struct bidi_it)
+                 + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+                 + sizeof (bidi_cache_start),
+                 sizeof (bidi_cache_last_idx));
+         bidi_cache_total_alloc -=
+           sizeof (bidi_cache_idx) + bidi_cache_idx * sizeof (struct bidi_it)
+           + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+           + sizeof (bidi_cache_start) + sizeof (bidi_cache_last_idx);
+       }
 
       xfree (p);
     }