lwlib.c 33.8 KB
Newer Older
Richard M. Stallman's avatar
Richard M. Stallman committed
1
/* A general interface to the widgets of different toolkits.
Glenn Morris's avatar
Glenn Morris committed
2

Glenn Morris's avatar
Glenn Morris committed
3
Copyright (C) 1992, 1993 Lucid, Inc.
Paul Eggert's avatar
Paul Eggert committed
4
Copyright (C) 1994-1996, 1999-2020 Free Software Foundation, 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 2, 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
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
19
along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
20

21 22
#include <config.h>

23
#include <setjmp.h>
Glenn Morris's avatar
Glenn Morris committed
24
#include <lisp.h>
25
#include <c-strcase.h>
26

Richard M. Stallman's avatar
Richard M. Stallman committed
27 28
#include <sys/types.h>
#include <stdio.h>
29
#include "lwlib-int.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
30
#include "lwlib-utils.h"
31
#include <X11/StringDefs.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
32 33 34 35 36 37

#if defined (USE_LUCID)
#include "lwlib-Xlw.h"
#endif
#if defined (USE_MOTIF)
#include "lwlib-Xm.h"
Fred Pierresteguy's avatar
Fred Pierresteguy committed
38 39 40 41
#else /* not USE_MOTIF */
#if defined (USE_LUCID)
#define USE_XAW
#endif /* not USE_MOTIF && USE_LUCID */
Richard M. Stallman's avatar
Richard M. Stallman committed
42
#endif
Fred Pierresteguy's avatar
Fred Pierresteguy committed
43
#if defined (USE_XAW)
Chong Yidong's avatar
Chong Yidong committed
44 45 46
#ifdef HAVE_XAW3D
#include <X11/Xaw3d/Paned.h>
#else /* !HAVE_XAW3D */
Andreas Schwab's avatar
Andreas Schwab committed
47
#include <X11/Xaw/Paned.h>
Chong Yidong's avatar
Chong Yidong committed
48
#endif /* HAVE_XAW3D */
Fred Pierresteguy's avatar
Fred Pierresteguy committed
49 50
#include "lwlib-Xaw.h"
#endif
Richard M. Stallman's avatar
Richard M. Stallman committed
51

Dave Love's avatar
Dave Love committed
52 53
#if !defined (USE_LUCID) && !defined (USE_MOTIF)
 #error  At least one of USE_LUCID or USE_MOTIF must be defined.
Richard M. Stallman's avatar
Richard M. Stallman committed
54 55
#endif

Paul Reilly's avatar
Paul Reilly committed
56 57 58 59
#ifndef max
#define max(x, y) ((x) > (y) ? (x) : (y))
#endif

Richard M. Stallman's avatar
Richard M. Stallman committed
60 61 62 63
/* List of all widgets managed by the library. */
static widget_info*
all_widget_info = NULL;

64
#ifdef USE_MOTIF
65
const char *lwlib_toolkit_type = "motif";
66
#else
67
const char *lwlib_toolkit_type = "lucid";
68
#endif
Richard M. Stallman's avatar
Richard M. Stallman committed
69

70 71 72 73 74 75 76
static widget_value *merge_widget_value (widget_value *,
                                         widget_value *,
                                         int, int *);
static void instantiate_widget_instance (widget_instance *);
static void free_widget_value_tree (widget_value *);
static widget_value *copy_widget_value_tree (widget_value *,
                                             change_type);
77
static widget_info *allocate_widget_info (const char *, const char *, LWLIB_ID,
78 79 80 81 82 83 84 85 86 87 88
                                          widget_value *,
                                          lw_callback, lw_callback,
                                          lw_callback, lw_callback);
static void free_widget_info (widget_info *);
static void mark_widget_destroyed (Widget, XtPointer, XtPointer);
static widget_instance *allocate_widget_instance (widget_info *,
                                                  Widget, Boolean);
static void free_widget_instance (widget_instance *);
static widget_info *get_widget_info (LWLIB_ID, Boolean);
static widget_instance *get_widget_instance (Widget, Boolean);
static widget_instance *find_instance (LWLIB_ID, Widget, Boolean);
89 90
static Boolean safe_strcmp (const char *, const char *);
static Widget name_to_widget (widget_instance *, const char *);
91 92 93 94
static void set_one_value (widget_instance *, widget_value *, Boolean);
static void update_one_widget_instance (widget_instance *, Boolean);
static void update_all_widget_values (widget_info *, Boolean);
static void initialize_widget_instance (widget_instance *);
95 96
static widget_creation_function find_in_table (const char *, const widget_creation_entry *);
static Boolean dialog_spec_p (const char *);
97 98 99 100
static void destroy_one_instance (widget_instance *);
static void lw_pop_all_widgets (LWLIB_ID, Boolean);
static Boolean get_one_value (widget_instance *, widget_value *);
static void show_one_widget_busy (Widget, Boolean);
Richard M. Stallman's avatar
Richard M. Stallman committed
101 102

static void
103
free_widget_value_tree (widget_value *wv)
Richard M. Stallman's avatar
Richard M. Stallman committed
104 105 106 107
{
  if (!wv)
    return;

108 109 110
  xfree (wv->name);
  xfree (wv->value);
  xfree (wv->key);
Richard M. Stallman's avatar
Richard M. Stallman committed
111

112
  wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
Richard M. Stallman's avatar
Richard M. Stallman committed
113 114 115

  if (wv->toolkit_data && wv->free_toolkit_data)
    {
116
      XtFree (wv->toolkit_data);
Richard M. Stallman's avatar
Richard M. Stallman committed
117 118 119 120 121 122 123 124 125 126 127 128 129
      wv->toolkit_data = (void *) 0xDEADBEEF;
    }

  if (wv->contents && (wv->contents != (widget_value*)1))
    {
      free_widget_value_tree (wv->contents);
      wv->contents = (widget_value *) 0xDEADBEEF;
    }
  if (wv->next)
    {
      free_widget_value_tree (wv->next);
      wv->next = (widget_value *) 0xDEADBEEF;
    }
130
  xfree (wv);
Richard M. Stallman's avatar
Richard M. Stallman committed
131 132 133
}

