Merge from trunk.
[emacs.git] / lwlib / lwlib-Xaw.c
blob9c9a007bc15d768efc6af4c79ce10e1daad32f51
1 /* The lwlib interface to Athena widgets.
3 Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
4 Copyright (C) 1994, 2001-2011 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 <stdio.h>
28 #include <setjmp.h>
29 #include <ctype.h>
31 #include <lisp.h>
33 #include "lwlib-Xaw.h"
35 #include <X11/StringDefs.h>
36 #include <X11/IntrinsicP.h>
37 #include <X11/CoreP.h>
38 #include <X11/Shell.h>
40 #ifdef HAVE_XAW3D
41 #include <X11/Xaw3d/Scrollbar.h>
42 #include <X11/Xaw3d/Paned.h>
43 #include <X11/Xaw3d/Dialog.h>
44 #include <X11/Xaw3d/Form.h>
45 #include <X11/Xaw3d/Command.h>
46 #include <X11/Xaw3d/Label.h>
47 #else /* !HAVE_XAW3D */
48 #include <X11/Xaw/Scrollbar.h>
49 #include <X11/Xaw/Paned.h>
50 #include <X11/Xaw/Dialog.h>
51 #include <X11/Xaw/Form.h>
52 #include <X11/Xaw/Command.h>
53 #include <X11/Xaw/Label.h>
54 #endif /* HAVE_XAW3D */
56 #include <X11/Xatom.h>
58 #ifdef HAVE_XFT
59 #include <X11/Xft/Xft.h>
61 struct widget_xft_data
63 Widget widget;
64 XftFont *xft_font;
65 XftDraw *xft_draw;
66 XftColor xft_fg, xft_bg;
67 int p_width, p_height;
68 Pixmap p;
72 #endif
74 static void xaw_generic_callback (Widget widget,
75 XtPointer closure,
76 XtPointer call_data);
79 Boolean
80 lw_xaw_widget_p (Widget widget)
82 return (XtIsSubclass (widget, scrollbarWidgetClass) ||
83 XtIsSubclass (widget, dialogWidgetClass));
87 #ifdef HAVE_XFT
88 static void
89 fill_xft_data (struct widget_xft_data *data, Widget widget, XftFont *font)
91 Pixel bg, fg;
92 XColor colors[2];
94 data->widget = widget;
95 data->xft_font = font;
96 XtVaGetValues (widget,
97 XtNbackground, &bg,
98 XtNforeground, &fg,
99 NULL);
101 colors[0].pixel = data->xft_fg.pixel = fg;
102 colors[1].pixel = data->xft_bg.pixel = bg;
103 XQueryColors (XtDisplay (widget),
104 DefaultColormapOfScreen (XtScreen (widget)),
105 colors, 2);
107 data->xft_fg.color.alpha = 0xFFFF;
108 data->xft_fg.color.red = colors[0].red;
109 data->xft_fg.color.green = colors[0].green;
110 data->xft_fg.color.blue = colors[0].blue;
111 data->xft_bg.color.alpha = 0xFFFF;
112 data->xft_bg.color.red = colors[1].red;
113 data->xft_bg.color.green = colors[1].green;
114 data->xft_bg.color.blue = colors[1].blue;
116 data->p = None;
117 data->xft_draw = 0;
118 data->p_width = data->p_height = 0;
121 static XftFont*
122 openFont (Widget widget, char *name)
124 char *fname = name;
125 int screen = XScreenNumberOfScreen (XtScreen (widget));
126 int len = strlen (fname), i = len-1;
127 XftFont *fn;
129 /* Try to convert Gtk-syntax (Sans 9) to Xft syntax Sans-9. */
130 while (i > 0 && isdigit (fname[i]))
131 --i;
132 if (fname[i] == ' ')
134 fname = xstrdup (name);
135 fname[i] = '-';
138 fn = XftFontOpenName (XtDisplay (widget), screen, fname);
139 if (fname != name) free (fname);
141 return fn;
144 static int
145 get_text_width_and_height (Widget widget, char *text,
146 XftFont *xft_font,
147 int *height)
149 int w = 0, h = 0;
150 char *bp = text;
152 while (bp && *bp != '\0')
154 XGlyphInfo gi;
155 char *cp = strchr (bp, '\n');
156 XftTextExtentsUtf8 (XtDisplay (widget), xft_font,
157 (FcChar8 *) bp,
158 cp ? cp - bp : strlen (bp),
159 &gi);
160 bp = cp ? cp + 1 : NULL;
161 h += xft_font->height;
162 if (w < gi.width) w = gi.width;
165 *height = h;
166 return w;
169 static void
170 draw_text (struct widget_xft_data *data, char *lbl, int inverse)
172 Screen *sc = XtScreen (data->widget);
173 int screen = XScreenNumberOfScreen (sc);
174 int y = data->xft_font->ascent;
175 int x = inverse ? 0 : 2;
176 char *bp = lbl;
178 data->xft_draw = XftDrawCreate (XtDisplay (data->widget),
179 data->p,
180 DefaultVisual (XtDisplay (data->widget),
181 screen),
182 DefaultColormapOfScreen (sc));
183 XftDrawRect (data->xft_draw,
184 inverse ? &data->xft_fg : &data->xft_bg,
185 0, 0, data->p_width, data->p_height);
187 if (!inverse) y += 2;
188 while (bp && *bp != '\0')
190 char *cp = strchr (bp, '\n');
191 XftDrawStringUtf8 (data->xft_draw,
192 inverse ? &data->xft_bg : &data->xft_fg,
193 data->xft_font, x, y,
194 (FcChar8 *) bp,
195 cp ? cp - bp : strlen (bp));
196 bp = cp ? cp + 1 : NULL;
197 /* 1.2 gives reasonable line spacing. */
198 y += data->xft_font->height * 1.2;
204 static void
205 set_text (struct widget_xft_data *data, Widget toplevel, char *lbl, int margin)
207 int width, height;
209 width = get_text_width_and_height (data->widget, lbl, data->xft_font,
210 &height);
211 data->p_width = width + margin;
212 data->p_height = height + margin;
214 data->p = XCreatePixmap (XtDisplay (data->widget),
215 XtWindow (toplevel),
216 data->p_width,
217 data->p_height,
218 DefaultDepthOfScreen (XtScreen (data->widget)));
219 draw_text (data, lbl, 0);
220 XtVaSetValues (data->widget, XtNbitmap, data->p, NULL);
223 static struct widget_xft_data *
224 find_xft_data (Widget widget)
226 widget_instance *inst = NULL;
227 Widget parent = XtParent (widget);
228 struct widget_xft_data *data = NULL;
229 int nr;
230 while (parent && !inst)
232 inst = lw_get_widget_instance (parent);
233 parent = XtParent (parent);
235 if (!inst || !inst->xft_data || !inst->xft_data[0].xft_font) return 0;
237 for (nr = 0; data == NULL && nr < inst->nr_xft_data; ++nr)
239 if (inst->xft_data[nr].widget == widget)
240 data = &inst->xft_data[nr];
243 return data;
246 static void
247 command_press (Widget widget,
248 XEvent* event,
249 String *params,
250 Cardinal *num_params)
252 struct widget_xft_data *data = find_xft_data (widget);
253 if (data)
255 char *lbl;
256 /* Since this isn't used for rectangle buttons, use it to for armed. */
257 XtVaSetValues (widget, XtNcornerRoundPercent, 1, NULL);
259 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
260 draw_text (data, lbl, 1);
264 static void
265 command_reset (Widget widget,
266 XEvent* event,
267 String *params,
268 Cardinal *num_params)
270 struct widget_xft_data *data = find_xft_data (widget);
271 if (data)
273 Dimension cr;
274 XtVaGetValues (widget, XtNcornerRoundPercent, &cr, NULL);
275 if (cr == 1)
277 char *lbl;
278 XtVaSetValues (widget, XtNcornerRoundPercent, 0, NULL);
279 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
280 draw_text (data, lbl, 0);
286 #endif
288 void
289 xaw_update_one_widget (widget_instance *instance,
290 Widget widget,
291 widget_value *val,
292 Boolean deep_p)
294 if (XtIsSubclass (widget, dialogWidgetClass))
297 #ifdef HAVE_XFT
298 if (instance->xft_data && instance->xft_data[0].xft_font)
300 set_text (&instance->xft_data[0], instance->parent,
301 val->contents->value, 10);
303 #endif
304 XtVaSetValues (widget, XtNlabel, val->contents->value, NULL);
306 else if (XtIsSubclass (widget, commandWidgetClass))
308 Dimension bw = 0;
309 Arg al[10];
310 int ac = 0;
312 XtVaGetValues (widget, XtNborderWidth, &bw, NULL);
313 if (bw == 0)
314 /* Don't let buttons end up with 0 borderwidth, that's ugly...
315 Yeah, all this should really be done through app-defaults files
316 or fallback resources, but that's a whole different can of worms
317 that I don't feel like opening right now. Making Athena widgets
318 not look like shit is just entirely too much work.
321 XtSetArg (al[0], XtNborderWidth, 1);
322 XtSetValues (widget, al, 1);
325 XtSetSensitive (widget, val->enabled);
326 XtSetArg (al[ac], XtNlabel, val->value);ac++;
327 /* Force centered button text. Se above. */
328 XtSetArg (al[ac], XtNjustify, XtJustifyCenter);ac++;
329 #ifdef HAVE_XFT
330 if (instance->xft_data && instance->xft_data[0].xft_font)
332 int th;
333 int nr;
334 for (nr = 0; nr < instance->nr_xft_data; ++nr)
335 if (instance->xft_data[nr].widget == widget)
336 break;
337 if (nr < instance->nr_xft_data)
339 set_text (&instance->xft_data[nr], instance->parent,
340 val->value, 6);
342 /* Must set internalHeight to twice the highlight thickness,
343 or else it gets overwritten by our pixmap. Probably a bug. */
344 XtVaGetValues (widget, XtNhighlightThickness, &th, NULL);
345 XtSetArg (al[ac], XtNinternalHeight, 2*th);ac++;
348 #endif
349 XtSetValues (widget, al, ac);
350 XtRemoveAllCallbacks (widget, XtNcallback);
351 XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance);
355 void
356 xaw_update_one_value (widget_instance *instance,
357 Widget widget,
358 widget_value *val)
360 /* This function is not used by the scrollbars and those are the only
361 Athena widget implemented at the moment so do nothing. */
362 return;
365 void
366 xaw_destroy_instance (widget_instance *instance)
368 #ifdef HAVE_XFT
369 if (instance->xft_data)
371 int i;
372 for (i = 0; i < instance->nr_xft_data; ++i)
374 if (instance->xft_data[i].xft_draw)
375 XftDrawDestroy (instance->xft_data[i].xft_draw);
376 if (instance->xft_data[i].p != None)
378 XtVaSetValues (instance->xft_data[i].widget, XtNbitmap, None,
379 NULL);
380 XFreePixmap (XtDisplay (instance->widget),
381 instance->xft_data[i].p);
384 if (instance->xft_data[0].xft_font)
385 XftFontClose (XtDisplay (instance->widget),
386 instance->xft_data[0].xft_font);
387 free (instance->xft_data);
389 #endif
390 if (XtIsSubclass (instance->widget, dialogWidgetClass))
391 /* Need to destroy the Shell too. */
392 XtDestroyWidget (XtParent (instance->widget));
393 else
394 XtDestroyWidget (instance->widget);
397 void
398 xaw_popup_menu (Widget widget, XEvent *event)
400 /* An Athena menubar has not been implemented. */
401 return;
404 void
405 xaw_pop_instance (widget_instance *instance, Boolean up)
407 Widget widget = instance->widget;
409 if (up)
411 if (XtIsSubclass (widget, dialogWidgetClass))
413 /* For dialogs, we need to call XtPopup on the parent instead
414 of calling XtManageChild on the widget.
415 Also we need to hack the shell's WM_PROTOCOLS to get it to
416 understand what the close box is supposed to do!!
418 Display *dpy = XtDisplay (widget);
419 Widget shell = XtParent (widget);
420 Atom props [2];
421 int i = 0;
422 props [i++] = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
423 XChangeProperty (dpy, XtWindow (shell),
424 XInternAtom (dpy, "WM_PROTOCOLS", False),
425 XA_ATOM, 32, PropModeAppend,
426 (unsigned char *) props, i);
428 /* Center the widget in its parent. Why isn't this kind of crap
429 done automatically? I thought toolkits were supposed to make
430 life easier?
433 unsigned int x, y, w, h;
434 Widget topmost = instance->parent;
435 Arg args[2];
437 w = shell->core.width;
438 h = shell->core.height;
439 while (topmost->core.parent && XtIsRealized (topmost->core.parent))
440 topmost = topmost->core.parent;
441 if (topmost->core.width < w) x = topmost->core.x;
442 else x = topmost->core.x + ((topmost->core.width - w) / 2);
443 if (topmost->core.height < h) y = topmost->core.y;
444 else y = topmost->core.y + ((topmost->core.height - h) / 2);
445 /* Using XtMoveWidget caused the widget to come
446 out in the wrong place with vtwm.
447 Question of virtual vs real coords, perhaps. */
448 XtSetArg (args[0], XtNx, x);
449 XtSetArg (args[1], XtNy, y);
450 XtSetValues (shell, args, 2);
453 /* Finally, pop it up. */
454 XtPopup (shell, XtGrabNonexclusive);
456 else
457 XtManageChild (widget);
459 else
461 if (XtIsSubclass (widget, dialogWidgetClass))
462 XtUnmanageChild (XtParent (widget));
463 else
464 XtUnmanageChild (widget);
469 /* Dialog boxes */
471 static char overrideTrans[] =
472 "<Message>WM_PROTOCOLS: lwlib_delete_dialog()";
473 /* Dialogs pop down on any key press */
474 static char dialogOverride[] =
475 "<KeyPress>Escape: lwlib_delete_dialog()";
476 static void wm_delete_window (Widget w,
477 XEvent *event,
478 String *params,
479 Cardinal *num_params);
480 static XtActionsRec xaw_actions [] = {
481 {"lwlib_delete_dialog", wm_delete_window}
483 static Boolean actions_initted = False;
485 #ifdef HAVE_XFT
486 static XtActionsRec button_actions[] =
488 { "my_reset", command_reset },
489 { "my_press", command_press },
491 char buttonTrans[] =
492 "<Leave>: reset() my_reset()\n"
493 "<Btn1Down>: set() my_press()\n"
494 "<Btn1Up>: my_reset() notify() unset()\n";
495 #endif
497 static Widget
498 make_dialog (char* name,
499 Widget parent,
500 Boolean pop_up_p,
501 char* shell_title,
502 char* icon_name,
503 Boolean text_input_slot,
504 Boolean radio_box,
505 Boolean list,
506 int left_buttons,
507 int right_buttons,
508 widget_instance *instance)
510 Arg av [20];
511 int ac = 0;
512 int i, bc;
513 char button_name [255];
514 Widget shell;
515 Widget dialog;
516 Widget button;
517 XtTranslations override;
518 #ifdef HAVE_XFT
519 XftFont *xft_font = 0;
520 XtTranslations button_override;
521 #endif
523 if (! pop_up_p) abort (); /* not implemented */
524 if (text_input_slot) abort (); /* not implemented */
525 if (radio_box) abort (); /* not implemented */
526 if (list) abort (); /* not implemented */
528 if (! actions_initted)
530 XtAppContext app = XtWidgetToApplicationContext (parent);
531 XtAppAddActions (app, xaw_actions,
532 sizeof (xaw_actions) / sizeof (xaw_actions[0]));
533 #ifdef HAVE_XFT
534 XtAppAddActions (app, button_actions,
535 sizeof (button_actions) / sizeof (button_actions[0]));
536 #endif
537 actions_initted = True;
540 override = XtParseTranslationTable (overrideTrans);
542 ac = 0;
543 XtSetArg (av[ac], XtNtitle, shell_title); ac++;
544 XtSetArg (av[ac], XtNallowShellResize, True); ac++;
546 /* Don't allow any geometry request from the user. */
547 XtSetArg (av[ac], XtNgeometry, 0); ac++;
549 shell = XtCreatePopupShell ("dialog", transientShellWidgetClass,
550 parent, av, ac);
551 XtOverrideTranslations (shell, override);
553 ac = 0;
554 dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac);
555 override = XtParseTranslationTable (dialogOverride);
556 XtOverrideTranslations (dialog, override);
558 #ifdef HAVE_XFT
560 int num;
561 Widget *ch = NULL;
562 Widget w = 0;
563 XtVaGetValues (dialog,
564 XtNnumChildren, &num,
565 XtNchildren, &ch, NULL);
566 for (i = 0; i < num; ++i)
568 if (!XtIsSubclass (ch[i], commandWidgetClass)
569 && XtIsSubclass (ch[i], labelWidgetClass))
571 w = ch[i];
572 break;
575 instance->xft_data = 0;
576 instance->nr_xft_data = 0;
577 if (w)
579 XtResource rec[] =
580 { { "font", "Font", XtRString, sizeof(String), 0, XtRString,
581 (XtPointer)"Sans-10" }};
582 char *fontName = NULL;
583 XtVaGetSubresources (dialog, &fontName, "Dialog", "dialog",
584 rec, 1, (String)NULL);
585 if (fontName)
587 XFontStruct *xfn = XLoadQueryFont (XtDisplay (dialog), fontName);
588 if (!xfn)
589 xft_font = openFont (dialog, fontName);
590 else
591 XFreeFont (XtDisplay (dialog), xfn);
594 if (xft_font)
596 instance->nr_xft_data = left_buttons + right_buttons + 1;
597 instance->xft_data = calloc (instance->nr_xft_data,
598 sizeof(*instance->xft_data));
600 fill_xft_data (&instance->xft_data[0], w, xft_font);
604 button_override = XtParseTranslationTable (buttonTrans);
606 #endif
608 bc = 0;
609 button = 0;
610 for (i = 0; i < left_buttons; i++)
612 ac = 0;
613 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
614 XtSetArg (av [ac], XtNleft, XtChainLeft); ac++;
615 XtSetArg (av [ac], XtNright, XtChainLeft); ac++;
616 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
617 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
618 XtSetArg (av [ac], XtNresizable, True); ac++;
619 #ifdef HAVE_XAW3D
620 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
622 /* Turn of dithered shadow if we can. Looks bad */
623 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
625 #endif
626 sprintf (button_name, "button%d", ++bc);
627 button = XtCreateManagedWidget (button_name, commandWidgetClass,
628 dialog, av, ac);
629 #ifdef HAVE_XFT
630 if (xft_font)
632 fill_xft_data (&instance->xft_data[bc], button, xft_font);
633 XtOverrideTranslations (button, button_override);
635 #endif
638 for (i = 0; i < right_buttons; i++)
640 ac = 0;
641 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
642 if (i == 0)
644 /* Separator to the other buttons. */
645 XtSetArg (av [ac], XtNhorizDistance, 30); ac++;
647 XtSetArg (av [ac], XtNleft, XtChainRight); ac++;
648 XtSetArg (av [ac], XtNright, XtChainRight); ac++;
649 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
650 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
651 XtSetArg (av [ac], XtNresizable, True); ac++;
652 #ifdef HAVE_XAW3D
653 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
655 /* Turn of dithered shadow if we can. Looks bad */
656 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
658 #endif
659 sprintf (button_name, "button%d", ++bc);
660 button = XtCreateManagedWidget (button_name, commandWidgetClass,
661 dialog, av, ac);
662 #ifdef HAVE_XFT
663 if (xft_font)
665 fill_xft_data (&instance->xft_data[bc], button, xft_font);
666 XtOverrideTranslations (button, button_override);
668 #endif
671 return dialog;
674 Widget
675 xaw_create_dialog (widget_instance *instance)
677 char *name = instance->info->type;
678 Widget parent = instance->parent;
679 Widget widget;
680 Boolean pop_up_p = instance->pop_up_p;
681 char *shell_name = 0;
682 char *icon_name = 0;
683 Boolean text_input_slot = False;
684 Boolean radio_box = False;
685 Boolean list = False;
686 int total_buttons;
687 int left_buttons = 0;
688 int right_buttons = 1;
690 switch (name [0]) {
691 case 'E': case 'e':
692 icon_name = "dbox-error";
693 shell_name = "Error";
694 break;
696 case 'I': case 'i':
697 icon_name = "dbox-info";
698 shell_name = "Information";
699 break;
701 case 'L': case 'l':
702 list = True;
703 icon_name = "dbox-question";
704 shell_name = "Prompt";
705 break;
707 case 'P': case 'p':
708 text_input_slot = True;
709 icon_name = "dbox-question";
710 shell_name = "Prompt";
711 break;
713 case 'Q': case 'q':
714 icon_name = "dbox-question";
715 shell_name = "Question";
716 break;
719 total_buttons = name [1] - '0';
721 if (name [3] == 'T' || name [3] == 't')
723 text_input_slot = False;
724 radio_box = True;
726 else if (name [3])
727 right_buttons = name [4] - '0';
729 left_buttons = total_buttons - right_buttons;
731 widget = make_dialog (name, parent, pop_up_p,
732 shell_name, icon_name, text_input_slot, radio_box,
733 list, left_buttons, right_buttons, instance);
734 return widget;
738 static void
739 xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data)
741 widget_instance *instance = (widget_instance *) closure;
742 Widget instance_widget;
743 LWLIB_ID id;
744 XtPointer user_data;
746 lw_internal_update_other_instances (widget, closure, call_data);
748 if (! instance)
749 return;
750 if (widget->core.being_destroyed)
751 return;
753 instance_widget = instance->widget;
754 if (!instance_widget)
755 return;
757 id = instance->info->id;
759 /* Damn! Athena doesn't give us a way to hang our own data on the
760 buttons, so we have to go find it... I guess this assumes that
761 all instances of a button have the same call data. */
763 widget_value *val = instance->info->val->contents;
764 char *name = XtName (widget);
765 while (val)
767 if (val->name && !strcmp (val->name, name))
768 break;
769 val = val->next;
771 if (! val) abort ();
772 user_data = val->call_data;
775 if (instance->info->selection_cb)
776 instance->info->selection_cb (widget, id, user_data);
779 static void
780 wm_delete_window (Widget w,
781 XEvent *event,
782 String *params,
783 Cardinal *num_params)
785 LWLIB_ID id;
786 Cardinal nkids;
787 int i;
788 Widget *kids = 0;
789 Widget widget = 0, shell;
791 if (XtIsSubclass (w, dialogWidgetClass))
792 shell = XtParent (w);
793 else
794 shell = w;
796 if (! XtIsSubclass (shell, shellWidgetClass))
797 abort ();
798 XtVaGetValues (shell, XtNnumChildren, &nkids, NULL);
799 XtVaGetValues (shell, XtNchildren, &kids, NULL);
800 if (!kids || !*kids)
801 abort ();
802 for (i = 0; i < nkids; i++)
804 widget = kids[i];
805 if (XtIsSubclass (widget, dialogWidgetClass))
806 break;
808 if (! widget) return;
810 id = lw_get_widget_id (widget);
811 if (! id) abort ();
814 widget_info *info = lw_get_widget_info (id);
815 if (! info) abort ();
816 if (info->selection_cb)
817 info->selection_cb (widget, id, (XtPointer) -1);
820 lw_destroy_all_widgets (id);
825 static Widget
826 xaw_create_main (widget_instance *instance)
828 Arg al[1];
829 int ac;
831 /* Create a vertical Paned to hold menubar */
832 ac = 0;
833 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
834 return XtCreateWidget (instance->info->name, panedWidgetClass,
835 instance->parent, al, ac);
838 widget_creation_entry
839 xaw_creation_table [] =
841 {"main", xaw_create_main},
842 {NULL, NULL}