Convert consecutive FSF copyright years to ranges.
[bpt/emacs.git] / lwlib / lwlib-Xaw.c
CommitLineData
b70cfce2 1/* The lwlib interface to Athena widgets.
4424d48a 2Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
73b0cd50 3Copyright (C) 1994, 2001-2011 Free Software Foundation, Inc.
b70cfce2
FP
4
5This file is part of the Lucid Widget Library.
6
177c0ea7 7The Lucid Widget Library is free software; you can redistribute it and/or
b70cfce2
FP
8modify it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 1, or (at your option)
10any later version.
11
12The Lucid Widget Library is distributed in the hope that it will be useful,
177c0ea7 13but WITHOUT ANY WARRANTY; without even the implied warranty of
b70cfce2
FP
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
364c38d3
LK
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA. */
b70cfce2 21
0f0912e6
PE
22#ifdef HAVE_CONFIG_H
23#include <config.h>
24#endif
25
b70cfce2 26#include <stdio.h>
d7306fe6 27#include <setjmp.h>
e4c8d29a 28#include <ctype.h>
b70cfce2 29
2f96293d
RS
30#include "../src/lisp.h"
31
b70cfce2
FP
32#include "lwlib-Xaw.h"
33
34#include <X11/StringDefs.h>
35#include <X11/IntrinsicP.h>
36#include <X11/CoreP.h>
37#include <X11/Shell.h>
38
5262c5c7
CY
39#ifdef HAVE_XAW3D
40#include <X11/Xaw3d/Scrollbar.h>
41#include <X11/Xaw3d/Paned.h>
42#include <X11/Xaw3d/Dialog.h>
43#include <X11/Xaw3d/Form.h>
44#include <X11/Xaw3d/Command.h>
45#include <X11/Xaw3d/Label.h>
46#else /* !HAVE_XAW3D */
b70cfce2
FP
47#include <X11/Xaw/Scrollbar.h>
48#include <X11/Xaw/Paned.h>
49#include <X11/Xaw/Dialog.h>
50#include <X11/Xaw/Form.h>
51#include <X11/Xaw/Command.h>
52#include <X11/Xaw/Label.h>
5262c5c7 53#endif /* HAVE_XAW3D */
b70cfce2
FP
54
55#include <X11/Xatom.h>
56
1ecb2d3f
JD
57#ifdef HAVE_XFT
58#include <X11/Xft/Xft.h>
59
60struct widget_xft_data
61{
62 Widget widget;
63 XftFont *xft_font;
64 XftDraw *xft_draw;
65 XftColor xft_fg, xft_bg;
66 int p_width, p_height;
67 Pixmap p;
68};
69
70
71#endif
72
c825c0b6
J
73static void xaw_generic_callback (Widget widget,
74 XtPointer closure,
75 XtPointer call_data);
b70cfce2
FP
76
77
78Boolean
c3174d16 79lw_xaw_widget_p (Widget widget)
b70cfce2
FP
80{
81 return (XtIsSubclass (widget, scrollbarWidgetClass) ||
82 XtIsSubclass (widget, dialogWidgetClass));
83}
84
b70cfce2 85
1ecb2d3f
JD
86#ifdef HAVE_XFT
87static void
88fill_xft_data (struct widget_xft_data *data, Widget widget, XftFont *font)
89{
1ecb2d3f
JD
90 Pixel bg, fg;
91 XColor colors[2];
1ecb2d3f 92
c632dfda
JD
93 data->widget = widget;
94 data->xft_font = font;
1ecb2d3f
JD
95 XtVaGetValues (widget,
96 XtNbackground, &bg,
97 XtNforeground, &fg,
98 NULL);
99
100 colors[0].pixel = data->xft_fg.pixel = fg;
101 colors[1].pixel = data->xft_bg.pixel = bg;
102 XQueryColors (XtDisplay (widget),
103 DefaultColormapOfScreen (XtScreen (widget)),
104 colors, 2);
105
106 data->xft_fg.color.alpha = 0xFFFF;
107 data->xft_fg.color.red = colors[0].red;
108 data->xft_fg.color.green = colors[0].green;
109 data->xft_fg.color.blue = colors[0].blue;
110 data->xft_bg.color.alpha = 0xFFFF;
111 data->xft_bg.color.red = colors[1].red;
112 data->xft_bg.color.green = colors[1].green;
113 data->xft_bg.color.blue = colors[1].blue;
114
115 data->p = None;
116 data->xft_draw = 0;
117 data->p_width = data->p_height = 0;
118}
119
120static XftFont*
121openFont (Widget widget, char *name)
122{
123 char *fname = name;
124 int screen = XScreenNumberOfScreen (XtScreen (widget));
125 int len = strlen (fname), i = len-1;
126 XftFont *fn;
127
128 /* Try to convert Gtk-syntax (Sans 9) to Xft syntax Sans-9. */
129 while (i > 0 && isdigit (fname[i]))
130 --i;
131 if (fname[i] == ' ')
132 {
133 fname = xstrdup (name);
134 fname[i] = '-';
135 }
136
137 fn = XftFontOpenName (XtDisplay (widget), screen, fname);
138 if (fname != name) free (fname);
139
140 return fn;
141}
142
143static int
144get_text_width_and_height (Widget widget, char *text,
145 XftFont *xft_font,
146 int *height)
147{
148 int w = 0, h = 0;
149 char *bp = text;
150
151 while (bp && *bp != '\0')
152 {
153 XGlyphInfo gi;
154 char *cp = strchr (bp, '\n');
155 XftTextExtentsUtf8 (XtDisplay (widget), xft_font,
156 (FcChar8 *) bp,
157 cp ? cp - bp : strlen (bp),
158 &gi);
159 bp = cp ? cp + 1 : NULL;
160 h += xft_font->height;
161 if (w < gi.width) w = gi.width;
162 }
163
164 *height = h;
165 return w;
166}
167
168static void
169draw_text (struct widget_xft_data *data, char *lbl, int inverse)
170{
171 Screen *sc = XtScreen (data->widget);
172 int screen = XScreenNumberOfScreen (sc);
173 int y = data->xft_font->ascent;
174 int x = inverse ? 0 : 2;
175 char *bp = lbl;
176
177 data->xft_draw = XftDrawCreate (XtDisplay (data->widget),
178 data->p,
179 DefaultVisual (XtDisplay (data->widget),
180 screen),
181 DefaultColormapOfScreen (sc));
182 XftDrawRect (data->xft_draw,
183 inverse ? &data->xft_fg : &data->xft_bg,
184 0, 0, data->p_width, data->p_height);
185
186 if (!inverse) y += 2;
187 while (bp && *bp != '\0')
188 {
189 char *cp = strchr (bp, '\n');
190 XftDrawStringUtf8 (data->xft_draw,
191 inverse ? &data->xft_bg : &data->xft_fg,
e4c8d29a
J
192 data->xft_font, x, y,
193 (FcChar8 *) bp,
194 cp ? cp - bp : strlen (bp));
1ecb2d3f
JD
195 bp = cp ? cp + 1 : NULL;
196 /* 1.2 gives reasonable line spacing. */
197 y += data->xft_font->height * 1.2;
198 }
199
200}
201
202
203static void
204set_text (struct widget_xft_data *data, Widget toplevel, char *lbl, int margin)
205{
1ecb2d3f
JD
206 int width, height;
207
208 width = get_text_width_and_height (data->widget, lbl, data->xft_font,
209 &height);
210 data->p_width = width + margin;
211 data->p_height = height + margin;
212
213 data->p = XCreatePixmap (XtDisplay (data->widget),
214 XtWindow (toplevel),
215 data->p_width,
216 data->p_height,
217 DefaultDepthOfScreen (XtScreen (data->widget)));
218 draw_text (data, lbl, 0);
219 XtVaSetValues (data->widget, XtNbitmap, data->p, NULL);
220}
221
222static struct widget_xft_data *
223find_xft_data (Widget widget)
224{
225 widget_instance *inst = NULL;
226 Widget parent = XtParent (widget);
227 struct widget_xft_data *data = NULL;
228 int nr;
229 while (parent && !inst)
230 {
231 inst = lw_get_widget_instance (parent);
232 parent = XtParent (parent);
233 }
e4c8d29a 234 if (!inst || !inst->xft_data || !inst->xft_data[0].xft_font) return 0;
1ecb2d3f
JD
235
236 for (nr = 0; data == NULL && nr < inst->nr_xft_data; ++nr)
237 {
238 if (inst->xft_data[nr].widget == widget)
239 data = &inst->xft_data[nr];
240 }
241
242 return data;
243}
244
245static void
246command_press (Widget widget,
247 XEvent* event,
248 String *params,
249 Cardinal *num_params)
250{
251 struct widget_xft_data *data = find_xft_data (widget);
252 if (data)
253 {
254 char *lbl;
255 /* Since this isn't used for rectangle buttons, use it to for armed. */
256 XtVaSetValues (widget, XtNcornerRoundPercent, 1, NULL);
257
258 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
259 draw_text (data, lbl, 1);
260 }
261}
262
263static void
264command_reset (Widget widget,
c825c0b6
J
265 XEvent* event,
266 String *params,
267 Cardinal *num_params)
1ecb2d3f
JD
268{
269 struct widget_xft_data *data = find_xft_data (widget);
270 if (data)
271 {
272 Dimension cr;
273 XtVaGetValues (widget, XtNcornerRoundPercent, &cr, NULL);
274 if (cr == 1)
275 {
276 char *lbl;
277 XtVaSetValues (widget, XtNcornerRoundPercent, 0, NULL);
278 XtVaGetValues (widget, XtNlabel, &lbl, NULL);
279 draw_text (data, lbl, 0);
280 }
281 }
282}
283
284
285#endif
286
b70cfce2 287void
c825c0b6
J
288xaw_update_one_widget (widget_instance *instance,
289 Widget widget,
290 widget_value *val,
291 Boolean deep_p)
b70cfce2 292{
13162c0e 293 if (XtIsSubclass (widget, dialogWidgetClass))
b70cfce2 294 {
1ecb2d3f
JD
295
296#ifdef HAVE_XFT
297 if (instance->xft_data && instance->xft_data[0].xft_font)
298 {
299 set_text (&instance->xft_data[0], instance->parent,
300 val->contents->value, 10);
301 }
302#endif
303 XtVaSetValues (widget, XtNlabel, val->contents->value, NULL);
b70cfce2
FP
304 }
305 else if (XtIsSubclass (widget, commandWidgetClass))
306 {
307 Dimension bw = 0;
1ecb2d3f
JD
308 Arg al[10];
309 int ac = 0;
13162c0e 310
8dd095ee 311 XtVaGetValues (widget, XtNborderWidth, &bw, NULL);
b70cfce2
FP
312 if (bw == 0)
313 /* Don't let buttons end up with 0 borderwidth, that's ugly...
314 Yeah, all this should really be done through app-defaults files
315 or fallback resources, but that's a whole different can of worms
316 that I don't feel like opening right now. Making Athena widgets
317 not look like shit is just entirely too much work.
318 */
13162c0e
RS
319 {
320 XtSetArg (al[0], XtNborderWidth, 1);
321 XtSetValues (widget, al, 1);
322 }
b70cfce2 323
2a73ab60 324 XtSetSensitive (widget, val->enabled);
1ecb2d3f 325 XtSetArg (al[ac], XtNlabel, val->value);ac++;
13162c0e 326 /* Force centered button text. Se above. */
1ecb2d3f
JD
327 XtSetArg (al[ac], XtNjustify, XtJustifyCenter);ac++;
328#ifdef HAVE_XFT
329 if (instance->xft_data && instance->xft_data[0].xft_font)
330 {
331 int th;
332 int nr;
333 for (nr = 0; nr < instance->nr_xft_data; ++nr)
334 if (instance->xft_data[nr].widget == widget)
335 break;
336 if (nr < instance->nr_xft_data)
337 {
338 set_text (&instance->xft_data[nr], instance->parent,
339 val->value, 6);
340
341 /* Must set internalHeight to twice the highlight thickness,
342 or else it gets overwritten by our pixmap. Probably a bug. */
343 XtVaGetValues (widget, XtNhighlightThickness, &th, NULL);
344 XtSetArg (al[ac], XtNinternalHeight, 2*th);ac++;
345 }
346 }
347#endif
348 XtSetValues (widget, al, ac);
b70cfce2
FP
349 XtRemoveAllCallbacks (widget, XtNcallback);
350 XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance);
351 }
352}
353
354void
c825c0b6
J
355xaw_update_one_value (widget_instance *instance,
356 Widget widget,
357 widget_value *val)
b70cfce2
FP
358{
359 /* This function is not used by the scrollbars and those are the only
360 Athena widget implemented at the moment so do nothing. */
361 return;
362}
363
364void
c3174d16 365xaw_destroy_instance (widget_instance *instance)
b70cfce2 366{
1ecb2d3f
JD
367#ifdef HAVE_XFT
368 if (instance->xft_data)
369 {
370 int i;
371 for (i = 0; i < instance->nr_xft_data; ++i)
372 {
373 if (instance->xft_data[i].xft_draw)
374 XftDrawDestroy (instance->xft_data[i].xft_draw);
375 if (instance->xft_data[i].p != None)
376 {
377 XtVaSetValues (instance->xft_data[i].widget, XtNbitmap, None,
378 NULL);
379 XFreePixmap (XtDisplay (instance->widget),
380 instance->xft_data[i].p);
381 }
382 }
383 if (instance->xft_data[0].xft_font)
384 XftFontClose (XtDisplay (instance->widget),
385 instance->xft_data[0].xft_font);
386 free (instance->xft_data);
387 }
388#endif
b70cfce2
FP
389 if (XtIsSubclass (instance->widget, dialogWidgetClass))
390 /* Need to destroy the Shell too. */
391 XtDestroyWidget (XtParent (instance->widget));
392 else
393 XtDestroyWidget (instance->widget);
394}
395
396void
c3174d16 397xaw_popup_menu (Widget widget, XEvent *event)
b70cfce2
FP
398{
399 /* An Athena menubar has not been implemented. */
400 return;
401}
402
403void
207c13a7 404xaw_pop_instance (widget_instance *instance, Boolean up)
b70cfce2
FP
405{
406 Widget widget = instance->widget;
407
408 if (up)
409 {
410 if (XtIsSubclass (widget, dialogWidgetClass))
411 {
412 /* For dialogs, we need to call XtPopup on the parent instead
413 of calling XtManageChild on the widget.
414 Also we need to hack the shell's WM_PROTOCOLS to get it to
415 understand what the close box is supposed to do!!
416 */
417 Display *dpy = XtDisplay (widget);
418 Widget shell = XtParent (widget);
419 Atom props [2];
420 int i = 0;
421 props [i++] = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
422 XChangeProperty (dpy, XtWindow (shell),
423 XInternAtom (dpy, "WM_PROTOCOLS", False),
424 XA_ATOM, 32, PropModeAppend,
425 (unsigned char *) props, i);
426
427 /* Center the widget in its parent. Why isn't this kind of crap
428 done automatically? I thought toolkits were supposed to make
429 life easier?
430 */
431 {
e363091e 432 unsigned int x, y, w, h;
b70cfce2 433 Widget topmost = instance->parent;
2af91681
PR
434 Arg args[2];
435
b70cfce2
FP
436 w = shell->core.width;
437 h = shell->core.height;
438 while (topmost->core.parent && XtIsRealized (topmost->core.parent))
439 topmost = topmost->core.parent;
440 if (topmost->core.width < w) x = topmost->core.x;
441 else x = topmost->core.x + ((topmost->core.width - w) / 2);
442 if (topmost->core.height < h) y = topmost->core.y;
443 else y = topmost->core.y + ((topmost->core.height - h) / 2);
2af91681
PR
444 /* Using XtMoveWidget caused the widget to come
445 out in the wrong place with vtwm.
446 Question of virtual vs real coords, perhaps. */
447 XtSetArg (args[0], XtNx, x);
448 XtSetArg (args[1], XtNy, y);
449 XtSetValues (shell, args, 2);
b70cfce2
FP
450 }
451
452 /* Finally, pop it up. */
453 XtPopup (shell, XtGrabNonexclusive);
454 }
455 else
456 XtManageChild (widget);
457 }
458 else
459 {
460 if (XtIsSubclass (widget, dialogWidgetClass))
461 XtUnmanageChild (XtParent (widget));
462 else
463 XtUnmanageChild (widget);
464 }
465}
466
467\f
468/* Dialog boxes */
469
470static char overrideTrans[] =
471 "<Message>WM_PROTOCOLS: lwlib_delete_dialog()";
244c93fe
JD
472/* Dialogs pop down on any key press */
473static char dialogOverride[] =
4e6e2184 474 "<KeyPress>Escape: lwlib_delete_dialog()";
e4c8d29a
J
475static void wm_delete_window (Widget w,
476 XEvent *event,
477 String *params,
478 Cardinal *num_params);
b70cfce2
FP
479static XtActionsRec xaw_actions [] = {
480 {"lwlib_delete_dialog", wm_delete_window}
481};
482static Boolean actions_initted = False;
483
1ecb2d3f
JD
484#ifdef HAVE_XFT
485static XtActionsRec button_actions[] =
486 {
487 { "my_reset", command_reset },
488 { "my_press", command_press },
489 };
490char buttonTrans[] =
491 "<Leave>: reset() my_reset()\n"
492 "<Btn1Down>: set() my_press()\n"
493 "<Btn1Up>: my_reset() notify() unset()\n";
494#endif
495
b70cfce2 496static Widget
c825c0b6
J
497make_dialog (char* name,
498 Widget parent,
499 Boolean pop_up_p,
500 char* shell_title,
501 char* icon_name,
502 Boolean text_input_slot,
503 Boolean radio_box,
504 Boolean list,
505 int left_buttons,
506 int right_buttons,
507 widget_instance *instance)
b70cfce2
FP
508{
509 Arg av [20];
510 int ac = 0;
511 int i, bc;
512 char button_name [255];
513 Widget shell;
514 Widget dialog;
515 Widget button;
516 XtTranslations override;
1ecb2d3f
JD
517#ifdef HAVE_XFT
518 XftFont *xft_font = 0;
519 XtTranslations button_override;
520#endif
b70cfce2
FP
521
522 if (! pop_up_p) abort (); /* not implemented */
523 if (text_input_slot) abort (); /* not implemented */
524 if (radio_box) abort (); /* not implemented */
525 if (list) abort (); /* not implemented */
526
527 if (! actions_initted)
528 {
529 XtAppContext app = XtWidgetToApplicationContext (parent);
530 XtAppAddActions (app, xaw_actions,
531 sizeof (xaw_actions) / sizeof (xaw_actions[0]));
1ecb2d3f
JD
532#ifdef HAVE_XFT
533 XtAppAddActions (app, button_actions,
534 sizeof (button_actions) / sizeof (button_actions[0]));
535#endif
b70cfce2
FP
536 actions_initted = True;
537 }
538
539 override = XtParseTranslationTable (overrideTrans);
540
541 ac = 0;
542 XtSetArg (av[ac], XtNtitle, shell_title); ac++;
543 XtSetArg (av[ac], XtNallowShellResize, True); ac++;
dc49df96
FP
544
545 /* Don't allow any geometry request from the user. */
546 XtSetArg (av[ac], XtNgeometry, 0); ac++;
547
b70cfce2
FP
548 shell = XtCreatePopupShell ("dialog", transientShellWidgetClass,
549 parent, av, ac);
550 XtOverrideTranslations (shell, override);
551
552 ac = 0;
553 dialog = XtCreateManagedWidget (name, dialogWidgetClass, shell, av, ac);
244c93fe
JD
554 override = XtParseTranslationTable (dialogOverride);
555 XtOverrideTranslations (dialog, override);
b70cfce2 556
1ecb2d3f
JD
557#ifdef HAVE_XFT
558 {
559 int num;
560 Widget *ch = NULL;
561 Widget w = 0;
562 XtVaGetValues (dialog,
563 XtNnumChildren, &num,
564 XtNchildren, &ch, NULL);
565 for (i = 0; i < num; ++i)
566 {
567 if (!XtIsSubclass (ch[i], commandWidgetClass)
568 && XtIsSubclass (ch[i], labelWidgetClass))
569 {
570 w = ch[i];
571 break;
572 }
573 }
574 instance->xft_data = 0;
575 instance->nr_xft_data = 0;
576 if (w)
577 {
578 XtResource rec[] =
579 { { "faceName", "FaceName", XtRString, sizeof(String), 0, XtRString,
580 (XtPointer)"Sans-14" }};
581 char *faceName;
582 XtVaGetSubresources (dialog, &faceName, "Dialog", "dialog",
41d81b80 583 rec, 1, (String)NULL);
1ecb2d3f
JD
584 if (strcmp ("none", faceName) != 0)
585 xft_font = openFont (dialog, faceName);
586 if (xft_font)
587 {
588 instance->nr_xft_data = left_buttons + right_buttons + 1;
589 instance->xft_data = calloc (instance->nr_xft_data,
590 sizeof(*instance->xft_data));
591
592 fill_xft_data (&instance->xft_data[0], w, xft_font);
593 }
594 }
595
596 button_override = XtParseTranslationTable (buttonTrans);
597 }
598#endif
599
b70cfce2
FP
600 bc = 0;
601 button = 0;
602 for (i = 0; i < left_buttons; i++)
603 {
604 ac = 0;
605 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
606 XtSetArg (av [ac], XtNleft, XtChainLeft); ac++;
607 XtSetArg (av [ac], XtNright, XtChainLeft); ac++;
608 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
609 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
610 XtSetArg (av [ac], XtNresizable, True); ac++;
1ecb2d3f
JD
611#ifdef HAVE_XAW3D
612 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
613 {
614 /* Turn of dithered shadow if we can. Looks bad */
615 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
616 }
617#endif
b70cfce2
FP
618 sprintf (button_name, "button%d", ++bc);
619 button = XtCreateManagedWidget (button_name, commandWidgetClass,
620 dialog, av, ac);
1ecb2d3f
JD
621#ifdef HAVE_XFT
622 if (xft_font)
623 {
624 fill_xft_data (&instance->xft_data[bc], button, xft_font);
625 XtOverrideTranslations (button, button_override);
626 }
627#endif
b70cfce2 628 }
b70cfce2 629
b70cfce2
FP
630 for (i = 0; i < right_buttons; i++)
631 {
632 ac = 0;
633 XtSetArg (av [ac], XtNfromHoriz, button); ac++;
1ecb2d3f
JD
634 if (i == 0)
635 {
636 /* Separator to the other buttons. */
637 XtSetArg (av [ac], XtNhorizDistance, 30); ac++;
638 }
b70cfce2
FP
639 XtSetArg (av [ac], XtNleft, XtChainRight); ac++;
640 XtSetArg (av [ac], XtNright, XtChainRight); ac++;
641 XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
642 XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
643 XtSetArg (av [ac], XtNresizable, True); ac++;
1ecb2d3f
JD
644#ifdef HAVE_XAW3D
645 if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
646 {
647 /* Turn of dithered shadow if we can. Looks bad */
648 XtSetArg (av [ac], "beNiceToColormap", False); ac++;
649 }
650#endif
b70cfce2
FP
651 sprintf (button_name, "button%d", ++bc);
652 button = XtCreateManagedWidget (button_name, commandWidgetClass,
653 dialog, av, ac);
1ecb2d3f
JD
654#ifdef HAVE_XFT
655 if (xft_font)
656 {
657 fill_xft_data (&instance->xft_data[bc], button, xft_font);
658 XtOverrideTranslations (button, button_override);
659 }
660#endif
b70cfce2
FP
661 }
662
663 return dialog;
664}
665
666Widget
c3174d16 667xaw_create_dialog (widget_instance *instance)
b70cfce2
FP
668{
669 char *name = instance->info->type;
670 Widget parent = instance->parent;
671 Widget widget;
672 Boolean pop_up_p = instance->pop_up_p;
673 char *shell_name = 0;
ca79970e 674 char *icon_name = 0;
b70cfce2
FP
675 Boolean text_input_slot = False;
676 Boolean radio_box = False;
677 Boolean list = False;
678 int total_buttons;
679 int left_buttons = 0;
680 int right_buttons = 1;
681
682 switch (name [0]) {
683 case 'E': case 'e':
684 icon_name = "dbox-error";
685 shell_name = "Error";
686 break;
687
688 case 'I': case 'i':
689 icon_name = "dbox-info";
690 shell_name = "Information";
691 break;
692
693 case 'L': case 'l':
694 list = True;
695 icon_name = "dbox-question";
696 shell_name = "Prompt";
697 break;
698
699 case 'P': case 'p':
700 text_input_slot = True;
701 icon_name = "dbox-question";
702 shell_name = "Prompt";
703 break;
704
705 case 'Q': case 'q':
706 icon_name = "dbox-question";
707 shell_name = "Question";
708 break;
709 }
177c0ea7 710
b70cfce2
FP
711 total_buttons = name [1] - '0';
712
713 if (name [3] == 'T' || name [3] == 't')
714 {
715 text_input_slot = False;
716 radio_box = True;
717 }
718 else if (name [3])
719 right_buttons = name [4] - '0';
177c0ea7 720
b70cfce2 721 left_buttons = total_buttons - right_buttons;
177c0ea7 722
b70cfce2
FP
723 widget = make_dialog (name, parent, pop_up_p,
724 shell_name, icon_name, text_input_slot, radio_box,
1ecb2d3f 725 list, left_buttons, right_buttons, instance);
b70cfce2
FP
726 return widget;
727}
728
729
730static void
c3174d16 731xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data)
b70cfce2
FP
732{
733 widget_instance *instance = (widget_instance *) closure;
734 Widget instance_widget;
735 LWLIB_ID id;
736 XtPointer user_data;
737
738 lw_internal_update_other_instances (widget, closure, call_data);
739
740 if (! instance)
741 return;
742 if (widget->core.being_destroyed)
743 return;
744
745 instance_widget = instance->widget;
746 if (!instance_widget)
747 return;
748
749 id = instance->info->id;
750
b70cfce2
FP
751 /* Damn! Athena doesn't give us a way to hang our own data on the
752 buttons, so we have to go find it... I guess this assumes that
753 all instances of a button have the same call data. */
754 {
755 widget_value *val = instance->info->val->contents;
756 char *name = XtName (widget);
757 while (val)
758 {
759 if (val->name && !strcmp (val->name, name))
760 break;
761 val = val->next;
762 }
763 if (! val) abort ();
764 user_data = val->call_data;
765 }
b70cfce2
FP
766
767 if (instance->info->selection_cb)
768 instance->info->selection_cb (widget, id, user_data);
769}
770
771static void
e4c8d29a
J
772wm_delete_window (Widget w,
773 XEvent *event,
774 String *params,
775 Cardinal *num_params)
b70cfce2
FP
776{
777 LWLIB_ID id;
8dce2ddc
RS
778 Cardinal nkids;
779 int i;
b70cfce2 780 Widget *kids = 0;
e4c8d29a 781 Widget widget = 0, shell;
244c93fe
JD
782
783 if (XtIsSubclass (w, dialogWidgetClass))
784 shell = XtParent (w);
785 else
786 shell = w;
787
b70cfce2
FP
788 if (! XtIsSubclass (shell, shellWidgetClass))
789 abort ();
8dd095ee
GM
790 XtVaGetValues (shell, XtNnumChildren, &nkids, NULL);
791 XtVaGetValues (shell, XtNchildren, &kids, NULL);
b70cfce2
FP
792 if (!kids || !*kids)
793 abort ();
8dce2ddc
RS
794 for (i = 0; i < nkids; i++)
795 {
796 widget = kids[i];
797 if (XtIsSubclass (widget, dialogWidgetClass))
798 break;
799 }
e4c8d29a
J
800 if (! widget) return;
801
b70cfce2
FP
802 id = lw_get_widget_id (widget);
803 if (! id) abort ();
804
805 {
806 widget_info *info = lw_get_widget_info (id);
807 if (! info) abort ();
808 if (info->selection_cb)
809 info->selection_cb (widget, id, (XtPointer) -1);
810 }
811
812 lw_destroy_all_widgets (id);
813}
814
815\f
b70cfce2 816
2af91681 817static Widget
c3174d16 818xaw_create_main (widget_instance *instance)
2af91681
PR
819{
820 Arg al[1];
821 int ac;
822
823 /* Create a vertical Paned to hold menubar */
824 ac = 0;
825 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
826 return XtCreateWidget (instance->info->name, panedWidgetClass,
827 instance->parent, al, ac);
828}
829
b70cfce2
FP
830widget_creation_entry
831xaw_creation_table [] =
832{
2af91681 833 {"main", xaw_create_main},
b70cfce2
FP
834 {NULL, NULL}
835};
ab5796a9 836