static widget_value *
134
copy_widget_value_tree (widget_value *val, change_type change)
Richard M. Stallman's avatar
Richard M. Stallman committed
135 136
{
  widget_value* copy;
137

Richard M. Stallman's avatar
Richard M. Stallman committed
138 139 140 141 142
  if (!val)
    return NULL;
  if (val == (widget_value *) 1)
    return val;

143 144
  copy = xmalloc (sizeof (widget_value));
  copy->lname = copy->lkey = Qnil;
145 146 147
  copy->name = xstrdup (val->name);
  copy->value = val->value ? xstrdup (val->value) : NULL;
  copy->key = val->key ? xstrdup (val->key) : NULL;
148
  copy->help = val->help;
Richard M. Stallman's avatar
Richard M. Stallman committed
149
  copy->enabled = val->enabled;
Gerd Moellmann's avatar
Gerd Moellmann committed
150
  copy->button_type = val->button_type;
Richard M. Stallman's avatar
Richard M. Stallman committed
151 152 153
  copy->selected = val->selected;
  copy->edited = False;
  copy->change = change;
154
  copy->this_one_change = change;
Richard M. Stallman's avatar
Richard M. Stallman committed
155 156 157 158 159 160 161 162 163
  copy->contents = copy_widget_value_tree (val->contents, change);
  copy->call_data = val->call_data;
  copy->next = copy_widget_value_tree (val->next, change);
  copy->toolkit_data = NULL;
  copy->free_toolkit_data = False;
  return copy;
}

static widget_info *
164 165
allocate_widget_info (const char* type,
                      const char* name,
166 167 168 169 170 171
                      LWLIB_ID id,
                      widget_value* val,
                      lw_callback pre_activate_cb,
                      lw_callback selection_cb,
                      lw_callback post_activate_cb,
                      lw_callback highlight_cb)
Richard M. Stallman's avatar
Richard M. Stallman committed
172
{
Jan D's avatar
Jan D committed
173
  widget_info* info = (widget_info*) xmalloc (sizeof (widget_info));
174 175
  info->type = xstrdup (type);
  info->name = xstrdup (name);
Richard M. Stallman's avatar
Richard M. Stallman committed
176 177 178 179 180 181
  info->id = id;
  info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
  info->busy = False;
  info->pre_activate_cb = pre_activate_cb;
  info->selection_cb = selection_cb;
  info->post_activate_cb = post_activate_cb;
182
  info->highlight_cb = highlight_cb;
Richard M. Stallman's avatar
Richard M. Stallman committed
183 184 185 186 187 188 189 190 191
  info->instances = NULL;

  info->next = all_widget_info;
  all_widget_info = info;

  return info;
}

static void
192
free_widget_info (widget_info *info)
Richard M. Stallman's avatar
Richard M. Stallman committed
193
{
194 195
  xfree (info->type);
  xfree (info->name);
Richard M. Stallman's avatar
Richard M. Stallman committed
196
  free_widget_value_tree (info->val);
197
  memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
198
  xfree (info);
Richard M. Stallman's avatar
Richard M. Stallman committed
199 200 201
}

static void
202
mark_widget_destroyed (Widget widget, XtPointer closure, XtPointer call_data)
Richard M. Stallman's avatar
Richard M. Stallman committed
203 204 205 206 207 208 209 210 211
{
  widget_instance* instance = (widget_instance*)closure;

  /* be very conservative */
  if (instance->widget == widget)
    instance->widget = NULL;
}

