Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtappbuilder / src / ab / conn_interpret.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  *      $XConsortium: conn_interpret.c /main/3 1995/11/06 17:25:58 rswiston $
25  *
26  * @(#)conn_interpret.c 1.58 12 Apr 1995 cde_app_builder/src/ab
27  *
28  *      RESTRICTED CONFIDENTIAL INFORMATION:
29  *
30  *      The information in this document is subject to special
31  *      restrictions in a confidential disclosure agreement between
32  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
33  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
34  *      Sun's specific written approval.  This document and all copies
35  *      and derivative works thereof must be returned or destroyed at
36  *      Sun's request.
37  *
38  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
39  *
40  */
41
42
43 #include <stdio.h>
44 #include <Dt/SpinBox.h>
45 #include <ab_private/XmAll.h>
46 #include <ab_private/obj.h>
47 #include <ab_private/trav.h>
48 #include <ab_private/istr.h>
49 #include <ab_private/ab.h>
50 #include <ab_private/abobj.h>
51 #include <ab_private/abobj_set.h>
52 #include <ab_private/connP.h>
53 #include <ab_private/proj.h>
54 #include <ab/util_types.h>
55 #include <ab_private/util_ds.h>
56 #include <ab_private/help.h>
57 #include <ab_private/ui_util.h>
58 #include <ab_private/tmodeP.h>
59
60 typedef void    (*INTERPRET_HANDLER)(
61                     AB_ACTION_INFO      *,
62                     XtCallbackProc      when_cb
63                 );
64 typedef void    (*ACTION_HANDLER)(
65                     AB_ACTION_INFO      *
66                 );
67
68 static XtCallbackProc           get_when_callback(AB_WHEN when);
69 static INTERPRET_HANDLER        get_when_attach_handler(AB_WHEN when);
70 static INTERPRET_HANDLER        get_when_detach_handler(AB_WHEN when);
71 static ACTION_HANDLER           get_std_action_handler(
72                                     AB_BUILTIN_ACTION std_act
73                                 );
74 \f
75 static void     attach_interpretation(
76     ABObj       action
77 );
78 static void     attach_for_single_refs(
79                     BOOL                for_from,
80                     ABObj               *item_refs,
81                     AB_ACTION_INFO      *info,
82                     INTERPRET_HANDLER   handler,
83                     XtCallbackProc      when_callback
84                 );
85 static void     attach_for_both_refs(
86                     ABObj               *from_refs,
87                     ABObj               *to_refs,
88                     AB_ACTION_INFO      *info,
89                     INTERPRET_HANDLER   handler,
90                     XtCallbackProc      when_callback
91                 );
92 static void     detach_interpretation(
93                     ABObj       action
94                 );
95 static void     tree_set_initial_state(
96                     ABObj       obj,
97                     BOOL        ignore_win_visibility
98                 );
99 static void     tree_set_obj_initial_state(
100                     ABObj       obj
101                 );
102 static void     tree_restore_build_state(
103                     ABObj       obj
104                 );
105 static void     set_obj_initial_state(
106                     ABObj       obj
107                 );
108 static void     set_initial_state(
109                     ABObj       trg_obj,
110                     BOOL        ignore_win_visibility
111                 );
112 static void     restore_build_state(
113                     ABObj       trg_obj
114                 );
115 static int      setup_window_for_test_mode(
116                     ABObj       win
117                 );
118 static void     deiconify_wins(
119                     void        *cl_data
120                 );
121 static void     make_win_iconic(
122                     ABObj       win,
123                     BOOL        to_iconify
124                 );
125 static void     remove_win_close(
126                     void        *cl_data
127                 );
128 static void     destroy_menus(
129                     void        *cl_data
130                 );
131 static void     sensitize_objects(
132                     void        *cl_data
133                 );
134 static void     free_infos(
135                     void        *cl_data
136                 );
137 static void     reset_layer(
138                     void        *cl_data
139                 );
140 static void     manage_objs(
141                     void        *cl_data
142                 );
143 \f
144 static ACTION_HANDLER   get_action_handler(
145                     AB_ACTION_INFO      *notify_info
146                 );
147
148 static void     activate_attach_handler(
149                     AB_ACTION_INFO      *notify_info,
150                     XtCallbackProc      when_cb
151                 );
152 static void     activate_detach_handler(
153                     AB_ACTION_INFO      *notify_info,
154                     XtCallbackProc      when_cb
155                 );
156 static void     post_menu_attach_handler(
157                     AB_ACTION_INFO      *notify_info,
158                     XtCallbackProc      when_cb
159                 );
160 static void     post_menu_detach_handler(
161                     AB_ACTION_INFO      *notify_info,
162                     XtCallbackProc      when_cb
163                 );
164
165 static void     activate_when_cb(
166                     Widget      w,
167                     XtPointer   client_data,
168                     XtPointer   call_data
169                 );
170 static void     post_menu_when_cb(
171                     Widget      w,
172                     XtPointer   client_data,
173                     XtPointer   call_data
174                 );
175
176 static void     user_def_fn_handler(
177                     AB_ACTION_INFO      *action_info
178                 );
179 static void     code_frag_handler(
180                     AB_ACTION_INFO      *action_info
181                 );
182 static void     on_item_help_handler( 
183                     AB_ACTION_INFO      *action_info 
184                 );
185 static void     help_volume_handler( 
186                     AB_ACTION_INFO      *action_info 
187                 );
188 static void     show_action_handler(
189                     AB_ACTION_INFO      *action_info
190                 );
191 static void     hide_action_handler(
192                     AB_ACTION_INFO      *action_info
193                 );
194 static void     enable_action_handler(
195                     AB_ACTION_INFO      *action_info
196                 );
197 static void     disable_action_handler(
198                     AB_ACTION_INFO      *action_info
199                 );
200 static void     set_text_action_handler(
201                     AB_ACTION_INFO      *action_info
202                 );
203 static void     set_value_action_handler(
204                     AB_ACTION_INFO      *action_info
205                 );
206 static void     set_label_action_handler(
207                     AB_ACTION_INFO      *action_info
208                 );
209 static void     show_help_action_handler(
210                     AB_ACTION_INFO      *action_info
211                 );
212
213 \f
214 static void     tree_enable_help(
215                     ABObj root
216                 );
217
218 static void     tree_disable_help(
219                     ABObj root
220                 );
221
222 static void     win_closeCB(
223                     Widget      w,
224                     XtPointer   client_data,
225                     XtPointer   call_data
226                 );
227
228
229 static XtCallbackProc
230 get_when_callback(AB_WHEN       when)
231 {
232     switch (when)
233     {
234       case AB_WHEN_UNDEF:               return (XtCallbackProc)NULL;
235       case AB_WHEN_ACTIVATED:           return activate_when_cb;
236       case AB_WHEN_DESTROYED:           return (XtCallbackProc)NULL;
237       case AB_WHEN_DROPPED_ON:          return (XtCallbackProc)NULL;
238       case AB_WHEN_DOUBLE_CLICKED_ON:   return (XtCallbackProc)NULL;
239       case AB_WHEN_ITEM_SELECTED:       return (XtCallbackProc)NULL;
240       case AB_WHEN_POPPED_DOWN:         return (XtCallbackProc)NULL;
241       case AB_WHEN_POPPED_UP:           return (XtCallbackProc)NULL;
242       case AB_WHEN_REPAINT_NEEDED:      return (XtCallbackProc)NULL;
243       case AB_WHEN_NUM_VALUES:          return (XtCallbackProc)NULL;
244     }
245     return (XtCallbackProc)NULL;
246 }
247
248 static INTERPRET_HANDLER
249 get_when_attach_handler(AB_WHEN when)
250 {
251     switch (when)
252     {
253       case AB_WHEN_UNDEF:               return (INTERPRET_HANDLER)NULL;
254       case AB_WHEN_ACTIVATED:           return activate_attach_handler;
255       case AB_WHEN_AFTER_CREATED:       return (INTERPRET_HANDLER)NULL;
256       case AB_WHEN_DESTROYED:           return (INTERPRET_HANDLER)NULL;
257       case AB_WHEN_DROPPED_ON:          return (INTERPRET_HANDLER)NULL;
258       case AB_WHEN_DOUBLE_CLICKED_ON:   return (INTERPRET_HANDLER)NULL;
259       case AB_WHEN_ITEM_SELECTED:       return (INTERPRET_HANDLER)NULL;
260       case AB_WHEN_POPPED_DOWN:         return (INTERPRET_HANDLER)NULL;
261       case AB_WHEN_POPPED_UP:           return (INTERPRET_HANDLER)NULL;
262       case AB_WHEN_REPAINT_NEEDED:      return (INTERPRET_HANDLER)NULL;
263       case AB_WHEN_NUM_VALUES:          return (INTERPRET_HANDLER)NULL;
264     }
265     return (INTERPRET_HANDLER)NULL;
266 }
267
268 static INTERPRET_HANDLER
269 get_when_detach_handler(AB_WHEN when)
270 {
271     switch (when)
272     {
273       case AB_WHEN_UNDEF:               return (INTERPRET_HANDLER)NULL;
274       case AB_WHEN_ACTIVATED:           return activate_detach_handler;
275       case AB_WHEN_AFTER_CREATED:       return (INTERPRET_HANDLER)NULL;
276       case AB_WHEN_DESTROYED:           return (INTERPRET_HANDLER)NULL;
277       case AB_WHEN_DROPPED_ON:          return (INTERPRET_HANDLER)NULL;
278       case AB_WHEN_DOUBLE_CLICKED_ON:   return (INTERPRET_HANDLER)NULL;
279       case AB_WHEN_ITEM_SELECTED:       return (INTERPRET_HANDLER)NULL;
280       case AB_WHEN_POPPED_DOWN:         return (INTERPRET_HANDLER)NULL;
281       case AB_WHEN_POPPED_UP:           return (INTERPRET_HANDLER)NULL;
282       case AB_WHEN_REPAINT_NEEDED:      return (INTERPRET_HANDLER)NULL;
283       case AB_WHEN_NUM_VALUES:          return (INTERPRET_HANDLER)NULL;
284     }
285     return (INTERPRET_HANDLER)NULL;
286 }
287
288 static ACTION_HANDLER
289 get_std_action_handler(AB_BUILTIN_ACTION std_act)
290 {
291     switch (std_act)
292     {
293       case AB_STDACT_UNDEF:             return (ACTION_HANDLER)NULL;
294       case AB_STDACT_DISABLE:           return disable_action_handler;
295       case AB_STDACT_ENABLE:            return enable_action_handler;
296       case AB_STDACT_HIDE:              return hide_action_handler;
297       case AB_STDACT_SET_LABEL:         return set_label_action_handler;
298       case AB_STDACT_SET_TEXT:          return set_text_action_handler;
299       case AB_STDACT_SET_VALUE:         return set_value_action_handler;
300       case AB_STDACT_SHOW:              return show_action_handler;
301       case AB_BUILTIN_ACTION_NUM_VALUES:return (ACTION_HANDLER)NULL;
302     }
303     return (ACTION_HANDLER)NULL;
304 }
305
306 \f
307 static BOOL             is_enabled = FALSE;
308
309 static ABObj    *       get_menu_item_refs(
310                             ABObj       menu_item
311                         );
312
313 /*
314  * These variables are used to track information to correct when transitioning
315  * from test mode back to build mode.
316  *
317  * conn_test_mode_initialize() and conn_enable_action_interpret() initialize
318  * the lists.
319  *
320  * conn_test_mode_cleanup() and conn_disable_action_interpret() revert what
321  * was done during test mode and free the lists.
322  */
323
324                /* conn_{enable,disable}_action_interpret() */
325 static ASet             ConnP_manage; /* objs to manage - initially visible & hidden */
326 static ASet             ConnP_senses;          /* objs to senitize */
327 static LList            ConnP_menu_item_infos; /* objs to free item infos from */
328
329                 /* conn_test_mode_{initialize,cleanup}() */
330 static ASet             ConnP_win_close;       /* dialogs, FSB(s) to rm close cb from */
331 static ASet             ConnP_modules_disable; /* modules to disable */
332 static ASet             ConnP_wins_deiconify;  /* windows to deiconify */
333 static ASet             ConnP_layer;           /* layers that were shown or hidden */
334
335 /*
336  * Final entry into test mode.
337  *
338  * Windows need to be mapped/unmapped, visibility set/unset, sensitivity
339  * set/unset, connection inperpretations setup, help setup, window close
340  * callbacks added, and ? (think that's it).
341  */
342 extern void
343 conn_enable_action_interpret(
344     ABObj       project,
345     BOOL        to_test_project
346 )
347 {
348     if (project == NULL || !obj_is_project(project))
349         return;
350
351     ConnP_manage          = util_aset_create();
352     ConnP_senses          = util_aset_create();
353     ConnP_menu_item_infos = util_llist_create();
354
355     if (to_test_project)
356         tree_set_initial_state(project, FALSE);
357     else
358     {
359         ABObj           mod;
360         AB_TRAVERSAL    trav;
361
362         for (trav_open(&trav, project, AB_TRAV_MODULES);
363              (mod = trav_next(&trav)) != NULL; )
364             if (obj_is_module(mod) && obj_has_flag(mod, MappedFlag))
365                 tree_set_initial_state(mod, TRUE);
366         trav_close(&trav);
367     }
368     is_enabled = TRUE;
369 }
370
371 /*
372  * Cleanup on exit from Test mode
373  */
374 extern void
375 conn_disable_action_interpret(
376     ABObj       project
377 )
378 {
379     ABObj               obj;
380     AB_TRAVERSAL        trav;
381
382     if (!is_enabled)
383         return;
384
385     if (project == NULL || !obj_is_project(project))
386         return;
387
388     tree_restore_build_state(project);
389
390     util_aset_iterate(ConnP_manage, manage_objs);
391     util_aset_iterate(ConnP_senses, sensitize_objects);
392     util_llist_iterate(ConnP_menu_item_infos, free_infos);
393
394     util_llist_destroy(ConnP_menu_item_infos);
395     util_aset_destroy(ConnP_manage);
396     util_aset_destroy(ConnP_senses);
397
398     is_enabled = FALSE;
399 }
400
401 /*
402  * recurse throught the tree, setting the initial state of the objects
403  */
404 static void
405 tree_set_initial_state(
406     ABObj       obj,
407     BOOL        ignore_win_visibility
408 )
409 {
410     ABObj               child;
411     AB_TRAVERSAL        trav;
412
413     if (obj_is_menu_item(obj))
414     {
415         ABObj   *ref_list = get_menu_item_refs(obj);
416         ABObj   *cur_obj;
417
418         if (ref_list != NULL)
419         {
420             for (cur_obj = ref_list; *cur_obj != NULL; cur_obj++)
421                 set_initial_state(*cur_obj, ignore_win_visibility);
422             XtFree((char *)ref_list);
423         }
424     }
425     else if (!obj_is_virtual(obj))
426         set_initial_state(obj, ignore_win_visibility);
427
428     for (trav_open(&trav, obj, AB_TRAV_SALIENT_CHILDREN);
429          (child = trav_next(&trav)) != NULL; )
430         tree_set_initial_state(child, ignore_win_visibility);
431     trav_close(&trav);
432 }
433
434 /*
435  * recurse throught the tree, setting the initial state of the objects
436  */
437 static void
438 tree_set_obj_initial_state(
439     ABObj       obj
440 )
441 {
442     ABObj               child;
443     AB_TRAVERSAL        trav;
444
445     if (obj_is_menu_item(obj))
446     {
447         ABObj   *ref_list = get_menu_item_refs(obj);
448         ABObj   *cur_obj;
449
450         if (ref_list != NULL)
451         {
452             for (cur_obj = ref_list; *cur_obj != NULL; cur_obj++)
453                 set_obj_initial_state(*cur_obj);
454             XtFree((char *)ref_list);
455         }
456     }
457     else if (!obj_is_virtual(obj))
458         set_obj_initial_state(obj);
459
460     for (trav_open(&trav, obj, AB_TRAV_SALIENT_CHILDREN);
461          (child = trav_next(&trav)) != NULL; )
462         tree_set_obj_initial_state(child);
463     trav_close(&trav);
464 }
465
466 static void
467 tree_restore_build_state(
468     ABObj       obj
469 )
470 {
471     ABObj               child;
472     AB_TRAVERSAL        trav;
473
474     if (!obj_is_virtual(obj))
475         restore_build_state(obj);
476
477     for (trav_open(&trav, obj, AB_TRAV_SALIENT_CHILDREN);
478          (child = trav_next(&trav)) != NULL; )
479         tree_restore_build_state(child);
480     trav_close(&trav);
481 }
482
483 static void
484 set_obj_initial_state(
485     ABObj       obj
486 )
487 {
488     if (!obj || !objxm_get_widget(obj))
489         return;
490     
491     if (!obj_is_initially_active(obj))
492     {
493         XtSetSensitive(objxm_get_widget(obj), FALSE);
494
495         /* apply to the actual XmList also */
496         if (obj_is_list(obj))
497             XtSetSensitive(objxm_get_widget(
498                                objxm_comp_get_subobj(obj, AB_CFG_OBJECT_OBJ)),
499                            FALSE);
500         
501         if (!obj_is_menu_item(obj))
502             util_llist_insert_after((LList)ConnP_senses, obj);
503     }
504
505     if (!obj_is_window(obj) && !obj_is_initially_visible(obj))
506     {
507         ui_set_visible(objxm_get_widget(obj), FALSE);
508         util_aset_add(ConnP_manage, obj);
509     }
510 }
511
512 static void
513 set_initial_state(
514     ABObj       trg_obj,
515     BOOL        ignore_win_visibility
516 )
517 {
518     /*
519      * Basic Algorithm:
520      *  trg_obj is a window (e.g. BASE_WINDOW, DIALOG or FILE_CHOOSER):
521      *                          Initial state
522      *                  Visible                         Not Visible
523      *
524      *          Shown     Do nothing                      Unmap
525      *
526      *          Hidden  XmConfig module if not already    Do nothing
527      *                  done, and map window/dialog
528      *
529      *  all other ui elements:
530      *          if window/dialog it belongs to is mapped,
531      *                  do the active/inactive setting
532      *                  set the visibility
533      *          else
534      *                  do nothing.
535      *
536      * This applies directly if we are going to TestProject mode (in which
537      * case ignore_win_visibility will be FALSE).  If we are going to
538      * TestShowModules mode (ignore_win_visibility is TRUE) then we modify
539      * the above algorithm so that it ignores the current state but is able
540      * to reset to it when we return to Build mode (in case any connections
541      * have hidden/shown something).
542      */
543     AB_OBJECT_TYPE      trg_type = obj_get_type(trg_obj);
544
545     if (obj_is_window(trg_obj))
546     {
547         BOOL is_visible = obj_is_initially_visible(trg_obj);
548
549         /* Are we going to TestShownModules mode? */
550         if(ignore_win_visibility)
551         {
552             if (setup_window_for_test_mode(trg_obj) == -1) goto cret;
553
554             /* 
555             ** For TestShownModules, if the object is currently invisible
556             ** show it.
557             */
558             if (!obj_has_flag(trg_obj, MappedFlag))
559             {
560                 if (objxm_tree_map(trg_obj, TRUE) == -1) goto cret;
561             }
562
563             /* 
564             ** If the object is supposed to be iconic (and visible) 
565             ** make it iconic, but remember that we have to deiconify
566             ** it we go back to Build mode
567             */
568             if (obj_is_initially_iconic(trg_obj))
569             {
570                 make_win_iconic(trg_obj, TRUE);
571                 util_llist_insert_after(ConnP_wins_deiconify, trg_obj);
572             }
573         }
574         else
575         {
576             /* 
577             ** No, we're going to TestProject mode, so we must honor
578             ** initial state (but remember current state)
579             */
580             if (is_visible)             /* The object should be visible */
581             {
582                 if (setup_window_for_test_mode(trg_obj) == -1) goto cret;
583
584                 /* 
585                 ** If the object is currently invisible show it.
586                 */
587                 if (!obj_has_flag(trg_obj, MappedFlag))
588                 {
589                     if (objxm_tree_map(trg_obj, TRUE) == -1) goto cret;
590                 }
591
592                 /* 
593                 ** If the object is supposed to be iconic (and visible) 
594                 ** make it iconic, but remember that we have to deiconify
595                 ** it we go back to Build mode
596                 */
597                 if (obj_is_initially_iconic(trg_obj))
598                 {
599                     make_win_iconic(trg_obj, TRUE);
600                     util_llist_insert_after(ConnP_wins_deiconify, trg_obj);
601                 }
602             }
603             else /* !is_visible */
604             {
605                 /* 
606                 ** Object is supposed to be invisible.  If it is currently
607                 ** visible and is a real widget, make invisible.
608                 */
609                 if (obj_has_flag(trg_obj, MappedFlag) && objxm_get_widget(trg_obj))
610                     objxm_tree_map(trg_obj, FALSE);
611             }
612         }
613     }
614     
615     set_obj_initial_state(trg_obj);
616     
617 cret:
618     return;
619 }
620
621 static void
622 restore_build_state(
623     ABObj       trg_obj
624 )
625 {
626     Widget      trg_w;
627
628     if ((trg_w = objxm_get_widget(trg_obj)) == NULL)
629         return;
630
631     /* Going back to Build mode, we need to ensure all windows
632      * are resizable (have resize decorations) again.
633      */  
634     if (obj_is_window(trg_obj) && !obj_get_resizable(trg_obj))
635         ui_win_set_resizable(trg_w, True, obj_has_flag(trg_obj, MappedFlag));
636 }
637
638 static int
639 setup_window_for_test_mode(
640     ABObj       win
641 )
642 {
643     int         ret_val = -1;
644     ABObj       module = obj_get_module(win);
645
646     if (module == NULL)
647         goto cret;
648
649     /* Make sure the module is instantiated */
650     if (!obj_has_flag(module, InstantiatedFlag))
651     {
652         if (abobj_instantiate_tree(module, TRUE) == -1)
653             goto cret;
654     }
655     
656     /* 
657     ** If this module isn't already in the list of modules we've set up,
658     ** add connection interpretation and help and add it to the list.
659     */
660     if (!util_llist_find(ConnP_modules_disable, module))
661     {
662         AB_TRAVERSAL    trav;
663         ABObj           action;
664
665         objxm_instantiate_menus(module);
666
667         util_aset_add(ConnP_modules_disable, module);
668
669         /* Setup connections */
670         for (trav_open(&trav, obj_get_project(module), AB_TRAV_ACTIONS);
671              (action = trav_next(&trav)) != NULL; )
672         {
673             AB_ACTION_INFO      *info = &(action->info.action);
674
675             if (info == NULL || info->from == NULL ||
676                 obj_get_module(info->from) != module)
677                 continue;
678             
679             attach_interpretation(action);
680         }
681         trav_close(&trav);
682
683         /* Enable test-mode help support on this module's children */
684         tree_enable_help(module);
685     }
686
687     /*
688     ** Now, we can setup the window.
689     */
690     if(obj_is_base_win(win) || obj_is_popup_win(win) || obj_is_file_chooser(win)) 
691     {
692         /* Windows, Dialogs and FSB's need a window-close callback to
693          * handle "manual" close as if it were a 'hide' action.
694          */
695         ui_add_window_close_callback(objxm_get_widget(win),
696                                      win_closeCB, (XtPointer)win, XmUNMAP);
697         util_aset_add(ConnP_win_close, win);
698
699
700         /* In Build mode, ALL windows are resizable, therefore we need
701          * to remove the resize decorations from any window whose
702          * "User Resize" attribute is "Fixed".
703          */
704         if (obj_get_resizable(win) == False)
705         {
706             ui_win_set_resizable(objxm_get_widget(win), False, 
707                                  obj_has_flag(win, MappedFlag));
708             /*
709              * Since we need to unmap/remap the window in order to get
710              * the decorations to change, we need to mark this window
711              * object so that when the iconify_tracker event handler is
712              * called, it doesn't interpret the Unmap event as an
713              * iconify. (this is an unfortunate hack to get around
714              * the mysterious problem of the Unmap event occurring
715              * AFTER we return to BUILD mode).
716              */
717             obj_set_flag(win, DecorChangedFlag);
718         }    
719     }
720     
721     ret_val = 0;
722 cret:
723     return(ret_val);
724 }
725
726 static void
727 disable_modules(
728     void        *cl_data
729 )
730 {
731     ABObj               mod = (ABObj)cl_data;
732     ABObj               action;
733     AB_TRAVERSAL        trav;
734
735     if (mod == NULL || !obj_is_module(mod))
736         goto cret;
737     
738     /* Remove connections */
739     for (trav_open(&trav, obj_get_project(mod), AB_TRAV_ACTIONS);
740          (action = trav_next(&trav)) != NULL; )
741     {
742         AB_ACTION_INFO  *info = &(action->info.action);
743         
744         if (info == NULL || info->from == NULL ||
745             obj_get_module(info->from) != mod)
746             continue;
747         
748         detach_interpretation(action);
749     }
750     trav_close(&trav);
751     
752     /* Disable test-mode help support */
753     tree_disable_help(mod);
754
755     objxm_destroy_menus(mod);
756 cret:
757     return;
758 }
759
760 static void
761 deiconify_wins(
762     void        *cl_data
763 )
764 {
765     ABObj       obj = (ABObj)cl_data;
766
767     make_win_iconic(obj, FALSE);
768 }
769
770 static void
771 sensitize_objects(
772     void        *cl_data
773 )
774 {
775     ABObj       obj = (ABObj)cl_data;
776
777     if (obj != NULL &&
778         !tmodeP_obj_has_flags(obj_get_window(obj), TestModeFlagResizedWindow) &&
779         objxm_get_widget(obj) != NULL)
780     {
781         XtSetSensitive(objxm_get_widget(obj), TRUE);
782         
783         /* apply to the actual XmList also */
784         if (obj_is_list(obj))
785             XtSetSensitive(objxm_get_widget(
786                                objxm_comp_get_subobj(obj, AB_CFG_OBJECT_OBJ)),
787                            TRUE);
788     }
789 }
790
791 static void
792 free_infos(
793     void        *cl_data
794 )
795 {
796     AB_ACTION_INFO      *info = (AB_ACTION_INFO *)cl_data;
797
798     if (info != NULL)
799     {
800         INTERPRET_HANDLER       handler;
801         AB_WHEN                 c_when;
802
803         c_when = info->when;
804         handler = get_when_detach_handler(c_when);
805         if (handler != NULL && info->from != NULL)
806             (*handler)(info, get_when_callback(c_when));
807
808         XtFree((char *)info);
809     }
810 }
811
812 static void
813 reset_layer(
814     void        *cl_data
815 )
816 {
817     ABObj       obj = (ABObj)cl_data;
818
819     if (obj != NULL)
820     {
821         if (obj_is_layers(obj))
822             abobj_layer_manage_visible(obj);
823     }
824 }
825
826 /* manage non-window objects */
827 static void
828 manage_objs(
829     void        *cl_data
830 )
831 {
832     ABObj       obj    = (ABObj)cl_data;
833
834     /*
835     ** If the window was resized, there is no need to set the
836     ** visibility. The widget will be re-instantiated.
837     */
838     if (obj && !obj_is_window(obj) && objxm_get_widget(obj) &&
839         !tmodeP_obj_has_flags(obj_get_window(obj), TestModeFlagResizedWindow))
840     {
841         ui_set_visible(objxm_get_widget(obj), TRUE);
842     }
843 }
844
845 static void
846 attach_interpretation(
847     ABObj       action
848 )
849 {
850     AB_ACTION_INFO      *info = &(action->info.action);
851     INTERPRET_HANDLER   handler;
852     AB_WHEN             c_when;
853     BOOL                needs_from_refs = FALSE;
854     BOOL                needs_to_refs = FALSE;
855
856     c_when = info->when;
857     handler = get_when_attach_handler(c_when);
858     if (handler == NULL || info->from == NULL)
859         return;
860
861     /* if source is a menu item */
862     if (obj_is_menu_item(info->from))
863         needs_from_refs = TRUE;
864
865     if (info->func_type == AB_FUNC_BUILTIN)
866     { /* connection is a builtin one and needs a target */
867         /* if target is a menu item */
868         if (info->to != NULL && obj_is_menu_item(info->to))
869             needs_to_refs = TRUE;
870     }
871
872     if (needs_from_refs == TRUE)
873     {
874         ABObj   *from_refs = get_menu_item_refs(info->from);
875
876         if (from_refs == NULL)
877             return;
878
879         if (needs_to_refs == TRUE)
880         {
881             ABObj       *to_refs = get_menu_item_refs(info->to);
882
883             if (to_refs == NULL)
884             {
885                 XtFree((char *)from_refs);
886                 return;
887             }
888             attach_for_both_refs(from_refs, to_refs, info,
889                                         handler, get_when_callback(c_when));
890             XtFree((char *)to_refs);
891         }
892         else
893             attach_for_single_refs(TRUE, from_refs, info,
894                                         handler, get_when_callback(c_when));
895         XtFree((char *)from_refs);
896     }
897     else if (needs_to_refs == TRUE)
898     {
899         ABObj   *to_refs = get_menu_item_refs(info->to);
900
901         if (to_refs == NULL)
902             return;
903
904         attach_for_single_refs(FALSE, to_refs, info,
905                                     handler, get_when_callback(c_when));
906         XtFree((char *)to_refs);
907     }
908     else
909         (*handler)(info, get_when_callback(c_when));
910 }
911
912 static void
913 attach_for_both_refs(
914     ABObj               *from_refs,
915     ABObj               *to_refs,
916     AB_ACTION_INFO      *info,
917     INTERPRET_HANDLER   handler,
918     XtCallbackProc      when_callback
919 )
920 {
921     ABObj       *trav_from;
922
923     for (trav_from = from_refs; *trav_from != NULL; trav_from++)
924     {
925         ABObj   *trav_to;
926
927         for (trav_to = to_refs; *trav_to != NULL; trav_to++)
928         {
929             AB_ACTION_INFO      *new_info;
930
931             /* create new info structure and copy old one */
932             new_info = (AB_ACTION_INFO *)
933                                 XtMalloc(sizeof(AB_ACTION_INFO));
934             memmove((void *)new_info, (void *)info,
935                                         sizeof(AB_ACTION_INFO));
936
937             /* assign reference instead of item to from and to */
938             new_info->from = *trav_from;
939             new_info->to   = *trav_to;
940
941             /* add info to list */
942             util_llist_insert_after(ConnP_menu_item_infos, new_info);
943             /* call the handler on this info record */
944             (*handler)(new_info, when_callback);
945         }
946     }
947 }
948
949 static void
950 attach_for_single_refs(
951     BOOL                for_from,
952     ABObj               *item_refs,
953     AB_ACTION_INFO      *info,
954     INTERPRET_HANDLER   handler,
955     XtCallbackProc      when_callback
956 )
957 {
958     ABObj       *trav_item;
959
960     for (trav_item = item_refs; *trav_item != NULL; trav_item++)
961     {
962         AB_ACTION_INFO  *new_info;
963
964         /* create new info structure and copy old one */
965         new_info = (AB_ACTION_INFO *)
966                             XtMalloc(sizeof(AB_ACTION_INFO));
967         memmove((void *)new_info, (void *)info,
968                                     sizeof(AB_ACTION_INFO));
969
970         /* assign reference instead of item to from or to */
971         if (for_from)
972             new_info->from = *trav_item;
973         else
974             new_info->to = *trav_item;
975
976         /* add info to list */
977         util_llist_insert_after(ConnP_menu_item_infos, new_info);
978         /* call the handler on this info record */
979         (*handler)(new_info, when_callback);
980     }
981 }
982
983 static void
984 detach_interpretation(
985     ABObj       action
986 )
987 {
988     AB_ACTION_INFO      *info = &(action->info.action);
989     INTERPRET_HANDLER   handler;
990     AB_WHEN             c_when;
991
992     c_when = info->when;
993     handler = get_when_detach_handler(c_when);
994     if (handler == NULL || info->from == NULL)
995         return;
996
997     (*handler)(info, get_when_callback(c_when));
998 }
999
1000 static ACTION_HANDLER
1001 get_action_handler(
1002     AB_ACTION_INFO      *notify_info
1003 )
1004 {
1005     ACTION_HANDLER      handler = (ACTION_HANDLER)NULL;
1006
1007     switch (notify_info->func_type)
1008     {
1009       case AB_FUNC_BUILTIN:
1010         /*
1011          * case target is not a window or dialog:
1012          * case target is a window or dialog and !show and !hide:
1013          *      if window/dialog unmapped, return NULL
1014          * case target is a window or dialog and show or hide:
1015          *      return handler (xmconfig processing in handlers)
1016          *
1017          */
1018         {
1019             ABObj               trg = notify_info->to;
1020             AB_OBJECT_TYPE      trg_type;
1021
1022             if (trg == NULL)
1023                 goto cret;
1024
1025             trg_type = obj_get_type(trg);
1026             /* Used to just check for BASE_WINDOW and DIALOG */
1027             if (obj_is_window(trg))
1028             {
1029                 AB_BUILTIN_ACTION std_act = notify_info->func_value.builtin;
1030
1031                 switch (std_act)
1032                 {
1033                   case AB_STDACT_SHOW:
1034                   case AB_STDACT_HIDE:
1035                     handler = get_std_action_handler(
1036                                     notify_info->func_value.builtin);
1037                     break;
1038                   default:
1039                     if (!obj_has_flag(trg, MappedFlag))
1040                         goto cret;
1041                     else
1042                         handler = get_std_action_handler(
1043                                         notify_info->func_value.builtin);
1044                     break;
1045                 }
1046             }
1047             else
1048             {
1049                 ABObj   win = obj_get_window(trg);
1050
1051                 if (win == NULL)
1052                     goto cret;
1053                 if (!obj_has_flag(win, MappedFlag))
1054                     goto cret;
1055                 handler = get_std_action_handler(
1056                                 notify_info->func_value.builtin);
1057             }
1058             break;
1059         }
1060       case AB_FUNC_USER_DEF:
1061         handler = user_def_fn_handler;
1062         break;
1063       case AB_FUNC_CODE_FRAG:
1064         handler = code_frag_handler;
1065         break;
1066       case AB_FUNC_ON_ITEM_HELP:
1067         handler = on_item_help_handler;
1068         break;
1069       case AB_FUNC_HELP_VOLUME:
1070         handler = help_volume_handler;
1071         break;
1072     }
1073 cret:
1074     return(handler);
1075 }
1076
1077 \f
1078 static void
1079 activate_attach_handler(
1080     AB_ACTION_INFO      *notify_info,
1081     XtCallbackProc      when_cb
1082 )
1083 {
1084     ABObj       c_from  = notify_info->from;
1085     ABObj       c_to    = notify_info->to;
1086     Widget      attach_w;
1087     AB_ITEM_TYPE        item_type;
1088
1089     if (when_cb == NULL)
1090         return;
1091
1092     switch(obj_get_type(c_from))
1093     {
1094       case AB_TYPE_ITEM:
1095         item_type = (AB_ITEM_TYPE)obj_get_subtype(c_from);
1096         switch(item_type)
1097         {
1098           case AB_ITEM_FOR_MENU:
1099             if (obj_has_menu(c_from))
1100             {
1101                 if (objxm_get_widget(c_from) != NULL)
1102                     XtAddCallback(objxm_get_widget(c_from),
1103                                 XmNcascadingCallback,
1104                                 when_cb, (XtPointer)notify_info);
1105             }
1106             else
1107             {
1108                 if (objxm_get_widget(c_from)!= NULL)
1109                     XtAddCallback(objxm_get_widget(c_from),
1110                                 XmNactivateCallback,
1111                                 when_cb, (XtPointer)notify_info);
1112             }
1113             break;
1114
1115           case AB_ITEM_FOR_CHOICE:
1116             attach_w = objxm_get_widget(c_from);
1117             if (attach_w != NULL)
1118             {
1119                 if (obj_is_option_menu(
1120                         obj_get_root(obj_get_parent(c_from))))
1121                     XtAddCallback(attach_w, XmNactivateCallback,
1122                                     when_cb, (XtPointer)notify_info);
1123                 else
1124                     XtAddCallback(attach_w, XmNvalueChangedCallback,
1125                                     when_cb, (XtPointer)notify_info);
1126             }
1127             break;
1128         }
1129         break;
1130       case AB_TYPE_BUTTON:
1131         attach_w = objxm_get_widget(c_from);
1132         if (attach_w != NULL)
1133             XtAddCallback(attach_w, XmNactivateCallback,
1134                             when_cb, (XtPointer)notify_info);
1135         break;
1136       default:
1137         break;
1138     }
1139 }
1140
1141 static void
1142 post_menu_attach_handler(
1143     AB_ACTION_INFO      *notify_info,
1144     XtCallbackProc      when_cb
1145 )
1146 {
1147     ABObj       c_from  = notify_info->from;
1148     ABObj       c_to    = notify_info->to;
1149     Widget      attach_w;
1150     AB_ITEM_TYPE        item_type;
1151
1152     if (when_cb == NULL)
1153         return;
1154
1155     switch(obj_get_type(c_from))
1156     {
1157       case AB_TYPE_ITEM:
1158         item_type = (AB_ITEM_TYPE)obj_get_subtype(c_from);
1159         switch(item_type)
1160         {
1161           case AB_ITEM_FOR_MENU:
1162             {
1163                 if (obj_has_menu(c_from))
1164                 {
1165                     if (objxm_get_widget(c_from) != NULL)
1166                         XtAddCallback(objxm_get_widget(c_from),
1167                                     XmNcascadingCallback,
1168                                     when_cb, (XtPointer)notify_info);
1169                 }
1170                 else
1171                 {
1172                     if (objxm_get_widget(c_from) != NULL)
1173                         XtAddCallback(objxm_get_widget(c_from),
1174                                     XmNactivateCallback,
1175                                     when_cb, (XtPointer)notify_info);
1176                 }
1177             }
1178             break;
1179         }
1180         break;
1181       default:
1182         break;
1183     }
1184 }
1185
1186 static void
1187 activate_detach_handler(
1188     AB_ACTION_INFO      *notify_info,
1189     XtCallbackProc      when_cb
1190 )
1191 {
1192     ABObj       c_from  = notify_info->from;
1193     Widget      attach_w;
1194     AB_ITEM_TYPE        item_type;
1195
1196     if (when_cb == NULL)
1197         return;
1198
1199     switch(obj_get_type(c_from))
1200     {
1201       case AB_TYPE_ITEM:
1202         item_type = (AB_ITEM_TYPE)obj_get_subtype(c_from);
1203         switch(item_type)
1204         {
1205           case AB_ITEM_FOR_MENU:
1206             {
1207                 if (obj_has_menu(c_from))
1208                 {
1209                     if (objxm_get_widget(c_from) != NULL)
1210                         XtRemoveCallback(objxm_get_widget(c_from),
1211                                     XmNcascadingCallback,
1212                                     when_cb, (XtPointer)notify_info);
1213                 }
1214                 else
1215                 {
1216                     if (objxm_get_widget(c_from) != NULL)
1217                         XtRemoveCallback(objxm_get_widget(c_from),
1218                                     XmNactivateCallback,
1219                                     when_cb, (XtPointer)notify_info);
1220                 }
1221             }
1222             break;
1223
1224           case AB_ITEM_FOR_CHOICE:
1225             attach_w = objxm_get_widget(c_from);
1226             if (attach_w != NULL)
1227             {
1228                 if (obj_is_option_menu(
1229                         obj_get_root(obj_get_parent(c_from))))
1230                     XtRemoveCallback(attach_w, XmNactivateCallback,
1231                                     when_cb, (XtPointer)notify_info);
1232                 else
1233                     XtRemoveCallback(attach_w, XmNvalueChangedCallback,
1234                                     when_cb, (XtPointer)notify_info);
1235             }
1236             break;
1237         }
1238         break;
1239       case AB_TYPE_BUTTON:
1240         attach_w = objxm_get_widget(c_from);
1241         if (attach_w != NULL)
1242             XtRemoveCallback(attach_w, XmNactivateCallback,
1243                                 when_cb, (XtPointer)notify_info);
1244         break;
1245       default:
1246         break;
1247     }
1248 }
1249
1250 static void
1251 post_menu_detach_handler(
1252     AB_ACTION_INFO      *notify_info,
1253     XtCallbackProc      when_cb
1254 )
1255 {
1256     ABObj       c_from  = notify_info->from;
1257     Widget      attach_w;
1258     AB_ITEM_TYPE        item_type;
1259
1260     if (when_cb == NULL)
1261         return;
1262
1263     switch(obj_get_type(c_from))
1264     {
1265       case AB_TYPE_ITEM:
1266         item_type = (AB_ITEM_TYPE)obj_get_subtype(c_from);
1267         switch(item_type)
1268         {
1269           case AB_ITEM_FOR_MENU:
1270             {
1271                 if (obj_has_menu(c_from))
1272                 {
1273                     if (objxm_get_widget(c_from) != NULL)
1274                         XtRemoveCallback(objxm_get_widget(c_from),
1275                                     XmNcascadingCallback,
1276                                     when_cb, (XtPointer)notify_info);
1277                 }
1278                 else
1279                 {
1280                     if (objxm_get_widget(c_from) != NULL)
1281                         XtRemoveCallback(objxm_get_widget(c_from),
1282                                     XmNactivateCallback,
1283                                     when_cb, (XtPointer)notify_info);
1284                 }
1285             }
1286             break;
1287         }
1288         break;
1289       default:
1290         break;
1291     }
1292 }
1293 \f
1294 static void
1295 activate_when_cb(
1296     Widget      w,
1297     XtPointer   client_data,
1298     XtPointer   call_data
1299 )
1300 {
1301     AB_ACTION_INFO      *notify_info = (AB_ACTION_INFO *)client_data;
1302     ACTION_HANDLER      handler;
1303
1304     if (notify_info == NULL)
1305         return;
1306
1307     switch (obj_get_type(notify_info->from))
1308     {
1309       case AB_TYPE_ITEM:
1310         if (obj_get_subtype(notify_info->from) == (int)AB_ITEM_FOR_CHOICE)
1311         {
1312             if (!obj_is_option_menu(
1313                     obj_get_root(obj_get_parent(notify_info->from))))
1314             {
1315                 XmToggleButtonCallbackStruct *tog_data =
1316                         (XmToggleButtonCallbackStruct *)call_data;
1317
1318                 if (!tog_data || tog_data->reason != XmCR_VALUE_CHANGED ||
1319                     !tog_data->set)
1320                     return;
1321             }
1322         }
1323         break;
1324       default:
1325         break;
1326     }
1327
1328     handler = get_action_handler(notify_info);
1329     if (handler != NULL)
1330         (*handler)(notify_info);
1331 }
1332
1333 static void
1334 post_menu_when_cb(
1335     Widget      w,
1336     XtPointer   client_data,
1337     XtPointer   call_data
1338 )
1339 {
1340     AB_ACTION_INFO      *notify_info = (AB_ACTION_INFO *)client_data;
1341     ACTION_HANDLER      handler;
1342
1343     if (notify_info == NULL)
1344         return;
1345
1346     handler = get_action_handler(notify_info);
1347
1348     if (handler != NULL)
1349         (*handler)(notify_info);
1350 }
1351 \f
1352 static void
1353 user_def_fn_handler(
1354     AB_ACTION_INFO      *action_info
1355 )
1356 {
1357     if (action_info->func_type != AB_FUNC_USER_DEF)
1358         return;
1359
1360     if (action_info->func_value.func_name != (ISTRING)NULL)
1361     printf("Call user-defined function: \"%s\"\n",
1362                 istr_string(action_info->func_value.func_name));
1363 }
1364
1365 static void
1366 code_frag_handler(
1367     AB_ACTION_INFO      *action_info
1368 )
1369 {
1370     if (action_info->func_type != AB_FUNC_CODE_FRAG)
1371         return;
1372
1373     printf("Execute user code\n");
1374 }
1375
1376 static void
1377 on_item_help_handler(
1378     AB_ACTION_INFO      *action_info
1379 )
1380 {
1381     if (action_info->func_type != AB_FUNC_ON_ITEM_HELP)
1382         return;
1383     dtb_do_onitem_help();
1384 }
1385
1386 static void 
1387 help_volume_handler( 
1388     AB_ACTION_INFO      *action_info 
1389
1390
1391     if (action_info->func_type != AB_FUNC_HELP_VOLUME) 
1392         return;    
1393
1394     
1395     dtb_show_help_volume_info(istr_string(action_info->volume_id),
1396                 istr_string(action_info->location)); 
1397
1398
1399 /*
1400 ** Handle a 'show-help' connection by dispatching the XmNhelpCallback on the
1401 ** target object (if it has one).
1402 */
1403 static void
1404 show_help_action_handler(
1405     AB_ACTION_INFO      *action_info
1406 )
1407 {
1408     ABObj               c_to    = action_info->to;
1409     ABObj               root_obj, help_obj;
1410     
1411     if (c_to == NULL || objxm_get_widget(c_to) == NULL)
1412         return;
1413
1414     if(obj_has_help_data(c_to) == True) {
1415         help_obj = objxm_comp_get_subobj(c_to,AB_CFG_HELP_OBJ);
1416         if(help_obj != NULL) {
1417                 XtCallCallbacks(objxm_get_widget(help_obj),XmNhelpCallback,
1418                         (XtPointer)NULL);
1419         }
1420     }
1421 }
1422
1423 static void
1424 show_action_handler(
1425     AB_ACTION_INFO      *action_info
1426 )
1427 {
1428     ABObj               c_to    = action_info->to;
1429     ABObj               layer;
1430     
1431     /* If target object doesn't exist, just return */
1432     if (c_to == NULL) return;
1433
1434     if(obj_is_window(c_to))
1435     {
1436         if (setup_window_for_test_mode(c_to) == -1)
1437             goto cret;
1438         if (obj_has_flag(c_to, MappedFlag))
1439             goto cret;
1440         tree_set_obj_initial_state(c_to);
1441         if (objxm_tree_map(c_to, TRUE) == -1)
1442             goto cret;
1443     }
1444     else {
1445         /* Don't do anything with an unrealized non-window object */
1446         if(objxm_get_widget(c_to) && !XtIsManaged(objxm_get_widget(c_to)))
1447         {
1448             if (!obj_is_menu_item(c_to)) {
1449                 /* Layers */
1450                 if (obj_is_layers(obj_get_parent(c_to)))
1451                 {
1452                     layer = obj_get_parent(c_to);
1453                     /*
1454                      * If there is only one pane, this one must be it.
1455                      * Thus, do nothing; else manage it.
1456                      */
1457                     if (obj_get_num_salient_children(layer) > 1)
1458                     {
1459                         ui_set_visible(objxm_get_widget(c_to), TRUE);
1460
1461                         /* add layer to clean up when we go back to Build Mode */
1462                         util_aset_add(ConnP_layer, layer);
1463                     }
1464                 }
1465                 else
1466                 {
1467                     ui_set_visible(objxm_get_widget(c_to), TRUE);
1468                 }
1469             }
1470         }
1471     }
1472 cret:
1473     return;
1474 }
1475
1476
1477 static void
1478 hide_action_handler(
1479     AB_ACTION_INFO      *action_info
1480 )
1481 {
1482     ABObj               c_to    = action_info->to;
1483     ABObj               layer;
1484     
1485     if (!c_to || !objxm_get_widget(c_to))
1486         return;
1487
1488     if(obj_is_window(c_to))
1489     {
1490         ABObj   module = obj_get_module(c_to);
1491
1492         if (!module)
1493             goto cret;
1494         if (obj_has_flag(c_to, MappedFlag))
1495         {
1496             if (objxm_tree_map(c_to, FALSE) == -1)
1497                 goto cret;
1498         }
1499     }
1500     else
1501     {
1502         if (XtIsManaged(objxm_get_widget(c_to)))
1503         {
1504             if (!obj_is_menu_item(c_to)) {
1505                 /* Layers */
1506                 if (obj_is_layers(obj_get_parent(c_to)))
1507                 {
1508                     layer = obj_get_parent(c_to);
1509                     /*
1510                      * If there is only one pane, this one must be it.
1511                      * Thus, do nothing; else unmanage it.
1512                      */
1513                     if (obj_get_num_salient_children(layer) > 1)
1514                     {
1515                         ui_set_visible(objxm_get_widget(c_to), FALSE);
1516
1517                         /* add layer to clean up when we go back to Build Mode? */
1518                         util_aset_add(ConnP_layer, layer);
1519                     }
1520                 }
1521                 else
1522                     ui_set_visible(objxm_get_widget(c_to), FALSE);
1523
1524                 /* Show this object when we go back to Build mode */
1525                 util_aset_add(ConnP_manage, c_to);
1526             }
1527         }
1528     }
1529 cret:
1530     return;
1531 }
1532
1533 static void
1534 enable_action_handler(
1535     AB_ACTION_INFO      *action_info
1536 )
1537 {
1538     ABObj       c_to    = action_info->to;
1539     
1540     if (c_to == NULL || objxm_get_widget(c_to) == NULL)
1541         return;
1542
1543     ui_set_active(objxm_get_widget(c_to), TRUE);
1544         
1545     if (!obj_is_menu_item(c_to))
1546         util_aset_remove(ConnP_senses, c_to);
1547 }
1548
1549 static void
1550 disable_action_handler(
1551     AB_ACTION_INFO      *action_info
1552 )
1553 {
1554     ABObj       c_to    = action_info->to;
1555     
1556     if (c_to == NULL || objxm_get_widget(c_to) == NULL)
1557         return;
1558
1559     ui_set_active(objxm_get_widget(c_to), FALSE);
1560         
1561     if (!obj_is_menu_item(c_to))
1562         util_aset_add(ConnP_senses, c_to);
1563 }
1564
1565 static void
1566 set_text_action_handler(
1567     AB_ACTION_INFO      *action_info
1568 )
1569 {
1570     ABObj       c_to    = action_info->to;
1571     
1572     if (c_to == NULL)
1573         return;
1574
1575     if (obj_is_text(c_to))
1576     {
1577         ABObj   subObj   = NULL;
1578         ISTRING txt_istr = NULL;
1579         STRING  txt_str  = NULL;
1580
1581         /* obtain the actual text object */
1582         subObj = objxm_comp_get_subobj(c_to, AB_CFG_OBJECT_OBJ);
1583         if (subObj == NULL || objxm_get_widget(subObj) == NULL)
1584             return;
1585
1586         /* obtain the string */
1587         txt_istr = action_info->arg_value.sval;
1588         if (txt_istr != (ISTRING)NULL)
1589             txt_str = istr_string(txt_istr);
1590         else
1591             txt_str = Util_empty_string;
1592             
1593         /* set the string on the widget */
1594         ui_field_set_string(objxm_get_widget(subObj), txt_str);
1595
1596         /* mark this obj's window as dirty */
1597         tmodeP_obj_set_flags(obj_get_window(c_to), TestModeFlagDirtyWindow);
1598     }
1599 }
1600
1601 static void
1602 set_value_action_handler(
1603     AB_ACTION_INFO      *action_info
1604 )
1605 {
1606     ABObj       c_to    = action_info->to;
1607     
1608     if (c_to == NULL)
1609         return;
1610
1611     if(obj_is_spin_box(c_to) || obj_is_scale(c_to))
1612     {
1613         ABObj   subObj  = NULL;
1614         int     val_int = 0;
1615         
1616         /* get the actual object */
1617         subObj = objxm_comp_get_subobj(c_to, AB_CFG_OBJECT_OBJ);
1618         if (subObj == NULL || objxm_get_widget(subObj) == NULL)
1619             return;
1620         
1621         /* get the value */
1622         val_int = action_info->arg_value.ival;
1623     
1624         /* set the value */
1625         if (obj_is_spin_box(c_to))
1626             XtVaSetValues(objxm_get_widget(subObj), DtNposition, val_int, NULL);
1627         else
1628             XtVaSetValues(objxm_get_widget(subObj), XmNvalue, val_int, NULL);
1629         
1630         /* mark this obj's window as dirty */
1631         tmodeP_obj_set_flags(obj_get_window(c_to), TestModeFlagDirtyWindow);
1632     }
1633 }
1634
1635 static void
1636 set_label_action_handler(
1637     AB_ACTION_INFO      *action_info
1638 )
1639 {
1640     ABObj       c_to     = action_info->to;
1641     ISTRING     lab_istr = NULL;
1642     STRING      lab_str  = NULL;
1643     
1644     if (c_to == NULL)
1645         return;
1646
1647     /* obtain the label */
1648     lab_istr = action_info->arg_value.sval;
1649     if (lab_istr != (ISTRING)NULL)
1650         lab_str = istr_string(lab_istr);
1651     else
1652         lab_str = Util_empty_string;
1653         
1654     /* set the label */
1655     ui_obj_set_label(c_to, lab_str);
1656
1657     /* mark this obj's window as dirty */
1658     tmodeP_obj_set_flags(obj_get_window(c_to), TestModeFlagDirtyWindow);
1659 }
1660
1661 static ABObj    *
1662 get_menu_item_refs(
1663     ABObj       menu_item
1664 )
1665 {
1666     ABObj               parent_menu;
1667     ABObj               this_module;
1668     ABObj               child;
1669     AB_TRAVERSAL        trav;
1670     int                 num_refs;
1671     int                 list_size;
1672     ABObj               *item_ref_list;
1673     AB_TRAVERSAL        item_trav;
1674     ABObj               item_child;
1675     int                 i;
1676     int                 item_index;
1677
1678     if (menu_item == NULL || !obj_is_menu_item(menu_item))
1679         return(NULL);
1680
1681     /* Get parent menu of item */
1682     parent_menu = obj_get_parent(menu_item);
1683
1684     if (parent_menu == NULL || obj_get_type(parent_menu) != AB_TYPE_MENU)
1685         return(NULL);
1686
1687     if ((this_module = obj_get_module(parent_menu)) == NULL)
1688         return(NULL);
1689
1690     item_index = -1;
1691     for (i = 0, trav_open(&trav, parent_menu, AB_TRAV_CHILDREN);
1692          (item_child = trav_next(&trav)) != NULL; i++)
1693     {
1694         if (obj_get_type(item_child) == AB_TYPE_ITEM &&
1695             util_streq(obj_get_name(item_child), obj_get_name(menu_item)))
1696         {
1697             item_index = i;
1698             break;
1699         }
1700     }
1701     trav_close(&trav);
1702
1703     if (item_index == -1)       /* should never happen */
1704         return(NULL);
1705
1706     num_refs = 0; list_size = 1;
1707     item_ref_list = (ABObj *) XtMalloc(sizeof(ABObj) * (list_size + 1));
1708
1709     /* Traverse module for all menu-references pointing to this menu */
1710     for (trav_open(&trav, this_module, AB_TRAV_ALL);
1711          (child = trav_next(&trav)) != NULL; )
1712     {
1713         if (obj_is_menu_ref(child) && obj_get_actual_obj(child) == parent_menu)
1714         {
1715             ABObj               item_ref;
1716
1717             /* Find our item by index in each tree rooted at a menu-reference */
1718
1719             item_child = obj_get_item(child, item_index);
1720             if (item_child != (ABObj)NULL)
1721             {
1722                 if (num_refs == list_size)
1723                 {
1724                     list_size += 2;
1725                     item_ref_list = (ABObj *) XtRealloc(
1726                                         (char *)item_ref_list,
1727                                         sizeof(ABObj) * (list_size + 1));
1728                 }
1729                 /* Add item to return list */
1730                 item_ref_list[num_refs++] = item_child;
1731             }
1732         }
1733     }
1734     trav_close(&trav);
1735
1736     if (num_refs > 0)
1737         item_ref_list[num_refs] = NULL; /* NULL-terminate the array */
1738     else
1739     {
1740         XtFree((char *)item_ref_list);
1741         item_ref_list = NULL;
1742     }
1743     return(item_ref_list);
1744 }
1745
1746 /*
1747  * initialization for test mode.
1748  */
1749 extern void
1750 conn_test_mode_initialize(
1751     ABObj       project
1752 )
1753 {
1754     AB_TRAVERSAL        trav;
1755     ABObj               obj;
1756
1757     ConnP_wins_deiconify  = util_llist_create();
1758     
1759     ConnP_modules_disable = util_aset_create();
1760     ConnP_win_close       = util_aset_create();
1761     ConnP_layer           = util_aset_create();
1762 }
1763
1764 /*
1765  * cleanup for test mode
1766  */
1767 extern void
1768 conn_test_mode_cleanup(
1769     ABObj       project
1770 )
1771 {
1772     util_aset_iterate(ConnP_modules_disable, disable_modules);
1773     util_aset_iterate(ConnP_win_close, remove_win_close);
1774     util_aset_iterate(ConnP_wins_deiconify, deiconify_wins);
1775     util_aset_iterate(ConnP_layer, reset_layer);
1776
1777     util_aset_destroy(ConnP_modules_disable);
1778     util_aset_destroy(ConnP_win_close);
1779     util_aset_destroy(ConnP_wins_deiconify);
1780     util_aset_destroy(ConnP_layer);
1781 }
1782
1783 static void
1784 make_win_iconic(
1785     ABObj       win,
1786     BOOL        to_iconify
1787 )
1788 {
1789     XEvent      event;
1790     Widget      top_level;
1791     Window      root;
1792
1793     if (!obj_is_window(win))
1794         goto cret;
1795
1796     top_level = objxm_get_widget(win);
1797     root = XRootWindowOfScreen(XtScreen(top_level));
1798
1799     event.xclient.type = ClientMessage;
1800     event.xclient.display = XtDisplay(top_level);
1801     event.xclient.window = XtWindow(top_level);
1802     event.xclient.message_type = XInternAtom (XtDisplay(top_level),
1803                                                 "WM_CHANGE_STATE", False);
1804     event.xclient.format = 32;
1805     event.xclient.data.l[0] = to_iconify?IconicState:NormalState;
1806
1807     XSendEvent(XtDisplay(top_level), root, False,
1808                 SubstructureRedirectMask|SubstructureNotifyMask,
1809                 &event);
1810
1811     XFlush(XtDisplay(top_level));
1812
1813 cret:
1814     return;
1815 }
1816
1817 /* Enable test-mode help support on an object and its children */
1818 static void
1819 tree_enable_help(ABObj obj)
1820 {
1821     ABObj               child;
1822     AB_TRAVERSAL        trav;
1823
1824     if (!obj_is_virtual(obj)) help_test_enable(obj);
1825
1826     for (trav_open(&trav, obj, AB_TRAV_SALIENT_CHILDREN);
1827          (child = trav_next(&trav)) != NULL; ) {
1828             /* Recursively descend through all children */
1829             tree_enable_help(child);
1830     }
1831     trav_close(&trav);
1832 }
1833
1834 /* Disable test-mode help support on an object and its children */
1835 static void
1836 tree_disable_help(ABObj obj)
1837 {
1838     ABObj               child;
1839     AB_TRAVERSAL        trav;
1840
1841     if (!obj_is_virtual(obj)) help_test_disable(obj);
1842
1843     for (trav_open(&trav, obj, AB_TRAV_SALIENT_CHILDREN);
1844          (child = trav_next(&trav)) != NULL; ) {
1845             /* Recursively descend through all children */
1846             tree_disable_help(child);
1847     }
1848     trav_close(&trav);
1849 }
1850
1851 /* 
1852 ** This function is called when the user manually closes a dialog or
1853 ** file selection box while in test mode.  It handles the necessary
1854 ** bookkeeping as if the window had been hidden via a connection.
1855 */
1856 static void     
1857 win_closeCB(
1858         Widget      w,
1859         XtPointer   client_data,
1860         XtPointer   call_data
1861 )
1862 {
1863     ABObj       obj = (ABObj)client_data;
1864     ABObj       project = proj_get_project();
1865
1866     /*
1867      * If we are in Test Project mode and the user has just Closed
1868      * the Root Window of the project, then we want to simulate an
1869      * application close (quit) and take down all windows.
1870      */
1871     if (AB_builder_mode == MODE_TEST_PROJ &&
1872         obj_get_root_window(project) == obj)
1873     {
1874         ABObj           win;
1875         AB_TRAVERSAL    trav;
1876
1877         for (trav_open(&trav, project, AB_TRAV_WINDOWS);
1878              (win = trav_next(&trav)) != NULL; )
1879         {
1880             if (obj_has_flag(win, MappedFlag))
1881                 objxm_tree_map(win, False);
1882         }
1883     }
1884     obj_clear_flag(obj,MappedFlag);
1885
1886     /*
1887     ** We're going to let the window manager 'hide' this object.
1888     */
1889 }
1890
1891 /* 
1892 ** Routine used to remove the window close callback on those dialogs 
1893 ** and file choosers that had one added (and which therefore appear on the
1894 ** ConnP_win_close list). 
1895 */
1896 static void
1897 remove_win_close(
1898     void        *cl_data
1899 )
1900 {
1901     ABObj               obj = (ABObj)cl_data;
1902
1903     ui_remove_window_close_callback(objxm_get_widget(obj),
1904                         win_closeCB,(XtPointer)obj);
1905 }
1906