As always, only ms-windows. I will apply this to cvs.
andy
1999-06-13 Andy Piper <andy(a)xemacs.org>
* menubar.h: update declarations involving gui_items.
* lisp.h: declare Lisp_Gui_Item.
* glyphs.h (struct Lisp_Image_Instance): update type of gui_item.
* glyphs.c (mark_image_instance): modify for new lisp-based gui_items.
(print_image_instance): ditto.
(image_instance_equal): ditto.
(image_instance_hash): ditto.
* event-msw.c (mswindows_need_event): assert badly_p status.
(mswindows_wnd_proc): modify WM_NOTIFY handling to cope with
callbacks in tree-view and tab-control widgets.
(emacs_mswindows_next_event): modify use of
mswindows_dequeue_dispatch_event.
* dialog-msw.c (mswindows_popup_dialog_box): modify for new
lisp-based gui_items.
* glyphs-msw.c (mswindows_update_subwindow): update use of
gui_items.
(mswindows_register_gui_item): new function.
(mswindows_register_gui_item): fix to use lisp gui_items.
(mswindows_widget_instantiate): ditto.
(mswindows_button_instantiate): ditto.
(add_tree_item): new function to recursively add tree view
elements.
(add_tree_item_list): ditto.
(mswindows_tree_instantiate): new function. instantiate tree view
controls.
(add_tab_item): new function to add tabs to a tab control.
(mswindows_tab_instantiate): new function. instantiate tab
controls.
(image_instantiator_format_create_glyphs_mswindows): add tree view
and tab controls.
(vars_of_glyphs_mswindows): ditto.
* glyphs-widget.c (check_valid_item_list_1): allow nested lists in
item lists.
(check_valid_item_list): ditto.
(initialize_widget_image_instance): fix to use new lisp gui_item.
(widget_instantiate_1): allow the setting of default textwidth in
characters.
(widget_instantiate): change to use new widget_instantiate_1
signature.
(combo_instantiate): ditto.
(static_instantiate): ditto.
(tab_instantiate): new function for tab widgets.
(image_instantiator_format_create_glyphs_widget): add tab and tree
view widgets.
* menubar-msw.c (displayable_menu_item): convert to use lisp
gui_items.
(populate_menu_add_item): ditto.
(populate_or_checksum_helper): ditto.
* menubar.c (menu_parse_submenu_keywords): convert to use lisp
gui_items.
(Fmenu_find_real_submenu): ditto.
* gui.h (struct Lisp_Gui_Item): make gui_item a lisp oebjct.
* gui.c (gui_item_add_keyval_pair): gui_items are now lisp
objects, convert functions that use them accordingly.
(gui_item_init): ditto.
(gui_item_active_p): ditto.
(gui_item_selected_p): ditto.
(gui_item_included_p): ditto.
(gui_item_display_flush_left): ditto.
(gui_item_display_flush_right): ditto.
(mark_gui_item): ditto.
(allocate_gui_item): new function to create a gui_item.
(make_gui_item_from_keywords_internal): ditto. create and return a
gui_item as well as setting keywords.
(gui_parse_item_keywords): ditto.
(gui_parse_item_keywords_no_errors): ditto.
(gui_add_item_keywords_to_plist): new function, not yet used.
(gui_item_hash): new function.
(gui_item_id_hash): use gui_item_hash.
(gui_item_equal): new function.
(print_gui_item): new function.
Index: etc/NEWS
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/etc/NEWS,v
retrieving revision 1.58.2.14
diff -u -r1.58.2.14 NEWS
--- etc/NEWS 1999/05/17 01:47:10 1.58.2.14
+++ etc/NEWS 1999/06/13 19:49:49
@@ -88,6 +88,22 @@
The new primitives available for this purpose are functions named
`user-name-completion' and `user-name-all-completions'.
+** Native widgets can be displayed in buffers.
+
+The glyph system has been extended to allow the display of glyphs that
+are implemented as native window-system widgets. Thus you can embed
+buttons, scrollbars, combo boxes, edit fields and progress gauges in a
+buffer. As a side effect subwindow support now works once again.
+
+This support is currently only available under MS-Windows.
+
+** X-Face support is now available under MS-Windows
+
+If an X-Face libary built under MS-Windows is available then XEmacs
+will use this at build time.
+
+** The font-menu is now available under MS-Windows
+
* Lisp and internal changes in XEmacs 21.2
==========================================
Index: src/dialog-msw.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/dialog-msw.c,v
retrieving revision 1.5.2.1
diff -u -r1.5.2.1 dialog-msw.c
--- src/dialog-msw.c 1998/12/05 16:55:31 1.5.2.1
+++ src/dialog-msw.c 1999/06/13 19:49:56
@@ -110,12 +110,6 @@
#define ID_ITEM_BIAS 32
-typedef struct gui_item struct_gui_item;
-typedef struct
-{
- Dynarr_declare (struct gui_item);
-} struct_gui_item_dynarr;
-
/* Dialog procedure */
static BOOL CALLBACK
dialog_proc (HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
@@ -200,7 +194,7 @@
static void
mswindows_popup_dialog_box (struct frame* f, Lisp_Object desc)
{
- struct_gui_item_dynarr *dialog_items = Dynarr_new (struct_gui_item);
+ Lisp_Object_dynarr *dialog_items = Dynarr_new (Lisp_Object);
unsigned_char_dynarr *template = Dynarr_new (unsigned_char);
unsigned int button_row_width = 0;
unsigned int text_width, text_height;
@@ -223,11 +217,10 @@
{
if (!NILP (XCAR (item_cons)))
{
- struct gui_item gitem;
- gui_item_init (&gitem);
- gui_parse_item_keywords (XCAR (item_cons), &gitem);
+ Lisp_Object gitem = gui_parse_item_keywords (XCAR (item_cons));
Dynarr_add (dialog_items, gitem);
- button_row_width += button_width (gitem.name) + X_BUTTON_MARGIN;
+ button_row_width += button_width (XGUI_ITEM (gitem)->name)
+ + X_BUTTON_MARGIN;
}
}
if (Dynarr_length (dialog_items) == 0)
@@ -350,10 +343,11 @@
for (i = 0; i < Dynarr_length (dialog_items); ++i)
{
- struct gui_item *pgui_item = Dynarr_atp (dialog_items, i);
+ Lisp_Object* gui_item = Dynarr_atp (dialog_items, i);
+ struct Lisp_Gui_Item *pgui_item = XGUI_ITEM (*gui_item);
item_tem.style = (WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON
- | (gui_item_active_p (pgui_item) ? 0 : WS_DISABLED));
+ | (gui_item_active_p (*gui_item) ? 0 : WS_DISABLED));
item_tem.cx = button_width (pgui_item->name);
/* Item ids are indices into dialog_items plus offset, to avoid having
items by reserved ids (IDOK, IDCANCEL) */
@@ -390,7 +384,7 @@
vector = make_vector (Dynarr_length (dialog_items), Qunbound);
dialog_data = Fcons (frame, vector);
for (i = 0; i < Dynarr_length (dialog_items); i++)
- XVECTOR_DATA (vector) [i] = Dynarr_atp (dialog_items, i)->callback;
+ XVECTOR_DATA (vector) [i] = XGUI_ITEM (*Dynarr_atp (dialog_items, i))->callback;
/* Woof! Everything is ready. Pop pop pop in now! */
if (!CreateDialogIndirectParam (NULL,
Index: src/event-msw.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/event-msw.c,v
retrieving revision 1.38.2.10
diff -u -r1.38.2.10 event-msw.c
--- src/event-msw.c 1999/02/17 20:03:58 1.38.2.10
+++ src/event-msw.c 1999/06/13 19:50:05
@@ -1327,6 +1327,7 @@
if (active == 0)
{
+ assert (!badly_p);
return; /* timeout */
}
else if (active > 0)
@@ -1925,17 +1926,21 @@
Qcancel_mode_internal, Qnil);
break;
-#ifdef HAVE_TOOLBARS
case WM_NOTIFY:
{
- LPTOOLTIPTEXT tttext = (LPTOOLTIPTEXT)lParam;
- Lisp_Object btext;
- if (tttext->hdr.code == TTN_NEEDTEXT)
+ LPNMHDR nmhdr = (LPNMHDR)lParam;
+ int idCtrl = (int)wParam;
+
+ if (nmhdr->code == TTN_NEEDTEXT)
{
+#ifdef HAVE_TOOLBARS
+ LPTOOLTIPTEXT tttext = (LPTOOLTIPTEXT)lParam;
+ Lisp_Object btext;
+
/* find out which toolbar */
frame = XFRAME (mswindows_find_frame (hwnd));
btext = mswindows_get_toolbar_button_text ( frame,
- tttext->hdr.idFrom );
+ nmhdr->idFrom );
tttext->lpszText = NULL;
tttext->hinst = NULL;
@@ -1947,13 +1952,28 @@
GET_C_STRING_EXT_DATA_ALLOCA (btext, FORMAT_OS,
tttext->lpszText);
}
-#if 0
- tttext->uFlags |= TTF_DI_SETITEM;
#endif
- }
+ }
+ /* handle tree view callbacks */
+ else if (nmhdr->code == TVN_SELCHANGED)
+ {
+ NM_TREEVIEW* ptree = (NM_TREEVIEW*)lParam;
+ frame = XFRAME (mswindows_find_frame (hwnd));
+ mswindows_handle_gui_wm_command (frame, 0, ptree->itemNew.lParam);
+ }
+ /* handle tab control callbacks */
+ else if (nmhdr->code == TCN_SELCHANGE)
+ {
+ TC_ITEM item;
+ int index = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0);
+ frame = XFRAME (mswindows_find_frame (hwnd));
+ SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)index,
+ (LPARAM)&item);
+
+ mswindows_handle_gui_wm_command (frame, 0, item.lParam);
+ }
}
break;
-#endif
case WM_PAINT:
{
@@ -2552,7 +2572,7 @@
mswindows_need_event (1);
- event = mswindows_dequeue_dispatch_event (!NILP(mswindows_u_dispatch_event_queue));
+ event = mswindows_dequeue_dispatch_event ();
XSETEVENT (event2, emacs_event);
Fcopy_event (event, event2);
Fdeallocate_event (event);
Index: src/glyphs-msw.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs-msw.c,v
retrieving revision 1.21.2.14
diff -u -r1.21.2.14 glyphs-msw.c
--- src/glyphs-msw.c 1999/04/22 01:22:36 1.21.2.14
+++ src/glyphs-msw.c 1999/06/13 19:50:14
@@ -71,6 +71,8 @@
DEFINE_DEVICE_IIFORMAT (mswindows, scrollbar);
DEFINE_DEVICE_IIFORMAT (mswindows, combo);
DEFINE_DEVICE_IIFORMAT (mswindows, progress);
+DEFINE_DEVICE_IIFORMAT (mswindows, tree);
+DEFINE_DEVICE_IIFORMAT (mswindows, tab);
DEFINE_IMAGE_INSTANTIATOR_FORMAT (bmp);
Lisp_Object Qbmp;
@@ -282,7 +284,7 @@
struct device *d = XDEVICE (device);
struct frame *f;
void* bmp_buf=0;
- int type;
+ int type = 0;
HBITMAP bitmap;
HDC hdc;
@@ -2041,7 +2043,7 @@
/* buttons checked or otherwise */
if ( EQ (IMAGE_INSTANCE_WIDGET_TYPE (p), Qbutton))
{
- if (gui_item_selected_p (&IMAGE_INSTANCE_WIDGET_ITEM (p)))
+ if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_SINGLE_ITEM (p)))
SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p),
BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
else
@@ -2055,19 +2057,26 @@
callbacks. The hashtable is weak so deregistration is handled
automatically */
static int
-mswindows_register_widget_instance (Lisp_Object instance, Lisp_Object domain)
+mswindows_register_gui_item (Lisp_Object gui, Lisp_Object domain)
{
Lisp_Object frame = FW_FRAME (domain);
struct frame* f = XFRAME (frame);
- int id = gui_item_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f),
- &XIMAGE_INSTANCE_WIDGET_ITEM (instance),
- WIDGET_GLYPH_SLOT);
+ int id = gui_item_id_hash (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f),
+ gui,
+ WIDGET_GLYPH_SLOT);
Fputhash (make_int (id),
- XIMAGE_INSTANCE_WIDGET_CALLBACK (instance),
+ XGUI_ITEM (gui)->callback,
FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f));
return id;
}
+static int
+mswindows_register_widget_instance (Lisp_Object instance, Lisp_Object domain)
+{
+ return mswindows_register_gui_item (XIMAGE_INSTANCE_WIDGET_SINGLE_ITEM (instance),
+ domain);
+}
+
static void
mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
Lisp_Object pointer_fg, Lisp_Object pointer_bg,
@@ -2164,7 +2173,6 @@
/************************************************************************/
/* widgets */
/************************************************************************/
-
static void
mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
Lisp_Object pointer_fg, Lisp_Object pointer_bg,
@@ -2182,7 +2190,8 @@
Extbyte* nm=0;
HWND wnd;
int id = 0xffff;
- struct gui_item* pgui = &IMAGE_INSTANCE_WIDGET_ITEM (ii);
+ Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
+ struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
if (!DEVICE_MSWINDOWS_P (d))
signal_simple_error ("Not an mswindows device", device);
@@ -2197,7 +2206,7 @@
groupii = XIMAGE_INSTANCE (group);
}
#endif
- if (!gui_item_active_p (pgui))
+ if (!gui_item_active_p (gui))
flags |= WS_DISABLED;
style = pgui->style;
@@ -2256,10 +2265,11 @@
HWND wnd;
int flags = BS_NOTIFY;
Lisp_Object style;
- struct gui_item* pgui = &IMAGE_INSTANCE_WIDGET_ITEM (ii);
+ Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii);
+ struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui);
Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image);
- if (!gui_item_active_p (pgui))
+ if (!gui_item_active_p (gui))
flags |= WS_DISABLED;
if (!NILP (glyph))
@@ -2291,7 +2301,7 @@
wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
/* set the checked state */
- if (gui_item_selected_p (pgui))
+ if (gui_item_selected_p (gui))
SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
else
SendMessage (wnd, BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0);
@@ -2320,7 +2330,7 @@
WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT);
}
-/* instantiate an edit control */
+/* instantiate a progress gauge */
static void
mswindows_progress_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
Lisp_Object pointer_fg, Lisp_Object pointer_bg,
@@ -2352,6 +2362,178 @@
#endif
}
+/* instantiate a tree view widget */
+static HTREEITEM add_tree_item (Lisp_Object image_instance,
+ HWND wnd, HTREEITEM parent, Lisp_Object entry,
+ 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 (VECTORP (entry))
+ {
+ /* we always maintain the real gui item at the head of the
+ list. We have to put them in the list in the first place
+ because the whole model assumes that the glyph instances have
+ references to all the associated data. If we didn't do this
+ GC would bite us badly. */
+ Lisp_Object gui = gui_parse_item_keywords_no_errors (entry);
+ if (CONSP (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance)))
+ {
+ Lisp_Object rest =
+ Fcons (gui, XCDR (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance)));
+ Fsetcdr (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), rest);
+ }
+ else
+ {
+ XIMAGE_INSTANCE_WIDGET_ITEM (image_instance) =
+ Fcons (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), gui);
+ }
+
+ tvitem.item.lParam = mswindows_register_gui_item (gui, domain);
+ tvitem.item.mask |= TVIF_PARAM;
+ GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (gui)->name,
+ tvitem.item.pszText);
+ }
+ else
+ GET_C_STRING_OS_DATA_ALLOCA (entry, tvitem.item.pszText);
+
+ 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", entry);
+
+ 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_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;
+ struct 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 | WS_EX_CONTROLPARENT);
+
+ wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+
+ /* define a root */
+ parent = add_tree_item (image_instance,
+ wnd, NULL, IMAGE_INSTANCE_WIDGET_TEXT (ii), TRUE,
+ domain);
+
+ /* recursively add items to the tree view */
+ LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil))
+ {
+ 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);
+ }
+}
+
+/* instantiate a tab control */
+static TC_ITEM* add_tab_item (Lisp_Object image_instance,
+ HWND wnd, Lisp_Object entry,
+ Lisp_Object domain, int index)
+{
+ TC_ITEM tvitem, *ret;
+
+ tvitem.mask = TCIF_TEXT;
+
+ if (VECTORP (entry))
+ {
+ /* we always maintain the real gui item at the head of the
+ list. We have to put them in the list in the first place
+ because the whole model assumes that the glyph instances have
+ references to all the associated data. If we didn't do this
+ GC would bite us badly. */
+ Lisp_Object gui = gui_parse_item_keywords_no_errors (entry);
+ if (CONSP (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance)))
+ {
+ Lisp_Object rest =
+ Fcons (gui, XCDR (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance)));
+ Fsetcdr (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), rest);
+ }
+ else
+ {
+ XIMAGE_INSTANCE_WIDGET_ITEM (image_instance) =
+ Fcons (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), gui);
+ }
+
+ tvitem.lParam = mswindows_register_gui_item (gui, domain);
+ tvitem.mask |= TCIF_PARAM;
+ GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (gui)->name,
+ tvitem.pszText);
+ }
+ else
+ GET_C_STRING_OS_DATA_ALLOCA (entry, tvitem.pszText);
+
+ tvitem.cchTextMax = strlen (tvitem.pszText);
+
+ if ((ret = (TC_ITEM*)SendMessage (wnd, TCM_INSERTITEM,
+ index, (LPARAM)&tvitem)) < 0)
+ signal_simple_error ("error adding tab entry", entry);
+
+ return ret;
+}
+
+static void
+mswindows_tab_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;
+ int index = 0;
+ struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
+ mswindows_widget_instantiate (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain, WC_TABCONTROL,
+ /* borders don't suit tabs so well */
+ WS_TABSTOP,
+ WS_EX_CONTROLPARENT);
+
+ wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii);
+
+ /* add items to the tab */
+ LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil))
+ {
+ add_tab_item (image_instance, wnd, XCAR (rest), domain, index);
+ index++;
+ }
+}
+
/* instantiate a static control possible for putting other things in */
static void
mswindows_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
@@ -2558,6 +2740,7 @@
INITIALIZE_DEVICE_IIFORMAT (mswindows, xface);
IIFORMAT_HAS_DEVMETHOD (mswindows, xface, instantiate);
#endif
+ /* button widget */
INITIALIZE_DEVICE_IIFORMAT (mswindows, button);
IIFORMAT_HAS_DEVMETHOD (mswindows, button, property);
IIFORMAT_HAS_DEVMETHOD (mswindows, button, instantiate);
@@ -2575,22 +2758,35 @@
INITIALIZE_DEVICE_IIFORMAT (mswindows, group);
IIFORMAT_HAS_DEVMETHOD (mswindows, group, instantiate);
#endif
+ /* label */
INITIALIZE_DEVICE_IIFORMAT (mswindows, label);
IIFORMAT_HAS_DEVMETHOD (mswindows, label, instantiate);
+ /* combo box */
INITIALIZE_DEVICE_IIFORMAT (mswindows, combo);
IIFORMAT_HAS_DEVMETHOD (mswindows, combo, property);
IIFORMAT_HAS_DEVMETHOD (mswindows, combo, instantiate);
+ /* scrollbar */
INITIALIZE_DEVICE_IIFORMAT (mswindows, scrollbar);
IIFORMAT_HAS_DEVMETHOD (mswindows, scrollbar, instantiate);
+ /* progress gauge */
INITIALIZE_DEVICE_IIFORMAT (mswindows, progress);
IIFORMAT_HAS_DEVMETHOD (mswindows, progress, set_property);
IIFORMAT_HAS_DEVMETHOD (mswindows, progress, instantiate);
- INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp");
+ /* tree view widget */
+ INITIALIZE_DEVICE_IIFORMAT (mswindows, tree);
+ /* IIFORMAT_HAS_DEVMETHOD (mswindows, progress, set_property);*/
+ IIFORMAT_HAS_DEVMETHOD (mswindows, tree, instantiate);
+
+ /* tab control widget */
+ INITIALIZE_DEVICE_IIFORMAT (mswindows, tab);
+ IIFORMAT_HAS_DEVMETHOD (mswindows, tab, instantiate);
+ /* windows bitmap format */
+ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp");
IIFORMAT_HAS_METHOD (bmp, validate);
IIFORMAT_HAS_METHOD (bmp, normalize);
IIFORMAT_HAS_METHOD (bmp, possible_dest_types);
@@ -2599,6 +2795,7 @@
IIFORMAT_VALID_KEYWORD (bmp, Q_data, check_valid_string);
IIFORMAT_VALID_KEYWORD (bmp, Q_file, check_valid_string);
+ /* mswindows resources */
INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (mswindows_resource,
"mswindows-resource");
@@ -2630,6 +2827,8 @@
Fprovide (Qscrollbar);
Fprovide (Qlabel);
Fprovide (Qprogress);
+ Fprovide (Qtree);
+ Fprovide (Qtab);
}
void
Index: src/glyphs-widget.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/Attic/glyphs-widget.c,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 glyphs-widget.c
--- src/glyphs-widget.c 1999/01/05 19:51:21 1.1.2.4
+++ src/glyphs-widget.c 1999/06/13 19:50:14
@@ -53,6 +53,10 @@
Lisp_Object Qlabel;
DEFINE_IMAGE_INSTANTIATOR_FORMAT (progress);
Lisp_Object Qprogress;
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (tree);
+Lisp_Object Qtree;
+DEFINE_IMAGE_INSTANTIATOR_FORMAT (tab);
+Lisp_Object Qtab;
Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items;
Lisp_Object Q_image, Q_text, Q_percent;
@@ -146,21 +150,35 @@
}
static void
-check_valid_item_list (Lisp_Object data)
+check_valid_item_list_1 (Lisp_Object items)
{
Lisp_Object rest;
- Lisp_Object items;
- Fcheck_valid_plist (data);
-
- items = Fplist_get (data, Q_items, Qnil);
CHECK_LIST (items);
EXTERNAL_LIST_LOOP (rest, items)
{
- CHECK_STRING (XCAR (rest));
+ if (STRINGP (XCAR (rest)))
+ CHECK_STRING (XCAR (rest));
+ else if (VECTORP (XCAR (rest)))
+ gui_parse_item_keywords (XCAR (rest));
+ else if (LISTP (XCAR (rest)))
+ check_valid_item_list_1 (XCAR (rest));
+ else
+ signal_simple_error ("Items must be vectors, lists or strings", items);
}
}
+static void
+check_valid_item_list (Lisp_Object data)
+{
+ Lisp_Object items;
+
+ Fcheck_valid_plist (data);
+ items = Fplist_get (data, Q_items, Qnil);
+
+ check_valid_item_list_1 (items);
+}
+
/* wire widget property invocations to specific widgets ... The
problem we are solving here is that when instantiators get converted
to instances they lose some type information (they just become
@@ -235,15 +253,15 @@
widget_validate (Lisp_Object instantiator)
{
Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor);
- struct gui_item gui;
+
if (NILP (desc))
signal_simple_error ("Must supply :descriptor", instantiator);
if (VECTORP (desc))
- gui_parse_item_keywords (desc, &gui);
+ gui_parse_item_keywords (desc);
if (!NILP (find_keyword_in_vector (instantiator, Q_width))
- && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
+ && !NILP (find_keyword_in_vector (instantiator, Q_pixel_width)))
signal_simple_error ("Must supply only one of :width and :pixel-width", instantiator);
if (!NILP (find_keyword_in_vector (instantiator, Q_height))
@@ -300,23 +318,22 @@
IMAGE_INSTANCE_WIDGET_TYPE (ii) = type;
IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil;
IMAGE_INSTANCE_WIDGET_FACE (ii) = Vwidget_face;
- gui_item_init (&IMAGE_INSTANCE_WIDGET_ITEM (ii));
+ IMAGE_INSTANCE_WIDGET_ITEM (ii) = allocate_gui_item ();
}
/* 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 images instances can have a
+ 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
widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator,
Lisp_Object pointer_fg, Lisp_Object pointer_bg,
int dest_mask, Lisp_Object domain, int default_textheight,
- int default_pixheight)
+ int default_pixheight, int default_textwidth)
{
struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance);
- struct gui_item* pgui = &IMAGE_INSTANCE_WIDGET_ITEM (ii);
Lisp_Object face = find_keyword_in_vector (instantiator, Q_face);
Lisp_Object height = find_keyword_in_vector (instantiator, Q_height);
Lisp_Object width = find_keyword_in_vector (instantiator, Q_width);
@@ -349,11 +366,13 @@
if (STRINGP (desc) || NILP (desc))
{
/* big cheat - we rely on the fact that a gui item looks like an instantiator */
- gui_parse_item_keywords_no_errors (instantiator, pgui);
+ IMAGE_INSTANCE_WIDGET_ITEM (ii) =
+ gui_parse_item_keywords_no_errors (instantiator);
IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc;
}
else
- gui_parse_item_keywords_no_errors (desc, pgui);
+ IMAGE_INSTANCE_WIDGET_ITEM (ii) =
+ gui_parse_item_keywords_no_errors (desc);
/* normalize size information */
if (!NILP (width))
@@ -377,8 +396,14 @@
}
/* if we still don' t have sizes, guess from text size */
- if (!tw && !pw && !NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
- tw = XSTRING_LENGTH (IMAGE_INSTANCE_WIDGET_TEXT (ii));
+ if (!tw && !pw)
+ {
+ if (default_textwidth)
+ tw = default_textwidth;
+ else if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii)))
+ tw = XSTRING_LENGTH (IMAGE_INSTANCE_WIDGET_TEXT (ii));
+ }
+
if (!th && !ph)
{
if (default_textheight)
@@ -404,9 +429,10 @@
int dest_mask, Lisp_Object domain)
{
widget_instantiate_1 (image_instance, instantiator, pointer_fg,
- pointer_bg, dest_mask, domain, 1, 0);
+ pointer_bg, dest_mask, domain, 1, 0, 0);
}
+/* combo-box generic instantiation - get he heigh right */
static void
combo_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
Lisp_Object pointer_fg, Lisp_Object pointer_bg,
@@ -416,8 +442,34 @@
Q_items, Qnil);
int len;
GET_LIST_LENGTH (data, len);
+ widget_instantiate_1 (image_instance, instantiator, pointer_fg,
+ pointer_bg, dest_mask, domain, len + 1, 0, 0);
+}
+
+static void
+tab_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
+ Lisp_Object pointer_fg, Lisp_Object pointer_bg,
+ int dest_mask, Lisp_Object domain)
+{
+ Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties),
+ Q_items, Qnil);
+ Lisp_Object rest;
+ int len = 0;
+
+ LIST_LOOP (rest, data)
+ {
+ len += 3; /* some bias */
+ if (STRINGP (XCAR (rest)))
+ len += XSTRING_LENGTH (XCAR (rest));
+ else if (VECTORP (XCAR (rest)))
+ {
+ Lisp_Object gui = gui_parse_item_keywords (XCAR (rest));
+ len += XSTRING_LENGTH (XGUI_ITEM (gui)->name);
+ }
+ }
+
widget_instantiate_1 (image_instance, instantiator, pointer_fg,
- pointer_bg, dest_mask, domain, len + 1, 0);
+ pointer_bg, dest_mask, domain, 0, 0, len);
}
/* Instantiate a static control */
@@ -427,7 +479,7 @@
int dest_mask, Lisp_Object domain)
{
widget_instantiate_1 (image_instance, instantiator, pointer_fg,
- pointer_bg, dest_mask, domain, 0, 4);
+ pointer_bg, dest_mask, domain, 0, 4, 0);
}
@@ -445,7 +497,7 @@
defkeyword (&Q_items, ":items");
defkeyword (&Q_image, ":image");
defkeyword (&Q_percent, ":percent");
- defkeyword (&Q_text, "text");
+ defkeyword (&Q_text, ":text");
}
void
@@ -524,9 +576,27 @@
INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress, "progress");
IIFORMAT_HAS_SHARED_METHOD (progress, validate, widget);
IIFORMAT_HAS_SHARED_METHOD (progress, possible_dest_types, widget);
- IIFORMAT_HAS_SHARED_METHOD (progress, instantiate, widget);
+ IIFORMAT_HAS_SHARED_METHOD (progress, instantiate, combo);
VALID_WIDGET_KEYWORDS (progress);
VALID_GUI_KEYWORDS (progress);
+
+ /* tree view */
+ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree, "tree");
+ IIFORMAT_HAS_SHARED_METHOD (tree, validate, combo);
+ IIFORMAT_HAS_SHARED_METHOD (tree, possible_dest_types, widget);
+ IIFORMAT_HAS_SHARED_METHOD (tree, instantiate, combo);
+ VALID_WIDGET_KEYWORDS (tree);
+ VALID_GUI_KEYWORDS (tree);
+ IIFORMAT_VALID_KEYWORD (tree, Q_properties, check_valid_item_list);
+
+ /* tab control */
+ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tab, "tab");
+ IIFORMAT_HAS_SHARED_METHOD (tab, validate, combo);
+ IIFORMAT_HAS_SHARED_METHOD (tab, possible_dest_types, widget);
+ IIFORMAT_HAS_METHOD (tab, instantiate);
+ VALID_WIDGET_KEYWORDS (tab);
+ VALID_GUI_KEYWORDS (tab);
+ IIFORMAT_VALID_KEYWORD (tab, Q_properties, check_valid_item_list);
/* labels */
INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (label, "label");
Index: src/glyphs.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.c,v
retrieving revision 1.23.2.11
diff -u -r1.23.2.11 glyphs.c
--- src/glyphs.c 1999/04/22 07:27:22 1.23.2.11
+++ src/glyphs.c 1999/06/13 19:50:24
@@ -600,7 +600,7 @@
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);
+ markobj (IMAGE_INSTANCE_WIDGET_ITEM (i));
case IMAGE_SUBWINDOW:
markobj (IMAGE_INSTANCE_SUBWINDOW_FRAME (i));
break;
@@ -707,11 +707,13 @@
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);
@@ -834,15 +836,14 @@
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))
+ IMAGE_INSTANCE_WIDGET_TYPE (i2))
+ && internal_equal (IMAGE_INSTANCE_WIDGET_ITEM (i1),
+ IMAGE_INSTANCE_WIDGET_ITEM (i2),
+ depth + 1)
&& 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:
if (!(IMAGE_INSTANCE_SUBWINDOW_WIDTH (i1) ==
@@ -892,7 +893,7 @@
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));
+ internal_hash (IMAGE_INSTANCE_WIDGET_ITEM (i), depth + 1));
case IMAGE_SUBWINDOW:
hash = HASH4 (hash, IMAGE_INSTANCE_SUBWINDOW_WIDTH (i),
IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i),
Index: src/glyphs.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/glyphs.h,v
retrieving revision 1.18.2.10
diff -u -r1.18.2.10 glyphs.h
--- src/glyphs.h 1999/03/07 13:37:01 1.18.2.10
+++ src/glyphs.h 1999/06/13 19:50:27
@@ -432,7 +432,7 @@
Lisp_Object face; /* foreground and background colors */
Lisp_Object type;
Lisp_Object props; /* properties */
- struct gui_item gui_item;
+ Lisp_Object gui_item; /* a list of gui_items */
} widget; /* widgets are subwindows */
} subwindow;
} u;
@@ -472,13 +472,15 @@
IMAGE_INSTANCE_SUBWINDOW_WIDTH(i)
#define IMAGE_INSTANCE_WIDGET_HEIGHT(i) \
IMAGE_INSTANCE_SUBWINDOW_HEIGHT(i)
-#define IMAGE_INSTANCE_WIDGET_CALLBACK(i) \
- ((i)->u.subwindow.widget.gui_item.callback)
#define IMAGE_INSTANCE_WIDGET_TYPE(i) ((i)->u.subwindow.widget.type)
#define IMAGE_INSTANCE_WIDGET_PROPS(i) ((i)->u.subwindow.widget.props)
#define IMAGE_INSTANCE_WIDGET_FACE(i) ((i)->u.subwindow.widget.face)
-#define IMAGE_INSTANCE_WIDGET_TEXT(i) ((i)->u.subwindow.widget.gui_item.name)
#define IMAGE_INSTANCE_WIDGET_ITEM(i) ((i)->u.subwindow.widget.gui_item)
+#define IMAGE_INSTANCE_WIDGET_SINGLE_ITEM(i) \
+(CONSP (IMAGE_INSTANCE_WIDGET_ITEM (i)) ? \
+XCAR (IMAGE_INSTANCE_WIDGET_ITEM (i)) : \
+ IMAGE_INSTANCE_WIDGET_ITEM (i))
+#define IMAGE_INSTANCE_WIDGET_TEXT(i) XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (i))->name
#define XIMAGE_INSTANCE_DEVICE(i) \
IMAGE_INSTANCE_DEVICE (XIMAGE_INSTANCE (i))
@@ -513,18 +515,18 @@
IMAGE_INSTANCE_WIDGET_WIDTH (XIMAGE_INSTANCE (i))
#define XIMAGE_INSTANCE_WIDGET_HEIGHT(i) \
IMAGE_INSTANCE_WIDGET_HEIGHT (XIMAGE_INSTANCE (i))
-#define XIMAGE_INSTANCE_WIDGET_CALLBACK(i) \
- IMAGE_INSTANCE_WIDGET_CALLBACK (XIMAGE_INSTANCE (i))
#define XIMAGE_INSTANCE_WIDGET_TYPE(i) \
IMAGE_INSTANCE_WIDGET_TYPE (XIMAGE_INSTANCE (i))
#define XIMAGE_INSTANCE_WIDGET_PROPS(i) \
IMAGE_INSTANCE_WIDGET_PROPS (XIMAGE_INSTANCE (i))
#define XIMAGE_INSTANCE_WIDGET_FACE(i) \
IMAGE_INSTANCE_WIDGET_FACE (XIMAGE_INSTANCE (i))
-#define XIMAGE_INSTANCE_WIDGET_TEXT(i) \
- IMAGE_INSTANCE_WIDGET_TEXT (XIMAGE_INSTANCE (i))
#define XIMAGE_INSTANCE_WIDGET_ITEM(i) \
IMAGE_INSTANCE_WIDGET_ITEM (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_WIDGET_SINGLE_ITEM(i) \
+ IMAGE_INSTANCE_WIDGET_SINGLE_ITEM (XIMAGE_INSTANCE (i))
+#define XIMAGE_INSTANCE_WIDGET_TEXT(i) \
+ IMAGE_INSTANCE_WIDGET_TEXT (XIMAGE_INSTANCE (i))
#define XIMAGE_INSTANCE_SUBWINDOW_WIDTH(i) \
IMAGE_INSTANCE_SUBWINDOW_WIDTH (XIMAGE_INSTANCE (i))
@@ -623,6 +625,7 @@
extern Lisp_Object Qxpm, Qxface;
extern Lisp_Object Q_data, Q_file, Q_color_symbols, Qconst_glyph_variable;
extern Lisp_Object Qxbm, Qedit, Qgroup, Qlabel, Qcombo, Qscrollbar, Qprogress;
+extern Lisp_Object Qtree, Qtab;
extern Lisp_Object Q_mask_file, Q_mask_data, Q_hotspot_x, Q_hotspot_y;
extern Lisp_Object Q_foreground, Q_background, Q_face, Q_descriptor, Q_group;
extern Lisp_Object Q_width, Q_height, Q_pixel_width, Q_pixel_height, Q_text;
Index: src/gui.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/gui.c,v
retrieving revision 1.10.2.5
diff -u -r1.10.2.5 gui.c
--- src/gui.c 1999/01/27 20:12:04 1.10.2.5
+++ src/gui.c 1999/06/13 19:50:30
@@ -97,35 +97,17 @@
}
/*
- * Initialize the gui_item structure by setting all (GC-protected)
- * fields to their default values. The defaults are t for :active and
- * :included values, and nil for others.
- */
-void
-gui_item_init (struct gui_item *pgui_item)
-{
- pgui_item->name = Qnil;
- pgui_item->callback = Qnil;
- pgui_item->suffix = Qnil;
- pgui_item->active = Qt;
- pgui_item->included = Qt;
- pgui_item->config = Qnil;
- pgui_item->filter = Qnil;
- pgui_item->style = Qnil;
- pgui_item->selected = Qnil;
- pgui_item->keys = Qnil;
-}
-
-/*
* Add a value VAL associated with keyword KEY into PGUI_ITEM
* structure. If KEY is not a keyword, or is an unknown keyword, then
* error is signaled.
*/
void
-gui_item_add_keyval_pair (struct gui_item *pgui_item,
+gui_item_add_keyval_pair (Lisp_Object gui_item,
Lisp_Object key, Lisp_Object val,
Error_behavior errb)
{
+ struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
+
if (!KEYWORDP (key))
signal_simple_error_2 ("Non-keyword in gui item", key, pgui_item->name);
@@ -144,17 +126,51 @@
signal_simple_error_2 ("Unknown keyword in gui item", key, pgui_item->name);
}
+void
+gui_item_init (Lisp_Object gui_item)
+{
+ struct Lisp_Gui_Item *lp = XGUI_ITEM (gui_item);
+
+ lp->name = Qnil;
+ lp->callback = Qnil;
+ lp->suffix = Qnil;
+ lp->active = Qt;
+ lp->included = Qt;
+ lp->config = Qnil;
+ lp->filter = Qnil;
+ lp->style = Qnil;
+ lp->selected = Qnil;
+ lp->keys = Qnil;
+}
+
+Lisp_Object
+allocate_gui_item ()
+{
+ struct Lisp_Gui_Item *lp =
+ alloc_lcrecord_type (struct Lisp_Gui_Item, &lrecord_gui_item);
+ Lisp_Object val;
+
+ zero_lcrecord (lp);
+ XSETGUI_ITEM (val, lp);
+
+ gui_item_init (val);
+
+ return val;
+}
+
/*
* ITEM is a lisp vector, describing a menu item or a button. The
* function extracts the description of the item into the PGUI_ITEM
* structure.
*/
-static void
-gui_parse_item_keywords_internal (Lisp_Object item, struct gui_item *pgui_item,
- Error_behavior errb)
+static Lisp_Object
+make_gui_item_from_keywords_internal (Lisp_Object item,
+ Error_behavior errb)
{
int length, plist_p, start;
Lisp_Object *contents;
+ Lisp_Object gui_item = allocate_gui_item ();
+ struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
CHECK_VECTOR (item);
length = XVECTOR_LENGTH (item);
@@ -204,21 +220,48 @@
{
Lisp_Object key = contents [i++];
Lisp_Object val = contents [i++];
- gui_item_add_keyval_pair (pgui_item, key, val, errb);
+ gui_item_add_keyval_pair (gui_item, key, val, errb);
}
}
+ return gui_item;
}
-void
-gui_parse_item_keywords (Lisp_Object item, struct gui_item *pgui_item)
+Lisp_Object
+gui_parse_item_keywords (Lisp_Object item)
{
- gui_parse_item_keywords_internal (item, pgui_item, ERROR_ME);
+ return make_gui_item_from_keywords_internal (item, ERROR_ME);
}
+Lisp_Object
+gui_parse_item_keywords_no_errors (Lisp_Object item)
+{
+ return make_gui_item_from_keywords_internal (item, ERROR_ME_NOT);
+}
+
+/* convert a gui item into plist properties */
void
-gui_parse_item_keywords_no_errors (Lisp_Object item, struct gui_item *pgui_item)
+gui_add_item_keywords_to_plist (Lisp_Object plist, Lisp_Object gui_item)
{
- gui_parse_item_keywords_internal (item, pgui_item, ERROR_ME_NOT);
+ struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
+
+ if (!NILP (pgui_item->callback))
+ Fplist_put (plist, Q_callback, pgui_item->callback);
+ if (!NILP (pgui_item->suffix))
+ Fplist_put (plist, Q_suffix, pgui_item->suffix);
+ if (!NILP (pgui_item->active))
+ Fplist_put (plist, Q_active, pgui_item->active);
+ if (!NILP (pgui_item->included))
+ Fplist_put (plist, Q_included, pgui_item->included);
+ if (!NILP (pgui_item->config))
+ Fplist_put (plist, Q_config, pgui_item->config);
+ if (!NILP (pgui_item->filter))
+ Fplist_put (plist, Q_filter, pgui_item->filter);
+ if (!NILP (pgui_item->style))
+ Fplist_put (plist, Q_style, pgui_item->style);
+ if (!NILP (pgui_item->selected))
+ Fplist_put (plist, Q_selected, pgui_item->selected);
+ if (!NILP (pgui_item->keys))
+ Fplist_put (plist, Q_keys, pgui_item->keys);
}
/*
@@ -226,13 +269,13 @@
* if any
*/
int
-gui_item_active_p (CONST struct gui_item *pgui_item)
+gui_item_active_p (Lisp_Object gui_item)
{
/* This function can call lisp */
/* Shortcut to avoid evaluating Qt each time */
- return (EQ (pgui_item->active, Qt)
- || !NILP (Feval (pgui_item->active)));
+ return (EQ (XGUI_ITEM (gui_item)->active, Qt)
+ || !NILP (Feval (XGUI_ITEM (gui_item)->active)));
}
/*
@@ -240,13 +283,13 @@
* if any
*/
int
-gui_item_selected_p (CONST struct gui_item *pgui_item)
+gui_item_selected_p (Lisp_Object gui_item)
{
/* This function can call lisp */
/* Shortcut to avoid evaluating Qt each time */
- return (EQ (pgui_item->selected, Qt)
- || !NILP (Feval (pgui_item->selected)));
+ return (EQ (XGUI_ITEM (gui_item)->selected, Qt)
+ || !NILP (Feval (XGUI_ITEM (gui_item)->selected)));
}
/*
@@ -255,9 +298,10 @@
* configuration variable
*/
int
-gui_item_included_p (CONST struct gui_item *pgui_item, Lisp_Object conflist)
+gui_item_included_p (Lisp_Object gui_item, Lisp_Object conflist)
{
/* This function can call lisp */
+ struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
/* Evaluate :included first. Shortcut to avoid evaluating Qt each time */
if (!EQ (pgui_item->included, Qt)
@@ -289,11 +333,12 @@
* buffer.
*/
unsigned int
-gui_item_display_flush_left (CONST struct gui_item *pgui_item,
+gui_item_display_flush_left (Lisp_Object gui_item,
char* buf, Bytecount buf_len)
{
char *p = buf;
Bytecount len;
+ struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
/* Copy item name first */
CHECK_STRING (pgui_item->name);
@@ -336,9 +381,10 @@
* buffer.
*/
unsigned int
-gui_item_display_flush_right (CONST struct gui_item *pgui_item,
+gui_item_display_flush_right (Lisp_Object gui_item,
char* buf, Bytecount buf_len)
{
+ struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
*buf = 0;
/* Have keys? */
@@ -374,9 +420,11 @@
}
#endif /* HAVE_WINDOW_SYSTEM */
-Lisp_Object
-mark_gui_item (struct gui_item* p, void (*markobj) (Lisp_Object))
+static Lisp_Object
+mark_gui_item (Lisp_Object obj, void (*markobj) (Lisp_Object))
{
+ struct Lisp_Gui_Item *p = XGUI_ITEM (obj);
+
markobj (p->name);
markobj (p->callback);
markobj (p->suffix);
@@ -391,10 +439,27 @@
return Qnil;
}
+static unsigned long
+gui_item_hash (Lisp_Object obj, int depth)
+{
+ struct Lisp_Gui_Item *p = XGUI_ITEM (obj);
+
+ return HASH2 (HASH5 (internal_hash (p->name, depth + 1),
+ internal_hash (p->callback, depth + 1),
+ internal_hash (p->suffix, depth + 1),
+ internal_hash (p->active, depth + 1),
+ internal_hash (p->included, depth + 1)),
+ HASH5 (internal_hash (p->config, depth + 1),
+ internal_hash (p->filter, depth + 1),
+ internal_hash (p->style, depth + 1),
+ internal_hash (p->selected, depth + 1),
+ internal_hash (p->keys, depth + 1)));
+}
+
int
-gui_item_hash (Lisp_Object hashtable, struct gui_item* g, int slot)
+gui_item_id_hash (Lisp_Object hashtable, Lisp_Object gitem, int slot)
{
- int hashid = HASH2 (internal_hash (g->callback, 0), internal_hash (g->name, 0));
+ int hashid = gui_item_hash (gitem, 0);
int id = GUI_ITEM_ID_BITS (hashid, slot);
while (!NILP (Fgethash (make_int (id),
hashtable, Qnil)))
@@ -403,6 +468,55 @@
}
return id;
}
+
+static int
+gui_item_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
+{
+ struct Lisp_Gui_Item *p1 = XGUI_ITEM (obj1);
+ struct Lisp_Gui_Item *p2 = XGUI_ITEM (obj2);
+
+ if (!(internal_equal (p1->name, p2->name, depth + 1)
+ &&
+ internal_equal (p1->callback, p2->callback, depth + 1)
+ &&
+ EQ (p1->suffix, p2->suffix)
+ &&
+ EQ (p1->active, p2->active)
+ &&
+ EQ (p1->included, p2->included)
+ &&
+ EQ (p1->config, p2->config)
+ &&
+ EQ (p1->filter, p2->filter)
+ &&
+ EQ (p1->style, p2->style)
+ &&
+ EQ (p1->selected, p2->selected)
+ &&
+ EQ (p1->keys, p2->keys)))
+ return 0;
+ return 1;
+}
+
+static void
+print_gui_item (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
+{
+ struct Lisp_Gui_Item *g = XGUI_ITEM (obj);
+ char buf[20];
+
+ if (print_readably)
+ error ("printing unreadable object #<gui-item 0x%x>", g->header.uid);
+
+ write_c_string ("#<gui-item ", printcharfun);
+ sprintf (buf, "0x%x>", g->header.uid);
+ write_c_string (buf, printcharfun);
+}
+
+DEFINE_LRECORD_IMPLEMENTATION ("gui-item", gui_item,
+ mark_gui_item, print_gui_item,
+ 0, gui_item_equal,
+ gui_item_hash,
+ struct Lisp_Gui_Item);
void
syms_of_gui (void)
Index: src/gui.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/gui.h,v
retrieving revision 1.6.2.3
diff -u -r1.6.2.3 gui.h
--- src/gui.h 1998/12/29 21:32:35 1.6.2.3
+++ src/gui.h 1999/06/13 19:50:30
@@ -32,10 +32,24 @@
extern int popup_up_p;
+/************************************************************************/
+/* Image Instance Object */
+/************************************************************************/
+
+DECLARE_LRECORD (gui_item, struct Lisp_Gui_Item);
+#define XGUI_ITEM(x) \
+ XRECORD (x, gui_item, struct Lisp_Gui_Item)
+#define XSETGUI_ITEM(x, p) XSETRECORD (x, p, gui_item)
+#define GUI_ITEMP(x) RECORDP (x, gui_item)
+#define GC_GUI_ITEMP(x) GC_RECORDP (x, gui_item)
+#define CHECK_GUI_ITEM(x) CHECK_RECORD (x, gui_item)
+#define CONCHECK_GUI_ITEM(x) CONCHECK_RECORD (x, gui_item)
+
/* This structure describes gui button,
menu item or submenu properties */
-struct gui_item
+struct Lisp_Gui_Item
{
+ struct lcrecord_header header;
Lisp_Object name; /* String */
Lisp_Object callback; /* Symbol or form */
Lisp_Object suffix; /* String */
@@ -47,44 +61,27 @@
Lisp_Object selected; /* Form */
Lisp_Object keys; /* String */
};
-#define GUI_ITEM_LAST_GCPROED keys
-#define GUI_ITEM_GCPRO_COUNT \
- (slot_offset(struct gui_item, GUI_ITEM_LAST_GCPROED) / sizeof(Lisp_Object) + 1)
-/*
- * gui_item is a struct containing a bunch of Lisp_Object
- * members. We need to GC-protect all the member slots.
- * Rather than build a long chain of individual gcpro structs
- * that protect the slots individually, we protect all the
- * member slots by pretending the struct is an array. ANSI C
- * requires this hack to work, ugly though it is.
- */
-#define GCPRO_GUI_ITEM(pgui_item) \
- do { \
- Lisp_Object *gui_item_array = (Lisp_Object *) pgui_item; \
- GCPRO1 (gui_item_array[0]); \
- gcpro1.nvars = GUI_ITEM_GCPRO_COUNT; \
- } while (0);
-
extern Lisp_Object Q_accelerator, Q_active, Q_config, Q_filter, Q_included;
extern Lisp_Object Q_keys, Q_selected, Q_suffix, Qradio, Qtoggle;
extern Lisp_Object Q_key_sequence, Q_label, Q_callback;
-void gui_item_init (struct gui_item *pgui_item);
-void gui_item_add_keyval_pair (struct gui_item *pgui_item,
+void gui_item_add_keyval_pair (Lisp_Object,
Lisp_Object key, Lisp_Object val,
Error_behavior errb);
-void gui_parse_item_keywords (Lisp_Object item, struct gui_item *pgui_item);
-void gui_parse_item_keywords_no_errors (Lisp_Object item, struct gui_item *pgui_item);
-int gui_item_active_p (CONST struct gui_item *pgui_item);
-int gui_item_selected_p (CONST struct gui_item *pgui_item);
-int gui_item_included_p (CONST struct gui_item *pgui_item, Lisp_Object into);
-int gui_item_hash (Lisp_Object, struct gui_item*, int);
-Lisp_Object mark_gui_item (struct gui_item* p, void (*markobj) (Lisp_Object));
-unsigned int gui_item_display_flush_left (CONST struct gui_item *pgui_item,
+Lisp_Object gui_parse_item_keywords (Lisp_Object item);
+Lisp_Object gui_parse_item_keywords_no_errors (Lisp_Object item);
+int gui_item_active_p (Lisp_Object);
+int gui_item_selected_p (Lisp_Object);
+int gui_item_included_p (Lisp_Object, Lisp_Object into);
+int gui_item_id_hash (Lisp_Object, Lisp_Object gui_item, int);
+unsigned int gui_item_display_flush_left (Lisp_Object pgui_item,
char* buf, Bytecount buf_len);
-unsigned int gui_item_display_flush_right (CONST struct gui_item *pgui_item,
+unsigned int gui_item_display_flush_right (Lisp_Object gui_item,
char* buf, Bytecount buf_len);
+
+Lisp_Object allocate_gui_item ();
+void gui_item_init (Lisp_Object gui_item);
/* this is mswindows biased but reasonably safe I think */
#define GUI_ITEM_ID_SLOTS 8
Index: src/lisp.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/lisp.h,v
retrieving revision 1.38.2.12
diff -u -r1.38.2.12 lisp.h
--- src/lisp.h 1999/05/13 12:26:48 1.38.2.12
+++ src/lisp.h 1999/06/13 19:50:37
@@ -336,6 +336,8 @@
typedef struct Lisp_Font_Instance Lisp_Font_Instance;
struct Lisp_Image_Instance;
typedef struct Lisp_Image_Instance Lisp_Image_Instance;
+struct Lisp_Gui_Item;
+typedef struct Lisp_Gui_Item Lisp_Gui_Item;
struct display_line;
struct redisplay_info;
struct window_mirror;
Index: src/menubar-msw.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/menubar-msw.c,v
retrieving revision 1.16.2.5
diff -u -r1.16.2.5 menubar-msw.c
--- src/menubar-msw.c 1999/03/10 12:48:28 1.16.2.5
+++ src/menubar-msw.c 1999/06/13 19:50:41
@@ -123,7 +123,7 @@
* "Left Flush\tRight Flush"
*/
static char*
-displayable_menu_item (struct gui_item* pgui_item, int bar_p)
+displayable_menu_item (Lisp_Object gui_item, int bar_p)
{
/* We construct the name in a static buffer. That's fine, because
menu items longer than 128 chars are probably programming errors,
@@ -134,7 +134,7 @@
unsigned int ll, lr;
/* Left flush part of the string */
- ll = gui_item_display_flush_left (pgui_item, buf, MAX_MENUITEM_LENGTH);
+ ll = gui_item_display_flush_left (gui_item, buf, MAX_MENUITEM_LENGTH);
/* Escape '&' as '&&' */
ptr = buf;
@@ -142,7 +142,7 @@
{
if (ll+2 >= MAX_MENUITEM_LENGTH)
signal_simple_error ("Menu item produces too long displayable string",
- pgui_item->name);
+ XGUI_ITEM (gui_item)->name);
memmove (ptr+1, ptr, (ll-(ptr-buf))+1);
ll++;
ptr+=2;
@@ -165,7 +165,7 @@
if (!bar_p)
{
assert (MAX_MENUITEM_LENGTH > ll + 1);
- lr = gui_item_display_flush_right (pgui_item, buf + ll + 1,
+ lr = gui_item_display_flush_right (gui_item, buf + ll + 1,
MAX_MENUITEM_LENGTH - ll - 1);
if (lr)
buf [ll] = '\t';
@@ -279,21 +279,21 @@
{
/* Submenu */
HMENU submenu;
- struct gui_item gui_item;
+ Lisp_Object gui_item = allocate_gui_item ();
+ struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
struct gcpro gcpro1;
- gui_item_init (&gui_item);
- GCPRO_GUI_ITEM (&gui_item);
+ GCPRO1 (gui_item);
- menu_parse_submenu_keywords (item, &gui_item);
+ menu_parse_submenu_keywords (item, gui_item);
- if (!STRINGP (gui_item.name))
+ if (!STRINGP (pgui_item->name))
signal_simple_error ("Menu name (first element) must be a string", item);
- if (!gui_item_included_p (&gui_item, Vmenubar_configuration))
+ if (!gui_item_included_p (gui_item, Vmenubar_configuration))
return;
- if (!gui_item_active_p (&gui_item))
+ if (!gui_item_active_p (gui_item))
item_info.fState = MFS_GRAYED;
/* Temptation is to put 'else' right here. Although, the
displayed item won't have an arrow indicating that it is a
@@ -301,7 +301,7 @@
submenu = create_empty_popup_menu();
item_info.fMask |= MIIM_SUBMENU;
- item_info.dwTypeData = displayable_menu_item (&gui_item, bar_p);
+ item_info.dwTypeData = displayable_menu_item (gui_item, bar_p);
item_info.hSubMenu = submenu;
if (!(item_info.fState & MFS_GRAYED))
@@ -310,12 +310,12 @@
keyed by menu handle */
if (NILP(path))
/* list1 cannot GC */
- path = list1 (gui_item.name);
+ path = list1 (pgui_item->name);
else
{
Lisp_Object arg[2];
arg[0] = path;
- arg[1] = list1 (gui_item.name);
+ arg[1] = list1 (pgui_item->name);
/* Fappend gcpro'es its arg */
path = Fappend (2, arg);
}
@@ -329,22 +329,20 @@
{
/* An ordinary item */
Lisp_Object style, id;
- struct gui_item gui_item;
+ Lisp_Object gui_item = gui_parse_item_keywords (item);
+ struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
struct gcpro gcpro1;
- gui_item_init (&gui_item);
- GCPRO_GUI_ITEM (&gui_item);
+ GCPRO1 (gui_item);
- gui_parse_item_keywords (item, &gui_item);
-
- if (!gui_item_included_p (&gui_item, Vmenubar_configuration))
+ if (!gui_item_included_p (gui_item, Vmenubar_configuration))
return;
- if (!gui_item_active_p (&gui_item))
+ if (!gui_item_active_p (gui_item))
item_info.fState = MFS_GRAYED;
- style = (NILP (gui_item.selected) || NILP (Feval (gui_item.selected))
- ? Qnil : gui_item.style);
+ style = (NILP (pgui_item->selected) || NILP (Feval (pgui_item->selected))
+ ? Qnil : pgui_item->style);
if (EQ (style, Qradio))
{
@@ -356,13 +354,13 @@
item_info.fState |= MFS_CHECKED;
}
- id = allocate_menu_item_id (path, gui_item.name,
- gui_item.suffix);
- Fputhash (id, gui_item.callback, hash_tab);
+ id = allocate_menu_item_id (path, pgui_item->name,
+ pgui_item->suffix);
+ Fputhash (id, pgui_item->callback, hash_tab);
item_info.wID = (UINT) XINT(id);
item_info.fType |= MFT_STRING;
- item_info.dwTypeData = displayable_menu_item (&gui_item, bar_p);
+ item_info.dwTypeData = displayable_menu_item (gui_item, bar_p);
UNGCPRO; /* gui_item */
}
@@ -396,10 +394,9 @@
int deep_p, flush_right;
struct gcpro gcpro1;
unsigned long checksum;
- struct gui_item gui_item;
-
- gui_item_init (&gui_item);
- GCPRO_GUI_ITEM (&gui_item);
+ Lisp_Object gui_item = allocate_gui_item ();
+ struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
+ GCPRO1 (gui_item);
/* We are sometimes called with the menubar unchanged, and with changed
right flush. We have to update the menubar in this case,
@@ -414,15 +411,15 @@
deep_p = !NILP (path);
/* Fetch keywords prepending the item list */
- desc = menu_parse_submenu_keywords (desc, &gui_item);
+ desc = menu_parse_submenu_keywords (desc, gui_item);
/* Check that menu name is specified when expected */
- if (NILP (gui_item.name) && deep_p)
+ if (NILP (pgui_item->name) && deep_p)
signal_simple_error ("Menu must have a name", desc);
/* Apply filter if specified */
- if (!NILP (gui_item.filter))
- desc = call1 (gui_item.filter, desc);
+ if (!NILP (pgui_item->filter))
+ desc = call1 (pgui_item->filter, desc);
/* Loop thru the desc's CDR and add items for each entry */
flush_right = 0;
@@ -453,11 +450,11 @@
/* Add the header to the popup, if told so. The same as in X - an
insensitive item, and a separator (Seems to me, there were
two separators in X... In Windows this looks ugly, anyways. */
- if (!bar_p && !deep_p && popup_menu_titles && !NILP(gui_item.name))
+ if (!bar_p && !deep_p && popup_menu_titles && !NILP(pgui_item->name))
{
- CHECK_STRING (gui_item.name);
+ CHECK_STRING (pgui_item->name);
InsertMenu (menu, 0, MF_BYPOSITION | MF_STRING | MF_DISABLED,
- 0, XSTRING_DATA(gui_item.name));
+ 0, XSTRING_DATA(pgui_item->name));
InsertMenu (menu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
SetMenuDefaultItem (menu, 0, MF_BYPOSITION);
}
Index: src/menubar.c
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/menubar.c,v
retrieving revision 1.12.2.3
diff -u -r1.12.2.3 menubar.c
--- src/menubar.c 1998/12/29 21:32:36 1.12.2.3
+++ src/menubar.c 1999/06/13 19:50:43
@@ -102,8 +102,10 @@
}
Lisp_Object
-menu_parse_submenu_keywords (Lisp_Object desc, struct gui_item* pgui_item)
+menu_parse_submenu_keywords (Lisp_Object desc, Lisp_Object gui_item)
{
+ struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
+
/* Menu descriptor should be a list */
CHECK_CONS (desc);
@@ -130,7 +132,7 @@
desc = XCDR (desc);
if (!NILP (desc))
CHECK_CONS (desc);
- gui_item_add_keyval_pair (pgui_item, key, val, ERROR_ME);
+ gui_item_add_keyval_pair (gui_item, key, val, ERROR_ME);
}
/* Return the rest - supposed to be a list of items */
@@ -152,10 +154,10 @@
{
Lisp_Object path_entry, submenu_desc, submenu;
struct gcpro gcpro1;
- struct gui_item gui_item;
+ Lisp_Object gui_item = allocate_gui_item ();
+ struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item);
- gui_item_init (&gui_item);
- GCPRO_GUI_ITEM (&gui_item);
+ GCPRO1 (gui_item);
EXTERNAL_LIST_LOOP (path_entry, path)
{
@@ -164,15 +166,15 @@
RETURN_UNGCPRO (Qnil);
/* Parse this menu */
- desc = menu_parse_submenu_keywords (desc, &gui_item);
+ desc = menu_parse_submenu_keywords (desc, gui_item);
/* Check that this (sub)menu is active */
- if (!gui_item_active_p (&gui_item))
+ if (!gui_item_active_p (gui_item))
RETURN_UNGCPRO (Qnil);
/* Apply :filter */
- if (!NILP (gui_item.filter))
- desc = call1 (gui_item.filter, desc);
+ if (!NILP (pgui_item->filter))
+ desc = call1 (pgui_item->filter, desc);
/* Find the next menu on the path inside this one */
EXTERNAL_LIST_LOOP (submenu_desc, desc)
@@ -191,7 +193,7 @@
descend:
/* Prepare for the next iteration */
- gui_item_init (&gui_item);
+ gui_item_init (gui_item);
}
/* We have successfully descended down the end of the path */
Index: src/menubar.h
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/src/menubar.h,v
retrieving revision 1.4
diff -u -r1.4 menubar.h
--- src/menubar.h 1998/03/31 20:11:58 1.4
+++ src/menubar.h 1999/06/13 19:50:43
@@ -30,7 +30,7 @@
void update_frame_menubars (struct frame *f);
void free_frame_menubars (struct frame *f);
Lisp_Object menu_parse_submenu_keywords (Lisp_Object desc,
- struct gui_item* pgui_item);
+ Lisp_Object gui_item);
Lisp_Object current_frame_menubar (CONST struct frame* f);
EXFUN (Fmenu_find_real_submenu, 2);
Index: tests/glyph-test.el
===================================================================
RCS file: /usr/CVSroot/XEmacs/xemacs/tests/Attic/glyph-test.el,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 glyph-test.el
--- tests/glyph-test.el 1999/01/12 01:38:21 1.1.2.4
+++ tests/glyph-test.el 1999/06/13 19:50:43
@@ -25,6 +25,29 @@
:face modeline-mousable
:descriptor "ok" :callback foo
:selected t])))
+
+;; tree view
+(set-extent-begin-glyph
+ (make-extent (point) (point))
+ (setq tree (make-glyph
+ [tree :width 10
+ :descriptor "My Tree"
+ :properties (:items (["One" foo]
+ (["Two" foo]
+ ["Four" foo]
+ "Six")
+ "Three"))])))
+
+;; tab control
+(set-extent-begin-glyph
+ (make-extent (point) (point))
+ (setq tab (make-glyph
+ [tab :descriptor "My Tab"
+ :face default
+ :properties (:items (["One" foo]
+ ["Two" foo]
+ ["Three" foo]))])))
+
;; progress gauge
(set-extent-begin-glyph
(make-extent (point) (point))
@@ -63,6 +86,7 @@
(set-extent-begin-glyph
(make-extent (point) (point))
(make-glyph [button :descriptor ["A Big Button" foo ]]))
+
;; edit box
(set-extent-begin-glyph
(make-extent (point) (point))
--------------------------------------------------------------
Dr Andy Piper
Senior Consultant Architect, BEA Systems Ltd