Rewrite globals to allow indirection in C.
[emacs.git] / lwlib / lwlib-Xlw.c
blob115997d361237d870a6cd65c70c9947960509698
1 /* The lwlib interface to "xlwmenu" menus.
2 Copyright (C) 1992 Lucid, Inc.
3 Copyright (C) 1994, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4 2008, 2009, 2010 Free Software Foundation, Inc.
6 This file is part of the Lucid Widget Library.
8 The Lucid Widget Library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 1, or (at your option)
11 any later version.
13 The Lucid Widget Library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <setjmp.h>
28 #include "lisp.h"
30 #include "lwlib-Xlw.h"
31 #include <X11/StringDefs.h>
32 #include <X11/IntrinsicP.h>
33 #include <X11/ObjectP.h>
34 #include <X11/CompositeP.h>
35 #include <X11/Shell.h>
36 #include "xlwmenu.h"
38 #if 0
40 #include <stdio.h>
42 /* Print the complete X resource name of widget WIDGET to stderr.
43 This is sometimes handy to have available. */
45 void
46 x_print_complete_resource_name (widget)
47 Widget widget;
49 int i;
50 String names[100];
52 for (i = 0; i < 100 && widget != NULL; ++i)
54 names[i] = XtName (widget);
55 widget = XtParent (widget);
58 for (--i; i >= 1; --i)
59 fprintf (stderr, "%s.", names[i]);
60 fprintf (stderr, "%s\n", names[0]);
63 #endif /* 0 */
66 \f/* Menu callbacks */
68 /* Callback XtNhighlightCallback for Lucid menus. W is the menu
69 widget, CLIENT_DATA contains a pointer to the widget_instance
70 for the menu, CALL_DATA contains a pointer to the widget_value
71 structure for the highlighted menu item. The latter may be null
72 if there isn't any highlighted menu item. */
74 static void
75 highlight_hook (w, client_data, call_data)
76 Widget w;
77 XtPointer client_data;
78 XtPointer call_data;
80 widget_instance *instance = (widget_instance *) client_data;
82 if (instance->info->highlight_cb
83 && !w->core.being_destroyed)
84 instance->info->highlight_cb (w, instance->info->id, call_data);
87 static void
88 enter_hook (w, client_data, call_data)
89 Widget w;
90 XtPointer client_data;
91 XtPointer call_data;
93 highlight_hook (w, client_data, call_data);
96 static void
97 leave_hook (w, client_data, call_data)
98 Widget w;
99 XtPointer client_data;
100 XtPointer call_data;
102 highlight_hook (w, client_data, NULL);
106 static void
107 pre_hook (w, client_data, call_data)
108 Widget w;
109 XtPointer client_data;
110 XtPointer call_data;
112 widget_instance* instance = (widget_instance*)client_data;
113 widget_value* val;
115 if (w->core.being_destroyed)
116 return;
118 val = lw_get_widget_value_for_widget (instance, w);
119 if (instance->info->pre_activate_cb)
120 instance->info->pre_activate_cb (w, instance->info->id,
121 val ? val->call_data : NULL);
124 static void
125 pick_hook (w, client_data, call_data)
126 Widget w;
127 XtPointer client_data;
128 XtPointer call_data;
130 widget_instance* instance = (widget_instance*)client_data;
131 widget_value* contents_val = (widget_value*)call_data;
132 widget_value* widget_val;
133 XtPointer widget_arg;
135 if (w->core.being_destroyed)
136 return;
138 if (instance->info->selection_cb && contents_val && contents_val->enabled
139 && !contents_val->contents)
140 instance->info->selection_cb (w, instance->info->id,
141 contents_val->call_data);
143 widget_val = lw_get_widget_value_for_widget (instance, w);
144 widget_arg = widget_val ? widget_val->call_data : NULL;
145 if (instance->info->post_activate_cb)
146 instance->info->post_activate_cb (w, instance->info->id, widget_arg);
150 \f/* creation functions */
152 static Widget
153 xlw_create_menubar (instance)
154 widget_instance* instance;
156 Widget widget;
157 Arg al[5];
158 int ac = 0;
160 XtSetArg (al[ac], XtNmenu, instance->info->val); ac++;
161 #ifdef emacs
162 XtSetArg (al[ac], XtNshowGrip, 0); ac++;
163 XtSetArg (al[ac], XtNresizeToPreferred, 1); ac++;
164 XtSetArg (al[ac], XtNallowResize, 1); ac++;
165 #endif
167 /* This used to use XtVaCreateWidget, but an old Xt version
168 has a bug in XtVaCreateWidget that frees instance->info->name. */
169 widget
170 = XtCreateWidget (instance->info->name, xlwMenuWidgetClass,
171 instance->parent, al, ac);
173 XtAddCallback (widget, XtNopen, pre_hook, (XtPointer)instance);
174 XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
175 XtAddCallback (widget, XtNleaveCallback, leave_hook, (XtPointer)instance);
176 XtAddCallback (widget, XtNenterCallback, enter_hook, (XtPointer)instance);
177 return widget;
180 static Widget
181 xlw_create_popup_menu (instance)
182 widget_instance* instance;
184 Widget popup_shell
185 = XtCreatePopupShell (instance->info->name, overrideShellWidgetClass,
186 instance->parent, NULL, 0);
188 Widget widget;
189 Arg al[2];
190 int ac = 0;
192 XtSetArg (al[ac], XtNmenu, instance->info->val); ac++;
193 XtSetArg (al[ac], XtNhorizontal, False); ac++;
195 /* This used to use XtVaManagedCreateWidget, but an old Xt version
196 has a bug in XtVaManagedCreateWidget that frees instance->info->name. */
197 widget
198 = XtCreateManagedWidget ("popup", xlwMenuWidgetClass,
199 popup_shell, al, ac);
201 XtAddCallback (widget, XtNselect, pick_hook, (XtPointer)instance);
202 XtAddCallback (widget, XtNleaveCallback, leave_hook, (XtPointer)instance);
203 XtAddCallback (widget, XtNenterCallback, enter_hook, (XtPointer)instance);
205 return popup_shell;
208 widget_creation_entry
209 xlw_creation_table [] =
211 {"menubar", xlw_create_menubar},
212 {"popup", xlw_create_popup_menu},
213 {NULL, NULL}
216 Boolean
217 lw_lucid_widget_p (widget)
218 Widget widget;
220 WidgetClass the_class = XtClass (widget);
222 if (the_class == xlwMenuWidgetClass)
223 return True;
224 if (the_class == overrideShellWidgetClass)
225 return (XtClass (((CompositeWidget)widget)->composite.children [0])
226 == xlwMenuWidgetClass);
227 return False;
230 void
231 #ifdef PROTOTYPES
232 xlw_update_one_widget (widget_instance* instance, Widget widget,
233 widget_value* val, Boolean deep_p)
234 #else
235 xlw_update_one_widget (instance, widget, val, deep_p)
236 widget_instance* instance;
237 Widget widget;
238 widget_value* val;
239 Boolean deep_p;
240 #endif
242 Arg al[1];
244 /* This used to use XtVaSetValues, but some old Xt versions
245 that have a bug in XtVaCreateWidget might have it here too. */
246 XtSetArg (al[0], XtNmenu, instance->info->val);
248 XtSetValues (widget, al, 1);
251 void
252 xlw_update_one_value (instance, widget, val)
253 widget_instance* instance;
254 Widget widget;
255 widget_value* val;
257 return;
260 void
261 #ifdef PROTOTYPES
262 xlw_pop_instance (widget_instance* instance, Boolean up)
263 #else
264 xlw_pop_instance (instance, up)
265 widget_instance* instance;
266 Boolean up;
267 #endif
271 void
272 xlw_popup_menu (widget, event)
273 Widget widget;
274 XEvent *event;
276 XlwMenuWidget mw;
278 if (!XtIsShell (widget))
279 return;
281 mw = (XlwMenuWidget)((CompositeWidget)widget)->composite.children [0];
283 if (event)
284 XtCallActionProc ((Widget) mw, "start", event, NULL, 0);
285 else
287 XEvent dummy;
288 XButtonPressedEvent *bd = &dummy.xbutton;
290 bd->type = ButtonPress;
291 bd->serial = 0;
292 bd->send_event = 0;
293 bd->display = XtDisplay (widget);
294 bd->window = XtWindow (XtParent (widget));
295 bd->time = CurrentTime;
296 bd->button = 0;
297 XQueryPointer (bd->display, bd->window, &bd->root,
298 &bd->subwindow, &bd->x_root, &bd->y_root,
299 &bd->x, &bd->y, &bd->state);
301 XtCallActionProc ((Widget) mw, "start", &dummy, NULL, 0);
305 \f/* Destruction of instances */
306 void
307 xlw_destroy_instance (instance)
308 widget_instance* instance;
310 if (instance->widget)
311 XtDestroyWidget (instance->widget);
314 /* arch-tag: 541e3912-477d-406e-9bf2-dbf2b7ff8c3b
315 (do not change this comment) */