lwlib-Xm.c 55.9 KB
Newer Older
Richard M. Stallman's avatar
Richard M. Stallman committed
1
/* The lwlib interface to Motif widgets.
2 3 4

Copyright (C) 1994-1997, 1999-2011  Free Software Foundation, Inc.
Copyright (C) 1992 Lucid, Inc.
Richard M. Stallman's avatar
Richard M. Stallman committed
5 6 7

This file is part of the Lucid Widget Library.

8
The Lucid Widget Library is free software; you can redistribute it and/or
Richard M. Stallman's avatar
Richard M. Stallman committed
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)
Richard M. Stallman's avatar
Richard M. Stallman committed
11 12 13
any later version.

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
Richard M. Stallman's avatar
Richard M. Stallman committed
15 16 17 18 19
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING.  If not, write to
Lute Kamstra's avatar
Lute Kamstra committed
20 21
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
22

23 24 25 26
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

Richard M. Stallman's avatar
Richard M. Stallman committed
27 28
#include <unistd.h>
#include <stdio.h>
29
#include <setjmp.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
30 31 32 33 34 35 36

#include <X11/StringDefs.h>
#include <X11/IntrinsicP.h>
#include <X11/ObjectP.h>
#include <X11/CoreP.h>
#include <X11/CompositeP.h>

Richard M. Stallman's avatar
Richard M. Stallman committed
37 38
#include "../src/lisp.h"

Richard M. Stallman's avatar
Richard M. Stallman committed
39 40 41 42 43
#include "lwlib-Xm.h"
#include "lwlib-utils.h"

#include <Xm/BulletinB.h>
#include <Xm/CascadeB.h>
44
#include <Xm/CascadeBG.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
45 46 47 48
#include <Xm/DrawingA.h>
#include <Xm/FileSB.h>
#include <Xm/Label.h>
#include <Xm/List.h>
Paul Reilly's avatar
Paul Reilly committed
49
#include <Xm/MainW.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
50 51
#include <Xm/MenuShell.h>
#include <Xm/MessageB.h>
Paul Reilly's avatar
Paul Reilly committed
52
#include <Xm/PanedW.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
53 54 55 56 57 58 59 60 61 62 63 64 65 66
#include <Xm/PushB.h>
#include <Xm/PushBG.h>
#include <Xm/ArrowB.h>
#include <Xm/SelectioB.h>
#include <Xm/Text.h>
#include <Xm/TextF.h>
#include <Xm/ToggleB.h>
#include <Xm/ToggleBG.h>
#include <Xm/RowColumn.h>
#include <Xm/ScrolledW.h>
#include <Xm/Separator.h>
#include <Xm/DialogS.h>
#include <Xm/Form.h>

Gerd Moellmann's avatar
Gerd Moellmann committed
67
enum do_call_type { pre_activate, selection, no_selection, post_activate };
Richard M. Stallman's avatar
Richard M. Stallman committed
68 69 70


/* Structures to keep destroyed instances */
71
typedef struct _destroyed_instance
Richard M. Stallman's avatar
Richard M. Stallman committed
72 73 74 75 76 77 78 79 80
{
  char*		name;
  char*		type;
  Widget 	widget;
  Widget	parent;
  Boolean	pop_up_p;
  struct _destroyed_instance*	next;
} destroyed_instance;

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
static destroyed_instance *make_destroyed_instance (char *, char *,
                                                    Widget, Widget,
                                                    Boolean);
static void free_destroyed_instance (destroyed_instance*);
Widget first_child (Widget);
Boolean lw_motif_widget_p (Widget);
static XmString resource_motif_string (Widget, char *);
static void destroy_all_children (Widget, int);
static void xm_update_label (widget_instance *, Widget, widget_value *);
static void xm_update_list (widget_instance *, Widget, widget_value *);
static void xm_update_pushbutton (widget_instance *, Widget,
                                  widget_value *);
static void xm_update_cascadebutton (widget_instance *, Widget,
                                     widget_value *);
static void xm_update_toggle (widget_instance *, Widget, widget_value *);
static void xm_update_radiobox (widget_instance *, Widget, widget_value *);
static void make_menu_in_widget (widget_instance *, Widget,
                                 widget_value *, int);
static void update_one_menu_entry (widget_instance *, Widget,
                                   widget_value *, Boolean);
static void xm_update_menu (widget_instance *, Widget, widget_value *,
                            Boolean);
static void xm_update_text (widget_instance *, Widget, widget_value *);
static void xm_update_text_field (widget_instance *, Widget,
                                  widget_value *);
void xm_update_one_value (widget_instance *, Widget, widget_value *);
static void activate_button (Widget, XtPointer, XtPointer);
static Widget make_dialog (char *, Widget, Boolean, char *, char *,
                           Boolean, Boolean, Boolean, int, int);
static destroyed_instance* find_matching_instance (widget_instance*);
static void mark_dead_instance_destroyed (Widget, XtPointer, XtPointer);
static void recenter_widget (Widget);
static Widget recycle_instance (destroyed_instance*);
Widget xm_create_dialog (widget_instance*);
static Widget make_menubar (widget_instance*);
static void remove_grabs (Widget, XtPointer, XtPointer);
static Widget make_popup_menu (widget_instance*);
static Widget make_main (widget_instance*);
void xm_destroy_instance (widget_instance*);
void xm_popup_menu (Widget, XEvent *);
static void set_min_dialog_size (Widget);
static void do_call (Widget, XtPointer, enum do_call_type);
static void xm_generic_callback (Widget, XtPointer, XtPointer);
static void xm_nosel_callback (Widget, XtPointer, XtPointer);
static void xm_pull_down_callback (Widget, XtPointer, XtPointer);
static void xm_pop_down_callback (Widget, XtPointer, XtPointer);
void xm_set_keyboard_focus (Widget, Widget);
void xm_set_main_areas (Widget, Widget, Widget);
static void xm_internal_update_other_instances (Widget, XtPointer,
                                                XtPointer);
static void xm_arm_callback (Widget, XtPointer, XtPointer);
Gerd Moellmann's avatar
Gerd Moellmann committed
132 133

