* 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.
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
\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
/* 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;
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 *));
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;
}
-/* 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;
{
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;
}
void
-clear_image_caches (int force_p)
+clear_image_caches (Lisp_Object filter)
{
/* FIXME: We want to do
* struct terminal *t;
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;
}
struct image *img;
{
mark_object (img->spec);
+ mark_object (img->dependencies);
if (!NILP (img->data.lisp_val))
mark_object (img->data.lisp_val);
int pos;
{
int noverlays;
- int endpos;
+ EMACS_INT endpos;
Lisp_Object *overlays;
int i;
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));
}
#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 */
/* 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
}
}
- if (row_found && !MATRIX_ROW_DISPLAYS_TEXT_P (row_found))
- abort ();
+ eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
return row_found;
}
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);
if (FRAME_WINDOW_P (f))
clear_face_gcs (FRAME_FACE_CACHE (f));
}
- clear_image_caches (0);
+ clear_image_caches (Qnil);
}
#endif /* HAVE_WINDOW_SYSTEM */
}
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]));
}
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
/* 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)