]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow fine-grained image-cache flushing.
authorStefan Monnier <monnier@iro.umontreal.ca>
Sun, 24 Feb 2008 13:36:39 +0000 (13:36 +0000)
committerStefan Monnier <monnier@iro.umontreal.ca>
Sun, 24 Feb 2008 13:36:39 +0000 (13:36 +0000)
* dispextern.h (struct image): Add `dependencies' field.
(clear_image_caches): Change arg to Lisp_Object.
* image.c (make_image): Initialize `dependencies' field.
(clear_image_cache): Change arg to allow fine-grained flushing.
Perform the flush even if image-cache-eviction-delay is nil.
(clear_image_caches): Change arg to Lisp_Object.
(Fclear_image_cache): Expand meaning of the argument.
(mark_image): Mark `dependencies' field.
* xfaces.c (clear_face_cache): Adapt arg to call to clear_image_caches.
(lface_hash): Use XHASH rather than XFASTINT.
(face_at_buffer_position): Fix int -> EMACS_INT position.
* xdisp.c (next_overlay_change): Fix int -> EMACS_INT position.
(select_frame_for_redisplay): Remove code duplication.
(redisplay_internal): Adapt arg to call to clear_image_caches.

doc/lispref/display.texi
etc/NEWS
src/dispextern.h
src/image.c
src/xdisp.c
src/xfaces.c

index ee3c828857a17f0555055c8386db47be76573805..c647111047ce57afb40beb7ba4cdb015ed85c168 100644 (file)
@@ -4364,10 +4364,12 @@ This works by removing all image with image specifications matching
 displayed, Emacs will load the image again.
 @end defun
 
-@defun clear-image-cache &optional frame
-This function clears the entire image cache.  If @var{frame} is
-non-@code{nil}, only the cache for that frame is cleared.  Otherwise,
-all frames' caches are cleared.
+@defun clear-image-cache &optional filter
+This function clears the image cache.  If @var{filter} is
+a frame, only the cache for that frame is cleared.  If omitted or
+@code{nil}, clear the images on the selected frame.  If @code{t},
+all frames' caches are cleared.  Otherwise, @var{filter} is taken as
+a file name and only images that reference this file will be flushed.
 @end defun
 
 If an image in the image cache has not been displayed for a specified
index cbb32b3710d93d52635b787d6c8b29eadc696497..686f48fcb95479a1d36391ccac8a37549c088352 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -596,6 +596,8 @@ functions and variables (formerly used for Tamil script).
 \f
 * Lisp Changes in Emacs 23.1
 
+** `clear-image-cache' can be told to flush only images of a specific file.
+
 ** clone-indirect-buffer now runs the clone-indirect-buffer-hook.
 
 ** `beginning-of-defun-function' now takes one argument, the count
index 9e0e160c5bbdd353212fe4be5214fb35b56c19ba..ea5a077d7b215e19a4b739c6b76a8039b74db043 100644 (file)
@@ -2487,6 +2487,11 @@ struct image
   /* Lisp specification of this image.  */
   Lisp_Object spec;
 
+  /* List of "references" followed to build the image.
+     Typically will just contain the name of the image file.
+     Used to allow fine-grained cache flushing.  */
+  Lisp_Object dependencies;
+
   /* Relief to draw around the image.  */
   int relief;
 
@@ -2818,7 +2823,7 @@ extern Lisp_Object x_find_image_file P_ ((Lisp_Object));
 void x_kill_gs_process P_ ((Pixmap, struct frame *));
 struct image_cache *make_image_cache P_ ((void));
 void free_image_cache P_ ((struct frame *));
-void clear_image_caches P_ ((int));
+void clear_image_caches P_ ((Lisp_Object));
 void mark_image_cache P_ ((struct image_cache *));
 int valid_image_p P_ ((Lisp_Object));
 void prepare_image_for_display P_ ((struct frame *, struct image *));
index cce0024e8356a84785db38d1beef874463190065..81754ca68d2e221282e92ce327c024110507a68e 100644 (file)
@@ -1184,9 +1184,11 @@ make_image (spec, hash)
      unsigned hash;
 {
   struct image *img = (struct image *) xmalloc (sizeof *img);
+  Lisp_Object file = image_spec_value (spec, QCfile, NULL);
 
   xassert (valid_image_p (spec));
   bzero (img, sizeof *img);
+  img->dependencies = NILP (file) ? Qnil : list1 (file);
   img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
   xassert (img->type != NULL);
   img->spec = spec;
@@ -1707,21 +1709,20 @@ free_image_cache (f)
 }
 
 
-/* Clear image cache of frame F.  FORCE_P non-zero means free all
-   images.  FORCE_P zero means clear only images that haven't been
-   displayed for some time.  Should be called from time to time to
-   reduce the number of loaded images.  If image-cache-eviction-delay
-   is non-nil, this frees images in the cache which weren't displayed
-   for at least that many seconds.  */
+/* Clear image cache of frame F.  FILTER=t means free all images.
+   FILTER=nil means clear only images that haven't been
+   displayed for some time.
+   Else, only free the images which have FILTER in their `dependencies'.
+   Should be called from time to time to reduce the number of loaded images.
+   If image-cache-eviction-delay is non-nil, this frees images in the cache
+   which weren't displayed for at least that many seconds.  */
 
 void