static widget_instance *
Dave Love's avatar
Dave Love committed
212
allocate_widget_instance (widget_info* info, Widget parent, Boolean pop_up_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
213 214
{
  widget_instance* instance =
Jan D's avatar
Jan D committed
215
    (widget_instance*) xmalloc (sizeof (widget_instance));
216
  memset (instance, 0, sizeof *instance);
Richard M. Stallman's avatar
Richard M. Stallman committed
217 218 219 220 221 222
  instance->parent = parent;
  instance->pop_up_p = pop_up_p;
  instance->info = info;
  instance->next = info->instances;
  info->instances = instance;

223
  instantiate_widget_instance (instance);
Richard M. Stallman's avatar
Richard M. Stallman committed
224 225 226 227 228 229 230

  XtAddCallback (instance->widget, XtNdestroyCallback,
		 mark_widget_destroyed, (XtPointer)instance);
  return instance;
}

static void
231
free_widget_instance (widget_instance *instance)
Richard M. Stallman's avatar
Richard M. Stallman committed
232
{
233
  memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
234
  xfree (instance);
Richard M. Stallman's avatar
Richard M. Stallman committed
235 236 237
}

static widget_info *
Dave Love's avatar
Dave Love committed
238
get_widget_info (LWLIB_ID id, Boolean remove_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
{
  widget_info* info;
  widget_info* prev;
  for (prev = NULL, info = all_widget_info;
       info;
       prev = info, info = info->next)
    if (info->id == id)
     {
       if (remove_p)
	 {
	   if (prev)
	     prev->next = info->next;
	   else
	     all_widget_info = info->next;
	 }
      return info;
     }
  return NULL;
}

Fred Pierresteguy's avatar
Fred Pierresteguy committed
259 260 261
/* Internal function used by the library dependent implementation to get the
   widget_value for a given widget in an instance */
widget_info *
262
lw_get_widget_info (LWLIB_ID id)
Fred Pierresteguy's avatar
Fred Pierresteguy committed
263 264 265 266
{
  return get_widget_info (id, 0);
}

Richard M. Stallman's avatar
Richard M. Stallman committed
267
static widget_instance *
Dave Love's avatar
Dave Love committed
268
get_widget_instance (Widget widget, Boolean remove_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
{
  widget_info* info;
  widget_instance* instance;
  widget_instance* prev;
  for (info = all_widget_info; info; info = info->next)
    for (prev = NULL, instance = info->instances;
	 instance;
	 prev = instance, instance = instance->next)
      if (instance->widget == widget)
	{
	  if (remove_p)
	    {
	      if (prev)
		prev->next = instance->next;
	      else
		info->instances = instance->next;
	    }
	  return instance;
	}
  return (widget_instance *) 0;
}

291 292 293 294
/* Value is a pointer to the widget_instance corresponding to
   WIDGET, or null if WIDGET is not a lwlib widget.  */

widget_instance *
295
lw_get_widget_instance (Widget widget)
296 297 298 299
{
  return get_widget_instance (widget, False);
}

Richard M. Stallman's avatar
Richard M. Stallman committed
300
static widget_instance*
Dave Love's avatar
Dave Love committed
301
find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
{
  widget_info* info = get_widget_info (id, False);
  widget_instance* instance;

  if (info)
    for (instance = info->instances; instance; instance = instance->next)
      if (instance->parent == parent && instance->pop_up_p == pop_up_p)
	return instance;

  return NULL;
}


/* utility function for widget_value */
static Boolean
317
safe_strcmp (const char *s1, const char *s2)
Richard M. Stallman's avatar
Richard M. Stallman committed
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
{
  if (!!s1 ^ !!s2) return True;
  return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
}


#if 0
# define EXPLAIN(name, oc, nc, desc, a1, a2)				\
   printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n",		\
	   name,							\
	   (oc == NO_CHANGE ? "none" :					\
	    (oc == INVISIBLE_CHANGE ? "invisible" :			\
	     (oc == VISIBLE_CHANGE ? "visible" :			\
	      (oc == STRUCTURAL_CHANGE ? "structural" : "???")))),	\
	   oc,								\
	   (nc == NO_CHANGE ? "none" :					\
	    (nc == INVISIBLE_CHANGE ? "invisible" :			\
	     (nc == VISIBLE_CHANGE ? "visible" :			\
	      (nc == STRUCTURAL_CHANGE ? "structural" : "???")))),	\
	   nc, desc, a1, a2)
#else
339
# define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
Richard M. Stallman's avatar
Richard M. Stallman committed
340 341 342 343
#endif


static widget_value *
344 345 346 347
merge_widget_value (widget_value *val1,
                    widget_value *val2,
                    int level,
                    int *change_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
348
{
349
  change_type change, this_one_change;
Richard M. Stallman's avatar
Richard M. Stallman committed
350 351 352 353 354 355
  widget_value* merged_next;
  widget_value* merged_contents;

  if (!val1)
    {
      if (val2)
356 357 358 359
	{
	  *change_p = 1;
	  return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
	}
Richard M. Stallman's avatar
Richard M. Stallman committed
360 361 362 363 364
      else
	return NULL;
    }
  if (!val2)
    {
365
      *change_p = 1;
Richard M. Stallman's avatar
Richard M. Stallman committed
366 367 368
      free_widget_value_tree (val1);
      return NULL;
    }
369

Richard M. Stallman's avatar
Richard M. Stallman committed
370 371 372 373 374 375 376
  change = NO_CHANGE;

  if (safe_strcmp (val1->name, val2->name))
    {
      EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
	       val1->name, val2->name);
      change = max (change, STRUCTURAL_CHANGE);
377
      dupstring (&val1->name, val2->name);
Richard M. Stallman's avatar
Richard M. Stallman committed
378 379 380 381 382 383
    }
  if (safe_strcmp (val1->value, val2->value))
    {
      EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
	       val1->value, val2->value);
      change = max (change, VISIBLE_CHANGE);
384
      dupstring (&val1->value, val2->value);
Richard M. Stallman's avatar
Richard M. Stallman committed
385 386 387 388 389 390
    }
  if (safe_strcmp (val1->key, val2->key))
    {
      EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
	       val1->key, val2->key);
      change = max (change, VISIBLE_CHANGE);
391
      dupstring (&val1->key, val2->key);
Richard M. Stallman's avatar
Richard M. Stallman committed
392
    }
393
  if (! EQ (val1->help, val2->help))
394 395 396 397
    {
      EXPLAIN (val1->name, change, VISIBLE_CHANGE, "help change",
	       val1->help, val2->help);
      change = max (change, VISIBLE_CHANGE);
398
      val1->help = val2->help;
399
    }
Richard M. Stallman's avatar
Richard M. Stallman committed
400 401 402 403 404 405 406
  if (val1->enabled != val2->enabled)
    {
      EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
	       val1->enabled, val2->enabled);
      change = max (change, VISIBLE_CHANGE);
      val1->enabled = val2->enabled;
    }
Gerd Moellmann's avatar
Gerd Moellmann committed
407 408 409 410 411 412 413
  if (val1->button_type != val2->button_type)
    {
      EXPLAIN (val1->name, change, VISIBLE_CHANGE, "button type change",
	       val1->button_type, val2->button_type);
      change = max (change, VISIBLE_CHANGE);
      val1->button_type = val2->button_type;
    }
Richard M. Stallman's avatar
Richard M. Stallman committed
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
  if (val1->selected != val2->selected)
    {
      EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
	       val1->selected, val2->selected);
      change = max (change, VISIBLE_CHANGE);
      val1->selected = val2->selected;
    }
  if (val1->call_data != val2->call_data)
    {
      EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
	       val1->call_data, val2->call_data);
      change = max (change, INVISIBLE_CHANGE);
      val1->call_data = val2->call_data;
    }

  if (level > 0)
    {
      merged_contents =
432 433
	merge_widget_value (val1->contents, val2->contents, level - 1,
			    change_p);
434

Richard M. Stallman's avatar
Richard M. Stallman committed
435 436
      if (val1->contents && !merged_contents)
	{
437 438 439 440 441 442
	  /* This used to say INVISIBLE_CHANGE,
	     but it is visible and vitally important when
	     the contents of the menu bar itself are entirely deleted.

	     But maybe it doesn't matter.  This fails to fix the bug.  */
	  EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(contents gone)",
Richard M. Stallman's avatar
Richard M. Stallman committed
443
		   0, 0);
444
	  change = max (change, STRUCTURAL_CHANGE);
Richard M. Stallman's avatar
Richard M. Stallman committed
445 446 447 448 449 450
	}
      else if (merged_contents && merged_contents->change != NO_CHANGE)
	{
	  EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
		   0, 0);
	  change = max (change, INVISIBLE_CHANGE);
451
#if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c.  */
452 453
#ifdef USE_MOTIF
	  change = max (merged_contents->change, change);
454
#endif
455
#endif
Richard M. Stallman's avatar
Richard M. Stallman committed
456
	}
457

Richard M. Stallman's avatar
Richard M. Stallman committed
458 459 460
      val1->contents = merged_contents;
    }

461 462
  this_one_change = change;

463
  merged_next = merge_widget_value (val1->next, val2->next, level, change_p);
Richard M. Stallman's avatar
Richard M. Stallman committed
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480

  if (val1->next && !merged_next)
    {
      EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
	       0, 0);
      change = max (change, STRUCTURAL_CHANGE);
    }
  else if (merged_next)
    {
      if (merged_next->change)
	EXPLAIN (val1->name, change, merged_next->change, "(following change)",
		 0, 0);
      change = max (change, merged_next->change);
    }

  val1->next = merged_next;

481
  val1->this_one_change = this_one_change;
Richard M. Stallman's avatar
Richard M. Stallman committed
482
  val1->change = change;
483

