Allow fine-grained image-cache flushing.
* 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.
This commit is contained in:
parent
01dcf28448
commit
a2bc5bdd7d
6 changed files with 68 additions and 62 deletions
|
@ -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
|
||||
|
|
2
etc/NEWS
2
etc/NEWS
|
@ -596,6 +596,8 @@ functions and variables (formerly used for Tamil script).
|
|||
|
||||
* 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
|
||||
|
|
|
@ -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 *));
|
||||
|
|
48
src/image.c
48
src/image.c
|
@ -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;
|
||||
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 (frame, Qt))
|
||||
clear_image_caches (1);
|
||||
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);
|
||||
|
|
49
src/xdisp.c
49
src/xdisp.c
|
@ -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);
|
||||
|
|
14
src/xfaces.c
14
src/xfaces.c
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue