Mercurial > hg > xemacs-beta
diff src/glyphs.c @ 384:bbff43aa5eb7 r21-2-7
Import from CVS: tag r21-2-7
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:08:24 +0200 |
parents | 8626e4521993 |
children | aabb7f5b1c81 |
line wrap: on
line diff
--- a/src/glyphs.c Mon Aug 13 11:07:40 2007 +0200 +++ b/src/glyphs.c Mon Aug 13 11:08:24 2007 +0200 @@ -3,6 +3,7 @@ Copyright (C) 1995 Tinker Systems Copyright (C) 1995, 1996 Ben Wing Copyright (C) 1995 Sun Microsystems + Copyright (C) 1998 Andy Piper This file is part of XEmacs. @@ -34,10 +35,13 @@ #include "faces.h" #include "frame.h" #include "insdel.h" -#include "glyphs.h" +#include "opaque.h" #include "objects.h" #include "redisplay.h" #include "window.h" +#include "frame.h" +#include "chartab.h" +#include "rangetab.h" #ifdef HAVE_XPM #include <X11/xpm.h> @@ -52,11 +56,11 @@ Lisp_Object Qcolor_pixmap_image_instance_p; Lisp_Object Qpointer_image_instance_p; Lisp_Object Qsubwindow_image_instance_p; +Lisp_Object Qwidget_image_instance_p; Lisp_Object Qconst_glyph_variable; Lisp_Object Qmono_pixmap, Qcolor_pixmap, Qsubwindow; -Lisp_Object Q_file, Q_data, Q_face; +Lisp_Object Q_file, Q_data, Q_face, Q_pixel_width, Q_pixel_height; Lisp_Object Qformatted_string; - Lisp_Object Vcurrent_display_table; Lisp_Object Vtruncation_glyph, Vcontinuation_glyph, Voctal_escape_glyph; Lisp_Object Vcontrol_arrow_glyph, Vinvisible_text_glyph, Vhscroll_glyph; @@ -70,6 +74,7 @@ DEFINE_IMAGE_INSTANTIATOR_FORMAT (inherit); DEFINE_IMAGE_INSTANTIATOR_FORMAT (string); DEFINE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); +DEFINE_IMAGE_INSTANTIATOR_FORMAT (subwindow); #ifdef HAVE_WINDOW_SYSTEM DEFINE_IMAGE_INSTANTIATOR_FORMAT (xbm); @@ -95,6 +100,7 @@ struct image_instantiator_format_entry { Lisp_Object symbol; + Lisp_Object device; struct image_instantiator_methods *meths; }; @@ -119,8 +125,9 @@ * Image Instantiators * ****************************************************************************/ -static struct image_instantiator_methods * -decode_image_instantiator_format (Lisp_Object format, Error_behavior errb) +struct image_instantiator_methods * +decode_device_ii_format (Lisp_Object device, Lisp_Object format, + Error_behavior errb) { int i; @@ -134,10 +141,19 @@ for (i = 0; i < Dynarr_length (the_image_instantiator_format_entry_dynarr); i++) { - if (EQ (format, - Dynarr_at (the_image_instantiator_format_entry_dynarr, i). - symbol)) - return Dynarr_at (the_image_instantiator_format_entry_dynarr, i).meths; + if ( EQ (format, + Dynarr_at (the_image_instantiator_format_entry_dynarr, i). + symbol) ) + { + Lisp_Object d = Dynarr_at (the_image_instantiator_format_entry_dynarr, i). + device; + if ((NILP (d) && NILP (device)) + || + (!NILP (device) && + EQ (CONSOLE_TYPE (XCONSOLE + (DEVICE_CONSOLE (XDEVICE (device)))), d))) + return Dynarr_at (the_image_instantiator_format_entry_dynarr, i).meths; + } } maybe_signal_simple_error ("Invalid image-instantiator format", format, @@ -146,6 +162,12 @@ return 0; } +struct image_instantiator_methods * +decode_image_instantiator_format (Lisp_Object format, Error_behavior errb) +{ + return decode_device_ii_format (Qnil, format, errb); +} + static int valid_image_instantiator_format_p (Lisp_Object format) { @@ -157,7 +179,7 @@ Given an IMAGE-INSTANTIATOR-FORMAT, return non-nil if it is valid. Valid formats are some subset of 'nothing, 'string, 'formatted-string, 'xpm, 'xbm, 'xface, 'gif, 'jpeg, 'png, 'tiff, 'cursor-font, 'font, -'autodetect, and 'subwindow, depending on how XEmacs was compiled. +'autodetect, 'widget and 'subwindow, depending on how XEmacs was compiled. */ (image_instantiator_format)) { @@ -175,17 +197,25 @@ } void +add_entry_to_device_ii_format_list (Lisp_Object device, Lisp_Object symbol, + struct image_instantiator_methods *meths) +{ + struct image_instantiator_format_entry entry; + + entry.symbol = symbol; + entry.device = device; + entry.meths = meths; + Dynarr_add (the_image_instantiator_format_entry_dynarr, entry); + Vimage_instantiator_format_list = + Fcons (symbol, Vimage_instantiator_format_list); +} + +void add_entry_to_image_instantiator_format_list (Lisp_Object symbol, struct image_instantiator_methods *meths) { - struct image_instantiator_format_entry entry; - - entry.symbol = symbol; - entry.meths = meths; - Dynarr_add (the_image_instantiator_format_entry_dynarr, entry); - Vimage_instantiator_format_list = - Fcons (symbol, Vimage_instantiator_format_list); + add_entry_to_device_ii_format_list (Qnil, symbol, meths); } static Lisp_Object * @@ -355,7 +385,13 @@ CHECK_STRING (data); } -static void +void +check_valid_vector (Lisp_Object data) +{ + CHECK_VECTOR (data); +} + +void check_valid_face (Lisp_Object data) { Fget_face (data); @@ -481,12 +517,16 @@ longer exist (e.g. w3 pixmaps are almost always from temporary files). */ { - struct image_instantiator_methods * meths = - decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0], - ERROR_ME); - return IIFORMAT_METH_OR_GIVEN (meths, normalize, - (instantiator, contype), - instantiator); + struct gcpro gcpro1; + 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, + (instantiator, contype), + instantiator)); } } @@ -499,16 +539,25 @@ Lisp_Object ii = allocate_image_instance (device); struct image_instantiator_methods *meths; struct gcpro gcpro1; + int methp = 0; GCPRO1 (ii); meths = decode_image_instantiator_format (XVECTOR_DATA (instantiator)[0], ERROR_ME); - if (!HAS_IIFORMAT_METH_P (meths, instantiate)) + 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); + + if (!methp && (!meths || !HAS_IIFORMAT_METH_P (meths, instantiate))) signal_simple_error ("Don't know how to instantiate this image instantiator?", instantiator); - IIFORMAT_METH (meths, instantiate, (ii, instantiator, pointer_fg, - pointer_bg, dest_mask, domain)); + MAYBE_IIFORMAT_METH (meths, instantiate, (ii, instantiator, pointer_fg, + pointer_bg, dest_mask, domain)); UNGCPRO; return ii; @@ -541,9 +590,16 @@ markobj (IMAGE_INSTANCE_PIXMAP_FG (i)); markobj (IMAGE_INSTANCE_PIXMAP_BG (i)); break; + + case IMAGE_WIDGET: + markobj (IMAGE_INSTANCE_WIDGET_TYPE (i)); + markobj (IMAGE_INSTANCE_WIDGET_PROPS (i)); + markobj (IMAGE_INSTANCE_WIDGET_FACE (i)); + mark_gui_item (&IMAGE_INSTANCE_WIDGET_ITEM (i), markobj); case IMAGE_SUBWINDOW: - /* #### implement me */ + markobj (IMAGE_INSTANCE_SUBWINDOW_FRAME (i)); break; + default: break; } @@ -645,8 +701,48 @@ } 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); + 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: - /* #### implement me */ + sprintf (buf, " %dx%d", IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii), + IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii)); + write_c_string (buf, printcharfun); + + /* This is stolen from frame.c. Subwindows are strange in that they + are specific to a particular frame so we want to print in their + description what that frame is. */ + + 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 + write_c_string (DEVICE_TYPE_NAME (XDEVICE (FRAME_DEVICE (f))), + printcharfun); + + write_c_string ("-frame ", printcharfun); + } + write_c_string (">", printcharfun); + sprintf (buf, " 0x%p", IMAGE_INSTANCE_SUBWINDOW_ID (ii)); + write_c_string (buf, printcharfun); + break; default: @@ -669,6 +765,15 @@ return; if (for_disksave) finalose (i); + /* do this so that the cachels get reset */ + if (IMAGE_INSTANCE_TYPE (i) == IMAGE_WIDGET + || + IMAGE_INSTANCE_TYPE (i) == IMAGE_SUBWINDOW) + { + MARK_FRAME_GLYPHS_CHANGED + (XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (i))); + } + MAYBE_DEVMETH (XDEVICE (i->device), finalize_image_instance, (i)); } @@ -722,8 +827,26 @@ return 0; break; + case IMAGE_WIDGET: + if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1), + IMAGE_INSTANCE_WIDGET_TYPE (i2)) && + EQ (IMAGE_INSTANCE_WIDGET_CALLBACK (i1), + IMAGE_INSTANCE_WIDGET_CALLBACK (i2)) + && internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1), + IMAGE_INSTANCE_WIDGET_PROPS (i2), + depth + 1) + && internal_equal (IMAGE_INSTANCE_WIDGET_TEXT (i1), + IMAGE_INSTANCE_WIDGET_TEXT (i2), + depth + 1))) + return 0; case IMAGE_SUBWINDOW: - /* #### implement me */ + 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) == + IMAGE_INSTANCE_SUBWINDOW_ID (i2))) + return 0; break; default: @@ -760,8 +883,15 @@ depth + 1)); break; + case IMAGE_WIDGET: + hash = HASH4 (hash, + internal_hash (IMAGE_INSTANCE_WIDGET_TYPE (i), depth + 1), + internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1), + internal_hash (IMAGE_INSTANCE_WIDGET_CALLBACK (i), depth + 1)); case IMAGE_SUBWINDOW: - /* #### implement me */ + hash = HASH4 (hash, IMAGE_INSTANCE_SUBWINDOW_WIDTH (i), + IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i), + (int) IMAGE_INSTANCE_SUBWINDOW_ID (i)); break; default: @@ -805,6 +935,7 @@ if (EQ (type, Qcolor_pixmap)) return IMAGE_COLOR_PIXMAP; if (EQ (type, Qpointer)) return IMAGE_POINTER; if (EQ (type, Qsubwindow)) return IMAGE_SUBWINDOW; + if (EQ (type, Qwidget)) return IMAGE_WIDGET; maybe_signal_simple_error ("Invalid image-instance type", type, Qimage, errb); @@ -823,6 +954,7 @@ case IMAGE_COLOR_PIXMAP: return Qcolor_pixmap; case IMAGE_POINTER: return Qpointer; case IMAGE_SUBWINDOW: return Qsubwindow; + case IMAGE_WIDGET: return Qwidget; default: abort (); } @@ -1069,17 +1201,94 @@ DEFUN ("image-instance-string", Fimage_instance_string, 1, 1, 0, /* Return the string of the given image instance. -This will only be non-nil for text image instances. +This will only be non-nil for text image instances and widgets. */ (image_instance)) { CHECK_IMAGE_INSTANCE (image_instance); if (XIMAGE_INSTANCE_TYPE (image_instance) == IMAGE_TEXT) return XIMAGE_INSTANCE_TEXT_STRING (image_instance); + else if (XIMAGE_INSTANCE_TYPE (image_instance) == IMAGE_WIDGET) + return XIMAGE_INSTANCE_WIDGET_TEXT (image_instance); else return Qnil; } +DEFUN ("image-instance-property", Fimage_instance_property, 2, 2, 0, /* +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. +*/ + (image_instance, prop)) +{ + struct Lisp_Image_Instance* ii; + Lisp_Object type, ret; + struct image_instantiator_methods* meths; + + CHECK_IMAGE_INSTANCE (image_instance); + CHECK_SYMBOL (prop); + ii = XIMAGE_INSTANCE (image_instance); + + /* ... then try device specific methods ... */ + type = encode_image_instance_type (IMAGE_INSTANCE_TYPE (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; + } + /* ... then format specific methods ... */ + meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT); + if (meths && HAS_IIFORMAT_METH_P (meths, property) + && + !UNBOUNDP (ret = IIFORMAT_METH (meths, property, (image_instance, prop)))) + { + return ret; + } + /* ... then fail */ + return Qnil; +} + +DEFUN ("set-image-instance-property", Fset_image_instance_property, 3, 3, 0, /* +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_Object type, ret; + struct image_instantiator_methods* meths; + + CHECK_IMAGE_INSTANCE (image_instance); + CHECK_SYMBOL (prop); + 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), + type, ERROR_ME_NOT); + if (meths && HAS_IIFORMAT_METH_P (meths, set_property) + && + !UNBOUNDP (ret = + IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) + { + return ret; + } + /* ... then format specific methods ... */ + meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT); + if (meths && HAS_IIFORMAT_METH_P (meths, set_property) + && + !UNBOUNDP (ret = + IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) + { + return ret; + } + + return val; +} + DEFUN ("image-instance-file-name", Fimage_instance_file_name, 1, 1, 0, /* Return the file name from which IMAGE-INSTANCE was read, if known. */ @@ -1152,6 +1361,10 @@ case IMAGE_POINTER: return make_int (XIMAGE_INSTANCE_PIXMAP_HEIGHT (image_instance)); + case IMAGE_SUBWINDOW: + case IMAGE_WIDGET: + return make_int (XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (image_instance)); + default: return Qnil; } @@ -1171,6 +1384,10 @@ case IMAGE_POINTER: return make_int (XIMAGE_INSTANCE_PIXMAP_WIDTH (image_instance)); + case IMAGE_SUBWINDOW: + case IMAGE_WIDGET: + return make_int (XIMAGE_INSTANCE_SUBWINDOW_WIDTH (image_instance)); + default: return Qnil; } @@ -1240,6 +1457,12 @@ case IMAGE_POINTER: return XIMAGE_INSTANCE_PIXMAP_FG (image_instance); + case IMAGE_WIDGET: + return FACE_FOREGROUND ( + XIMAGE_INSTANCE_WIDGET_FACE (image_instance), + XIMAGE_INSTANCE_SUBWINDOW_FRAME + (image_instance)); + default: return Qnil; } @@ -1261,6 +1484,12 @@ case IMAGE_POINTER: return XIMAGE_INSTANCE_PIXMAP_BG (image_instance); + case IMAGE_WIDGET: + return FACE_BACKGROUND ( + XIMAGE_INSTANCE_WIDGET_FACE (image_instance), + XIMAGE_INSTANCE_SUBWINDOW_FRAME + (image_instance)); + default: return Qnil; } @@ -1769,19 +1998,6 @@ IMAGE_POINTER_MASK; } -static void -xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, - Lisp_Object pointer_fg, Lisp_Object pointer_bg, - int dest_mask, Lisp_Object domain) -{ - Lisp_Object device= IMAGE_INSTANCE_DEVICE (XIMAGE_INSTANCE (image_instance)); - - MAYBE_DEVMETH (XDEVICE (device), - xbm_instantiate, - (image_instance, instantiator, pointer_fg, - pointer_bg, dest_mask, domain)); -} - #endif @@ -1796,8 +2012,10 @@ { char **data; int result; - - result = XpmReadFileToData ((char *) XSTRING_DATA (name), &data); + char *fname = 0; + + GET_C_STRING_FILENAME_DATA_ALLOCA (name, fname); + result = XpmReadFileToData (fname, &data); if (result == XpmSuccess) { @@ -1994,19 +2212,6 @@ IMAGE_POINTER_MASK; } -static void -xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, - Lisp_Object pointer_fg, Lisp_Object pointer_bg, - int dest_mask, Lisp_Object domain) -{ - Lisp_Object device= IMAGE_INSTANCE_DEVICE (XIMAGE_INSTANCE (image_instance)); - - MAYBE_DEVMETH (XDEVICE (device), - xpm_instantiate, - (image_instance, instantiator, pointer_fg, - pointer_bg, dest_mask, domain)); -} - #endif /* HAVE_XPM */ @@ -2109,7 +2314,7 @@ /* 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 @@ -2133,8 +2338,28 @@ instance = Qunbound; } else - instance = Fgethash (pointerp ? ls3 : instantiator, - subtable, Qunbound); + { + instance = Fgethash (pointerp ? ls3 : instantiator, + subtable, Qunbound); + /* subwindows have a per-window cache and have to be treated + differently. dest_mask can be a bitwise OR of all image + types so we will only catch someone possibly trying to + instantiate a subwindow type thing. Unfortunately, this + will occur most of the time so this probably slows things + down. But with the current design I don't see anyway + round it. */ + if (UNBOUNDP (instance) + && + dest_mask & (IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK)) + { + if (!WINDOWP (domain)) + signal_simple_error ("Can't instantiate subwindow outside a window", + instantiator); + instance = Fgethash (instantiator, + XWINDOW (domain)->subwindow_instance_cache, + Qunbound); + } + } if (UNBOUNDP (instance)) { @@ -2143,7 +2368,7 @@ 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 @@ -2157,7 +2382,21 @@ instantiator, pointer_fg, pointer_bg, dest_mask); + 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)) + { + if (!WINDOWP (domain)) + signal_simple_error ("Can't instantiate subwindow outside a window", + instantiator); + + Fsetcdr (XCDR (locative), XWINDOW (domain)->subwindow_instance_cache ); + } unbind_to (speccount, Qnil); } else @@ -2357,7 +2596,7 @@ (Display this image as a text string, with replaceable fields; not currently implemented.) 'xbm - (An X bitmap; only if X support was compiled into this XEmacs. + (An X bitmap; only if X or Windows support was compiled into this XEmacs. Can be instanced as `mono-pixmap', `color-pixmap', or `pointer'.) 'xpm (An XPM pixmap; only if XPM support was compiled into this XEmacs. @@ -2393,6 +2632,8 @@ probably be fixed.) 'subwindow (An embedded X window; not currently implemented.) +'widget + (A widget control, for instance text field or radio button.) 'autodetect (XEmacs tries to guess what format the data is in. If X support exists, the data string will be checked to see if it names a filename. @@ -2423,7 +2664,7 @@ `cursor-font', `font', `autodetect', and `inherit'.) :foreground :background - (For `xbm', `xface', `cursor-font', and `font'. These keywords + (For `xbm', `xface', `cursor-font', `widget' and `font'. These keywords allow you to explicitly specify foreground and background colors. The argument should be anything acceptable to `make-color-instance'. This will cause what would be a `mono-pixmap' to instead be colorized @@ -2628,8 +2869,9 @@ { case GLYPH_BUFFER: XIMAGE_SPECIFIER_ALLOWED (g->image) = - IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK | IMAGE_MONO_PIXMAP_MASK | - IMAGE_COLOR_PIXMAP_MASK | IMAGE_SUBWINDOW_MASK; + IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK + | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK + | IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK; break; case GLYPH_POINTER: XIMAGE_SPECIFIER_ALLOWED (g->image) = @@ -2825,8 +3067,8 @@ return 0; case IMAGE_SUBWINDOW: - /* #### implement me */ - return 0; + case IMAGE_WIDGET: + return XIMAGE_INSTANCE_SUBWINDOW_WIDTH (instance); default: abort (); @@ -2929,8 +3171,12 @@ return 0; case IMAGE_SUBWINDOW: - /* #### implement me */ - return 0; + case IMAGE_WIDGET: + /* #### Ugh ugh ugh -- temporary crap */ + if (function == RETURN_ASCENT || function == RETURN_HEIGHT) + return XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (instance); + else + return 0; default: abort (); @@ -3200,36 +3446,399 @@ #endif /* MEMORY_USAGE_STATS */ + + +/***************************************************************************** + * subwindow cachel functions * + *****************************************************************************/ +/* 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 + instantiator in the hashtable and when the instantiator goes away + we want the instance to go away also. However we also have a + per-frame instance cache that we use to determine if a subwindow is + obscuring an area that we want to clear. We need to be able to flip + through this quickly so a hashtable is not suitable hence the + subwindow_cachels. The question is should we just not mark + instances in the subwindow_cachelsnor should we try and invalidate + the cache at suitable points in redisplay? If we don't invalidate + the cache it will fill up with crud that will only get removed when + the frame is deleted. So invalidation is good, the question is when + and whether we mark as well. Go for the simple option - don't mark, + MARK_SUBWINDOWS_CHANGED when a subwindow gets deleted. */ + +void +mark_subwindow_cachels (subwindow_cachel_dynarr *elements, + void (*markobj) (Lisp_Object)) +{ + int elt; + + if (!elements) + return; + + for (elt = 0; elt < Dynarr_length (elements); elt++) + { + struct subwindow_cachel *cachel = Dynarr_atp (elements, elt); + markobj (cachel->subwindow); + } +} + +static void +update_subwindow_cachel_data (struct frame *f, Lisp_Object subwindow, + struct subwindow_cachel *cachel) +{ + if (NILP (cachel->subwindow) || !EQ (cachel->subwindow, subwindow)) + { + cachel->subwindow = subwindow; + cachel->width = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow); + cachel->height = XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow); + } + + cachel->updated = 1; +} + +static void +add_subwindow_cachel (struct frame *f, Lisp_Object subwindow) +{ + struct subwindow_cachel new_cachel; + + 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; +} + +void +reset_subwindow_cachels (struct frame *f) +{ + 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; +} + + +/***************************************************************************** + * 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; +} + /***************************************************************************** * display tables * *****************************************************************************/ -/* Get the display table for use currently on window W with face FACE. - Precedence: - - -- FACE's display table - -- W's display table (comes from specifier `current-display-table') - - Ignore the specified tables if they are not valid; - if no valid table is specified, return 0. */ - -struct Lisp_Vector * -get_display_table (struct window *w, face_index findex) +/* Get the display tables for use currently on window W with face + FACE. #### This will have to be redone. */ + +void +get_display_tables (struct window *w, face_index findex, + Lisp_Object *face_table, Lisp_Object *window_table) { Lisp_Object tem; - tem = WINDOW_FACE_CACHEL_DISPLAY_TABLE (w, findex); - if (VECTORP (tem) && XVECTOR_LENGTH (tem) == DISP_TABLE_SIZE) - return XVECTOR (tem); - + if (UNBOUNDP (tem)) + tem = Qnil; + if (!LISTP (tem)) + tem = noseeum_cons (tem, Qnil); + *face_table = tem; tem = w->display_table; - if (VECTORP (tem) && XVECTOR_LENGTH (tem) == DISP_TABLE_SIZE) - return XVECTOR (tem); - - return 0; + if (UNBOUNDP (tem)) + tem = Qnil; + if (!LISTP (tem)) + tem = noseeum_cons (tem, Qnil); + *window_table = tem; } +Lisp_Object +display_table_entry (Emchar ch, Lisp_Object face_table, + Lisp_Object window_table) +{ + Lisp_Object tail; + + /* Loop over FACE_TABLE, and then over WINDOW_TABLE. */ + for (tail = face_table; 1; tail = XCDR (tail)) + { + Lisp_Object table; + if (NILP (tail)) + { + if (!NILP (window_table)) + { + tail = window_table; + window_table = Qnil; + } + else + return Qnil; + } + table = XCAR (tail); + + if (VECTORP (table)) + { + if (ch < XVECTOR_LENGTH (table) && !NILP (XVECTOR_DATA (table)[ch])) + return XVECTOR_DATA (table)[ch]; + else + continue; + } + else if (CHAR_TABLEP (table) + && XCHAR_TABLE_TYPE (table) == CHAR_TABLE_TYPE_CHAR) + { + return get_char_table (ch, XCHAR_TABLE (table)); + } + else if (CHAR_TABLEP (table) + && XCHAR_TABLE_TYPE (table) == CHAR_TABLE_TYPE_GENERIC) + { + Lisp_Object gotit = get_char_table (ch, XCHAR_TABLE (table)); + if (!NILP (gotit)) + return gotit; + else + continue; + } + else if (RANGE_TABLEP (table)) + { + Lisp_Object gotit = Fget_range_table (make_char (ch), table, Qnil); + if (!NILP (gotit)) + return gotit; + else + continue; + } + else + abort (); + } +} /***************************************************************************** * initialization * @@ -3248,6 +3857,8 @@ defkeyword (&Q_file, ":file"); defkeyword (&Q_data, ":data"); defkeyword (&Q_face, ":face"); + defkeyword (&Q_pixel_height, ":pixel-height"); + defkeyword (&Q_pixel_width, ":pixel-width"); #ifdef HAVE_XPM defkeyword (&Q_color_symbols, ":color-symbols"); @@ -3274,6 +3885,7 @@ defsymbol (&Qmono_pixmap_image_instance_p, "mono-pixmap-image-instance-p"); defsymbol (&Qcolor_pixmap_image_instance_p, "color-pixmap-image-instance-p"); defsymbol (&Qpointer_image_instance_p, "pointer-image-instance-p"); + defsymbol (&Qwidget_image_instance_p, "widget-image-instance-p"); defsymbol (&Qsubwindow_image_instance_p, "subwindow-image-instance-p"); DEFSUBR (Fmake_image_instance); @@ -3292,7 +3904,14 @@ DEFSUBR (Fimage_instance_hotspot_y); DEFSUBR (Fimage_instance_foreground); DEFSUBR (Fimage_instance_background); + DEFSUBR (Fimage_instance_property); + DEFSUBR (Fset_image_instance_property); DEFSUBR (Fcolorize_image_instance); + /* subwindows */ + DEFSUBR (Fsubwindowp); + DEFSUBR (Fimage_instance_subwindow_id); + DEFSUBR (Fresize_subwindow); + DEFSUBR (Fforce_subwindow_map); /* Qnothing defined as part of the "nothing" image-instantiator type. */ @@ -3300,7 +3919,6 @@ defsymbol (&Qmono_pixmap, "mono-pixmap"); defsymbol (&Qcolor_pixmap, "color-pixmap"); /* Qpointer defined in general.c */ - defsymbol (&Qsubwindow, "subwindow"); /* glyphs */ @@ -3390,13 +4008,19 @@ IIFORMAT_VALID_KEYWORD (formatted_string, Q_data, check_valid_string); + /* subwindows */ + INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (subwindow, "subwindow"); + IIFORMAT_HAS_METHOD (subwindow, possible_dest_types); + IIFORMAT_HAS_METHOD (subwindow, instantiate); + IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_width, check_valid_int); + IIFORMAT_VALID_KEYWORD (subwindow, Q_pixel_height, check_valid_int); + #ifdef HAVE_WINDOW_SYSTEM INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (xbm, "xbm"); IIFORMAT_HAS_METHOD (xbm, validate); IIFORMAT_HAS_METHOD (xbm, normalize); IIFORMAT_HAS_METHOD (xbm, possible_dest_types); - IIFORMAT_HAS_METHOD (xbm, instantiate); IIFORMAT_VALID_KEYWORD (xbm, Q_data, check_valid_xbm_inline); IIFORMAT_VALID_KEYWORD (xbm, Q_file, check_valid_string); @@ -3414,7 +4038,6 @@ IIFORMAT_HAS_METHOD (xpm, validate); IIFORMAT_HAS_METHOD (xpm, normalize); IIFORMAT_HAS_METHOD (xpm, possible_dest_types); - IIFORMAT_HAS_METHOD (xpm, instantiate); IIFORMAT_VALID_KEYWORD (xpm, Q_data, check_valid_string); IIFORMAT_VALID_KEYWORD (xpm, Q_file, check_valid_string); @@ -3430,8 +4053,9 @@ /* image instances */ - Vimage_instance_type_list = list6 (Qnothing, Qtext, Qmono_pixmap, - Qcolor_pixmap, Qpointer, Qsubwindow); + Vimage_instance_type_list = Fcons (Qnothing, + list6 (Qtext, Qmono_pixmap, Qcolor_pixmap, + Qpointer, Qsubwindow, Qwidget)); staticpro (&Vimage_instance_type_list); /* glyphs */ @@ -3467,7 +4091,9 @@ What to display at the beginning of horizontally scrolled lines. */); Vhscroll_glyph = allocate_glyph (GLYPH_BUFFER, redisplay_glyph_changed); - +#ifdef HAVE_WINDOW_SYSTEM + Fprovide (Qxbm); +#endif #ifdef HAVE_XPM Fprovide (Qxpm);