rm not definition
[bpt/emacs.git] / lwlib / lwlib-Xaw.c
CommitLineData
b70cfce2 1/* The lwlib interface to Athena widgets.
67f02b82 2
4424d48a 3Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
ba318903 4Copyright (C) 1994, 2001-2014 Free Software Foundation, Inc.
b70cfce2
FP
5
6This file is part of the Lucid Widget Library.
7
177c0ea7 8The Lucid Widget Library is free software; you can redistribute it and/or
b70cfce2
FP
9modify it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 1, or (at your option)
11any later version.
12
13The Lucid Widget Library is distributed in the hope that it will be useful,
177c0ea7 14but WITHOUT ANY WARRANTY; without even the implied warranty of
b70cfce2
FP
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
fee0bd5f 19along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
b70cfce2 20
0f0912e6 21#include <config.h>
0f0912e6 22
b70cfce2 23#include <stdio.h>
d7306fe6 24#include <setjmp.h>
b70cfce2 25
67f02b82 26#include <lisp.h>
2f96293d 27
b70cfce2
FP
28#include "lwlib-Xaw.h"
29
30#include <X11/StringDefs.h>
31#include <X11/IntrinsicP.h>
32#include <X11/CoreP.h>
33#include <X11/Shell.h>
34
5262c5c7
CY
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 */
b70cfce2
FP
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>
5262c5c7 49#endif /* HAVE_XAW3D */
b70cfce2
FP
50
51#include <X11/Xatom.h>
52
1ecb2d3f
JD
53#ifdef HAVE_XFT
54#include <X11/Xft/Xft.h>
55
56struct widget_xft_data
57{
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;
64};
65
66
67#endif
68
c825c0b6
J
69static void xaw_generic_callback (Widget widget,
70 XtPointer closure,
71 XtPointer call_data);
b70cfce2
FP
72
73
74Boolean
c3174d16 75lw_xaw_widget_p (Widget widget)
b70cfce2
FP
76{
77 return (XtIsSubclass (widget, scrollbarWidgetClass) ||
78 XtIsSubclass (widget, dialogWidgetClass));
79}
80
b70cfce2 81
1ecb2d3f
JD
82#ifdef HAVE_XFT
83static void
84fill_xft_data (struct widget_xft_data *data, Widget widget, XftFont *font)
85{
1ecb2d3f
JD
86 Pixel bg, fg;
87 XColor colors[2];
1ecb2d3f 88
c632dfda
JD
89 data->widget = widget;
90 data->xft_font = font;
1ecb2d3f
JD
91 XtVaGetValues (widget,
92 XtNbackground, &bg,
93 XtNforeground, &fg,
94 NULL);
95
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);
101
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;
110
111 data->p = None;
112 data->xft_draw = 0;
113 data->p_width = data->p_height = 0;
114}
115
116static XftFont*
117openFont (Widget widget, char *name)
118{
119 char *fname = name;
120 int screen = XScreenNumberOfScreen (XtScreen (widget));
121 int len = strlen (fname), i = len-1;
122 XftFont *fn;
123
124 /* Try to convert Gtk-syntax (Sans 9) to Xft syntax Sans-9. */
620f13b0 125 while (i > 0 && '0' <= fname[i] && fname[i] <= '9')
1ecb2d3f
JD
126 --i;
127 if (fname[i] == ' ')
128 {
129 fname = xstrdup (name);
130 fname[i] = '-';
131 }
132
133 fn = XftFontOpenName (XtDisplay (widget), screen, fname);
81d40c92 134 if (fname != name) xfree (fname);
1ecb2d3f
JD
135
136 return fn;
137}
138
139static int
140get_text_width_and_height (Widget widget, char *text,
141 XftFont *xft_font,
142 int *height)
143{
144 int w = 0, h = 0;
145 char *bp = text;
cf38a720 146
1ecb2d3f
JD
147 while (bp && *bp != '\0')
148 {
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;
158 }
159
160 *height = h;
161 return w;
162}
163
164static void
165draw_text (struct widget_xft_data *data, char *lbl, int inverse)
166{
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;
172
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);
181
182 if (!inverse) y += 2;
183 while (bp && *bp != '\0')
184 {
185 char *cp = strchr (bp, '\n');
186 XftDrawStringUtf8 (data->xft_draw,
187 inverse ? &data->xft_bg : &data->xft_fg,
e4c8d29a
J
188 data->xft_font, x, y,
189 (FcChar8 *) bp,
190 cp ? cp - bp : strlen (bp));
1ecb2d3f
JD
191 bp = cp ? cp + 1 : NULL;
192 /* 1.2 gives reasonable line spacing. */
193 y += data->xft_font->height * 1.2;
194 }
195
196}
197
198
199static void
200set_text (struct widget_xft_data *data, Widget toplevel, char *lbl, int margin)
201{
1ecb2d3f
JD
202 int width, height;
203
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;
208
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);
216}
217
218static struct widget_xft_data *
219find_xft_data (Widget widget)
220{
221 widget_instance *inst = NULL;
222 Widget parent = XtParent (widget);
223 struct widget_xft_data *data = NULL;
224 int nr;
cf38a720 225 while (parent && !inst)
1ecb2d3f
JD
226 {
227 inst = lw_get_widget_instance (parent);
228 parent = XtParent (parent);
229 }
e4c8d29a 230 if (!inst || !inst->xft_data || !inst->xft_data[0].xft_font) return 0;
1ecb2d3f 231
cf38a720 232 for (nr = 0; data == NULL && nr < inst->nr_xft_data; ++nr)
1ecb2d3f 233 {
cf38a720 234 if (inst->xft_data[nr].widget == widget)
1ecb2d3f
JD
235 data = &inst->xft_data[nr];
236 }
237
238 return data;
239}
240
241static void
242command_press (Widget widget,
243 XEvent* event,
244 String *params,
245 Cardinal *num_params)
246{
247 struct widget_xft_data *data = find_xft_data (widget);
cf38a720 248 if (data)
1ecb2d3f
JD
249 {
250 char *lbl;
251 /* Since this isn't used for rectangle buttons, use it to for armed. */
252 XtVaSetValues (widget, XtNcornerRoundPercent, 1, NULL);
253
254 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
255 draw_text (data, lbl, 1);
256 }
257}
258
259static void
260command_reset (Widget widget,
c825c0b6
J
261 XEvent* event,
262 String *params,
263 Cardinal *num_params)
1ecb2d3f
JD
264{
265 struct widget_xft_data *data = find_xft_data (widget);
cf38a720 266 if (data)
1ecb2d3f
JD
267 {
268 Dimension cr;
269 XtVaGetValues (widget, XtNcornerRoundPercent, &cr, NULL);
cf38a720 270 if (cr == 1)
1ecb2d3f
JD
271 {
272 char *lbl;
273 XtVaSetValues (widget, XtNcornerRoundPercent, 0, NULL);
274 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
275 draw_text (data, lbl, 0);
276 }
277 }
278}
279
280
281#endif
282
b70cfce2 283void
c825c0b6
J
284xaw_update_one_widget (widget_instance *instance,
285 Widget widget,
286 widget_value *val,
287 Boolean deep_p)
b70cfce2 288{
13162c0e 289 if (XtIsSubclass (widget, dialogWidgetClass))
b70cfce2 290 {
1ecb2d3f
JD
291
292#ifdef HAVE_XFT
293 if (instance->xft_data && instance->xft_data[0].xft_font)
294 {
295 set_text (&instance->xft_data[0], instance->parent,
296 val->contents->value, 10);
297 }
298#endif
299 XtVaSetValues (widget, XtNlabel, val->contents->value, NULL);
b70cfce2
FP
300 }
301 else if (XtIsSubclass (widget, commandWidgetClass))
302 {
303 Dimension bw = 0;
1ecb2d3f
JD
304 Arg al[10];
305 int ac = 0;
13162c0e 306
8dd095ee 307 XtVaGetValues (widget, XtNborderWidth, &bw, NULL);
b70cfce2
FP
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.
314 */
13162c0e
RS
315 {
316 XtSetArg (al[0], XtNborderWidth, 1);
317 XtSetValues (widget, al, 1);
318 }
b70cfce2 319
2a73ab60 320 XtSetSensitive (widget, val->enabled);
1ecb2d3f 321 XtSetArg (al[ac], XtNlabel, val->value);ac++;
13162c0e 322 /* Force centered button text. Se above. */
1ecb2d3f
JD
323 XtSetArg (al[ac], XtNjustify, XtJustifyCenter);ac++;
324#ifdef HAVE_XFT
325 if (instance->xft_data && instance->xft_data[0].xft_font)
326 {
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)
333 {
334 set_text (&instance->xft_data[nr], instance->parent,
335 val->value, 6);
336
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++;
341 }
342 }
343#endif
344 XtSetValues (widget, al, ac);
b70cfce2
FP
345 XtRemoveAllCallbacks (widget, XtNcallback);
346 XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance);
347 }
348}
349
350void
c825c0b6
J
351xaw_update_one_value (widget_instance *instance,
352 Widget widget,
353 widget_value *val)
b70cfce2
FP
354{
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;
358}
359
360void
c3174d16 361xaw_destroy_instance (widget_instance *instance)
b70cfce2 362{
1ecb2d3f 363#ifdef HAVE_XFT
cf38a720 364 if (instance->xft_data)
1ecb2d3f
JD
365 {
366 int i;
cf38a720 367 for (i = 0; i < instance->nr_xft_data; ++i)
1ecb2d3f
JD
368 {
369 if (instance->xft_data[i].xft_draw)
370 XftDrawDestroy (instance->xft_data[i].xft_draw);
cf38a720 371 if (instance->xft_data[i].p != None)
1ecb2d3f
JD
372 {
373 XtVaSetValues (instance->xft_data[i].widget, XtNbitmap, None,
374 NULL);
375 XFreePixmap (XtDisplay (instance->widget),
376 instance->xft_data[i].p);
377 }
378 }
379 if (instance->xft_data[0].xft_font)
380 XftFontClose (XtDisplay (instance->widget),
381 instance->xft_data[0].xft_font);
81d40c92 382 xfree (instance->xft_data);
1ecb2d3f
JD
383 }
384#endif
b70cfce2
FP
385 if (XtIsSubclass (instance->widget, dialogWidgetClass))
386 /* Need to destroy the Shell too. */
387 XtDestroyWidget (XtParent (instance->widget));
388 else
389 XtDestroyWidget (instance->widget);
390}
391
392void
c3174d16 393xaw_popup_menu (Widget widget, XEvent *event)
b70cfce2
FP
394{
395 /* An Athena menubar has not been implemented. */
396 return;
397}
398
399void
207c13a7 400xaw_pop_instance (widget_instance *instance, Boolean up)
b70cfce2
FP
401{
402 Widget widget = instance->widget;
403
404 if (up)
405 {
406 if (XtIsSubclass (widget, dialogWidgetClass))
407 {
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!!
412 */
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);
422
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?
426 */
427 {
e363091e 428 unsigned int x, y, w, h;
b70cfce2 429 Widget topmost = instance->parent;
2af91681
PR
430 Arg args[2];
431
b70cfce2
FP
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);
2af91681
PR
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);
b70cfce2
FP
446 }
447
448 /* Finally, pop it up. */
449 XtPopup (shell, XtGrabNonexclusive);
450 }
451 else
452 XtManageChild (widget);
453 }
454 else
455 {
456 if (XtIsSubclass (widget, dialogWidgetClass))
457 XtUnmanageChild (XtParent (widget));
458 else
459 XtUnmanageChild (widget);
460 }
461}
462
463\f
464/* Dialog boxes */
465
466static char overrideTrans[] =
467 "<Message>WM_PROTOCOLS: lwlib_delete_dialog()";
244c93fe
JD
468/* Dialogs pop down on any key press */
469static char dialogOverride[] =
4e6e2184 470 "<KeyPress>Escape: lwlib_delete_dialog()";
e4c8d29a
J
471static void wm_delete_window (Widget w,
472 XEvent *event,
473 String *params,
474 Cardinal *num_params);
b70cfce2
FP
475static XtActionsRec xaw_actions [] = {
476 {"lwlib_delete_dialog", wm_delete_window}
477};
478static Boolean actions_initted = False;
479
1ecb2d3f 480#ifdef HAVE_XFT
cf38a720 481static XtActionsRec button_actions[] =
1ecb2d3f
JD
482 {
483 { "my_reset", command_reset },
484 { "my_press", command_press },
485 };
486char buttonTrans[] =
487 "<Leave>: reset() my_reset()\n"
488 "<Btn1Down>: set() my_press()\n"
489 "<Btn1Up>: my_reset() notify() unset()\n";
490#endif
491
b70cfce2 492static Widget
c825c0b6
J
493make_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)
b70cfce2
FP
504{
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;
1ecb2d3f
JD
513#ifdef HAVE_XFT
514 XftFont *xft_font = 0;
515 XtTranslations button_override;
516#endif
b70cfce2
FP
517
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 */
522
523 if (! actions_initted)
524 {
525 XtAppContext app = XtWidgetToApplicationContext (parent);
526 XtAppAddActions (app, xaw_actions,
527 sizeof (xaw_actions) / sizeof (xaw_actions[0]));
1ecb2d3f
JD
528#ifdef HAVE_XFT
529 XtAppAddActions (app, button_actions,
530 sizeof (button_actions) / sizeof (button_actions[0]));
531#endif
b70cfce2
FP
532 actions_initted = True;
533 }
534
535 override = XtParseTranslationTable (overrideTrans);
536
537 ac = 0;
538 XtSetArg (av[ac], XtNtitle, shell_title); ac++;
539 XtSetArg (av[ac], XtNallowShellResize, True); ac++;
dc49df96
FP
540
541 /* Don't allow any geometry request from the user. */
542 XtSetArg (av[ac], XtNgeometry, 0); ac++;
543
b70cfce2
FP
544 shell = XtCreatePopupShell ("dialog", transientShellWidgetClass,
545 parent, av, ac);
546 XtOverrideTranslations (shell, override);
547
548 ac = 0;
549 dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac);
244c93fe
JD
550 override = XtParseTranslationTable (dialogOverride);
551 XtOverrideTranslations (dialog, override);
b70cfce2 552
1ecb2d3f
JD
553#ifdef HAVE_XFT
554 {
555 int num;
556 Widget *ch = NULL;
557 Widget w = 0;
558 XtVaGetValues (dialog,
559 XtNnumChildren, &num,
560 XtNchildren, &ch, NULL);
cf38a720 561 for (i = 0; i < num; ++i)
1ecb2d3f
JD
562 {
563 if (!XtIsSubclass (ch[i], commandWidgetClass)
564 && XtIsSubclass (ch[i], labelWidgetClass))
565 {
566 w = ch[i];
567 break;
568 }
569 }
570 instance->xft_data = 0;
571 instance->nr_xft_data = 0;
cf38a720 572 if (w)
1ecb2d3f 573 {
cf38a720 574 XtResource rec[] =
3928f2b6
JD
575 { { "font", "Font", XtRString, sizeof(String), 0, XtRString,
576 (XtPointer)"Sans-10" }};
577 char *fontName = NULL;
578 XtVaGetSubresources (dialog, &fontName, "Dialog", "dialog",
41d81b80 579 rec, 1, (String)NULL);
3928f2b6
JD
580 if (fontName)
581 {
582 XFontStruct *xfn = XLoadQueryFont (XtDisplay (dialog), fontName);
583 if (!xfn)
584 xft_font = openFont (dialog, fontName);
585 else
586 XFreeFont (XtDisplay (dialog), xfn);
587 }
cf38a720
PE
588
589 if (xft_font)
1ecb2d3f
JD
590 {
591 instance->nr_xft_data = left_buttons + right_buttons + 1;
592 instance->xft_data = calloc (instance->nr_xft_data,
593 sizeof(*instance->xft_data));
594
595 fill_xft_data (&instance->xft_data[0], w, xft_font);
596 }
597 }
598
599 button_override = XtParseTranslationTable (buttonTrans);
600 }
601#endif
602
b70cfce2
FP
603 bc = 0;
604 button = 0;
605 for (i = 0; i < left_buttons; i++)
606 {
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++;
1ecb2d3f
JD
614#ifdef HAVE_XAW3D
615 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
616 {
617 /* Turn of dithered shadow if we can. Looks bad */
618 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
619 }
620#endif
b70cfce2
FP
621 sprintf (button_name, "button%d", ++bc);
622 button = XtCreateManagedWidget (button_name, commandWidgetClass,
623 dialog, av, ac);
1ecb2d3f
JD
624#ifdef HAVE_XFT
625 if (xft_font)
626 {
627 fill_xft_data (&instance->xft_data[bc], button, xft_font);
628 XtOverrideTranslations (button, button_override);
629 }
630#endif
b70cfce2 631 }
b70cfce2 632
b70cfce2
FP
633 for (i = 0; i < right_buttons; i++)
634 {
635 ac = 0;
636 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
cf38a720 637 if (i == 0)
1ecb2d3f
JD
638 {
639 /* Separator to the other buttons. */
640 XtSetArg (av [ac], XtNhorizDistance, 30); ac++;
641 }
b70cfce2
FP
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++;
1ecb2d3f
JD
647#ifdef HAVE_XAW3D
648 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
649 {
650 /* Turn of dithered shadow if we can. Looks bad */
651 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
652 }
653#endif
b70cfce2
FP
654 sprintf (button_name, "button%d", ++bc);
655 button = XtCreateManagedWidget (button_name, commandWidgetClass,
656 dialog, av, ac);
1ecb2d3f
JD
657#ifdef HAVE_XFT
658 if (xft_font)
659 {
660 fill_xft_data (&instance->xft_data[bc], button, xft_font);
661 XtOverrideTranslations (button, button_override);
662 }
663#endif
b70cfce2
FP
664 }
665
666 return dialog;
667}
668
669Widget
c3174d16 670xaw_create_dialog (widget_instance *instance)
b70cfce2
FP
671{
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;
ca79970e 677 char *icon_name = 0;
b70cfce2
FP
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;
684
685 switch (name [0]) {
686 case 'E': case 'e':
687 icon_name = "dbox-error";
688 shell_name = "Error";
689 break;
690
691 case 'I': case 'i':
692 icon_name = "dbox-info";
693 shell_name = "Information";
694 break;
695
696 case 'L': case 'l':
697 list = True;
698 icon_name = "dbox-question";
699 shell_name = "Prompt";
700 break;
701
702 case 'P': case 'p':
703 text_input_slot = True;
704 icon_name = "dbox-question";
705 shell_name = "Prompt";
706 break;
707
708 case 'Q': case 'q':
709 icon_name = "dbox-question";
710 shell_name = "Question";
711 break;
712 }
177c0ea7 713
b70cfce2
FP
714 total_buttons = name [1] - '0';
715
716 if (name [3] == 'T' || name [3] == 't')
717 {
718 text_input_slot = False;
719 radio_box = True;
720 }
721 else if (name [3])
722 right_buttons = name [4] - '0';
177c0ea7 723
b70cfce2 724 left_buttons = total_buttons - right_buttons;
177c0ea7 725
b70cfce2
FP
726 widget = make_dialog (name, parent, pop_up_p,
727 shell_name, icon_name, text_input_slot, radio_box,
1ecb2d3f 728 list, left_buttons, right_buttons, instance);
b70cfce2
FP
729 return widget;
730}
731
732
733static void
c3174d16 734xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data)
b70cfce2
FP
735{
736 widget_instance *instance = (widget_instance *) closure;
737 Widget instance_widget;
738 LWLIB_ID id;
739 XtPointer user_data;
740
741 lw_internal_update_other_instances (widget, closure, call_data);
742
743 if (! instance)
744 return;
745 if (widget->core.being_destroyed)
746 return;
747
748 instance_widget = instance->widget;
749 if (!instance_widget)
750 return;
751
752 id = instance->info->id;
753
b70cfce2
FP
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. */
757 {
758 widget_value *val = instance->info->val->contents;
759 char *name = XtName (widget);
760 while (val)
761 {
762 if (val->name && !strcmp (val->name, name))
763 break;
764 val = val->next;
765 }
766 if (! val) abort ();
767 user_data = val->call_data;
768 }
b70cfce2
FP
769
770 if (instance->info->selection_cb)
771 instance->info->selection_cb (widget, id, user_data);
772}
773
774static void
e4c8d29a
J
775wm_delete_window (Widget w,
776 XEvent *event,
777 String *params,
778 Cardinal *num_params)
b70cfce2
FP
779{
780 LWLIB_ID id;
8dce2ddc
RS
781 Cardinal nkids;
782 int i;
b70cfce2 783 Widget *kids = 0;
e4c8d29a 784 Widget widget = 0, shell;
244c93fe
JD
785
786 if (XtIsSubclass (w, dialogWidgetClass))
787 shell = XtParent (w);
788 else
789 shell = w;
790
b70cfce2
FP
791 if (! XtIsSubclass (shell, shellWidgetClass))
792 abort ();
8dd095ee
GM
793 XtVaGetValues (shell, XtNnumChildren, &nkids, NULL);
794 XtVaGetValues (shell, XtNchildren, &kids, NULL);
b70cfce2
FP
795 if (!kids || !*kids)
796 abort ();
8dce2ddc
RS
797 for (i = 0; i < nkids; i++)
798 {
799 widget = kids[i];
800 if (XtIsSubclass (widget, dialogWidgetClass))
801 break;
802 }
e4c8d29a
J
803 if (! widget) return;
804
b70cfce2
FP
805 id = lw_get_widget_id (widget);
806 if (! id) abort ();
807
808 {
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);
813 }
814
815 lw_destroy_all_widgets (id);
816}
817
818\f
b70cfce2 819
2af91681 820static Widget
c3174d16 821xaw_create_main (widget_instance *instance)
2af91681
PR
822{
823 Arg al[1];
824 int ac;
825
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);
831}
832
b70cfce2
FP
833widget_creation_entry
834xaw_creation_table [] =
835{
2af91681 836 {"main", xaw_create_main},
b70cfce2
FP
837 {NULL, NULL}
838};