Richard M. Stallman's avatar
Richard M. Stallman committed
484 485
  if (change > NO_CHANGE && val1->toolkit_data)
    {
486
      *change_p = 1;
Richard M. Stallman's avatar
Richard M. Stallman committed
487
      if (val1->free_toolkit_data)
488
	XtFree (val1->toolkit_data);
Richard M. Stallman's avatar
Richard M. Stallman committed
489 490 491 492 493 494 495 496 497
      val1->toolkit_data = NULL;
    }

  return val1;
}


/* modifying the widgets */
static Widget
498
name_to_widget (widget_instance *instance, const char *name)
Richard M. Stallman's avatar
Richard M. Stallman committed
499 500 501 502 503 504 505 506 507 508 509
{
  Widget widget = NULL;

  if (!instance->widget)
    return NULL;

  if (!strcmp (XtName (instance->widget), name))
    widget = instance->widget;
  else
    {
      int length = strlen (name) + 2;
510
      char* real_name = (char *) xmalloc (length);
Richard M. Stallman's avatar
Richard M. Stallman committed
511 512
      real_name [0] = '*';
      strcpy (real_name + 1, name);
513

Richard M. Stallman's avatar
Richard M. Stallman committed
514
      widget = XtNameToWidget (instance->widget, real_name);
515

516
      xfree (real_name);
Richard M. Stallman's avatar
Richard M. Stallman committed
517 518 519 520 521
    }
  return widget;
}