#if 0
134 135 136 137
void xm_update_one_widget (widget_instance *, Widget, widget_value *,
                           Boolean);
void xm_pop_instance (widget_instance*, Boolean);
void xm_manage_resizing (Widget, Boolean);
Gerd Moellmann's avatar
Gerd Moellmann committed
138 139 140
#endif


141 142 143 144 145 146
#if 0

/* Print the complete X resource name of widget WIDGET to stderr.
   This is sometimes handy to have available.  */

void
147
x_print_complete_resource_name (Widget widget)
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
{
  int i;
  String names[100];

  for (i = 0; i < 100 && widget != NULL; ++i)
    {
      names[i] = XtName (widget);
      widget = XtParent (widget);
    }

  for (--i; i >= 1; --i)
    fprintf (stderr, "%s.", names[i]);
  fprintf (stderr, "%s\n", names[0]);
}

#endif /* 0 */


166
static destroyed_instance *all_destroyed_instances = NULL;
Richard M. Stallman's avatar
Richard M. Stallman committed
167 168

static destroyed_instance*
169 170 171 172 173
make_destroyed_instance (char* name,
                         char* type,
                         Widget widget,
                         Widget parent,
                         Boolean pop_up_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
174 175
{
  destroyed_instance* instance =
Jan D's avatar
Jan D committed
176
    (destroyed_instance*) xmalloc (sizeof (destroyed_instance));
Paul Reilly's avatar
Paul Reilly committed
177 178
  instance->name = safe_strdup (name);
  instance->type = safe_strdup (type);
Richard M. Stallman's avatar
Richard M. Stallman committed
179 180 181 182 183 184
  instance->widget = widget;
  instance->parent = parent;
  instance->pop_up_p = pop_up_p;
  instance->next = NULL;
  return instance;
}
185

Richard M. Stallman's avatar
Richard M. Stallman committed
186
static void
187
free_destroyed_instance (destroyed_instance* instance)
Richard M. Stallman's avatar
Richard M. Stallman committed
188 189 190 191 192 193 194 195
{
  free (instance->name);
  free (instance->type);
  free (instance);
}

/* motif utility functions */
Widget
196
first_child (Widget widget)
Richard M. Stallman's avatar
Richard M. Stallman committed
197 198 199 200 201
{
  return ((CompositeWidget)widget)->composite.children [0];
}

Boolean
202
lw_motif_widget_p (Widget widget)
Richard M. Stallman's avatar
Richard M. Stallman committed
203
{
204
  return
Richard M. Stallman's avatar
Richard M. Stallman committed
205 206 207 208 209
    XtClass (widget) == xmDialogShellWidgetClass
      || XmIsPrimitive (widget) || XmIsManager (widget) || XmIsGadget (widget);
}

static XmString
210 211
resource_motif_string (Widget widget,
                       char* name)
Richard M. Stallman's avatar
Richard M. Stallman committed
212 213 214
{
  XtResource resource;
  XmString result = 0;
215

Richard M. Stallman's avatar
Richard M. Stallman committed
216 217 218 219 220 221 222 223 224 225 226 227 228
  resource.resource_name = name;
  resource.resource_class = XmCXmString;
  resource.resource_type = XmRXmString;
  resource.resource_size = sizeof (XmString);
  resource.resource_offset = 0;
  resource.default_type = XtRImmediate;
  resource.default_addr = 0;

  XtGetSubresources (widget, (XtPointer)&result, "dialogString",
		     "DialogString", &resource, 1, NULL, 0);
  return result;
}

229 230 231
/* Destroy all of the children of WIDGET
   starting with number FIRST_CHILD_TO_DESTROY.  */

Richard M. Stallman's avatar
Richard M. Stallman committed
232
static void
233 234
destroy_all_children (Widget widget,
                      int first_child_to_destroy)
Richard M. Stallman's avatar
Richard M. Stallman committed
235 236 237 238 239 240 241 242
{
  Widget* children;
  unsigned int number;
  int i;

  children = XtCompositeChildren (widget, &number);
  if (children)
    {
243 244 245
      XtUnmanageChildren (children + first_child_to_destroy,
			  number - first_child_to_destroy);

246
      /* Unmanage all children and destroy them.  They will only be
247 248
	 really destroyed when we get out of DispatchEvent.  */
      for (i = first_child_to_destroy; i < number; i++)
249 250 251 252 253 254 255 256
	{
	  Arg al[2];
	  Widget submenu = 0;
	  /* Cascade buttons have submenus,and these submenus
	     need to be freed.  But they are not included in
	     XtCompositeChildren.  So get it out of the cascade button
	     and free it.  If this child is not a cascade button,
	     then submenu should remain unchanged.  */
257
	  XtSetArg (al[0], XmNsubMenuId, &submenu);
258 259
  	  XtGetValues (children[i], al, 1);
	  if (submenu)
260 261 262 263
            {
              destroy_all_children (submenu, 0);
              XtDestroyWidget (submenu);
            }
264 265
	  XtDestroyWidget (children[i]);
	}
266

Richard M. Stallman's avatar
Richard M. Stallman committed
267 268 269 270
      XtFree ((char *) children);
    }
}

271 272 273 274 275 276 277 278 279


/* Callback XmNarmCallback and XmNdisarmCallback for buttons in a
   menu.  CLIENT_DATA contains a pointer to the widget_value
   corresponding to widget W.  CALL_DATA contains a
   XmPushButtonCallbackStruct containing the reason why the callback
   is called.  */

static void
280
xm_arm_callback (Widget w, XtPointer client_data, XtPointer call_data)
281 282 283 284 285
{
  XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *) call_data;
  widget_value *wv = (widget_value *) client_data;
  widget_instance *instance;

286
  /* Get the id of the menu bar or popup menu this widget is in.  */
287
  while (w != NULL)
288
    {
289
      if (XmIsRowColumn (w))
290
	{
291
	  unsigned char type = 0xff;
292

293 294 295
	  XtVaGetValues (w, XmNrowColumnType, &type, NULL);
	  if (type == XmMENU_BAR || type == XmMENU_POPUP)
	    break;
296
	}
297

298 299 300
      w = XtParent (w);
    }

301
  if (w != NULL)
302
    {
303 304 305 306 307 308
      instance = lw_get_widget_instance (w);
      if (instance && instance->info->highlight_cb)
	{
	  call_data = cbs->reason == XmCR_DISARM ? NULL : wv;
	  instance->info->highlight_cb (w, instance->info->id, call_data);
	}
309 310 311 312
    }
}


