Fix bug #9221 with memory leak in bidi display.
[bpt/emacs.git] / src / xdisp.c
index 59a6bc3..69baea9 100644 (file)
@@ -604,7 +604,7 @@ int current_mode_line_height, current_header_line_height;
 #define SAVE_IT(ITCOPY,ITORIG,CACHE)           \
   do {                                         \
     if (CACHE)                                 \
-      xfree (CACHE);                           \
+      bidi_unshelve_cache (CACHE, 1);          \
     ITCOPY = ITORIG;                           \
     CACHE = bidi_shelve_cache();               \
   } while (0)
@@ -613,7 +613,7 @@ int current_mode_line_height, current_header_line_height;
   do {                                         \
     if (pITORIG != pITCOPY)                    \
       *(pITORIG) = *(pITCOPY);                 \
-    bidi_unshelve_cache (CACHE);               \
+    bidi_unshelve_cache (CACHE, 0);            \
     CACHE = NULL;                              \
   } while (0)
 
@@ -1341,9 +1341,9 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
          *vpos = it2.vpos;
        }
       else
-       xfree (it2data);
+       bidi_unshelve_cache (it2data, 1);
     }
-  bidi_unshelve_cache (itdata);
+  bidi_unshelve_cache (itdata, 0);
 
   if (old_buffer)
     set_buffer_internal_1 (old_buffer);
@@ -2627,7 +2627,7 @@ init_iterator (struct it *it, struct window *w,
            it->paragraph_embedding = R2L;
          else
            it->paragraph_embedding = NEUTRAL_DIR;
-         bidi_unshelve_cache (NULL);
+         bidi_unshelve_cache (NULL, 0);
          bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
                        &it->bidi_it);
        }
@@ -5618,7 +5618,7 @@ back_to_previous_visible_line_start (struct it *it)
        pos = --IT_CHARPOS (it2);
        --IT_BYTEPOS (it2);
        it2.sp = 0;
-       bidi_unshelve_cache (NULL);
+       bidi_unshelve_cache (NULL, 0);
        it2.string_from_display_prop_p = 0;
        it2.from_disp_prop_p = 0;
        if (handle_display_prop (&it2) == HANDLED_RETURN
@@ -5828,7 +5828,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
     {
       bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
                    &it->bidi_it);
-      bidi_unshelve_cache (NULL);
+      bidi_unshelve_cache (NULL, 0);
       it->bidi_it.paragraph_dir = NEUTRAL_DIR;
       it->bidi_it.string.s = NULL;
       it->bidi_it.string.lstring = Qnil;
@@ -8009,13 +8009,13 @@ move_it_in_display_line_to (struct it *it,
             positions smaller than TO_CHARPOS, return
             MOVE_POS_MATCH_OR_ZV, like the unidirectional display
             did.  */
-         if ((op & MOVE_TO_POS) != 0
+         if (it->bidi_p && (op & MOVE_TO_POS) != 0
              && !saw_smaller_pos
              && IT_CHARPOS (*it) > to_charpos)
            {
-             result = MOVE_POS_MATCH_OR_ZV;
-             if (it->bidi_p && IT_CHARPOS (ppos_it) < ZV)
+             if (IT_CHARPOS (ppos_it) < ZV)
                RESTORE_IT (it, &ppos_it, ppos_data);
+             goto buffer_pos_reached;
            }
          else
            result = MOVE_NEWLINE_OR_CR;
@@ -8054,14 +8054,13 @@ move_it_in_display_line_to (struct it *it,
                     character positions smaller than TO_CHARPOS,
                     return MOVE_POS_MATCH_OR_ZV, like the
                     unidirectional display did.  */
-                 || ((op & MOVE_TO_POS) != 0
+                 || (it->bidi_p && (op & MOVE_TO_POS) != 0
                      && !saw_smaller_pos
                      && IT_CHARPOS (*it) > to_charpos))
                {
-                 result = MOVE_POS_MATCH_OR_ZV;
-                 if (it->bidi_p && !at_eob_p && IT_CHARPOS (ppos_it) < ZV)
+                 if (!at_eob_p && IT_CHARPOS (ppos_it) < ZV)
                    RESTORE_IT (it, &ppos_it, ppos_data);
-                 break;
+                 goto buffer_pos_reached;
                }
              if (ITERATOR_AT_END_OF_LINE_P (it))
                {
@@ -8069,14 +8068,13 @@ move_it_in_display_line_to (struct it *it,
                  break;
                }
            }
-         else if ((op & MOVE_TO_POS) != 0
+         else if (it->bidi_p && (op & MOVE_TO_POS) != 0
                   && !saw_smaller_pos
                   && IT_CHARPOS (*it) > to_charpos)
            {
-             result = MOVE_POS_MATCH_OR_ZV;
-             if (it->bidi_p && IT_CHARPOS (ppos_it) < ZV)
+             if (IT_CHARPOS (ppos_it) < ZV)
                RESTORE_IT (it, &ppos_it, ppos_data);
-             break;
+             goto buffer_pos_reached;
            }
          result = MOVE_LINE_TRUNCATED;
          break;
@@ -8096,13 +8094,13 @@ move_it_in_display_line_to (struct it *it,
  done:
 
   if (atpos_data)
-    xfree (atpos_data);
+    bidi_unshelve_cache (atpos_data, 1);
   if (atx_data)
-    xfree (atx_data);
+    bidi_unshelve_cache (atx_data, 1);
   if (wrap_data)
-    xfree (wrap_data);
+    bidi_unshelve_cache (wrap_data, 1);
   if (ppos_data)
-    xfree (ppos_data);
+    bidi_unshelve_cache (ppos_data, 1);
 
   /* Restore the iterator settings altered at the beginning of this
      function.  */
@@ -8137,7 +8135,7 @@ move_it_in_display_line (struct it *it,
            (it, -1, prev_x, MOVE_TO_X);
        }
       else
-       xfree (save_data);
+       bidi_unshelve_cache (save_data, 1);
     }
   else
     move_it_in_display_line_to (it, to_charpos, to_x, op);
@@ -8396,7 +8394,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos
     }
 
   if (backup_data)
-    xfree (backup_data);
+    bidi_unshelve_cache (backup_data, 1);
 
   TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
 }
@@ -8475,7 +8473,7 @@ move_it_vertically_backward (struct it *it, int dy)
       RESTORE_IT (it, it, it2data);
       if (nlines > 0)
        move_it_by_lines (it, nlines);
-      xfree (it3data);
+      bidi_unshelve_cache (it3data, 1);
     }
   else
     {
@@ -8671,7 +8669,7 @@ move_it_by_lines (struct it *it, int dvpos)
          if (IT_CHARPOS (*it) >= start_charpos)
            RESTORE_IT (it, &it2, it2data);
          else
-           xfree (it2data);
+           bidi_unshelve_cache (it2data, 1);
        }
       else
        RESTORE_IT (it, it, it2data);
@@ -18779,6 +18777,9 @@ display_line (struct it *it)
        }
     }
 
+  if (wrap_data)
+    bidi_unshelve_cache (wrap_data, 1);
+
   /* If line is not empty and hscrolled, maybe insert truncation glyphs
      at the left window margin.  */
   if (it->first_visible_x