; * src/fns.c (Fmake_hash_table): Prefer 'double' to 'float'.
[emacs.git] / lwlib / lwlib-Xaw.c
blobaf57a7fe9101c502314acec48ba89348b4d10f47
1 /* The lwlib interface to Athena widgets.
3 Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
4 Copyright (C) 1994, 2001-2017 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. If not, see <http://www.gnu.org/licenses/>. */
21 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <setjmp.h>
27 #include <lisp.h>
29 #include "lwlib-Xaw.h"
31 #include <X11/StringDefs.h>
32 #include <X11/IntrinsicP.h>
33 #include <X11/CoreP.h>
34 #include <X11/Shell.h>
36 #ifdef HAVE_XAW3D
37 #include <X11/Xaw3d/Scrollbar.h>
38 #include <X11/Xaw3d/Paned.h>
39 #include <X11/Xaw3d/Dialog.h>
40 #include <X11/Xaw3d/Form.h>
41 #include <X11/Xaw3d/Command.h>
42 #include <X11/Xaw3d/Label.h>
43 #else /* !HAVE_XAW3D */
44 #include <X11/Xaw/Scrollbar.h>
45 #include <X11/Xaw/Paned.h>
46 #include <X11/Xaw/Dialog.h>
47 #include <X11/Xaw/Form.h>
48 #include <X11/Xaw/Command.h>
49 #include <X11/Xaw/Label.h>
50 #endif /* HAVE_XAW3D */
52 #include <X11/Xatom.h>
54 #ifdef HAVE_XFT
55 #include <X11/Xft/Xft.h>
57 struct widget_xft_data
59 Widget widget;
60 XftFont *xft_font;
61 XftDraw *xft_draw;
62 XftColor xft_fg, xft_bg;
63 int p_width, p_height;
64 Pixmap p;
68 #endif
70 static void xaw_generic_callback (Widget widget,
71 XtPointer closure,
72 XtPointer call_data);
75 Boolean
76 lw_xaw_widget_p (Widget widget)
78 return (XtIsSubclass (widget, scrollbarWidgetClass) ||
79 XtIsSubclass (widget, dialogWidgetClass));
83 #ifdef HAVE_XFT
84 static void
85 fill_xft_data (struct widget_xft_data *data, Widget widget, XftFont *font)
87 Pixel bg, fg;
88 XColor colors[2];
90 data->widget = widget;
91 data->xft_font = font;
92 XtVaGetValues (widget,
93 XtNbackground, &bg,
94 XtNforeground, &fg,
95 NULL);
97 colors[0].pixel = data->xft_fg.pixel = fg;
98 colors[1].pixel = data->xft_bg.pixel = bg;
99 XQueryColors (XtDisplay (widget),
100 DefaultColormapOfScreen (XtScreen (widget)),
101 colors, 2);
103 data->xft_fg.color.alpha = 0xFFFF;
104 data->xft_fg.color.red = colors[0].red;
105 data->xft_fg.color.green = colors[0].green;
106 data->xft_fg.color.blue = colors[0].blue;
107 data->xft_bg.color.alpha = 0xFFFF;
108 data->xft_bg.color.red = colors[1].red;
109 data->xft_bg.color.green = colors[1].green;
110 data->xft_bg.color.blue = colors[1].blue;
112 data->p = None;
113 data->xft_draw = 0;
114 data->p_width = data->p_height = 0;
117 static XftFont*
118 openFont (Widget widget, char *name)
120 char *fname = name;
121 int screen = XScreenNumberOfScreen (XtScreen (widget));
122 int len = strlen (fname), i = len-1;
123 XftFont *fn;
125 /* Try to convert Gtk-syntax (Sans 9) to Xft syntax Sans-9. */
126 while (i > 0 && '0' <= fname[i] && fname[i] <= '9')
127 --i;
128 if (fname[i] == ' ')
130 fname = xstrdup (name);
131 fname[i] = '-';
134 fn = XftFontOpenName (XtDisplay (widget), screen, fname);
135 if (fname != name) xfree (fname);
137 return fn;
140 static int
141 get_text_width_and_height (Widget widget, char *text,
142 XftFont *xft_font,
143 int *height)
145 int w = 0, h = 0;
146 char *bp = text;
148 while (bp && *bp != '\0')
150 XGlyphInfo gi;
151 char *cp = strchr (bp, '\n');
152 XftTextExtentsUtf8 (XtDisplay (widget), xft_font,
153 (FcChar8 *) bp,
154 cp ? cp - bp : strlen (bp),
155 &gi);
156 bp = cp ? cp + 1 : NULL;
157 h += xft_font->height;
158 if (w < gi.width) w = gi.width;
161 *height = h;
162 return w;
165 static void
166 draw_text (struct widget_xft_data *data, char *lbl, int inverse)
168 Screen *sc = XtScreen (data->widget);
169 int screen = XScreenNumberOfScreen (sc);
170 int y = data->xft_font->ascent;
171 int x = inverse ? 0 : 2;
172 char *bp = lbl;
174 data->xft_draw = XftDrawCreate (XtDisplay (data->widget),
175 data->p,
176 DefaultVisual (XtDisplay (data->widget),
177 screen),
178 DefaultColormapOfScreen (sc));
179 XftDrawRect (data->xft_draw,
180 inverse ? &data->xft_fg : &data->xft_bg,
181 0, 0, data->p_width, data->p_height);
183 if (!inverse) y += 2;
184 while (bp && *bp != '\0')
186 char *cp = strchr (bp, '\n');
187 XftDrawStringUtf8 (data->xft_draw,
188 inverse ? &data->xft_bg : &data->xft_fg,
189 data->xft_font, x, y,
190 (FcChar8 *) bp,
191 cp ? cp - bp : strlen (bp));
192 bp = cp ? cp + 1 : NULL;
193 /* 1.2 gives reasonable line spacing. */
194 y += data->xft_font->height * 1.2;
200 static void
201 set_text (struct widget_xft_data *data, Widget toplevel, char *lbl, int margin)
203 int width, height;
205 width = get_text_width_and_height (data->widget, lbl, data->xft_font,
206 &height);
207 data->p_width = width + margin;
208 data->p_height = height + margin;
210 data->p = XCreatePixmap (XtDisplay (data->widget),
211 XtWindow (toplevel),
212 data->p_width,
213 data->p_height,
214 DefaultDepthOfScreen (XtScreen (data->widget)));
215 draw_text (data, lbl, 0);
216 XtVaSetValues (data->widget, XtNbitmap, data->p, NULL);
219 static struct widget_xft_data *
220 find_xft_data (Widget widget)
222 widget_instance *inst = NULL;
223 Widget parent = XtParent (widget);
224 struct widget_xft_data *data = NULL;
225 int nr;
226 while (parent && !inst)
228 inst = lw_get_widget_instance (parent);
229 parent = XtParent (parent);
231 if (!inst || !inst->xft_data || !inst->xft_data[0].xft_font) return 0;
233 for (nr = 0; data == NULL && nr < inst->nr_xft_data; ++nr)
235 if (inst->xft_data[nr].widget == widget)
236 data = &inst->xft_data[nr];
239 return data;
242 static void
243 command_press (Widget widget,
244 XEvent* event,
245 String *params,
246 Cardinal *num_params)
248 struct widget_xft_data *data = find_xft_data (widget);
249 if (data)
251 char *lbl;
252 /* Since this isn't used for rectangle buttons, use it to for armed. */
253 XtVaSetValues (widget, XtNcornerRoundPercent, 1, NULL);
255 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
256 draw_text (data, lbl, 1);
260 static void
261 command_reset (Widget widget,
262 XEvent* event,
263 String *params,
264 Cardinal *num_params)
266 struct widget_xft_data *data = find_xft_data (widget);
267 if (data)
269 Dimension cr;
270 XtVaGetValues (widget, XtNcornerRoundPercent, &cr, NULL);
271 if (cr == 1)
273 char *lbl;
274 XtVaSetValues (widget, XtNcornerRoundPercent, 0, NULL);
275 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
276 draw_text (data, lbl, 0);
282 #endif
284 void
285 xaw_update_one_widget (widget_instance *instance,
286 Widget widget,
287 widget_value *val,
288 Boolean deep_p)
290 if (XtIsSubclass (widget, dialogWidgetClass))
293 #ifdef HAVE_XFT
294 if (instance->xft_data && instance->xft_data[0].xft_font)
296 set_text (&instance->xft_data[0], instance->parent,
297 val->contents->value, 10);
299 #endif
300 XtVaSetValues (widget, XtNlabel, val->contents->value, NULL);
302 else if (XtIsSubclass (widget, commandWidgetClass))
304 Dimension bw = 0;
305 Arg al[10];
306 int ac = 0;
308 XtVaGetValues (widget, XtNborderWidth, &bw, NULL);
309 if (bw == 0)
310 /* Don't let buttons end up with 0 borderwidth, that's ugly...
311 Yeah, all this should really be done through app-defaults files
312 or fallback resources, but that's a whole different can of worms
313 that I don't feel like opening right now. Making Athena widgets
314 not look like shit is just entirely too much work.
317 XtSetArg (al[0], XtNborderWidth, 1);
318 XtSetValues (widget, al, 1);
321 XtSetSensitive (widget, val->enabled);
322 XtSetArg (al[ac], XtNlabel, val->value);ac++;
323 /* Force centered button text. Se above. */
324 XtSetArg (al[ac], XtNjustify, XtJustifyCenter);ac++;
325 #ifdef HAVE_XFT
326 if (instance->xft_data && instance->xft_data[0].xft_font)
328 int th;
329 int nr;
330 for (nr = 0; nr < instance->nr_xft_data; ++nr)
331 if (instance->xft_data[nr].widget == widget)
332 break;
333 if (nr < instance->nr_xft_data)
335 set_text (&instance->xft_data[nr], instance->parent,
336 val->value, 6);
338 /* Must set internalHeight to twice the highlight thickness,
339 or else it gets overwritten by our pixmap. Probably a bug. */
340 XtVaGetValues (widget, XtNhighlightThickness, &th, NULL);
341 XtSetArg (al[ac], XtNinternalHeight, 2*th);ac++;
344 #endif
345 XtSetValues (widget, al, ac);
346 XtRemoveAllCallbacks (widget, XtNcallback);
347 XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance);
351 void
352 xaw_update_one_value (widget_instance *instance,
353 Widget widget,
354 widget_value *val)
356 /* This function is not used by the scrollbars and those are the only
357 Athena widget implemented at the moment so do nothing. */
358 return;
361 void
362 xaw_destroy_instance (widget_instance *instance)
364 #ifdef HAVE_XFT
365 if (instance->xft_data)
367 int i;
368 for (i = 0; i < instance->nr_xft_data; ++i)
370 if (instance->xft_data[i].xft_draw)
371 XftDrawDestroy (instance->xft_data[i].xft_draw);
372 if (instance->xft_data[i].p != None)
374 XtVaSetValues (instance->xft_data[i].widget, XtNbitmap, None,
375 NULL);
376 XFreePixmap (XtDisplay (instance->widget),
377 instance->xft_data[i].p);
380 if (instance->xft_data[0].xft_font)
381 XftFontClose (XtDisplay (instance->widget),
382 instance->xft_data[0].xft_font);
383 xfree (instance->xft_data);
385 #endif
386 if (XtIsSubclass (instance->widget, dialogWidgetClass))
387 /* Need to destroy the Shell too. */
388 XtDestroyWidget (XtParent (instance->widget));
389 else
390 XtDestroyWidget (instance->widget);
393 void
394 xaw_popup_menu (Widget widget, XEvent *event)
396 /* An Athena menubar has not been implemented. */
397 return;
400 void
401 xaw_pop_instance (widget_instance *instance, Boolean up)
403 Widget widget = instance->widget;
405 if (up)
407 if (XtIsSubclass (widget, dialogWidgetClass))
409 /* For dialogs, we need to call XtPopup on the parent instead
410 of calling XtManageChild on the widget.
411 Also we need to hack the shell's WM_PROTOCOLS to get it to
412 understand what the close box is supposed to do!!
414 Display *dpy = XtDisplay (widget);
415 Widget shell = XtParent (widget);
416 Atom props [2];
417 int i = 0;
418 props [i++] = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
419 XChangeProperty (dpy, XtWindow (shell),
420 XInternAtom (dpy, "WM_PROTOCOLS", False),
421 XA_ATOM, 32, PropModeAppend,
422 (unsigned char *) props, i);
424 /* Center the widget in its parent. Why isn't this kind of crap
425 done automatically? I thought toolkits were supposed to make
426 life easier?
429 unsigned int x, y, w, h;
430 Widget topmost = instance->parent;
431 Arg args[2];
433 w = shell->core.width;
434 h = shell->core.height;
435 while (topmost->core.parent && XtIsRealized (topmost->core.parent))
436 topmost = topmost->core.parent;
437 if (topmost->core.width < w) x = topmost->core.x;
438 else x = topmost->core.x + ((topmost->core.width - w) / 2);
439 if (topmost->core.height < h) y = topmost->core.y;
440 else y = topmost->core.y + ((topmost->core.height - h) / 2);
441 /* Using XtMoveWidget caused the widget to come
442 out in the wrong place with vtwm.
443 Question of virtual vs real coords, perhaps. */
444 XtSetArg (args[0], XtNx, x);
445 XtSetArg (args[1], XtNy, y);
446 XtSetValues (shell, args, 2);
449 /* Finally, pop it up. */
450 XtPopup (shell, XtGrabNonexclusive);
452 else
453 XtManageChild (widget);
455 else
457 if (XtIsSubclass (widget, dialogWidgetClass))
458 XtUnmanageChild (XtParent (widget));
459 else
460 XtUnmanageChild (widget);
465 /* Dialog boxes */
467 static char overrideTrans[] =
468 "<Message>WM_PROTOCOLS: lwlib_delete_dialog()";
469 /* Dialogs pop down on any key press */
470 static char dialogOverride[] =
471 "<KeyPress>Escape: lwlib_delete_dialog()";
472 static void wm_delete_window (Widget w,
473 XEvent *event,
474 String *params,
475 Cardinal *num_params);
476 static XtActionsRec xaw_actions [] = {
477 {"lwlib_delete_dialog", wm_delete_window}
479 static Boolean actions_initted = False;
481 #ifdef HAVE_XFT
482 static XtActionsRec button_actions[] =
484 { "my_reset", command_reset },
485 { "my_press", command_press },
487 char buttonTrans[] =
488 "<Leave>: reset() my_reset()\n"
489 "<Btn1Down>: set() my_press()\n"
490 "<Btn1Up>: my_reset() notify() unset()\n";
491 #endif
493 static Widget
494 make_dialog (char* name,
495 Widget parent,
496 Boolean pop_up_p,
497 char* shell_title,
498 char* icon_name,
499 Boolean text_input_slot,
500 Boolean radio_box,
501 Boolean list,
502 int left_buttons,
503 int right_buttons,
504 widget_instance *instance)
506 Arg av [20];
507 int ac = 0;
508 int i, bc;
509 char button_name [255];
510 Widget shell;
511 Widget dialog;
512 Widget button;
513 XtTranslations override;
514 #ifdef HAVE_XFT
515 XftFont *xft_font = 0;
516 XtTranslations button_override;
517 #endif
519 if (! pop_up_p) abort (); /* not implemented */
520 if (text_input_slot) abort (); /* not implemented */
521 if (radio_box) abort (); /* not implemented */
522 if (list) abort (); /* not implemented */
524 if (! actions_initted)
526 XtAppContext app = XtWidgetToApplicationContext (parent);
527 XtAppAddActions (app, xaw_actions,
528 sizeof (xaw_actions) / sizeof (xaw_actions[0]));
529 #ifdef HAVE_XFT
530 XtAppAddActions (app, button_actions,
531 sizeof (button_actions) / sizeof (button_actions[0]));
532 #endif
533 actions_initted = True;
536 override = XtParseTranslationTable (overrideTrans);
538 ac = 0;
539 XtSetArg (av[ac], XtNtitle, shell_title); ac++;
540 XtSetArg (av[ac], XtNallowShellResize, True); ac++;
542 /* Don't allow any geometry request from the user. */
543 XtSetArg (av[ac], XtNgeometry, 0); ac++;
545 shell = XtCreatePopupShell ("dialog", transientShellWidgetClass,
546 parent, av, ac);
547 XtOverrideTranslations (shell, override);
549 ac = 0;
550 dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac);
551 override = XtParseTranslationTable (dialogOverride);
552 XtOverrideTranslations (dialog, override);
554 #ifdef HAVE_XFT
556 int num;
557 Widget *ch = NULL;
558 Widget w = 0;
559 XtVaGetValues (dialog,
560 XtNnumChildren, &num,
561 XtNchildren, &ch, NULL);
562 for (i = 0; i < num; ++i)
564 if (!XtIsSubclass (ch[i], commandWidgetClass)
565 && XtIsSubclass (ch[i], labelWidgetClass))
567 w = ch[i];
568 break;
571 instance->xft_data = 0;
572 instance->nr_xft_data = 0;
573 if (w)
575 XtResource rec[] =
576 { { "font", "Font", XtRString, sizeof(String), 0, XtRString,
577 (XtPointer)"Sans-10" }};
578 char *fontName = NULL;
579 XtVaGetSubresources (dialog, &fontName, "Dialog", "dialog",
580 rec, 1, (String)NULL);
581 if (fontName)
583 XFontStruct *xfn = XLoadQueryFont (XtDisplay (dialog), fontName);
584 if (!xfn)
585 xft_font = openFont (dialog, fontName);
586 else
587 XFreeFont (XtDisplay (dialog), xfn);
590 if (xft_font)
592 instance->nr_xft_data = left_buttons + right_buttons + 1;
593 instance->xft_data = calloc (instance->nr_xft_data,
594 sizeof(*instance->xft_data));
596 fill_xft_data (&instance->xft_data[0], w, xft_font);
600 button_override = XtParseTranslationTable (buttonTrans);
602 #endif
604 bc = 0;
605 button = 0;
606 for (i = 0; i < left_buttons; i++)
608 ac = 0;
609 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
610 XtSetArg (av [ac], XtNleft, XtChainLeft); ac++;
611 XtSetArg (av [ac], XtNright, XtChainLeft); ac++;
612 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
613 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
614 XtSetArg (av [ac], XtNresizable, True); ac++;
615 #ifdef HAVE_XAW3D
616 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
618 /* Turn of dithered shadow if we can. Looks bad */
619 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
621 #endif
622 sprintf (button_name, "button%d", ++bc);
623 button = XtCreateManagedWidget (button_name, commandWidgetClass,
624 dialog, av, ac);
625 #ifdef HAVE_XFT
626 if (xft_font)
628 fill_xft_data (&instance->xft_data[bc], button, xft_font);
629 XtOverrideTranslations (button, button_override);
631 #endif
634 for (i = 0; i < right_buttons; i++)
636 ac = 0;
637 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
638 if (i == 0)
640 /* Separator to the other buttons. */
641 XtSetArg (av [ac], XtNhorizDistance, 30); ac++;
643 XtSetArg (av [ac], XtNleft, XtChainRight); ac++;
644 XtSetArg (av [ac], XtNright, XtChainRight); ac++;
645 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
646 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
647 XtSetArg (av [ac], XtNresizable, True); ac++;
648 #ifdef HAVE_XAW3D
649 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
651 /* Turn of dithered shadow if we can. Looks bad */
652 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
654 #endif
655 sprintf (button_name, "button%d", ++bc);
656 button = XtCreateManagedWidget (button_name, commandWidgetClass,
657 dialog, av, ac);
658 #ifdef HAVE_XFT
659 if (xft_font)
661 fill_xft_data (&instance->xft_data[bc], button, xft_font);
662 XtOverrideTranslations (button, button_override);
664 #endif
667 return dialog;
670 Widget
671 xaw_create_dialog (widget_instance *instance)
673 char *name = instance->info->type;
674 Widget parent = instance->parent;
675 Widget widget;
676 Boolean pop_up_p = instance->pop_up_p;
677 char *shell_name = 0;
678 char *icon_name = 0;
679 Boolean text_input_slot = False;
680 Boolean radio_box = False;
681 Boolean list = False;
682 int total_buttons;
683 int left_buttons = 0;
684 int right_buttons = 1;
686 switch (name [0]) {
687 case 'E': case 'e':
688 icon_name = "dbox-error";
689 shell_name = "Error";
690 break;
692 case 'I': case 'i':
693 icon_name = "dbox-info";
694 shell_name = "Information";
695 break;
697 case 'L': case 'l':
698 list = True;
699 icon_name = "dbox-question";
700 shell_name = "Prompt";
701 break;
703 case 'P': case 'p':
704 text_input_slot = True;
705 icon_name = "dbox-question";
706 shell_name = "Prompt";
707 break;
709 case 'Q': case 'q':
710 icon_name = "dbox-question";
711 shell_name = "Question";
712 break;
715 total_buttons = name [1] - '0';
717 if (name [3] == 'T' || name [3] == 't')
719 text_input_slot = False;
720 radio_box = True;
722 else if (name [3])
723 right_buttons = name [4] - '0';
725 left_buttons = total_buttons - right_buttons;
727 widget = make_dialog (name, parent, pop_up_p,
728 shell_name, icon_name, text_input_slot, radio_box,
729 list, left_buttons, right_buttons, instance);
730 return widget;
734 static void
735 xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data)
737 widget_instance *instance = (widget_instance *) closure;
738 Widget instance_widget;
739 LWLIB_ID id;
740 XtPointer user_data;
742 lw_internal_update_other_instances (widget, closure, call_data);
744 if (! instance)
745 return;
746 if (widget->core.being_destroyed)
747 return;
749 instance_widget = instance->widget;
750 if (!instance_widget)
751 return;
753 id = instance->info->id;
755 /* Damn! Athena doesn't give us a way to hang our own data on the
756 buttons, so we have to go find it... I guess this assumes that
757 all instances of a button have the same call data. */
759 widget_value *val = instance->info->val->contents;
760 char *name = XtName (widget);
761 while (val)
763 if (val->name && !strcmp (val->name, name))
764 break;
765 val = val->next;
767 if (! val) abort ();
768 user_data = val->call_data;
771 if (instance->info->selection_cb)
772 instance->info->selection_cb (widget, id, user_data);
775 static void
776 wm_delete_window (Widget w,
777 XEvent *event,
778 String *params,
779 Cardinal *num_params)
781 LWLIB_ID id;
782 Cardinal nkids;
783 int i;
784 Widget *kids = 0;
785 Widget widget = 0, shell;
787 if (XtIsSubclass (w, dialogWidgetClass))
788 shell = XtParent (w);
789 else
790 shell = w;
792 if (! XtIsSubclass (shell, shellWidgetClass))
793 abort ();
794 XtVaGetValues (shell, XtNnumChildren, &nkids, NULL);
795 XtVaGetValues (shell, XtNchildren, &kids, NULL);
796 if (!kids || !*kids)
797 abort ();
798 for (i = 0; i < nkids; i++)
800 widget = kids[i];
801 if (XtIsSubclass (widget, dialogWidgetClass))
802 break;
804 if (! widget) return;
806 id = lw_get_widget_id (widget);
807 if (! id) abort ();
810 widget_info *info = lw_get_widget_info (id);
811 if (! info) abort ();
812 if (info->selection_cb)
813 info->selection_cb (widget, id, (XtPointer) -1);
816 lw_destroy_all_widgets (id);
821 static Widget
822 xaw_create_main (widget_instance *instance)
824 Arg al[1];
825 int ac;
827 /* Create a vertical Paned to hold menubar */
828 ac = 0;
829 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
830 return XtCreateWidget (instance->info->name, panedWidgetClass,
831 instance->parent, al, ac);
834 widget_creation_entry
835 xaw_creation_table [] =
837 {"main", xaw_create_main},
838 {NULL, NULL}