Gerd Moellmann's avatar
Gerd Moellmann committed
313 314 315 316 317 318

/* Update the label of widget WIDGET.  WIDGET must be a Label widget
   or a subclass of Label.  WIDGET_INSTANCE is unused.  VAL contains
   the value to update.

   Menus:
319

Gerd Moellmann's avatar
Gerd Moellmann committed
320 321 322 323 324 325 326 327 328 329 330
   Emacs fills VAL->name with the text to display in the menu, and
   sets VAL->value to null.  Function make_menu_in_widget creates
   widgets with VAL->name as resource name.  This works because the
   Label widget uses its resource name for display if no
   XmNlabelString is set.

   Dialogs:

   VAL->name is again set to the resource name, but VAL->value is
   not null, and contains the label string to display.  */

Richard M. Stallman's avatar
Richard M. Stallman committed
331
static void
332 333 334
xm_update_label (widget_instance* instance,
                 Widget widget,
                 widget_value* val)
Richard M. Stallman's avatar
Richard M. Stallman committed
335 336 337 338 339 340
{
  XmString res_string = 0;
  XmString built_string = 0;
  XmString key_string = 0;
  Arg al [256];
  int ac;
Gerd Moellmann's avatar
Gerd Moellmann committed
341

Richard M. Stallman's avatar
Richard M. Stallman committed
342 343 344 345
  ac = 0;

  if (val->value)
    {
Gerd Moellmann's avatar
Gerd Moellmann committed
346 347
      /* A label string is specified, i.e. we are in a dialog.  First
	 see if it is overridden by something from the resource file.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
348 349 350 351 352 353 354 355 356
      res_string = resource_motif_string (widget, val->value);

      if (res_string)
	{
	  XtSetArg (al [ac], XmNlabelString, res_string); ac++;
	}
      else
	{
	  built_string =
357
	    XmStringCreateLocalized (val->value);
Richard M. Stallman's avatar
Richard M. Stallman committed
358 359
	  XtSetArg (al [ac], XmNlabelString, built_string); ac++;
	}
360

Richard M. Stallman's avatar
Richard M. Stallman committed
361 362
      XtSetArg (al [ac], XmNlabelType, XmSTRING); ac++;
    }
363

Richard M. Stallman's avatar
Richard M. Stallman committed
364 365
  if (val->key)
    {
366
      key_string = XmStringCreateLocalized (val->key);
Richard M. Stallman's avatar
Richard M. Stallman committed
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
      XtSetArg (al [ac], XmNacceleratorText, key_string); ac++;
    }

  if (ac)
    XtSetValues (widget, al, ac);

  if (built_string)
    XmStringFree (built_string);

  if (key_string)
    XmStringFree (key_string);
}

/* update of list */
static void
382 383 384
xm_update_list (widget_instance* instance,
                Widget widget,
                widget_value* val)
Richard M. Stallman's avatar
Richard M. Stallman committed
385 386 387 388 389 390 391 392 393
{
  widget_value* cur;
  int i;
  XtRemoveAllCallbacks (widget, XmNsingleSelectionCallback);
  XtAddCallback (widget, XmNsingleSelectionCallback, xm_generic_callback,
		 instance);
  for (cur = val->contents, i = 0; cur; cur = cur->next)
    if (cur->value)
      {
394
	XmString xmstr = XmStringCreateLocalized (cur->value);
Richard M. Stallman's avatar
Richard M. Stallman committed
395 396 397 398 399 400 401 402 403 404
	i += 1;
	XmListAddItem (widget, xmstr, 0);
	if (cur->selected)
	  XmListSelectPos (widget, i, False);
	XmStringFree (xmstr);
      }
}

/* update of buttons */
static void
405 406 407
xm_update_pushbutton (widget_instance* instance,
                      Widget widget,
                      widget_value* val)
Richard M. Stallman's avatar
Richard M. Stallman committed
408
{
Gerd Moellmann's avatar
Gerd Moellmann committed
409
  XtVaSetValues (widget, XmNalignment, XmALIGNMENT_CENTER, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
410 411 412 413 414
  XtRemoveAllCallbacks (widget, XmNactivateCallback);
  XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
}

static void
415 416 417
xm_update_cascadebutton (widget_instance* instance,
                         Widget widget,
                         widget_value* val)
Richard M. Stallman's avatar
Richard M. Stallman committed
418 419 420 421 422 423 424 425 426
{
  /* Should also rebuild the menu by calling ...update_menu... */
  XtRemoveAllCallbacks (widget, XmNcascadingCallback);
  XtAddCallback (widget, XmNcascadingCallback, xm_pull_down_callback,
		 instance);
}

/* update toggle and radiobox */
static void
427 428 429
xm_update_toggle (widget_instance* instance,
                  Widget widget,
                  widget_value* val)
Richard M. Stallman's avatar
Richard M. Stallman committed
430 431 432
{
  XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
  XtAddCallback (widget, XmNvalueChangedCallback,
Gerd Moellmann's avatar
Gerd Moellmann committed
433
		 xm_generic_callback, instance);
Richard M. Stallman's avatar
Richard M. Stallman committed
434
  XtVaSetValues (widget, XmNset, val->selected,
Gerd Moellmann's avatar
Gerd Moellmann committed
435
		 XmNalignment, XmALIGNMENT_BEGINNING, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
436 437 438
}

static void
439 440 441
xm_update_radiobox (widget_instance* instance,
                    Widget widget,
                    widget_value* val)
Paul Reilly's avatar
Paul Reilly committed
442

Richard M. Stallman's avatar
Richard M. Stallman committed
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
{
  Widget toggle;
  widget_value* cur;

  /* update the callback */
  XtRemoveAllCallbacks (widget, XmNentryCallback);
  XtAddCallback (widget, XmNentryCallback, xm_generic_callback, instance);

  /* first update all the toggles */
  /* Energize kernel interface is currently bad.  It sets the selected widget
     with the selected flag but returns it by its name.  So we currently
     have to support both setting the selection with the selected slot
     of val contents and setting it with the "value" slot of val.  The latter
     has a higher priority.  This to be removed when the kernel is fixed. */
  for (cur = val->contents; cur; cur = cur->next)
    {
      toggle = XtNameToWidget (widget, cur->value);
      if (toggle)
	{
462
	  XtSetSensitive (toggle, cur->enabled);
Richard M. Stallman's avatar
Richard M. Stallman committed
463
	  if (!val->value && cur->selected)
Gerd Moellmann's avatar
Gerd Moellmann committed
464
	    XtVaSetValues (toggle, XmNset, cur->selected, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
465
	  if (val->value && strcmp (val->value, cur->value))
Gerd Moellmann's avatar
Gerd Moellmann committed
466
	    XtVaSetValues (toggle, XmNset, False, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
467 468 469 470 471 472 473 474
	}
    }

  /* The selected was specified by the value slot */
  if (val->value)
    {
      toggle = XtNameToWidget (widget, val->value);
      if (toggle)
Gerd Moellmann's avatar
Gerd Moellmann committed
475
	XtVaSetValues (toggle, XmNset, True, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
476 477 478
    }
}

Gerd Moellmann's avatar
Gerd Moellmann committed
479 480

/* update a popup menu, pulldown menu or a menubar */
Richard M. Stallman's avatar
Richard M. Stallman committed
481

482 483
/* KEEP_FIRST_CHILDREN gives the number of initial children to keep.  */

Richard M. Stallman's avatar
Richard M. Stallman committed
484
static void
485 486 487 488
make_menu_in_widget (widget_instance* instance,
                     Widget widget,
                     widget_value* val,
                     int keep_first_children)
Richard M. Stallman's avatar
Richard M. Stallman committed
489 490 491 492 493 494
{
  Widget* children = 0;
  int num_children;
  int child_index;
  widget_value* cur;
  Widget button = 0;
Gerd Moellmann's avatar
Gerd Moellmann committed
495
  Widget title = 0;
Richard M. Stallman's avatar
Richard M. Stallman committed
496 497 498 499
  Widget menu;
  Arg al [256];
  int ac;
  Boolean menubar_p;
Gerd Moellmann's avatar
Gerd Moellmann committed
500
  unsigned char type;
Richard M. Stallman's avatar
Richard M. Stallman committed
501

502 503 504
  Widget* old_children;
  unsigned int old_num_children;

505 506 507 508
  /* Disable drag and drop for labels in menu bar.  */
  static char overrideTrans[] = "<Btn2Down>: Noop()";
  XtTranslations override = XtParseTranslationTable (overrideTrans);

509 510
  old_children = XtCompositeChildren (widget, &old_num_children);

Richard M. Stallman's avatar
Richard M. Stallman committed
511
  /* Allocate the children array */
512 513
  for (num_children = 0, cur = val; cur; num_children++, cur = cur->next)
    ;
Richard M. Stallman's avatar
Richard M. Stallman committed
514 515
  children = (Widget*)XtMalloc (num_children * sizeof (Widget));

Gerd Moellmann's avatar
Gerd Moellmann committed
516 517 518 519 520 521 522
  /* WIDGET should be a RowColumn.  */
  if (!XmIsRowColumn (widget))
    abort ();

  /* Determine whether WIDGET is a menu bar.  */
  type = -1;
  XtSetArg (al[0], XmNrowColumnType, &type);
Richard M. Stallman's avatar
Richard M. Stallman committed
523
  XtGetValues (widget, al, 1);
Gerd Moellmann's avatar
Gerd Moellmann committed
524 525 526
  if (type != XmMENU_BAR && type != XmMENU_PULLDOWN && type != XmMENU_POPUP)
    abort ();
  menubar_p = type == XmMENU_BAR;
Richard M. Stallman's avatar
Richard M. Stallman committed
527

Gerd Moellmann's avatar
Gerd Moellmann committed
528 529
  /* Add a callback to popups and pulldowns that is called when
     it is made invisible again.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
530 531 532 533
  if (!menubar_p)
    XtAddCallback (XtParent (widget), XmNpopdownCallback,
		   xm_pop_down_callback, (XtPointer)instance);

534 535 536 537 538 539 540 541 542 543 544 545
  /* Preserve the first KEEP_FIRST_CHILDREN old children.  */
  for (child_index = 0, cur = val; child_index < keep_first_children;
       child_index++, cur = cur->next)
    children[child_index] = old_children[child_index];

  /* Check that those are all we have
     (the caller should have deleted the rest).  */
  if (old_num_children != keep_first_children)
    abort ();

  /* Create the rest.  */
  for (child_index = keep_first_children; cur; child_index++, cur = cur->next)
Gerd Moellmann's avatar
Gerd Moellmann committed
546 547 548
    {
      enum menu_separator separator;

Richard M. Stallman's avatar
Richard M. Stallman committed
549
      ac = 0;
Gerd Moellmann's avatar
Gerd Moellmann committed
550 551 552
      XtSetArg (al[ac], XmNsensitive, cur->enabled); ac++;
      XtSetArg (al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
      XtSetArg (al[ac], XmNuserData, cur->call_data); ac++;
553

554
      if (instance->pop_up_p && !cur->contents && !cur->call_data
Gerd Moellmann's avatar
Gerd Moellmann committed
555
	  && !lw_separator_p (cur->name, &separator, 1))
556 557 558
	{
	  ac = 0;
	  XtSetArg (al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
Gerd Moellmann's avatar
Gerd Moellmann committed
559
	  title = button = XmCreateLabel (widget, cur->name, al, ac);
560
	}
Gerd Moellmann's avatar
Gerd Moellmann committed
561
      else if (lw_separator_p (cur->name, &separator, 1))
Richard M. Stallman's avatar
Richard M. Stallman committed
562
	{
Gerd Moellmann's avatar
Gerd Moellmann committed
563 564 565
	  ac = 0;
	  XtSetArg (al[ac], XmNseparatorType, separator); ++ac;
	  button = XmCreateSeparator (widget, cur->name, al, ac);
Richard M. Stallman's avatar
Richard M. Stallman committed
566 567 568 569 570 571 572
	}
      else if (!cur->contents)
	{
	  if (menubar_p)
	    button = XmCreateCascadeButton (widget, cur->name, al, ac);
	  else if (!cur->call_data)
	    button = XmCreateLabel (widget, cur->name, al, ac);
Gerd Moellmann's avatar
Gerd Moellmann committed
573 574 575 576 577 578 579 580 581
	  else if (cur->button_type == BUTTON_TYPE_TOGGLE
		   || cur->button_type == BUTTON_TYPE_RADIO)
	    {
	      XtSetArg (al[ac], XmNset, cur->selected); ++ac;
	      XtSetArg (al[ac], XmNvisibleWhenOff, True); ++ac;
	      XtSetArg (al[ac], XmNindicatorType,
			(cur->button_type == BUTTON_TYPE_TOGGLE
			 ? XmN_OF_MANY : XmONE_OF_MANY));
	      ++ac;
582
	      button = XmCreateToggleButton (widget, cur->name, al, ac);
583 584
	      XtAddCallback (button, XmNarmCallback, xm_arm_callback, cur);
	      XtAddCallback (button, XmNdisarmCallback, xm_arm_callback, cur);
Gerd Moellmann's avatar
Gerd Moellmann committed
585
	    }
Richard M. Stallman's avatar
Richard M. Stallman committed
586
	  else
587 588 589 590 591
	    {
	      button = XmCreatePushButton (widget, cur->name, al, ac);
	      XtAddCallback (button, XmNarmCallback, xm_arm_callback, cur);
	      XtAddCallback (button, XmNdisarmCallback, xm_arm_callback, cur);
	    }
592

Richard M. Stallman's avatar
Richard M. Stallman committed
593
	  xm_update_label (instance, button, cur);
594

Gerd Moellmann's avatar
Gerd Moellmann committed
595 596 597 598 599 600 601
	  /* Add a callback that is called when the button is
	     selected.  Toggle buttons don't support
	     XmNactivateCallback, we use XmNvalueChangedCallback in
	     that case.  Don't add a callback to a simple label.  */
	  if (cur->button_type)
	    xm_update_toggle (instance, button, cur);
	  else if (cur->call_data)
Richard M. Stallman's avatar
Richard M. Stallman committed
602 603 604 605 606
	    XtAddCallback (button, XmNactivateCallback, xm_generic_callback,
			   (XtPointer)instance);
	}
      else
	{
607
	  menu = XmCreatePulldownMenu (widget, cur->name, NULL, 0);
608

609
	  make_menu_in_widget (instance, menu, cur->contents, 0);
610
          XtSetArg (al[ac], XmNsubMenuId, menu); ac++;
611
	  button = XmCreateCascadeButton (widget, cur->name, al, ac);
Richard M. Stallman's avatar
Richard M. Stallman committed
612 613 614 615 616

	  xm_update_label (instance, button, cur);

	  XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
			 (XtPointer)instance);
617 618
          XtOverrideTranslations (button, override);

Richard M. Stallman's avatar
Richard M. Stallman committed
619 620
	}

Gerd Moellmann's avatar
Gerd Moellmann committed
621
      children[child_index] = button;
Richard M. Stallman's avatar
Richard M. Stallman committed
622 623
    }

Gerd Moellmann's avatar
Gerd Moellmann committed
624 625 626 627 628
  /* Last entry is the help button.  The original comment read "Has to
     be done after managing the buttons otherwise the menubar is only
     4 pixels high."  This is no longer true, and to make
     XmNmenuHelpWidget work, we need to set it before managing the
     children.. --gerd.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
629
  if (button)
Gerd Moellmann's avatar
Gerd Moellmann committed
630
    XtVaSetValues (widget, XmNmenuHelpWidget, button, NULL);
Gerd Moellmann's avatar
Gerd Moellmann committed
631 632 633

  if (num_children)
    XtManageChildren (children, num_children);
Richard M. Stallman's avatar
Richard M. Stallman committed
634 635

  XtFree ((char *) children);
636 637
  if (old_children)
    XtFree ((char *) old_children);
Richard M. Stallman's avatar
Richard M. Stallman committed
638 639 640
}

static void
641 642 643 644
update_one_menu_entry (widget_instance* instance,
                       Widget widget,
                       widget_value* val,
                       Boolean deep_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
645 646 647 648 649 650
{
  Arg al [256];
  int ac;
  Widget menu;
  widget_value* contents;

651
  if (val->this_one_change == NO_CHANGE)
Richard M. Stallman's avatar
Richard M. Stallman committed
652 653 654 655
    return;

  /* update the sensitivity and userdata */
  /* Common to all widget types */
656 657
  XtSetSensitive (widget, val->enabled);
  XtVaSetValues (widget, XmNuserData, val->call_data, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
658 659

  /* update the menu button as a label. */
660
  if (val->this_one_change >= VISIBLE_CHANGE)
Gerd Moellmann's avatar
Gerd Moellmann committed
661 662 663 664 665
    {
      xm_update_label (instance, widget, val);
      if (val->button_type)
	xm_update_toggle (instance, widget, val);
    }
Richard M. Stallman's avatar
Richard M. Stallman committed
666 667 668 669 670 671

  /* update the pulldown/pullaside as needed */
  ac = 0;
  menu = NULL;
  XtSetArg (al [ac], XmNsubMenuId, &menu); ac++;
  XtGetValues (widget, al, ac);
672

Richard M. Stallman's avatar
Richard M. Stallman committed
673 674 675 676 677 678
  contents = val->contents;

  if (!menu)
    {
      if (contents)
	{
679
	  unsigned int old_num_children, i;
680
	  Widget parent;
681 682 683 684 685 686 687 688 689 690 691
	  Widget *widget_list;

	  parent = XtParent (widget);
	  widget_list = XtCompositeChildren (parent, &old_num_children);

	  /* Find the widget position within the parent's widget list.  */
	  for (i = 0; i < old_num_children; i++)
	    if (strcmp (XtName (widget_list[i]), XtName (widget)) == 0)
	      break;
	  if (i == old_num_children)
	    abort ();
692 693 694 695 696 697 698 699 700 701 702
	  if (XmIsCascadeButton (widget_list[i]))
	    {
	      menu = XmCreatePulldownMenu (parent, XtName(widget), NULL, 0);
	      make_menu_in_widget (instance, menu, contents, 0);
	      ac = 0;
	      XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
	      XtSetValues (widget, al, ac);
	    }
	  else
	    {
	      Widget button;
703 704

	      /* The current menuitem is a XmPushButtonGadget, it
705 706 707 708 709 710 711 712 713
		 needs to be replaced by a CascadeButtonGadget */
	      XtDestroyWidget (widget_list[i]);
	      menu = XmCreatePulldownMenu (parent, val->name, NULL, 0);
	      make_menu_in_widget (instance, menu, contents, 0);
	      ac = 0;
	      XtSetArg (al [ac], XmNsubMenuId, menu); ac++;
	      /* Non-zero values don't work reliably in
		 conjunction with Emacs' event loop */
	      XtSetArg (al [ac], XmNmappingDelay, 0); ac++;
714
#ifdef XmNpositionIndex /* This is undefined on SCO ODT 2.0.  */
715
	      /* Tell Motif to put it in the right place */
716 717
	      XtSetArg (al [ac], XmNpositionIndex , i); ac++;
#endif
718
	      button = XmCreateCascadeButton (parent, val->name, al, ac);
719
	      xm_update_label (instance, button, val);
720

721 722 723 724
	      XtAddCallback (button, XmNcascadingCallback, xm_pull_down_callback,
			     (XtPointer)instance);
	      XtManageChild (button);
	    }
725 726 727

          if (widget_list)
            XtFree ((char*) widget_list);
Richard M. Stallman's avatar
Richard M. Stallman committed
728 729 730 731 732 733 734 735 736 737 738 739 740 741
	}
    }
  else if (!contents)
    {
      ac = 0;
      XtSetArg (al [ac], XmNsubMenuId, NULL); ac++;
      XtSetValues (widget, al, ac);
      XtDestroyWidget (menu);
    }
  else if (deep_p && contents->change != NO_CHANGE)
    xm_update_menu (instance, menu, val, 1);
}

static void
742 743 744 745
xm_update_menu (widget_instance* instance,
                Widget widget,
                widget_value* val,
                Boolean deep_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
746
{
747 748 749 750 751 752 753 754
  Widget* children;
  unsigned int num_children;
  int num_children_to_keep = 0;
  int i;
  widget_value* cur;

  children = XtCompositeChildren (widget, &num_children);

Richard M. Stallman's avatar
Richard M. Stallman committed
755 756 757
  /* Widget is a RowColumn widget whose contents have to be updated
   * to reflect the list of items in val->contents */

758 759 760 761 762 763
  /* See how many buttons we can keep, and how many we
     must completely replace.  */
  if (val->contents == 0)
    num_children_to_keep = 0;
  else if (val->contents->change == STRUCTURAL_CHANGE)
    {
Richard M. Stallman's avatar
Richard M. Stallman committed
764 765
      if (children)
	{
766
	  for (i = 0, cur = val->contents;
767 768
               (i < num_children
		&& cur); /* how else to ditch unwanted children ?? - mgd */
769
	       i++, cur = cur->next)
Richard M. Stallman's avatar
Richard M. Stallman committed
770
	    {
771 772
	      if (cur->this_one_change == STRUCTURAL_CHANGE)
		break;
Richard M. Stallman's avatar
Richard M. Stallman committed
773
	    }
774 775 776 777 778 779 780 781 782 783 784 785 786 787

	  num_children_to_keep = i;
	}
    }
  else
    num_children_to_keep = num_children;

  /* Update all the buttons of the RowColumn, in order,
     except for those we are going to replace entirely.  */
  if (children)
    {
      for (i = 0, cur = val->contents; i < num_children_to_keep; i++)
	{
	  if (!cur)
788 789 790 791
	    {
	      num_children_to_keep = i;
	      break;
	    }
792 793 794 795 796
	  if (children [i]->core.being_destroyed
	      || strcmp (XtName (children [i]), cur->name))
	    continue;
	  update_one_menu_entry (instance, children [i], cur, deep_p);
	  cur = cur->next;
Richard M. Stallman's avatar
Richard M. Stallman committed
797 798
	}
    }
799 800 801

  /* Now replace from scratch all the buttons after the last
     place that the top-level structure changed.  */
802
  if (val->contents && val->contents->change == STRUCTURAL_CHANGE)
803 804 805
    {
      destroy_all_children (widget, num_children_to_keep);
      make_menu_in_widget (instance, widget, val->contents,
806
                           num_children_to_keep);
807 808 809
    }

  XtFree ((char *) children);
Richard M. Stallman's avatar
Richard M. Stallman committed
810 811 812 813 814 815
}


/* update text widgets */

static void
816 817 818
xm_update_text (widget_instance* instance,
                Widget widget,
                widget_value* val)
Richard M. Stallman's avatar
Richard M. Stallman committed
819 820 821 822 823 824 825 826 827 828
{
  XmTextSetString (widget, val->value ? val->value : "");
  XtRemoveAllCallbacks (widget, XmNactivateCallback);
  XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
  XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
  XtAddCallback (widget, XmNvalueChangedCallback,
		 xm_internal_update_other_instances, instance);
}

static void
829 830 831
xm_update_text_field (widget_instance* instance,
                      Widget widget,
                      widget_value* val)
Richard M. Stallman's avatar
Richard M. Stallman committed
832 833 834 835 836 837 838 839 840 841 842 843 844
{
  XmTextFieldSetString (widget, val->value ? val->value : "");
  XtRemoveAllCallbacks (widget, XmNactivateCallback);
  XtAddCallback (widget, XmNactivateCallback, xm_generic_callback, instance);
  XtRemoveAllCallbacks (widget, XmNvalueChangedCallback);
  XtAddCallback (widget, XmNvalueChangedCallback,
		 xm_internal_update_other_instances, instance);
}


/* update a motif widget */

void
845 846 847 848
xm_update_one_widget (widget_instance* instance,
                      Widget widget,
                      widget_value* val,
                      Boolean deep_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
849 850
{
  WidgetClass class;
851

Richard M. Stallman's avatar
Richard M. Stallman committed
852 853 854 855
  /* Mark as not edited */
  val->edited = False;

  /* Common to all widget types */
856 857
  XtSetSensitive (widget, val->enabled);
  XtVaSetValues (widget, XmNuserData, val->call_data, NULL);
858

Richard M. Stallman's avatar
Richard M. Stallman committed
859 860 861
  /* Common to all label like widgets */
  if (XtIsSubclass (widget, xmLabelWidgetClass))
    xm_update_label (instance, widget, val);
862

Richard M. Stallman's avatar
Richard M. Stallman committed
863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883
  class = XtClass (widget);
  /* Class specific things */
  if (class == xmPushButtonWidgetClass ||
      class == xmArrowButtonWidgetClass)
    {
      xm_update_pushbutton (instance, widget, val);
    }
  else if (class == xmCascadeButtonWidgetClass)
    {
      xm_update_cascadebutton (instance, widget, val);
    }
  else if (class == xmToggleButtonWidgetClass
	   || class == xmToggleButtonGadgetClass)
    {
      xm_update_toggle (instance, widget, val);
    }
  else if (class == xmRowColumnWidgetClass)
    {
      Boolean radiobox = 0;
      int ac = 0;
      Arg al [1];
884

Richard M. Stallman's avatar
Richard M. Stallman committed
885 886
      XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
      XtGetValues (widget, al, ac);
887

Richard M. Stallman's avatar
Richard M. Stallman committed
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908
      if (radiobox)
	xm_update_radiobox (instance, widget, val);
      else
	xm_update_menu (instance, widget, val, deep_p);
    }
  else if (class == xmTextWidgetClass)
    {
      xm_update_text (instance, widget, val);
    }
  else if (class == xmTextFieldWidgetClass)
    {
      xm_update_text_field (instance, widget, val);
    }
  else if (class == xmListWidgetClass)
    {
      xm_update_list (instance, widget, val);
    }
}

/* getting the value back */
void
909 910 911
xm_update_one_value (widget_instance* instance,
                     Widget widget,
                     widget_value* val)
Richard M. Stallman's avatar
Richard M. Stallman committed
912 913 914 915 916 917 918 919 920 921 922
{
  WidgetClass class = XtClass (widget);
  widget_value *old_wv;

  /* copy the call_data slot into the "return" widget_value */
  for (old_wv = instance->info->val->contents; old_wv; old_wv = old_wv->next)
    if (!strcmp (val->name, old_wv->name))
      {
	val->call_data = old_wv->call_data;
	break;
      }
923

Richard M. Stallman's avatar
Richard M. Stallman committed
924 925
  if (class == xmToggleButtonWidgetClass || class == xmToggleButtonGadgetClass)
    {
Gerd Moellmann's avatar
Gerd Moellmann committed
926
      XtVaGetValues (widget, XmNset, &val->selected, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
927 928 929 930
      val->edited = True;
    }
  else if (class == xmTextWidgetClass)
    {
931
      free (val->value);
Richard M. Stallman's avatar
Richard M. Stallman committed
932 933 934 935 936
      val->value = XmTextGetString (widget);
      val->edited = True;
    }
  else if (class == xmTextFieldWidgetClass)
    {
937
      free (val->value);
Richard M. Stallman's avatar
Richard M. Stallman committed
938 939 940 941 942 943 944 945
      val->value = XmTextFieldGetString (widget);
      val->edited = True;
    }
  else if (class == xmRowColumnWidgetClass)
    {
      Boolean radiobox = 0;
      int ac = 0;
      Arg al [1];
946

Richard M. Stallman's avatar
Richard M. Stallman committed
947 948
      XtSetArg (al [ac], XmNradioBehavior, &radiobox); ac++;
      XtGetValues (widget, al, ac);
949

Richard M. Stallman's avatar
Richard M. Stallman committed
950 951 952 953 954 955 956 957
      if (radiobox)
	{
	  CompositeWidget radio = (CompositeWidget)widget;
	  int i;
	  for (i = 0; i < radio->composite.num_children; i++)
	    {
	      int set = False;
	      Widget toggle = radio->composite.children [i];
958

Gerd Moellmann's avatar
Gerd Moellmann committed
959
	      XtVaGetValues (toggle, XmNset, &set, NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
960 961
	      if (set)
		{
962
		  free (val->value);
Paul Reilly's avatar
Paul Reilly committed
963
		  val->value = safe_strdup (XtName (toggle));
Richard M. Stallman's avatar
Richard M. Stallman committed
964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
		}
	    }
	  val->edited = True;
	}
    }
  else if (class == xmListWidgetClass)
    {
      int pos_cnt;
      int* pos_list;
      if (XmListGetSelectedPos (widget, &pos_list, &pos_cnt))
	{
	  int i;
	  widget_value* cur;
	  for (cur = val->contents, i = 0; cur; cur = cur->next)
	    if (cur->value)
	      {
		int j;
		cur->selected = False;
		i += 1;
		for (j = 0; j < pos_cnt; j++)
		  if (pos_list [j] == i)
		    {
		      cur->selected = True;
Paul Reilly's avatar
Paul Reilly committed
987
		      val->value = safe_strdup (cur->name);
Richard M. Stallman's avatar
Richard M. Stallman committed
988 989 990 991 992 993 994 995 996 997 998 999
		    }
	      }
	  val->edited = 1;
	  XtFree ((char *) pos_list);
	}
    }
}


/* This function is for activating a button from a program.  It's wrong because
   we pass a NULL argument in the call_data which is not Motif compatible.
   This is used from the XmNdefaultAction callback of the List widgets to
1000
   have a double-click put down a dialog box like the button would do.
Richard M. Stallman's avatar
Richard M. Stallman committed
1001 1002 1003
   I could not find a way to do that with accelerators.
 */
static void
1004 1005 1006
activate_button (Widget widget,
                 XtPointer closure,
                 XtPointer call_data)
Richard M. Stallman's avatar
Richard M. Stallman committed
1007 1008 1009 1010 1011 1012 1013
{
  Widget button = (Widget)closure;
  XtCallCallbacks (button, XmNactivateCallback, NULL);
}

/* creation functions */

1014 1015
/* Called for key press in dialogs.  Used to pop down dialog on ESC.  */
static void
1016 1017 1018 1019
dialog_key_cb (Widget widget,
               XtPointer closure,
               XEvent *event,
               Boolean *continue_to_dispatch)
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
{
  KeySym sym = 0;
  Modifiers modif_ret;
  
  XtTranslateKeycode (event->xkey.display, event->xkey.keycode, 0,
                      &modif_ret, &sym);
                      
  if (sym == osfXK_Cancel)
    {
      Widget w = *((Widget *) closure);

      while (w && ! XtIsShell (w))
        w = XtParent (w);

      if (XtIsShell (w)) XtPopdown (w);
    }

  *continue_to_dispatch = TRUE;
}

Richard M. Stallman's avatar
Richard M. Stallman committed
1040 1041
/* dialogs */
static Widget
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051
make_dialog (char* name,
             Widget parent,
             Boolean pop_up_p,
             char* shell_title,
             char* icon_name,
             Boolean text_input_slot,
             Boolean radio_box,
             Boolean list,
             int left_buttons,
             int right_buttons)
Richard M. Stallman's avatar
Richard M. Stallman committed
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
{
  Widget result;
  Widget form;
  Widget row;
  Widget icon;
  Widget icon_separator;
  Widget message;
  Widget value = 0;
  Widget separator;
  Widget button = 0;
  Widget children [16];		/* for the final XtManageChildren */
  int	 n_children;
  Arg 	al[64];			/* Arg List */
  int 	ac;			/* Arg Count */
  int 	i;
1067

Richard M. Stallman's avatar
Richard M. Stallman committed
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
  if (pop_up_p)
    {
      ac = 0;
      XtSetArg(al[ac], XmNtitle, shell_title); ac++;
      XtSetArg(al[ac], XtNallowShellResize, True); ac++;
      XtSetArg(al[ac], XmNdeleteResponse, XmUNMAP); ac++;
      result = XmCreateDialogShell (parent, "dialog", al, ac);
      ac = 0;
      XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
/*      XtSetArg(al[ac], XmNautoUnmanage, TRUE); ac++; */ /* ####is this ok? */
      XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
      form = XmCreateForm (result, shell_title, al, ac);
    }
  else
    {
      ac = 0;
      XtSetArg(al[ac], XmNautoUnmanage, FALSE); ac++;
      XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
      form = XmCreateForm (parent, shell_title, al, ac);
      result = form;
    }

Richard M. Stallman's avatar
Richard M. Stallman committed
1090
  n_children = left_buttons + right_buttons + 1;
Richard M. Stallman's avatar
Richard M. Stallman committed
1091
  ac = 0;
1092
  XtSetArg(al[ac], XmNpacking, n_children == 3?
Richard M. Stallman's avatar
Richard M. Stallman committed
1093
	   XmPACK_COLUMN: XmPACK_TIGHT); ac++;
1094
  XtSetArg(al[ac], XmNorientation, n_children == 3?
Richard M. Stallman's avatar
Richard M. Stallman committed
1095
	   XmVERTICAL: XmHORIZONTAL); ac++;
Richard M. Stallman's avatar
Richard M. Stallman committed
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
  XtSetArg(al[ac], XmNnumColumns, left_buttons + right_buttons + 1); ac++;
  XtSetArg(al[ac], XmNmarginWidth, 0); ac++;
  XtSetArg(al[ac], XmNmarginHeight, 0); ac++;
  XtSetArg(al[ac], XmNspacing, 13); ac++;
  XtSetArg(al[ac], XmNadjustLast, False); ac++;
  XtSetArg(al[ac], XmNalignment, XmALIGNMENT_CENTER); ac++;
  XtSetArg(al[ac], XmNisAligned, True); ac++;
  XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
  XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
  XtSetArg(al[ac], XmNbottomOffset, 13); ac++;
  XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
  XtSetArg(al[ac], XmNleftOffset, 13); ac++;
  XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
  XtSetArg(al[ac], XmNrightOffset, 13); ac++;
  row = XmCreateRowColumn (form, "row", al, ac);
1111

Richard M. Stallman's avatar
Richard M. Stallman committed
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122
  n_children = 0;
  for (i = 0; i < left_buttons; i++)
    {
      char button_name [16];
      sprintf (button_name, "button%d", i + 1);
      ac = 0;
      if (i == 0)
	{
	  XtSetArg(al[ac], XmNhighlightThickness, 1); ac++;
	  XtSetArg(al[ac], XmNshowAsDefault, TRUE); ac++;
	}
Richard M. Stallman's avatar
Richard M. Stallman committed
1123
      XtSetArg(al[ac], XmNmarginWidth, 10); ac++;
Richard M. Stallman's avatar
Richard M. Stallman committed
1124 1125
      XtSetArg(al[ac], XmNnavigationType, XmTAB_GROUP); ac++;
      children [n_children] = XmCreatePushButton (row, button_name, al, ac);
1126 1127
      XtAddEventHandler (children [n_children],
                         KeyPressMask, False, dialog_key_cb, result);
Richard M. Stallman's avatar
Richard M. Stallman committed
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139

      if (i == 0)
	{
	  button = children [n_children];
	  ac = 0;
	  XtSetArg(al[ac], XmNdefaultButton, button); ac++;
	  XtSetValues (row, al, ac);
	}

      n_children++;
    }

Karl Heuer's avatar
Karl Heuer committed
1140
  /* invisible separator button */
Richard M. Stallman's avatar
Richard M. Stallman committed
1141 1142 1143 1144
  ac = 0;
  XtSetArg (al[ac], XmNmappedWhenManaged, FALSE); ac++;
  children [n_children] = XmCreateLabel (row, "separator_button", al, ac);
  n_children++;
1145

Richard M. Stallman's avatar
Richard M. Stallman committed
1146 1147 1148