Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtappbuilder / src / ab / abobj_events.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: abobj_events.c /main/3 1995/11/06 17:15:49 rswiston $
25  *
26  * @(#)abobj_events.c   1.50 15 Feb 1994      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 /*
44  ***********************************************************************
45  * abobj_events.c - implements UI object 'behavior' for created
46  *         UI objects
47  *         
48  *
49  ***********************************************************************
50  */
51 #include <stdio.h>
52 #include <X11/keysym.h>
53 #include <Xm/Xm.h>
54 #include <Xm/XmStrDefs.h>
55 #include <Xm/DrawingA.h>
56 #include <Xm/MainW.h>
57 #include <Xm/ScrolledW.h>
58 #include <Xm/Scale.h>
59 #include <Xm/Text.h>
60 #include <Xm/FileSB.h>
61 #include <Dt/ComboBox.h>
62 #include <Dt/MenuButton.h>
63 #include <Dt/SpinBox.h>
64 #include <ab_private/trav.h>
65 #include <ab_private/objxm.h>
66 #include <ab_private/ab.h>
67 #include <ab_private/pal.h>
68 #include "abobjP.h"
69 #include <ab_private/x_util.h>
70 #include <ab_private/ui_util.h>
71 #include <ab_private/conn.h>
72 #include <ab_private/brws.h>
73 #include <ab_private/prop.h>
74 #include "palette_ui.h"
75
76
77 #define AB_MAX_TRANSTBLS    70
78
79 /*
80  * Structure to store info related to implementing programmatic
81  * double-click on widgets where the translation does not work
82  * (DtMenuButton)
83  */
84 typedef struct DOUBLE_CLICK_INFO {
85     Widget              widget;
86     XEvent              *event;
87     unsigned int        interval;
88     int                 start_x;
89     int                 start_y;
90     BOOL                waiting;
91 } DoubleClickInfo;
92
93 /*************************************************************************
94 **                                                                      **
95 **       Private Function Declarations                                  **
96 **                                                                      **
97 **************************************************************************/
98 /*
99  * Widget Action Procs
100  */
101 static void     object_button_press(
102                     Widget w,
103                     XEvent *ev,
104                     String *params,
105                     int nparams
106                 );
107 static void     object_mouse_enter(
108                     Widget w,
109                     XEvent *ev,
110                     String *params,
111                     int nparams
112                 );
113 static void     object_mouse_leave( 
114                     Widget w, 
115                     XEvent *ev, 
116                     String *params, 
117                     int nparams 
118                 ); 
119 static void     object_mouse_motion( 
120                     Widget w,  
121                     XEvent *ev,  
122                     String *params,  
123                     int nparams  
124                 );  
125 static void     object_select(
126                     Widget w, 
127                     XEvent *ev, 
128                     String *params, 
129                     int nparams
130                 );
131 static void     object_toggle_select(
132                     Widget w, 
133                     XEvent *ev, 
134                     String *params, 
135                     int nparams
136                 );
137 static void     object_invoke_props(
138                     Widget w, 
139                     XEvent *ev, 
140                     String *params, 
141                     int nparams
142                 );
143 static void     object_popup_menu(
144                     Widget w, 
145                     XEvent *ev, 
146                     String *params, 
147                     int nparams
148                 );
149 static void     objects_pixel_move(
150                     Widget w,
151                     XEvent *ev,
152                     String *params,
153                     int nparams
154                 );
155
156 /*
157  * Widget Event Handlers
158  */
159 static void     interpose_button_event(
160                     Widget w,
161                     XtPointer cd,
162                     XEvent *ev,
163                     Boolean *cont
164                 );
165 static void     object_button_drag(
166                     Widget w,
167                     XtPointer cd,
168                     XEvent *ev,
169                     Boolean *cont
170                 );
171 static void     object_move_release(
172                     Widget w, 
173                     XtPointer cd, 
174                     XEvent *ev, 
175                     Boolean *cont
176                 );
177 static void     object_resize_release(
178                     Widget w, 
179                     XtPointer cd, 
180                     XEvent *ev, 
181                     Boolean *cont
182                 );
183 static void     object_mselect(
184                     Widget      widget,
185                     XEvent      *event,
186                     XRectangle  *rb_rect,
187                     XtPointer   client_data
188                 );
189 static void     object_track_move(
190                     Widget      widget,
191                     XtPointer   cd,
192                     XEvent      *ev,
193                     Boolean     *cont
194                 );
195 static void     object_track_iconify(
196                     Widget      widget,
197                     XtPointer   cd,
198                     XEvent      *ev,
199                     Boolean     *cont
200                 );
201 static void     prevent_closeCB(
202                     Widget      w,
203                     XtPointer   client_data,
204                     XtPointer   call_data
205                 );
206 static void     wait_for_double(
207                     XtPointer    client_data,
208                     XtIntervalId timer_id
209                 );
210
211 /*
212  * Private Internal Procs
213  */
214 static int      initiate_move(
215                     Widget      widget, 
216                     ABObj       obj 
217                 );
218
219 static int      initiate_resize(
220                     Widget      widget,
221                     ABObj       obj,
222                     RESIZE_DIR  dir
223                 );
224
225 static int      initiate_mselect(
226                     Widget      widget,
227                     ABObj       obj
228                 );
229
230 /*************************************************************************
231 **                                                                      **
232 **    Private Data                                                    **
233 **                                                                      **
234 **************************************************************************/
235
236 /*
237  * Build-Mode Actions
238  */
239 XtActionsRec build_actions[] = {
240     {"ObjectMouseEnter",    (XtActionProc)object_mouse_enter },
241     {"ObjectMouseLeave",    (XtActionProc)object_mouse_leave },
242     {"ObjectMouseMotion",   (XtActionProc)object_mouse_motion },
243     {"ObjectSelect",        (XtActionProc)object_select },
244     {"ObjectButtonPress",   (XtActionProc)object_button_press },
245     {"ObjectToggleSelect",  (XtActionProc)object_toggle_select },
246     {"ObjectInvokeProps",   (XtActionProc)object_invoke_props },
247     {"ObjectPopupMenu",     (XtActionProc)object_popup_menu },
248     {"ObjectDragChord",     (XtActionProc)conn_drag_chord },
249     {"ObjectsPixelMove",    (XtActionProc)objects_pixel_move }
250 };
251
252 /* 
253  * Build-Mode Translations
254  */
255 String base_translations =
256     "<Enter>:                   ObjectMouseEnter() \n\
257      <Leave>:                   ObjectMouseLeave() \n\
258      <Motion>:                  ObjectMouseMotion() \n\
259       Ctrl <Btn1Down>:          ObjectDragChord() \n\
260       Shift <Btn1Down>:         ObjectButtonPress() \n\
261       Shift <Btn1Down>,<Btn1Up>:ObjectToggleSelect() \n\
262      <Btn1Down>:                ObjectButtonPress() \n\
263      <Btn1Down>,<Btn1Up>:       ObjectSelect() \n\
264      <Btn1Up>(2):               ObjectInvokeProps() \n\
265      <Key>Left:                 ObjectsPixelMove() \n\
266      <Key>Right:                ObjectsPixelMove() \n\
267      <Key>Down:                 ObjectsPixelMove() \n\
268      <Key>Up:                   ObjectsPixelMove() \n"; /* will be appended-to */
269
270 String btn2_adjust_translations = 
271     "<Btn2Down>:                ObjectButtonPress() \n\
272      <Btn2Down>,<Btn2Up>:       ObjectToggleSelect() \n"; /* will be appended-to */
273
274 String btn3_menu_translations =
275      "<Btn3Down>:               ObjectPopupMenu()";
276
277 String btn2_menu_translations =
278      "<Btn2Down>:               ObjectPopupMenu()";
279
280 static XtTranslations build_transtbl = NULL;
281
282
283
284 extern const int AB_drag_threshold;
285
286 static RESIZE_DIR resize_dir      = NONE;
287 static Boolean just_moved         = False;
288 static Boolean just_mselected     = False;
289 static Boolean potential_move     = False;
290 static Boolean move_in_progress   = False;
291 static Boolean resize_in_progress = False;
292 static Boolean mselect_in_progress= False;
293 static Boolean mselect_adjust     = False;
294 static Boolean actions_init       = False;
295
296 /*************************************************************************
297 **                                                                      **
298 **       Function Definitions                                           **
299 **                                                                      **
300 **************************************************************************/
301
302 /*
303  * Traverse tree and set the mode of behavior ("build" or "test")
304  * for each object with a valid ui_handle (instantiated widget ID)
305  */
306 int
307 abobj_tree_set_build_actions(
308     ABObj       root
309 )
310 {
311     AB_TRAVERSAL        trav;
312     ABObj               obj;
313  
314     if (root == NULL)
315         return ERROR;
316
317     /* set the appropriate build actions */
318     for (trav_open(&trav, root, AB_TRAV_UI);
319         (obj = trav_next(&trav)) != NULL; )
320     {
321         if (objxm_get_widget(obj) != NULL)
322         {
323             if (AB_builder_mode == MODE_BUILD)
324                 abobjP_enable_build_actions(obj, objxm_get_widget(obj));
325             else /* TEST MODE */
326                 abobjP_disable_build_actions(obj, objxm_get_widget(obj));
327         }
328     }
329     trav_close(&trav);
330
331     return OK;
332 }
333
334 /*
335  * Register build actions with Xt
336  */
337 void
338 abobj_register_build_actions(
339     XtAppContext app
340 )
341 {
342
343     /* Register Build Actions */
344     XtAppAddActions(app, build_actions, XtNumber(build_actions));
345     actions_init = True;
346
347 }
348
349 static void
350 enable_on_internal_widgets(
351     Widget      widget,
352     ABObj       obj,
353     ABObj       root
354 )
355 {
356     WidgetList          children;
357     int                 num_children = 0;
358     int                 i;
359
360     XtVaGetValues(widget,
361                    XtNnumChildren,    &num_children,
362                    XtNchildren,       &children,
363                    NULL);
364
365     for (i = 0; i < num_children; ++i)
366     {
367         if (!XtIsWidget(children[i]) || 
368             XtIsSubclass(children[i], shellWidgetClass) ||
369             XtIsSubclass(children[i], xmTextWidgetClass) ||
370             XtIsSubclass(children[i], xmDrawingAreaWidgetClass))
371             continue;
372
373         objxm_store_obj_and_actions(children[i], obj);
374
375         XtVaSetValues(children[i],
376                 XtNtranslations,        build_transtbl,
377                 NULL);
378
379         XtAddEventHandler(children[i], Button1MotionMask | Button2MotionMask,
380                 False, object_button_drag, (XtPointer)root);
381
382         /* Recursion...*/
383         if (XtIsSubclass(children[i], compositeWidgetClass))
384             enable_on_internal_widgets(children[i], obj, root);
385     }
386 }
387
388 static void
389 disable_on_internal_widgets(
390     Widget      widget,
391     ABObj       obj,
392     ABObj       root
393 )
394 {
395     WidgetList          children;
396     int                 num_children = 0;
397     XtTranslations      orig_trans;
398     int                 i;
399
400     XtVaGetValues(widget,
401                    XtNnumChildren,    &num_children,
402                    XtNchildren,       &children,
403                    NULL);
404
405     for (i = 0; i < num_children; ++i)
406     {
407         if (!XtIsWidget(children[i]) || 
408             XtIsSubclass(children[i], shellWidgetClass) ||
409             XtIsSubclass(children[i], xmTextWidgetClass) ||
410             XtIsSubclass(children[i], xmDrawingAreaWidgetClass))
411             continue;
412
413         XtRemoveEventHandler(children[i],
414                         Button1MotionMask | Button2MotionMask,
415                         False,
416                         object_button_drag, (XtPointer)root);
417  
418         orig_trans = objxm_get_actions_from_widget(children[i]);
419  
420         if (orig_trans)
421             XtVaSetValues(children[i],
422                         XtNtranslations, orig_trans,
423                         NULL);
424         else
425             XtUninstallTranslations(children[i]);
426
427         /* Recursion...*/
428         if (XtIsSubclass(children[i], compositeWidgetClass)) 
429             disable_on_internal_widgets(children[i], obj, root);
430     }
431 }
432
433
434 /*
435  * Enable build-mode behavior for the widget
436  */
437 void
438 abobjP_enable_build_actions(
439     ABObj       obj, 
440     Widget      widget
441 )
442 {
443     ABObj        evObj;
444     ABObj        rootObj = obj_get_root(obj);
445
446     if (obj_has_flag(obj, BuildActionsFlag))
447         return; /* Already has actions */
448
449     if (objxm_is_menu_widget(widget) || obj_is_menu_item(obj))
450         return;
451
452     /* Window objects require specialized event tracking */
453     if (obj_is_window(obj) && XtIsSubclass(widget, shellWidgetClass))
454     {
455         /* Prevent the user from "Quitting" a window in build-mode*/
456         ui_add_window_close_callback(widget, prevent_closeCB, NULL, XmDO_NOTHING);
457
458         /* Track when a window is iconified */
459         if (obj_is_base_win(obj))
460             ui_add_window_iconify_handler(widget, object_track_iconify, (XtPointer)obj);
461
462         /* Track when the user moves the window so that if it is re-instantiated,
463          * it will appear in the position the user placed it in.
464          * NOTE: this does not set a permanent position attribute for a window!
465          */
466         XtAddEventHandler(widget, StructureNotifyMask, False,
467                 (XtEventHandler)object_track_move, (XtPointer)rootObj);
468         return;
469     }
470
471     if (build_transtbl == NULL)
472     {
473         int        len;
474         String     build_translations, menu_translations;
475
476         /* First time only.
477          * Build up translation table based on the number of mouse buttons
478          * and the value of the display resource, "enableBtn1Transfer".
479          */
480         menu_translations = (AB_BMenu == Button3? btn3_menu_translations : btn2_menu_translations);
481
482         len = strlen(base_translations) + strlen(menu_translations) + 1;
483
484         if (AB_BMenu == Button3 && AB_btn1_transfer == True) 
485             /* Button2 can be used for ADJUST */
486             len += strlen(btn2_adjust_translations);
487
488         build_translations = (String)util_malloc(len*sizeof(char));
489         if (build_translations == NULL)
490             return; /* ouch */
491
492         /* Build Translation table */
493         strcpy(build_translations, base_translations);
494         if (AB_BMenu == Button3 && AB_btn1_transfer == True)
495            strcat(build_translations, btn2_adjust_translations);
496         strcat(build_translations, menu_translations);
497
498         build_transtbl = XtParseTranslationTable(build_translations);
499
500         util_free(build_translations);
501     }
502
503     /* Enable build mode behavior */
504     XtVaSetValues(widget, 
505                 XtNtranslations, build_transtbl,
506                 NULL);
507
508     if (obj_is_item(obj))
509         evObj = obj_get_parent(obj);
510     else
511         evObj = obj;
512
513     /* The DtMenuButton widget uses an internal event-handler to post its menu,
514      * so our standard translations will not get called. Therefore,  we use
515      * an event-handler to get these buttons events before the widget does.
516      */  
517     if (XtIsSubclass(widget, dtMenuButtonWidgetClass))
518         XtInsertEventHandler(widget, 
519                 ButtonMotionMask | ButtonPressMask | ButtonReleaseMask,
520                 False, interpose_button_event, (XtPointer)rootObj, XtListHead);
521
522     /* Track drag events on all other widgets */
523     else if (!(obj_is_sub(obj) && obj_is_window(rootObj)) &&
524         !obj_is_menubar(rootObj))
525         XtAddEventHandler(widget, Button1MotionMask | Button2MotionMask, False,
526                 object_button_drag, (XtPointer)rootObj);
527
528     /* Track size changes caused internally & externally */
529     if (objxm_comp_get_subobj(rootObj, AB_CFG_SIZE_OBJ) == obj)
530         XtAddEventHandler(widget, StructureNotifyMask, False,
531                 (XtEventHandler)abobjP_track_external_resizes, (XtPointer)rootObj);
532
533     /* Ensure all this stuff gets registered on *internal* widgets as well */
534     if ((XtIsSubclass(widget, xmScrolledWindowWidgetClass) &&
535         !XtIsSubclass(widget, xmMainWindowWidgetClass)) ||
536         XtIsSubclass(widget, dtComboBoxWidgetClass) ||
537         XtIsSubclass(widget, xmScaleWidgetClass) ||
538         XtIsSubclass(widget, xmFileSelectionBoxWidgetClass) ||
539         XtIsSubclass(widget, dtSpinBoxWidgetClass))
540         enable_on_internal_widgets(widget, obj, rootObj);
541
542     obj_set_flag(obj, BuildActionsFlag);
543
544 }
545
546 /*
547  * Disable build-mode behavior for the widget
548  */
549 void
550 abobjP_disable_build_actions(
551     ABObj       obj,
552     Widget      widget
553 )
554 {
555     ABObj          evObj;
556     ABObj          rootObj = obj_get_root(obj);
557     XtTranslations orig_trans;
558
559     if (obj_is_window(obj) && XtIsSubclass(widget, shellWidgetClass))
560     {
561         ui_remove_window_close_callback(widget, prevent_closeCB, NULL);
562
563         if (obj_is_base_win(obj))
564             ui_remove_window_iconify_handler(widget, object_track_iconify, (XtPointer)obj); 
565
566         XtRemoveEventHandler(widget, StructureNotifyMask, False, 
567                 (XtEventHandler)object_track_move, (XtPointer)rootObj);
568     }
569
570     /* Don't bother for Shells or menu-related widgets */
571     if (XtIsSubclass(widget, shellWidgetClass) ||
572         objxm_is_menu_widget(widget) || obj_is_menu_item(obj))
573         return;
574
575     if (!obj_has_flag(obj, BuildActionsFlag))
576         return;  /* No actions to disable */
577
578     if (obj_is_item(obj))
579         evObj = obj_get_parent(obj);
580     else
581         evObj = obj;
582
583     abobj_deselect(obj);
584  
585     if (XtIsSubclass(widget, dtMenuButtonWidgetClass))
586         XtRemoveEventHandler(widget, 
587                 ButtonMotionMask | ButtonPressMask | ButtonReleaseMask,
588                 False, interpose_button_event, (XtPointer)rootObj);
589
590     else if (!(obj_is_sub(obj) && obj_is_window(rootObj)) &&
591         !(obj_is_menubar(rootObj))) 
592         XtRemoveEventHandler(widget, Button1MotionMask | Button2MotionMask, False,
593                 object_button_drag, (XtPointer)rootObj);
594
595     if (objxm_comp_get_subobj(rootObj, AB_CFG_SIZE_OBJ) == obj)
596         XtRemoveEventHandler(widget, StructureNotifyMask, False,
597                 (XtEventHandler)abobjP_track_external_resizes, (XtPointer)rootObj);
598
599     orig_trans = objxm_get_actions_from_widget(widget);
600
601     /*
602      * if no original translations, uninstall instead of setting
603      * XtNtranslations to NULL because this may not have any
604      * effect
605      */
606     if (orig_trans)
607         XtVaSetValues(widget, XtNtranslations, orig_trans, NULL);
608     else
609         XtUninstallTranslations(widget);
610
611     if ((XtIsSubclass(widget, xmScrolledWindowWidgetClass) &&
612         !XtIsSubclass(widget, xmMainWindowWidgetClass)) ||
613         XtIsSubclass(widget, dtComboBoxWidgetClass) ||
614         XtIsSubclass(widget, xmScaleWidgetClass) ||
615         XtIsSubclass(widget, xmFileSelectionBoxWidgetClass) ||
616         XtIsSubclass(widget, dtSpinBoxWidgetClass))
617         disable_on_internal_widgets(widget, obj, rootObj);
618
619     obj_clear_flag(obj, BuildActionsFlag);
620 }
621
622 /*
623  * Action: pointer has 'entered' widget
624  */
625 static void
626 object_mouse_enter(
627     Widget      widget,
628     XEvent      *event,
629     String      *params,
630     int         num_params
631 )
632 {
633     ABObj obj = NULL;
634     ABObj rootObj;
635     char  pos_str[12];
636     char  sz_str[16];
637
638     obj = objxm_get_obj_from_widget(widget);
639
640     if (obj != NULL)
641     {
642         rootObj = obj_is_item(obj)? obj_get_parent(obj) : obj;
643
644         rootObj = obj_get_root(rootObj);
645
646         sprintf(pos_str, "%3d,%3d", rootObj->x, rootObj->y);
647         sprintf(sz_str,  "%3d X %3d", 
648                 abobj_get_actual_width(rootObj), abobj_get_actual_height(rootObj));
649         ab_update_stat_region(AB_STATUS_OBJ_TYPE, pal_get_item_subname(rootObj,obj_get_subtype(rootObj)));
650         ab_update_stat_region(AB_STATUS_OBJ_NAME, obj_get_name(rootObj));
651         ab_update_stat_region(AB_STATUS_OBJ_POS,  pos_str);
652         ab_update_stat_region(AB_STATUS_OBJ_SIZE,  sz_str);
653     }
654 }
655
656 /*
657  * Action: pointer has 'left' widget
658  */
659 static void 
660 object_mouse_leave(
661     Widget      widget, 
662     XEvent      *event, 
663     String      *params,
664     int         num_params 
665 )
666
667
668     ab_update_stat_region(AB_STATUS_OBJ_TYPE, "      ");
669     ab_update_stat_region(AB_STATUS_OBJ_NAME, "      "); 
670     ab_update_stat_region(AB_STATUS_CURS_POS, "      ");
671     ab_update_stat_region(AB_STATUS_OBJ_POS,  "      ");
672     ab_update_stat_region(AB_STATUS_OBJ_SIZE, "      ");
673
674
675
676 /* 
677  * Action: pointer has 'left' widget 
678  */ 
679 static void  
680 object_mouse_motion(
681     Widget      widget, 
682     XEvent      *event,  
683     String      *params, 
684     int         num_params  
685
686 {  
687     ABObj        obj = NULL, rootObj;
688     XMotionEvent *mevent = (XMotionEvent*)event;
689     char         motionstr[16];
690     int          rx, ry;
691
692     obj = objxm_get_obj_from_widget(widget);
693
694     if (obj != NULL)
695     {
696         /* Make sure the x,y position is relative to the ROOT obj
697          * of a given obj or CompositeObj
698          */
699         rootObj = obj_is_item(obj)? obj_get_parent(obj) : obj;
700         rootObj = obj_get_root(rootObj);
701         if (rootObj != obj)
702             x_widget_translate_xy(objxm_get_widget(obj), (XtPointer)objxm_get_widget(rootObj), 
703                 mevent->x, mevent->y, &rx, &ry); 
704         else
705         {
706             rx = mevent->x;
707             ry = mevent->y;
708         }
709   
710         sprintf(motionstr, "%3d,%3d", rx, ry);
711         ab_update_stat_region(AB_STATUS_CURS_POS, motionstr);  
712     }
713 }  
714     
715 /*
716  * Action: caused the object to become "selected"
717  */
718 static void
719 object_select(
720     Widget      widget, 
721     XEvent      *event, 
722     String      *params, 
723     int         num_params
724 )
725 {
726     ABObj obj = NULL;
727
728     obj = objxm_get_obj_from_widget(widget);
729
730     /* This action is called directly after a Move (on the Mouse
731      * button Release), therefore, IF a Move just occurred, DO NOT
732      * deselect all other selected objects...
733      */
734     if (!just_moved)
735         abobj_deselect_all(obj_get_project(obj));
736     else
737         just_moved = False;
738
739     abobj_select(obj);
740
741 }
742
743 /*
744  * Action: toggles the select-state of the object
745  */
746 static void
747 object_toggle_select(
748     Widget      widget, 
749     XEvent      *event, 
750     String      *params, 
751     int         num_params
752 )
753 {
754     ABObj         obj, rootObj;
755     ABSelectedRec sel;
756     BOOL          allow = True;
757     int           i;
758
759     if (just_moved) /* BUTTON2 TRANSFER - don't toggle select! */
760     {
761         just_moved = False;
762         return;
763     }
764
765     obj = objxm_get_obj_from_widget(widget);
766     rootObj = obj_get_root(obj);
767     if (obj_is_item(rootObj))
768         rootObj = obj_get_root(obj_get_parent(rootObj));
769
770     if (obj_is_selected(rootObj))
771         abobj_deselect(rootObj); 
772     else
773     {
774         /* Only objects on the same level (siblings) may be
775          * selected at one time.  If a non-sibling object is
776          * already selected, do not allow the new object to
777          * become selected...
778          */
779         abobj_get_selected(obj_get_window(rootObj), True, False, &sel);
780
781         for(i = 0; i < sel.count; i++)
782         {
783             if (!obj_is_sibling(rootObj, sel.list[i]))
784                 allow = False;
785         }
786         if (allow)
787             abobj_select(rootObj);
788
789         util_free(sel.list);
790     }
791
792 }
793
794 /*
795  * Action: invokes the property sheet for the object
796  */
797 static void
798 object_invoke_props(
799     Widget      widget, 
800     XEvent      *event, 
801     String      *params, 
802     int         num_params
803 )
804 {
805     ABObj         obj = NULL;
806
807     obj = objxm_get_obj_from_widget(widget);
808
809     prop_load_obj(obj, AB_PROP_REVOLVING);
810  
811 }
812
813 /*
814  * Action: popup the build menu for the object
815  */
816 static void
817 object_popup_menu(
818     Widget      widget, 
819     XEvent      *event, 
820     String      *params, 
821     int         num_params
822 )
823 {
824     ABObj         obj = NULL;
825     ABSelectedRec sel;
826
827     obj = objxm_get_obj_from_widget(widget); 
828
829     abobj_get_selected(obj_get_window(obj), True, False, &sel);
830
831     if (event->type == ButtonPress)
832         abobj_popup_menu(WIN_EDIT_MENU, widget, &sel, (XButtonEvent *)event);
833
834     util_free(sel.list);
835
836 }
837
838 /*
839  * Action: move selected objects by 1 pixel
840  */
841 static void
842 objects_pixel_move(
843     Widget      widget,
844     XEvent      *event,
845     String      *params,
846     int         num_params
847 )
848 {
849     XKeyEvent     *kevent;
850     ABObj         obj = NULL;
851     ABSelectedRec sel;
852     KeySym        keysym;
853     Modifiers     mod;
854
855     if (event->type == KeyPress)
856     {
857         kevent = (XKeyEvent*)event;
858
859         obj = objxm_get_obj_from_widget(widget);
860  
861         abobj_get_selected(obj_get_window(obj), False, False, &sel);
862
863         if (sel.count == 0)
864             return;
865
866         XtTranslateKeycode(kevent->display, kevent->keycode, kevent->state,
867                 &mod, &keysym);
868
869         switch(keysym)
870         {
871             case XK_Up:
872                 abobj_nudge_selected(sel.list, sel.count, 0, -1, True);
873                 break;
874             case XK_Down:
875                 abobj_nudge_selected(sel.list, sel.count, 0, 1, True); 
876                 break; 
877             case XK_Right:
878                 abobj_nudge_selected(sel.list, sel.count, 1, 0, True);  
879                 break;  
880             case XK_Left:
881                 abobj_nudge_selected(sel.list, sel.count, -1, 0, True);   
882                 break;   
883             default:
884                 break;
885         }
886
887         util_free(sel.list);
888     }
889 }
890
891 /*
892  * grab the pointer to track the movement of the object
893  */
894 static int 
895 initiate_move(
896     Widget      widget, 
897     ABObj       obj 
898 )
899 {
900     ABObj               rootObj;
901     ABObj               geomObj;
902     Widget              geomWidget;
903     Widget              parent;
904     static Cursor       move_cursor = NULL;
905
906     rootObj = obj_get_root(obj);
907
908     geomObj    = objxm_comp_get_subobj(rootObj, AB_CFG_POSITION_OBJ);
909     geomWidget = objxm_get_widget(geomObj);
910
911     if (geomWidget == NULL)
912     {
913         util_dprintf(0,"initiate_move: no geometry widget\n");
914         return ERROR;
915     }
916     parent = XtParent(geomWidget);
917
918     if (!move_cursor)
919         move_cursor = abobjP_get_resize_cursor(widget, MOVE);
920
921     XtAddEventHandler(widget, ButtonReleaseMask,  False,
922                 object_move_release, (XtPointer)rootObj);
923
924     if (XtGrabPointer(widget, False, 
925                 ButtonReleaseMask | ButtonMotionMask | PointerMotionMask, 
926                 GrabModeAsync, GrabModeAsync,  XtWindow(parent), 
927                         move_cursor, CurrentTime) == GrabSuccess)
928         return OK;
929
930     return ERROR;
931
932 }
933
934 /*
935  * Grab the pointer to interpret the resize action
936  */
937 static int 
938 initiate_resize(
939     Widget      widget,
940     ABObj       obj,
941     RESIZE_DIR  dir
942 )
943 {
944     ABObj     rootObj;
945     ABObj     geomObj;
946     Widget    geomWidget;
947     Cursor    resize_cursor;
948
949     rootObj = obj_get_root(obj);
950     geomObj    = objxm_comp_get_subobj(rootObj, AB_CFG_SIZE_OBJ);
951     geomWidget = objxm_get_widget(geomObj);
952
953     if (geomWidget == NULL)
954     {
955         util_dprintf(0,"initiate_resize: no geometry widget\n");
956         return ERROR;
957     }
958
959     resize_cursor = abobjP_get_resize_cursor(widget, dir);
960
961     XtAddEventHandler(widget, ButtonReleaseMask,  False,
962                 object_resize_release, (XtPointer)obj);
963  
964     if (XtGrabPointer(widget, False,
965         ButtonReleaseMask | ButtonMotionMask | PointerMotionMask,
966         GrabModeAsync, GrabModeAsync,  NULL,
967             resize_cursor, CurrentTime) == GrabSuccess)
968  
969         return OK;
970  
971     return ERROR;
972  
973 }
974
975 /*
976  * Action: mouse button down...
977  */
978 static void
979 object_button_press(
980     Widget      widget,
981     XEvent      *event,
982     String      *params,
983     int         num_params
984 )
985 {
986     XButtonEvent        *bevent;
987     ABObj               obj = NULL;
988     ABObj               rootObj;
989
990     potential_move = False;
991     just_moved = False;
992
993     obj = objxm_get_obj_from_widget(widget); 
994     rootObj = obj_get_root(obj);
995
996     if (obj_is_window(rootObj))
997         return;
998  
999     if (event->type == ButtonPress) 
1000     {
1001         bevent = (XButtonEvent*)event;
1002
1003         if (bevent->state == 0 &&
1004             (bevent->button == 1 ||
1005             (AB_btn1_transfer != True && bevent->button == 2)))
1006                                 /* MOVE, RESIZE or RUBBERBAND-SELECT */
1007         {
1008             resize_dir = abobjP_find_resize_direction(obj, widget, event);
1009
1010             if (resize_dir == MOVE) /* MOVE (pending subsequent drag event) */
1011                 potential_move = True;
1012
1013             else if (bevent->button == 1 && resize_dir == NONE && obj_is_pane(rootObj))
1014             {
1015                 if (obj_is_control_panel(rootObj))
1016                 {
1017                     /* RUBBERBAND-SELECT */
1018                     if (ui_initiate_rubberband(widget, False,
1019                         object_mselect, (XtPointer)obj) == ERROR)
1020                     {
1021                         mselect_in_progress = False;
1022                         util_dprintf(0,"object_button_press: couldn't begin rubberband\n");
1023                     }
1024                     else
1025                     {
1026                         mselect_in_progress = True;
1027                         mselect_adjust = False;
1028                     }
1029                 }
1030             }
1031             else if (bevent->button == 1) /* RESIZE */
1032             {
1033                 if (obj_is_selected(rootObj))
1034                 {
1035                     if (initiate_resize(widget, obj, resize_dir) == ERROR)
1036                     {
1037                         resize_in_progress = False;
1038                         util_dprintf(0, "object_button_press: couldn't begin resize\n");
1039                     }
1040                     else
1041                         resize_in_progress = True;
1042                 }
1043             }
1044         }
1045         else if (bevent->button == 2 || 
1046                  (bevent->button == 1 && (bevent->state & ShiftMask))) /* RUBBERBAND-ADJUST */
1047         {
1048             if (obj_is_control_panel(rootObj))
1049             {
1050                 if (ui_initiate_rubberband(widget, False,
1051                         object_mselect, (XtPointer)obj) == ERROR)
1052                 {
1053                     mselect_in_progress = False;
1054                     util_dprintf(0,"object_button_press: couldn't begin rubberband\n");
1055                 }
1056                 else
1057                     mselect_in_progress = mselect_adjust = True;
1058             }
1059         }
1060     }
1061 }
1062
1063 /*
1064  * Xt Timer proc : used to detect a double-click event for widgets
1065  *                 where the translation doesn't work (DtMenuButton).
1066  */
1067 static void 
1068 wait_for_double(
1069     XtPointer    client_data,
1070     XtIntervalId timer_id
1071 )
1072 {
1073     DoubleClickInfo *d_click = (DoubleClickInfo*)client_data;
1074
1075     /* Waiting interval for double-click expired.
1076      * Go ahead and process the single-click...
1077      */
1078     d_click->waiting = False;
1079     object_button_press(d_click->widget, d_click->event, NULL, 0);
1080
1081 }
1082
1083 /*
1084  * Event Handler: For widgets which use internal event-handlers for
1085  *                button events, we must use an event-handler (instead
1086  *                of translations) to grab these events.  We simply
1087  *                call the appropriate action procedure ourselves.
1088  */
1089 static void
1090 interpose_button_event(
1091     Widget      widget,
1092     XtPointer   client_data,
1093     XEvent      *event,
1094     Boolean     *cont_dispatch
1095 )
1096 {
1097     XButtonEvent                *bevent;
1098     XMotionEvent                *mevent;
1099     static XEvent               event_cpy;
1100     static DoubleClickInfo      *d_click = NULL;
1101     static XtIntervalId         timer_id = NULL;
1102     ABObj                       obj = (ABObj)client_data;
1103     ABObj                       moveObj;
1104     
1105     if (event->type == ButtonPress || event->type == ButtonRelease)
1106     {
1107         bevent = (XButtonEvent*)event;
1108
1109         /* absorb all button events */
1110         *cont_dispatch = False;
1111
1112         switch(bevent->button)
1113         {
1114             case 1:
1115                 if (event->type == ButtonPress)
1116                 {
1117                     if (bevent->state & ControlMask) /* Connections Accelerator */
1118                     {
1119                         conn_drag_chord(widget, event, NULL, 0);
1120                         return;
1121                     }
1122
1123                     if (d_click == NULL) /* Init DoubleClick structure */
1124                     {
1125                         d_click = (DoubleClickInfo*)util_malloc(sizeof(DoubleClickInfo));
1126                         if (d_click == NULL)
1127                             return; /* yikes! */
1128                         d_click->widget = NULL;
1129                         d_click->event = NULL;
1130                         d_click->interval = XtGetMultiClickTime(XtDisplay(widget));
1131                         d_click->waiting = False;
1132                     }   
1133
1134                     if (d_click->waiting) /* double-click occurred */
1135                     {
1136                         XtRemoveTimeOut(timer_id);
1137                         d_click->waiting = False;
1138                         object_invoke_props(widget, event, NULL, 0);
1139                     }
1140                     else if (bevent->state == 0) /* Start timing for double-click */
1141                     {
1142                         event_cpy = *event;
1143                         d_click->waiting = True;
1144                         d_click->widget = widget;
1145                         d_click->event = &event_cpy;
1146                         d_click->start_x = bevent->x;
1147                         d_click->start_y = bevent->y;
1148                         timer_id = XtAppAddTimeOut(
1149                                 XtWidgetToApplicationContext(widget), 
1150                                 d_click->interval,
1151                                 (XtTimerCallbackProc)wait_for_double, 
1152                                 (XtPointer)d_click);
1153                     }
1154
1155                 }
1156                 /* ButtonRelease */
1157
1158                 else if (resize_in_progress)
1159                     object_resize_release(widget, client_data, event, cont_dispatch);
1160
1161                 else if (move_in_progress) /* ButtonRelease */
1162                     object_move_release(widget, client_data, event, cont_dispatch);
1163
1164                 else if (bevent->state & ShiftMask)
1165                     object_toggle_select(widget, event, NULL, 0);
1166
1167                 else
1168                     object_select(widget, event, NULL, 0);
1169                 break;
1170
1171             case 2:
1172                 if (event->type == ButtonPress && AB_btn1_transfer != True) /* BUTTON2 TRANSFER */
1173                     object_button_press(widget, event, NULL, 0);
1174
1175                 else if (event->type == ButtonRelease)
1176                 {
1177                     if (AB_btn1_transfer != True && move_in_progress) /* BUTTON2 TRANSFER */
1178                         object_move_release(widget, client_data, event, cont_dispatch);
1179                     else
1180                         object_toggle_select(widget, event, NULL, 0);
1181                 }
1182                 break;
1183
1184             case 3:
1185                 if (event->type == ButtonPress)
1186                     object_popup_menu(widget, event, NULL, 0);
1187                 break;
1188         }
1189     }
1190     else if (event->type == MotionNotify)
1191     {
1192         mevent = (XMotionEvent*)event;
1193         if (mevent->state & Button1Mask)
1194         {
1195             /* Check to see if the drag occurred while we are waiting for hte
1196              * double-click interval to expire. If so, then if the drag is
1197              * outside the threshhold, cancel the double-click and initiate
1198              * a move or resize.
1199              */
1200             if (d_click->waiting)
1201             {
1202                 if (abs(mevent->x - d_click->start_x) > AB_drag_threshold ||
1203                     abs(mevent->y - d_click->start_y) > AB_drag_threshold)
1204                 {
1205                      XtRemoveTimeOut(timer_id);
1206                      d_click->waiting = False;
1207                      object_button_press(d_click->widget, d_click->event, NULL, 0);
1208                 }
1209             }
1210             else /* call the generic drag event-handler to process the drag */
1211                 object_button_drag(widget, client_data, event, cont_dispatch);
1212         }
1213         else if (mevent->state & Button2Mask && AB_btn1_transfer != True)
1214             object_button_drag(widget, client_data, event, cont_dispatch);
1215
1216         /* absorb all motion events */
1217         *cont_dispatch = False;
1218     }
1219 }
1220
1221 /*
1222  * EventHandler: drag action ...
1223  */
1224 static void
1225 object_button_drag(
1226     Widget      widget,
1227     XtPointer   client_data,
1228     XEvent      *event,
1229     Boolean     *cont_dispatch
1230 )
1231 {
1232     XMotionEvent        *mevent;
1233     ABObj               obj = (ABObj)client_data;
1234     ABObj               moveObj;
1235  
1236     if (event->type == MotionNotify)
1237     {
1238         mevent = (XMotionEvent*)event;
1239
1240         if (obj_is_item(obj))
1241             obj = obj_get_root(obj_get_parent(obj));
1242
1243         if (mevent->state & Button1Mask ||
1244             (AB_btn1_transfer != True && mevent->state & Button2Mask)) 
1245                                                 /* RESIZE, MOVE or RUBBERBAND-SELECT */
1246         {
1247             if (resize_in_progress)
1248             {
1249                 abobjP_resize_object_outline(obj, event, resize_dir);
1250             }
1251             else if (potential_move)
1252             {
1253                 /* If moving a Control within a Group, move the whole
1254                  * Group instead.
1255                  */
1256                 moveObj = obj_get_root(obj);
1257                 while(obj_is_group(obj_get_root(obj_get_parent(moveObj))))
1258                     moveObj = obj_get_root(obj_get_parent(moveObj));
1259  
1260                 if (moveObj != obj_get_root(obj)) /* moveObj is translated to Group */
1261                 {
1262                     Widget orig_w;
1263                     int    trans_x, trans_y;
1264                     Window win;
1265
1266                     /* Translate obj/widget to be the Group */
1267                     obj = objxm_comp_get_subobj(moveObj, AB_CFG_PARENT_OBJ);
1268                     orig_w = widget;
1269                     widget = objxm_get_widget(obj);
1270
1271                     /* Translate Control's x,y position relative to Group 0,0 */
1272                     XTranslateCoordinates(XtDisplay(orig_w), 
1273                         XtWindow(orig_w), XtWindow(widget),
1274                         mevent->x, mevent->y, &trans_x, &trans_y, &win);
1275
1276                     mevent->x = trans_x;
1277                     mevent->y = trans_y;
1278                 }
1279                 if (!move_in_progress) /* Initialize Move operation */
1280                 {
1281                     if (!obj_is_selected(moveObj))
1282                         object_select(widget, NULL, NULL, 0);
1283  
1284                     if (initiate_move(widget, obj) == ERROR)
1285                     {
1286                         move_in_progress = False;
1287                         potential_move   = False;
1288                         util_dprintf(0, "object_select_drag: couldn't begin move\n");
1289                     }
1290                     else
1291                         move_in_progress = True;
1292                 }
1293                 abobjP_move_object_outline(obj, mevent);
1294                 just_moved = True;
1295             }
1296             else if (mselect_in_progress) /* RUBBERBAND-SELECT */
1297                 ui_button_drag(widget, event, (XtPointer)obj);
1298         }
1299         else if (mevent->state & Button2Mask) /* RUBBERBAND-ADJUST */
1300             ui_button_drag(widget, event, (XtPointer)obj);
1301     }
1302 }
1303
1304
1305 /*
1306  * EventHandler: object move action is completed...
1307  *         move the object!
1308  */
1309 static void
1310 object_move_release(
1311     Widget       widget, 
1312     XtPointer    client_data, 
1313     XEvent       *event, 
1314     Boolean      *cont_dispatch
1315 )
1316 {
1317     ABObj obj         = (ABObj)client_data;
1318
1319     if (event->type != ButtonRelease)
1320         return;
1321
1322     if (move_in_progress)
1323     {
1324         XtUngrabPointer(widget, CurrentTime);
1325         XtRemoveEventHandler(widget, ButtonReleaseMask, False, 
1326             object_move_release, (XtPointer)obj);
1327         move_in_progress = False;
1328         if (just_moved)
1329         {
1330             abobj_move(obj, event);
1331         }
1332     }
1333  
1334 }
1335
1336 /*
1337  * EventHandler: object resize action is completed...
1338  *          resize the object!
1339  */
1340 static void
1341 object_resize_release(
1342     Widget      widget,
1343     XtPointer   client_data,
1344     XEvent      *event,
1345     Boolean     *cont_dispatch
1346 )
1347 {
1348     ABObj obj = (ABObj)client_data;
1349
1350     if (!resize_in_progress || event->type != ButtonRelease)
1351         return; 
1352
1353     XtUngrabPointer(widget, CurrentTime);
1354     XtRemoveEventHandler(widget, ButtonReleaseMask, False,
1355             object_resize_release, (XtPointer)obj);
1356     resize_in_progress = False;
1357     abobj_resize(obj, event);
1358     *cont_dispatch = False;
1359  
1360 }
1361
1362 static void
1363 object_mselect(
1364     Widget      widget,
1365     XEvent      *event,
1366     XRectangle  *rb_rect,
1367     XtPointer   client_data
1368 )
1369 {
1370     ABObj       control,
1371                 pobj,
1372                 xyobj,
1373                 obj = NULL;
1374     ABSelectedRec old_sel, new_sel;
1375     int         num_controls; 
1376     XRectangle  c_rect;
1377     XRectangle  tmp_rect;
1378     int         i, j;
1379
1380     if (!mselect_in_progress)
1381         return;
1382
1383     obj = (ABObj)client_data;
1384
1385     pobj = objxm_comp_get_subobj(obj, AB_CFG_PARENT_OBJ);
1386     num_controls = obj_get_num_children(pobj);
1387     new_sel.list = (ABObj*)util_malloc(num_controls*sizeof(ABObj));
1388     new_sel.count = 0;
1389
1390     abobj_get_selected(obj_get_window(pobj), True, False, &old_sel);
1391
1392     /* If rubberband was drawn from lower-right to upper-left,
1393      * translate rect so that x,y is upper-left point in rectangle.
1394      */
1395     if (rect_right(rb_rect) < rb_rect->x ||
1396         rect_bottom(rb_rect) < rb_rect->y)
1397     {
1398         tmp_rect.x = rect_right(rb_rect);
1399         tmp_rect.y = rect_bottom(rb_rect);
1400         tmp_rect.width = rb_rect->x - tmp_rect.x;
1401         tmp_rect.height = rb_rect->y - tmp_rect.y;
1402         rb_rect = &tmp_rect;
1403     }
1404
1405     for (i = 0; i < num_controls; i++)
1406     {
1407         control = obj_get_child(pobj, i);
1408
1409         if (obj_is_salient(control))
1410         {
1411             xyobj = objxm_comp_get_subobj(control, AB_CFG_POSITION_OBJ);
1412
1413             if (objxm_get_widget(xyobj) != NULL)
1414             {
1415                 x_get_widget_rect(objxm_get_widget(xyobj), &c_rect);
1416
1417                 if (rect_includesrect(rb_rect, &c_rect))
1418                 {
1419                     /* 
1420                      * If RUBBERBAND-SELECT, deselect other currently selected 
1421                      * objects.
1422                      * If RUBBERBAND-ADJUST, deselect only currently selected
1423                      * NON-sibling objects
1424                      */
1425                     if (old_sel.count > 0)
1426                     {
1427                         for(j = 0; j < old_sel.count; j++) 
1428                         { 
1429                             if (control != old_sel.list[j] &&
1430                                 (!mselect_adjust ||
1431                                 !obj_is_sibling(control, old_sel.list[j])))
1432                                 abobj_deselect(old_sel.list[j]);
1433                         } 
1434                         old_sel.count = 0;
1435                     }
1436                     new_sel.list[new_sel.count] = control;
1437                     new_sel.count++;
1438                 }
1439             }
1440         }
1441     }
1442     for (i=0; i < new_sel.count; i++)
1443         abobj_select(new_sel.list[i]);
1444
1445     util_free(old_sel.list);
1446     util_free(new_sel.list);
1447
1448     mselect_in_progress = mselect_adjust = False;
1449 }
1450
1451
1452 static void
1453 prevent_closeCB(
1454     Widget      widget,
1455     XtPointer   client_data,
1456     XtPointer   call_data
1457 )
1458 {
1459    dtb_palette_prevent_close_msg_initialize(
1460                 &dtb_palette_prevent_close_msg); 
1461     dtb_show_message(widget, &dtb_palette_prevent_close_msg, NULL, NULL);
1462 }
1463
1464 static void
1465 object_track_move(
1466     Widget      widget,
1467     XtPointer   client_data,
1468     XEvent      *event,
1469     Boolean     *cont_disp
1470 )
1471 {
1472     ABObj               winobj = (ABObj)client_data;
1473     XConfigureEvent     *cevent;
1474
1475     if (event->type == ConfigureNotify)
1476     {
1477         cevent = (XConfigureEvent*)event;
1478         winobj->x = cevent->x;
1479         winobj->y = cevent->y;
1480     }
1481 }
1482
1483 static void
1484 object_track_iconify(
1485     Widget      widget,
1486     XtPointer   client_data,
1487     XEvent      *event,
1488     Boolean     *cont_disp
1489 )
1490 {
1491     ABObj       winobj = (ABObj)client_data;
1492
1493     switch (event->type)
1494     {
1495         case MapNotify: 
1496             /* 
1497              * If this event is a result of the remap that occurs when
1498              * window decorations are changed going to/from Test mode, then
1499              * do not interpret it as a de-iconification.
1500              */
1501             if (obj_has_flag(winobj, DecorChangedFlag))
1502                 obj_clear_flag(winobj, DecorChangedFlag);
1503
1504             /* 
1505              * If this event is a result of the remap that occurs when
1506              * windows are maped exiting from Test mode, then do not
1507              * interpret it as a de-iconification.
1508              */
1509             else if (obj_has_flag(winobj, TestModeWinFlag))
1510                 obj_clear_flag(winobj, TestModeWinFlag);
1511             
1512             else if (InBuildMode && 
1513                 obj_has_flag(winobj, IconifiedFlag) &&
1514                 !ab_window_leader_iconified())
1515             {
1516                 obj_clear_flag(winobj, IconifiedFlag);
1517                 XtVaSetValues(widget, XtNinitialState, NormalState, NULL);
1518             }
1519             break;
1520  
1521         case UnmapNotify:
1522             /* 
1523              * If this event is a result of the unmap that occurs when
1524              * window decorations are changed going to/from Test mode, then 
1525              * do not interpret it as an iconification. 
1526              */ 
1527             if (obj_has_flag(winobj, DecorChangedFlag))
1528                 obj_clear_flag(winobj, DecorChangedFlag);
1529
1530             /* 
1531              * If this event is a result of the unmap that occurs when
1532              * windows are unmaped exiting from Test mode, then do not
1533              * interpret it as an iconification.
1534              */
1535             else if (obj_has_flag(winobj, TestModeWinFlag))
1536                 obj_clear_flag(winobj, TestModeWinFlag);
1537             
1538             else if (InBuildMode && 
1539                 !obj_has_flag(winobj, IconifiedFlag) &&
1540                  obj_has_flag(winobj, MappedFlag) &&
1541                 !ab_window_leader_iconified())
1542             {
1543                 obj_set_flag(winobj, IconifiedFlag);
1544                 XtVaSetValues(widget, XtNinitialState, IconicState, NULL);
1545             }
1546             break;
1547     }
1548 }