-clear_image_cache (f, force_p)
-     struct frame *f;
-     int force_p;
+clear_image_cache (struct frame *f, Lisp_Object filter)
 {
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
 
-  if (c && INTEGERP (Vimage_cache_eviction_delay))
+  if (c && (!NILP (filter) || INTEGERP (Vimage_cache_eviction_delay)))
     {
       EMACS_TIME t;
       unsigned long old;
@@ -1738,7 +1739,9 @@ clear_image_cache (f, force_p)
        {
          struct image *img = c->images[i];
          if (img != NULL
-             && (force_p || img->timestamp < old))
+             && (NILP (filter) ? img->timestamp < old
+                 : (EQ (Qt, filter)
+                    || !NILP (Fmember (filter, img->dependencies)))))
            {
              free_image (f, img);
              ++nfreed;
@@ -1768,7 +1771,7 @@ clear_image_cache (f, force_p)
 }
 
 void
-clear_image_caches (int force_p)
+clear_image_caches (Lisp_Object filter)
 {
   /* FIXME: We want to do
    * struct terminal *t;
@@ -1777,21 +1780,23 @@ clear_image_caches (int force_p)
   Lisp_Object tail, frame;
   FOR_EACH_FRAME (tail, frame)
     if (FRAME_WINDOW_P (XFRAME (frame)))
-      clear_image_cache (XFRAME (frame), force_p);
+      clear_image_cache (XFRAME (frame), filter);
 }
 
 DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
        0, 1, 0,
-       doc: /* Clear the image cache of FRAME.
-FRAME nil or omitted means use the selected frame.
-FRAME t means clear the image caches of all frames.  */)
-     (frame)
-     Lisp_Object frame;
-{
-  if (EQ (frame, Qt))
-    clear_image_caches (1);
+       doc: /* Clear the image cache.
+FILTER nil or a frame means clear all images in the selected frame.
+FILTER t means clear the image caches of all frames.
+Anything else, means only clear those images which refer to FILTER,
+which is then usually a filename.  */)
+     (filter)
+     Lisp_Object filter;
+{
+  if (!(EQ (filter, Qnil) || FRAMEP (filter)))
+    clear_image_caches (filter);
   else
-    clear_image_cache (check_x_frame (frame), 1);
+    clear_image_cache (check_x_frame (filter), Qt);
 
   return Qnil;
 }
@@ -2074,6 +2079,7 @@ mark_image (img)
      struct image *img;
 {
   mark_object (img->spec);
+  mark_object (img->dependencies);
 
   if (!NILP (img->data.lisp_val))
     mark_object (img->data.lisp_val);
index 2006274489ce74b7ae1b0a756ea28d712c94bbcb..588d145e9e14bc0e90475d1f505b5c6285dca255 100644 (file)
@@ -3229,7 +3229,7 @@ next_overlay_change (pos)
      int pos;
 {
   int noverlays;
-  int endpos;
+  EMACS_INT endpos;
   Lisp_Object *overlays;
   int i;
 
@@ -11042,27 +11042,20 @@ select_frame_for_redisplay (frame)
 
   selected_frame = frame;
 
-  for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
-    if (CONSP (XCAR (tail))
-       && (sym = XCAR (XCAR (tail)),
-           SYMBOLP (sym))
-       && (sym = indirect_variable (sym),
-           val = SYMBOL_VALUE (sym),
-           (BUFFER_LOCAL_VALUEP (val)))
-       && XBUFFER_LOCAL_VALUE (val)->check_frame)
-      /* Use find_symbol_value rather than Fsymbol_value
-        to avoid an error if it is void.  */
-      find_symbol_value (sym);
-
-  for (tail = XFRAME (old)->param_alist; CONSP (tail); tail = XCDR (tail))
-    if (CONSP (XCAR (tail))
-       && (sym = XCAR (XCAR (tail)),
-           SYMBOLP (sym))
-       && (sym = indirect_variable (sym),
-           val = SYMBOL_VALUE (sym),
-           (BUFFER_LOCAL_VALUEP (val)))
-       && XBUFFER_LOCAL_VALUE (val)->check_frame)
-      find_symbol_value (sym);
+  do
+    {
+      for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
+       if (CONSP (XCAR (tail))
+           && (sym = XCAR (XCAR (tail)),
+               SYMBOLP (sym))
+           && (sym = indirect_variable (sym),
+               val = SYMBOL_VALUE (sym),
+               (BUFFER_LOCAL_VALUEP (val)))
+           && XBUFFER_LOCAL_VALUE (val)->check_frame)
+         /* Use find_symbol_value rather than Fsymbol_value
+            to avoid an error if it is void.  */
+         find_symbol_value (sym);
+    } while (!EQ (frame, old) && (frame = old, 1));
 }
 
 
@@ -11797,7 +11790,7 @@ redisplay_internal (preserve_echo_area)
 #ifdef HAVE_WINDOW_SYSTEM
       if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
        {
-         clear_image_caches (0);
+         clear_image_caches (Qnil);
          clear_image_cache_count = 0;
        }
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -14426,8 +14419,7 @@ find_first_unchanged_at_end_row (w, delta, delta_bytes)
 
   /* Display must not have been paused, otherwise the current matrix
      is not up to date.  */
-  if (NILP (w->window_end_valid))
-    abort ();
+  eassert (!NILP (w->window_end_valid));
 
   /* A value of window_end_pos >= END_UNCHANGED means that the window
      end is in the range of changed text.  If so, there is no
@@ -14478,8 +14470,7 @@ find_first_unchanged_at_end_row (w, delta, delta_bytes)
        }
     }
 
-  if (row_found && !MATRIX_ROW_DISPLAYS_TEXT_P (row_found))
-    abort ();
+  eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
 
   return row_found;
 }
@@ -18104,8 +18095,8 @@ decode_mode_spec (w, c, field_width, precision, multibyte, string)
            goto no_value;
          }
 
-       if (!NILP (w->base_line_number)
-           && !NILP (w->base_line_pos)
+       if (INTEGERP (w->base_line_number)
+           && INTEGERP (w->base_line_pos)
            && XFASTINT (w->base_line_pos) <= startpos)
          {
            line = XFASTINT (w->base_line_number);
index d160d9e8c2902b762a5872513df17f6457b09846..897d8383a490837a951f43b91b6d6dff3bb97551 100644 (file)
@@ -1011,7 +1011,7 @@ clear_face_cache (clear_fonts_p)
          if (FRAME_WINDOW_P (f))
              clear_face_gcs (FRAME_FACE_CACHE (f));
        }
-      clear_image_caches (0);
+      clear_image_caches (Qnil);
     }
 #endif /* HAVE_WINDOW_SYSTEM */
 }
@@ -5481,10 +5481,10 @@ lface_hash (v)
   return (hash_string_case_insensitive (v[LFACE_FAMILY_INDEX])
          ^ hash_string_case_insensitive (v[LFACE_FOREGROUND_INDEX])
          ^ hash_string_case_insensitive (v[LFACE_BACKGROUND_INDEX])
-         ^ XFASTINT (v[LFACE_WEIGHT_INDEX])
-         ^ XFASTINT (v[LFACE_SLANT_INDEX])
-         ^ XFASTINT (v[LFACE_SWIDTH_INDEX])
-         ^ XFASTINT (v[LFACE_HEIGHT_INDEX]));
+         ^ XHASH (v[LFACE_WEIGHT_INDEX])
+         ^ XHASH (v[LFACE_SLANT_INDEX])
+         ^ XHASH (v[LFACE_SWIDTH_INDEX])
+         ^ XHASH (v[LFACE_HEIGHT_INDEX]));
 }
 
 
@@ -7755,7 +7755,7 @@ realize_x_face (cache, attrs)
        font_load_for_face (f, face);
       else
 #endif /* USE_FONT_BACKEND */
-      load_face_font (f, face);
+       load_face_font (f, face);
       if (face->font)
        face->fontset = make_fontset_for_ascii_face (f, fontset, face);
       else
@@ -8149,7 +8149,7 @@ face_at_buffer_position (w, pos, region_beg, region_end,
 
   /* Look at properties from overlays.  */
   {
-    int next_overlay;
+    EMACS_INT next_overlay;
 
     GET_OVERLAYS_AT (pos, overlay_vec, noverlays, &next_overlay, 0);
     if (next_overlay < endpos)