lwlib.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423
  1. /* A general interface to the widgets of different toolkits.
  2. Copyright (C) 1992, 1993 Lucid, Inc.
  3. Copyright (C) 1994-1996, 1999-2012 Free Software Foundation, Inc.
  4. This file is part of the Lucid Widget Library.
  5. The Lucid Widget Library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. The Lucid Widget Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GNU Emacs; see the file COPYING. If not, write to
  15. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. Boston, MA 02110-1301, USA. */
  17. #ifdef HAVE_CONFIG_H
  18. #include <config.h>
  19. #endif
  20. #include <setjmp.h>
  21. #include <lisp.h>
  22. #include <sys/types.h>
  23. #include <stdio.h>
  24. #include <ctype.h>
  25. #include "lwlib-int.h"
  26. #include "lwlib-utils.h"
  27. #include <X11/StringDefs.h>
  28. #if defined (USE_LUCID)
  29. #include "lwlib-Xlw.h"
  30. #endif
  31. #if defined (USE_MOTIF)
  32. #include "lwlib-Xm.h"
  33. #else /* not USE_MOTIF */
  34. #if defined (USE_LUCID)
  35. #define USE_XAW
  36. #endif /* not USE_MOTIF && USE_LUCID */
  37. #endif
  38. #if defined (USE_XAW)
  39. #ifdef HAVE_XAW3D
  40. #include <X11/Xaw3d/Paned.h>
  41. #else /* !HAVE_XAW3D */
  42. #include <X11/Xaw/Paned.h>
  43. #endif /* HAVE_XAW3D */
  44. #include "lwlib-Xaw.h"
  45. #endif
  46. #if !defined (USE_LUCID) && !defined (USE_MOTIF)
  47. #error At least one of USE_LUCID or USE_MOTIF must be defined.
  48. #endif
  49. #ifndef max
  50. #define max(x, y) ((x) > (y) ? (x) : (y))
  51. #endif
  52. /* List of all widgets managed by the library. */
  53. static widget_info*
  54. all_widget_info = NULL;
  55. #ifdef USE_MOTIF
  56. const char *lwlib_toolkit_type = "motif";
  57. #else
  58. const char *lwlib_toolkit_type = "lucid";
  59. #endif
  60. static widget_value *merge_widget_value (widget_value *,
  61. widget_value *,
  62. int, int *);
  63. static void instantiate_widget_instance (widget_instance *);
  64. static int my_strcasecmp (const char *, const char *);
  65. static void safe_free_str (char *);
  66. static void free_widget_value_tree (widget_value *);
  67. static widget_value *copy_widget_value_tree (widget_value *,
  68. change_type);
  69. static widget_info *allocate_widget_info (const char *, const char *, LWLIB_ID,
  70. widget_value *,
  71. lw_callback, lw_callback,
  72. lw_callback, lw_callback);
  73. static void free_widget_info (widget_info *);
  74. static void mark_widget_destroyed (Widget, XtPointer, XtPointer);
  75. static widget_instance *allocate_widget_instance (widget_info *,
  76. Widget, Boolean);
  77. static void free_widget_instance (widget_instance *);
  78. static widget_info *get_widget_info (LWLIB_ID, Boolean);
  79. static widget_instance *get_widget_instance (Widget, Boolean);
  80. static widget_instance *find_instance (LWLIB_ID, Widget, Boolean);
  81. static Boolean safe_strcmp (const char *, const char *);
  82. static Widget name_to_widget (widget_instance *, const char *);
  83. static void set_one_value (widget_instance *, widget_value *, Boolean);
  84. static void update_one_widget_instance (widget_instance *, Boolean);
  85. static void update_all_widget_values (widget_info *, Boolean);
  86. static void initialize_widget_instance (widget_instance *);
  87. static widget_creation_function find_in_table (const char *, const widget_creation_entry *);
  88. static Boolean dialog_spec_p (const char *);
  89. static void destroy_one_instance (widget_instance *);
  90. static void lw_pop_all_widgets (LWLIB_ID, Boolean);
  91. static Boolean get_one_value (widget_instance *, widget_value *);
  92. static void show_one_widget_busy (Widget, Boolean);
  93. /* utility functions for widget_instance and widget_info */
  94. char *
  95. safe_strdup (const char *s)
  96. {
  97. char *result;
  98. if (! s) return 0;
  99. result = (char *) xmalloc (strlen (s) + 1);
  100. strcpy (result, s);
  101. return result;
  102. }
  103. /* Like strcmp but ignore differences in case. */
  104. static int
  105. my_strcasecmp (const char *s1, const char *s2)
  106. {
  107. while (1)
  108. {
  109. int c1 = *s1++;
  110. int c2 = *s2++;
  111. if (isupper (c1))
  112. c1 = tolower (c1);
  113. if (isupper (c2))
  114. c2 = tolower (c2);
  115. if (c1 != c2)
  116. return (c1 > c2 ? 1 : -1);
  117. if (c1 == 0)
  118. return 0;
  119. }
  120. }
  121. static void
  122. safe_free_str (char *s)
  123. {
  124. xfree (s);
  125. }
  126. static widget_value *widget_value_free_list = 0;
  127. static int malloc_cpt = 0;
  128. widget_value *
  129. malloc_widget_value (void)
  130. {
  131. widget_value *wv;
  132. if (widget_value_free_list)
  133. {
  134. wv = widget_value_free_list;
  135. widget_value_free_list = wv->free_list;
  136. wv->free_list = 0;
  137. }
  138. else
  139. {
  140. wv = (widget_value *) xmalloc (sizeof (widget_value));
  141. malloc_cpt++;
  142. }
  143. memset ((void*) wv, 0, sizeof (widget_value));
  144. return wv;
  145. }
  146. /* this is analogous to free(). It frees only what was allocated
  147. by malloc_widget_value(), and no substructures.
  148. */
  149. void
  150. free_widget_value (widget_value *wv)
  151. {
  152. if (wv->free_list)
  153. abort ();
  154. if (malloc_cpt > 25)
  155. {
  156. /* When the number of already allocated cells is too big,
  157. We free it. */
  158. xfree (wv);
  159. malloc_cpt--;
  160. }
  161. else
  162. {
  163. wv->free_list = widget_value_free_list;
  164. widget_value_free_list = wv;
  165. }
  166. }
  167. static void
  168. free_widget_value_tree (widget_value *wv)
  169. {
  170. if (!wv)
  171. return;
  172. xfree (wv->name);
  173. xfree (wv->value);
  174. xfree (wv->key);
  175. wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
  176. if (wv->toolkit_data && wv->free_toolkit_data)
  177. {
  178. XtFree (wv->toolkit_data);
  179. wv->toolkit_data = (void *) 0xDEADBEEF;
  180. }
  181. if (wv->contents && (wv->contents != (widget_value*)1))
  182. {
  183. free_widget_value_tree (wv->contents);
  184. wv->contents = (widget_value *) 0xDEADBEEF;
  185. }
  186. if (wv->next)
  187. {
  188. free_widget_value_tree (wv->next);
  189. wv->next = (widget_value *) 0xDEADBEEF;
  190. }
  191. free_widget_value (wv);
  192. }
  193. static widget_value *
  194. copy_widget_value_tree (widget_value *val, change_type change)
  195. {
  196. widget_value* copy;
  197. if (!val)
  198. return NULL;
  199. if (val == (widget_value *) 1)
  200. return val;
  201. copy = malloc_widget_value ();
  202. copy->name = safe_strdup (val->name);
  203. copy->value = safe_strdup (val->value);
  204. copy->key = safe_strdup (val->key);
  205. copy->help = val->help;
  206. copy->enabled = val->enabled;
  207. copy->button_type = val->button_type;
  208. copy->selected = val->selected;
  209. copy->edited = False;
  210. copy->change = change;
  211. copy->this_one_change = change;
  212. copy->contents = copy_widget_value_tree (val->contents, change);
  213. copy->call_data = val->call_data;
  214. copy->next = copy_widget_value_tree (val->next, change);
  215. copy->toolkit_data = NULL;
  216. copy->free_toolkit_data = False;
  217. return copy;
  218. }
  219. static widget_info *
  220. allocate_widget_info (const char* type,
  221. const char* name,
  222. LWLIB_ID id,
  223. widget_value* val,
  224. lw_callback pre_activate_cb,
  225. lw_callback selection_cb,
  226. lw_callback post_activate_cb,
  227. lw_callback highlight_cb)
  228. {
  229. widget_info* info = (widget_info*) xmalloc (sizeof (widget_info));
  230. info->type = safe_strdup (type);
  231. info->name = safe_strdup (name);
  232. info->id = id;
  233. info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE);
  234. info->busy = False;
  235. info->pre_activate_cb = pre_activate_cb;
  236. info->selection_cb = selection_cb;
  237. info->post_activate_cb = post_activate_cb;
  238. info->highlight_cb = highlight_cb;
  239. info->instances = NULL;
  240. info->next = all_widget_info;
  241. all_widget_info = info;
  242. return info;
  243. }
  244. static void
  245. free_widget_info (widget_info *info)
  246. {
  247. safe_free_str (info->type);
  248. safe_free_str (info->name);
  249. free_widget_value_tree (info->val);
  250. memset ((void*)info, 0xDEADBEEF, sizeof (widget_info));
  251. xfree (info);
  252. }
  253. static void
  254. mark_widget_destroyed (Widget widget, XtPointer closure, XtPointer call_data)
  255. {
  256. widget_instance* instance = (widget_instance*)closure;
  257. /* be very conservative */
  258. if (instance->widget == widget)
  259. instance->widget = NULL;
  260. }
  261. static widget_instance *
  262. allocate_widget_instance (widget_info* info, Widget parent, Boolean pop_up_p)
  263. {
  264. widget_instance* instance =
  265. (widget_instance*) xmalloc (sizeof (widget_instance));
  266. memset (instance, 0, sizeof *instance);
  267. instance->parent = parent;
  268. instance->pop_up_p = pop_up_p;
  269. instance->info = info;
  270. instance->next = info->instances;
  271. info->instances = instance;
  272. instantiate_widget_instance (instance);
  273. XtAddCallback (instance->widget, XtNdestroyCallback,
  274. mark_widget_destroyed, (XtPointer)instance);
  275. return instance;
  276. }
  277. static void
  278. free_widget_instance (widget_instance *instance)
  279. {
  280. memset ((void*)instance, 0xDEADBEEF, sizeof (widget_instance));
  281. xfree (instance);
  282. }
  283. static widget_info *
  284. get_widget_info (LWLIB_ID id, Boolean remove_p)
  285. {
  286. widget_info* info;
  287. widget_info* prev;
  288. for (prev = NULL, info = all_widget_info;
  289. info;
  290. prev = info, info = info->next)
  291. if (info->id == id)
  292. {
  293. if (remove_p)
  294. {
  295. if (prev)
  296. prev->next = info->next;
  297. else
  298. all_widget_info = info->next;
  299. }
  300. return info;
  301. }
  302. return NULL;
  303. }
  304. /* Internal function used by the library dependent implementation to get the
  305. widget_value for a given widget in an instance */
  306. widget_info *
  307. lw_get_widget_info (LWLIB_ID id)
  308. {
  309. return get_widget_info (id, 0);
  310. }
  311. static widget_instance *
  312. get_widget_instance (Widget widget, Boolean remove_p)
  313. {
  314. widget_info* info;
  315. widget_instance* instance;
  316. widget_instance* prev;
  317. for (info = all_widget_info; info; info = info->next)
  318. for (prev = NULL, instance = info->instances;
  319. instance;
  320. prev = instance, instance = instance->next)
  321. if (instance->widget == widget)
  322. {
  323. if (remove_p)
  324. {
  325. if (prev)
  326. prev->next = instance->next;
  327. else
  328. info->instances = instance->next;
  329. }
  330. return instance;
  331. }
  332. return (widget_instance *) 0;
  333. }
  334. /* Value is a pointer to the widget_instance corresponding to
  335. WIDGET, or null if WIDGET is not a lwlib widget. */
  336. widget_instance *
  337. lw_get_widget_instance (Widget widget)
  338. {
  339. return get_widget_instance (widget, False);
  340. }
  341. static widget_instance*
  342. find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p)
  343. {
  344. widget_info* info = get_widget_info (id, False);
  345. widget_instance* instance;
  346. if (info)
  347. for (instance = info->instances; instance; instance = instance->next)
  348. if (instance->parent == parent && instance->pop_up_p == pop_up_p)
  349. return instance;
  350. return NULL;
  351. }
  352. /* utility function for widget_value */
  353. static Boolean
  354. safe_strcmp (const char *s1, const char *s2)
  355. {
  356. if (!!s1 ^ !!s2) return True;
  357. return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2;
  358. }
  359. #if 0
  360. # define EXPLAIN(name, oc, nc, desc, a1, a2) \
  361. printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \
  362. name, \
  363. (oc == NO_CHANGE ? "none" : \
  364. (oc == INVISIBLE_CHANGE ? "invisible" : \
  365. (oc == VISIBLE_CHANGE ? "visible" : \
  366. (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
  367. oc, \
  368. (nc == NO_CHANGE ? "none" : \
  369. (nc == INVISIBLE_CHANGE ? "invisible" : \
  370. (nc == VISIBLE_CHANGE ? "visible" : \
  371. (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \
  372. nc, desc, a1, a2)
  373. #else
  374. # define EXPLAIN(name, oc, nc, desc, a1, a2) ((void) 0)
  375. #endif
  376. static widget_value *
  377. merge_widget_value (widget_value *val1,
  378. widget_value *val2,
  379. int level,
  380. int *change_p)
  381. {
  382. change_type change, this_one_change;
  383. widget_value* merged_next;
  384. widget_value* merged_contents;
  385. if (!val1)
  386. {
  387. if (val2)
  388. {
  389. *change_p = 1;
  390. return copy_widget_value_tree (val2, STRUCTURAL_CHANGE);
  391. }
  392. else
  393. return NULL;
  394. }
  395. if (!val2)
  396. {
  397. *change_p = 1;
  398. free_widget_value_tree (val1);
  399. return NULL;
  400. }
  401. change = NO_CHANGE;
  402. if (safe_strcmp (val1->name, val2->name))
  403. {
  404. EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change",
  405. val1->name, val2->name);
  406. change = max (change, STRUCTURAL_CHANGE);
  407. safe_free_str (val1->name);
  408. val1->name = safe_strdup (val2->name);
  409. }
  410. if (safe_strcmp (val1->value, val2->value))
  411. {
  412. EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change",
  413. val1->value, val2->value);
  414. change = max (change, VISIBLE_CHANGE);
  415. safe_free_str (val1->value);
  416. val1->value = safe_strdup (val2->value);
  417. }
  418. if (safe_strcmp (val1->key, val2->key))
  419. {
  420. EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change",
  421. val1->key, val2->key);
  422. change = max (change, VISIBLE_CHANGE);
  423. safe_free_str (val1->key);
  424. val1->key = safe_strdup (val2->key);
  425. }
  426. if (! EQ (val1->help, val2->help))
  427. {
  428. EXPLAIN (val1->name, change, VISIBLE_CHANGE, "help change",
  429. val1->help, val2->help);
  430. change = max (change, VISIBLE_CHANGE);
  431. val1->help = val2->help;
  432. }
  433. if (val1->enabled != val2->enabled)
  434. {
  435. EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change",
  436. val1->enabled, val2->enabled);
  437. change = max (change, VISIBLE_CHANGE);
  438. val1->enabled = val2->enabled;
  439. }
  440. if (val1->button_type != val2->button_type)
  441. {
  442. EXPLAIN (val1->name, change, VISIBLE_CHANGE, "button type change",
  443. val1->button_type, val2->button_type);
  444. change = max (change, VISIBLE_CHANGE);
  445. val1->button_type = val2->button_type;
  446. }
  447. if (val1->selected != val2->selected)
  448. {
  449. EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change",
  450. val1->selected, val2->selected);
  451. change = max (change, VISIBLE_CHANGE);
  452. val1->selected = val2->selected;
  453. }
  454. if (val1->call_data != val2->call_data)
  455. {
  456. EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change",
  457. val1->call_data, val2->call_data);
  458. change = max (change, INVISIBLE_CHANGE);
  459. val1->call_data = val2->call_data;
  460. }
  461. if (level > 0)
  462. {
  463. merged_contents =
  464. merge_widget_value (val1->contents, val2->contents, level - 1,
  465. change_p);
  466. if (val1->contents && !merged_contents)
  467. {
  468. /* This used to say INVISIBLE_CHANGE,
  469. but it is visible and vitally important when
  470. the contents of the menu bar itself are entirely deleted.
  471. But maybe it doesn't matter. This fails to fix the bug. */
  472. EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(contents gone)",
  473. 0, 0);
  474. change = max (change, STRUCTURAL_CHANGE);
  475. }
  476. else if (merged_contents && merged_contents->change != NO_CHANGE)
  477. {
  478. EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)",
  479. 0, 0);
  480. change = max (change, INVISIBLE_CHANGE);
  481. #if 0 /* This was replaced by the August 9 1996 change in lwlib-Xm.c. */
  482. #ifdef USE_MOTIF
  483. change = max (merged_contents->change, change);
  484. #endif
  485. #endif
  486. }
  487. val1->contents = merged_contents;
  488. }
  489. this_one_change = change;
  490. merged_next = merge_widget_value (val1->next, val2->next, level, change_p);
  491. if (val1->next && !merged_next)
  492. {
  493. EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)",
  494. 0, 0);
  495. change = max (change, STRUCTURAL_CHANGE);
  496. }
  497. else if (merged_next)
  498. {
  499. if (merged_next->change)
  500. EXPLAIN (val1->name, change, merged_next->change, "(following change)",
  501. 0, 0);
  502. change = max (change, merged_next->change);
  503. }
  504. val1->next = merged_next;
  505. val1->this_one_change = this_one_change;
  506. val1->change = change;
  507. if (change > NO_CHANGE && val1->toolkit_data)
  508. {
  509. *change_p = 1;
  510. if (val1->free_toolkit_data)
  511. XtFree (val1->toolkit_data);
  512. val1->toolkit_data = NULL;
  513. }
  514. return val1;
  515. }
  516. /* modifying the widgets */
  517. static Widget
  518. name_to_widget (widget_instance *instance, const char *name)
  519. {
  520. Widget widget = NULL;
  521. if (!instance->widget)
  522. return NULL;
  523. if (!strcmp (XtName (instance->widget), name))
  524. widget = instance->widget;
  525. else
  526. {
  527. int length = strlen (name) + 2;
  528. char* real_name = (char *) xmalloc (length);
  529. real_name [0] = '*';
  530. strcpy (real_name + 1, name);
  531. widget = XtNameToWidget (instance->widget, real_name);
  532. xfree (real_name);
  533. }
  534. return widget;
  535. }
  536. static void
  537. set_one_value (widget_instance* instance, widget_value* val, Boolean deep_p)
  538. {
  539. Widget widget = name_to_widget (instance, val->name);
  540. if (widget)
  541. {
  542. #if defined (USE_LUCID)
  543. if (lw_lucid_widget_p (instance->widget))
  544. xlw_update_one_widget (instance, widget, val, deep_p);
  545. #endif
  546. #if defined (USE_MOTIF)
  547. if (lw_motif_widget_p (instance->widget))
  548. xm_update_one_widget (instance, widget, val, deep_p);
  549. #endif
  550. #if defined (USE_XAW)
  551. if (lw_xaw_widget_p (instance->widget))
  552. xaw_update_one_widget (instance, widget, val, deep_p);
  553. #endif
  554. }
  555. }
  556. static void
  557. update_one_widget_instance (widget_instance* instance, Boolean deep_p)
  558. {
  559. widget_value *val;
  560. if (!instance->widget)
  561. /* the widget was destroyed */
  562. return;
  563. for (val = instance->info->val; val; val = val->next)
  564. if (val->change != NO_CHANGE)
  565. set_one_value (instance, val, deep_p);
  566. }
  567. static void
  568. update_all_widget_values (widget_info* info, Boolean deep_p)
  569. {
  570. widget_instance* instance;
  571. widget_value* val;
  572. for (instance = info->instances; instance; instance = instance->next)
  573. update_one_widget_instance (instance, deep_p);
  574. for (val = info->val; val; val = val->next)
  575. val->change = NO_CHANGE;
  576. }
  577. int
  578. lw_modify_all_widgets (LWLIB_ID id, widget_value* val, Boolean deep_p)
  579. {
  580. widget_info* info = get_widget_info (id, False);
  581. widget_value* new_val;
  582. widget_value* next_new_val;
  583. widget_value* cur;
  584. widget_value* prev;
  585. widget_value* next;
  586. int found;
  587. int change_p = 0;
  588. if (!info)
  589. return 0;
  590. for (new_val = val; new_val; new_val = new_val->next)
  591. {
  592. next_new_val = new_val->next;
  593. new_val->next = NULL;
  594. found = False;
  595. for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next)
  596. if (!strcmp (cur->name, new_val->name))
  597. {
  598. found = True;
  599. next = cur->next;
  600. cur->next = NULL;
  601. cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1,
  602. &change_p);
  603. if (prev)
  604. prev->next = cur ? cur : next;
  605. else
  606. info->val = cur ? cur : next;
  607. if (cur)
  608. cur->next = next;
  609. break;
  610. }
  611. if (!found)
  612. {
  613. /* Could not find it, add it */
  614. if (prev)
  615. prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
  616. else
  617. info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE);
  618. change_p = 1;
  619. }
  620. new_val->next = next_new_val;
  621. }
  622. update_all_widget_values (info, deep_p);
  623. return change_p;
  624. }
  625. /* creating the widgets */
  626. static void
  627. initialize_widget_instance (widget_instance *instance)
  628. {
  629. widget_value* val;
  630. for (val = instance->info->val; val; val = val->next)
  631. val->change = STRUCTURAL_CHANGE;
  632. update_one_widget_instance (instance, True);
  633. for (val = instance->info->val; val; val = val->next)
  634. val->change = NO_CHANGE;
  635. }
  636. static widget_creation_function
  637. find_in_table (const char *type, const widget_creation_entry *table)
  638. {
  639. const widget_creation_entry* cur;
  640. for (cur = table; cur->type; cur++)
  641. if (!my_strcasecmp (type, cur->type))
  642. return cur->function;
  643. return NULL;
  644. }
  645. static Boolean
  646. dialog_spec_p (const char *name)
  647. {
  648. /* return True if name matches [EILPQeilpq][1-9][Bb] or
  649. [EILPQeilpq][1-9][Bb][Rr][1-9] */
  650. if (!name)
  651. return False;
  652. switch (name [0])
  653. {
  654. case 'E': case 'I': case 'L': case 'P': case 'Q':
  655. case 'e': case 'i': case 'l': case 'p': case 'q':
  656. if (name [1] >= '0' && name [1] <= '9')
  657. {
  658. if (name [2] != 'B' && name [2] != 'b')
  659. return False;
  660. if (!name [3])
  661. return True;
  662. if ((name [3] == 'T' || name [3] == 't') && !name [4])
  663. return True;
  664. if ((name [3] == 'R' || name [3] == 'r')
  665. && name [4] >= '0' && name [4] <= '9' && !name [5])
  666. return True;
  667. return False;
  668. }
  669. else
  670. return False;
  671. default:
  672. return False;
  673. }
  674. }
  675. static void
  676. instantiate_widget_instance (widget_instance *instance)
  677. {
  678. widget_creation_function function = NULL;
  679. #if defined (USE_LUCID)
  680. if (!function)
  681. function = find_in_table (instance->info->type, xlw_creation_table);
  682. #endif
  683. #if defined(USE_MOTIF)
  684. if (!function)
  685. function = find_in_table (instance->info->type, xm_creation_table);
  686. #endif
  687. #if defined (USE_XAW)
  688. if (!function)
  689. function = find_in_table (instance->info->type, xaw_creation_table);
  690. #endif
  691. if (!function)
  692. {
  693. if (dialog_spec_p (instance->info->type))
  694. {
  695. #if defined (USE_LUCID)
  696. /* not yet */
  697. #endif
  698. #if defined(USE_MOTIF)
  699. if (!function)
  700. function = xm_create_dialog;
  701. #endif
  702. #if defined (USE_XAW)
  703. if (!function)
  704. function = xaw_create_dialog;
  705. #endif
  706. }
  707. }
  708. if (!function)
  709. {
  710. printf ("No creation function for widget type %s\n",
  711. instance->info->type);
  712. abort ();
  713. }
  714. instance->widget = (*function) (instance);
  715. if (!instance->widget)
  716. abort ();
  717. /* XtRealizeWidget (instance->widget);*/
  718. }
  719. void
  720. lw_register_widget (const char* type,
  721. const char* name,
  722. LWLIB_ID id,
  723. widget_value* val,
  724. lw_callback pre_activate_cb,
  725. lw_callback selection_cb,
  726. lw_callback post_activate_cb,
  727. lw_callback highlight_cb)
  728. {
  729. if (!get_widget_info (id, False))
  730. allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb,
  731. post_activate_cb, highlight_cb);
  732. }
  733. Widget
  734. lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
  735. {
  736. widget_instance* instance;
  737. instance = find_instance (id, parent, pop_up_p);
  738. return instance ? instance->widget : NULL;
  739. }
  740. Widget
  741. lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p)
  742. {
  743. widget_instance* instance;
  744. widget_info* info;
  745. instance = find_instance (id, parent, pop_up_p);
  746. if (!instance)
  747. {
  748. info = get_widget_info (id, False);
  749. if (!info)
  750. return NULL;
  751. instance = allocate_widget_instance (info, parent, pop_up_p);
  752. initialize_widget_instance (instance);
  753. }
  754. if (!instance->widget)
  755. abort ();
  756. return instance->widget;
  757. }
  758. Widget
  759. lw_create_widget (const char* type, const char* name, LWLIB_ID id, widget_value* val,
  760. Widget parent, Boolean pop_up_p,
  761. lw_callback pre_activate_cb, lw_callback selection_cb,
  762. lw_callback post_activate_cb, lw_callback highlight_cb)
  763. {
  764. lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb,
  765. post_activate_cb, highlight_cb);
  766. return lw_make_widget (id, parent, pop_up_p);
  767. }
  768. /* destroying the widgets */
  769. static void
  770. destroy_one_instance (widget_instance *instance)
  771. {
  772. /* Remove the destroy callback on the widget; that callback will try to
  773. dereference the instance object (to set its widget slot to 0, since the
  774. widget is dead.) Since the instance is now dead, we don't have to worry
  775. about the fact that its widget is dead too.
  776. This happens in the Phase2Destroy of the widget, so this callback would
  777. not have been run until arbitrarily long after the instance was freed.
  778. */
  779. if (instance->widget)
  780. XtRemoveCallback (instance->widget, XtNdestroyCallback,
  781. mark_widget_destroyed, (XtPointer)instance);
  782. if (instance->widget)
  783. {
  784. /* The else are pretty tricky here, including the empty statement
  785. at the end because it would be very bad to destroy a widget
  786. twice. */
  787. #if defined (USE_LUCID)
  788. if (lw_lucid_widget_p (instance->widget))
  789. xlw_destroy_instance (instance);
  790. else
  791. #endif
  792. #if defined (USE_MOTIF)
  793. if (lw_motif_widget_p (instance->widget))
  794. xm_destroy_instance (instance);
  795. else
  796. #endif
  797. #if defined (USE_XAW)
  798. if (lw_xaw_widget_p (instance->widget))
  799. xaw_destroy_instance (instance);
  800. else
  801. #endif
  802. {
  803. /* Empty compound statement to terminate if-then-else chain. */
  804. }
  805. }
  806. free_widget_instance (instance);
  807. }
  808. void
  809. lw_destroy_widget (Widget w)
  810. {
  811. widget_instance* instance = get_widget_instance (w, True);
  812. if (instance)
  813. {
  814. widget_info *info = instance->info;
  815. /* instance has already been removed from the list; free it */
  816. destroy_one_instance (instance);
  817. /* if there are no instances left, free the info too */
  818. if (!info->instances)
  819. lw_destroy_all_widgets (info->id);
  820. }
  821. }
  822. void
  823. lw_destroy_all_widgets (LWLIB_ID id)
  824. {
  825. widget_info* info = get_widget_info (id, True);
  826. widget_instance* instance;
  827. widget_instance* next;
  828. if (info)
  829. {
  830. for (instance = info->instances; instance; )
  831. {
  832. next = instance->next;
  833. destroy_one_instance (instance);
  834. instance = next;
  835. }
  836. free_widget_info (info);
  837. }
  838. }
  839. void
  840. lw_destroy_everything (void)
  841. {
  842. while (all_widget_info)
  843. lw_destroy_all_widgets (all_widget_info->id);
  844. }
  845. void
  846. lw_destroy_all_pop_ups (void)
  847. {
  848. widget_info* info;
  849. widget_info* next;
  850. widget_instance* instance;
  851. for (info = all_widget_info; info; info = next)
  852. {
  853. next = info->next;
  854. instance = info->instances;
  855. if (instance && instance->pop_up_p)
  856. lw_destroy_all_widgets (info->id);
  857. }
  858. }
  859. #ifdef USE_MOTIF
  860. extern Widget first_child (Widget); /* garbage */
  861. #endif
  862. Widget
  863. lw_raise_all_pop_up_widgets (void)
  864. {
  865. widget_info* info;
  866. widget_instance* instance;
  867. Widget result = NULL;
  868. for (info = all_widget_info; info; info = info->next)
  869. for (instance = info->instances; instance; instance = instance->next)
  870. if (instance->pop_up_p)
  871. {
  872. Widget widget = instance->widget;
  873. if (widget)
  874. {
  875. if (XtIsManaged (widget)
  876. #ifdef USE_MOTIF
  877. /* What a complete load of crap!!!!
  878. When a dialogShell is on the screen, it is not managed!
  879. */
  880. || (lw_motif_widget_p (instance->widget) &&
  881. XtIsManaged (first_child (widget)))
  882. #endif
  883. )
  884. {
  885. if (!result)
  886. result = widget;
  887. XMapRaised (XtDisplay (widget), XtWindow (widget));
  888. }
  889. }
  890. }
  891. return result;
  892. }
  893. static void
  894. lw_pop_all_widgets (LWLIB_ID id, Boolean up)
  895. {
  896. widget_info* info = get_widget_info (id, False);
  897. widget_instance* instance;
  898. if (info)
  899. for (instance = info->instances; instance; instance = instance->next)
  900. if (instance->pop_up_p && instance->widget)
  901. {
  902. #if defined (USE_LUCID)
  903. if (lw_lucid_widget_p (instance->widget))
  904. {
  905. XtRealizeWidget (instance->widget);
  906. xlw_pop_instance (instance, up);
  907. }
  908. #endif
  909. #if defined (USE_MOTIF)
  910. if (lw_motif_widget_p (instance->widget))
  911. {
  912. XtRealizeWidget (instance->widget);
  913. xm_pop_instance (instance, up);
  914. }
  915. #endif
  916. #if defined (USE_XAW)
  917. if (lw_xaw_widget_p (instance->widget))
  918. {
  919. XtRealizeWidget (XtParent (instance->widget));
  920. XtRealizeWidget (instance->widget);
  921. xaw_pop_instance (instance, up);
  922. }
  923. #endif
  924. }
  925. }
  926. void
  927. lw_pop_up_all_widgets (LWLIB_ID id)
  928. {
  929. lw_pop_all_widgets (id, True);
  930. }
  931. void
  932. lw_pop_down_all_widgets (LWLIB_ID id)
  933. {
  934. lw_pop_all_widgets (id, False);
  935. }
  936. void
  937. lw_popup_menu (Widget widget, XEvent *event)
  938. {
  939. #if defined (USE_LUCID)
  940. if (lw_lucid_widget_p (widget))
  941. xlw_popup_menu (widget, event);
  942. #endif
  943. #if defined (USE_MOTIF)
  944. if (lw_motif_widget_p (widget))
  945. xm_popup_menu (widget, event);
  946. #endif
  947. #if defined (USE_XAW)
  948. if (lw_xaw_widget_p (widget))
  949. xaw_popup_menu (widget, event);
  950. #endif
  951. }
  952. /* get the values back */
  953. static Boolean
  954. get_one_value (widget_instance *instance, widget_value *val)
  955. {
  956. Widget widget = name_to_widget (instance, val->name);
  957. if (widget)
  958. {
  959. #if defined (USE_LUCID)
  960. if (lw_lucid_widget_p (instance->widget))
  961. xlw_update_one_value (instance, widget, val);
  962. #endif
  963. #if defined (USE_MOTIF)
  964. if (lw_motif_widget_p (instance->widget))
  965. xm_update_one_value (instance, widget, val);
  966. #endif
  967. #if defined (USE_XAW)
  968. if (lw_xaw_widget_p (instance->widget))
  969. xaw_update_one_value (instance, widget, val);
  970. #endif
  971. return True;
  972. }
  973. else
  974. return False;
  975. }
  976. Boolean
  977. lw_get_some_values (LWLIB_ID id, widget_value *val_out)
  978. {
  979. widget_info* info = get_widget_info (id, False);
  980. widget_instance* instance;
  981. widget_value* val;
  982. Boolean result = False;
  983. if (!info)
  984. return False;
  985. instance = info->instances;
  986. if (!instance)
  987. return False;
  988. for (val = val_out; val; val = val->next)
  989. if (get_one_value (instance, val))
  990. result = True;
  991. return result;
  992. }
  993. widget_value*
  994. lw_get_all_values (LWLIB_ID id)
  995. {
  996. widget_info* info = get_widget_info (id, False);
  997. widget_value* val = info->val;
  998. if (lw_get_some_values (id, val))
  999. return val;
  1000. else
  1001. return NULL;
  1002. }
  1003. /* internal function used by the library dependent implementation to get the
  1004. widget_value for a given widget in an instance */
  1005. widget_value*
  1006. lw_get_widget_value_for_widget (widget_instance *instance, Widget w)
  1007. {
  1008. char* name = XtName (w);
  1009. widget_value* cur;
  1010. for (cur = instance->info->val; cur; cur = cur->next)
  1011. if (!strcmp (cur->name, name))
  1012. return cur;
  1013. return NULL;
  1014. }
  1015. /* update other instances value when one thing changed */
  1016. /* To forbid recursive calls */
  1017. static Boolean lwlib_updating;
  1018. /* This function can be used as an XtCallback for the widgets that get
  1019. modified to update other instances of the widgets. Closure should be the
  1020. widget_instance. */
  1021. void
  1022. lw_internal_update_other_instances (Widget widget,
  1023. XtPointer closure,
  1024. XtPointer call_data)
  1025. {
  1026. widget_instance* instance = (widget_instance*)closure;
  1027. char* name = XtName (widget);
  1028. widget_info* info;
  1029. widget_instance* cur;
  1030. widget_value* val;
  1031. /* Avoid possibly infinite recursion. */
  1032. if (lwlib_updating)
  1033. return;
  1034. /* protect against the widget being destroyed */
  1035. if (XtWidgetBeingDestroyedP (widget))
  1036. return;
  1037. /* Return immediately if there are no other instances */
  1038. info = instance->info;
  1039. if (!info->instances->next)
  1040. return;
  1041. lwlib_updating = True;
  1042. for (val = info->val; val && strcmp (val->name, name); val = val->next);
  1043. if (val && get_one_value (instance, val))
  1044. for (cur = info->instances; cur; cur = cur->next)
  1045. if (cur != instance)
  1046. set_one_value (cur, val, True);
  1047. lwlib_updating = False;
  1048. }
  1049. /* get the id */
  1050. LWLIB_ID
  1051. lw_get_widget_id (Widget w)
  1052. {
  1053. widget_instance* instance = get_widget_instance (w, False);
  1054. return instance ? instance->info->id : 0;
  1055. }
  1056. /* set the keyboard focus */
  1057. void
  1058. lw_set_keyboard_focus (Widget parent, Widget w)
  1059. {
  1060. #if defined (USE_MOTIF)
  1061. xm_set_keyboard_focus (parent, w);
  1062. #else
  1063. XtSetKeyboardFocus (parent, w);
  1064. #endif
  1065. }
  1066. /* Show busy */
  1067. static void
  1068. show_one_widget_busy (Widget w, Boolean flag)
  1069. {
  1070. Pixel foreground = 0;
  1071. Pixel background = 1;
  1072. Widget widget_to_invert = XtNameToWidget (w, "*sheet");
  1073. if (!widget_to_invert)
  1074. widget_to_invert = w;
  1075. XtVaGetValues (widget_to_invert,
  1076. XtNforeground, &foreground,
  1077. XtNbackground, &background,
  1078. NULL);
  1079. XtVaSetValues (widget_to_invert,
  1080. XtNforeground, background,
  1081. XtNbackground, foreground,
  1082. NULL);
  1083. }
  1084. void
  1085. lw_show_busy (Widget w, Boolean busy)
  1086. {
  1087. widget_instance* instance = get_widget_instance (w, False);
  1088. widget_info* info;
  1089. widget_instance* next;
  1090. if (instance)
  1091. {
  1092. info = instance->info;
  1093. if (info->busy != busy)
  1094. {
  1095. for (next = info->instances; next; next = next->next)
  1096. if (next->widget)
  1097. show_one_widget_busy (next->widget, busy);
  1098. info->busy = busy;
  1099. }
  1100. }
  1101. }
  1102. /* This hack exists because Lucid/Athena need to execute the strange
  1103. function below to support geometry management. */
  1104. void
  1105. lw_refigure_widget (Widget w, Boolean doit)
  1106. {
  1107. #if defined (USE_XAW)
  1108. XawPanedSetRefigureMode (w, doit);
  1109. #endif
  1110. #if defined (USE_MOTIF)
  1111. if (doit)
  1112. XtManageChild (w);
  1113. else
  1114. XtUnmanageChild (w);
  1115. #endif
  1116. }
  1117. /* Toolkit independent way of determining if an event window is in the
  1118. menubar. */
  1119. Boolean
  1120. lw_window_is_in_menubar (Window win, Widget menubar_widget)
  1121. {
  1122. return menubar_widget
  1123. #if defined (USE_LUCID)
  1124. && XtWindow (menubar_widget) == win;
  1125. #endif
  1126. #if defined (USE_MOTIF)
  1127. && ((XtWindow (menubar_widget) == win)
  1128. || (XtWindowToWidget (XtDisplay (menubar_widget), win)
  1129. && (XtParent (XtWindowToWidget (XtDisplay (menubar_widget), win))
  1130. == menubar_widget)));
  1131. #endif
  1132. }
  1133. /* Motif hack to set the main window areas. */
  1134. void
  1135. lw_set_main_areas (Widget parent, Widget menubar, Widget work_area)
  1136. {
  1137. #if defined (USE_MOTIF)
  1138. xm_set_main_areas (parent, menubar, work_area);
  1139. #endif
  1140. }
  1141. /* Manage resizing for Motif. This disables resizing when the menubar
  1142. is about to be modified. */
  1143. void
  1144. lw_allow_resizing (Widget w, Boolean flag)
  1145. {
  1146. #if defined (USE_MOTIF)
  1147. xm_manage_resizing (w, flag);
  1148. #endif
  1149. }
  1150. /* Value is non-zero if LABEL is a menu separator. If it is, *TYPE is
  1151. set to an appropriate enumerator of type enum menu_separator.
  1152. MOTIF_P non-zero means map separator types not supported by Motif
  1153. to similar ones that are supported. */
  1154. int
  1155. lw_separator_p (const char *label, enum menu_separator *type, int motif_p)
  1156. {
  1157. int separator_p = 0;
  1158. if (strlen (label) >= 3
  1159. && memcmp (label, "--:", 3) == 0)
  1160. {
  1161. static struct separator_table
  1162. {
  1163. const char *name;
  1164. enum menu_separator type;
  1165. }
  1166. separator_names[] =
  1167. {
  1168. {"space", SEPARATOR_NO_LINE},
  1169. {"noLine", SEPARATOR_NO_LINE},
  1170. {"singleLine", SEPARATOR_SINGLE_LINE},
  1171. {"doubleLine", SEPARATOR_DOUBLE_LINE},
  1172. {"singleDashedLine", SEPARATOR_SINGLE_DASHED_LINE},
  1173. {"doubleDashedLine", SEPARATOR_DOUBLE_DASHED_LINE},
  1174. {"shadowEtchedIn", SEPARATOR_SHADOW_ETCHED_IN},
  1175. {"shadowEtchedOut", SEPARATOR_SHADOW_ETCHED_OUT},
  1176. {"shadowEtchedInDash", SEPARATOR_SHADOW_ETCHED_IN_DASH},
  1177. {"shadowEtchedOutDash", SEPARATOR_SHADOW_ETCHED_OUT_DASH},
  1178. {"shadowDoubleEtchedIn", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN},
  1179. {"shadowDoubleEtchedOut", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT},
  1180. {"shadowDoubleEtchedInDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH},
  1181. {"shadowDoubleEtchedOutDash", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH},
  1182. {0,0}
  1183. };
  1184. int i;
  1185. label += 3;
  1186. for (i = 0; separator_names[i].name; ++i)
  1187. if (strcmp (label, separator_names[i].name) == 0)
  1188. {
  1189. separator_p = 1;
  1190. *type = separator_names[i].type;
  1191. /* If separator type is not supported under Motif,
  1192. use a similar one. */
  1193. if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
  1194. *type -= 4;
  1195. break;
  1196. }
  1197. }
  1198. else if (strlen (label) > 3
  1199. && memcmp (label, "--", 2) == 0
  1200. && label[2] != '-')
  1201. {
  1202. /* Alternative, more Emacs-style names. */
  1203. static struct separator_table
  1204. {
  1205. const char *name;
  1206. enum menu_separator type;
  1207. }
  1208. separator_names[] =
  1209. {
  1210. {"space", SEPARATOR_NO_LINE},
  1211. {"no-line", SEPARATOR_NO_LINE},
  1212. {"single-line", SEPARATOR_SINGLE_LINE},
  1213. {"double-line", SEPARATOR_DOUBLE_LINE},
  1214. {"single-dashed-line", SEPARATOR_SINGLE_DASHED_LINE},
  1215. {"double-dashed-line", SEPARATOR_DOUBLE_DASHED_LINE},
  1216. {"shadow-etched-in", SEPARATOR_SHADOW_ETCHED_IN},
  1217. {"shadow-etched-out", SEPARATOR_SHADOW_ETCHED_OUT},
  1218. {"shadow-etched-in-dash", SEPARATOR_SHADOW_ETCHED_IN_DASH},
  1219. {"shadow-etched-out-dash", SEPARATOR_SHADOW_ETCHED_OUT_DASH},
  1220. {"shadow-double-etched-in", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN},
  1221. {"shadow-double-etched-out", SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT},
  1222. {"shadow-double-etched-in-dash", SEPARATOR_SHADOW_DOUBLE_ETCHED_IN_DASH},
  1223. {"shadow-double-etched-out-dash",SEPARATOR_SHADOW_DOUBLE_ETCHED_OUT_DASH},
  1224. {0,0}
  1225. };
  1226. int i;
  1227. label += 2;
  1228. for (i = 0; separator_names[i].name; ++i)
  1229. if (strcmp (label, separator_names[i].name) == 0)
  1230. {
  1231. separator_p = 1;
  1232. *type = separator_names[i].type;
  1233. /* If separator type is not supported under Motif,
  1234. use a similar one. */
  1235. if (motif_p && *type >= SEPARATOR_SHADOW_DOUBLE_ETCHED_IN)
  1236. *type -= 4;
  1237. break;
  1238. }
  1239. }
  1240. else
  1241. {
  1242. /* Old-style separator, maybe. It's a separator if it contains
  1243. only dashes. */
  1244. while (*label == '-')
  1245. ++label;
  1246. separator_p = *label == 0;
  1247. *type = SEPARATOR_SHADOW_ETCHED_IN;
  1248. }
  1249. return separator_p;
  1250. }