+#ifdef HAVE_WIDGETS
+
+/************************************************************************/
+/* widgets */
+/************************************************************************/
+static void
+mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain,
+ const char* class, int flags, int exflags)
+{
+ /* this function can call lisp */
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), style;
+ Lisp_Object frame = DOMAIN_FRAME (domain);
+ Extbyte* nm=0;
+ HWND wnd;
+ int id = 0xffff;
+ Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
+ Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
+
+ CHECK_MSWINDOWS_DEVICE (device);
+
+ if (!gui_item_active_p (gui))
+ flags |= WS_DISABLED;
+
+ style = pgui->style;
+
+ if (!NILP (pgui->callback) || !NILP (pgui->callback_ex))
+ {
+ id = mswindows_register_widget_instance (image_instance, domain);
+ }
+
+ if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
+ TO_EXTERNAL_FORMAT (LISP_STRING, IMAGE_INSTANCE_WIDGET_TEXT (ii),
+ C_STRING_ALLOCA, nm,
+ Qnative);
+
+ /* allocate space for the clip window and then allocate the clip window */
+ ii->data = xnew_and_zero (struct mswindows_subwindow_data);
+
+ if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii)
+ = CreateWindowEx(
+ WS_EX_CONTROLPARENT, /* EX flags */
+ XEMACS_CONTROL_CLASS,
+ 0, /* text */
+ WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD,
+ 0, /* starting x position */
+ 0, /* starting y position */
+ IMAGE_INSTANCE_WIDGET_WIDTH (ii),
+ IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
+ /* parent window */
+ DOMAIN_MSWINDOWS_HANDLE (domain),
+ (HMENU)id, /* No menu */
+ NULL, /* must be null for this class */
+ NULL)) == NULL)
+ signal_simple_error ("window creation failed with code",
+ make_int (GetLastError()));
+
+ if ((wnd = CreateWindowEx(
+ exflags /* | WS_EX_NOPARENTNOTIFY*/,
+ class,
+ nm,
+ flags | WS_CHILD | WS_VISIBLE,
+ 0, /* starting x position */
+ 0, /* starting y position */
+ IMAGE_INSTANCE_WIDGET_WIDTH (ii),
+ IMAGE_INSTANCE_WIDGET_HEIGHT (ii),
+ /* parent window */
+ IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii),
+ (HMENU)id, /* No menu */
+ (HINSTANCE)
+ GetWindowLong
+ (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)),
+ GWL_HINSTANCE),
+ NULL)) == NULL)
+ signal_simple_error ("window creation failed with code",
+ make_int (GetLastError()));
+
+ IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd;
+ SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance));
+ /* set the widget font from the widget face */
+ if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
+ SendMessage (wnd, WM_SETFONT,
+ (WPARAM) mswindows_widget_hfont (ii, domain),
+ MAKELPARAM (TRUE, 0));
+}
+
+/* Instantiate a native layout widget. */
+static void
+mswindows_native_layout_instantiate (Lisp_Object image_instance,
+ Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain)
+{
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+ mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain, "STATIC",
+ /* Approximation to styles available with
+ an XEmacs layout. */
+ (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
+ Qetched_in) ||
+ EQ (IMAGE_INSTANCE_LAYOUT_BORDER (ii),
+ Qetched_out) ||
+ GLYPHP (IMAGE_INSTANCE_LAYOUT_BORDER (ii))
+ ? SS_ETCHEDFRAME : SS_SUNKEN) | DS_CONTROL,
+ 0);
+}
+
+/* Instantiate a button widget. Unfortunately instantiated widgets are
+ particular to a frame since they need to have a parent. It's not
+ like images where you just select the image into the context you
+ want to display it in and BitBlt it. So image instances can have a
+ many-to-one relationship with things you see, whereas widgets can
+ only be one-to-one (i.e. per frame) */
+static void
+mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain)
+{
+ /* This function can call lisp */
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ HWND wnd;
+ int flags = WS_TABSTOP | BS_NOTIFY;
+ /* BS_NOTIFY #### is needed to get exotic feedback only. Since we
+ seem to want nothing beyond BN_CLICK, the style is perhaps not
+ necessary -- kkm */
+ Lisp_Object style;
+ Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
+ Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
+ Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
+
+ if (!NILP (glyph))
+ {
+ if (!IMAGE_INSTANCEP (glyph))
+ glyph = glyph_image_instance (glyph, domain, ERROR_ME, 1);
+
+ if (IMAGE_INSTANCEP (glyph))
+ flags |= XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
+ BS_BITMAP : BS_ICON;
+ }
+
+ style = pgui->style;
+
+ /* #### consider using the default face for radio and toggle
+ buttons. */
+ if (EQ (style, Qradio))
+ {
+ flags |= BS_RADIOBUTTON;
+ }
+ else if (EQ (style, Qtoggle))
+ {
+ flags |= BS_AUTOCHECKBOX;
+ }
+ else
+ {
+ flags |= BS_DEFPUSHBUTTON;
+ }
+
+ mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain, "BUTTON",
+ flags, 0);
+
+ wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+ /* set the checked state */
+ if (gui_item_selected_p (gui))
+ SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
+ else
+ SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
+ /* add the image if one was given */
+ if (!NILP (glyph) && IMAGE_INSTANCEP (glyph)
+ &&
+ IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (glyph)))
+ {
+ SendMessage (wnd, BM_SETIMAGE,
+ (WPARAM) (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
+ IMAGE_BITMAP : IMAGE_ICON),
+ (XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) ?
+ (LPARAM) XIMAGE_INSTANCE_MSWINDOWS_BITMAP (glyph) :
+ (LPARAM) XIMAGE_INSTANCE_MSWINDOWS_ICON (glyph)));
+ }
+}
+
+/* Update the state of a button. */
+static void
+mswindows_button_redisplay (Lisp_Object image_instance)
+{
+ /* This function can GC if IN_REDISPLAY is false. */
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+ /* buttons checked or otherwise */
+ if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_ITEM (ii)))
+ SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
+ BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
+ else
+ SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
+ BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
+}
+
+/* instantiate an edit control */
+static void
+mswindows_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain)
+{
+ mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain, "EDIT",
+ ES_LEFT | ES_AUTOHSCROLL | WS_TABSTOP
+ | WS_BORDER, WS_EX_CLIENTEDGE);
+}
+
+/* instantiate a progress gauge */
+static void
+mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain)
+{
+ HWND wnd;
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Object val;
+ mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain, PROGRESS_CLASS,
+ WS_BORDER | PBS_SMOOTH, WS_EX_CLIENTEDGE);
+ wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+ /* set the colors */
+#ifdef PBS_SETBKCOLOR
+ SendMessage (wnd, PBS_SETBKCOLOR, 0,
+ (LPARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR
+ (XCOLOR_INSTANCE
+ (FACE_BACKGROUND
+ (XIMAGE_INSTANCE_WIDGET_FACE (ii),
+ XIMAGE_INSTANCE_FRAME (ii))))));
+#endif
+#ifdef PBS_SETBARCOLOR
+ SendMessage (wnd, PBS_SETBARCOLOR, 0,
+ (L:PARAM) (COLOR_INSTANCE_MSWINDOWS_COLOR
+ (XCOLOR_INSTANCE
+ (FACE_FOREGROUND
+ (XIMAGE_INSTANCE_WIDGET_FACE (ii),
+ XIMAGE_INSTANCE_FRAME (ii))))));
+#endif
+ val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEMS (ii))->value;
+ CHECK_INT (val);
+ SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
+ PBM_SETPOS, (WPARAM)XINT (val), 0);
+}
+
+/* instantiate a tree view widget */
+static HTREEITEM add_tree_item (Lisp_Object image_instance,
+ HWND wnd, HTREEITEM parent, Lisp_Object item,
+ int children, Lisp_Object domain)
+{
+ TV_INSERTSTRUCT tvitem;
+ HTREEITEM ret;
+
+ tvitem.hParent = parent;
+ tvitem.hInsertAfter = TVI_LAST;
+ tvitem.item.mask = TVIF_TEXT | TVIF_CHILDREN;
+ tvitem.item.cChildren = children;
+
+ if (GUI_ITEMP (item))
+ {
+ tvitem.item.lParam = mswindows_register_gui_item (image_instance,
+ item, domain);
+ tvitem.item.mask |= TVIF_PARAM;
+ TO_EXTERNAL_FORMAT (LISP_STRING, XGUI_ITEM (item)->name,
+ C_STRING_ALLOCA, tvitem.item.pszText,
+ Qnative);
+ }
+ else
+ TO_EXTERNAL_FORMAT (LISP_STRING, item,
+ C_STRING_ALLOCA, tvitem.item.pszText,
+ Qnative);
+
+ tvitem.item.cchTextMax = strlen (tvitem.item.pszText);
+
+ if ((ret = (HTREEITEM)SendMessage (wnd, TVM_INSERTITEM,
+ 0, (LPARAM)&tvitem)) == 0)
+ signal_simple_error ("error adding tree view entry", item);
+
+ return ret;
+}
+
+static void add_tree_item_list (Lisp_Object image_instance,
+ HWND wnd, HTREEITEM parent, Lisp_Object list,
+ Lisp_Object domain)
+{
+ Lisp_Object rest;
+
+ /* get the first item */
+ parent = add_tree_item (image_instance, wnd, parent, XCAR (list), TRUE, domain);
+ /* recursively add items to the tree view */
+ LIST_LOOP (rest, XCDR (list))
+ {
+ if (LISTP (XCAR (rest)))
+ add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
+ else
+ add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
+ }
+}
+
+static void
+mswindows_tree_view_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;
+ HWND wnd;
+ HTREEITEM parent;
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain, WC_TREEVIEW,
+ WS_TABSTOP | WS_BORDER | PBS_SMOOTH
+ | TVS_HASLINES | TVS_HASBUTTONS,
+ WS_EX_CLIENTEDGE);
+
+ wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+
+ /* define a root */
+ parent = add_tree_item (image_instance, wnd, NULL,
+ XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)),
+ TRUE, domain);
+
+ /* recursively add items to the tree view */
+ /* add items to the tab */
+ LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
+ {
+ if (LISTP (XCAR (rest)))
+ add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain);
+ else
+ add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE, domain);
+ }
+}
+
+/* Set the properties of a tree view. */
+static void
+mswindows_tree_view_redisplay (Lisp_Object image_instance)
+{
+ /* This function can GC if IN_REDISPLAY is false. */
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+ if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
+ {
+ HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+ Lisp_Object rest;
+ HTREEITEM parent;
+ /* Delete previous items. */
+ SendMessage (wnd, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
+ /* define a root */
+ parent = add_tree_item (image_instance, wnd, NULL,
+ XCAR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)),
+ TRUE, IMAGE_INSTANCE_DOMAIN (ii));
+
+ /* recursively add items to the tree view */
+ /* add items to the tab */
+ LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
+ {
+ if (LISTP (XCAR (rest)))
+ add_tree_item_list (image_instance, wnd, parent, XCAR (rest),
+ IMAGE_INSTANCE_DOMAIN (ii));
+ else
+ add_tree_item (image_instance, wnd, parent, XCAR (rest), FALSE,
+ IMAGE_INSTANCE_DOMAIN (ii));
+ }
+ }
+}
+
+/* instantiate a tab control */
+static int
+add_tab_item (Lisp_Object image_instance,
+ HWND wnd, Lisp_Object item,
+ Lisp_Object domain, int i)
+{
+ TC_ITEM tvitem;
+ int ret = 0;
+
+ tvitem.mask = TCIF_TEXT;
+
+ if (GUI_ITEMP (item))
+ {
+ tvitem.lParam = mswindows_register_gui_item (image_instance,
+ item, domain);
+ tvitem.mask |= TCIF_PARAM;
+ TO_EXTERNAL_FORMAT (LISP_STRING, XGUI_ITEM (item)->name,
+ C_STRING_ALLOCA, tvitem.pszText,
+ Qnative);
+ }
+ else
+ {
+ CHECK_STRING (item);
+ TO_EXTERNAL_FORMAT (LISP_STRING, item,
+ C_STRING_ALLOCA, tvitem.pszText,
+ Qnative);
+ }
+
+ tvitem.cchTextMax = strlen (tvitem.pszText);
+
+ if ((ret = SendMessage (wnd, TCM_INSERTITEM,
+ i, (LPARAM)&tvitem)) < 0)
+ signal_simple_error ("error adding tab entry", item);
+
+ return ret;
+}
+
+static void
+mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain)
+{
+ /* This function can call lisp */
+ Lisp_Object rest;
+ HWND wnd;
+ int i = 0, selected = 0;
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation);
+ unsigned int flags = WS_TABSTOP;
+
+ if (EQ (orient, Qleft) || EQ (orient, Qright))
+ {
+ flags |= TCS_VERTICAL | TCS_MULTILINE;
+ }
+ if (EQ (orient, Qright) || EQ (orient, Qbottom))
+ {
+ flags |= TCS_BOTTOM;
+ }
+
+ mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain, WC_TABCONTROL,
+ /* borders don't suit tabs so well */
+ flags, 0);
+ wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+ /* add items to the tab */
+ LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
+ {
+ int idx = add_tab_item (image_instance, wnd, XCAR (rest), domain, i);
+ assert (idx == i);
+ if (gui_item_selected_p (XCAR (rest)))
+ selected = i;
+ i++;
+ }
+ SendMessage (wnd, TCM_SETCURSEL, selected, 0);
+}
+
+/* Set the properties of a tab control. */
+static void
+mswindows_tab_control_redisplay (Lisp_Object image_instance)
+{
+ /* This function can GC if IN_REDISPLAY is false. */
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+#ifdef DEBUG_WIDGET_OUTPUT
+ stderr_out ("tab control %p redisplayed\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii));
+#endif
+ if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii)
+ ||
+ IMAGE_INSTANCE_WIDGET_ACTION_OCCURRED (ii))
+ {
+ HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+ int i = 0, selected_idx = 0;
+ Lisp_Object rest;
+
+ assert (!NILP (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
+
+ /* If only the order has changed then simply select the first
+ one. This stops horrendous rebuilding of the tabs each time
+ you click on one. */
+ if (tab_control_order_only_changed (image_instance))
+ {
+ Lisp_Object selected =
+ gui_item_list_find_selected
+ (NILP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)) ?
+ XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)) :
+ XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
+
+ LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)))
+ {
+ if (gui_item_equal_sans_selected (XCAR (rest), selected, 0))
+ {
+ Lisp_Object old_selected = gui_item_list_find_selected
+ (XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)));
+
+ /* Pick up the new selected item. */
+ XGUI_ITEM (old_selected)->selected =
+ XGUI_ITEM (XCAR (rest))->selected;
+ XGUI_ITEM (XCAR (rest))->selected =
+ XGUI_ITEM (selected)->selected;
+ /* We're not actually changing the items. */
+ IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii) = 0;
+ IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii) = Qnil;
+
+ SendMessage (wnd, TCM_SETCURSEL, i, 0);
+#ifdef DEBUG_WIDGET_OUTPUT
+ stderr_out ("tab control %p selected item %d\n",
+ IMAGE_INSTANCE_SUBWINDOW_ID (ii), i);
+#endif
+ break;
+ }
+ i++;
+ }
+ }
+ else
+ {
+ /* delete the pre-existing items */
+ SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0);
+
+ /* add items to the tab */
+ LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)))
+ {
+ add_tab_item (image_instance, wnd, XCAR (rest),
+ IMAGE_INSTANCE_FRAME (ii), i);
+ if (gui_item_selected_p (XCAR (rest)))
+ selected_idx = i;
+ i++;
+ }
+ SendMessage (wnd, TCM_SETCURSEL, selected_idx, 0);
+ }
+ }
+}
+
+/* instantiate a static control possible for putting other things in */
+static void
+mswindows_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain)
+{
+ mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain, "STATIC",
+ 0, WS_EX_STATICEDGE);
+}
+
+/* instantiate a scrollbar control */
+static void
+mswindows_scrollbar_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain)
+{
+ mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain, "SCROLLBAR",
+ WS_TABSTOP, WS_EX_CLIENTEDGE);
+}
+
+/* instantiate a combo control */
+static void
+mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain)
+{
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ HWND wnd;
+ Lisp_Object rest;
+ Lisp_Object items = find_keyword_in_vector (instantiator, Q_items);
+ int len, height;
+
+ /* Maybe ought to generalise this more but it may be very windows
+ specific. In windows the window height of a combo box is the
+ height when the combo box is open. Thus we need to set the height
+ before creating the window and then reset it to a single line
+ after the window is created so that redisplay does the right
+ thing. */
+ widget_instantiate (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain);
+
+ /* We now have everything right apart from the height. */
+ default_face_font_info (domain, 0, 0, &height, 0, 0);
+ GET_LIST_LENGTH (items, len);
+
+ height = (height + DEFAULT_WIDGET_BORDER_WIDTH * 2 ) * len;
+ IMAGE_INSTANCE_HEIGHT (ii) = height;
+
+ /* Now create the widget. */
+ mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain, "COMBOBOX",
+ WS_BORDER | WS_TABSTOP | CBS_DROPDOWN
+ | CBS_AUTOHSCROLL
+ | CBS_HASSTRINGS | WS_VSCROLL,
+ WS_EX_CLIENTEDGE);
+ /* Reset the height. layout will probably do this safely, but better make sure. */
+ image_instance_layout (image_instance,
+ IMAGE_UNSPECIFIED_GEOMETRY,
+ IMAGE_UNSPECIFIED_GEOMETRY,
+ IMAGE_UNCHANGED_GEOMETRY,
+ IMAGE_UNCHANGED_GEOMETRY,
+ domain);
+
+ wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+ /* add items to the combo box */
+ SendMessage (wnd, CB_RESETCONTENT, 0, 0);
+ LIST_LOOP (rest, items)
+ {
+ Extbyte* lparam;
+ TO_EXTERNAL_FORMAT (LISP_STRING, XCAR (rest),
+ C_STRING_ALLOCA, lparam,
+ Qnative);
+ if (SendMessage (wnd, CB_ADDSTRING, 0, (LPARAM)lparam) == CB_ERR)
+ signal_simple_error ("error adding combo entries", instantiator);
+ }
+}
+
+/* get properties of a control */
+static Lisp_Object
+mswindows_widget_property (Lisp_Object image_instance, Lisp_Object prop)
+{
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+ /* get the text from a control */
+ if (EQ (prop, Q_text))
+ {
+ Extcount len = SendMessage (wnd, WM_GETTEXTLENGTH, 0, 0);
+ Extbyte *buf = (Extbyte*) alloca (len+1);
+
+ SendMessage (wnd, WM_GETTEXT, (WPARAM)len+1, (LPARAM) buf);
+ return build_ext_string (buf, Qnative);
+ }
+ return Qunbound;
+}
+
+/* get properties of a button */
+static Lisp_Object
+mswindows_button_property (Lisp_Object image_instance, Lisp_Object prop)
+{
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+ /* check the state of a button */
+ if (EQ (prop, Q_selected))
+ {
+ if (SendMessage (wnd, BM_GETSTATE, 0, 0) & BST_CHECKED)
+ return Qt;
+ else
+ return Qnil;
+ }
+ return Qunbound;
+}
+
+/* get properties of a combo box */
+static Lisp_Object
+mswindows_combo_box_property (Lisp_Object image_instance, Lisp_Object prop)
+{
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ HWND wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+ /* get the text from a control */
+ if (EQ (prop, Q_text))
+ {
+ long item = SendMessage (wnd, CB_GETCURSEL, 0, 0);
+ Extcount len = SendMessage (wnd, CB_GETLBTEXTLEN, (WPARAM)item, 0);
+ Extbyte* buf = (Extbyte*) alloca (len+1);
+ SendMessage (wnd, CB_GETLBTEXT, (WPARAM)item, (LPARAM)buf);
+ return build_ext_string (buf, Qnative);
+ }
+ return Qunbound;
+}
+
+/* set the properties of a progress gauge */
+static void
+mswindows_progress_gauge_redisplay (Lisp_Object image_instance)
+{
+ Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+
+ if (IMAGE_INSTANCE_WIDGET_ITEMS_CHANGED (ii))
+ {
+ Lisp_Object val;
+#ifdef ERROR_CHECK_GLYPHS
+ assert (GUI_ITEMP (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii)));
+#endif
+ val = XGUI_ITEM (IMAGE_INSTANCE_WIDGET_PENDING_ITEMS (ii))->value;
+#ifdef DEBUG_WIDGET_OUTPUT
+ stderr_out ("progress gauge displayed value on %p updated to %ld\n",
+ WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
+ XINT(val));
+#endif
+ CHECK_INT (val);
+ SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii),
+ PBM_SETPOS, (WPARAM)XINT (val), 0);
+ }
+}
+
+LRESULT WINAPI
+mswindows_control_wnd_proc (HWND hwnd, UINT msg,
+ WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_NOTIFY:
+ case WM_COMMAND:
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORSTATIC:
+ case WM_CTLCOLORSCROLLBAR:
+
+ return mswindows_wnd_proc (GetParent (hwnd), msg, wParam, lParam);
+ default:
+ return DefWindowProc (hwnd, msg, wParam, lParam);
+ }
+}
+
+#endif /* HAVE_WIDGETS */
+
+\f