Update copyright year to 2014 by running admin/update-copyright.
[emacs.git] / lwlib / lwlib-Xaw.c
blob11eefd92c0420f021332ab592688af69e341223f
1 /* The lwlib interface to Athena widgets.
3 Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
4 Copyright (C) 1994, 2001-2014 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 <setjmp.h>
26 #include <lisp.h>
28 #include "lwlib-Xaw.h"
30 #include <X11/StringDefs.h>
31 #include <X11/IntrinsicP.h>
32 #include <X11/CoreP.h>
33 #include <X11/Shell.h>
35 #ifdef HAVE_XAW3D
36 #include <X11/Xaw3d/Scrollbar.h>
37 #include <X11/Xaw3d/Paned.h>
38 #include <X11/Xaw3d/Dialog.h>
39 #include <X11/Xaw3d/Form.h>
40 #include <X11/Xaw3d/Command.h>
41 #include <X11/Xaw3d/Label.h>
42 #else /* !HAVE_XAW3D */
43 #include <X11/Xaw/Scrollbar.h>
44 #include <X11/Xaw/Paned.h>
45 #include <X11/Xaw/Dialog.h>
46 #include <X11/Xaw/Form.h>
47 #include <X11/Xaw/Command.h>
48 #include <X11/Xaw/Label.h>
49 #endif /* HAVE_XAW3D */
51 #include <X11/Xatom.h>
53 #ifdef HAVE_XFT
54 #include <X11/Xft/Xft.h>
56 struct widget_xft_data
58 Widget widget;
59 XftFont *xft_font;
60 XftDraw *xft_draw;
61 XftColor xft_fg, xft_bg;
62 int p_width, p_height;
63 Pixmap p;
67 #endif
69 static void xaw_generic_callback (Widget widget,
70 XtPointer closure,
71 XtPointer call_data);
74 Boolean
75 lw_xaw_widget_p (Widget widget)
77 return (XtIsSubclass (widget, scrollbarWidgetClass) ||
78 XtIsSubclass (widget, dialogWidgetClass));
82 #ifdef HAVE_XFT
83 static void
84 fill_xft_data (struct widget_xft_data *data, Widget widget, XftFont *font)
86 Pixel bg, fg;
87 XColor colors[2];
89 data->widget = widget;
90 data->xft_font = font;
91 XtVaGetValues (widget,
92 XtNbackground, &bg,
93 XtNforeground, &fg,
94 NULL);
96 colors[0].pixel = data->xft_fg.pixel = fg;
97 colors[1].pixel = data->xft_bg.pixel = bg;
98 XQueryColors (XtDisplay (widget),
99 DefaultColormapOfScreen (XtScreen (widget)),
100 colors, 2);
102 data->xft_fg.color.alpha = 0xFFFF;
103 data->xft_fg.color.red = colors[0].red;
104 data->xft_fg.color.green = colors[0].green;
105 data->xft_fg.color.blue = colors[0].blue;
106 data->xft_bg.color.alpha = 0xFFFF;
107 data->xft_bg.color.red = colors[1].red;
108 data->xft_bg.color.green = colors[1].green;
109 data->xft_bg.color.blue = colors[1].blue;
111 data->p = None;
112 data->xft_draw = 0;
113 data->p_width = data->p_height = 0;
116 static XftFont*
117 openFont (Widget widget, char *name)
119 char *fname = name;
120 int screen = XScreenNumberOfScreen (XtScreen (widget));
121 int len = strlen (fname), i = len-1;
122 XftFont *fn;
124 /* Try to convert Gtk-syntax (Sans 9) to Xft syntax Sans-9. */
125 while (i > 0 && '0' <= fname[i] && fname[i] <= '9')
126 --i;
127 if (fname[i] == ' ')
129 fname = xstrdup (name);
130 fname[i] = '-';
133 fn = XftFontOpenName (XtDisplay (widget), screen, fname);
134 if (fname != name) xfree (fname);
136 return fn;
139 static int
140 get_text_width_and_height (Widget widget, char *text,
141 XftFont *xft_font,
142 int *height)
144 int w = 0, h = 0;
145 char *bp = text;
147 while (bp && *bp != '\0')
149 XGlyphInfo gi;
150 char *cp = strchr (bp, '\n');
151 XftTextExtentsUtf8 (XtDisplay (widget), xft_font,
152 (FcChar8 *) bp,
153 cp ? cp - bp : strlen (bp),
154 &gi);
155 bp = cp ? cp + 1 : NULL;
156 h += xft_font->height;
157 if (w < gi.width) w = gi.width;
160 *height = h;
161 return w;
164 static void
165 draw_text (struct widget_xft_data *data, char *lbl, int inverse)
167 Screen *sc = XtScreen (data->widget);
168 int screen = XScreenNumberOfScreen (sc);
169 int y = data->xft_font->ascent;
170 int x = inverse ? 0 : 2;
171 char *bp = lbl;
173 data->xft_draw = XftDrawCreate (XtDisplay (data->widget),
174 data->p,
175 DefaultVisual (XtDisplay (data->widget),
176 screen),
177 DefaultColormapOfScreen (sc));
178 XftDrawRect (data->xft_draw,
179 inverse ? &data->xft_fg : &data->xft_bg,
180 0, 0, data->p_width, data->p_height);
182 if (!inverse) y += 2;
183 while (bp && *bp != '\0')
185 char *cp = strchr (bp, '\n');
186 XftDrawStringUtf8 (data->xft_draw,
187 inverse ? &data->xft_bg : &data->xft_fg,
188 data->xft_font, x, y,
189 (FcChar8 *) bp,
190 cp ? cp - bp : strlen (bp));
191 bp = cp ? cp + 1 : NULL;
192 /* 1.2 gives reasonable line spacing. */
193 y += data->xft_font->height * 1.2;
199 static void
200 set_text (struct widget_xft_data *data, Widget toplevel, char *lbl, int margin)
202 int width, height;
204 width = get_text_width_and_height (data->widget, lbl, data->xft_font,
205 &height);
206 data->p_width = width + margin;
207 data->p_height = height + margin;
209 data->p = XCreatePixmap (XtDisplay (data->widget),
210 XtWindow (toplevel),
211 data->p_width,
212 data->p_height,
213 DefaultDepthOfScreen (XtScreen (data->widget)));
214 draw_text (data, lbl, 0);
215 XtVaSetValues (data->widget, XtNbitmap, data->p, NULL);
218 static struct widget_xft_data *
219 find_xft_data (Widget widget)
221 widget_instance *inst = NULL;
222 Widget parent = XtParent (widget);
223 struct widget_xft_data *data = NULL;
224 int nr;
225 while (parent && !inst)
227 inst = lw_get_widget_instance (parent);
228 parent = XtParent (parent);
230 if (!inst || !inst->xft_data || !inst->xft_data[0].xft_font) return 0;
232 for (nr = 0; data == NULL && nr < inst->nr_xft_data; ++nr)
234 if (inst->xft_data[nr].widget == widget)
235 data = &inst->xft_data[nr];
238 return data;
241 static void
242 command_press (Widget widget,
243 XEvent* event,
244 String *params,
245 Cardinal *num_params)
247 struct widget_xft_data *data = find_xft_data (widget);
248 if (data)
250 char *lbl;
251 /* Since this isn't used for rectangle buttons, use it to for armed. */
252 XtVaSetValues (widget, XtNcornerRoundPercent, 1, NULL);
254 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
255 draw_text (data, lbl, 1);
259 static void
260 command_reset (Widget widget,
261 XEvent* event,
262 String *params,
263 Cardinal *num_params)
265 struct widget_xft_data *data = find_xft_data (widget);
266 if (data)
268 Dimension cr;
269 XtVaGetValues (widget, XtNcornerRoundPercent, &cr, NULL);
270 if (cr == 1)
272 char *lbl;
273 XtVaSetValues (widget, XtNcornerRoundPercent, 0, NULL);
274 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
275 draw_text (data, lbl, 0);
281 #endif
283 void
284 xaw_update_one_widget (widget_instance *instance,
285 Widget widget,
286 widget_value *val,
287 Boolean deep_p)
289 if (XtIsSubclass (widget, dialogWidgetClass))
292 #ifdef HAVE_XFT
293 if (instance->xft_data && instance->xft_data[0].xft_font)
295 set_text (&instance->xft_data[0], instance->parent,
296 val->contents->value, 10);
298 #endif
299 XtVaSetValues (widget, XtNlabel, val->contents->value, NULL);
301 else if (XtIsSubclass (widget, commandWidgetClass))
303 Dimension bw = 0;
304 Arg al[10];
305 int ac = 0;
307 XtVaGetValues (widget, XtNborderWidth, &bw, NULL);
308 if (bw == 0)
309 /* Don't let buttons end up with 0 borderwidth, that's ugly...
310 Yeah, all this should really be done through app-defaults files
311 or fallback resources, but that's a whole different can of worms
312 that I don't feel like opening right now. Making Athena widgets
313 not look like shit is just entirely too much work.
316 XtSetArg (al[0], XtNborderWidth, 1);
317 XtSetValues (widget, al, 1);
320 XtSetSensitive (widget, val->enabled);
321 XtSetArg (al[ac], XtNlabel, val->value);ac++;
322 /* Force centered button text. Se above. */
323 XtSetArg (al[ac], XtNjustify, XtJustifyCenter);ac++;
324 #ifdef HAVE_XFT
325 if (instance->xft_data && instance->xft_data[0].xft_font)
327 int th;
328 int nr;
329 for (nr = 0; nr < instance->nr_xft_data; ++nr)
330 if (instance->xft_data[nr].widget == widget)
331 break;
332 if (nr < instance->nr_xft_data)
334 set_text (&instance->xft_data[nr], instance->parent,
335 val->value, 6);
337 /* Must set internalHeight to twice the highlight thickness,
338 or else it gets overwritten by our pixmap. Probably a bug. */
339 XtVaGetValues (widget, XtNhighlightThickness, &th, NULL);
340 XtSetArg (al[ac], XtNinternalHeight, 2*th);ac++;
343 #endif
344 XtSetValues (widget, al, ac);
345 XtRemoveAllCallbacks (widget, XtNcallback);
346 XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance);
350 void
351 xaw_update_one_value (widget_instance *instance,
352 Widget widget,
353 widget_value *val)
355 /* This function is not used by the scrollbars and those are the only
356 Athena widget implemented at the moment so do nothing. */
357 return;
360 void
361 xaw_destroy_instance (widget_instance *instance)
363 #ifdef HAVE_XFT
364 if (instance->xft_data)
366 int i;
367 for (i = 0; i < instance->nr_xft_data; ++i)
369 if (instance->xft_data[i].xft_draw)
370 XftDrawDestroy (instance->xft_data[i].xft_draw);
371 if (instance->xft_data[i].p != None)
373 XtVaSetValues (instance->xft_data[i].widget, XtNbitmap, None,
374 NULL);
375 XFreePixmap (XtDisplay (instance->widget),
376 instance->xft_data[i].p);
379 if (instance->xft_data[0].xft_font)
380 XftFontClose (XtDisplay (instance->widget),
381 instance->xft_data[0].xft_font);
382 xfree (instance->xft_data);
384 #endif
385 if (XtIsSubclass (instance->widget, dialogWidgetClass))
386 /* Need to destroy the Shell too. */
387 XtDestroyWidget (XtParent (instance->widget));
388 else
389 XtDestroyWidget (instance->widget);
392 void
393 xaw_popup_menu (Widget widget, XEvent *event)
395 /* An Athena menubar has not been implemented. */
396 return;
399 void
400 xaw_pop_instance (widget_instance *instance, Boolean up)
402 Widget widget = instance->widget;
404 if (up)
406 if (XtIsSubclass (widget, dialogWidgetClass))
408 /* For dialogs, we need to call XtPopup on the parent instead
409 of calling XtManageChild on the widget.
410 Also we need to hack the shell's WM_PROTOCOLS to get it to
411 understand what the close box is supposed to do!!
413 Display *dpy = XtDisplay (widget);
414 Widget shell = XtParent (widget);
415 Atom props [2];
416 int i = 0;
417 props [i++] = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
418 XChangeProperty (dpy, XtWindow (shell),
419 XInternAtom (dpy, "WM_PROTOCOLS", False),
420 XA_ATOM, 32, PropModeAppend,
421 (unsigned char *) props, i);
423 /* Center the widget in its parent. Why isn't this kind of crap
424 done automatically? I thought toolkits were supposed to make
425 life easier?
428 unsigned int x, y, w, h;
429 Widget topmost = instance->parent;
430 Arg args[2];
432 w = shell->core.width;
433 h = shell->core.height;
434 while (topmost->core.parent && XtIsRealized (topmost->core.parent))
435 topmost = topmost->core.parent;
436 if (topmost->core.width < w) x = topmost->core.x;
437 else x = topmost->core.x + ((topmost->core.width - w) / 2);
438 if (topmost->core.height < h) y = topmost->core.y;
439 else y = topmost->core.y + ((topmost->core.height - h) / 2);
440 /* Using XtMoveWidget caused the widget to come
441 out in the wrong place with vtwm.
442 Question of virtual vs real coords, perhaps. */
443 XtSetArg (args[0], XtNx, x);
444 XtSetArg (args[1], XtNy, y);
445 XtSetValues (shell, args, 2);
448 /* Finally, pop it up. */
449 XtPopup (shell, XtGrabNonexclusive);
451 else
452 XtManageChild (widget);
454 else
456 if (XtIsSubclass (widget, dialogWidgetClass))
457 XtUnmanageChild (XtParent (widget));
458 else
459 XtUnmanageChild (widget);
464 /* Dialog boxes */
466 static char overrideTrans[] =
467 "<Message>WM_PROTOCOLS: lwlib_delete_dialog()";
468 /* Dialogs pop down on any key press */
469 static char dialogOverride[] =
470 "<KeyPress>Escape: lwlib_delete_dialog()";
471 static void wm_delete_window (Widget w,
472 XEvent *event,
473 String *params,
474 Cardinal *num_params);
475 static XtActionsRec xaw_actions [] = {
476 {"lwlib_delete_dialog", wm_delete_window}
478 static Boolean actions_initted = False;
480 #ifdef HAVE_XFT
481 static XtActionsRec button_actions[] =
483 { "my_reset", command_reset },
484 { "my_press", command_press },
486 char buttonTrans[] =
487 "<Leave>: reset() my_reset()\n"
488 "<Btn1Down>: set() my_press()\n"
489 "<Btn1Up>: my_reset() notify() unset()\n";
490 #endif
492 static Widget
493 make_dialog (char* name,
494 Widget parent,
495 Boolean pop_up_p,
496 char* shell_title,
497 char* icon_name,
498 Boolean text_input_slot,
499 Boolean radio_box,
500 Boolean list,
501 int left_buttons,
502 int right_buttons,
503 widget_instance *instance)
505 Arg av [20];
506 int ac = 0;
507 int i, bc;
508 char button_name [255];
509 Widget shell;
510 Widget dialog;
511 Widget button;
512 XtTranslations override;
513 #ifdef HAVE_XFT
514 XftFont *xft_font = 0;
515 XtTranslations button_override;
516 #endif
518 if (! pop_up_p) abort (); /* not implemented */
519 if (text_input_slot) abort (); /* not implemented */
520 if (radio_box) abort (); /* not implemented */
521 if (list) abort (); /* not implemented */
523 if (! actions_initted)
525 XtAppContext app = XtWidgetToApplicationContext (parent);
526 XtAppAddActions (app, xaw_actions,
527 sizeof (xaw_actions) / sizeof (xaw_actions[0]));
528 #ifdef HAVE_XFT
529 XtAppAddActions (app, button_actions,
530 sizeof (button_actions) / sizeof (button_actions[0]));
531 #endif
532 actions_initted = True;
535 override = XtParseTranslationTable (overrideTrans);
537 ac = 0;
538 XtSetArg (av[ac], XtNtitle, shell_title); ac++;
539 XtSetArg (av[ac], XtNallowShellResize, True); ac++;
541 /* Don't allow any geometry request from the user. */
542 XtSetArg (av[ac], XtNgeometry, 0); ac++;
544 shell = XtCreatePopupShell ("dialog", transientShellWidgetClass,
545 parent, av, ac);
546 XtOverrideTranslations (shell, override);
548 ac = 0;
549 dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac);
550 override = XtParseTranslationTable (dialogOverride);
551 XtOverrideTranslations (dialog, override);
553 #ifdef HAVE_XFT
555 int num;
556 Widget *ch = NULL;
557 Widget w = 0;
558 XtVaGetValues (dialog,
559 XtNnumChildren, &num,
560 XtNchildren, &ch, NULL);
561 for (i = 0; i < num; ++i)
563 if (!XtIsSubclass (ch[i], commandWidgetClass)
564 && XtIsSubclass (ch[i], labelWidgetClass))
566 w = ch[i];
567 break;
570 instance->xft_data = 0;
571 instance->nr_xft_data = 0;
572 if (w)
574 XtResource rec[] =
575 { { "font", "Font", XtRString, sizeof(String), 0, XtRString,
576 (XtPointer)"Sans-10" }};
577 char *fontName = NULL;
578 XtVaGetSubresources (dialog, &fontName, "Dialog", "dialog",
579 rec, 1, (String)NULL);
580 if (fontName)
582 XFontStruct *xfn = XLoadQueryFont (XtDisplay (dialog), fontName);
583 if (!xfn)
584 xft_font = openFont (dialog, fontName);
585 else
586 XFreeFont (XtDisplay (dialog), xfn);
589 if (xft_font)
591 instance->nr_xft_data = left_buttons + right_buttons + 1;
592 instance->xft_data = calloc (instance->nr_xft_data,
593 sizeof(*instance->xft_data));
595 fill_xft_data (&instance->xft_data[0], w, xft_font);
599 button_override = XtParseTranslationTable (buttonTrans);
601 #endif
603 bc = 0;
604 button = 0;
605 for (i = 0; i < left_buttons; i++)
607 ac = 0;
608 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
609 XtSetArg (av [ac], XtNleft, XtChainLeft); ac++;
610 XtSetArg (av [ac], XtNright, XtChainLeft); ac++;
611 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
612 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
613 XtSetArg (av [ac], XtNresizable, True); ac++;
614 #ifdef HAVE_XAW3D
615 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
617 /* Turn of dithered shadow if we can. Looks bad */
618 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
620 #endif
621 sprintf (button_name, "button%d", ++bc);
622 button = XtCreateManagedWidget (button_name, commandWidgetClass,
623 dialog, av, ac);
624 #ifdef HAVE_XFT
625 if (xft_font)
627 fill_xft_data (&instance->xft_data[bc], button, xft_font);
628 XtOverrideTranslations (button, button_override);
630 #endif
633 for (i = 0; i < right_buttons; i++)
635 ac = 0;
636 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
637 if (i == 0)
639 /* Separator to the other buttons. */
640 XtSetArg (av [ac], XtNhorizDistance, 30); ac++;
642 XtSetArg (av [ac], XtNleft, XtChainRight); ac++;
643 XtSetArg (av [ac], XtNright, XtChainRight); ac++;
644 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
645 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
646 XtSetArg (av [ac], XtNresizable, True); ac++;
647 #ifdef HAVE_XAW3D
648 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
650 /* Turn of dithered shadow if we can. Looks bad */
651 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
653 #endif
654 sprintf (button_name, "button%d", ++bc);
655 button = XtCreateManagedWidget (button_name, commandWidgetClass,
656 dialog, av, ac);
657 #ifdef HAVE_XFT
658 if (xft_font)
660 fill_xft_data (&instance->xft_data[bc], button, xft_font);
661 XtOverrideTranslations (button, button_override);
663 #endif
666 return dialog;
669 Widget
670 xaw_create_dialog (widget_instance *instance)
672 char *name = instance->info->type;
673 Widget parent = instance->parent;
674 Widget widget;
675 Boolean pop_up_p = instance->pop_up_p;
676 char *shell_name = 0;
677 char *icon_name = 0;
678 Boolean text_input_slot = False;
679 Boolean radio_box = False;
680 Boolean list = False;
681 int total_buttons;
682 int left_buttons = 0;
683 int right_buttons = 1;
685 switch (name [0]) {
686 case 'E': case 'e':
687 icon_name = "dbox-error";
688 shell_name = "Error";
689 break;
691 case 'I': case 'i':
692 icon_name = "dbox-info";
693 shell_name = "Information";
694 break;
696 case 'L': case 'l':
697 list = True;
698 icon_name = "dbox-question";
699 shell_name = "Prompt";
700 break;
702 case 'P': case 'p':
703 text_input_slot = True;
704 icon_name = "dbox-question";
705 shell_name = "Prompt";
706 break;
708 case 'Q': case 'q':
709 icon_name = "dbox-question";
710 shell_name = "Question";
711 break;
714 total_buttons = name [1] - '0';
716 if (name [3] == 'T' || name [3] == 't')
718 text_input_slot = False;
719 radio_box = True;
721 else if (name [3])
722 right_buttons = name [4] - '0';
724 left_buttons = total_buttons - right_buttons;
726 widget = make_dialog (name, parent, pop_up_p,
727 shell_name, icon_name, text_input_slot, radio_box,
728 list, left_buttons, right_buttons, instance);
729 return widget;
733 static void
734 xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data)
736 widget_instance *instance = (widget_instance *) closure;
737 Widget instance_widget;
738 LWLIB_ID id;
739 XtPointer user_data;
741 lw_internal_update_other_instances (widget, closure, call_data);
743 if (! instance)
744 return;
745 if (widget->core.being_destroyed)
746 return;
748 instance_widget = instance->widget;
749 if (!instance_widget)
750 return;
752 id = instance->info->id;
754 /* Damn! Athena doesn't give us a way to hang our own data on the
755 buttons, so we have to go find it... I guess this assumes that
756 all instances of a button have the same call data. */
758 widget_value *val = instance->info->val->contents;
759 char *name = XtName (widget);
760 while (val)
762 if (val->name && !strcmp (val->name, name))
763 break;
764 val = val->next;
766 if (! val) abort ();
767 user_data = val->call_data;
770 if (instance->info->selection_cb)
771 instance->info->selection_cb (widget, id, user_data);
774 static void
775 wm_delete_window (Widget w,
776 XEvent *event,
777 String *params,
778 Cardinal *num_params)
780 LWLIB_ID id;
781 Cardinal nkids;
782 int i;
783 Widget *kids = 0;
784 Widget widget = 0, shell;
786 if (XtIsSubclass (w, dialogWidgetClass))
787 shell = XtParent (w);
788 else
789 shell = w;
791 if (! XtIsSubclass (shell, shellWidgetClass))
792 abort ();
793 XtVaGetValues (shell, XtNnumChildren, &nkids, NULL);
794 XtVaGetValues (shell, XtNchildren, &kids, NULL);
795 if (!kids || !*kids)
796 abort ();
797 for (i = 0; i < nkids; i++)
799 widget = kids[i];
800 if (XtIsSubclass (widget, dialogWidgetClass))
801 break;
803 if (! widget) return;
805 id = lw_get_widget_id (widget);
806 if (! id) abort ();
809 widget_info *info = lw_get_widget_info (id);
810 if (! info) abort ();
811 if (info->selection_cb)
812 info->selection_cb (widget, id, (XtPointer) -1);
815 lw_destroy_all_widgets (id);
820 static Widget
821 xaw_create_main (widget_instance *instance)
823 Arg al[1];
824 int ac;
826 /* Create a vertical Paned to hold menubar */
827 ac = 0;
828 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
829 return XtCreateWidget (instance->info->name, panedWidgetClass,
830 instance->parent, al, ac);
833 widget_creation_entry
834 xaw_creation_table [] =
836 {"main", xaw_create_main},
837 {NULL, NULL}