Copyright (C) 1995 Tinker Systems
Copyright (C) 1995, 1996 Ben Wing
Copyright (C) 1995 Sun Microsystems
- Copyright (C) 1998, 1999 Andy Piper
+ Copyright (C) 1998, 1999, 2000 Andy Piper
This file is part of XEmacs.
/* Synched up with: Not in FSF. */
-/* Written by Ben Wing and Chuck Thompson. */
+/* Written by Ben Wing and Chuck Thompson. Heavily modified /
+ rewritten by Andy Piper. */
#include <config.h>
#include "lisp.h"
image_instantiator_format_entry_dynarr *
the_image_instantiator_format_entry_dynarr;
-static Lisp_Object allocate_image_instance (Lisp_Object device);
+static Lisp_Object allocate_image_instance (Lisp_Object device, Lisp_Object glyph);
static void image_validate (Lisp_Object instantiator);
static void glyph_property_was_changed (Lisp_Object glyph,
Lisp_Object property,
instantiate_image_instantiator (Lisp_Object device, Lisp_Object domain,
Lisp_Object instantiator,
Lisp_Object pointer_fg, Lisp_Object pointer_bg,
- int dest_mask)
+ int dest_mask, Lisp_Object glyph)
{
- Lisp_Object ii = allocate_image_instance (device);
+ Lisp_Object ii = allocate_image_instance (device, glyph);
struct image_instantiator_methods *meths;
struct gcpro gcpro1;
int methp = 0;
struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
mark_object (i->name);
+ /* We don't mark the glyph reference since that would create a
+ circularity preventing GC. */
switch (IMAGE_INSTANCE_TYPE (i))
{
case IMAGE_TEXT:
break;
case IMAGE_WIDGET:
- /*
- if (!NILP (IMAGE_INSTANCE_WIDGET_CALLBACK (ii)))
- {
- print_internal (IMAGE_INSTANCE_WIDGET_CALLBACK (ii), printcharfun, 0);
- write_c_string (", ", printcharfun);
- }
- */
if (!NILP (IMAGE_INSTANCE_WIDGET_FACE (ii)))
{
write_c_string (" (", printcharfun);
if (d1 != d2)
return 0;
- if (IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2))
+ if (IMAGE_INSTANCE_TYPE (i1) != IMAGE_INSTANCE_TYPE (i2)
+ || IMAGE_INSTANCE_WIDTH (i1) != IMAGE_INSTANCE_WIDTH (i2)
+ || IMAGE_INSTANCE_HEIGHT (i1) != IMAGE_INSTANCE_HEIGHT (i2)
+ || IMAGE_INSTANCE_XOFFSET (i1) != IMAGE_INSTANCE_XOFFSET (i2)
+ || IMAGE_INSTANCE_YOFFSET (i1) != IMAGE_INSTANCE_YOFFSET (i2))
return 0;
if (!internal_equal (IMAGE_INSTANCE_NAME (i1), IMAGE_INSTANCE_NAME (i2),
depth + 1))
case IMAGE_MONO_PIXMAP:
case IMAGE_COLOR_PIXMAP:
case IMAGE_POINTER:
- if (!(IMAGE_INSTANCE_PIXMAP_WIDTH (i1) ==
- IMAGE_INSTANCE_PIXMAP_WIDTH (i2) &&
- IMAGE_INSTANCE_PIXMAP_HEIGHT (i1) ==
- IMAGE_INSTANCE_PIXMAP_HEIGHT (i2) &&
- IMAGE_INSTANCE_PIXMAP_DEPTH (i1) ==
+ if (!(IMAGE_INSTANCE_PIXMAP_DEPTH (i1) ==
IMAGE_INSTANCE_PIXMAP_DEPTH (i2) &&
IMAGE_INSTANCE_PIXMAP_SLICE (i1) ==
IMAGE_INSTANCE_PIXMAP_SLICE (i2) &&
case IMAGE_WIDGET:
if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1),
IMAGE_INSTANCE_WIDGET_TYPE (i2))
+ && IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
+ IMAGE_INSTANCE_SUBWINDOW_ID (i2)
&& internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (i1),
IMAGE_INSTANCE_WIDGET_ITEMS (i2),
depth + 1)
depth + 1)
))
return 0;
+ break;
+
case IMAGE_LAYOUT:
if (IMAGE_INSTANCE_TYPE (i1) == IMAGE_LAYOUT
&&
IMAGE_INSTANCE_LAYOUT_CHILDREN (i2),
depth + 1)))
return 0;
+ break;
+
case IMAGE_SUBWINDOW:
- if (!(IMAGE_INSTANCE_SUBWINDOW_WIDTH (i1) ==
- IMAGE_INSTANCE_SUBWINDOW_WIDTH (i2) &&
- IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i1) ==
- IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i2) &&
- IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
+ if (!(IMAGE_INSTANCE_SUBWINDOW_ID (i1) ==
IMAGE_INSTANCE_SUBWINDOW_ID (i2)))
return 0;
break;
{
struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj);
struct device *d = XDEVICE (i->device);
- unsigned long hash = (unsigned long) d;
+ unsigned long hash = HASH3 ((unsigned long) d,
+ IMAGE_INSTANCE_WIDTH (i),
+ IMAGE_INSTANCE_HEIGHT (i));
switch (IMAGE_INSTANCE_TYPE (i))
{
case IMAGE_MONO_PIXMAP:
case IMAGE_COLOR_PIXMAP:
case IMAGE_POINTER:
- hash = HASH6 (hash, IMAGE_INSTANCE_PIXMAP_WIDTH (i),
- IMAGE_INSTANCE_PIXMAP_HEIGHT (i),
- IMAGE_INSTANCE_PIXMAP_DEPTH (i),
+ hash = HASH4 (hash, IMAGE_INSTANCE_PIXMAP_DEPTH (i),
IMAGE_INSTANCE_PIXMAP_SLICE (i),
internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i),
depth + 1));
internal_hash (IMAGE_INSTANCE_WIDGET_TYPE (i), depth + 1),
internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1),
internal_hash (IMAGE_INSTANCE_WIDGET_ITEMS (i), depth + 1));
- case IMAGE_LAYOUT:
- if (IMAGE_INSTANCE_TYPE (i) == IMAGE_LAYOUT)
- hash = HASH3 (hash,
- internal_hash (IMAGE_INSTANCE_LAYOUT_BORDER (i), depth + 1),
- internal_hash (IMAGE_INSTANCE_LAYOUT_CHILDREN (i),
- depth + 1));
case IMAGE_SUBWINDOW:
- hash = HASH4 (hash, IMAGE_INSTANCE_SUBWINDOW_WIDTH (i),
- IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i),
- (int) IMAGE_INSTANCE_SUBWINDOW_ID (i));
+ 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:
struct Lisp_Image_Instance);
static Lisp_Object
-allocate_image_instance (Lisp_Object device)
+allocate_image_instance (Lisp_Object device, Lisp_Object glyph)
{
struct Lisp_Image_Instance *lp =
alloc_lcrecord_type (struct Lisp_Image_Instance, &lrecord_image_instance);
lp->name = Qnil;
lp->x_offset = 0;
lp->y_offset = 0;
+ lp->width = 0;
+ lp->height = 0;
+ lp->glyph = glyph;
+ MARK_IMAGE_INSTANCE_CHANGED (lp); /* So that layouts get done. */
XSETIMAGE_INSTANCE (val, lp);
+ MARK_GLYPHS_CHANGED; /* So that the dirty flag gets reset. */
return val;
}
if (VECTORP (data) && EQ (XVECTOR_DATA (data)[0], Qinherit))
signal_simple_error ("Inheritance not allowed here", data);
ii = instantiate_image_instantiator (device, device, data,
- Qnil, Qnil, dest_mask);
+ Qnil, Qnil, dest_mask, Qnil);
RETURN_UNGCPRO (ii);
}
case IMAGE_MONO_PIXMAP:
case IMAGE_COLOR_PIXMAP:
case IMAGE_POINTER:
- return make_int (XIMAGE_INSTANCE_PIXMAP_HEIGHT (image_instance));
-
case IMAGE_SUBWINDOW:
case IMAGE_WIDGET:
case IMAGE_LAYOUT:
- return make_int (XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (image_instance));
+ return make_int (XIMAGE_INSTANCE_HEIGHT (image_instance));
default:
return Qnil;
case IMAGE_MONO_PIXMAP:
case IMAGE_COLOR_PIXMAP:
case IMAGE_POINTER:
- return make_int (XIMAGE_INSTANCE_PIXMAP_WIDTH (image_instance));
-
case IMAGE_SUBWINDOW:
case IMAGE_WIDGET:
case IMAGE_LAYOUT:
- return make_int (XIMAGE_INSTANCE_SUBWINDOW_WIDTH (image_instance));
+ return make_int (XIMAGE_INSTANCE_WIDTH (image_instance));
default:
return Qnil;
/* #### There should be a copy_image_instance(), which calls a
device-specific method to copy the window-system subobject. */
- new = allocate_image_instance (device);
+ new = allocate_image_instance (device, Qnil);
copy_lcrecord (XIMAGE_INSTANCE (new), XIMAGE_INSTANCE (image_instance));
/* note that if this method returns non-zero, this method MUST
copy any window-system resources, so that when one image instance is
return new;
}
+
+/************************************************************************/
+/* Geometry calculations */
+/************************************************************************/
+
+/* 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,
+ enum image_instance_geometry disp,
+ Lisp_Object domain)
+{
+ struct 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,
+ disp, domain));
+ }
+ else
+ {
+ if (width)
+ *width = IMAGE_INSTANCE_WIDTH (ii);
+ if (height)
+ *height = IMAGE_INSTANCE_HEIGHT (ii);
+ }
+}
+
+/* Layout the image instance using the provided dimensions. Layout
+ widgets are going to do different kinds of calculations to
+ determine what size to give things so we could make the layout
+ function relatively simple to take account of that. An alternative
+ approach is to consider separately the two cases, one where you
+ 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,
+ Lisp_Object domain)
+{
+ struct 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 geometry is unspecified then get some reasonable values for it. */
+ if (width == IMAGE_UNSPECIFIED_GEOMETRY
+ ||
+ height == IMAGE_UNSPECIFIED_GEOMETRY)
+ {
+ unsigned int dwidth, dheight;
+
+ /* 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,
+ domain));
+ }
+ else
+ {
+ dwidth = IMAGE_INSTANCE_WIDTH (ii);
+ dheight = IMAGE_INSTANCE_HEIGHT (ii);
+ }
+
+ /* Compare with allowed geometry. */
+ if (width == IMAGE_UNSPECIFIED_GEOMETRY)
+ width = dwidth;
+ if (height == IMAGE_UNSPECIFIED_GEOMETRY)
+ height = dheight;
+ }
+
+ /* At this point width and height should contain sane values. Thus
+ we set the glyph geometry and lay it out. */
+ 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. */
+}
+
\f
/************************************************************************/
/* error helpers */
return IMAGE_TEXT_MASK;
}
-/* called from autodetect_instantiate() */
+/* Called from autodetect_instantiate() */
void
string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
Lisp_Object pointer_fg, Lisp_Object pointer_bg,
{
Lisp_Object string = find_keyword_in_vector (instantiator, Q_data);
struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-
- assert (!NILP (string));
+
+ /* Should never get here with a domain other than a window. */
+ assert (!NILP (string) && WINDOWP (domain));
if (dest_mask & IMAGE_TEXT_MASK)
{
IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT;
incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK);
}
+/* Sort out the size of the text that is being displayed. Calculating
+ it dynamically allows us to change the text and still see
+ everything. Note that the following methods are for text not string
+ since that is what the instantiated type is. The first method is a
+ 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* descent, Lisp_Object domain)
+{
+ struct font_metric_info fm;
+ Charset_ID charsets[NUM_LEADING_BYTES];
+ struct face_cachel frame_cachel;
+ struct face_cachel *cachel;
+ Lisp_Object frame = FW_FRAME (domain);
+
+ /* Compute height */
+ if (height)
+ {
+ /* Compute string metric info */
+ find_charsets_in_bufbyte_string (charsets,
+ XSTRING_DATA (string),
+ XSTRING_LENGTH (string));
+
+ /* Fallback to the default face if none was provided. */
+ if (!NILP (face))
+ {
+ reset_face_cachel (&frame_cachel);
+ update_face_cachel_data (&frame_cachel, frame, face);
+ cachel = &frame_cachel;
+ }
+ else
+ {
+ 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)
+ {
+ if (!NILP (face))
+ *width = redisplay_frame_text_width_string (XFRAME (frame),
+ face,
+ 0, string, 0, -1);
+ else
+ *width = redisplay_frame_text_width_string (XFRAME (frame),
+ Vdefault_face,
+ 0, string, 0, -1);
+ }
+}
+
+Lisp_Object
+query_string_font (Lisp_Object string, Lisp_Object face, Lisp_Object domain)
+{
+ Charset_ID charsets[NUM_LEADING_BYTES];
+ struct face_cachel frame_cachel;
+ struct face_cachel *cachel;
+ int i;
+ Lisp_Object frame = FW_FRAME (domain);
+
+ /* Compute string font info */
+ 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 +
+ MIN_LEADING_BYTE));
+
+ }
+ }
+
+ return Qnil; /* NOT REACHED */
+}
+
+static void
+text_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);
+ unsigned int descent = 0;
+
+ query_string_geometry (IMAGE_INSTANCE_TEXT_STRING (ii),
+ IMAGE_INSTANCE_FACE (ii),
+ width, height, &descent, domain);
+
+ /* The descent gets set as a side effect of querying the
+ geometry. */
+ IMAGE_INSTANCE_TEXT_DESCENT (ii) = descent;
+}
+
/* set the properties of a string */
static Lisp_Object
text_set_property (Lisp_Object image_instance, Lisp_Object prop,
Lisp_Object pointer_fg, Lisp_Object pointer_bg,
int dest_mask, Lisp_Object domain)
{
- Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
- struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
-
- assert (!NILP (data));
/* #### implement this */
warn_when_safe (Qunimplemented, Qnotice,
"`formatted-string' not yet implemented; assuming `string'");
- if (dest_mask & IMAGE_TEXT_MASK)
- {
- IMAGE_INSTANCE_TYPE (ii) = IMAGE_TEXT;
- IMAGE_INSTANCE_TEXT_STRING (ii) = data;
- }
- else
- incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK);
+
+ string_instantiate (image_instance, instantiator,
+ pointer_fg, pointer_bg, dest_mask, domain);
}
\f
{
Lisp_Object device = DFW_DEVICE (domain);
struct device *d = XDEVICE (device);
+ Lisp_Object glyph = IMAGE_SPECIFIER_ATTACHEE (XIMAGE_SPECIFIER (specifier));
int dest_mask = XIMAGE_SPECIFIER_ALLOWED (specifier);
int pointerp = dest_mask & image_instance_type_to_mask (IMAGE_POINTER);
domain,
instantiator,
pointer_fg, pointer_bg,
- dest_mask);
+ dest_mask,
+ glyph);
Fsetcar (locative, instance);
/* only after the image has been instantiated do we know
break;
case GLYPH_ICON:
XIMAGE_SPECIFIER_ALLOWED (g->image) =
- IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK;
+ IMAGE_NOTHING_MASK | IMAGE_MONO_PIXMAP_MASK
+ | IMAGE_COLOR_PIXMAP_MASK;
break;
default:
abort ();
}
}
-/*****************************************************************************
- glyph_width
+Lisp_Object
+glyph_image_instance (Lisp_Object glyph, Lisp_Object domain,
+ Error_behavior errb, int no_quit)
+{
+ Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph));
- Return the width of the given GLYPH on the given WINDOW. If the
- instance is a string then the width is calculated using the font of
- the given FACE, unless a face is defined by the glyph itself.
- ****************************************************************************/
-unsigned short
-glyph_width (Lisp_Object glyph_or_image, Lisp_Object frame_face,
- face_index window_findex, Lisp_Object window)
+ /* This can never return Qunbound. All glyphs have 'nothing as
+ a fallback. */
+ Lisp_Object image_instance = specifier_instance (specifier, Qunbound,
+ domain, errb, no_quit, 0,
+ Qzero);
+
+ return image_instance;
+}
+
+static Lisp_Object
+glyph_image_instance_maybe (Lisp_Object glyph_or_image, Lisp_Object window)
{
Lisp_Object instance = glyph_or_image;
- Lisp_Object frame = XWINDOW (window)->frame;
- /* #### We somehow need to distinguish between the user causing this
- error condition and a bug causing it. */
if (GLYPHP (glyph_or_image))
instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
- if (!IMAGE_INSTANCEP (instance))
- return 0;
-
- switch (XIMAGE_INSTANCE_TYPE (instance))
- {
- case IMAGE_TEXT:
- {
- Lisp_Object str = XIMAGE_INSTANCE_TEXT_STRING (instance);
- Lisp_Object private_face = Qnil;
-
- if (GLYPHP (glyph_or_image))
- private_face = XGLYPH_FACE(glyph_or_image);
-
- if (!NILP (private_face))
- return redisplay_frame_text_width_string (XFRAME (frame),
- private_face,
- 0, str, 0, -1);
- else
- if (!NILP (frame_face))
- return redisplay_frame_text_width_string (XFRAME (frame),
- frame_face,
- 0, str, 0, -1);
- else
- return redisplay_text_width_string (XWINDOW (window),
- window_findex,
- 0, str, 0, -1);
- }
+ return instance;
+}
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_POINTER:
- return XIMAGE_INSTANCE_PIXMAP_WIDTH (instance);
+/*****************************************************************************
+ glyph_width
- case IMAGE_NOTHING:
- return 0;
+ Return the width of the given GLYPH on the given WINDOW.
+ Calculations are done based on recursively querying the geometry of
+ the associated image instances.
+ ****************************************************************************/
+unsigned short
+glyph_width (Lisp_Object glyph_or_image, Lisp_Object domain)
+{
+ Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
+ domain);
+ if (!IMAGE_INSTANCEP (instance))
+ return 0;
- case IMAGE_SUBWINDOW:
- case IMAGE_WIDGET:
- case IMAGE_LAYOUT:
- return XIMAGE_INSTANCE_SUBWINDOW_WIDTH (instance);
+ if (XIMAGE_INSTANCE_DIRTYP (instance))
+ image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
+ IMAGE_UNSPECIFIED_GEOMETRY, domain);
- default:
- abort ();
- return 0;
- }
+ return XIMAGE_INSTANCE_WIDTH (instance);
}
DEFUN ("glyph-width", Fglyph_width, 1, 2, 0, /*
XSETWINDOW (window, decode_window (window));
CHECK_GLYPH (glyph);
- return make_int (glyph_width (glyph, Qnil, DEFAULT_INDEX, window));
-}
-
-#define RETURN_ASCENT 0
-#define RETURN_DESCENT 1
-#define RETURN_HEIGHT 2
-
-Lisp_Object
-glyph_image_instance (Lisp_Object glyph, Lisp_Object domain,
- Error_behavior errb, int no_quit)
-{
- Lisp_Object specifier = GLYPH_IMAGE (XGLYPH (glyph));
-
- /* This can never return Qunbound. All glyphs have 'nothing as
- a fallback. */
- return specifier_instance (specifier, Qunbound, domain, errb, no_quit, 0,
- Qzero);
+ return make_int (glyph_width (glyph, window));
}
-static unsigned short
-glyph_height_internal (Lisp_Object glyph_or_image, Lisp_Object frame_face,
- face_index window_findex, Lisp_Object window,
- int function)
+unsigned short
+glyph_ascent (Lisp_Object glyph_or_image, Lisp_Object domain)
{
- Lisp_Object instance = glyph_or_image;
- Lisp_Object frame = XWINDOW (window)->frame;
-
- if (GLYPHP (glyph_or_image))
- instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
-
+ Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
+ domain);
if (!IMAGE_INSTANCEP (instance))
return 0;
- switch (XIMAGE_INSTANCE_TYPE (instance))
- {
- case IMAGE_TEXT:
- {
- struct font_metric_info fm;
- Lisp_Object string = XIMAGE_INSTANCE_TEXT_STRING (instance);
- Charset_ID charsets[NUM_LEADING_BYTES];
- struct face_cachel frame_cachel;
- struct face_cachel *cachel;
-
- find_charsets_in_bufbyte_string (charsets,
- XSTRING_DATA (string),
- XSTRING_LENGTH (string));
-
- if (!NILP (frame_face))
- {
- reset_face_cachel (&frame_cachel);
- update_face_cachel_data (&frame_cachel, frame, frame_face);
- cachel = &frame_cachel;
- }
- else
- cachel = WINDOW_FACE_CACHEL (XWINDOW (window), window_findex);
- ensure_face_cachel_complete (cachel, window, charsets);
+ if (XIMAGE_INSTANCE_DIRTYP (instance))
+ image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
+ IMAGE_UNSPECIFIED_GEOMETRY, domain);
- face_cachel_charset_font_metric_info (cachel, charsets, &fm);
-
- switch (function)
- {
- case RETURN_ASCENT: return fm.ascent;
- case RETURN_DESCENT: return fm.descent;
- case RETURN_HEIGHT: return fm.ascent + fm.descent;
- default:
- abort ();
- return 0; /* not reached */
- }
- }
-
- case IMAGE_MONO_PIXMAP:
- case IMAGE_COLOR_PIXMAP:
- case IMAGE_POINTER:
- /* #### Ugh ugh ugh -- temporary crap */
- if (function == RETURN_ASCENT || function == RETURN_HEIGHT)
- return XIMAGE_INSTANCE_PIXMAP_HEIGHT (instance);
- else
- return 0;
-
- case IMAGE_NOTHING:
- return 0;
-
- case IMAGE_SUBWINDOW:
- case IMAGE_WIDGET:
- case IMAGE_LAYOUT:
- /* #### Ugh ugh ugh -- temporary crap */
- if (function == RETURN_ASCENT || function == RETURN_HEIGHT)
- return XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (instance);
- else
- return 0;
-
- default:
- abort ();
- return 0;
- }
+ if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT)
+ return XIMAGE_INSTANCE_TEXT_ASCENT (instance);
+ else
+ return XIMAGE_INSTANCE_HEIGHT (instance);
}
unsigned short
-glyph_ascent (Lisp_Object glyph, Lisp_Object frame_face,
- face_index window_findex, Lisp_Object window)
+glyph_descent (Lisp_Object glyph_or_image, Lisp_Object domain)
{
- return glyph_height_internal (glyph, frame_face, window_findex, window,
- RETURN_ASCENT);
-}
+ Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
+ domain);
+ if (!IMAGE_INSTANCEP (instance))
+ return 0;
-unsigned short
-glyph_descent (Lisp_Object glyph, Lisp_Object frame_face,
- face_index window_findex, Lisp_Object window)
-{
- return glyph_height_internal (glyph, frame_face, window_findex, window,
- RETURN_DESCENT);
+ if (XIMAGE_INSTANCE_DIRTYP (instance))
+ image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
+ IMAGE_UNSPECIFIED_GEOMETRY, domain);
+
+ if (XIMAGE_INSTANCE_TYPE (instance) == IMAGE_TEXT)
+ return XIMAGE_INSTANCE_TEXT_DESCENT (instance);
+ else
+ return 0;
}
/* strictly a convenience function. */
unsigned short
-glyph_height (Lisp_Object glyph, Lisp_Object frame_face,
- face_index window_findex, Lisp_Object window)
+glyph_height (Lisp_Object glyph_or_image, Lisp_Object domain)
{
- return glyph_height_internal (glyph, frame_face, window_findex, window,
- RETURN_HEIGHT);
+ Lisp_Object instance = glyph_image_instance_maybe (glyph_or_image,
+ domain);
+
+ if (!IMAGE_INSTANCEP (instance))
+ return 0;
+
+ if (XIMAGE_INSTANCE_DIRTYP (instance))
+ image_instance_layout (instance, IMAGE_UNSPECIFIED_GEOMETRY,
+ IMAGE_UNSPECIFIED_GEOMETRY, domain);
+
+ return XIMAGE_INSTANCE_HEIGHT (instance);
}
DEFUN ("glyph-ascent", Fglyph_ascent, 1, 2, 0, /*
XSETWINDOW (window, decode_window (window));
CHECK_GLYPH (glyph);
- return make_int (glyph_ascent (glyph, Qnil, DEFAULT_INDEX, window));
+ return make_int (glyph_ascent (glyph, window));
}
DEFUN ("glyph-descent", Fglyph_descent, 1, 2, 0, /*
XSETWINDOW (window, decode_window (window));
CHECK_GLYPH (glyph);
- return make_int (glyph_descent (glyph, Qnil, DEFAULT_INDEX, window));
+ return make_int (glyph_descent (glyph, window));
}
/* This is redundant but I bet a lot of people expect it to exist. */
XSETWINDOW (window, decode_window (window));
CHECK_GLYPH (glyph);
- return make_int (glyph_height (glyph, Qnil, DEFAULT_INDEX, window));
+ return make_int (glyph_height (glyph, window));
}
-#undef RETURN_ASCENT
-#undef RETURN_DESCENT
-#undef RETURN_HEIGHT
-
static unsigned int
glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window)
{
- Lisp_Object instance = glyph_or_image;
-
- if (GLYPHP (glyph_or_image))
- instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1);
-
- return XIMAGE_INSTANCE_DIRTYP (instance);
+ return XIMAGE_INSTANCE_DIRTYP (glyph_image_instance_maybe
+ (glyph_or_image, window));
}
static void
(XGLYPH (glyph)->after_change) (glyph, property, locale);
}
+#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,
+ 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);
+}
+
+static void
+glyph_layout (Lisp_Object glyph_or_image, Lisp_Object window,
+ unsigned int width, unsigned int height, 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_layout (instance, width, height, domain);
+}
+#endif
+
\f
/*****************************************************************************
* glyph cachel functions *
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);
- cachel->width = glyph_width (instance, Qnil, DEFAULT_INDEX, window);
- cachel->ascent = glyph_ascent (instance, Qnil, DEFAULT_INDEX, window);
- cachel->descent = glyph_descent (instance, Qnil, DEFAULT_INDEX, window);
+ cachel->width = glyph_width (instance, window);
+ cachel->ascent = glyph_ascent (instance, window);
+ cachel->descent = glyph_descent (instance, window);
}
cachel->updated = 1;
/*****************************************************************************
* subwindow cachel functions *
*****************************************************************************/
-/* subwindows are curious in that you have to physically unmap them to
+/* Subwindows are curious in that you have to physically unmap them to
not display them. It is problematic deciding what to do in
redisplay. We have two caches - a per-window instance cache that
keeps track of subwindows on a window, these are linked to their
return;
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)));
}
+/* Update all the subwindows on a frame. */
void
update_frame_subwindows (struct frame *f)
{
/* make sure we don't get expose events */
register_ignored_expose (f, cachel->x, cachel->y, cachel->width, cachel->height);
- cachel->x = -1;
- cachel->y = -1;
+ cachel->x = ~0;
+ cachel->y = ~0;
cachel->being_displayed = 0;
IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
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));
}
IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = frame;
- /* this stuff may get overidden by the widget code */
+ /* #### 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
CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
if (NILP (width))
- neww = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow);
+ neww = XIMAGE_INSTANCE_WIDTH (subwindow);
else
neww = XINT (width);
if (NILP (height))
- newh = XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow);
+ newh = XIMAGE_INSTANCE_HEIGHT (subwindow);
else
newh = XINT (height);
-
- MAYBE_DEVMETH (XDEVICE (XIMAGE_INSTANCE_DEVICE (subwindow)),
- resize_subwindow, (XIMAGE_INSTANCE (subwindow), neww, newh));
-
- XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow) = newh;
- XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow) = neww;
+ /* The actual resizing gets done asychronously by
+ update_subwindow. */
+ XIMAGE_INSTANCE_HEIGHT (subwindow) = newh;
+ XIMAGE_INSTANCE_WIDTH (subwindow) = neww;
/* need to update the cachels as redisplay will not do this */
update_subwindow_cachel (subwindow);
also might not. */
MARK_DEVICE_FRAMES_GLYPHS_CHANGED
(XDEVICE (IMAGE_INSTANCE_DEVICE (ii)));
- IMAGE_INSTANCE_DIRTYP (ii) = 1;
+ MARK_IMAGE_INSTANCE_CHANGED (ii);
}
}
}
/* Do this so we can set strings. */
INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (text, "text");
IIFORMAT_HAS_METHOD (text, set_property);
+ IIFORMAT_HAS_METHOD (text, query_geometry);
INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string");
set_specifier_fallback (Vcurrent_display_table,
list1 (Fcons (Qnil, Qnil)));
set_specifier_caching (Vcurrent_display_table,
- slot_offset (struct window,
- display_table),
+ offsetof (struct window, display_table),
some_window_value_changed,
0, 0);
}