+ xzero (new_cachel);
+ new_cachel.subwindow = Qnil;
+ new_cachel.x=0;
+ new_cachel.y=0;
+ new_cachel.being_displayed=0;
+
+ update_subwindow_cachel_data (f, subwindow, &new_cachel);
+ Dynarr_add (f->subwindow_cachels, new_cachel);
+}
+
+static int
+get_subwindow_cachel_index (struct frame *f, Lisp_Object subwindow)
+{
+ int elt;
+
+ if (noninteractive)
+ return 0;
+
+ for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
+ {
+ struct subwindow_cachel *cachel =
+ Dynarr_atp (f->subwindow_cachels, elt);
+
+ if (EQ (cachel->subwindow, subwindow) && !NILP (subwindow))
+ {
+ if (!cachel->updated)
+ update_subwindow_cachel_data (f, subwindow, cachel);
+ return elt;
+ }
+ }
+
+ /* If we didn't find the glyph, add it and then return its index. */
+ add_subwindow_cachel (f, subwindow);
+ return elt;
+}
+
+/* redisplay in general assumes that drawing something will erase
+ what was there before. unfortunately this does not apply to
+ subwindows that need to be specifically unmapped in order to
+ disappear. we take a brute force approach - on the basis that its
+ cheap - and unmap all subwindows in a display line */
+void
+reset_subwindow_cachels (struct frame *f)
+{
+ int elt;
+ for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
+ {
+ struct subwindow_cachel *cachel =
+ Dynarr_atp (f->subwindow_cachels, elt);
+
+ if (!NILP (cachel->subwindow) && cachel->being_displayed)
+ {
+ struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (cachel->subwindow);
+ MAYBE_DEVMETH (XDEVICE (f->device), unmap_subwindow, (ii));
+ }
+ }
+ Dynarr_reset (f->subwindow_cachels);
+}
+
+void
+mark_subwindow_cachels_as_not_updated (struct frame *f)
+{
+ int elt;
+
+ for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++)
+ Dynarr_atp (f->subwindow_cachels, elt)->updated = 0;
+}
+
+\f
+/*****************************************************************************
+ * subwindow functions *
+ *****************************************************************************/
+
+/* update the displayed characteristics of a subwindow */
+static void
+update_subwindow (Lisp_Object subwindow)
+{
+ struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
+
+ if (!IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET
+ ||
+ NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))
+ return;
+
+ MAYBE_DEVMETH (XDEVICE (ii->device), update_subwindow, (ii));
+}
+
+void
+update_frame_subwindows (struct frame *f)
+{
+ int elt;
+
+ if (f->subwindows_changed || f->glyphs_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)
+ {
+ update_subwindow (cachel->subwindow);
+ }
+ }
+}
+
+/* remove a subwindow from its frame */
+void unmap_subwindow (Lisp_Object subwindow)
+{
+ struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
+ int elt;
+ struct subwindow_cachel* cachel;
+ struct frame* f;
+
+ if (!(IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET
+ ||
+ IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW)
+ ||
+ NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))
+ return;
+
+ f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
+ elt = get_subwindow_cachel_index (f, subwindow);
+ cachel = Dynarr_atp (f->subwindow_cachels, elt);
+
+ cachel->x = -1;
+ cachel->y = -1;
+ cachel->being_displayed = 0;
+ IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
+
+ MAYBE_DEVMETH (XDEVICE (ii->device), unmap_subwindow, (ii));
+}
+
+/* show a subwindow in its frame */
+void map_subwindow (Lisp_Object subwindow, int x, int y)
+{
+ struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow);
+ int elt;
+ struct subwindow_cachel* cachel;
+ struct frame* f;
+
+ if (!(IMAGE_INSTANCE_TYPE (ii) == IMAGE_WIDGET
+ ||
+ IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW)
+ ||
+ NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)))
+ return;
+
+ f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii));
+ IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 1;
+ elt = get_subwindow_cachel_index (f, subwindow);
+ cachel = Dynarr_atp (f->subwindow_cachels, elt);
+ cachel->x = x;
+ cachel->y = y;
+ cachel->being_displayed = 1;
+
+ MAYBE_DEVMETH (XDEVICE (ii->device), map_subwindow, (ii, x, y));
+}
+
+static int
+subwindow_possible_dest_types (void)
+{
+ return IMAGE_SUBWINDOW_MASK;
+}
+
+/* Partially instantiate a subwindow. */
+void
+subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain)
+{
+ struct 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);
+ Lisp_Object height = find_keyword_in_vector (instantiator, Q_pixel_height);
+
+ 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);
+
+ ii->data = 0;
+ IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0;
+ IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = Qnil;
+ IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0;
+ IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = frame;
+
+ /* this stuff may get overidden by the widget code */
+ if (NILP (width))
+ IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = 20;
+ else
+ {
+ 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
+ {
+ int h = 1;
+ CHECK_INT (height);
+ if (XINT (height) > 1)
+ h = XINT (height);
+ IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = h;
+ }
+}
+
+DEFUN ("subwindowp", Fsubwindowp, 1, 1, 0, /*
+Return non-nil if OBJECT is a subwindow.
+*/
+ (object))
+{
+ CHECK_IMAGE_INSTANCE (object);
+ return (XIMAGE_INSTANCE_TYPE (object) == IMAGE_SUBWINDOW) ? Qt : Qnil;
+}
+
+DEFUN ("image-instance-subwindow-id", Fimage_instance_subwindow_id, 1, 1, 0, /*
+Return the window id of SUBWINDOW as a number.
+*/
+ (subwindow))
+{
+ CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
+ return make_int ((int) (XIMAGE_INSTANCE_SUBWINDOW_ID (subwindow)));
+}
+
+DEFUN ("resize-subwindow", Fresize_subwindow, 1, 3, 0, /*
+Resize SUBWINDOW to WIDTH x HEIGHT.
+If a value is nil that parameter is not changed.
+*/
+ (subwindow, width, height))
+{
+ int neww, newh;
+
+ CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
+
+ if (NILP (width))
+ neww = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow);
+ else
+ neww = XINT (width);
+
+ if (NILP (height))
+ newh = XIMAGE_INSTANCE_SUBWINDOW_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;
+
+ return subwindow;
+}
+
+DEFUN ("force-subwindow-map", Fforce_subwindow_map, 1, 1, 0, /*
+Generate a Map event for SUBWINDOW.
+*/
+ (subwindow))
+{
+ CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow);
+
+ map_subwindow (subwindow, 0, 0);
+
+ return subwindow;