X-Git-Url: http://git.chise.org/gitweb/?p=chise%2Fxemacs-chise.git.1;a=blobdiff_plain;f=src%2Fglyphs-gtk.c;h=d33e8d0a0ee65143dc0a92f12e5f822c659e4480;hp=69e59e1d3a1746587a8fcd9fc6f5aa7f75002d5f;hb=ee38d21b330f5001b47a577cefb5ba7b82a3b7d3;hpb=79d2db7d65205bc85d471590726d0cf3af5598e0 diff --git a/src/glyphs-gtk.c b/src/glyphs-gtk.c index 69e59e1..d33e8d0 100644 --- a/src/glyphs-gtk.c +++ b/src/glyphs-gtk.c @@ -63,6 +63,8 @@ Boston, MA 02111-1307, USA. */ #include "insdel.h" #include "opaque.h" #include "faces.h" +#include "elhash.h" +#include "events.h" #include "imgproc.h" @@ -70,10 +72,19 @@ Boston, MA 02111-1307, USA. */ #include +#if defined (HAVE_XPM) +#include +#endif + #ifdef FILE_CODING #include "file-coding.h" #endif +extern void enqueue_gtk_dispatch_event (Lisp_Object event); + +/* Widget callback hash table callback slot. */ +#define WIDGET_GLYPH_SLOT 0 + #if INTBITS == 32 # define FOUR_BYTE_TYPE unsigned int #elif LONGBITS == 32 @@ -412,7 +423,7 @@ gtk_finalize_image_instance (struct Lisp_Image_Instance *p) #endif else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) { - abort(); + ABORT(); } else { @@ -777,7 +788,7 @@ void init_image_instance_from_gdk_pixmap (struct Lisp_Image_Instance *ii, gint width, height, depth; if (!DEVICE_GTK_P (device)) - abort (); + ABORT (); IMAGE_INSTANCE_DEVICE (ii) = device; IMAGE_INSTANCE_TYPE (ii) = IMAGE_COLOR_PIXMAP; @@ -1023,7 +1034,7 @@ init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii, break; default: - abort (); + ABORT (); } } @@ -1084,105 +1095,21 @@ gtk_xbm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, /********************************************************************** * XPM * **********************************************************************/ -static void -write_lisp_string_to_temp_file (Lisp_Object string, char *filename_out) -{ - Lisp_Object instream, outstream; - Lstream *istr, *ostr; - char tempbuf[1024]; /* some random amount */ - int fubar = 0; - FILE *tmpfil; - static Extbyte_dynarr *conversion_out_dynarr; - Bytecount bstart, bend; - struct gcpro gcpro1, gcpro2; -#ifdef FILE_CODING - Lisp_Object conv_out_stream; - Lstream *costr; - struct gcpro gcpro3; -#endif - - /* This function can GC */ - if (!conversion_out_dynarr) - conversion_out_dynarr = Dynarr_new (Extbyte); - else - Dynarr_reset (conversion_out_dynarr); - - /* Create the temporary file ... */ - sprintf (filename_out, "/tmp/emacs%d.XXXXXX", (int) getpid ()); - mktemp (filename_out); - tmpfil = fopen (filename_out, "w"); - if (!tmpfil) - { - if (tmpfil) - { - int old_errno = errno; - fclose (tmpfil); - unlink (filename_out); - errno = old_errno; - } - report_file_error ("Creating temp file", - list1 (build_string (filename_out))); - } - - CHECK_STRING (string); - get_string_range_byte (string, Qnil, Qnil, &bstart, &bend, - GB_HISTORICAL_STRING_BEHAVIOR); - instream = make_lisp_string_input_stream (string, bstart, bend); - istr = XLSTREAM (instream); - /* setup the out stream */ - outstream = make_dynarr_output_stream((unsigned_char_dynarr *)conversion_out_dynarr); - ostr = XLSTREAM (outstream); -#ifdef FILE_CODING - /* setup the conversion stream */ - conv_out_stream = make_encoding_output_stream (ostr, Fget_coding_system(Qbinary)); - costr = XLSTREAM (conv_out_stream); - GCPRO3 (instream, outstream, conv_out_stream); -#else - GCPRO2 (instream, outstream); -#endif - /* Get the data while doing the conversion */ +/* strcasecmp() is not sufficiently portable or standard, + and it's easier just to write our own. */ +static int +ascii_strcasecmp (const char *s1, const char *s2) +{ while (1) { - int size_in_bytes = Lstream_read (istr, tempbuf, sizeof (tempbuf)); - if (!size_in_bytes) - break; - /* It does seem the flushes are necessary... */ -#ifdef FILE_CODING - Lstream_write (costr, tempbuf, size_in_bytes); - Lstream_flush (costr); -#else - Lstream_write (ostr, tempbuf, size_in_bytes); -#endif - Lstream_flush (ostr); - if (fwrite ((unsigned char *)Dynarr_atp(conversion_out_dynarr, 0), - Dynarr_length(conversion_out_dynarr), 1, tmpfil) != 1) - { - fubar = 1; - break; - } - /* reset the dynarr */ - Lstream_rewind(ostr); + char c1 = *s1++; + char c2 = *s2++; + if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A'; + if (c1 != c2) return c1 - c2; + if (c1 == '\0') return 0; } - - if (fclose (tmpfil) != 0) - fubar = 1; - Lstream_close (istr); -#ifdef FILE_CODING - Lstream_close (costr); -#endif - Lstream_close (ostr); - - UNGCPRO; - Lstream_delete (istr); - Lstream_delete (ostr); -#ifdef FILE_CODING - Lstream_delete (costr); -#endif - - if (fubar) - report_file_error ("Writing temp file", - list1 (build_string (filename_out))); } struct color_symbol @@ -1271,12 +1198,12 @@ gtk_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, GdkWindow *window = 0; int nsymbols = 0, i = 0; struct color_symbol *color_symbols = NULL; - GdkColor *transparent_color = NULL; Lisp_Object color_symbol_alist = find_keyword_in_vector (instantiator, Q_color_symbols); enum image_instance_type type; int force_mono; unsigned int w, h; + const unsigned char * volatile dstring; if (!DEVICE_GTK_P (XDEVICE (device))) signal_simple_error ("Not a Gtk device", device); @@ -1302,20 +1229,58 @@ gtk_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, assert (!NILP (data)); - /* Need to get the transparent color here */ - color_symbols = extract_xpm_color_names (device, domain, color_symbol_alist, &nsymbols); - for (i = 0; i < nsymbols; i++) - { - if (!strcasecmp ("BgColor", color_symbols[i].name) || - !strcasecmp ("None", color_symbols[i].name)) - { - transparent_color = &color_symbols[i].color; - } - } + /* Extract all the entries from xpm-color-symbols */ + color_symbols = extract_xpm_color_names (device, domain, color_symbol_alist, + &nsymbols); + + assert (!NILP (data)); - write_lisp_string_to_temp_file (data, temp_file_name); - pixmap = gdk_pixmap_create_from_xpm (window, &mask, transparent_color, temp_file_name); - unlink (temp_file_name); + + LISP_STRING_TO_EXTERNAL(data, dstring, Qbinary); + + /* + * GTK only uses the 'c' color entry of an XPM and doesn't use the symbolic + * color names at all. This is unfortunate because the way to change the + * colors from lisp is by adding the symbolic names, and the new colors, to + * the variable xpm-color-symbols. + * + * To get around this decode the XPM, add a 'c' entry of the desired color + * for each matching symbolic color, recode the XPM and pass it to GTK. The + * decode and recode stages aren't too bad because this also performs the + * external to internal format translation, which avoids contortions like + * writing the XPM back to disk in order to get it processed. + */ + + { + XpmImage image; + XpmInfo info; + char** data; + + XpmCreateXpmImageFromBuffer ((char*) dstring, &image, &info); + + for (i = 0; i < nsymbols; i++) + { + unsigned j; + + for (j = 0; j < image.ncolors; j++) + { + if (image.colorTable[j].symbolic != NULL && + !ascii_strcasecmp(color_symbols[i].name, image.colorTable[j].symbolic)) + { + image.colorTable[j].c_color = xmalloc(16); + + sprintf(image.colorTable[j].c_color, "#%.4x%.4x%.4x", + color_symbols[i].color.red, color_symbols[i].color.green, + color_symbols[i].color.blue); + } + } + } + + XpmCreateDataFromXpmImage (&data, &image, &info); + + pixmap = gdk_pixmap_create_from_xpm_d (window, &mask, NULL, + data); + } if (color_symbols) xfree (color_symbols); @@ -1327,7 +1292,7 @@ gtk_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, gdk_window_get_geometry (pixmap, NULL, NULL, &w, &h, &depth); IMAGE_INSTANCE_GTK_PIXMAP (ii) = pixmap; - IMAGE_INSTANCE_GTK_MASK (ii) = mask; + IMAGE_INSTANCE_PIXMAP_MASK (ii) = (void*) mask; IMAGE_INSTANCE_GTK_COLORMAP (ii) = cmap; IMAGE_INSTANCE_GTK_PIXELS (ii) = 0; IMAGE_INSTANCE_GTK_NPIXELS (ii) = 0; @@ -1382,7 +1347,7 @@ gtk_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, break; default: - abort (); + ABORT (); } } #endif /* HAVE_XPM */ @@ -2033,7 +1998,7 @@ gtk_unmap_subwindow (Lisp_Image_Instance *p) if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) { /* We don't support subwindows, but we do support widgets... */ - abort (); + ABORT (); } else /* must be a widget */ { @@ -2056,13 +2021,14 @@ gtk_map_subwindow (Lisp_Image_Instance *p, int x, int y, if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) { /* No subwindow support... */ - abort (); + ABORT (); } else /* must be a widget */ { struct frame *f = XFRAME (IMAGE_INSTANCE_FRAME (p)); GtkWidget *wid = IMAGE_INSTANCE_GTK_CLIPWIDGET (p); GtkAllocation a; + int moving; if (!wid) return; @@ -2071,38 +2037,58 @@ gtk_map_subwindow (Lisp_Image_Instance *p, int x, int y, a.width = dga->width; a.height = dga->height; + /* Is the widget cganging position? */ + moving = (a.x != wid->allocation.x) || + (a.y != wid->allocation.y); + if ((a.width != wid->allocation.width) || - (a.height != wid->allocation.height)) + (a.height != wid->allocation.height) || + moving) { gtk_widget_size_allocate (IMAGE_INSTANCE_GTK_CLIPWIDGET (p), &a); } - /* #### FIXME DAMMIT */ - if ((wid->allocation.x != -dga->xoffset) || - (wid->allocation.y != -dga->yoffset)) + if (moving) { guint32 old_flags = GTK_WIDGET_FLAGS (FRAME_GTK_TEXT_WIDGET (f)); - /* Fucking GtkFixed widget queues a resize when you add a widget. + /* GtkFixed widget queues a resize when you add a widget. ** But only if it is visible. ** losers. */ GTK_WIDGET_FLAGS(FRAME_GTK_TEXT_WIDGET (f)) &= ~GTK_VISIBLE; + if (IMAGE_INSTANCE_GTK_ALREADY_PUT(p)) { gtk_fixed_move (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)), wid, - -dga->xoffset, -dga->yoffset); + a.x, a.y); } else { IMAGE_INSTANCE_GTK_ALREADY_PUT(p) = TRUE; gtk_fixed_put (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)), wid, - -dga->xoffset, -dga->yoffset); + a.x, a.y); } + GTK_WIDGET_FLAGS(FRAME_GTK_TEXT_WIDGET (f)) = old_flags; } + else + { + if (IMAGE_INSTANCE_GTK_ALREADY_PUT(p)) + { + /* Do nothing... */ + } + else + { + /* Must make sure we have put the image at least once! */ + IMAGE_INSTANCE_GTK_ALREADY_PUT(p) = TRUE; + gtk_fixed_put (GTK_FIXED (FRAME_GTK_TEXT_WIDGET (f)), + wid, + a.x, a.y); + } + } if (!IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (p)) { @@ -2193,11 +2179,19 @@ gtk_redisplay_widget (Lisp_Image_Instance *p) || IMAGE_INSTANCE_TEXT_CHANGED (p)) { + GtkRequisition r; + GtkAllocation a = IMAGE_INSTANCE_GTK_CLIPWIDGET (p)->allocation; + assert (IMAGE_INSTANCE_GTK_WIDGET_ID (p) && IMAGE_INSTANCE_GTK_CLIPWIDGET (p)) ; - /* #### Resize the widget! */ - /* gtk_widget_size_allocate () */ + a.width = r.width = IMAGE_INSTANCE_WIDTH (p); + a.height = r.height = IMAGE_INSTANCE_HEIGHT (p); + + /* Force the widget's preferred and actual size to what we say it shall + be. */ + gtk_widget_size_request (IMAGE_INSTANCE_GTK_CLIPWIDGET (p), &r); + gtk_widget_size_allocate (IMAGE_INSTANCE_GTK_CLIPWIDGET (p), &a); } /* Adjust offsets within the frame. */ @@ -2356,6 +2350,10 @@ gtk_widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, */ IMAGE_INSTANCE_GTK_CLIPWIDGET (ii) = w; + /* The current theme may produce a widget of a different size that what we + expect so force reconsideration of the widget's size. */ + IMAGE_INSTANCE_LAYOUT_CHANGED (ii) = 1; + return (Qt); } @@ -2404,8 +2402,44 @@ FAKE_GTK_WIDGET_INSTANTIATOR(button); FAKE_GTK_WIDGET_INSTANTIATOR(progress_gauge); FAKE_GTK_WIDGET_INSTANTIATOR(edit_field); FAKE_GTK_WIDGET_INSTANTIATOR(combo_box); -FAKE_GTK_WIDGET_INSTANTIATOR(tab_control); FAKE_GTK_WIDGET_INSTANTIATOR(label); +/* Note: tab_control has a custom instantiator (see below) */ + +/* + Ask the widget to return it's preferred size. This device method must + defined for all widgets that also have format specific version of + query_geometry defined in glyphs-widget.c. This is because those format + specific versions return sizes that are appropriate for the X widgets. For + GTK, the size of a widget can change at runtime due to the user changing + their theme. + + This method can be called before the widget is instantiated. This is + because instantiate_image_instantiator() is tying to be helpful to other + toolkits and supply sane geometry values to them. This is not appropriate + for GTK and can be ignored. + + This method can be used by all widgets. +*/ +static void +gtk_widget_query_geometry (Lisp_Object image_instance, + int* width, int* height, + enum image_instance_geometry disp, Lisp_Object domain) +{ + Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); + + if (p->data != NULL) + { + GtkWidget *w = IMAGE_INSTANCE_GTK_CLIPWIDGET (p); + GtkRequisition r; + + gtk_widget_size_request(w, &r); + *height= r.height; + *width = r.width; + } +} + + +/* Button functions. */ /* Update a button's clicked state. */ static void @@ -2427,7 +2461,7 @@ gtk_button_redisplay (Lisp_Object image_instance) else { /* Unknown button type... */ - abort(); + ABORT(); } } @@ -2448,6 +2482,9 @@ gtk_button_property (Lisp_Object image_instance, Lisp_Object prop) return Qunbound; } + +/* Progress gauge functions. */ + /* set the properties of a progress gauge */ static void gtk_progress_gauge_redisplay (Lisp_Object image_instance) @@ -2467,6 +2504,198 @@ gtk_progress_gauge_redisplay (Lisp_Object image_instance) } } + +/* Tab Control functions. */ + +/* + Register a widget's callbacks with the frame's hashtable. The hashtable is + weak so deregistration is handled automatically. Tab controls have per-tab + callback list functions and the GTK callback architecture is not + sufficiently flexible to deal with this. Instead, the functions are + registered here and the id is passed through the callback loop. + */ +static int +gtk_register_gui_item (Lisp_Object image_instance, Lisp_Object gui, + Lisp_Object domain) +{ + struct frame *f = XFRAME(DOMAIN_FRAME(domain)); + int id = gui_item_id_hash(FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE(f), + gui, WIDGET_GLYPH_SLOT); + + Fputhash(make_int(id), image_instance, + FRAME_GTK_WIDGET_INSTANCE_HASH_TABLE (f)); + Fputhash(make_int(id), XGUI_ITEM (gui)->callback, + FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE (f)); + Fputhash(make_int(id), XGUI_ITEM (gui)->callback_ex, + FRAME_GTK_WIDGET_CALLBACK_EX_HASH_TABLE (f)); + return id; +} + +/* + Append the given item as a tab to the notebook. Callbacks, etc are all + setup. + */ +static void +gtk_add_tab_item(Lisp_Object image_instance, + GtkNotebook* nb, Lisp_Object item, + Lisp_Object domain, int i) +{ + Lisp_Object name; + int hash_id = 0; + char *c_name = NULL; + GtkWidget* box; + + if (GUI_ITEMP (item)) + { + Lisp_Gui_Item *pgui = XGUI_ITEM (item); + + if (!STRINGP (pgui->name)) + pgui->name = Feval (pgui->name); + + CHECK_STRING (pgui->name); + + hash_id = gtk_register_gui_item (image_instance, item, domain); + name = pgui->name; + } + else + { + CHECK_STRING (item); + name = item; + } + + TO_EXTERNAL_FORMAT (LISP_STRING, name, + C_STRING_ALLOCA, c_name, + Qctext); + + /* Dummy widget that the notbook wants to display when a tab is selected. */ + box = gtk_vbox_new (FALSE, 3); + + /* + Store the per-tab callback data id in the tab. The callback functions + themselves could have been stored in the widget but this avoids having to + worry about the garbage collector running between here and the callback + function. + */ + gtk_object_set_data(GTK_OBJECT(box), GTK_DATA_TAB_HASHCODE_IDENTIFIER, + (gpointer) hash_id); + + gtk_notebook_append_page (nb, box, gtk_label_new (c_name)); +} + +/* Signal handler for the switch-page signal. */ +static void gtk_tab_control_callback(GtkNotebook *notebook, + GtkNotebookPage *page, + gint page_num, + gpointer user_data) +{ + /* + This callback is called for every selection, not just user selection. + We're only interested in user selection, which occurs outside of + redisplay. + */ + + if (!in_display) + { + Lisp_Object image_instance, callback, callback_ex; + Lisp_Object frame, event; + int update_subwindows_p = 0; + struct frame *f = gtk_widget_to_frame(GTK_WIDGET(notebook)); + int id; + + if (!f) + return; + frame = wrap_frame (f); + + id = (int) gtk_object_get_data(GTK_OBJECT(page->child), + GTK_DATA_TAB_HASHCODE_IDENTIFIER); + image_instance = Fgethash(make_int(id), + FRAME_GTK_WIDGET_INSTANCE_HASH_TABLE(f), Qnil); + callback = Fgethash(make_int(id), + FRAME_GTK_WIDGET_CALLBACK_HASH_TABLE(f), Qnil); + callback_ex = Fgethash(make_int(id), + FRAME_GTK_WIDGET_CALLBACK_EX_HASH_TABLE(f), Qnil); + update_subwindows_p = 1; + + /* It is possible for a widget action to cause it to get out of + sync with its instantiator. Thus it is necessary to signal + this possibility. */ + if (IMAGE_INSTANCEP (image_instance)) + XIMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (image_instance) = 1; + + if (!NILP (callback_ex) && !UNBOUNDP (callback_ex)) + { + event = Fmake_event (Qnil, Qnil); + + XEVENT (event)->event_type = misc_user_event; + XEVENT (event)->channel = frame; + XEVENT (event)->event.eval.function = Qeval; + XEVENT (event)->event.eval.object = + list4 (Qfuncall, callback_ex, image_instance, event); + } + else if (NILP (callback) || UNBOUNDP (callback)) + event = Qnil; + else + { + Lisp_Object fn, arg; + + event = Fmake_event (Qnil, Qnil); + + get_gui_callback (callback, &fn, &arg); + XEVENT (event)->event_type = misc_user_event; + XEVENT (event)->channel = frame; + XEVENT (event)->event.eval.function = fn; + XEVENT (event)->event.eval.object = arg; + } + + if (!NILP (event)) + enqueue_gtk_dispatch_event (event); + + /* The result of this evaluation could cause other instances to change so + enqueue an update callback to check this. */ + if (update_subwindows_p && !NILP (event)) + enqueue_magic_eval_event (update_widget_instances, frame); + } +} + +/* Create a tab_control widget. The special handling of the individual tabs + means that the normal instantiation code cannot be used. */ +static void +gtk_tab_control_instantiate (Lisp_Object image_instance, + Lisp_Object instantiator, + Lisp_Object pointer_fg, + Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + Lisp_Object rest; + Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + int i = 0; + int selected = 0; + GtkNotebook *nb; + + /* The normal instantiation is still needed. */ + gtk_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain); + + nb = GTK_NOTEBOOK (IMAGE_INSTANCE_GTK_CLIPWIDGET (ii)); + + /* Add items to the tab, find the current selection */ + LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) + { + gtk_add_tab_item (image_instance, nb, XCAR (rest), domain, i); + + if (gui_item_selected_p (XCAR (rest))) + selected = i; + + i++; + } + + gtk_notebook_set_page(nb, selected); + + /* Call per-tab lisp callback when a tab is pressed. */ + gtk_signal_connect (GTK_OBJECT (nb), "switch-page", + GTK_SIGNAL_FUNC (gtk_tab_control_callback), NULL); +} + /* Set the properties of a tab control */ static void gtk_tab_control_redisplay (Lisp_Object image_instance) @@ -2483,6 +2712,7 @@ gtk_tab_control_redisplay (Lisp_Object image_instance) one. */ if (tab_control_order_only_changed (image_instance)) { + int i = 0; Lisp_Object rest, selected = gui_item_list_find_selected (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ? @@ -2496,9 +2726,6 @@ gtk_tab_control_redisplay (Lisp_Object image_instance) Lisp_Object old_selected =gui_item_list_find_selected (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))); - /* Need to focus on the widget... */ - stderr_out ("Hey, change the tab-focus you boob...\n"); - /* Pick up the new selected item. */ XGUI_ITEM (old_selected)->selected = XGUI_ITEM (XCAR (rest))->selected; @@ -2507,8 +2734,14 @@ gtk_tab_control_redisplay (Lisp_Object image_instance) /* We're not actually changing the items anymore. */ IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0; IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil; + + gtk_notebook_set_page(GTK_NOTEBOOK (IMAGE_INSTANCE_GTK_CLIPWIDGET (ii)), + i); + break; } + + i++; } } else @@ -2517,33 +2750,23 @@ gtk_tab_control_redisplay (Lisp_Object image_instance) GtkNotebook *nb = GTK_NOTEBOOK (IMAGE_INSTANCE_GTK_CLIPWIDGET (ii)); guint num_pages = g_list_length (nb->children); Lisp_Object rest; + int i; + /* Why is there no API to remove everything from a notebook? */ if (num_pages >= 0) { - int i; for (i = num_pages; i >= 0; --i) { gtk_notebook_remove_page (nb, i); } } - LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) - { - Lisp_Gui_Item *pgui = XGUI_ITEM (XCAR (rest)); - char *c_name = NULL; + i = 0; - if (!STRINGP (pgui->name)) - pgui->name = Feval (pgui->name); - - CHECK_STRING (pgui->name); - - TO_EXTERNAL_FORMAT (LISP_STRING, pgui->name, - C_STRING_ALLOCA, c_name, - Qctext); - - gtk_notebook_append_page (nb, - gtk_vbox_new (FALSE, 3), - gtk_label_new (c_name)); + LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))) + { + gtk_add_tab_item(image_instance, nb, XCAR(rest), + IMAGE_INSTANCE_FRAME(ii), i); } /* Show all the new widgets we just added... */ @@ -2640,14 +2863,17 @@ image_instantiator_format_create_glyphs_gtk (void) IIFORMAT_HAS_DEVMETHOD (gtk, button, property); IIFORMAT_HAS_DEVMETHOD (gtk, button, instantiate); IIFORMAT_HAS_DEVMETHOD (gtk, button, redisplay); + IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, button, query_geometry, widget); /* general widget methods. */ INITIALIZE_DEVICE_IIFORMAT (gtk, widget); IIFORMAT_HAS_DEVMETHOD (gtk, widget, property); + IIFORMAT_HAS_DEVMETHOD (gtk, widget, query_geometry); /* progress gauge */ INITIALIZE_DEVICE_IIFORMAT (gtk, progress_gauge); IIFORMAT_HAS_DEVMETHOD (gtk, progress_gauge, redisplay); IIFORMAT_HAS_DEVMETHOD (gtk, progress_gauge, instantiate); + IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, progress_gauge, query_geometry, widget); /* text field */ INITIALIZE_DEVICE_IIFORMAT (gtk, edit_field); IIFORMAT_HAS_DEVMETHOD (gtk, edit_field, instantiate); @@ -2658,6 +2884,7 @@ image_instantiator_format_create_glyphs_gtk (void) INITIALIZE_DEVICE_IIFORMAT (gtk, tab_control); IIFORMAT_HAS_DEVMETHOD (gtk, tab_control, instantiate); IIFORMAT_HAS_DEVMETHOD (gtk, tab_control, redisplay); + IIFORMAT_HAS_SHARED_DEVMETHOD (gtk, tab_control, query_geometry, widget); /* label */ INITIALIZE_DEVICE_IIFORMAT (gtk, label); IIFORMAT_HAS_DEVMETHOD (gtk, label, instantiate);