Lisp_Object Qpointer_image_instance_p;
Lisp_Object Qsubwindow_image_instance_p;
Lisp_Object Qlayout_image_instance_p;
+Lisp_Object Qupdate_widget_instances;
Lisp_Object Qwidget_image_instance_p;
Lisp_Object Qconst_glyph_variable;
Lisp_Object Qmono_pixmap, Qcolor_pixmap, Qsubwindow;
static void glyph_property_was_changed (Lisp_Object glyph,
Lisp_Object property,
Lisp_Object locale);
+static void set_image_instance_dirty_p (Lisp_Object instance, int dirty);
static void register_ignored_expose (struct frame* f, int x, int y, int width, int height);
/* Unfortunately windows and X are different. In windows BeginPaint()
will prevent WM_PAINT messages being generated so it is unnecessary
EXFUN (Fimage_instance_type, 1);
EXFUN (Fglyph_type, 1);
+EXFUN (Fnext_window, 4);
\f
/****************************************************************************
if ((NILP (d) && NILP (device))
||
(!NILP (device) &&
- EQ (CONSOLE_TYPE (XCONSOLE
+ EQ (CONSOLE_TYPE (XCONSOLE
(DEVICE_CONSOLE (XDEVICE (device)))), d)))
return Dynarr_at (the_image_instantiator_format_entry_dynarr, i).meths;
}
struct image_instantiator_methods *meths;
GCPRO1 (instantiator);
-
+
meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0],
ERROR_ME);
RETURN_UNGCPRO (IIFORMAT_METH_OR_GIVEN (meths, normalize,
int dest_mask, Lisp_Object glyph)
{
Lisp_Object ii = allocate_image_instance (device, glyph);
+ Lisp_Image_Instance* p = XIMAGE_INSTANCE (ii);
struct image_instantiator_methods *meths;
struct gcpro gcpro1;
int methp = 0;
methp = (int)HAS_IIFORMAT_METH_P (meths, instantiate);
MAYBE_IIFORMAT_METH (meths, instantiate, (ii, instantiator, pointer_fg,
pointer_bg, dest_mask, domain));
-
+
/* now do device specific instantiation */
meths = decode_device_ii_format (device, XVECTOR_DATA (instantiator)[0],
ERROR_ME_NOT);
pointer_bg, dest_mask, domain));
UNGCPRO;
+ /* Some code may have already laid out the widget, if not then do it
+ here. */
+ if (IMAGE_INSTANCE_LAYOUT_CHANGED (p))
+ image_instance_layout (ii, IMAGE_UNSPECIFIED_GEOMETRY,
+ IMAGE_UNSPECIFIED_GEOMETRY, domain);
+
+ /* We *must* have a clean image at this point. */
+ IMAGE_INSTANCE_TEXT_CHANGED (p) = 0;
+ IMAGE_INSTANCE_SIZE_CHANGED (p) = 0;
+ IMAGE_INSTANCE_LAYOUT_CHANGED (p) = 0;
+ IMAGE_INSTANCE_DIRTYP (p) = 0;
+
return ii;
}
static Lisp_Object
mark_image_instance (Lisp_Object obj)
{
- struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
+ Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
mark_object (i->name);
/* We don't mark the glyph reference since that would create a
break;
case IMAGE_WIDGET:
+ case IMAGE_LAYOUT:
mark_object (IMAGE_INSTANCE_WIDGET_TYPE (i));
mark_object (IMAGE_INSTANCE_WIDGET_PROPS (i));
mark_object (IMAGE_INSTANCE_WIDGET_FACE (i));
mark_object (IMAGE_INSTANCE_WIDGET_ITEMS (i));
+ mark_object (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (i));
+ mark_object (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i));
+ mark_object (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i));
case IMAGE_SUBWINDOW:
mark_object (IMAGE_INSTANCE_SUBWINDOW_FRAME (i));
break;
- case IMAGE_LAYOUT:
- mark_object (IMAGE_INSTANCE_LAYOUT_CHILDREN (i));
- mark_object (IMAGE_INSTANCE_LAYOUT_BORDER (i));
- mark_object (IMAGE_INSTANCE_SUBWINDOW_FRAME (i));
- break;
-
default:
break;
}
int escapeflag)
{
char buf[100];
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (obj);
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (obj);
if (print_readably)
error ("printing unreadable object #<image-instance 0x%x>",
break;
case IMAGE_WIDGET:
+ print_internal (IMAGE_INSTANCE_WIDGET_TYPE (ii), printcharfun, 0);
+
+ if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
+ {
+ write_c_string (" ", printcharfun);
+ print_internal (IMAGE_INSTANCE_WIDGET_TEXT (ii), printcharfun, 1);
+ }
+
if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii)))
{
- write_c_string (" (", printcharfun);
+ write_c_string (" face=", printcharfun);
print_internal
(IMAGE_INSTANCE_WIDGET_FACE (ii), printcharfun, 0);
- write_c_string (")", printcharfun);
}
- if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
- print_internal (IMAGE_INSTANCE_WIDGET_TEXT (ii), printcharfun, 0);
case IMAGE_SUBWINDOW:
case IMAGE_LAYOUT:
write_c_string (" on #<", printcharfun);
{
struct frame* f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
-
+
if (!FRAME_LIVE_P (f))
write_c_string ("dead", printcharfun);
- else
+ else
write_c_string (DEVICE_TYPE_NAME (XDEVICE (FRAME_DEVICE (f))),
printcharfun);
-
- write_c_string ("-frame ", printcharfun);
}
- write_c_string (">", printcharfun);
+ write_c_string ("-frame>", printcharfun);
sprintf (buf, " 0x%p", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
write_c_string (buf, printcharfun);
-
+
break;
default:
static void
finalize_image_instance (void *header, int for_disksave)
{
- struct Lisp_Image_Instance *i = (struct Lisp_Image_Instance *) header;
+ Lisp_Image_Instance *i = (Lisp_Image_Instance *) header;
if (IMAGE_INSTANCE_TYPE (i) == IMAGE_NOTHING)
/* objects like this exist at dump time, so don't bomb out. */
/* do this so that the cachels get reset */
if (IMAGE_INSTANCE_TYPE (i) == IMAGE_WIDGET
||
+ IMAGE_INSTANCE_TYPE (i) == IMAGE_SUBWINDOW
+ ||
IMAGE_INSTANCE_TYPE (i) == IMAGE_SUBWINDOW)
{
- MARK_FRAME_SUBWINDOWS_CHANGED
+ MARK_FRAME_SUBWINDOWS_CHANGED
(XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (i)));
}
static int
image_instance_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
{
- struct Lisp_Image_Instance *i1 = XIMAGE_INSTANCE (obj1);
- struct Lisp_Image_Instance *i2 = XIMAGE_INSTANCE (obj2);
+ Lisp_Image_Instance *i1 = XIMAGE_INSTANCE (obj1);
+ Lisp_Image_Instance *i2 = XIMAGE_INSTANCE (obj2);
struct device *d1 = XDEVICE (i1->device);
struct device *d2 = XDEVICE (i2->device);
break;
case IMAGE_WIDGET:
+ case IMAGE_LAYOUT:
if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1),
IMAGE_INSTANCE_WIDGET_TYPE (i2))
&& IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
IMAGE_INSTANCE_SUBWINDOW_ID (i2)
+ &&
+ EQ (IMAGE_INSTANCE_WIDGET_FACE (i1),
+ IMAGE_INSTANCE_WIDGET_TYPE (i2))
&& internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (i1),
IMAGE_INSTANCE_WIDGET_ITEMS (i2),
depth + 1)
&& internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1),
IMAGE_INSTANCE_WIDGET_PROPS (i2),
depth + 1)
+ && internal_equal (IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i1),
+ IMAGE_INSTANCE_WIDGET_WIDTH_SUBR (i2),
+ depth + 1)
+ && internal_equal (IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i1),
+ IMAGE_INSTANCE_WIDGET_HEIGHT_SUBR (i2),
+ depth + 1)
))
return 0;
break;
-
- case IMAGE_LAYOUT:
- if (IMAGE_INSTANCE_TYPE (i1) == IMAGE_LAYOUT
- &&
- !(EQ (IMAGE_INSTANCE_LAYOUT_BORDER (i1),
- IMAGE_INSTANCE_LAYOUT_BORDER (i2))
- &&
- internal_equal (IMAGE_INSTANCE_LAYOUT_CHILDREN (i1),
- IMAGE_INSTANCE_LAYOUT_CHILDREN (i2),
- depth + 1)))
- return 0;
- break;
-
+
case IMAGE_SUBWINDOW:
if (!(IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
IMAGE_INSTANCE_SUBWINDOW_ID (i2)))
return DEVMETH_OR_GIVEN (d1, image_instance_equal, (i1, i2, depth), 1);
}
+#if 0
+/* internal_hash will not go very far down a list because of the way
+ its written. For items we need to hash all elements so we provide
+ our own list hashing function. */
+static unsigned long
+full_list_hash (Lisp_Object obj, int depth)
+{
+ unsigned long hash = 0;
+ Lisp_Object rest;
+
+ if (!CONSP (obj))
+ return internal_hash (obj, depth + 1);
+
+ hash = LISP_HASH (XCAR (obj));
+ LIST_LOOP (rest, XCDR (obj))
+ {
+ hash = HASH2 (hash, internal_hash (XCAR (rest), depth + 1));
+ }
+ return hash;
+}
+#endif
+
static unsigned long
image_instance_hash (Lisp_Object obj, int depth)
{
- struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
+ Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
struct device *d = XDEVICE (i->device);
unsigned long hash = HASH3 ((unsigned long) d,
IMAGE_INSTANCE_WIDTH (i),
break;
case IMAGE_WIDGET:
- hash = HASH4 (hash,
- internal_hash (IMAGE_INSTANCE_WIDGET_TYPE (i), depth + 1),
+ case IMAGE_LAYOUT:
+ /* We need the hash to be equivalent to what should be
+ displayed. */
+ hash = HASH4 (hash,
+ LISP_HASH (IMAGE_INSTANCE_WIDGET_TYPE (i)),
internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1),
internal_hash (IMAGE_INSTANCE_WIDGET_ITEMS (i), depth + 1));
case IMAGE_SUBWINDOW:
hash = HASH2 (hash, (int) IMAGE_INSTANCE_SUBWINDOW_ID (i));
break;
- case IMAGE_LAYOUT:
- hash = HASH3 (hash,
- internal_hash (IMAGE_INSTANCE_LAYOUT_BORDER (i), depth + 1),
- internal_hash (IMAGE_INSTANCE_LAYOUT_CHILDREN (i),
- depth + 1));
- break;
-
default:
abort ();
}
mark_image_instance, print_image_instance,
finalize_image_instance, image_instance_equal,
image_instance_hash, 0,
- struct Lisp_Image_Instance);
+ Lisp_Image_Instance);
static Lisp_Object
allocate_image_instance (Lisp_Object device, Lisp_Object glyph)
{
- struct Lisp_Image_Instance *lp =
- alloc_lcrecord_type (struct Lisp_Image_Instance, &lrecord_image_instance);
+ Lisp_Image_Instance *lp =
+ alloc_lcrecord_type (Lisp_Image_Instance, &lrecord_image_instance);
Lisp_Object val;
zero_lcrecord (lp);
lp->y_offset = 0;
lp->width = 0;
lp->height = 0;
- lp->glyph = glyph;
- MARK_IMAGE_INSTANCE_CHANGED (lp); /* So that layouts get done. */
+ lp->parent = glyph;
+ /* So that layouts get done. */
+ lp->layout_changed = 1;
+
XSETIMAGE_INSTANCE (val, lp);
- MARK_GLYPHS_CHANGED; /* So that the dirty flag gets reset. */
+ MARK_GLYPHS_CHANGED;
+
return val;
}
(Qerror,
list2
(emacs_doprnt_string_lisp_2
- ((CONST Bufbyte *)
+ ((const Bufbyte *)
"No compatible image-instance types given: wanted one of %s, got %s",
Qnil, -1, 2,
encode_image_instance_type_list (desired_dest_mask),
}
}
+/* Recurse up the hierarchy looking for the topmost glyph. This means
+ that instances in layouts will inherit face properties from their
+ parent. */
+Lisp_Object image_instance_parent_glyph (Lisp_Image_Instance* ii)
+{
+ if (IMAGE_INSTANCEP (IMAGE_INSTANCE_PARENT (ii)))
+ {
+ return image_instance_parent_glyph
+ (XIMAGE_INSTANCE (IMAGE_INSTANCE_PARENT (ii)));
+ }
+ return IMAGE_INSTANCE_PARENT (ii);
+}
+
static Lisp_Object
make_image_instance_1 (Lisp_Object data, Lisp_Object device,
Lisp_Object dest_types)
NO-ERROR controls what happens when the image cannot be generated.
If nil, an error message is generated. If t, no messages are
generated and this function returns nil. If anything else, a warning
-message is generated and this function returns nil.
+message is generated and this function returns nil.
*/
(data, device, dest_types, no_error))
{
}
DEFUN ("image-instance-property", Fimage_instance_property, 2, 2, 0, /*
-Return the given property of the given image instance.
+Return the given property of the given image instance.
Returns nil if the property or the property method do not exist for
-the image instance in the domain.
+the image instance in the domain.
*/
(image_instance, prop))
{
- struct Lisp_Image_Instance* ii;
+ Lisp_Image_Instance* ii;
Lisp_Object type, ret;
struct image_instantiator_methods* meths;
/* ... then try device specific methods ... */
type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
- meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
+ meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
type, ERROR_ME_NOT);
if (meths && HAS_IIFORMAT_METH_P (meths, property)
- &&
+ &&
!UNBOUNDP (ret = IIFORMAT_METH (meths, property, (image_instance, prop))))
{
return ret;
}
DEFUN ("set-image-instance-property", Fset_image_instance_property, 3, 3, 0, /*
-Set the given property of the given image instance.
+Set the given property of the given image instance.
Does nothing if the property or the property method do not exist for
the image instance in the domain.
*/
(image_instance, prop, val))
{
- struct Lisp_Image_Instance* ii;
+ Lisp_Image_Instance* ii;
Lisp_Object type, ret;
struct image_instantiator_methods* meths;
ii = XIMAGE_INSTANCE (image_instance);
type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
/* try device specific methods first ... */
- meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
+ meths = decode_device_ii_format (IMAGE_INSTANCE_DEVICE (ii),
type, ERROR_ME_NOT);
if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
&&
- !UNBOUNDP (ret =
+ !UNBOUNDP (ret =
IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
{
val = ret;
meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
if (meths && HAS_IIFORMAT_METH_P (meths, set_property)
&&
- !UNBOUNDP (ret =
+ !UNBOUNDP (ret =
IIFORMAT_METH (meths, set_property, (image_instance, prop, val))))
{
val = ret;
}
/* Make sure the image instance gets redisplayed. */
- MARK_IMAGE_INSTANCE_CHANGED (ii);
+ set_image_instance_dirty_p (image_instance, 1);
+ /* Force the glyph to be laid out again. */
+ IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
+
MARK_SUBWINDOWS_STATE_CHANGED;
MARK_GLYPHS_CHANGED;
case IMAGE_WIDGET:
return FACE_FOREGROUND (
XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
- XIMAGE_INSTANCE_SUBWINDOW_FRAME
+ XIMAGE_INSTANCE_SUBWINDOW_FRAME
(image_instance));
default:
case IMAGE_WIDGET:
return FACE_BACKGROUND (
XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
- XIMAGE_INSTANCE_SUBWINDOW_FRAME
+ XIMAGE_INSTANCE_SUBWINDOW_FRAME
(image_instance));
default:
/* Find out desired geometry of the image instance. If there is no
special function then just return the width and / or height. */
void
-image_instance_query_geometry (Lisp_Object image_instance,
- unsigned int* width, unsigned int* height,
+image_instance_query_geometry (Lisp_Object image_instance,
+ unsigned int* width, unsigned int* height,
enum image_instance_geometry disp,
Lisp_Object domain)
{
- struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
Lisp_Object type;
struct image_instantiator_methods* meths;
type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (ii));
meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT);
-
+
if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
{
- IIFORMAT_METH (meths, query_geometry, (image_instance, width, height,
+ IIFORMAT_METH (meths, query_geometry, (image_instance, width, height,
disp, domain));
}
else
don't mind what size you have (normal widgets) and one where you
want to specifiy something (layout widgets). */
void
-image_instance_layout (Lisp_Object image_instance,
- unsigned int width, unsigned int height,
+image_instance_layout (Lisp_Object image_instance,
+ unsigned int width, unsigned int height,
Lisp_Object domain)
{
- struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image_instance);
Lisp_Object type;
struct image_instantiator_methods* meths;
/* Get the desired geometry. */
if (meths && HAS_IIFORMAT_METH_P (meths, query_geometry))
{
- IIFORMAT_METH (meths, query_geometry, (image_instance, &dwidth, &dheight,
- IMAGE_DESIRED_GEOMETRY,
+ IIFORMAT_METH (meths, query_geometry, (image_instance, &dwidth, &dheight,
+ IMAGE_DESIRED_GEOMETRY,
domain));
}
else
/* At this point width and height should contain sane values. Thus
we set the glyph geometry and lay it out. */
+ if (IMAGE_INSTANCE_WIDTH (ii) != width
+ ||
+ IMAGE_INSTANCE_HEIGHT (ii) != height)
+ {
+ IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1;
+ }
+
IMAGE_INSTANCE_WIDTH (ii) = width;
IMAGE_INSTANCE_HEIGHT (ii) = height;
-
+
if (meths && HAS_IIFORMAT_METH_P (meths, layout))
{
IIFORMAT_METH (meths, layout, (image_instance, width, height, domain));
}
/* else no change to the geometry. */
+
+ /* Do not clear the dirty flag here - redisplay will do this for
+ us at the end. */
+ IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 0;
+}
+
+/*
+ * Mark image instance in W as dirty if (a) W's faces have changed and
+ * (b) GLYPH_OR_II instance in W is a string.
+ *
+ * Return non-zero if instance has been marked dirty.
+ */
+int
+invalidate_glyph_geometry_maybe (Lisp_Object glyph_or_ii, struct window* w)
+{
+ if (XFRAME(WINDOW_FRAME(w))->faces_changed)
+ {
+ Lisp_Object image = glyph_or_ii;
+
+ if (GLYPHP (glyph_or_ii))
+ {
+ Lisp_Object window;
+ XSETWINDOW (window, w);
+ image = glyph_image_instance (glyph_or_ii, window, ERROR_ME_NOT, 1);
+ }
+
+ if (TEXT_IMAGE_INSTANCEP (image))
+ {
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (image);
+ IMAGE_INSTANCE_DIRTYP (ii) = 1;
+ IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1;
+ if (GLYPHP (glyph_or_ii))
+ XGLYPH_DIRTYP (glyph_or_ii) = 1;
+ return 1;
+ }
+ }
+
+ return 0;
}
\f
/* error helpers */
/************************************************************************/
DOESNT_RETURN
-signal_image_error (CONST char *reason, Lisp_Object frob)
+signal_image_error (const char *reason, Lisp_Object frob)
{
signal_error (Qimage_conversion_error,
list2 (build_translated_string (reason), frob));
}
DOESNT_RETURN
-signal_image_error_2 (CONST char *reason, Lisp_Object frob0, Lisp_Object frob1)
+signal_image_error_2 (const char *reason, Lisp_Object frob0, Lisp_Object frob1)
{
signal_error (Qimage_conversion_error,
list3 (build_translated_string (reason), frob0, frob1));
Lisp_Object pointer_fg, Lisp_Object pointer_bg,
int dest_mask, Lisp_Object domain)
{
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
if (dest_mask & IMAGE_NOTHING_MASK)
IMAGE_INSTANCE_TYPE (ii) = IMAGE_NOTHING;
int dest_mask, Lisp_Object domain)
{
Lisp_Object string = find_keyword_in_vector (instantiator, Q_data);
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
/* Should never get here with a domain other than a window. */
assert (!NILP (string) && WINDOWP (domain));
if (dest_mask & IMAGE_TEXT_MASK)
helper that is used elsewhere for calculating text geometry. */
void
query_string_geometry (Lisp_Object string, Lisp_Object face,
- unsigned int* width, unsigned int* height,
+ unsigned int* width, unsigned int* height,
unsigned int* descent, Lisp_Object domain)
{
struct font_metric_info fm;
- unsigned char charsets[NUM_LEADING_BYTES];
+ Charset_ID charsets[NUM_LEADING_BYTES];
struct face_cachel frame_cachel;
struct face_cachel *cachel;
Lisp_Object frame = FW_FRAME (domain);
find_charsets_in_bufbyte_string (charsets,
XSTRING_DATA (string),
XSTRING_LENGTH (string));
-
+
/* Fallback to the default face if none was provided. */
if (!NILP (face))
{
{
cachel = WINDOW_FACE_CACHEL (XWINDOW (domain), DEFAULT_INDEX);
}
-
+
ensure_face_cachel_complete (cachel, domain, charsets);
face_cachel_charset_font_metric_info (cachel, charsets, &fm);
-
+
*height = fm.ascent + fm.descent;
/* #### descent only gets set if we query the height as well. */
if (descent)
*descent = fm.descent;
}
-
+
/* Compute width */
if (width)
{
Lisp_Object
query_string_font (Lisp_Object string, Lisp_Object face, Lisp_Object domain)
{
- unsigned char charsets[NUM_LEADING_BYTES];
+ Charset_ID charsets[NUM_LEADING_BYTES];
struct face_cachel frame_cachel;
struct face_cachel *cachel;
int i;
find_charsets_in_bufbyte_string (charsets,
XSTRING_DATA (string),
XSTRING_LENGTH (string));
-
+
reset_face_cachel (&frame_cachel);
update_face_cachel_data (&frame_cachel, frame, face);
cachel = &frame_cachel;
ensure_face_cachel_complete (cachel, domain, charsets);
-
+
for (i = 0; i < NUM_LEADING_BYTES; i++)
{
if (charsets[i])
{
- return FACE_CACHEL_FONT (cachel,
- CHARSET_BY_LEADING_BYTE (i +
+ return FACE_CACHEL_FONT (cachel,
+ CHARSET_BY_LEADING_BYTE (i +
MIN_LEADING_BYTE));
- }
+ }
}
return Qnil; /* NOT REACHED */
static void
text_query_geometry (Lisp_Object image_instance,
- unsigned int* width, unsigned int* height,
+ unsigned int* width, unsigned int* height,
enum image_instance_geometry disp, Lisp_Object domain)
{
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
unsigned int descent = 0;
query_string_geometry (IMAGE_INSTANCE_TEXT_STRING (ii),
text_set_property (Lisp_Object image_instance, Lisp_Object prop,
Lisp_Object val)
{
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
if (EQ (prop, Q_data))
{
warn_when_safe (Qunimplemented, Qnotice,
"`formatted-string' not yet implemented; assuming `string'");
- string_instantiate (image_instance, instantiator,
+ string_instantiate (image_instance, instantiator,
pointer_fg, pointer_bg, dest_mask, domain);
}
unsigned int w, h;
Extbyte *data;
int result;
- CONST char *filename_ext;
+ const char *filename_ext;
- GET_C_STRING_FILENAME_DATA_ALLOCA (name, filename_ext);
+ TO_EXTERNAL_FORMAT (LISP_STRING, name,
+ C_STRING_ALLOCA, filename_ext,
+ Qfile_name);
result = read_bitmap_data_from_file (filename_ext, &w, &h,
&data, xhot, yhot);
int len = (w + 7) / 8 * h;
retval = list3 (make_int (w), make_int (h),
- make_ext_string (data, len, FORMAT_BINARY));
+ make_ext_string (data, len, Qbinary));
XFree ((char *) data);
return retval;
}
char **data;
int result;
char *fname = 0;
-
- GET_C_STRING_FILENAME_DATA_ALLOCA (name, fname);
+
+ TO_EXTERNAL_FORMAT (LISP_STRING, name,
+ C_STRING_ALLOCA, fname,
+ Qfile_name);
result = XpmReadFileToData (fname, &data);
if (result == XpmSuccess)
static void
image_create (Lisp_Object obj)
{
- struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
+ Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
IMAGE_SPECIFIER_ALLOWED (image) = ~0; /* all are allowed */
IMAGE_SPECIFIER_ATTACHEE (image) = Qnil;
static void
image_mark (Lisp_Object obj)
{
- struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
+ Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
mark_object (IMAGE_SPECIFIER_ATTACHEE (image));
mark_object (IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image));
static Lisp_Object
image_instantiate_cache_result (Lisp_Object locative)
{
- /* locative = (instance instantiator . subtable) */
+ /* locative = (instance instantiator . subtable)
+
+ So we are using the instantiator as the key and the instance as
+ the value. Since the hashtable is key-weak this means that the
+ image instance will stay around as long as the instantiator stays
+ around. The instantiator is stored in the `image' slot of the
+ glyph, so as long as the glyph is marked the instantiator will be
+ as well and hence the cached image instance also.*/
Fputhash (XCAR (XCDR (locative)), XCAR (locative), XCDR (XCDR (locative)));
free_cons (XCONS (XCDR (locative)));
free_cons (XCONS (locative));
Lisp_Object pointer_fg = Qnil;
Lisp_Object pointer_bg = Qnil;
+ /* We have to put subwindow, widget and text image instances in
+ a per-window cache so that we can see the same glyph in
+ different windows. Unfortunately we do not know the type of
+ image_instance until after it has been created. We thus need
+ to be really careful how we place things. */
+
if (pointerp)
{
pointer_fg = FACE_FOREGROUND (Vpointer_face, domain);
/* For the image instance cache, we do comparisons with EQ rather
than with EQUAL, as we do for color and font names.
The reasons are:
-
+
1) pixmap data can be very long, and thus the hashing and
comparing will take awhile.
2) It's not so likely that we'll run into things that are EQUAL
round it. */
if (UNBOUNDP (instance)
&&
- dest_mask & (IMAGE_SUBWINDOW_MASK
+ dest_mask & (IMAGE_SUBWINDOW_MASK
| IMAGE_WIDGET_MASK
- | IMAGE_TEXT_MASK))
+ | IMAGE_LAYOUT_MASK
+ | IMAGE_TEXT_MASK)
+ && WINDOWP (domain))
{
- if (!WINDOWP (domain))
- signal_simple_error ("Can't instantiate text or subwindow outside a window",
- instantiator);
- instance = Fgethash (instantiator,
- XWINDOW (domain)->subwindow_instance_cache,
+ instance = Fgethash (instantiator,
+ XWINDOW (domain)->subwindow_instance_cache,
Qunbound);
}
}
noseeum_cons (pointerp ? ls3 : instantiator,
subtable));
int speccount = specpdl_depth ();
-
+
/* make sure we cache the failures, too.
Use an unwind-protect to catch such errors.
If we fail, the unwind-protect records nil in
pointer_fg, pointer_bg,
dest_mask,
glyph);
-
+
Fsetcar (locative, instance);
/* only after the image has been instantiated do we know
whether we need to put it in the per-window image instance
cache. */
if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
&
- (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
+ (IMAGE_SUBWINDOW_MASK
+ | IMAGE_WIDGET_MASK
+ | IMAGE_LAYOUT_MASK
+ | IMAGE_TEXT_MASK ))
{
+#ifdef ERROR_CHECK_GLYPHS
+ if (XIMAGE_INSTANCE_TYPE (instance) != IMAGE_TEXT)
+ assert (EQ (XIMAGE_INSTANCE_SUBWINDOW_FRAME (instance),
+ FW_FRAME (domain)));
+#endif
if (!WINDOWP (domain))
- signal_simple_error ("Can't instantiate subwindow outside a window",
+ signal_simple_error ("Can't instantiate text or subwindow outside a window",
instantiator);
-
- Fsetcdr (XCDR (locative), XWINDOW (domain)->subwindow_instance_cache );
+#ifdef ERROR_CHECK_GLYPHS
+ if (XIMAGE_INSTANCE_TYPE (instance) != IMAGE_TEXT)
+ assert (EQ (XIMAGE_INSTANCE_SUBWINDOW_FRAME (instance),
+ FW_FRAME (domain)));
+#endif
+ Fsetcdr (XCDR (locative), XWINDOW (domain)->subwindow_instance_cache);
}
unbind_to (speccount, Qnil);
+#ifdef ERROR_CHECK_GLYPHS
+ if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
+ &
+ (IMAGE_SUBWINDOW_MASK
+ | IMAGE_WIDGET_MASK
+ | IMAGE_LAYOUT_MASK
+ | IMAGE_TEXT_MASK ))
+ assert (EQ (Fgethash ((pointerp ? ls3 : instantiator),
+ XWINDOW (domain)->subwindow_instance_cache,
+ Qunbound), instance));
+#endif
}
else
free_list (ls3);
if (NILP (instance))
signal_simple_error ("Can't instantiate image (probably cached)",
instantiator);
+#ifdef ERROR_CHECK_GLYPHS
+ if (image_instance_type_to_mask (XIMAGE_INSTANCE_TYPE (instance))
+ & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK))
+ assert (EQ (XIMAGE_INSTANCE_SUBWINDOW_FRAME (instance),
+ FW_FRAME (domain)));
+#endif
return instance;
}
set_image_attached_to (Lisp_Object obj, Lisp_Object face_or_glyph,
Lisp_Object property)
{
- struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
+ Lisp_Specifier *image = XIMAGE_SPECIFIER (obj);
IMAGE_SPECIFIER_ATTACHEE (image) = face_or_glyph;
IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image) = property;
instantiator = Fcopy_sequence (instantiator);
elt = XVECTOR_DATA (instantiator);
instantiator_len = XVECTOR_LENGTH (instantiator);
-
+
meths = decode_image_instantiator_format (elt[0], ERROR_ME);
for (i = 1; i < instantiator_len; i += 2)
static Lisp_Object
mark_glyph (Lisp_Object obj)
{
- struct Lisp_Glyph *glyph = XGLYPH (obj);
+ Lisp_Glyph *glyph = XGLYPH (obj);
mark_object (glyph->image);
mark_object (glyph->contrib_p);
static void
print_glyph (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
{
- struct Lisp_Glyph *glyph = XGLYPH (obj);
+ Lisp_Glyph *glyph = XGLYPH (obj);
char buf[20];
if (print_readably)
static int
glyph_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
{
- struct Lisp_Glyph *g1 = XGLYPH (obj1);
- struct Lisp_Glyph *g2 = XGLYPH (obj2);
+ Lisp_Glyph *g1 = XGLYPH (obj1);
+ Lisp_Glyph *g2 = XGLYPH (obj2);
depth++;
static Lisp_Object
glyph_getprop (Lisp_Object obj, Lisp_Object prop)
{
- struct Lisp_Glyph *g = XGLYPH (obj);
+ Lisp_Glyph *g = XGLYPH (obj);
if (EQ (prop, Qimage)) return g->image;
if (EQ (prop, Qcontrib_p)) return g->contrib_p;
static Lisp_Object
glyph_plist (Lisp_Object obj)
{
- struct Lisp_Glyph *glyph = XGLYPH (obj);
+ Lisp_Glyph *glyph = XGLYPH (obj);
Lisp_Object result = glyph->plist;
result = cons3 (Qface, glyph->face, result);
}
static const struct lrecord_description glyph_description[] = {
- { XD_LISP_OBJECT, offsetof(struct Lisp_Glyph, image), 5 },
+ { XD_LISP_OBJECT, offsetof (Lisp_Glyph, image) },
+ { XD_LISP_OBJECT, offsetof (Lisp_Glyph, contrib_p) },
+ { XD_LISP_OBJECT, offsetof (Lisp_Glyph, baseline) },
+ { XD_LISP_OBJECT, offsetof (Lisp_Glyph, face) },
+ { XD_LISP_OBJECT, offsetof (Lisp_Glyph, plist) },
{ XD_END }
};
glyph_equal, glyph_hash, glyph_description,
glyph_getprop, glyph_putprop,
glyph_remprop, glyph_plist,
- struct Lisp_Glyph);
+ Lisp_Glyph);
\f
Lisp_Object
allocate_glyph (enum glyph_type type,
{
/* This function can GC */
Lisp_Object obj = Qnil;
- struct Lisp_Glyph *g =
- alloc_lcrecord_type (struct Lisp_Glyph, &lrecord_glyph);
+ Lisp_Glyph *g = alloc_lcrecord_type (Lisp_Glyph, &lrecord_glyph);
g->type = type;
g->image = Fmake_specifier (Qimage); /* This function can GC */
{
case GLYPH_BUFFER:
XIMAGE_SPECIFIER_ALLOWED (g->image) =
- IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK
- | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
+ IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK
+ | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK
| IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK
| IMAGE_LAYOUT_MASK;
break;
/* This can never return Qunbound. All glyphs have 'nothing as
a fallback. */
- Lisp_Object image_instance = specifier_instance (specifier, Qunbound,
+ Lisp_Object image_instance = specifier_instance (specifier, Qunbound,
domain, errb, no_quit, 0,
Qzero);
+ assert (!UNBOUNDP (image_instance));
return image_instance;
}
if (!IMAGE_INSTANCEP (instance))
return 0;
- if (XIMAGE_INSTANCE_DIRTYP (instance))
+ if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
IMAGE_UNSPECIFIED_GEOMETRY, domain);
if (!IMAGE_INSTANCEP (instance))
return 0;
- if (XIMAGE_INSTANCE_DIRTYP (instance))
+ if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
IMAGE_UNSPECIFIED_GEOMETRY, domain);
if (!IMAGE_INSTANCEP (instance))
return 0;
- if (XIMAGE_INSTANCE_DIRTYP (instance))
+ if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
IMAGE_UNSPECIFIED_GEOMETRY, domain);
{
Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
domain);
-
+
if (!IMAGE_INSTANCEP (instance))
return 0;
- if (XIMAGE_INSTANCE_DIRTYP (instance))
+ if (XIMAGE_INSTANCE_NEEDS_LAYOUT (instance))
image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
IMAGE_UNSPECIFIED_GEOMETRY, domain);
return make_int (glyph_height (glyph, window));
}
-static unsigned int
-glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window)
-{
- return XIMAGE_INSTANCE_DIRTYP (glyph_image_instance_maybe
- (glyph_or_image, window));
-}
-
static void
set_glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window, int dirty)
{
}
}
+static void
+set_image_instance_dirty_p (Lisp_Object instance, int dirty)
+{
+ if (IMAGE_INSTANCEP (instance))
+ {
+ XIMAGE_INSTANCE_DIRTYP (instance) = dirty;
+ /* Now cascade up the hierarchy. */
+ set_image_instance_dirty_p (XIMAGE_INSTANCE_PARENT (instance),
+ dirty);
+ }
+ else if (GLYPHP (instance))
+ {
+ XGLYPH_DIRTYP (instance) = dirty;
+ }
+}
+
/* #### do we need to cache this info to speed things up? */
Lisp_Object
#if 0 /* Not used for now */
static void
glyph_query_geometry (Lisp_Object glyph_or_image, Lisp_Object window,
- unsigned int* width, unsigned int* height,
+ unsigned int* width, unsigned int* height,
enum image_instance_geometry disp, Lisp_Object domain)
{
Lisp_Object instance = glyph_or_image;
if (GLYPHP (glyph_or_image))
instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
-
+
image_instance_query_geometry (instance, width, height, disp, domain);
}
if (GLYPHP (glyph_or_image))
instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
-
+
image_instance_layout (instance, width, height, domain);
}
#endif
* glyph cachel functions *
*****************************************************************************/
-/*
- #### All of this is 95% copied from face cachels.
- Consider consolidating.
- */
-
+/* #### All of this is 95% copied from face cachels. Consider
+ consolidating.
+
+ Why do we need glyph_cachels? Simply because a glyph_cachel captures
+ per-window information about a particular glyph. A glyph itself is
+ not created in any particular context, so if we were to rely on a
+ glyph to tell us about its dirtiness we would not be able to reset
+ the dirty flag after redisplaying it as it may exist in other
+ contexts. When we have redisplayed we need to know which glyphs to
+ reset the dirty flags on - the glyph_cachels give us a nice list we
+ can iterate through doing this. */
void
mark_glyph_cachels (glyph_cachel_dynarr *elements)
{
struct glyph_cachel *cachel)
{
if (!cachel->updated || NILP (cachel->glyph) || !EQ (cachel->glyph, glyph)
- || XGLYPH_DIRTYP (cachel->glyph))
+ || XGLYPH_DIRTYP (cachel->glyph)
+ || XFRAME(WINDOW_FRAME(w))->faces_changed)
{
Lisp_Object window, instance;
XSETWINDOW (window, w);
cachel->glyph = glyph;
- /* Speed things up slightly by grabbing the glyph instantiation
- and passing it to the size functions. */
+ /* Speed things up slightly by grabbing the glyph instantiation
+ and passing it to the size functions. */
instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1);
- cachel->dirty = XGLYPH_DIRTYP (glyph) = glyph_dirty_p (glyph, window);
+
+ /* Mark text instance of the glyph dirty if faces have changed,
+ because its geometry might have changed. */
+ invalidate_glyph_geometry_maybe (instance, w);
+
+ /* #### Do the following 2 lines buy us anything? --kkm */
+ XGLYPH_DIRTYP (glyph) = XIMAGE_INSTANCE_DIRTYP (instance);
+ cachel->dirty = XGLYPH_DIRTYP (glyph);
cachel->width = glyph_width (instance, window);
cachel->ascent = glyph_ascent (instance, window);
cachel->descent = glyph_descent (instance, window);
}
/* Unset the dirty bit on all the glyph cachels that have it. */
-void
+void
mark_glyph_cachels_as_clean (struct window* w)
{
int elt;
{
struct subwindow_cachel *cachel =
Dynarr_atp (f->subwindow_cachels, elt);
-
+
if (EQ (cachel->subwindow, subwindow) && !NILP (subwindow))
{
update_subwindow_cachel_data (f, subwindow, cachel);
we have to check for overlaps. Being conservative we will
check for exposures wholly contained by the subwindow, this
might give us what we want.*/
- if (ei->x <= x && ei->y <= y
+ if (ei->x <= x && ei->y <= y
&& ei->x + ei->width >= x + width
&& ei->y + ei->height >= y + height)
{
f->subwindow_exposures = ei->next;
else
prev->next = ei->next;
-
+
if (ei == f->subwindow_exposures_tail)
f->subwindow_exposures_tail = prev;
if (!hold_ignored_expose_registration)
{
struct expose_ignore *ei;
-
+
ei = Blocktype_alloc (the_expose_ignore_blocktype);
-
+
ei->next = NULL;
ei->x = x;
ei->y = y;
ei->width = width;
ei->height = height;
-
+
/* we have to add the exposure to the end of the list, since we
want to check the oldest events first. for speed we keep a record
of the end so that we can add right to it. */
if (cachel->being_displayed
&&
cachel->x <= x && cachel->y <= y
- &&
+ &&
cachel->x + cachel->width >= x + width
&&
cachel->y + cachel->height >= y + height)
* subwindow functions *
*****************************************************************************/
-/* update the displayed characteristics of a subwindow */
-static void
+/* Update the displayed characteristics of a subwindow. This function
+ should generally only get called if the subwindow is actually
+ dirty. */
+void
update_subwindow (Lisp_Object subwindow)
{
- struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
+ int count = specpdl_depth ();
- if (!IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET
+ /* The update method is allowed to call eval. Since it is quite
+ common for this function to get called from somewhere in
+ redisplay we need to make sure that quits are ignored. Otherwise
+ Fsignal will abort. */
+ specbind (Qinhibit_quit, Qt);
+
+ if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET
||
- NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))
- return;
+ IMAGE_INSTANCE_TYPE (ii) == IMAGE_LAYOUT)
+ {
+ if (image_instance_changed (subwindow))
+ update_widget (subwindow);
+ /* Reset the changed flags. */
+ IMAGE_INSTANCE_WIDGET_FACE_CHANGED (ii) = 0;
+ IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
+ IMAGE_INSTANCE_TEXT_CHANGED (ii) = 0;
+ }
+ else if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW
+ &&
+ !NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))
+ {
+ MAYBE_DEVMETH (XDEVICE (ii->device), update_subwindow, (ii));
+ }
+
+ IMAGE_INSTANCE_SIZE_CHANGED (ii) = 0;
+ /* This function is typically called by redisplay just before
+ outputting the information to the screen. Thus we record a hash
+ of the output to determine whether on-screen is the same as
+ recorded structure. This approach has limitations in there is a
+ good chance that hash values will be different for the same
+ visual appearance. However, we would rather that then the other
+ way round - it simply means that we will get more displays than
+ we might need. We can get better hashing by making the depth
+ negative - currently it will recurse down 7 levels.*/
+ IMAGE_INSTANCE_DISPLAY_HASH (ii) = internal_hash (subwindow,
+ IMAGE_INSTANCE_HASH_DEPTH);
- MAYBE_DEVMETH (XDEVICE (ii->device), update_subwindow, (ii));
- /* We must update the window's size as it may have been changed by
- the the layout routines. We also do this here so that explicit resizing
- from lisp does not result in synchronous updates. */
- MAYBE_DEVMETH (XDEVICE (ii->device), resize_subwindow, (ii,
- IMAGE_INSTANCE_WIDTH (ii),
- IMAGE_INSTANCE_HEIGHT (ii)));
+ unbind_to (count, Qnil);
+}
+
+int
+image_instance_changed (Lisp_Object subwindow)
+{
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
+
+ if (internal_hash (subwindow, IMAGE_INSTANCE_HASH_DEPTH) !=
+ IMAGE_INSTANCE_DISPLAY_HASH (ii))
+ return 1;
+ else if ((WIDGET_IMAGE_INSTANCEP (subwindow)
+ || LAYOUT_IMAGE_INSTANCEP (subwindow))
+ && !internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (ii),
+ IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii), 0))
+ return 1;
+ else
+ return 0;
}
/* Update all the subwindows on a frame. */
-void
-update_frame_subwindows (struct frame *f)
+DEFUN ("update-widget-instances", Fupdate_widget_instances,1, 1, 0, /*
+Given a FRAME, re-evaluate the display hash code for all widgets in the frame.
+Don't use this.
+*/
+ (frame))
{
int elt;
+ struct frame* f;
+ CHECK_FRAME (frame);
+ f = XFRAME (frame);
- if (f->subwindows_changed || f->subwindows_state_changed || f->faces_changed)
- for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
+ /* If we get called we know something has changed. */
+ for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
{
struct subwindow_cachel *cachel =
Dynarr_atp (f->subwindow_cachels, elt);
-
- if (cachel->being_displayed)
+
+ if (cachel->being_displayed &&
+ image_instance_changed (cachel->subwindow))
{
- update_subwindow (cachel->subwindow);
+ set_image_instance_dirty_p (cachel->subwindow, 1);
+ MARK_FRAME_GLYPHS_CHANGED (f);
}
}
+ return Qnil;
}
/* remove a subwindow from its frame */
void unmap_subwindow (Lisp_Object subwindow)
{
- struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
int elt;
struct subwindow_cachel* cachel;
struct frame* f;
void map_subwindow (Lisp_Object subwindow, int x, int y,
struct display_glyph_area *dga)
{
- struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
- int elt;
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
+ int elt;
struct subwindow_cachel* cachel;
struct frame* f;
cachel->height = dga->height;
cachel->being_displayed = 1;
- /* This forces any pending display changes to happen to the image
- before we show it. I'm not sure whether or not we need mark as
- clean here, but for now we will. */
- if (IMAGE_INSTANCE_DIRTYP (ii))
- {
- update_subwindow (subwindow);
- IMAGE_INSTANCE_DIRTYP (ii) = 0;
- }
-
MAYBE_DEVMETH (XDEVICE (ii->device), map_subwindow, (ii, x, y, dga));
}
Lisp_Object pointer_fg, Lisp_Object pointer_bg,
int dest_mask, Lisp_Object domain)
{
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii);
Lisp_Object frame = FW_FRAME (domain);
Lisp_Object width = find_keyword_in_vector (instantiator, Q_pixel_width);
if (NILP (frame))
signal_simple_error ("No selected frame", device);
-
+
if (!(dest_mask & IMAGE_SUBWINDOW_MASK))
incompatible_image_types (instantiator, dest_mask, IMAGE_SUBWINDOW_MASK);
/* #### This stuff may get overidden by the widget code and is
actually really dumb now that we have dynamic geometry
calculations. What should really happen is that the subwindow
- should query its child for and appropriate geometry. */
- if (NILP (width))
- IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = 20;
- else
+ should query its child for an appropriate geometry. */
+ if (INTP (width))
{
int w = 1;
- CHECK_INT (width);
if (XINT (width) > 1)
w = XINT (width);
IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = w;
}
- if (NILP (height))
- IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = 20;
else
+ IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = 20;
+
+ if (INTP (height))
{
int h = 1;
- CHECK_INT (height);
if (XINT (height) > 1)
h = XINT (height);
IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = h;
}
+ else
+ IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = 20;
}
DEFUN ("subwindowp", Fsubwindowp, 1, 1, 0, /*
(subwindow, width, height))
{
int neww, newh;
+ Lisp_Image_Instance* ii;
CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
+ ii = XIMAGE_INSTANCE (subwindow);
if (NILP (width))
- neww = XIMAGE_INSTANCE_WIDTH (subwindow);
+ neww = IMAGE_INSTANCE_WIDTH (ii);
else
neww = XINT (width);
if (NILP (height))
- newh = XIMAGE_INSTANCE_HEIGHT (subwindow);
+ newh = IMAGE_INSTANCE_HEIGHT (ii);
else
newh = XINT (height);
/* The actual resizing gets done asychronously by
update_subwindow. */
- XIMAGE_INSTANCE_HEIGHT (subwindow) = newh;
- XIMAGE_INSTANCE_WIDTH (subwindow) = neww;
+ IMAGE_INSTANCE_HEIGHT (ii) = newh;
+ IMAGE_INSTANCE_WIDTH (ii) = neww;
+ IMAGE_INSTANCE_SIZE_CHANGED (ii) = 1;
/* need to update the cachels as redisplay will not do this */
update_subwindow_cachel (subwindow);
if (!NILP (XWEAK_LIST_LIST (arg)) && !NILP (XCAR (XWEAK_LIST_LIST (arg))))
{
Lisp_Object value = XCAR (XWEAK_LIST_LIST (arg));
-
+
if (IMAGE_INSTANCEP (value))
{
- struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (value);
+ Lisp_Image_Instance* ii = XIMAGE_INSTANCE (value);
if (COLOR_PIXMAP_IMAGE_INSTANCEP (value)
&&
% IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii);
/* We might need to kick redisplay at this point - but we
also might not. */
- MARK_DEVICE_FRAMES_GLYPHS_CHANGED
+ MARK_DEVICE_FRAMES_GLYPHS_CHANGED
(XDEVICE (IMAGE_INSTANCE_DEVICE (ii)));
- MARK_IMAGE_INSTANCE_CHANGED (ii);
+ /* Cascade dirtiness so that we can have an animated glyph in a layout
+ for instance. */
+ set_image_instance_dirty_p (value, 1);
}
}
}
void
syms_of_glyphs (void)
{
+ INIT_LRECORD_IMPLEMENTATION (glyph);
+ INIT_LRECORD_IMPLEMENTATION (image_instance);
+
/* image instantiators */
DEFSUBR (Fimage_instantiator_format_list);
DEFSUBR (Fvalid_image_instantiator_format_p);
DEFSUBR (Fset_console_type_image_conversion_list);
DEFSUBR (Fconsole_type_image_conversion_list);
+ DEFSUBR (Fupdate_widget_instances);
defkeyword (&Q_file, ":file");
defkeyword (&Q_data, ":data");
defsymbol (&Qwidget_image_instance_p, "widget-image-instance-p");
defsymbol (&Qsubwindow_image_instance_p, "subwindow-image-instance-p");
defsymbol (&Qlayout_image_instance_p, "layout-image-instance-p");
+ defsymbol (&Qupdate_widget_instances, "update-widget-instances");
DEFSUBR (Fmake_image_instance);
DEFSUBR (Fimage_instance_p);
}
static const struct lrecord_description image_specifier_description[] = {
- { XD_LISP_OBJECT, specifier_data_offset + offsetof(struct image_specifier, attachee), 2 },
+ { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee) },
+ { XD_LISP_OBJECT, specifier_data_offset + offsetof (struct image_specifier, attachee_property) },
{ XD_END }
};
static const struct lrecord_description iike_description_1[] = {
- { XD_LISP_OBJECT, offsetof(ii_keyword_entry, keyword), 1 },
+ { XD_LISP_OBJECT, offsetof (ii_keyword_entry, keyword) },
{ XD_END }
};
static const struct struct_description iike_description = {
- sizeof(ii_keyword_entry),
+ sizeof (ii_keyword_entry),
iike_description_1
};
static const struct lrecord_description iiked_description_1[] = {
- XD_DYNARR_DESC(ii_keyword_entry_dynarr, &iike_description),
+ XD_DYNARR_DESC (ii_keyword_entry_dynarr, &iike_description),
{ XD_END }
};
static const struct struct_description iiked_description = {
- sizeof(ii_keyword_entry_dynarr),
+ sizeof (ii_keyword_entry_dynarr),
iiked_description_1
};
static const struct lrecord_description iife_description_1[] = {
- { XD_LISP_OBJECT, offsetof(image_instantiator_format_entry, symbol), 2 },
- { XD_STRUCT_PTR, offsetof(image_instantiator_format_entry, meths), 1, &iim_description },
+ { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, symbol) },
+ { XD_LISP_OBJECT, offsetof (image_instantiator_format_entry, device) },
+ { XD_STRUCT_PTR, offsetof (image_instantiator_format_entry, meths), 1, &iim_description },
{ XD_END }
};
static const struct struct_description iife_description = {
- sizeof(image_instantiator_format_entry),
+ sizeof (image_instantiator_format_entry),
iife_description_1
};
static const struct lrecord_description iifed_description_1[] = {
- XD_DYNARR_DESC(image_instantiator_format_entry_dynarr, &iife_description),
+ XD_DYNARR_DESC (image_instantiator_format_entry_dynarr, &iife_description),
{ XD_END }
};
static const struct struct_description iifed_description = {
- sizeof(image_instantiator_format_entry_dynarr),
+ sizeof (image_instantiator_format_entry_dynarr),
iifed_description_1
};
static const struct lrecord_description iim_description_1[] = {
- { XD_LISP_OBJECT, offsetof(struct image_instantiator_methods, symbol), 2 },
- { XD_STRUCT_PTR, offsetof(struct image_instantiator_methods, keywords), 1, &iiked_description },
- { XD_STRUCT_PTR, offsetof(struct image_instantiator_methods, consoles), 1, &cted_description },
+ { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, symbol) },
+ { XD_LISP_OBJECT, offsetof (struct image_instantiator_methods, device) },
+ { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, keywords), 1, &iiked_description },
+ { XD_STRUCT_PTR, offsetof (struct image_instantiator_methods, consoles), 1, &cted_description },
{ XD_END }
};
/* image instances */
- Vimage_instance_type_list = Fcons (Qnothing,
- list6 (Qtext, Qmono_pixmap, Qcolor_pixmap,
+ Vimage_instance_type_list = Fcons (Qnothing,
+ list6 (Qtext, Qmono_pixmap, Qcolor_pixmap,
Qpointer, Qsubwindow, Qwidget));
staticpro (&Vimage_instance_type_list);