root/lwlib/lwlib-Xaw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lw_xaw_widget_p
  2. fill_xft_data
  3. destroy_xft_data
  4. openFont
  5. get_text_width_and_height
  6. draw_text
  7. set_text
  8. find_xft_data
  9. command_press
  10. command_reset
  11. xaw_update_one_widget
  12. xaw_update_one_value
  13. xaw_destroy_instance
  14. xaw_popup_menu
  15. xaw_pop_instance
  16. make_dialog
  17. xaw_create_dialog
  18. xaw_generic_callback
  19. wm_delete_window
  20. xaw_create_main

     1 /* The lwlib interface to Athena widgets.
     2 
     3 Copyright (C) 1993 Chuck Thompson <cthomp@cs.uiuc.edu>
     4 Copyright (C) 1994, 2001-2023 Free Software Foundation, Inc.
     5 
     6 This file is part of the Lucid Widget Library.
     7 
     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.
    12 
    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.
    17 
    18 You should have received a copy of the GNU General Public License
    19 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    20 
    21 #include <config.h>
    22 
    23 #include <stdio.h>
    24 #include <setjmp.h>
    25 
    26 #include <lisp.h>
    27 
    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 
    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 */
    50 
    51 #include <X11/Xatom.h>
    52 
    53 #if defined USE_CAIRO || defined HAVE_XFT
    54 #ifdef USE_CAIRO
    55 #include <stdlib.h>
    56 #include "lwlib-utils.h"
    57 #else  /* HAVE_XFT */
    58 #include <X11/Xft/Xft.h>
    59 #endif
    60 
    61 struct widget_xft_data
    62 {
    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;
    69 };
    70 
    71 
    72 #endif
    73 
    74 static void xaw_generic_callback (Widget widget,
    75                                   XtPointer closure,
    76                                   XtPointer call_data);
    77 
    78 
    79 Boolean
    80 lw_xaw_widget_p (Widget widget)
    81 {
    82   return (XtIsSubclass (widget, scrollbarWidgetClass) ||
    83           XtIsSubclass (widget, dialogWidgetClass));
    84 }
    85 
    86 
    87 #if defined USE_CAIRO || defined HAVE_XFT
    88 static void
    89 fill_xft_data (struct widget_xft_data *data, Widget widget, XftFont *font)
    90 {
    91   Pixel bg, fg;
    92   XColor colors[2];
    93 
    94   data->widget = widget;
    95   data->xft_font = font;
    96   XtVaGetValues (widget,
    97                  XtNbackground, &bg,
    98                  XtNforeground, &fg,
    99                  NULL);
   100 
   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);
   106 
   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;
   115 
   116   data->p = None;
   117   data->xft_draw = 0;
   118   data->p_width = data->p_height = 0;
   119 }
   120 
   121 static void
   122 destroy_xft_data (Widget widget, XtPointer closure, XtPointer call_data)
   123 {
   124   struct widget_xft_data *xft_data = closure;
   125 
   126   for (int i = 0; xft_data[i].widget; ++i)
   127     {
   128       if (xft_data[i].xft_draw)
   129         XftDrawDestroy (xft_data[i].xft_draw);
   130       if (xft_data[i].p != None)
   131         XFreePixmap (XtDisplay (widget), xft_data[i].p);
   132     }
   133   if (xft_data[0].xft_font)
   134     XftFontClose (XtDisplay (widget), xft_data[0].xft_font);
   135   xfree (xft_data);
   136 }
   137 
   138 static XftFont*
   139 openFont (Widget widget, char *name)
   140 {
   141   char *fname = name;
   142   int screen = XScreenNumberOfScreen (XtScreen (widget));
   143   int len = strlen (fname), i = len-1;
   144   XftFont *fn;
   145 
   146   /* Try to convert Gtk-syntax (Sans 9) to Xft syntax Sans-9.  */
   147   while (i > 0 && '0' <= fname[i] && fname[i] <= '9')
   148     --i;
   149   if (fname[i] == ' ')
   150     {
   151       fname = xstrdup (name);
   152       fname[i] = '-';
   153     }
   154 
   155   fn = XftFontOpenName (XtDisplay (widget), screen, fname);
   156   if (fname != name) xfree (fname);
   157 
   158   return fn;
   159 }
   160 
   161 static int
   162 get_text_width_and_height (Widget widget, char *text,
   163                            XftFont *xft_font,
   164                            int *height)
   165 {
   166   int w = 0, h = 0;
   167   char *bp = text;
   168 
   169   while (bp && *bp != '\0')
   170     {
   171       XGlyphInfo gi;
   172       char *cp = strchr (bp, '\n');
   173       XftTextExtentsUtf8 (XtDisplay (widget), xft_font,
   174                           (FcChar8 *) bp,
   175                           cp ? cp - bp : strlen (bp),
   176                           &gi);
   177       bp = cp ? cp + 1 : NULL;
   178       h += xft_font->height;
   179       if (w < gi.xOff) w = gi.xOff;
   180     }
   181 
   182   *height = h;
   183   return w;
   184 }
   185 
   186 static void
   187 draw_text (struct widget_xft_data *data, char *lbl, int inverse)
   188 {
   189   Screen *sc = XtScreen (data->widget);
   190   int screen = XScreenNumberOfScreen (sc);
   191   int y = data->xft_font->ascent;
   192   int x = inverse ? 0 : 2;
   193   char *bp = lbl;
   194 
   195   if (!data->xft_draw)
   196     data->xft_draw = XftDrawCreate (XtDisplay (data->widget),
   197                                     data->p,
   198                                     DefaultVisual (XtDisplay (data->widget),
   199                                                    screen),
   200                                     DefaultColormapOfScreen (sc));
   201   XftDrawRect (data->xft_draw,
   202                inverse ? &data->xft_fg : &data->xft_bg,
   203                0, 0, data->p_width, data->p_height);
   204 
   205   if (!inverse) y += 2;
   206   while (bp && *bp != '\0')
   207     {
   208       char *cp = strchr (bp, '\n');
   209       XftDrawStringUtf8 (data->xft_draw,
   210                          inverse ? &data->xft_bg : &data->xft_fg,
   211                          data->xft_font, x, y,
   212                          (FcChar8 *) bp,
   213                          cp ? cp - bp : strlen (bp));
   214       bp = cp ? cp + 1 : NULL;
   215       /* 1.2 gives reasonable line spacing.  */
   216       y += data->xft_font->height * 1.2;
   217     }
   218 #ifdef USE_CAIRO
   219   cairo_surface_flush (cairo_get_target (data->xft_draw));
   220 #endif
   221 
   222 }
   223 
   224 
   225 static void
   226 set_text (struct widget_xft_data *data, Widget toplevel, char *lbl, int margin)
   227 {
   228   int width, height;
   229 
   230   width = get_text_width_and_height (data->widget, lbl, data->xft_font,
   231                                      &height);
   232   data->p_width = width + margin;
   233   data->p_height = height + margin;
   234 
   235   data->p = XCreatePixmap (XtDisplay (data->widget),
   236                            XtWindow (toplevel),
   237                            data->p_width,
   238                            data->p_height,
   239                            DefaultDepthOfScreen (XtScreen (data->widget)));
   240   draw_text (data, lbl, 0);
   241   XtVaSetValues (data->widget, XtNbitmap, data->p, NULL);
   242 }
   243 
   244 static struct widget_xft_data *
   245 find_xft_data (Widget widget)
   246 {
   247   widget_instance *inst = NULL;
   248   Widget parent = XtParent (widget);
   249   struct widget_xft_data *data = NULL;
   250   int nr;
   251   while (parent && !inst)
   252     {
   253       inst = lw_get_widget_instance (parent);
   254       parent = XtParent (parent);
   255     }
   256   if (!inst || !inst->xft_data || !inst->xft_data[0].xft_font) return 0;
   257 
   258   for (nr = 0; data == NULL && inst->xft_data[nr].widget; ++nr)
   259     {
   260       if (inst->xft_data[nr].widget == widget)
   261         data = &inst->xft_data[nr];
   262     }
   263 
   264   return data;
   265 }
   266 
   267 static void
   268 command_press (Widget widget,
   269                XEvent* event,
   270                String *params,
   271                Cardinal *num_params)
   272 {
   273   struct widget_xft_data *data = find_xft_data (widget);
   274   if (data)
   275     {
   276       char *lbl;
   277       /* Since this isn't used for rectangle buttons, use it to for armed.  */
   278       XtVaSetValues (widget, XtNcornerRoundPercent, 1, NULL);
   279 
   280       XtVaGetValues (widget, XtNlabel, &lbl, NULL);
   281       draw_text (data, lbl, 1);
   282     }
   283 }
   284 
   285 static void
   286 command_reset (Widget widget,
   287                XEvent* event,
   288                String *params,
   289                Cardinal *num_params)
   290 {
   291   struct widget_xft_data *data = find_xft_data (widget);
   292   if (data)
   293     {
   294       Dimension cr;
   295       XtVaGetValues (widget, XtNcornerRoundPercent, &cr, NULL);
   296       if (cr == 1)
   297         {
   298           char *lbl;
   299           XtVaSetValues (widget, XtNcornerRoundPercent, 0, NULL);
   300           XtVaGetValues (widget, XtNlabel, &lbl, NULL);
   301           draw_text (data, lbl, 0);
   302         }
   303     }
   304 }
   305 
   306 
   307 #endif
   308 
   309 void
   310 xaw_update_one_widget (widget_instance *instance,
   311                        Widget widget,
   312                        widget_value *val,
   313                        Boolean deep_p)
   314 {
   315   if (XtIsSubclass (widget, dialogWidgetClass))
   316     {
   317 
   318 #if defined USE_CAIRO || defined HAVE_XFT
   319       if (instance->xft_data && instance->xft_data[0].xft_font)
   320         {
   321           set_text (&instance->xft_data[0], instance->parent,
   322                     val->contents->value, 10);
   323         }
   324 #endif
   325       XtVaSetValues (widget, XtNlabel, val->contents->value, NULL);
   326     }
   327   else if (XtIsSubclass (widget, commandWidgetClass))
   328     {
   329       Dimension bw = 0;
   330       Arg al[10];
   331       int ac = 0;
   332 
   333       XtVaGetValues (widget, XtNborderWidth, &bw, NULL);
   334       if (bw == 0)
   335         /* Don't let buttons end up with 0 borderwidth, that's ugly...
   336            Yeah, all this should really be done through app-defaults files
   337            or fallback resources, but that's a whole different can of worms
   338            that I don't feel like opening right now.  Making Athena widgets
   339            not look like shit is just entirely too much work.
   340          */
   341         {
   342           XtSetArg (al[0], XtNborderWidth, 1);
   343           XtSetValues (widget, al, 1);
   344         }
   345 
   346       XtSetSensitive (widget, val->enabled);
   347       XtSetArg (al[ac], XtNlabel, val->value);ac++;
   348       /* Force centered button text.  Se above. */
   349       XtSetArg (al[ac], XtNjustify, XtJustifyCenter);ac++;
   350 #if defined USE_CAIRO || defined HAVE_XFT
   351       if (instance->xft_data && instance->xft_data[0].xft_font)
   352         {
   353           int th;
   354           int nr;
   355           for (nr = 0; instance->xft_data[nr].widget; ++nr)
   356             if (instance->xft_data[nr].widget == widget)
   357               break;
   358           if (instance->xft_data[nr].widget)
   359             {
   360               set_text (&instance->xft_data[nr], instance->parent,
   361                         val->value, 6);
   362 
   363               /* Must set internalHeight to twice the highlight thickness,
   364                  or else it gets overwritten by our pixmap.  Probably a bug.  */
   365               XtVaGetValues (widget, XtNhighlightThickness, &th, NULL);
   366               XtSetArg (al[ac], XtNinternalHeight, 2*th);ac++;
   367             }
   368         }
   369 #endif
   370       XtSetValues (widget, al, ac);
   371       XtRemoveAllCallbacks (widget, XtNcallback);
   372       XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance);
   373     }
   374 }
   375 
   376 void
   377 xaw_update_one_value (widget_instance *instance,
   378                       Widget widget,
   379                       widget_value *val)
   380 {
   381   /* This function is not used by the scrollbars and those are the only
   382      Athena widget implemented at the moment so do nothing. */
   383   return;
   384 }
   385 
   386 void
   387 xaw_destroy_instance (widget_instance *instance)
   388 {
   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 
   396 void
   397 xaw_popup_menu (Widget widget, XEvent *event)
   398 {
   399   /* An Athena menubar has not been implemented. */
   400   return;
   401 }
   402 
   403 void
   404 xaw_pop_instance (widget_instance *instance, Boolean up)
   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           {
   432             unsigned int x, y, w, h;
   433             Widget topmost = instance->parent;
   434             Arg args[2];
   435 
   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);
   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);
   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 
   468 /* Dialog boxes */
   469 
   470 static char overrideTrans[] =
   471         "<Message>WM_PROTOCOLS: lwlib_delete_dialog()";
   472 /* Dialogs pop down on any key press */
   473 static char dialogOverride[] =
   474        "<KeyPress>Escape:       lwlib_delete_dialog()";
   475 static void wm_delete_window (Widget w,
   476                               XEvent *event,
   477                               String *params,
   478                               Cardinal *num_params);
   479 static XtActionsRec xaw_actions [] = {
   480   {"lwlib_delete_dialog", wm_delete_window}
   481 };
   482 static Boolean actions_initted = False;
   483 
   484 #if defined USE_CAIRO || defined HAVE_XFT
   485 static XtActionsRec button_actions[] =
   486   {
   487     { "my_reset", command_reset },
   488     { "my_press", command_press },
   489   };
   490 char buttonTrans[] =
   491   "<Leave>: reset() my_reset()\n"
   492   "<Btn1Down>: set() my_press()\n"
   493   "<Btn1Up>:  my_reset() notify() unset()\n";
   494 #endif
   495 
   496 static Widget
   497 make_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)
   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;
   517 #if defined USE_CAIRO || defined HAVE_XFT
   518   XftFont *xft_font = 0;
   519   XtTranslations button_override;
   520 #endif
   521 
   522   if (! pop_up_p) emacs_abort (); /* not implemented */
   523   if (text_input_slot) emacs_abort (); /* not implemented */
   524   if (radio_box) emacs_abort (); /* not implemented */
   525   if (list) emacs_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]));
   532 #if defined USE_CAIRO || defined HAVE_XFT
   533       XtAppAddActions (app, button_actions,
   534                        sizeof (button_actions) / sizeof (button_actions[0]));
   535 #endif
   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++;
   544 
   545   /* Don't allow any geometry request from the user.  */
   546   XtSetArg (av[ac], XtNgeometry, 0); ac++;
   547 
   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);
   554   override = XtParseTranslationTable (dialogOverride);
   555   XtOverrideTranslations (dialog, override);
   556 
   557 #if defined USE_CAIRO || defined 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     if (w)
   576       {
   577         XtResource rec[] =
   578           { { "font", "Font", XtRString, sizeof(String), 0, XtRString,
   579               (XtPointer)"Sans-10" }};
   580         char *fontName = NULL;
   581         XtVaGetSubresources (dialog, &fontName, "Dialog", "dialog",
   582                              rec, 1, (String)NULL);
   583         if (fontName)
   584           {
   585             XFontStruct *xfn = XLoadQueryFont (XtDisplay (dialog), fontName);
   586             if (!xfn)
   587               xft_font = openFont (dialog, fontName);
   588             else
   589               XFreeFont (XtDisplay (dialog), xfn);
   590           }
   591 
   592         if (xft_font)
   593           {
   594             int nr_xft_data = left_buttons + right_buttons + 1;
   595             instance->xft_data = calloc (nr_xft_data + 1,
   596                                          sizeof(*instance->xft_data));
   597             if (!instance->xft_data)
   598               memory_full ((nr_xft_data + 1) * sizeof *instance->xft_data);
   599 
   600             fill_xft_data (&instance->xft_data[0], w, xft_font);
   601             XtAddCallback (dialog, XtNdestroyCallback, destroy_xft_data,
   602                            instance->xft_data);
   603           }
   604       }
   605 
   606     button_override = XtParseTranslationTable (buttonTrans);
   607   }
   608 #endif
   609 
   610   bc = 0;
   611   button = 0;
   612   for (i = 0; i < left_buttons; i++)
   613     {
   614       ac = 0;
   615       XtSetArg (av [ac], XtNfromHoriz, button); ac++;
   616       XtSetArg (av [ac], XtNleft, XtChainLeft); ac++;
   617       XtSetArg (av [ac], XtNright, XtChainLeft); ac++;
   618       XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
   619       XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
   620       XtSetArg (av [ac], XtNresizable, True); ac++;
   621 #ifdef HAVE_XAW3D
   622       if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
   623         {
   624           /* Turn of dithered shadow if we can.  Looks bad */
   625           XtSetArg (av [ac], "beNiceToColormap", False); ac++;
   626         }
   627 #endif
   628       sprintf (button_name, "button%d", ++bc);
   629       button = XtCreateManagedWidget (button_name, commandWidgetClass,
   630                                       dialog, av, ac);
   631 #if defined USE_CAIRO || defined HAVE_XFT
   632       if (xft_font)
   633         {
   634           fill_xft_data (&instance->xft_data[bc], button, xft_font);
   635           XtOverrideTranslations (button, button_override);
   636         }
   637 #endif
   638     }
   639 
   640   for (i = 0; i < right_buttons; i++)
   641     {
   642       ac = 0;
   643       XtSetArg (av [ac], XtNfromHoriz, button); ac++;
   644       if (i == 0)
   645         {
   646           /* Separator to the other buttons. */
   647           XtSetArg (av [ac], XtNhorizDistance, 30); ac++;
   648         }
   649       XtSetArg (av [ac], XtNleft, XtChainRight); ac++;
   650       XtSetArg (av [ac], XtNright, XtChainRight); ac++;
   651       XtSetArg (av [ac], XtNtop, XtChainBottom); ac++;
   652       XtSetArg (av [ac], XtNbottom, XtChainBottom); ac++;
   653       XtSetArg (av [ac], XtNresizable, True); ac++;
   654 #ifdef HAVE_XAW3D
   655       if (DefaultDepthOfScreen (XtScreen (dialog)) >= 16)
   656         {
   657           /* Turn of dithered shadow if we can.  Looks bad */
   658           XtSetArg (av [ac], "beNiceToColormap", False); ac++;
   659         }
   660 #endif
   661       sprintf (button_name, "button%d", ++bc);
   662       button = XtCreateManagedWidget (button_name, commandWidgetClass,
   663                                       dialog, av, ac);
   664 #if defined USE_CAIRO || defined HAVE_XFT
   665       if (xft_font)
   666         {
   667           fill_xft_data (&instance->xft_data[bc], button, xft_font);
   668           XtOverrideTranslations (button, button_override);
   669         }
   670 #endif
   671     }
   672 
   673   return dialog;
   674 }
   675 
   676 Widget
   677 xaw_create_dialog (widget_instance *instance)
   678 {
   679   char *name = instance->info->type;
   680   Widget parent = instance->parent;
   681   Widget widget;
   682   Boolean pop_up_p = instance->pop_up_p;
   683   char *shell_name = 0;
   684   char *icon_name = 0;
   685   Boolean text_input_slot = False;
   686   Boolean radio_box = False;
   687   Boolean list = False;
   688   int total_buttons;
   689   int left_buttons = 0;
   690   int right_buttons = 1;
   691 
   692   switch (name [0]) {
   693   case 'E': case 'e':
   694     icon_name = "dbox-error";
   695     shell_name = "Error";
   696     break;
   697 
   698   case 'I': case 'i':
   699     icon_name = "dbox-info";
   700     shell_name = "Information";
   701     break;
   702 
   703   case 'L': case 'l':
   704     list = True;
   705     icon_name = "dbox-question";
   706     shell_name = "Prompt";
   707     break;
   708 
   709   case 'P': case 'p':
   710     text_input_slot = True;
   711     icon_name = "dbox-question";
   712     shell_name = "Prompt";
   713     break;
   714 
   715   case 'Q': case 'q':
   716     icon_name = "dbox-question";
   717     shell_name = "Question";
   718     break;
   719   }
   720 
   721   total_buttons = name [1] - '0';
   722 
   723   if (name [3] == 'T' || name [3] == 't')
   724     {
   725       text_input_slot = False;
   726       radio_box = True;
   727     }
   728   else if (name [3])
   729     right_buttons = name [4] - '0';
   730 
   731   left_buttons = total_buttons - right_buttons;
   732 
   733   widget = make_dialog (name, parent, pop_up_p,
   734                         shell_name, icon_name, text_input_slot, radio_box,
   735                         list, left_buttons, right_buttons, instance);
   736   return widget;
   737 }
   738 
   739 
   740 static void
   741 xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data)
   742 {
   743   widget_instance *instance = (widget_instance *) closure;
   744   Widget instance_widget;
   745   LWLIB_ID id;
   746   XtPointer user_data;
   747 
   748   lw_internal_update_other_instances (widget, closure, call_data);
   749 
   750   if (! instance)
   751     return;
   752   if (widget->core.being_destroyed)
   753     return;
   754 
   755   instance_widget = instance->widget;
   756   if (!instance_widget)
   757     return;
   758 
   759   id = instance->info->id;
   760 
   761   /* Damn!  Athena doesn't give us a way to hang our own data on the
   762      buttons, so we have to go find it...  I guess this assumes that
   763      all instances of a button have the same call data. */
   764   {
   765     widget_value *val = instance->info->val->contents;
   766     char *name = XtName (widget);
   767     while (val)
   768       {
   769         if (val->name && !strcmp (val->name, name))
   770           break;
   771         val = val->next;
   772       }
   773     if (! val) emacs_abort ();
   774     user_data = val->call_data;
   775   }
   776 
   777   if (instance->info->selection_cb)
   778     instance->info->selection_cb (widget, id, user_data);
   779 }
   780 
   781 static void
   782 wm_delete_window (Widget w,
   783                   XEvent *event,
   784                   String *params,
   785                   Cardinal *num_params)
   786 {
   787   LWLIB_ID id;
   788   Cardinal nkids;
   789   int i;
   790   Widget *kids = 0;
   791   Widget widget = 0, shell;
   792 
   793   if (XtIsSubclass (w, dialogWidgetClass))
   794     shell = XtParent (w);
   795   else
   796     shell = w;
   797 
   798   if (! XtIsSubclass (shell, shellWidgetClass))
   799     emacs_abort ();
   800   XtVaGetValues (shell, XtNnumChildren, &nkids, NULL);
   801   XtVaGetValues (shell, XtNchildren, &kids, NULL);
   802   if (!kids || !*kids)
   803     emacs_abort ();
   804   for (i = 0; i < nkids; i++)
   805     {
   806       widget = kids[i];
   807       if (XtIsSubclass (widget, dialogWidgetClass))
   808         break;
   809     }
   810   if (! widget) return;
   811 
   812   id = lw_get_widget_id (widget);
   813   if (! id) emacs_abort ();
   814 
   815   {
   816     widget_info *info = lw_get_widget_info (id);
   817     if (! info) emacs_abort ();
   818     if (info->selection_cb)
   819       info->selection_cb (widget, id, (XtPointer) -1);
   820   }
   821 
   822   lw_destroy_all_widgets (id);
   823 }
   824 
   825 
   826 
   827 static Widget
   828 xaw_create_main (widget_instance *instance)
   829 {
   830   Arg al[1];
   831   int ac;
   832 
   833   /* Create a vertical Paned to hold menubar */
   834   ac = 0;
   835   XtSetArg (al[ac], XtNborderWidth, 0); ac++;
   836   return XtCreateWidget (instance->info->name, panedWidgetClass,
   837                          instance->parent, al, ac);
   838 }
   839 
   840 widget_creation_entry
   841 xaw_creation_table [] =
   842 {
   843   {"main",                      xaw_create_main},
   844   {NULL, NULL}
   845 };

/* [<][>][^][v][top][bottom][index][help] */