static void
Dave Love's avatar
Dave Love committed
522
set_one_value (widget_instance* instance, widget_value* val, Boolean deep_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
523 524
{
  Widget widget = name_to_widget (instance, val->name);
525

Richard M. Stallman's avatar
Richard M. Stallman committed
526 527 528 529 530 531 532 533 534 535
  if (widget)
    {
#if defined (USE_LUCID)
      if (lw_lucid_widget_p (instance->widget))
	xlw_update_one_widget (instance, widget, val, deep_p);
#endif
#if defined (USE_MOTIF)
      if (lw_motif_widget_p (instance->widget))
	xm_update_one_widget (instance, widget, val, deep_p);
#endif
Fred Pierresteguy's avatar
Fred Pierresteguy committed
536 537 538
#if defined (USE_XAW)
      if (lw_xaw_widget_p (instance->widget))
	xaw_update_one_widget (instance, widget, val, deep_p);
Richard M. Stallman's avatar
Richard M. Stallman committed
539 540 541 542 543
#endif
    }
}

static void
Dave Love's avatar
Dave Love committed
544
update_one_widget_instance (widget_instance* instance, Boolean deep_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
545 546 547 548 549 550 551 552 553 554 555 556 557
{
  widget_value *val;

  if (!instance->widget)
    /* the widget was destroyed */
    return;

  for (val = instance->info->val; val; val = val->next)
    if (val->change != NO_CHANGE)
      set_one_value (instance, val, deep_p);
}

static void
Dave Love's avatar
Dave Love committed
558
update_all_widget_values (widget_info* info, Boolean deep_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
559 560 561 562 563 564 565 566 567 568 569
{
  widget_instance* instance;
  widget_value* val;

  for (instance = info->instances; instance; instance = instance->next)
    update_one_widget_instance (instance, deep_p);

  for (val = info->val; val; val = val->next)
    val->change = NO_CHANGE;
}

570
int
Dave Love's avatar
Dave Love committed
571
lw_modify_all_widgets (LWLIB_ID id, widget_value* val, Boolean deep_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
572 573 574 575 576 577 578 579
{
  widget_info* info = get_widget_info (id, False);
  widget_value* new_val;
  widget_value* next_new_val;
  widget_value* cur;
  widget_value* prev;
  widget_value* next;
  int		found;
580
  int change_p = 0;
Richard M. Stallman's avatar
Richard M. Stallman committed
581 582

  if (!info)
Dave Love's avatar
Dave Love committed
583
    return 0;
Richard M. Stallman's avatar
Richard M. Stallman committed
584 585 586 587 588 589 590 591 592 593 594 595

  for (new_val = val; new_val; new_val = new_val->next)
    {
      next_new_val = new_val->next;
      new_val->next = NULL;
      found = False;
      for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
	if (!strcmp (cur->name, new_val->name))
	  {
	    found = True;
	    next = cur->next;
	    cur->next = NULL;
596 597
	    cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1,
				      &change_p);
Richard M. Stallman's avatar
Richard M. Stallman committed
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
	    if (prev)
	      prev->next = cur ? cur : next;
	    else
	      info->val = cur ? cur : next;
	    if (cur)
	      cur->next = next;
	    break;
	  }
      if (!found)
	{
	  /* Could not find it, add it */
	  if (prev)
	    prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
	  else
	    info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
613
	  change_p = 1;
Richard M. Stallman's avatar
Richard M. Stallman committed
614 615 616 617 618
	}
      new_val->next = next_new_val;
    }

  update_all_widget_values (info, deep_p);
619
  return change_p;
Richard M. Stallman's avatar
Richard M. Stallman committed
620 621 622 623 624 625
}


/* creating the widgets */

static void
626
initialize_widget_instance (widget_instance *instance)
Richard M. Stallman's avatar
Richard M. Stallman committed
627 628 629 630 631 632 633 634 635 636 637 638 639 640
{
  widget_value* val;

  for (val = instance->info->val; val; val = val->next)
    val->change = STRUCTURAL_CHANGE;

  update_one_widget_instance (instance, True);

  for (val = instance->info->val; val; val = val->next)
    val->change = NO_CHANGE;
}


static widget_creation_function
641
find_in_table (const char *type, const widget_creation_entry *table)
Richard M. Stallman's avatar
Richard M. Stallman committed
642
{
643
  const widget_creation_entry* cur;
Richard M. Stallman's avatar
Richard M. Stallman committed
644
  for (cur = table; cur->type; cur++)
645
    if (!c_strcasecmp (type, cur->type))
Richard M. Stallman's avatar
Richard M. Stallman committed
646 647 648 649 650
      return cur->function;
  return NULL;
}

static Boolean
651
dialog_spec_p (const char *name)
Richard M. Stallman's avatar
Richard M. Stallman committed
652
{
653
  /* return True if name matches [EILPQeilpq][1-9][Bb] or
Richard M. Stallman's avatar
Richard M. Stallman committed
654 655 656
     [EILPQeilpq][1-9][Bb][Rr][1-9] */
  if (!name)
    return False;
657

Richard M. Stallman's avatar
Richard M. Stallman committed
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
  switch (name [0])
    {
    case 'E': case 'I': case 'L': case 'P': case 'Q':
    case 'e': case 'i': case 'l': case 'p': case 'q':
      if (name [1] >= '0' && name [1] <= '9')
	{
	  if (name [2] != 'B' && name [2] != 'b')
	    return False;
	  if (!name [3])
	    return True;
	  if ((name [3] == 'T' || name [3] == 't') && !name [4])
	    return True;
	  if ((name [3] == 'R' || name [3] == 'r')
	      && name [4] >= '0' && name [4] <= '9' && !name [5])
	    return True;
	  return False;
	}
      else
	return False;
677

Richard M. Stallman's avatar
Richard M. Stallman committed
678 679 680 681 682 683
    default:
      return False;
    }
}

static void
684
instantiate_widget_instance (widget_instance *instance)
Richard M. Stallman's avatar
Richard M. Stallman committed
685 686 687 688 689 690 691 692 693 694 695
{
  widget_creation_function function = NULL;

#if defined (USE_LUCID)
  if (!function)
    function = find_in_table (instance->info->type, xlw_creation_table);
#endif
#if defined(USE_MOTIF)
  if (!function)
    function = find_in_table (instance->info->type, xm_creation_table);
#endif
Fred Pierresteguy's avatar
Fred Pierresteguy committed
696 697 698 699
#if defined (USE_XAW)
  if (!function)
    function = find_in_table (instance->info->type, xaw_creation_table);
#endif
Richard M. Stallman's avatar
Richard M. Stallman committed
700 701 702 703 704 705 706 707 708 709 710 711

  if (!function)
    {
      if (dialog_spec_p (instance->info->type))
	{
#if defined (USE_LUCID)
	  /* not yet */
#endif
#if defined(USE_MOTIF)
	  if (!function)
	    function = xm_create_dialog;
#endif
Fred Pierresteguy's avatar
Fred Pierresteguy committed
712 713 714
#if defined (USE_XAW)
	  if (!function)
	    function = xaw_create_dialog;
Richard M. Stallman's avatar
Richard M. Stallman committed
715 716 717
#endif
	}
    }
718

Richard M. Stallman's avatar
Richard M. Stallman committed
719 720 721 722
  if (!function)
    {
      printf ("No creation function for widget type %s\n",
	      instance->info->type);
723
      emacs_abort ();
Richard M. Stallman's avatar
Richard M. Stallman committed
724 725 726 727 728
    }

  instance->widget = (*function) (instance);

  if (!instance->widget)
729
    emacs_abort ();
Richard M. Stallman's avatar
Richard M. Stallman committed
730 731 732 733

  /*   XtRealizeWidget (instance->widget);*/
}

734
void
735 736
lw_register_widget (const char* type,
                    const char* name,
737 738 739 740 741 742
                    LWLIB_ID id,
                    widget_value* val,
                    lw_callback pre_activate_cb,
                    lw_callback selection_cb,
                    lw_callback post_activate_cb,
                    lw_callback highlight_cb)
Richard M. Stallman's avatar
Richard M. Stallman committed
743 744 745
{
  if (!get_widget_info (id, False))
    allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
746
			  post_activate_cb, highlight_cb);
Richard M. Stallman's avatar
Richard M. Stallman committed
747 748 749
}

Widget
Dave Love's avatar
Dave Love committed
750
lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
751 752
{
  widget_instance* instance;
753

Richard M. Stallman's avatar
Richard M. Stallman committed
754 755 756 757 758
  instance = find_instance (id, parent, pop_up_p);
  return instance ? instance->widget : NULL;
}

Widget
Dave Love's avatar
Dave Love committed
759
lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
Richard M. Stallman's avatar
Richard M. Stallman committed
760 761 762
{
  widget_instance* instance;
  widget_info* info;
763

Richard M. Stallman's avatar
Richard M. Stallman committed
764 765 766 767 768 769 770 771 772 773
  instance = find_instance (id, parent, pop_up_p);
  if (!instance)
    {
      info = get_widget_info (id, False);
      if (!info)
	return NULL;
      instance = allocate_widget_instance (info, parent, pop_up_p);
      initialize_widget_instance (instance);
    }
  if (!instance->widget)
774
    emacs_abort ();
Richard M. Stallman's avatar
Richard M. Stallman committed
775 776 777 778
  return instance->widget;
}

Widget
779
lw_create_widget (const char* type, const char* name, LWLIB_ID id, widget_value* val,
Dave Love's avatar
Dave Love committed
780 781 782
		  Widget parent, Boolean pop_up_p,
		  lw_callback pre_activate_cb, lw_callback selection_cb,
		  lw_callback post_activate_cb, lw_callback highlight_cb)
Richard M. Stallman's avatar
Richard M. Stallman committed
783 784
{
  lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
785
		      post_activate_cb, highlight_cb);
Richard M. Stallman's avatar
Richard M. Stallman committed
786 787
  return lw_make_widget (id, parent, pop_up_p);
}
788

Richard M. Stallman's avatar
Richard M. Stallman committed
789 790 791

/* destroying the widgets */
static void
792
destroy_one_instance (widget_instance *instance)
Richard M. Stallman's avatar
Richard M. Stallman committed
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
{
  /* Remove the destroy callback on the widget; that callback will try to
     dereference the instance object (to set its widget slot to 0, since the
     widget is dead.)  Since the instance is now dead, we don't have to worry
     about the fact that its widget is dead too.

     This happens in the Phase2Destroy of the widget, so this callback would
     not have been run until arbitrarily long after the instance was freed.
   */
  if (instance->widget)
    XtRemoveCallback (instance->widget, XtNdestroyCallback,
		      mark_widget_destroyed, (XtPointer)instance);

  if (instance->widget)
    {
      /* The else are pretty tricky here, including the empty statement
	 at the end because it would be very bad to destroy a widget
	 twice. */
#if defined (USE_LUCID)
      if (lw_lucid_widget_p (instance->widget))
	xlw_destroy_instance (instance);
      else
#endif
#if defined (USE_MOTIF)
      if (lw_motif_widget_p (instance->widget))
	xm_destroy_instance (instance);
      else
#endif
Fred Pierresteguy's avatar
Fred Pierresteguy committed
821 822 823
#if defined (USE_XAW)
      if (lw_xaw_widget_p (instance->widget))
	xaw_destroy_instance (instance);
824
      else
Richard M. Stallman's avatar
Richard M. Stallman committed
825
#endif
826 827 828
	{
	  /* Empty compound statement to terminate if-then-else chain.  */
	}
Richard M. Stallman's avatar
Richard M. Stallman committed
829 830 831 832 833 834
    }

  free_widget_instance (instance);
}

void
835
lw_destroy_widget (Widget w)
Richard M. Stallman's avatar
Richard M. Stallman committed
836 837
{
  widget_instance* instance = get_widget_instance (w, True);
838

Richard M. Stallman's avatar
Richard M. Stallman committed
839 840 841 842 843 844 845 846 847 848 849 850
  if (instance)
    {
      widget_info *info = instance->info;
      /* instance has already been removed from the list; free it */
      destroy_one_instance (instance);
      /* if there are no instances left, free the info too */
      if (!info->instances)
	lw_destroy_all_widgets (info->id);
    }
}

void
851
lw_destroy_all_widgets (LWLIB_ID id)
Richard M. Stallman's avatar
Richard M. Stallman committed
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869
{
  widget_info* info = get_widget_info (id, True);
  widget_instance* instance;
  widget_instance* next;

  if (info)
    {
      for (instance = info->instances; instance; )
	{
	  next = instance->next;
	  destroy_one_instance (instance);
	  instance = next;
	}
      free_widget_info (info);
    }
}

void
870
lw_destroy_everything (void)
Richard M. Stallman's avatar
Richard M. Stallman committed
871 872 873 874 875 876
{
  while (all_widget_info)
    lw_destroy_all_widgets (all_widget_info->id);
}

void
877
lw_destroy_all_pop_ups (void)
Richard M. Stallman's avatar
Richard M. Stallman committed
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892
{
  widget_info* info;
  widget_info* next;
  widget_instance* instance;

  for (info = all_widget_info; info; info = next)
    {
      next = info->next;
      instance = info->instances;
      if (instance && instance->pop_up_p)
	lw_destroy_all_widgets (info->id);
    }
}

#ifdef USE_MOTIF
893
extern Widget first_child (Widget);	/* garbage */
Richard M. Stallman's avatar
Richard M. Stallman committed
894 895 896
#endif

Widget
897
lw_raise_all_pop_up_widgets (void)
Richard M. Stallman's avatar
Richard M. Stallman committed
898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
{
  widget_info* info;
  widget_instance* instance;
  Widget result = NULL;

  for (info = all_widget_info; info; info = info->next)
    for (instance = info->instances; instance; instance = instance->next)
      if (instance->pop_up_p)
	{
	  Widget widget = instance->widget;
	  if (widget)
	    {
	      if (XtIsManaged (widget)
#ifdef USE_MOTIF
		  /* What a complete load of crap!!!!
		     When a dialogShell is on the screen, it is not managed!
		   */
		  || (lw_motif_widget_p (instance->widget) &&
		      XtIsManaged (first_child (widget)))
#endif
		  )
		{
		  if (!result)
		    result = widget;
		  XMapRaised (XtDisplay (widget), XtWindow (widget));
		}
	    }
	}
  return result;
}

static void
Dave Love's avatar
Dave Love committed
930
lw_pop_all_widgets (LWLIB_ID id, Boolean up)
Richard M. Stallman's avatar
Richard M. Stallman committed
931 932 933 934 935 936 937 938 939 940
{
  widget_info* info = get_widget_info (id, False);
  widget_instance* instance;

  if (info)
    for (instance = info->instances; instance; instance = instance->next)
      if (instance->pop_up_p && instance->widget)
	{
#if defined (USE_LUCID)
	  if (lw_lucid_widget_p (instance->widget))
Fred Pierresteguy's avatar
Fred Pierresteguy committed
941 942 943 944
	    {
	      XtRealizeWidget (instance->widget);
	      xlw_pop_instance (instance, up);
	    }
Richard M. Stallman's avatar
Richard M. Stallman committed
945 946 947
#endif
#if defined (USE_MOTIF)
	  if (lw_motif_widget_p (instance->widget))
Fred Pierresteguy's avatar
Fred Pierresteguy committed
948 949 950 951
	    {
	      XtRealizeWidget (instance->widget);
	      xm_pop_instance (instance, up);
	    }
Richard M. Stallman's avatar
Richard M. Stallman committed
952
#endif
Fred Pierresteguy's avatar
Fred Pierresteguy committed
953 954 955 956 957 958 959
#if defined (USE_XAW)
	  if (lw_xaw_widget_p (instance->widget))
	    {
	      XtRealizeWidget (XtParent (instance->widget));
	      XtRealizeWidget (instance->widget);
	      xaw_pop_instance (instance, up);
	    }
Richard M. Stallman's avatar
Richard M. Stallman committed
960 961 962 963 964
#endif
	}
}

void
965
lw_pop_up_all_widgets (LWLIB_ID id)
Richard M. Stallman's avatar
Richard M. Stallman committed
966 967 968 969 970
{
  lw_pop_all_widgets (id, True);
}

void
971
lw_pop_down_all_widgets (LWLIB_ID id)
Richard M. Stallman's avatar
Richard M. Stallman committed
972 973 974 975 976
{
  lw_pop_all_widgets (id, False);
}

void
977
lw_popup_menu (Widget widget, XEvent *event)
Richard M. Stallman's avatar
Richard M. Stallman committed
978 979 980
{
#if defined (USE_LUCID)
  if (lw_lucid_widget_p (widget))
981
    xlw_popup_menu (widget, event);
Richard M. Stallman's avatar
Richard M. Stallman committed
982 983 984
#endif
#if defined (USE_MOTIF)
  if (lw_motif_widget_p (widget))
985
    xm_popup_menu (widget, event);
Richard M. Stallman's avatar
Richard M. Stallman committed
986
#endif
Fred Pierresteguy's avatar
Fred Pierresteguy committed
987 988
#if defined (USE_XAW)
  if (lw_xaw_widget_p (widget))
989
    xaw_popup_menu (widget, event);
Fred Pierresteguy's avatar
Fred Pierresteguy committed
990
#endif
Richard M. Stallman's avatar
Richard M. Stallman committed
991 992 993 994
}

/* get the values back */
static Boolean
995
get_one_value (widget_instance *instance, widget_value *val)
Richard M. Stallman's avatar
Richard M. Stallman committed
996 997
{
  Widget widget = name_to_widget (instance, val->name);
998

Richard M. Stallman's avatar
Richard M. Stallman committed
999 1000 1001 1002 1003 1004 1005 1006 1007 1008
  if (widget)
    {
#if defined (USE_LUCID)
      if (lw_lucid_widget_p (instance->widget))
	xlw_update_one_value (instance, widget, val);
#endif
#if defined (USE_MOTIF)
      if (lw_motif_widget_p (instance->widget))
	xm_update_one_value (instance, widget, val);
#endif
Fred Pierresteguy's avatar
Fred Pierresteguy committed
1009 1010 1011
#if defined (USE_XAW)
      if (lw_xaw_widget_p (instance->widget))
	xaw_update_one_value (instance, widget, val);
Richard M. Stallman's avatar
Richard M. Stallman committed
1012 1013 1014 1015 1016 1017 1018 1019
#endif
      return True;
    }
  else
    return False;
}

Boolean
1020
lw_get_some_values (LWLIB_ID id, widget_value *val_out)
Richard M. Stallman's avatar
Richard M. Stallman committed
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
{
  widget_info* info = get_widget_info (id, False);
  widget_instance* instance;
  widget_value* val;
  Boolean result = False;

  if (!info)
    return False;

  instance = info->instances;
  if (!instance)
    return False;

  for (val = val_out; val; val = val->next)
    if (get_one_value (instance, val))
      result = True;

  return result;
}

widget_value*
1042
lw_get_all_values (LWLIB_ID id)
Richard M. Stallman's avatar
Richard M. Stallman committed
1043 1044
{
  widget_info* info = get_widget_info (id, False);
1045 1046 1047 1048 1049 1050 1051
  if (info)
    {
      widget_value* val = info->val;
      if (lw_get_some_values (id, val))
	return val;
    }
  return NULL;
Richard M. Stallman's avatar
Richard M. Stallman committed
1052 1053 1054 1055 1056
}

/* internal function used by the library dependent implementation to get the
   widget_value for a given widget in an instance */
widget_value*
1057
lw_get_widget_value_for_widget (widget_instance *instance, Widget w)
Richard M. Stallman's avatar
Richard M. Stallman committed
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
{
  char* name = XtName (w);
  widget_value* cur;
  for (cur = instance->info->val; cur; cur = cur->next)
    if (!strcmp (cur->name, name))
      return cur;
  return NULL;
}

/* update other instances value when one thing changed */
1068 1069 1070 1071

/* To forbid recursive calls */
static Boolean lwlib_updating;

Juanma Barranquero's avatar
Juanma Barranquero committed
1072 1073 1074
/* This function can be used as an XtCallback for the widgets that get
   modified to update other instances of the widgets.  Closure should be the
   widget_instance. */
Richard M. Stallman's avatar
Richard M. Stallman committed
1075
void
1076 1077 1078
lw_internal_update_other_instances (Widget widget,
                                    XtPointer closure,
                                    XtPointer call_data)
Richard M. Stallman's avatar
Richard M. Stallman committed
1079 1080 1081 1082 1083 1084 1085
{
  widget_instance* instance = (widget_instance*)closure;
  char* name = XtName (widget);
  widget_info* info;
  widget_instance* cur;
  widget_value* val;

1086 1087
  /* Avoid possibly infinite recursion.  */
  if (lwlib_updating)
Richard M. Stallman's avatar
Richard M. Stallman committed
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
    return;

  /* protect against the widget being destroyed */
  if (XtWidgetBeingDestroyedP (widget))
    return;

  /* Return immediately if there are no other instances */
  info = instance->info;
  if (!info->instances->next)
    return;

1099
  lwlib_updating = True;
Richard M. Stallman's avatar
Richard M. Stallman committed
1100 1101 1102 1103 1104 1105 1106 1107

  for (val = info->val; val && strcmp (val->name, name); val = val->next);

  if (val && get_one_value (instance, val))
    for (cur = info->instances; cur; cur = cur->next)
      if (cur != instance)
	set_one_value (cur, val, True);

1108
  lwlib_updating = False;
Richard M. Stallman's avatar
Richard M. Stallman committed
1109 1110 1111 1112 1113 1114
}


/* get the id */

LWLIB_ID
1115
lw_get_widget_id (Widget w)
Richard M. Stallman's avatar
Richard M. Stallman committed
1116 1117 1118 1119 1120 1121 1122 1123
{
  widget_instance* instance = get_widget_instance (w, False);

  return instance ? instance->info->id : 0;
}

/* set the keyboard focus */
void
1124
lw_set_keyboard_focus (Widget parent, Widget w)
Richard M. Stallman's avatar
Richard M. Stallman committed
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
{
#if defined (USE_MOTIF)
  xm_set_keyboard_focus (parent, w);
#else
  XtSetKeyboardFocus (parent, w);
#endif
}

/* Show busy */
static void
Dave Love's avatar
Dave Love committed
1135
show_one_widget_busy (Widget w, Boolean flag)
Richard M. Stallman's avatar
Richard M. Stallman committed
1136 1137 1138 1139 1140 1141
{
  Pixel foreground = 0;
  Pixel background = 1;
  Widget widget_to_invert = XtNameToWidget (w, "*sheet");
  if (!widget_to_invert)
    widget_to_invert = w;
1142

Richard M. Stallman's avatar
Richard M. Stallman committed
1143 1144 1145
  XtVaGetValues (widget_to_invert,
		 XtNforeground, &foreground,
		 XtNbackground, &background,
Gerd Moellmann's avatar
Gerd Moellmann committed
1146
		 NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
1147 1148 1149
  XtVaSetValues (widget_to_invert,
		 XtNforeground, background,
		 XtNbackground, foreground,
Gerd Moellmann's avatar
Gerd Moellmann committed
1150
		 NULL);
Richard M. Stallman's avatar
Richard M. Stallman committed
1151 1152 1153
}

void
Dave Love's avatar
Dave Love committed
1154
lw_show_busy (Widget w, Boolean busy)
Richard M. Stallman's avatar
Richard M. Stallman committed
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
{
  widget_instance* instance = get_widget_instance (w, False);
  widget_info* info;
  widget_instance* next;

  if (instance)
    {
      info = instance->info;
      if (info->busy != busy)
	{
	  for (next = info->instances; next; next = next->next)
	    if (next->widget)
	      show_one_widget_busy (next->widget, busy);
	  info->busy = busy;
	}
    }
}
Paul Reilly's avatar
Paul Reilly committed
1172 1173 1174 1175

/* This hack exists because Lucid/Athena need to execute the strange
   function below to support geometry management. */
void
Dave Love's avatar
Dave Love committed
1176
lw_refigure_widget (Widget w, Boolean doit)
Paul Reilly's avatar
Paul Reilly committed
1177
{
1178
#if defined (USE_XAW)
Paul Reilly's avatar
Paul Reilly committed
1179 1180 1181 1182 1183
  XawPanedSetRefigureMode (w, doit);
#endif
#if defined (USE_MOTIF)
  if (doit)
    XtManageChild (w);
1184 1185
  else
    XtUnmanageChild (w);
Paul Reilly's avatar
Paul Reilly committed
1186 1187 1188 1189 1190 1191
#endif
}

/* Toolkit independent way of determining if an event window is in the
   menubar. */
Boolean
1192
lw_window_is_in_menubar (Window win, Widget menubar_widget)
Paul Reilly's avatar
Paul Reilly committed
1193 1194 1195 1196 1197 1198
{
  return menubar_widget
#if defined (USE_LUCID)
      && XtWindow (menubar_widget) == win;
#endif
#if defined (USE_MOTIF)
1199 1200 1201 1202
      && ((XtWindow (menubar_widget) == win)
	  || (XtWindowToWidget (XtDisplay (menubar_widget), win)
	      && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
		  == menubar_widget)));
Paul Reilly's avatar
Paul Reilly committed
1203 1204 1205 1206 1207
#endif
}

/* Motif hack to set the main window areas. */
void
1208
lw_set_main_areas (Widget parent, Widget menubar, Widget work_area)
Paul Reilly's avatar
Paul Reilly committed
1209 1210
{
#if defined (USE_MOTIF)
1211
  xm_set_main_areas (parent, menubar, work_area);
Paul Reilly's avatar
Paul Reilly committed
1212 1213 1214 1215 1216 1217
#endif
}

/* Manage resizing for Motif.  This disables resizing when the menubar
   is about to be modified. */
void
Dave Love's avatar
Dave Love committed
1218
lw_allow_resizing (Widget w, Boolean flag)
Paul Reilly's avatar
Paul Reilly committed
1219 1220
{
#if defined (USE_MOTIF)
1221
  xm_manage_resizing (w, flag);
Paul Reilly's avatar
Paul Reilly committed
1222 1223
#endif
}
Gerd Moellmann's avatar
Gerd Moellmann committed
1224 1225 1226 1227 1228 1229 1230 1231


/* Value is non-zero if LABEL is a menu separator.  If it is, *TYPE is
   set to an appropriate enumerator of type enum menu_separator.
   MOTIF_P non-zero means map separator types not supported by Motif
   to similar ones that are supported.  */

int
1232
lw_separator_p (const char *label, enum menu_separator *type, int motif_p)
Gerd Moellmann's avatar
Gerd Moellmann committed
1233
{
1234
  int separator_p = 0;
Gerd Moellmann's avatar
Gerd Moellmann committed
1235

1236
  if (strncmp (label, "--:",  3) == 0)
Gerd Moellmann's avatar
Gerd Moellmann committed
1237 1238 1239
    {
      static struct separator_table
      {
1240
	const char *name;
Gerd Moellmann's avatar
Gerd Moellmann committed
1241 1242 1243 1244
	enum menu_separator type;
      }
      separator_names[] =
      {
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
	{"space",		      SEPARATOR_NO_LINE},
	{"noLine",		      SEPARATOR_NO_LINE},
	{"singleLine",		      SEPARATOR_SINGLE_LINE},
	{"doubleLine",		      SEPARATOR_DOUBLE_LINE},
	{"singleDashedLine",	      SEPARATOR_SINGLE_DASHED_LINE},
	{"doubleDashedLine",	      SEPARATOR_DOUBLE_DASHED_LINE},
	{"shadowEtchedIn",	      SEPARATOR_SHADOW_ETCHED_IN},
	{"shadowEtchedOut",	      SEPARATOR_SHADOW_ETCHED_OUT},
	{"shadowEtchedInDash",	      SEPARATOR_SHADOW_ETCHED_IN_DASH},
	{"shadowEtchedOutDash",	      SEPARATOR_SHADOW_ETCHED_OUT_DASH},
	{"shadowDoubleEtchedIn",      SEPARATOR_SHADOW_DOUBLE_ETCHED_IN},
	{"shadowDoubleEtchedOut",     SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT},
	{"shadowDoubleEtchedInDash",  SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH},
	{"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH},
	{0,0}
Gerd Moellmann's avatar
Gerd Moellmann committed
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270
      };

      int i;

      label += 3;
      for (i = 0; separator_names[i].name; ++i)
	if (strcmp (label, separator_names[i].name) == 0)
	  {
	    separator_p = 1;
	    *type = separator_names[i].type;

1271 1272 1273 1274 1275 1276 1277
	    /* If separator type is not supported under Motif,
	       use a similar one.  */
	    if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
	      *type -= 4;
	    break;
	  }
    }
1278
  else if (strnlen (label, 4) == 4
1279
	   && memcmp (label, "--", 2) == 0
1280
	   && label[2] != '-')
1281 1282 1283 1284
    {
      /* Alternative, more Emacs-style names.  */
      static struct separator_table
      {
1285
	const char *name;
1286 1287 1288 1289
	enum menu_separator type;
      }
      separator_names[] =
      {
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304
	{"space",			 SEPARATOR_NO_LINE},
	{"no-line",			 SEPARATOR_NO_LINE},
	{"single-line",			 SEPARATOR_SINGLE_LINE},
	{"double-line",			 SEPARATOR_DOUBLE_LINE},
	{"single-dashed-line",		 SEPARATOR_SINGLE_DASHED_LINE},
	{"double-dashed-line",		 SEPARATOR_DOUBLE_DASHED_LINE},
	{"shadow-etched-in",		 SEPARATOR_SHADOW_ETCHED_IN},
	{"shadow-etched-out",		 SEPARATOR_SHADOW_ETCHED_OUT},
	{"shadow-etched-in-dash",	 SEPARATOR_SHADOW_ETCHED_IN_DASH},
	{"shadow-etched-out-dash",	 SEPARATOR_SHADOW_ETCHED_OUT_DASH},
	{"shadow-double-etched-in",	 SEPARATOR_SHADOW_DOUBLE_ETCHED_IN},
	{"shadow-double-etched-out",     SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT},
	{"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH},
	{"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH},
	{0,0}
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
      };

      int i;

      label += 2;
      for (i = 0; separator_names[i].name; ++i)
	if (strcmp (label, separator_names[i].name) == 0)
	  {
	    separator_p = 1;
	    *type = separator_names[i].type;

Gerd Moellmann's avatar
Gerd Moellmann committed
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334
	    /* If separator type is not supported under Motif,
	       use a similar one.  */
	    if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
	      *type -= 4;
	    break;
	  }
    }
  else
    {
      /* Old-style separator, maybe.  It's a separator if it contains
	 only dashes.  */
      while (*label == '-')
	++label;
      separator_p = *label == 0;
      *type = SEPARATOR_SHADOW_ETCHED_IN;
    }

  return separator_p;
}