Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtappbuilder / src / ab / attch_ed_stubs.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 /*** DTB_USER_CODE_START vvv Add file header below vvv ***/
24 /*
25  *      $XConsortium: attch_ed_stubs.c /main/7 1996/10/24 18:00:09 mustafa $
26  *
27  * @(#)attch_ed_stubs.c 1.32 27 Apr 1995 cde_app_builder/src/ab
28  *
29  *      RESTRICTED CONFIDENTIAL INFORMATION:
30  *
31  *      The information in this document is subject to special
32  *      restrictions in a confidential disclosure agreement between
33  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
35  *      Sun's specific written approval.  This document and all copies
36  *      and derivative works thereof must be returned or destroyed at
37  *      Sun's request.
38  *
39  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40  *
41  */
42
43 /*** DTB_USER_CODE_END   ^^^ Add file header above ^^^ ***/
44
45 /*
46  * File: attch_ed_stubs.c
47  * Contains: Module callbacks and connection functions
48  *
49  * This file was generated by dtcodegen, from module attch_ed
50  *
51  * Any text may be added between the DTB_USER_CODE_START and
52  * DTB_USER_CODE_END comments (even non-C code). Descriptive comments
53  * are provided only as an aid.
54  *
55  *  ** EDIT ONLY WITHIN SECTIONS MARKED WITH DTB_USER_CODE COMMENTS.  **
56  *  ** ALL OTHER MODIFICATIONS WILL BE OVERWRITTEN. DO NOT MODIFY OR  **
57  *  ** DELETE THE GENERATED COMMENTS!                                 **
58  */
59
60 #include <stdio.h>
61 #include <Xm/Xm.h>
62 #include "dtb_utils.h"
63 #include "dtbuilder.h"
64 #include "attch_ed_ui.h"
65
66
67 /**************************************************************************
68  *** DTB_USER_CODE_START
69  ***
70  *** All necessary header files have been included.
71  ***
72  *** Add include files, types, macros, externs, and user functions here.
73  ***/
74
75
76 #include <Xm/Form.h>
77 #include <Xm/RowColumn.h>
78 #include <Xm/PushB.h>
79 #include <Xm/List.h>
80 #include <Xm/Separator.h>
81 #include <ab_private/ab.h>
82 #include <ab_private/trav.h>
83 #include <ab_private/abobj_set.h>
84 #include <ab_private/abobj_list.h>
85 #include <ab_private/obj_notify.h>
86 #include <ab_private/pal.h>
87 #include <ab_private/prop.h>
88 #include <ab_private/proj.h>
89 #include <ab_private/attch_ed.h>
90 #include <ab_private/ui_util.h>
91 #include <ab_private/abobj_list.h>
92 #include "dtb_utils.h"
93 #include "dtbuilder.h"
94 #include "attch_ed_ui.h"
95
96 typedef struct ATTCH_ED_OBJ_TYPE_INFO_REC {
97     AB_OBJECT_TYPE  type;
98     int             subtype;
99 } AttchEdObjTypeInfoRec;
100
101 static AttchEdObjTypeInfoRec    AttchEdObjTypeInfo;
102
103
104 /*
105  * Declarations of global widgets used by callbacks.
106  */
107 /*
108  * End declarations of global widgets
109  */
110
111 static Widget   attch_editor_props_init(
112                     DtbAttchEdAttchEdDialogInfo  attch_ed_cgen,
113                     Widget              parent
114                 );
115
116 static int      attch_editor_load(
117                     ABObj   object
118                 );
119
120 static int      attch_editor_apply(
121                     ABObj   object
122                 );
123
124 static BOOL     attch_edP_pending(
125                 );
126
127 static int      attch_editor_activate(
128                     BOOL        active
129                 );
130
131 static BOOL     editable_obj_test(
132                     PalEditableObjInfo  *ed_obj_info
133                 );
134
135 static void     load_attch_obj(
136                     ABObj       obj,
137                     BOOL        turnoff_cb
138                 );
139
140 static void     create_children_list(
141                     ABObj       obj
142                 );
143
144 static void     update_attch_obj_parent(
145                     ABObj       obj
146                 );
147
148 static void     update_obj_type(
149                     ABObj       obj
150                 );
151
152 static void     update_objlist(
153                     ABObj       obj
154                 );
155
156 static void     create_obj_menu_dir(
157                     ABObj               object, 
158                     AB_COMPASS_POINT    dir
159                 );
160
161 static void     create_obj_menu(
162                     ABObj       object
163                 );
164
165 static void     delete_from_obj_menu(
166                     ABObj       cur_obj,
167                     ABObj       deleted_obj
168                 );
169
170 static void     select_objlist(
171                     ABObj       obj
172                 );
173
174 static void     turnoff_changebars(
175                 );
176
177 static void     get_attach_info(
178                     ABObj                       obj,
179                     ABAttachment                *attachment,
180                     ATTCH_ED_ATTACH_TYPE        *type,
181                     int                         *offset,
182                     int                         *position,
183                     ABObj                       *attach_obj
184                 );
185
186 static void     set_attach_info(
187                     ABObj                       obj,
188                     ABAttachment                *attachment,
189                     ATTCH_ED_ATTACH_TYPE        type,
190                     int                         offset,
191                     int                         position,
192                     ABObj                       attach_obj
193                 );
194
195 static void     attch_ed_select_itemCB(
196                     Widget      widget,
197                     XtPointer   client_data,
198                     XtPointer   call_data
199                 );
200
201 static void     populate_obj_menu(
202                     Widget      widget, 
203                     ABObj       object, 
204                     AB_COMPASS_POINT            dir,
205                     Widget      **item, 
206                     XtPointer   **item_val, 
207                     int         *n
208                 );
209
210 static void     attch_change_objecttypePalCB(
211                     Widget      widget,
212                     XtPointer   client_data,
213                     XtPointer   calldata
214                 );
215
216 static BOOL     attch_objlist_test_func(
217                     ABObj       test_obj
218                 );
219
220 static BOOL     attch_childrenlist_test_func(
221                     ABObj       test_obj
222                 );
223
224 static void     attch_objlist_selectCB(
225                     Widget      widget,
226                     XtPointer   client_data,
227                     XmListCallbackStruct *listdata
228                 );
229
230 static int      attch_obj_geom_changedCB(
231                     ObjEvAttChangeInfo evInfo
232                 );
233
234 static int      attch_obj_renameCB(
235                     ObjEvAttChangeInfo evInfo
236                 );
237
238 static int      attch_obj_destroyCB(
239                     ObjEvDestroyInfo evInfo
240                 );
241
242 static int      attch_obj_reparentCB(
243                     ObjEvReparentInfo info
244                 );
245
246 static void     handle_prop_sheet_obj_destroy(
247                     ObjEvDestroyInfo evInfo
248                 );
249
250 static void     handle_actual_obj_destroy(
251                     ObjEvDestroyInfo evInfo
252                 );
253
254 static void     handle_prop_sheet_obj_reparent(
255                     ObjEvReparentInfo evInfo
256                 );
257
258 static void     handle_actual_obj_reparent(
259                     ObjEvReparentInfo evInfo
260                 );
261
262 static void     set_widget_state(
263                     ATTCH_ED_ATTACH_TYPE        attach_type,
264                     Widget                      objlist,
265                     Widget                      offset,
266                     Widget                      position
267                 );
268
269 static void     enable_attach_types(
270                     ABObj       obj
271                 );
272
273 static void     set_attach_values(
274                     ATTCH_ED_ATTACH_TYPE        attach_type,
275                     PropFieldSetting            offset_setting,
276                     PropFieldSetting            position_setting,
277                     PropOptionsSetting          objlist_setting,
278                     int                         offset_value,
279                     int                         position_value,
280                     int                         objlist_value
281                 );
282
283 static void     change_attach_type(
284                     ABObj                       obj,
285                     AB_COMPASS_POINT            dir,
286                     ATTCH_ED_ATTACH_TYPE        attach_type
287                 );
288
289 static void     change_opp_attach_type(
290                     ABObj                       obj,
291                     AB_COMPASS_POINT            dir,
292                     ATTCH_ED_ATTACH_TYPE        attach_type
293                 );
294
295 static void     get_attach_values(
296                     ATTCH_ED_ATTACH_TYPE        attach_type,
297                     PropFieldSetting            offset_setting,
298                     PropFieldSetting            position_setting,
299                     PropOptionsSetting          objlist_setting,
300                     int                         *offset_value,
301                     int                         *position_value,
302                     XtPointer                   *objlist_value
303                 );
304
305 static void     convert_offset_position(
306                     ABObj                       cur_obj,
307                     ABObj                       sibling_obj,
308                     AB_COMPASS_POINT            dir,
309                     ATTCH_ED_ATTACH_TYPE        attach_type,
310                     int                         *ret_offset,
311                     int                         *ret_position
312                 );
313
314 static void     attach_obj_changed(
315                     Widget      widget,
316                     XtPointer   client_data,
317                     XtPointer   calldata
318                 );
319
320 static void     print_attach_type(
321                     ATTCH_ED_ATTACH_TYPE        attach_type
322                 );
323
324 static BOOL     attch_ed_obj_is_target_type(
325                     ABObj obj
326                 );
327
328 static void     attch_ed_change_objecttype(
329                     AB_OBJECT_TYPE      type,
330                     int                 subtype
331                 );
332
333 static ABObj    attch_ed_get_parent(
334                     ABObj       obj
335                 );
336
337 static void     attch_ed_view_child_attachments(
338                 );
339
340 static void     attch_ed_view_parent_attachments(
341                 );
342
343 static void     attch_ed_activate_parent_child_button(
344                 );
345
346 static void     attch_edP_prevent_closeCB(
347                     Widget      w,
348                     XtPointer   client_data,
349                     XtPointer   call_data
350                 );
351
352 static void     change_attype_from_sib_to_point(
353                     ABObj               obj,
354                     ABObj               attach_to_sib,
355                     AB_COMPASS_POINT    dir,
356                     BOOL                reparent
357                 );
358
359 static DTB_MODAL_ANSWER get_wrn_response(
360                             Widget              w,
361                             ATTCH_ED_WRN_TYPE   wrn_type,
362                             ABObj               new_obj
363                         );
364
365 static BOOL             attch_ed_verify_props(
366                         );
367
368 static BOOL             verify_one_attach(
369                             ATTCH_ED_ATTACH_TYPE        attach_type,
370                             PropFieldSetting            offset_setting,
371                             PropFieldSetting            position_setting
372                         );
373
374 static ABObj            attch_cur_parent = NULL;
375 static AB_OBJECT_TYPE   cur_type = AB_TYPE_UNDEF;
376 static int              cur_subtype;
377
378
379 AttchEditorSettingsRec attch_editor_settings_rec;
380
381 /*
382  * Declarations of global widgets used by callbacks.
383  */
384 /*
385  * End declarations of global widgets
386  */
387
388 static ABObj
389 attch_ed_get_parent(
390     ABObj       obj
391 )
392 {
393     ABObj       tmp;
394
395     if (!obj || !(obj_has_flag(obj, XmConfiguredFlag)))
396         return (NULL);
397     
398     if (!(tmp = obj_get_parent(obj)))
399         return (NULL);
400     
401     return(tmp);
402     /*
403     return(objxm_comp_get_subobj(tmp, AB_CFG_PARENT_OBJ));
404     */
405 }
406
407 void
408 attch_ed_init(
409 )
410 {
411     obj_add_destroy_callback(attch_obj_destroyCB, "ATTCH_ED");
412     obj_add_reparent_callback(attch_obj_reparentCB, "ATTCH_ED");
413 }
414
415 void
416 attch_ed_show_dialog(
417     ABObj       cur_obj
418 )
419 {
420     /*
421      * Set busy cursor
422      */
423     ab_set_busy_cursor(TRUE);
424
425     /* 
426      * If there is no Attachment Editor, create it 
427      */
428     if (AB_attch_ed_dialog == (Widget)NULL)
429     {
430         AB_attch_ed_dialog = attch_editor_props_init(&dtb_attch_ed_attch_ed_dialog, 
431                                 AB_toplevel);
432     }
433
434     if (AB_attch_ed_dialog != NULL)
435     {
436         DTB_MODAL_ANSWER            answer = DTB_ANSWER_ACTION1;
437         PalEditableObjInfo      *ed_obj_info;
438
439         /* Check to make sure cur_obj is an object that can be edited
440          * by the Attachments editor...
441          */
442         if (cur_obj)
443         {
444             if (ed_obj_info = pal_get_editable_obj_info(cur_obj))
445             {
446                 if (!editable_obj_test(ed_obj_info))
447                     cur_obj = NULL; /* can't edit current obj */
448             }
449             else
450                 cur_obj = NULL;
451         }
452
453         if (cur_obj && attch_edP_pending()) 
454         {
455             answer = get_wrn_response(AB_attch_ed_dialog, ATTCH_ED_WRN_LOAD,
456                                 cur_obj);
457         }
458
459         if (answer == DTB_ANSWER_ACTION1)
460         {
461             if (cur_obj)
462                 attch_editor_load(cur_obj);
463
464             else if (AttchEdObjTypeInfo.type == AB_TYPE_UNDEF)
465                 /* First time - start with First object type in menu */
466                 attch_ed_change_objecttype(AB_TYPE_BUTTON, AB_NO_SUBTYPE);
467
468             ab_show_window(AB_attch_ed_dialog);
469         }
470     }
471
472     /*
473      * Unset busy cursor
474      */
475     ab_set_busy_cursor(FALSE);
476
477 }
478
479 static BOOL
480 editable_obj_test(
481     PalEditableObjInfo  *ed_obj_info
482 )
483 {
484     BOOL        needed = True;
485
486     switch(ed_obj_info->type)
487     {
488         case AB_TYPE_BASE_WINDOW:
489         case AB_TYPE_DIALOG:
490         case AB_TYPE_FILE_CHOOSER:
491         case AB_TYPE_ITEM:
492         case AB_TYPE_MENU:
493         case AB_TYPE_MESSAGE:
494         case AB_TYPE_PROJECT:
495             needed = False;
496             break;
497         case AB_TYPE_CONTAINER:
498             if (ed_obj_info->subtype == AB_CONT_MENU_BAR)
499                 needed = False;
500             break;
501     }
502
503     return needed;
504 }
505
506 static Widget 
507 attch_editor_props_init(
508     DtbAttchEdAttchEdDialogInfo attch_ed_cgen,
509     Widget                      parent
510 )
511 {
512     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
513     Widget                      item[20], ret_value;
514     XtArgVal                    item_val[20];
515     int                         n;
516
517     /*
518      * Create Dialog widgets...
519      */
520     dtbAttchEdAttchEdDialogInfo_clear(attch_ed_cgen);
521
522     if (dtb_attch_ed_attch_ed_dialog_initialize(attch_ed_cgen, parent) == 0)
523     {
524         /*
525          * Setup object type menu
526          */
527
528         /*
529          * Destroy dummy item
530          */
531         XtDestroyWidget(attch_ed_cgen->obj_type_opmenu_items.Button_item);
532
533         /*
534          * Add choice items for every palette object type
535          */
536         pal_add_editable_obj_menu_items(attch_ed_cgen->obj_type_opmenu_menu,
537                 attch_change_objecttypePalCB, editable_obj_test);
538
539         AttchEdObjTypeInfo.type = AB_TYPE_UNDEF;
540         AttchEdObjTypeInfo.subtype = AB_NO_SUBTYPE;
541
542
543         XtAddCallback(attch_ed_cgen->objlist, XmNbrowseSelectionCallback,
544                     (XtCallbackProc)attch_objlist_selectCB, (XtPointer)NULL);
545
546         /* 
547          * Hook widgets up to Attachment Editor
548          */
549         /*
550         ats->prop_sheet = attch_ed_cgen->attachments_panel;
551         */
552         ats->prop_sheet = attch_ed_cgen->attach_grp;
553
554         ats->cur_object = (ABObj)NULL;
555
556         /********************** 
557          * Top Attachments    *
558          **********************/
559         /*
560          * Attachment type option menu
561          */
562         n = 0;
563         item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_form_xbm_item;
564         item_val[n] = ATTCH_ED_PARENT; n++;
565         item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_opposite_form_xbm_item;
566         item_val[n] = ATTCH_ED_OPPOSITE_PARENT; n++;
567         item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_widget_xbm_item;
568         item_val[n] = ATTCH_ED_SIBLING; n++;
569         item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_opposite_widget_xbm_item;
570         item_val[n] = ATTCH_ED_OPPOSITE_SIBLING; n++;
571         item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_position_xbm_item;
572         item_val[n] = ATTCH_ED_GRIDLINE; n++;
573
574         item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_center_position_xbm_item;
575         item_val[n] = ATTCH_ED_CENTER_GRIDLINE; n++;
576
577         item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_none_xbm_item;
578         item_val[n] = ATTCH_ED_NONE; n++;
579         prop_options_init(&(ats->top_attach_type), NULL,
580                 attch_ed_cgen->top_attach, attch_ed_cgen->top_attach_menu,
581                 n, item, (XtPointer*)item_val,
582                 attch_ed_cgen->top_attach_cb);
583         /*
584          * Top offset text field
585          */
586         prop_field_init(&(ats->top_attach_offset), attch_ed_cgen->top_offset_label,
587                                     attch_ed_cgen->top_offset, 
588                                     attch_ed_cgen->top_attach_cb);
589
590         /*
591          * Top position text field
592          */
593         prop_field_init(&(ats->top_attach_position), attch_ed_cgen->top_position_label,
594                                     attch_ed_cgen->top_position, 
595                                     attch_ed_cgen->top_attach_cb);
596
597
598         /********************** 
599          * Bottom Attachments *
600          **********************/
601         n = 0;
602         item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_form_xbm_item;
603         item_val[n] = ATTCH_ED_PARENT; n++;
604         item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_opposite_form_xbm_item;
605         item_val[n] = ATTCH_ED_OPPOSITE_PARENT; n++;
606         item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_widget_xbm_item;
607         item_val[n] = ATTCH_ED_SIBLING; n++;
608         item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_opposite_widget_xbm_item;
609         item_val[n] = ATTCH_ED_OPPOSITE_SIBLING; n++;
610         item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_position_xbm_item;
611         item_val[n] = ATTCH_ED_GRIDLINE; n++;
612
613         item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_center_position_xbm_item;
614         item_val[n] = ATTCH_ED_CENTER_GRIDLINE; n++;
615
616         item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_none_xbm_item;
617         item_val[n] = ATTCH_ED_NONE; n++;
618         prop_options_init(&(ats->bottom_attach_type), NULL,
619                 attch_ed_cgen->bottom_attach, attch_ed_cgen->bottom_attach_menu,
620                 n, item, (XtPointer*)item_val,
621                 attch_ed_cgen->bottom_attach_cb);
622
623         /*
624          * Bottom offset text field
625          */
626         prop_field_init(&(ats->bottom_attach_offset), attch_ed_cgen->bottom_offset_label,
627                                     attch_ed_cgen->bottom_offset, 
628                                     attch_ed_cgen->bottom_attach_cb);
629
630         /*
631          * Bottom position text field
632          */
633         prop_field_init(&(ats->bottom_attach_position), attch_ed_cgen->bottom_position_label,
634                                     attch_ed_cgen->bottom_position, 
635                                     attch_ed_cgen->bottom_attach_cb);
636
637
638
639         /********************** 
640          * Left Attachments   *
641          **********************/
642         n = 0;
643         item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_form_xbm_item;
644         item_val[n] = ATTCH_ED_PARENT; n++;
645         item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_opposite_form_xbm_item;
646         item_val[n] = ATTCH_ED_OPPOSITE_PARENT; n++;
647         item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_widget_xbm_item;
648         item_val[n] = ATTCH_ED_SIBLING; n++;
649         item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_opposite_widget_xbm_item;
650         item_val[n] = ATTCH_ED_OPPOSITE_SIBLING; n++;
651         item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_position_xbm_item;
652         item_val[n] = ATTCH_ED_GRIDLINE; n++;
653         item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_center_position_xbm_item;
654         item_val[n] = ATTCH_ED_CENTER_GRIDLINE; n++;
655         item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_none_xbm_item;
656         item_val[n] = ATTCH_ED_NONE; n++;
657         prop_options_init(&(ats->left_attach_type), NULL,
658                 attch_ed_cgen->left_attach, attch_ed_cgen->left_attach_menu,
659                 n, item, (XtPointer*)item_val,
660                 attch_ed_cgen->left_attach_cb);
661
662         /*
663          * Left offset text field
664          */
665         prop_field_init(&(ats->left_attach_offset), attch_ed_cgen->left_offset_label,
666                                     attch_ed_cgen->left_offset, 
667                                     attch_ed_cgen->left_attach_cb);
668
669
670         /*
671          * Left position text field
672          */
673         prop_field_init(&(ats->left_attach_position), attch_ed_cgen->left_position_label,
674                                     attch_ed_cgen->left_position, 
675                                     attch_ed_cgen->left_attach_cb);
676
677
678         /********************** 
679          * Right Attachments  *
680          **********************/
681         n = 0;
682         item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_form_xbm_item;
683         item_val[n] = ATTCH_ED_PARENT; n++;
684         item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_opposite_form_xbm_item;
685         item_val[n] = ATTCH_ED_OPPOSITE_PARENT; n++;
686         item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_widget_xbm_item;
687         item_val[n] = ATTCH_ED_SIBLING; n++;
688         item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_opposite_widget_xbm_item;
689         item_val[n] = ATTCH_ED_OPPOSITE_SIBLING; n++;
690         item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_position_xbm_item;
691         item_val[n] = ATTCH_ED_GRIDLINE; n++;
692         item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_center_position_xbm_item;
693         item_val[n] = ATTCH_ED_CENTER_GRIDLINE; n++;
694         item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_none_xbm_item;
695         item_val[n] = ATTCH_ED_NONE; n++;
696         prop_options_init(&(ats->right_attach_type), NULL,
697                 attch_ed_cgen->right_attach, attch_ed_cgen->right_attach_menu,
698                 n, item, (XtPointer*)item_val,
699                 attch_ed_cgen->left_attach_cb);
700
701         /*
702          * Right offset text field
703          */
704         prop_field_init(&(ats->right_attach_offset), attch_ed_cgen->right_offset_label,
705                                     attch_ed_cgen->right_offset, 
706                                     attch_ed_cgen->left_attach_cb);
707
708         /*
709          * Right position text field
710          */
711         prop_field_init(&(ats->right_attach_position), attch_ed_cgen->right_position_label,
712                                     attch_ed_cgen->right_position, 
713                                     attch_ed_cgen->left_attach_cb);
714
715         /* 
716          * Setup dialog to participate in dtbuilder window protocol
717          */ 
718         ab_register_window(attch_ed_cgen->attch_ed_dialog_shellform,
719                 AB_WIN_DIALOG, WindowHidden, AB_toplevel, AB_WPOS_TILE_HORIZONTAL,
720                 attch_edP_prevent_closeCB, NULL); 
721
722         ret_value = dtb_attch_ed_attch_ed_dialog.attch_ed_dialog_shellform;
723
724         /*
725          * Add callback to detect change in geometry
726          */
727         obj_add_geometry_change_callback(attch_obj_geom_changedCB, "ATTCH_ED");
728
729         obj_add_rename_callback(attch_obj_renameCB, "ATTCH_ED");
730
731     }
732     else
733     {
734         util_dprintf(3, "attch_editor_props_init: could not initialize Attachment Editor\n");
735         ret_value = NULL;
736     }
737
738     return(ret_value);
739 }
740
741
742 static int
743 attch_editor_load(
744     ABObjPtr    object
745 )
746 {
747     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
748
749     load_attch_obj(object, TRUE);
750
751     create_children_list(object);
752     update_attch_obj_parent(object);
753     update_obj_type(object);
754     update_objlist(object);
755     select_objlist(object);
756
757     return(0);
758 }
759
760 static void
761 load_attch_obj(
762     ABObj       object,
763     BOOL        turnoff_cb
764 )
765 {
766     DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
767     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
768     ABAttachment                *top_attachment,
769                                 *bottom_attachment,
770                                 *left_attachment,
771                                 *right_attachment;
772     ATTCH_ED_ATTACH_TYPE        top_attach_type = ATTCH_ED_NONE,
773                                 bottom_attach_type = ATTCH_ED_NONE,
774                                 left_attach_type = ATTCH_ED_NONE,
775                                 right_attach_type = ATTCH_ED_NONE;
776     int                         top_offset = 0,
777                                 top_position = 0,
778                                 bottom_offset = 0,
779                                 bottom_position = 0,
780                                 left_offset = 0,
781                                 left_position = 0,
782                                 right_offset = 0,
783                                 right_position = 0,
784                                 cur_position = 1,
785                                 child_count = 0,
786                                 n = 0;
787     ABObj                       top_obj = NULL,
788                                 bottom_obj = NULL,
789                                 left_obj = NULL,
790                                 right_obj = NULL,
791                                 *child_list = NULL;
792  
793     if (object == NULL)
794         return;
795
796     if (!attch_ed_can_edit_attachments(object))
797     {
798         ats->cur_object = NULL;
799         attch_editor_activate(FALSE);
800         return;
801     }
802
803     attch_editor_activate(TRUE);
804
805     /*
806      * Get attachment info from ABObj
807      */
808     top_attachment = obj_get_attachment(object, AB_CP_NORTH);
809     bottom_attachment = obj_get_attachment(object, AB_CP_SOUTH);
810     left_attachment = obj_get_attachment(object, AB_CP_WEST);
811     right_attachment = obj_get_attachment(object, AB_CP_EAST);
812
813     /*
814      * Get ATTCH_ED_ATTACH_TYPE, offset, position, attached object
815      */
816     get_attach_info(object, top_attachment, 
817         &top_attach_type, &top_offset, &top_position, &top_obj);
818     get_attach_info(object, bottom_attachment, 
819         &bottom_attach_type, &bottom_offset, &bottom_position, &bottom_obj);
820     get_attach_info(object, right_attachment, 
821         &right_attach_type, &right_offset, &right_position, &right_obj);
822     get_attach_info(object, left_attachment, 
823         &left_attach_type, &left_offset, &left_position, &left_obj);
824
825     /*
826      * (Re)Create option menu that lists which objects this
827      * object can attach to.
828      */
829     create_obj_menu(object);
830
831     /*
832      * Set attachment types
833      */
834     prop_options_set_value(&(ats->top_attach_type), (XtPointer)top_attach_type, False);
835     prop_options_set_value(&(ats->bottom_attach_type), (XtPointer)bottom_attach_type, False);
836     prop_options_set_value(&(ats->right_attach_type), (XtPointer)right_attach_type, False);
837     prop_options_set_value(&(ats->left_attach_type), (XtPointer)left_attach_type, False);
838
839     enable_attach_types(object);
840
841     /*
842      * Activate position/offset/objmenu depending on type of attachment
843      */
844     set_widget_state(left_attach_type, 
845         attch_ed_cgen->left_attach_objmenu,
846         attch_ed_cgen->left_offset_rowcolumn,
847         attch_ed_cgen->left_position_rowcolumn);
848
849     set_widget_state(right_attach_type, 
850         attch_ed_cgen->right_attach_objmenu,
851         attch_ed_cgen->right_offset_rowcolumn,
852         attch_ed_cgen->right_position_rowcolumn);
853
854     set_widget_state(top_attach_type, 
855         attch_ed_cgen->top_attach_objmenu,
856         attch_ed_cgen->top_offset_rowcolumn,
857         attch_ed_cgen->top_position_rowcolumn);
858
859     set_widget_state(bottom_attach_type, 
860         attch_ed_cgen->bottom_attach_objmenu,
861         attch_ed_cgen->bottom_offset_rowcolumn,
862         attch_ed_cgen->bottom_position_rowcolumn);
863
864     /*
865      * Set values for position/offset/objmenu depending on type of attachment
866      * i.e. if attachment is of type ATTCH_ED_PARENT, don't set the position
867      * value.
868      */
869     set_attach_values(left_attach_type, 
870         &(ats->left_attach_offset), 
871         &(ats->left_attach_position), 
872         &(ats->left_attach_obj), 
873         left_offset, 
874         left_position, 
875         (int)left_obj);
876
877     set_attach_values(right_attach_type, 
878         &(ats->right_attach_offset), 
879         &(ats->right_attach_position), 
880         &(ats->right_attach_obj), 
881         right_offset, 
882         right_position, 
883         (int)right_obj);
884
885     set_attach_values(top_attach_type, 
886         &(ats->top_attach_offset), 
887         &(ats->top_attach_position), 
888         &(ats->top_attach_obj), 
889         top_offset, 
890         top_position, 
891         (int)top_obj);
892
893     set_attach_values(bottom_attach_type, 
894         &(ats->bottom_attach_offset), 
895         &(ats->bottom_attach_position), 
896         &(ats->bottom_attach_obj), 
897         bottom_offset, 
898         bottom_position, 
899         (int)bottom_obj);
900
901     /*
902      * Set object name
903      */
904     ats->cur_object = object;
905     ui_set_label_string(attch_ed_cgen->obj_label, obj_get_name(object));
906     attch_ed_activate_parent_child_button();
907
908     if (turnoff_cb)
909         turnoff_changebars();
910 }
911
912 /*
913  * Update list containing siblings of object that is currently edited
914  */
915 static void
916 create_children_list(
917     ABObj       obj
918 )
919 {
920     DtbAttchEdAttchEdDialogInfo attch_ed_cgen 
921                         = &dtb_attch_ed_attch_ed_dialog;
922     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
923     ABObj                       parent,
924                                 *child_list,
925                                 cur_child;
926     AB_TRAVERSAL                trav;
927     int                         child_count,
928                                 i,
929                                 cur_position = 0;
930
931     if (!obj)
932         return;
933
934     parent = attch_ed_get_parent(obj);
935
936     if (!parent)
937         return;
938
939     /*
940      * Populate siblings list
941     if ((!ats->cur_object) || (obj_get_parent(ats->cur_object) != parent))
942      */
943     if (1)
944     {
945         /*
946          * Get array of child objects on list widget
947          */
948         XtVaGetValues(attch_ed_cgen->childrenlist,
949             XmNuserData,    &child_list,
950             NULL);
951
952         /*
953          * List of child objects:
954          * Free it
955          * Nullify XmNuserData
956          */
957         if (child_list)
958         {
959             util_free(child_list);
960             XtVaSetValues(attch_ed_cgen->childrenlist, XmNuserData, NULL, NULL);
961         }
962
963         /*
964          * Get child count
965          */
966         child_count = trav_count(parent, AB_TRAV_SALIENT_CHILDREN);
967
968         /*
969          * Delete all current items in list
970          */
971         XmListDeleteAllItems(attch_ed_cgen->childrenlist);
972
973         /*
974          * Return if no children to insert in list
975          */
976         if (child_count <= 0)
977             return;
978
979         /*
980          * Alloc new array to store child objects. This will be stored
981          * as user data on the list.
982          */
983         child_list = (ABObj *)util_malloc(child_count*sizeof(ABObj));
984
985         /*
986          * For all direct children of 'parent'.:
987          *      add to XmList object
988          *      add to ABObj list
989          *      remember position of 'object' in list
990          */
991         for (i = 1, trav_open(&trav, parent, AB_TRAV_SALIENT_CHILDREN); 
992                 (cur_child = trav_next(&trav)) != NULL; ++i)
993         {
994             if (cur_child == obj)
995             {
996                 cur_position = i;
997             }
998             child_list[i-1] = cur_child;
999             ui_list_add_item(attch_ed_cgen->childrenlist, obj_get_name(cur_child), 0);
1000         }
1001
1002         /*
1003          * Make current object selected, and visible in list
1004          */
1005         ui_list_select_pos(attch_ed_cgen->childrenlist, cur_position, False);
1006
1007         /*
1008          * Store ABObj list on XmList object
1009          */
1010         XtVaSetValues(attch_ed_cgen->childrenlist, XmNuserData, child_list, NULL);
1011
1012         /*
1013          * Register callback on list that will load selected object
1014          */
1015         XtAddCallback(attch_ed_cgen->childrenlist, XmNbrowseSelectionCallback, 
1016                 attch_ed_select_itemCB, (XtPointer)NULL);
1017     }
1018 }
1019
1020 static void
1021 update_attch_obj_parent(
1022     ABObj       obj
1023 )
1024 {
1025     DtbAttchEdAttchEdDialogInfo attch_ed_cgen 
1026                         = &dtb_attch_ed_attch_ed_dialog;
1027     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
1028     ABObj                       parent;
1029
1030     if (!obj)
1031         return;
1032
1033     parent = attch_ed_get_parent(obj);
1034     if (parent)
1035         parent = obj_get_root(parent);
1036
1037     /*
1038      * Set object parent's name
1039      */
1040     if (parent)
1041         ui_set_label_string(attch_ed_cgen->parent_obj_name, 
1042                                         obj_get_name(parent));
1043 }
1044
1045 static void
1046 update_obj_type(
1047     ABObj       obj
1048 )
1049 {
1050     DtbAttchEdAttchEdDialogInfo attch_ed_cgen 
1051                         = &dtb_attch_ed_attch_ed_dialog;
1052     PalEditableObjInfo  *ed_obj_info;
1053
1054     if (!obj)
1055         return;
1056
1057     AttchEdObjTypeInfo.type = obj_get_type(obj);
1058     AttchEdObjTypeInfo.subtype = obj_get_subtype(obj);
1059
1060     if ((ed_obj_info = pal_get_editable_obj_info(obj)) &&
1061         editable_obj_test(ed_obj_info))
1062     {
1063         ui_optionmenu_change_label(attch_ed_cgen->obj_type_opmenu, 
1064                 istr_string(ed_obj_info->name));
1065     }
1066
1067 }
1068
1069 static void
1070 update_objlist(
1071     ABObj       obj
1072 )
1073 {
1074     DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
1075     ABObj                       proj = proj_get_project();
1076     int                         num_items;
1077     
1078     if (!obj)
1079         return;
1080
1081     num_items = abobj_list_load(attch_ed_cgen->objlist, 
1082                                 proj, 
1083                                 attch_objlist_test_func);
1084 }
1085
1086 static void
1087 select_objlist(
1088     ABObj       obj
1089 )
1090 {
1091     DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
1092     char                        *modname = NULL;
1093
1094     if (!obj)
1095         return;
1096
1097     modname = abobj_get_moduled_name(obj);
1098
1099     if (modname)
1100     {
1101         ui_list_select_item(attch_ed_cgen->objlist, modname, FALSE);
1102         util_free(modname);
1103     }
1104 }
1105
1106 static int
1107 attch_editor_apply(
1108     ABObjPtr    object
1109 )
1110 {
1111     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
1112     ABAttachment                attachment;
1113     ATTCH_ED_ATTACH_TYPE        attach_type = ATTCH_ED_NONE;
1114     int                         offset = 0,
1115                                 position = 0;
1116     ABObj                       obj = NULL;
1117
1118     if (object == NULL)
1119         return ERROR;
1120
1121     if (!attch_ed_verify_props())
1122         return ERROR;
1123
1124     /*
1125      * Top attachment
1126      */
1127     if (prop_changed(ats->top_attach_type.changebar))
1128     {
1129         attach_type = 
1130                 (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->top_attach_type));
1131
1132         get_attach_values(attach_type,
1133                 &(ats->top_attach_offset), 
1134                 &(ats->top_attach_position),
1135                 &(ats->top_attach_obj),
1136                 &offset, &position, (XtPointer *)&obj);
1137
1138         set_attach_info(object,
1139                 &attachment, attach_type, offset, position, obj);
1140
1141         abobj_set_attachment(object, AB_CP_NORTH, &attachment);
1142     }
1143
1144     /*
1145      * Bottom attachment
1146      */
1147     if (prop_changed(ats->bottom_attach_type.changebar))
1148     {
1149         attach_type = (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->bottom_attach_type));
1150
1151         get_attach_values(attach_type,
1152                 &(ats->bottom_attach_offset), 
1153                 &(ats->bottom_attach_position),
1154                 &(ats->bottom_attach_obj),
1155                 &offset, &position, (XtPointer *)&obj);
1156
1157         set_attach_info(object,
1158                 &attachment, attach_type, offset, position, obj);
1159
1160         abobj_set_attachment(object, AB_CP_SOUTH, &attachment);
1161     }
1162
1163     /*
1164      * Left attachment
1165      */
1166     if (prop_changed(ats->left_attach_type.changebar))
1167     {
1168         attach_type = (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->left_attach_type));
1169
1170         get_attach_values(attach_type,
1171                 &(ats->left_attach_offset), 
1172                 &(ats->left_attach_position),
1173                 &(ats->left_attach_obj),
1174                 &offset, &position, (XtPointer *)&obj);
1175
1176         set_attach_info(object,
1177                 &attachment, attach_type, offset, position, obj);
1178
1179         abobj_set_attachment(object, AB_CP_WEST, &attachment);
1180     }
1181
1182     /*
1183      * Right attachment - shares changebar with left attachment
1184      */
1185     if (prop_changed(ats->left_attach_type.changebar))
1186     {
1187         attach_type = (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->right_attach_type));
1188
1189         get_attach_values(attach_type,
1190                 &(ats->right_attach_offset), 
1191                 &(ats->right_attach_position),
1192                 &(ats->right_attach_obj),
1193                 &offset, &position, (XtPointer *)&obj);
1194
1195         set_attach_info(object,
1196                 &attachment, attach_type, offset, position, obj);
1197
1198         abobj_set_attachment(object, AB_CP_EAST, &attachment);
1199     }
1200
1201     abobj_instantiate_changes(object);
1202  
1203     turnoff_changebars();
1204
1205     return OK;
1206
1207 }
1208
1209 static BOOL
1210 attch_edP_pending(
1211 )
1212 {
1213     AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
1214
1215     if (ats && ats->cur_object && prop_changebars_pending(ats->prop_sheet))
1216         return (TRUE);
1217
1218     return (FALSE);
1219 }
1220
1221 static int
1222 attch_editor_activate(
1223     BOOL        active
1224 )
1225 {
1226     DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
1227
1228     /*
1229     AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
1230     ui_set_active(ats->prop_sheet, active);
1231     */
1232
1233     ui_set_active(attch_ed_cgen->attachments_panel, active);
1234
1235     return(OK);
1236 }
1237
1238 static void
1239 turnoff_changebars(
1240 )
1241 {
1242     AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
1243
1244     prop_set_changebar(ats->top_attach_type.changebar,          PROP_CB_OFF);
1245     prop_set_changebar(ats->bottom_attach_type.changebar,       PROP_CB_OFF);
1246     prop_set_changebar(ats->left_attach_type.changebar, PROP_CB_OFF);
1247
1248     prop_changebars_cleared(ats->prop_sheet);
1249
1250 }
1251
1252 static void
1253 get_attach_info(
1254     ABObj                       obj,
1255     ABAttachment                *attachment,
1256     ATTCH_ED_ATTACH_TYPE        *type,
1257     int                         *offset,
1258     int                         *position,
1259     ABObj                       *attach_obj
1260 )
1261 {
1262     
1263     if (!obj || !attachment)
1264         return;
1265
1266     *offset = 0;
1267     *position = 0;
1268     *attach_obj = NULL;
1269     switch (attachment->type)
1270     {
1271         case AB_ATTACH_POINT:
1272             *type = ATTCH_ED_PARENT;
1273             *offset = attachment->offset;
1274         break;
1275
1276         case AB_ATTACH_OBJ:
1277             *attach_obj = (ABObj)attachment->value;
1278
1279             if (*attach_obj == attch_ed_get_parent(obj))
1280                 *type = ATTCH_ED_PARENT;
1281             else
1282                 *type = ATTCH_ED_SIBLING;
1283
1284             *offset = attachment->offset;
1285
1286         break;
1287
1288         case AB_ATTACH_ALIGN_OBJ_EDGE:
1289             *attach_obj = (ABObj)attachment->value;
1290
1291             if (*attach_obj == attch_ed_get_parent(obj))
1292                 *type = ATTCH_ED_OPPOSITE_PARENT;
1293             else
1294                 *type = ATTCH_ED_OPPOSITE_SIBLING;
1295
1296             *offset = attachment->offset;
1297
1298         break;
1299
1300         case AB_ATTACH_GRIDLINE:
1301             *type = ATTCH_ED_GRIDLINE;
1302             *offset = attachment->offset;
1303             *position = (int)attachment->value;
1304         break;
1305
1306         case AB_ATTACH_CENTER_GRIDLINE:
1307             *type = ATTCH_ED_CENTER_GRIDLINE;
1308             *position = (int)attachment->value;
1309             *offset = 0;
1310         break;
1311
1312         case AB_ATTACH_NONE:
1313             *type = ATTCH_ED_NONE;
1314         break;
1315
1316         default:
1317             fprintf(stderr, "get_attach_info: attachment is unresolved\n");
1318         break;
1319     }
1320 }
1321
1322
1323 static void
1324 set_attach_info(
1325     ABObj                       obj,
1326     ABAttachment                *attachment,
1327     ATTCH_ED_ATTACH_TYPE        type,
1328     int                         offset,
1329     int                         position,
1330     ABObj                       attach_obj
1331 )
1332 {
1333     
1334     switch (type)
1335     {
1336     case ATTCH_ED_PARENT:
1337         /*
1338         attachment->value = (void *)attach_obj;
1339         attachment->value = (void *)attch_ed_get_parent(obj);
1340         */
1341         attachment->type = AB_ATTACH_POINT;
1342         attachment->offset = offset;
1343     break;
1344
1345     case ATTCH_ED_SIBLING:
1346         attachment->value = (void *)attach_obj;
1347         attachment->type = AB_ATTACH_OBJ;
1348         attachment->offset = offset;
1349     break;
1350
1351     case ATTCH_ED_OPPOSITE_PARENT:
1352         attachment->value = (void *)attch_ed_get_parent(obj);
1353         attachment->type = AB_ATTACH_ALIGN_OBJ_EDGE;
1354         attachment->offset = offset;
1355     break;
1356
1357     case ATTCH_ED_OPPOSITE_SIBLING:
1358         attachment->value = (void *)attach_obj;
1359         attachment->type = AB_ATTACH_ALIGN_OBJ_EDGE;
1360         attachment->offset = offset;
1361     break;
1362
1363     case ATTCH_ED_GRIDLINE:
1364         attachment->type = AB_ATTACH_GRIDLINE;
1365         attachment->value = (void *)position;
1366         attachment->offset = offset;
1367     break;
1368
1369     case ATTCH_ED_CENTER_GRIDLINE:
1370         attachment->type = AB_ATTACH_CENTER_GRIDLINE;
1371         attachment->value = (void *)position;
1372         attachment->offset = 0;
1373     break;
1374
1375
1376     case ATTCH_ED_NONE:
1377         attachment->type = AB_ATTACH_NONE;
1378     break;
1379
1380     default:
1381         fprintf(stderr, "set_attach_info: attachment is unresolved\n");
1382     break;
1383     }
1384 }
1385
1386
1387 static void
1388 attch_ed_select_itemCB(
1389     Widget      widget,
1390     XtPointer   client_data,
1391     XtPointer   call_data
1392 )
1393 {
1394     XmListCallbackStruct        *listdata = (XmListCallbackStruct *)call_data;
1395     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
1396     ABObj                       *child_list = NULL,
1397                                 new_obj = NULL;
1398     int                         num_items = 0, pos;
1399
1400     XtVaGetValues(widget,
1401         XmNuserData,    &child_list,
1402         XmNitemCount,   &num_items,
1403         NULL);
1404     
1405     if (!child_list)
1406         return;
1407
1408     pos = ui_list_get_selected_pos(widget);
1409     if (pos > 0)
1410         new_obj = child_list[pos-1];
1411
1412     if (new_obj != ats->cur_object)
1413     {
1414         ABObj   old_obj = ats->cur_object;
1415         DTB_MODAL_ANSWER            answer = DTB_ANSWER_ACTION1;
1416
1417         if (attch_edP_pending())
1418         {
1419             answer = get_wrn_response(AB_attch_ed_dialog, ATTCH_ED_WRN_LOAD,
1420                                 new_obj);
1421
1422             if (answer == DTB_ANSWER_CANCEL)
1423             {
1424                 char    *name;
1425
1426                 name = obj_get_name(old_obj);
1427                 ui_list_select_item(widget, name, FALSE);
1428             }
1429         }
1430
1431         if (answer != DTB_ANSWER_ACTION1)
1432             return;
1433
1434         load_attch_obj(new_obj, TRUE);
1435         update_obj_type(new_obj);
1436
1437         /*
1438          * Update object list
1439          * If type of object did not change just select new object in list
1440          * otherwise, reload the list
1441          */
1442         if (old_obj && 
1443                 (pal_get_item_info(old_obj) == pal_get_item_info(new_obj)))
1444         {
1445             select_objlist(new_obj);
1446         }
1447         else
1448         {
1449             update_objlist(new_obj);
1450             select_objlist(new_obj);
1451         }
1452     }
1453 }
1454
1455
1456 /*
1457  * create_obj_menu()
1458  * Updates the sibling option menu for all attachments of
1459  * 'object'. This is necessary only for attachments that
1460  * need 'which sibling?' info.
1461  */
1462 static void
1463 create_obj_menu(
1464     ABObj                       object
1465 )
1466 {
1467     ABAttachment                *attachment;
1468     ATTCH_ED_ATTACH_TYPE        attach_type = ATTCH_ED_NONE;
1469     int                         offset,
1470                                 position;
1471     ABObj                       obj;
1472
1473     /*
1474      * Top attachment
1475      */
1476     attachment = obj_get_attachment(object, AB_CP_NORTH);
1477     get_attach_info(object, attachment, 
1478         &attach_type, &offset, &position, &obj);
1479     if (attch_ed_need_obj_menu(attach_type))
1480         create_obj_menu_dir(object, AB_CP_NORTH);
1481
1482     /*
1483      * Bottom attachment
1484      */
1485     attachment = obj_get_attachment(object, AB_CP_SOUTH);
1486     get_attach_info(object, attachment, 
1487         &attach_type, &offset, &position, &obj);
1488     if (attch_ed_need_obj_menu(attach_type))
1489         create_obj_menu_dir(object, AB_CP_SOUTH);
1490
1491     /*
1492      * Left attachment
1493      */
1494     attachment = obj_get_attachment(object, AB_CP_WEST);
1495     get_attach_info(object, attachment, 
1496         &attach_type, &offset, &position, &obj);
1497     if (attch_ed_need_obj_menu(attach_type))
1498         create_obj_menu_dir(object, AB_CP_WEST);
1499
1500     /*
1501      * Right attachment
1502      */
1503     attachment = obj_get_attachment(object, AB_CP_EAST);
1504     get_attach_info(object, attachment, 
1505         &attach_type, &offset, &position, &obj);
1506     if (attch_ed_need_obj_menu(attach_type))
1507         create_obj_menu_dir(object, AB_CP_EAST);
1508 }
1509
1510
1511 /*
1512  * delete_from_obj_menu()
1513  * Deletes the passed object from the object menu setting on the 
1514  * editor.
1515  */
1516 static void
1517 delete_from_obj_menu(
1518     ABObj                       cur_obj,
1519     ABObj                       deleted_obj
1520 )
1521 {
1522     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
1523     ABAttachment                *attachment;
1524     ATTCH_ED_ATTACH_TYPE        attach_type = ATTCH_ED_NONE;
1525     int                         offset,
1526                                 position;
1527     ABObj                       obj;
1528
1529     if (!cur_obj || !deleted_obj)
1530         return;
1531
1532     /*
1533      * Top attachment
1534      */
1535     attachment = obj_get_attachment(cur_obj, AB_CP_NORTH);
1536     get_attach_info(cur_obj, attachment, 
1537         &attach_type, &offset, &position, &obj);
1538     if (attch_ed_need_obj_menu(attach_type))
1539         prop_options_remove_value(&(ats->top_attach_obj), 
1540                         (XtPointer)deleted_obj, False);
1541
1542     /*
1543      * Bottom attachment
1544      */
1545     attachment = obj_get_attachment(cur_obj, AB_CP_SOUTH);
1546     get_attach_info(cur_obj, attachment, 
1547         &attach_type, &offset, &position, &obj);
1548     if (attch_ed_need_obj_menu(attach_type))
1549         prop_options_remove_value(&(ats->bottom_attach_obj), 
1550                         (XtPointer)deleted_obj, False);
1551
1552     /*
1553      * Left attachment
1554      */
1555     attachment = obj_get_attachment(cur_obj, AB_CP_WEST);
1556     get_attach_info(cur_obj, attachment, 
1557         &attach_type, &offset, &position, &obj);
1558     if (attch_ed_need_obj_menu(attach_type))
1559         prop_options_remove_value(&(ats->left_attach_obj), 
1560                         (XtPointer)deleted_obj, False);
1561
1562     /*
1563      * Right attachment
1564      */
1565     attachment = obj_get_attachment(cur_obj, AB_CP_EAST);
1566     get_attach_info(cur_obj, attachment, 
1567         &attach_type, &offset, &position, &obj);
1568     if (attch_ed_need_obj_menu(attach_type))
1569         prop_options_remove_value(&(ats->right_attach_obj), 
1570                         (XtPointer)deleted_obj, False);
1571 }
1572
1573 /*
1574  * create_obj_menu_dir()
1575  * Updates the sibling option menu for one attachment of
1576  * 'object' as specified by 'dir'.
1577  * The option menu is also initialized to have the first
1578  * entry of the menu as it's initial value.
1579  */
1580 static void
1581 create_obj_menu_dir(
1582     ABObj                       object, 
1583     AB_COMPASS_POINT            dir
1584 )
1585 {
1586     DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
1587     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
1588     PropOptionsSetting          option_setting;
1589     Widget                      label = NULL,
1590                                 optionbox,
1591                                 menu,
1592                                 changebar,
1593                                 *item = NULL;
1594     int                         item_values = NULL,
1595                                 *item_val = NULL, 
1596                                 n = 0;
1597
1598     /*
1599      * Return immediately if bad params
1600      */
1601     if (!object)
1602         return;
1603
1604     /*
1605      * Depending on what direction, remember what widgets/settings
1606      * to set.
1607      */
1608     switch (dir)
1609     {
1610         case AB_CP_NORTH:
1611             option_setting = &(ats->top_attach_obj);
1612             optionbox = attch_ed_cgen->top_attach_objmenu;
1613             menu = attch_ed_cgen->top_attach_objmenu_menu;
1614             changebar = attch_ed_cgen->top_attach_cb;
1615         break;
1616
1617         case AB_CP_SOUTH:
1618             option_setting = &(ats->bottom_attach_obj);
1619             optionbox = attch_ed_cgen->bottom_attach_objmenu;
1620             menu = attch_ed_cgen->bottom_attach_objmenu_menu;
1621             changebar = attch_ed_cgen->bottom_attach_cb;
1622         break;
1623
1624         case AB_CP_WEST:
1625             option_setting = &(ats->left_attach_obj);
1626             optionbox = attch_ed_cgen->left_attach_objmenu;
1627             menu = attch_ed_cgen->left_attach_objmenu_menu;
1628             changebar = attch_ed_cgen->left_attach_cb;
1629         break;
1630
1631         case AB_CP_EAST:
1632             option_setting = &(ats->right_attach_obj);
1633             optionbox = attch_ed_cgen->right_attach_objmenu;
1634             menu = attch_ed_cgen->right_attach_objmenu_menu;
1635             /* right/left menus share changebars */
1636             changebar = attch_ed_cgen->left_attach_cb;
1637         break;
1638     }
1639
1640     /*
1641      * If widgets/prop setting is NULL, return immediately
1642      */
1643     if (!option_setting || !optionbox || !menu || !changebar)
1644         return;
1645
1646     populate_obj_menu(menu, object, dir, &item, (XtPointer **)&item_val, &n);
1647     prop_options_init(option_setting, NULL,
1648                 optionbox, 
1649                 menu,
1650                 n, item, (XtPointer*)item_val,
1651                 changebar);
1652
1653     /*
1654      * If there were items, set the value of the setting to be the 
1655      * first one
1656      */
1657     if (n > 0)
1658         prop_options_set_value(option_setting, (XtPointer)item_val[0], False);
1659
1660     if (item)
1661         util_free(item);
1662
1663     if (item_val)
1664         util_free(item_val);
1665 }
1666
1667 /*
1668  * populate_obj_menu()
1669  * Inserts/Modifies the children of 'widget' to contain items
1670  * that have, as labels, the names of the sibling objects of
1671  * 'objects'.
1672  * The list of widget items is returned in 'ret_item'.
1673  * The list of ABObj pointers (siblings of 'object') is returned in 
1674  * 'ret_item_val'.
1675  * The number of items is returned in 'n'.
1676  * The lists returned are allocated in this function. It is up to
1677  * the caller to free them.
1678  */
1679 static void
1680 populate_obj_menu(
1681     Widget      widget, 
1682     ABObj       object, 
1683     AB_COMPASS_POINT            dir,
1684     Widget      **ret_item, 
1685     XtPointer   **ret_item_val, 
1686     int         *n
1687 )
1688 {
1689     AB_TRAVERSAL        trav;
1690     ABObj               parent,
1691                         cur_obj;
1692     Widget              *item_list = NULL;
1693     WidgetList          menu_children;
1694     XtPointer           *item_val_list = NULL;
1695     int                 i, 
1696                         num_menu_children,
1697                         num_items_needed,
1698                         num_trav_children;
1699     static BOOL         first_time = TRUE;
1700
1701     if (!widget || !object)
1702         return;
1703
1704     parent = attch_ed_get_parent(object);
1705
1706     if (!parent)
1707         return;
1708
1709     if (first_time)
1710     {
1711         DtbAttchEdAttchEdDialogInfo     attch_ed_cgen
1712                             = &dtb_attch_ed_attch_ed_dialog;
1713
1714         /*
1715          * Set up callabcks for menu items created in _ui.c file
1716          */
1717         XtAddCallback(attch_ed_cgen->left_attach_objmenu_items.Object1_item, 
1718                         XmNactivateCallback,
1719                         attach_obj_changed, (XtPointer)AB_CP_WEST);
1720
1721         XtAddCallback(attch_ed_cgen->right_attach_objmenu_items.Object1_item, 
1722                         XmNactivateCallback,
1723                         attach_obj_changed, (XtPointer)AB_CP_EAST);
1724
1725         XtAddCallback(attch_ed_cgen->top_attach_objmenu_items.Object1_item, 
1726                         XmNactivateCallback,
1727                         attach_obj_changed, (XtPointer)AB_CP_NORTH);
1728
1729         XtAddCallback(attch_ed_cgen->bottom_attach_objmenu_items.Object1_item, 
1730                         XmNactivateCallback,
1731                         attach_obj_changed, (XtPointer)AB_CP_SOUTH);
1732
1733         first_time = FALSE;
1734     }
1735
1736     num_trav_children = trav_count(parent, AB_TRAV_SALIENT_CHILDREN);
1737
1738     /*
1739      * The number of menu items we need is one less that the total child 
1740      * count.
1741      */
1742     num_items_needed = (num_trav_children > 0) 
1743                                 ? num_trav_children - 1
1744                                 : 0;
1745
1746     /*
1747      * Allocate lists to store widget id's and ABObj pointers
1748      */
1749     if (num_items_needed > 0)
1750     {
1751         item_list = (Widget *)util_malloc(num_items_needed * sizeof(Widget));
1752         item_val_list = (XtPointer *)
1753         util_malloc(num_items_needed * sizeof(XtPointer));
1754     }
1755
1756     /*
1757      * Get current list of menu items
1758      */
1759     XtVaGetValues(widget, 
1760                 XmNnumChildren, &num_menu_children, 
1761                 XmNchildren, &menu_children, 
1762                 NULL);
1763
1764     if (num_items_needed > num_menu_children)
1765     {
1766         /*
1767          * Create more menu items if needed
1768          */
1769         for (i = num_menu_children; i < num_items_needed; ++i)
1770         {
1771             Widget      menu_item;
1772
1773             menu_item = XtVaCreateWidget("attach_obj_menu", 
1774                         xmPushButtonWidgetClass, 
1775                         widget, 
1776                         NULL);
1777
1778             XtAddCallback(menu_item, XmNactivateCallback,
1779                         attach_obj_changed, (XtPointer)dir);
1780         }
1781
1782         /*
1783          * Re-fetch list of menu items
1784          */
1785         XtVaGetValues(widget, 
1786                 XmNnumChildren, &num_menu_children, 
1787                 XmNchildren, &menu_children, 
1788                 NULL);
1789     }
1790     
1791     /*
1792      * Set the label of the menu items to be the names of the ABObj's
1793      */
1794     for (i = 0, trav_open(&trav, parent, AB_TRAV_SALIENT_CHILDREN); 
1795         i < num_items_needed, (cur_obj = trav_next(&trav)) != NULL; )
1796     {
1797         char    *label;
1798
1799         /*
1800          * Skip the passed object.
1801          * We are only interested in the siblings of 'object'
1802          */
1803         if (cur_obj == object)
1804             continue;
1805         
1806         /*
1807          * Get label of ABObj
1808          */
1809         label = obj_get_name(cur_obj);
1810
1811         /*
1812          * Store the widget id of current menu item
1813          */
1814         item_list[i] = menu_children[i];
1815
1816         /*
1817          * If label exists, set it on the menu item
1818          */
1819         if (label)
1820             XtVaSetValues(item_list[i], 
1821                         XtVaTypedArg, XmNlabelString, XtRString, 
1822                         label, strlen(label)+1,
1823                         NULL);
1824
1825         /*
1826          * Store ABObj ptr
1827          */
1828         item_val_list[i] = (XtPointer)cur_obj;
1829
1830         ++i;
1831     }
1832
1833     /*
1834      * Manage only the needed menu items; hide/unmanage the rest
1835      */
1836     if (num_items_needed > 0)
1837     {
1838         for (i = 0; i < num_items_needed; ++i)
1839             XtManageChild(menu_children[i]);
1840
1841         for (i = num_items_needed; i < num_menu_children; ++i)
1842             XtUnmanageChild(menu_children[i]);
1843     }
1844
1845     /*
1846      * Special case:
1847      * If no siblings, create/manage one item with "None" label.
1848      */
1849     if (num_items_needed == 0)
1850     {
1851         Widget  none_item;
1852
1853         if (num_menu_children == 0)
1854         {
1855             none_item = XtVaCreateWidget("attach_obj_menu", 
1856                         xmPushButtonWidgetClass, 
1857                         widget, 
1858                         NULL);
1859         }
1860         else
1861         {
1862             none_item = menu_children[0];
1863         }
1864
1865         XtVaSetValues(none_item,
1866                         XtVaTypedArg, XmNlabelString, XtRString, 
1867                         "None", strlen("None")+1,
1868                         XmNuserData, NULL,
1869                         NULL);
1870
1871         XtManageChild(none_item);
1872     }
1873
1874     *ret_item = item_list;
1875     *ret_item_val = item_val_list;
1876     *n = num_items_needed;
1877 }
1878
1879
1880 static BOOL
1881 attch_objlist_test_func(
1882     ABObj       test_obj
1883 )
1884 {
1885     ABObj       module;
1886     BOOL        b;
1887
1888     if (!test_obj || !obj_is_defined(test_obj))
1889         return (False);
1890
1891     module = obj_get_module(test_obj);
1892
1893     if ((module != NULL) &&
1894             obj_is_salient_ui(test_obj) && 
1895             obj_has_flag(module, MappedFlag))
1896     {   
1897         b = attch_ed_obj_is_target_type(test_obj);
1898         return(b);
1899     }
1900     return(False);
1901 }
1902
1903 static BOOL
1904 attch_ed_obj_is_target_type(
1905     ABObj obj
1906 )
1907 {
1908     PalItemInfo         *palitem;
1909     AB_OBJECT_TYPE      type;
1910     int                 subtype;
1911
1912     if (!obj)
1913         return (FALSE);
1914
1915     type = obj_get_type(obj);
1916     subtype = obj_get_subtype(obj);
1917
1918     palitem = pal_get_type_item_info(AttchEdObjTypeInfo.type, 
1919                         AttchEdObjTypeInfo.subtype);
1920
1921     if (palitem && palitem->is_a_test)
1922         return ((*palitem->is_a_test)(obj));
1923
1924     switch (AttchEdObjTypeInfo.type)
1925     {
1926         case AB_TYPE_ITEM:
1927         case AB_TYPE_CONTAINER:
1928             if (type == AttchEdObjTypeInfo.type &&
1929                     subtype == AttchEdObjTypeInfo.subtype)
1930                 return(TRUE);
1931             else 
1932                 return(FALSE);
1933         break;
1934
1935         default:
1936             /* 
1937              * Otherwise we only need to check object type, and in fact 
1938              * don't want to check subtype because it might confuse things 
1939              * (e.g. we're looking for any Button palette item, which 
1940              * includes several subtypes of type AB_TYPE_BUTTON).
1941              */
1942             if(type == AttchEdObjTypeInfo.type) 
1943                 return(TRUE);
1944             else 
1945                 return(FALSE);
1946         break;
1947     }
1948
1949
1950     /* Should never get here - every test above returns True or False */
1951 }
1952
1953 static BOOL
1954 attch_childrenlist_test_func(
1955     ABObj       test_obj
1956 )
1957 {
1958     if (!test_obj || !attch_cur_parent)
1959         return (False);
1960
1961     if (attch_ed_get_parent(test_obj) == attch_cur_parent)
1962         return (True);
1963
1964     return(False);
1965 }
1966
1967 /*
1968  * Callback: a new object type has been selected off object type menu
1969  * This is for 'regular' palette objects
1970  */
1971 static void
1972 attch_change_objecttypePalCB(
1973     Widget      widget,
1974     XtPointer   client_data,
1975     XtPointer   calldata
1976 )
1977 {
1978     PalEditableObjInfo  *ed_obj_info = (PalEditableObjInfo*)client_data;
1979
1980     attch_ed_change_objecttype(ed_obj_info->type, ed_obj_info->subtype);
1981 }
1982
1983
1984 static void
1985 attch_ed_change_objecttype(
1986     AB_OBJECT_TYPE      type,
1987     int                 subtype
1988 )
1989 {
1990     DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
1991     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
1992     ABObj                       proj = proj_get_project();
1993     int                         num_items;
1994     char                        *modname = NULL;
1995     DTB_MODAL_ANSWER            answer = DTB_ANSWER_ACTION1;
1996
1997     if (!proj || !attch_ed_cgen->objlist)
1998         return;
1999
2000     if (attch_edP_pending()) 
2001     {
2002         answer = get_wrn_response(AB_attch_ed_dialog, ATTCH_ED_WRN_CHANGE_OBJTYPE,
2003                                 NULL);
2004
2005         if (answer == DTB_ANSWER_CANCEL)
2006             update_obj_type(ats->cur_object);
2007     }
2008
2009     if (answer != DTB_ANSWER_ACTION1)
2010         return;
2011
2012     /*
2013      * Reset current object
2014      */
2015     ats->cur_object = NULL;
2016
2017     AttchEdObjTypeInfo.type = type;
2018     AttchEdObjTypeInfo.subtype = subtype;
2019
2020     num_items = abobj_list_load(attch_ed_cgen->objlist, proj, attch_objlist_test_func);
2021
2022     /*
2023      * If number of items in object list is > 0,
2024      * make attachment editor active and edit the
2025      * first object in list the current one.
2026      * Otherwise, make editor inactive.
2027      */
2028     if (num_items > 0)
2029     {
2030         attch_editor_activate(TRUE);
2031         ui_list_select_pos(attch_ed_cgen->objlist, 1, TRUE);
2032     }
2033     else
2034     {
2035         attch_editor_activate(FALSE);
2036     }
2037 }
2038
2039 static void
2040 attch_objlist_selectCB(
2041     Widget      widget,
2042     XtPointer   client_data,
2043     XmListCallbackStruct *listdata
2044 )
2045 {
2046     ABObj               module;
2047     ABObj               selected_obj;
2048     STRING              name;
2049  
2050     name = objxm_xmstr_to_str(listdata->item);
2051     if (name)
2052     {
2053         abobj_moduled_name_extract(name, &module, &selected_obj);
2054         util_free(name);
2055
2056         if (selected_obj)
2057         {
2058             AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
2059             DTB_MODAL_ANSWER            answer = DTB_ANSWER_ACTION1;
2060             ABObj       parent;
2061             Widget      parent_widget;
2062             char        *name = obj_get_name(selected_obj);
2063
2064             if (attch_edP_pending()) 
2065             {
2066                 answer = get_wrn_response(AB_attch_ed_dialog, 
2067                                 ATTCH_ED_WRN_LOAD, selected_obj);
2068
2069                 if (answer == DTB_ANSWER_CANCEL)
2070                     select_objlist(ats->cur_object);
2071             }
2072
2073             if (answer != DTB_ANSWER_ACTION1)
2074                 return;
2075
2076             /*
2077              * Load selected object
2078              */
2079             load_attch_obj(selected_obj, TRUE);
2080
2081             /*
2082              * If load succeeded, create new children list,
2083              * and update parent label
2084             if (ats->cur_object) {
2085              */
2086                 create_children_list(selected_obj);
2087                 update_attch_obj_parent(selected_obj);
2088             /*
2089             }
2090             */
2091         }
2092     }
2093 }
2094
2095 static int
2096 attch_obj_geom_changedCB(
2097     ObjEvAttChangeInfo evInfo
2098 )
2099 {
2100     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
2101     ABObj                       obj = evInfo->obj;
2102
2103     if (!obj)
2104         return 0;
2105
2106     /*
2107      * Do only if position or size changed
2108      */
2109     if ((evInfo->atts & OBJEV_ATT_POSITION) ||
2110         (evInfo->atts & OBJEV_ATT_SIZE))
2111     {
2112         if (ats->cur_object == obj)
2113         {
2114             /*
2115              * Reload attachments of object into attachments editor,
2116              * keep changebars state as-is
2117              */
2118             load_attch_obj(obj, FALSE);
2119         }
2120     }
2121
2122     return 0;
2123 }
2124
2125
2126 static int
2127 attch_obj_destroyCB(
2128     ObjEvDestroyInfo info
2129 )
2130 {
2131     handle_actual_obj_destroy(info);
2132     handle_prop_sheet_obj_destroy(info);
2133
2134     return (0);
2135 }
2136
2137 static int
2138 attch_obj_reparentCB(
2139     ObjEvReparentInfo info
2140 )
2141 {
2142     handle_actual_obj_reparent(info);
2143     handle_prop_sheet_obj_reparent(info);
2144
2145     return (0);
2146 }
2147
2148
2149 static void
2150 handle_prop_sheet_obj_destroy(
2151     ObjEvDestroyInfo info
2152 )
2153 {
2154     DtbAttchEdAttchEdDialogInfo attch_ed_cgen 
2155                         = &dtb_attch_ed_attch_ed_dialog;
2156     AttchEditorSettingsRec              *ats 
2157                         = &attch_editor_settings_rec;
2158     ABObj       obj = info->obj;
2159     int         num_items, first_viz, last_viz;
2160
2161     if (!AB_attch_ed_dialog ||
2162         !obj_is_salient(obj) || obj_is_item(obj) || !ats->cur_object)
2163         return;
2164
2165     /*
2166      * Update object list only if the renamed object is the same
2167      * type as the one that is currently visible.
2168      */
2169     abobj_list_obj_destroyed(attch_ed_cgen->objlist, obj, 
2170                                         attch_objlist_test_func);
2171
2172     ui_list_get_info(attch_ed_cgen->objlist, &num_items, &first_viz, &last_viz);
2173
2174     if (num_items == 0)
2175     {
2176         /*
2177          * Deleted last item
2178          * Reset current object and inactivate editor
2179          */
2180         ats->cur_object = NULL;
2181         attch_editor_activate(FALSE);
2182     }
2183     else if (obj == ats->cur_object)
2184     {
2185         /*
2186          * Delete current object
2187          * Select 1st item in list, and make it the edited object
2188          */
2189         ui_list_select_pos(attch_ed_cgen->objlist, 1, TRUE);
2190     }
2191     else if (obj_is_sibling(obj, ats->cur_object))
2192     {
2193         /*
2194          * Sibling of current object deleted
2195          * Update attached object - to keep the sibling list option menu
2196          * current.
2197          * Update children list.
2198          * enable/disable sibling attachment types
2199          *
2200          * NOTE: should check if the object deleted is an 'attached-to' object.
2201          *
2202          * REMIND: create_children_list() loads the list 
2203          * Should manipulate the children list with the abobj_list_obj_destroyed()
2204          * API. Currently, it is loaded directly using the trav API.
2205         load_attch_obj(ats->cur_object, TRUE);
2206          */
2207         delete_from_obj_menu(ats->cur_object, obj);
2208         create_children_list(ats->cur_object);
2209         enable_attach_types(ats->cur_object);
2210     }
2211
2212 }
2213
2214 static void
2215 handle_actual_obj_destroy(
2216     ObjEvDestroyInfo info
2217 )
2218 {
2219     ABObjList           refList;
2220     ABObj               obj,
2221                         refObj,
2222                         project;
2223     void                *voidRefType = NULL;
2224     AB_OBJ_REF_TYPE     refType = AB_REF_UNDEF;
2225     ABAttachment        *attachment;
2226     ATTCH_ED_ATTACH_TYPE        attach_type;
2227     AB_COMPASS_POINT    dir;
2228     int                 i,
2229                         numRefs,
2230                         offset,
2231                         position;
2232     
2233     if (!info)
2234         return;
2235
2236     obj = info->obj;
2237
2238     if (!(project = obj_get_project(obj)))
2239         return;
2240
2241     /*
2242      * If the entire project is curently being destroyed,
2243      * skip this
2244      */
2245     if (obj_has_flag(project, BeingDestroyedFlag))
2246         return;
2247
2248     if (!attch_ed_can_edit_attachments(obj))
2249         return;
2250
2251     refList = obj_get_refs_to(obj);
2252
2253     if (!refList)
2254         return;
2255     
2256     numRefs = objlist_get_num_objs(refList);
2257     for (i = 0; i < numRefs; ++i)
2258     {
2259         BOOL    attach_ref;
2260
2261         refObj = objlist_get_obj(refList, i, &voidRefType);
2262
2263         if (!refObj || obj_is_descendant_of(refObj, obj))
2264             continue;
2265
2266         refType = (AB_OBJ_REF_TYPE)voidRefType;
2267
2268         switch (refType)
2269         {
2270             /*
2271              * The ref object may have different attachments to
2272              * 'obj'
2273              */
2274             case AB_REF_ATTACH_EAST:
2275             case AB_REF_ATTACH_NORTH:
2276             case AB_REF_ATTACH_SOUTH:
2277             case AB_REF_ATTACH_WEST:
2278                 attach_ref = TRUE;
2279                 break;
2280             default:
2281                 attach_ref = FALSE;
2282                 break;
2283         }
2284
2285         if (attach_ref)
2286         {
2287             /*
2288              * If there are any attachments from this object that involve 
2289              * 'obj', change them to AB_ATTACH_POINT
2290              */
2291             change_attype_from_sib_to_point(refObj, obj, AB_CP_NORTH, FALSE);
2292             change_attype_from_sib_to_point(refObj, obj, AB_CP_SOUTH, FALSE);
2293             change_attype_from_sib_to_point(refObj, obj, AB_CP_EAST, FALSE);
2294             change_attype_from_sib_to_point(refObj, obj, AB_CP_WEST, FALSE);
2295
2296         }
2297     }
2298 }
2299
2300
2301 static void     
2302 handle_prop_sheet_obj_reparent(
2303     ObjEvReparentInfo info
2304 )
2305 {
2306     DtbAttchEdAttchEdDialogInfo attch_ed_cgen 
2307                         = &dtb_attch_ed_attch_ed_dialog;
2308     AttchEditorSettingsRec              *ats 
2309                         = &attch_editor_settings_rec;
2310     ABObj       obj = info->obj;
2311     int         num_items, first_viz, last_viz;
2312
2313     if (!AB_attch_ed_dialog ||
2314         !obj_is_salient(obj) || obj_is_item(obj) || !ats->cur_object)
2315         return;
2316 }
2317
2318 static void
2319 change_attype_from_sib_to_point(
2320     ABObj               obj,
2321     ABObj               attach_to_sib,
2322     AB_COMPASS_POINT    dir,
2323     BOOL                reparent
2324 )
2325 {
2326     ABAttachment        *attachment;
2327     AB_ATTACH_TYPE      attach_type;
2328
2329     attachment = obj_get_attachment(obj, dir);
2330
2331     if (!attachment)
2332         return;
2333
2334     attach_type = obj_get_attach_type(obj, dir);
2335
2336     if ((attach_type == AB_ATTACH_OBJ) || 
2337         (attach_type == AB_ATTACH_ALIGN_OBJ_EDGE))
2338     {
2339         ABObj   attach_obj;
2340         int     offset,
2341                 position;
2342     
2343         /*
2344          * Get sibling obj that this object is attached to
2345          */
2346         attach_obj = (ABObj)obj_get_attach_value(obj, dir);
2347
2348         /*
2349          * Do not convert attachment type if:
2350          *      attach_obj == object (attach to itself)
2351          *      
2352          */
2353         if (!attach_obj || (obj == attach_obj))
2354             return;
2355
2356         /*
2357          * If the triggering event was a reparent, and
2358          * obj and attach_obj are still siblings, do not
2359          * convert
2360          */
2361         if (reparent && obj_is_sibling(obj, attach_obj))
2362             return;
2363
2364         /*
2365          * If a specific sibling was passed in, make sure
2366          * attach_obj matches it. If not, do not convert.
2367          */
2368         if (attach_to_sib && (attach_to_sib != attach_obj))
2369             return;
2370
2371         convert_offset_position(obj, NULL, dir, ATTCH_ED_PARENT,
2372                         &offset, &position);
2373         
2374         obj_set_attachment(obj, dir, AB_ATTACH_POINT, 
2375                             (void *)position, offset);
2376         objxm_obj_set_attachment_args(obj, OBJXM_CONFIG_BUILD);
2377     }
2378 }
2379
2380 static void     
2381 handle_actual_obj_reparent(
2382     ObjEvReparentInfo info
2383 )
2384 {
2385     ABObjList           refList;
2386     ABObj               obj,
2387                         refObj,
2388                         parent;
2389     void                *voidRefType = NULL;
2390     AB_OBJ_REF_TYPE     refType = AB_REF_UNDEF;
2391     ABAttachment        *attachment;
2392     ATTCH_ED_ATTACH_TYPE        attach_type;
2393     AB_COMPASS_POINT    dir;
2394     int                 i,
2395                         numRefs,
2396                         offset,
2397                         position;
2398     
2399     if (!info)
2400         return;
2401     
2402     obj = info->obj;
2403
2404     /*
2405      * name == NULL
2406      * -> New object dragged off from palette
2407      * Don't need to worry about attachments here
2408      */
2409     if (obj_get_name(obj) == NULL)
2410         return;
2411
2412     /*
2413      * The old parent is NULL
2414      * Don't need to worry about attachments here
2415      */
2416     if (!info->old_parent)
2417         return;
2418
2419     if (!attch_ed_can_edit_attachments(obj))
2420         return;
2421
2422     /*
2423      * If there are any attachments from this object that involve 
2424      * sibling objects, change them to AB_ATTACH_POINT
2425      */
2426     change_attype_from_sib_to_point(obj, NULL, AB_CP_NORTH, TRUE);
2427     change_attype_from_sib_to_point(obj, NULL, AB_CP_SOUTH, TRUE);
2428     change_attype_from_sib_to_point(obj, NULL, AB_CP_EAST, TRUE);
2429     change_attype_from_sib_to_point(obj, NULL, AB_CP_WEST, TRUE);
2430
2431     /*
2432      * If there are attachments *to* this object, change them
2433      * to AB_ATTACH_POINT
2434      */
2435     refList = obj_get_refs_to(obj);
2436
2437     if (!refList)
2438         return;
2439     
2440     numRefs = objlist_get_num_objs(refList);
2441     for (i = 0; i < numRefs; ++i)
2442     {
2443         BOOL    attach_ref;
2444
2445         refObj = objlist_get_obj(refList, i, &voidRefType);
2446
2447         if (!refObj || obj_is_descendant_of(refObj, obj))
2448             continue;
2449
2450         refType = (AB_OBJ_REF_TYPE)voidRefType;
2451
2452         switch (refType)
2453         {
2454             /*
2455              * The ref object may have different attachments to
2456              * 'obj'
2457              */
2458             case AB_REF_ATTACH_EAST:
2459             case AB_REF_ATTACH_NORTH:
2460             case AB_REF_ATTACH_SOUTH:
2461             case AB_REF_ATTACH_WEST:
2462                 attach_ref = TRUE;
2463                 break;
2464             default:
2465                 attach_ref = FALSE;
2466                 break;
2467         }
2468
2469         if (attach_ref)
2470         {
2471             /*
2472              * If there are any attachments from this object that involve 
2473              * 'obj', change them to AB_ATTACH_POINT
2474              */
2475             change_attype_from_sib_to_point(refObj, obj, AB_CP_NORTH, TRUE);
2476             change_attype_from_sib_to_point(refObj, obj, AB_CP_SOUTH, TRUE);
2477             change_attype_from_sib_to_point(refObj, obj, AB_CP_EAST, TRUE);
2478             change_attype_from_sib_to_point(refObj, obj, AB_CP_WEST, TRUE);
2479         }
2480     }
2481 }
2482
2483
2484 static int
2485 attch_obj_renameCB(
2486     ObjEvAttChangeInfo info
2487 )
2488 {
2489     DtbAttchEdAttchEdDialogInfo attch_ed_cgen 
2490                         = &dtb_attch_ed_attch_ed_dialog;
2491     AttchEditorSettingsRec              *ats 
2492                         = &attch_editor_settings_rec;
2493     ABObj       obj = info->obj,
2494                 root_parent;
2495
2496     if (!AB_attch_ed_dialog || 
2497         !obj_is_salient(obj) || obj_is_item(obj) || !ats->cur_object)
2498         return (0);
2499
2500     if (obj_is_module(obj))
2501     {
2502         if ((obj_get_module(ats->cur_object) == obj_get_module(obj)))
2503         {
2504             abobj_list_obj_renamed(attch_ed_cgen->objlist, 
2505                         obj, 
2506                         istr_string(info->old_name),
2507                         attch_objlist_test_func);
2508         }
2509     }
2510     else
2511     {
2512         /*
2513          * Update object list only if the renamed object is the same
2514          * type as the one that is currently visible.
2515          */
2516         abobj_list_obj_renamed(attch_ed_cgen->objlist, 
2517                         obj, 
2518                         istr_string(info->old_name),
2519                         attch_objlist_test_func);
2520
2521         /*
2522          * Update/reload attached object if:
2523          *      the attached object was renamed
2524          *      any of the attached object's siblings got renamed
2525          */
2526         if ((obj == ats->cur_object) || obj_is_sibling(obj, ats->cur_object))
2527         {
2528             /*
2529              * REMIND: load_attch_obj() loads the list 
2530              * Should manipulate the children list with the 
2531              * abobj_list_obj_renamed() API. Currently, it is loaded 
2532              * directly using the trav API.
2533              */
2534             load_attch_obj(ats->cur_object, TRUE);
2535             create_children_list(ats->cur_object);
2536             enable_attach_types(ats->cur_object);
2537         }
2538
2539         root_parent = attch_ed_get_parent(ats->cur_object);
2540         if (root_parent)
2541             root_parent = obj_get_root(root_parent);
2542
2543         /*
2544          * If current object's parent is renamed, update
2545          * parent object label
2546          */
2547         if (obj == root_parent)
2548         {
2549             update_attch_obj_parent(ats->cur_object);
2550         }
2551     }
2552
2553     return 0;
2554 }
2555
2556 static void
2557 set_widget_state(
2558     ATTCH_ED_ATTACH_TYPE        attach_type,
2559     Widget                      objlist,
2560     Widget                      offset,
2561     Widget                      position
2562 )
2563 {
2564     if (!objlist || !offset || !position)
2565         return;
2566
2567     switch(attach_type)
2568     {
2569         case ATTCH_ED_PARENT:
2570         case ATTCH_ED_OPPOSITE_PARENT:
2571             ui_set_active(objlist, False);
2572             ui_set_active(offset, True);
2573             ui_set_active(position, False);
2574         break;
2575
2576         case ATTCH_ED_SIBLING:
2577         case ATTCH_ED_OPPOSITE_SIBLING:
2578             ui_set_active(objlist, True);
2579             ui_set_active(offset, True);
2580             ui_set_active(position, False);
2581         break;
2582
2583         case ATTCH_ED_GRIDLINE:
2584             ui_set_active(objlist, False);
2585             ui_set_active(offset, True);
2586             ui_set_active(position, True);
2587         break;
2588
2589         case ATTCH_ED_CENTER_GRIDLINE:
2590             ui_set_active(objlist, False);
2591             ui_set_active(offset, False);
2592             ui_set_active(position, True);
2593         break;
2594
2595         case ATTCH_ED_NONE:
2596             ui_set_active(objlist, False);
2597             ui_set_active(offset, False);
2598             ui_set_active(position, False);
2599         break;
2600     }
2601 }
2602
2603
2604 static void     
2605 enable_attach_types(
2606     ABObj       obj
2607 )
2608 {
2609     DtbAttchEdAttchEdDialogInfo attch_ed_cgen 
2610                         = &dtb_attch_ed_attch_ed_dialog;
2611     AttchEditorSettingsRec      *ats 
2612                         = &attch_editor_settings_rec;
2613     ABObj                       parent;
2614     BOOL                        state = FALSE;
2615     int                         child_count;
2616
2617     if (!obj)
2618         return;
2619     
2620     parent = attch_ed_get_parent(obj);
2621     child_count = parent ? trav_count(parent, AB_TRAV_SALIENT_CHILDREN)
2622                          : 0;
2623
2624     /*
2625      * If this object has siblings, enable attach sibling
2626      * option menu items
2627      */
2628     if (child_count > 1)
2629         state = TRUE;
2630
2631     /* left attachment */
2632     ui_set_active(attch_ed_cgen->left_attach_items.bitmaps_attach_left_widget_xbm_item,
2633                         state);
2634     ui_set_active(attch_ed_cgen->left_attach_items.bitmaps_attach_left_opposite_widget_xbm_item,
2635                         state);
2636
2637     /* right attachment */
2638     ui_set_active(attch_ed_cgen->right_attach_items.bitmaps_attach_right_widget_xbm_item,
2639                         state);
2640     ui_set_active(attch_ed_cgen->right_attach_items.bitmaps_attach_right_opposite_widget_xbm_item,
2641                         state);
2642
2643     /* top attachment */
2644     ui_set_active(attch_ed_cgen->top_attach_items.bitmaps_attach_top_widget_xbm_item,
2645                         state);
2646     ui_set_active(attch_ed_cgen->top_attach_items.bitmaps_attach_top_opposite_widget_xbm_item,
2647                         state);
2648
2649     /* bottom attachment */
2650     ui_set_active(attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_widget_xbm_item,
2651                         state);
2652     ui_set_active(attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_opposite_widget_xbm_item,
2653                         state);
2654 }
2655
2656 static void
2657 set_attach_values(
2658     ATTCH_ED_ATTACH_TYPE        attach_type,
2659     PropFieldSetting            offset_setting,
2660     PropFieldSetting            position_setting,
2661     PropOptionsSetting          objlist_setting,
2662     int                         offset_value,
2663     int                         position_value,
2664     int                         objlist_value
2665 )
2666 {
2667     switch (attach_type)
2668     {
2669         case ATTCH_ED_PARENT:
2670             prop_field_set_numeric_value(offset_setting, offset_value, False);
2671         break;
2672
2673         case ATTCH_ED_OPPOSITE_PARENT:
2674             prop_field_set_numeric_value(offset_setting, offset_value, False);
2675         break;
2676
2677         case ATTCH_ED_SIBLING:
2678             prop_field_set_numeric_value(offset_setting, offset_value, False);
2679             prop_options_set_value(objlist_setting, (XtPointer)objlist_value, False);
2680         break;
2681
2682         case ATTCH_ED_OPPOSITE_SIBLING:
2683             prop_field_set_numeric_value(offset_setting, offset_value, False);
2684             prop_options_set_value(objlist_setting, (XtPointer)objlist_value, False);
2685         break;
2686
2687         case ATTCH_ED_GRIDLINE:
2688             prop_field_set_numeric_value(offset_setting, offset_value, False);
2689             prop_field_set_numeric_value(position_setting, position_value, False);
2690         break;
2691
2692         case ATTCH_ED_CENTER_GRIDLINE:
2693             prop_field_set_numeric_value(position_setting, position_value, False);
2694         break;
2695
2696         case ATTCH_ED_NONE:
2697         break;
2698     }
2699 }
2700
2701 static void
2702 get_attach_values(
2703     ATTCH_ED_ATTACH_TYPE        attach_type,
2704     PropFieldSetting            offset_setting,
2705     PropFieldSetting            position_setting,
2706     PropOptionsSetting          objlist_setting,
2707     int                         *offset_value,
2708     int                         *position_value,
2709     XtPointer                   *objlist_value
2710 )
2711 {
2712     switch (attach_type)
2713     {
2714         case ATTCH_ED_PARENT:
2715             *offset_value = prop_field_get_numeric_value(offset_setting);
2716         break;
2717
2718         case ATTCH_ED_OPPOSITE_PARENT:
2719             *offset_value = prop_field_get_numeric_value(offset_setting);
2720         break;
2721
2722         case ATTCH_ED_SIBLING:
2723             *offset_value = prop_field_get_numeric_value(offset_setting);
2724             *objlist_value = prop_options_get_value(objlist_setting);
2725         break;
2726
2727         case ATTCH_ED_OPPOSITE_SIBLING:
2728             *offset_value = prop_field_get_numeric_value(offset_setting);
2729             *objlist_value = prop_options_get_value(objlist_setting);
2730         break;
2731
2732         case ATTCH_ED_GRIDLINE:
2733             *offset_value = prop_field_get_numeric_value(offset_setting);
2734             *position_value = prop_field_get_numeric_value(position_setting);
2735         break;
2736
2737         case ATTCH_ED_CENTER_GRIDLINE:
2738             *position_value = prop_field_get_numeric_value(position_setting);
2739         break;
2740
2741         case ATTCH_ED_NONE:
2742         break;
2743     }
2744 }
2745
2746
2747 static void     
2748 convert_offset_position(
2749     ABObj                       cur_obj,
2750     ABObj                       sibling_obj,
2751     AB_COMPASS_POINT            dir,
2752     ATTCH_ED_ATTACH_TYPE        attach_type,
2753     int                         *ret_offset,
2754     int                         *ret_position
2755 )
2756 {
2757     Widget      cur_widget,
2758                 sibling_widget,
2759                 parent_widget;
2760     ABObj       parent_obj;
2761     Position    x = 0,
2762                 y = 0,
2763                 p_x = 0,
2764                 p_y = 0,
2765                 s_x = 0,
2766                 s_y = 0;
2767     Dimension   width = 0,
2768                 height = 0,
2769                 p_width = 0,
2770                 p_height = 0,
2771                 s_width = 0,
2772                 s_height = 0;
2773     int         fraction_base = 100,
2774                 offset_value = 0,
2775                 position_value = 0;
2776
2777     if (!cur_obj || !ret_offset || !ret_position)
2778         return;
2779
2780     /*
2781     parent_obj = attch_ed_get_parent(cur_obj);
2782     */
2783     parent_obj = obj_get_parent(cur_obj);
2784
2785     *ret_offset = *ret_position = 0;
2786
2787     if (!parent_obj)
2788         return;
2789
2790     cur_widget = objxm_get_widget(cur_obj);
2791     parent_widget = objxm_get_widget(parent_obj);
2792
2793     if (!cur_widget || !parent_widget)
2794         return;
2795
2796     XtVaGetValues(cur_widget,
2797         XmNx,           &x,
2798         XmNy,           &y,
2799         XmNwidth,       &width,
2800         XmNheight,      &height,
2801         NULL);
2802
2803     XtVaGetValues(parent_widget,
2804         XmNx,           &p_x,
2805         XmNy,           &p_y,
2806         XmNwidth,       &p_width,
2807         XmNheight,      &p_height,
2808         XmNfractionBase,&fraction_base,
2809         NULL);
2810
2811     if (attch_ed_need_obj_menu(attach_type))
2812     {
2813         if (!sibling_obj)
2814             return;
2815
2816         sibling_widget = objxm_get_widget(sibling_obj);
2817
2818         if (!sibling_widget)
2819             return;
2820
2821         XtVaGetValues(sibling_widget,
2822             XmNx,               &s_x,
2823             XmNy,               &s_y,
2824             XmNwidth,   &s_width,
2825             XmNheight,  &s_height,
2826             NULL);
2827     }
2828
2829     switch (dir)
2830     {
2831         case AB_CP_WEST:
2832             switch(attach_type)
2833             {
2834                 case ATTCH_ED_PARENT:
2835                     offset_value = (int)x;
2836                 break;
2837
2838                 case ATTCH_ED_OPPOSITE_PARENT:
2839                     offset_value = (int)(- ((int)p_width - (int)x));
2840                 break;
2841
2842                 case ATTCH_ED_SIBLING:
2843                     offset_value = (int)((int)x - ((int)s_x + (int)s_width));
2844                 break;
2845
2846                 case ATTCH_ED_OPPOSITE_SIBLING:
2847                     offset_value = (int)x - (int)s_x;
2848                 break;
2849
2850                 case ATTCH_ED_GRIDLINE:
2851                     position_value = (fraction_base * (int)x)/(int)p_width;
2852                 break;
2853
2854                 case ATTCH_ED_CENTER_GRIDLINE:
2855                     position_value = 
2856                         (fraction_base * ((int)x + ((int)width/2)))/(int)p_width;
2857                 break;
2858
2859                 case ATTCH_ED_NONE:
2860                 break;
2861             }
2862             break;
2863
2864         case AB_CP_EAST:
2865             switch(attach_type)
2866             {
2867                 case ATTCH_ED_PARENT:
2868                     offset_value = (int)p_width - ((int)x + (int)width);
2869                 break;
2870
2871                 case ATTCH_ED_OPPOSITE_PARENT:
2872                     offset_value = (int)(- ((int)p_width - ((int)x + (int)width)));
2873                 break;
2874
2875                 case ATTCH_ED_SIBLING:
2876                     offset_value = (int)s_x - ((int)x + (int)width);
2877                 break;
2878
2879                 case ATTCH_ED_OPPOSITE_SIBLING:
2880                     offset_value = ((int)s_x + (int)s_width) - ((int)x + (int)width);
2881                 break;
2882
2883                 case ATTCH_ED_GRIDLINE:
2884                     position_value = (fraction_base * ((int)x + (int)width))/(int)p_width;
2885                 break;
2886
2887                 case ATTCH_ED_CENTER_GRIDLINE:
2888                     position_value = 
2889                         (fraction_base * ((int)x + ((int)width/2)))/(int)p_width;
2890                 break;
2891
2892                 case ATTCH_ED_NONE:
2893                 break;
2894             }
2895             break;
2896
2897         case AB_CP_NORTH:
2898             switch(attach_type)
2899             {
2900                 case ATTCH_ED_PARENT:
2901                     offset_value = (int)y;
2902                 break;
2903
2904                 case ATTCH_ED_OPPOSITE_PARENT:
2905                     offset_value = (int)(- ((int)p_height - (int)y));
2906                 break;
2907
2908                 case ATTCH_ED_SIBLING:
2909                     offset_value = (int)y - ((int)s_y + (int)s_height);
2910                 break;
2911
2912                 case ATTCH_ED_OPPOSITE_SIBLING:
2913                     offset_value = (int)y - (int)s_y;
2914                 break;
2915
2916                 case ATTCH_ED_GRIDLINE:
2917                     position_value = (fraction_base * (int)y)/(int)p_height;
2918                 break;
2919
2920                 case ATTCH_ED_CENTER_GRIDLINE:
2921                     position_value = 
2922                         (fraction_base * ((int)y + ((int)height/2)))/(int)p_height;
2923                 break;
2924
2925                 case ATTCH_ED_NONE:
2926                 break;
2927             }
2928             break;
2929
2930         case AB_CP_SOUTH:
2931             switch(attach_type)
2932             {
2933                 case ATTCH_ED_PARENT:
2934                     offset_value = (int)p_height - ((int)y + (int)height);
2935                 break;
2936
2937                 case ATTCH_ED_OPPOSITE_PARENT:
2938                     offset_value = - ((int)y + (int)height);
2939                 break;
2940
2941                 case ATTCH_ED_SIBLING:
2942                     offset_value = (int)s_y - ((int)y + (int)height);
2943                 break;
2944
2945                 case ATTCH_ED_OPPOSITE_SIBLING:
2946                     offset_value = ((int)s_y + (int)s_height) - ((int)y + (int)height);
2947                 break;
2948
2949                 case ATTCH_ED_GRIDLINE:
2950                     position_value = (fraction_base * ((int)y + (int)height))/(int)p_height;
2951                 break;
2952
2953                 case ATTCH_ED_CENTER_GRIDLINE:
2954                     position_value = 
2955                         (fraction_base * ((int)y + ((int)height/2)))/(int)p_height;
2956                 break;
2957
2958                 case ATTCH_ED_NONE:
2959                 break;
2960             }
2961             break;
2962     }
2963
2964     /*
2965     set_attach_values(attach_type, 
2966                 offset_setting, position_setting, objlist_setting, 
2967                 offset_value, position_value, (int)sibling_obj);
2968     */
2969     
2970     *ret_offset = offset_value;
2971     *ret_position = position_value;
2972 }
2973
2974
2975 /*
2976  * Attachment type has changed. Figure out (and set) the
2977  * new 'fields' of this attachment i.e.
2978  *      offset
2979  *      position
2980  *      attached object
2981  */
2982 static void     
2983 change_attach_type(
2984     ABObj                       obj,
2985     AB_COMPASS_POINT            dir,
2986     ATTCH_ED_ATTACH_TYPE        attach_type
2987 )
2988 {
2989     DtbAttchEdAttchEdDialogInfo attch_ed_cgen
2990                             = &dtb_attch_ed_attch_ed_dialog;
2991     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
2992     ABAttachment                *attachment;
2993     int                         offset,
2994                                 position;
2995     ABObj                       attach_obj = NULL;
2996     PropOptionsSetting          objlist_setting = NULL;
2997     PropFieldSetting            offset_setting = NULL,
2998                                 position_setting = NULL;
2999     Widget                      objlist_w = NULL,
3000                                 offset_w = NULL,
3001                                 position_w = NULL;
3002
3003     /*
3004      * Based on 'dir', figure out which setting structures and
3005      * widgets are relevant.
3006      */
3007     switch (dir)
3008     {
3009         case AB_CP_WEST:
3010             offset_setting = &(ats->left_attach_offset);
3011             position_setting = &(ats->left_attach_position);
3012             objlist_setting = &(ats->left_attach_obj);
3013
3014             objlist_w = attch_ed_cgen->left_attach_objmenu;
3015             offset_w = attch_ed_cgen->left_offset_rowcolumn;
3016             position_w = attch_ed_cgen->left_position_rowcolumn;
3017         break;
3018
3019         case AB_CP_EAST:
3020             offset_setting = &(ats->right_attach_offset);
3021             position_setting = &(ats->right_attach_position);
3022             objlist_setting = &(ats->right_attach_obj);
3023
3024             objlist_w = attch_ed_cgen->right_attach_objmenu;
3025             offset_w = attch_ed_cgen->right_offset_rowcolumn;
3026             position_w = attch_ed_cgen->right_position_rowcolumn;
3027         break;
3028
3029         case AB_CP_NORTH:
3030             offset_setting = &(ats->top_attach_offset);
3031             position_setting = &(ats->top_attach_position);
3032             objlist_setting = &(ats->top_attach_obj);
3033
3034             objlist_w = attch_ed_cgen->top_attach_objmenu;
3035             offset_w = attch_ed_cgen->top_offset_rowcolumn;
3036             position_w = attch_ed_cgen->top_position_rowcolumn;
3037         break;
3038
3039         case AB_CP_SOUTH:
3040             offset_setting = &(ats->bottom_attach_offset);
3041             position_setting = &(ats->bottom_attach_position);
3042             objlist_setting = &(ats->bottom_attach_obj);
3043
3044             objlist_w = attch_ed_cgen->bottom_attach_objmenu;
3045             offset_w = attch_ed_cgen->bottom_offset_rowcolumn;
3046             position_w = attch_ed_cgen->bottom_position_rowcolumn;
3047         break;
3048     }
3049
3050     /*
3051      * If any of the settings/widgets cannot be determined, return
3052      * immediately
3053      */
3054     if (!offset_setting || !position_setting || !objlist_setting ||
3055         !objlist_w || !offset_w || !position_w)
3056         return;
3057
3058     /*
3059      * Set the (in)active state of the fields:
3060      *  object option menu
3061      *  offset
3062      *  percentage/position
3063      * depending on what the attachment type is
3064      */
3065     set_widget_state(attach_type,
3066                 objlist_w, offset_w, position_w);
3067
3068     /*
3069      * If the attachment type requires a sibling object,
3070      * make sure object option menu is current. Get
3071      * default/first sibling object.
3072      */
3073     if (attch_ed_need_obj_menu(attach_type))
3074     {
3075         create_obj_menu_dir(obj, dir);
3076         attach_obj = (ABObj)prop_options_get_value(objlist_setting);
3077     }
3078
3079     /*
3080      * Figure out offset/position based on (new) attachment type
3081      */
3082     convert_offset_position(obj, attach_obj, dir, attach_type,
3083                         &offset, &position);
3084     
3085     /*
3086      * Set the new offset/position/sibling object values
3087      */
3088     set_attach_values(attach_type, 
3089                 offset_setting, position_setting, objlist_setting, 
3090                 offset, position, (int)attach_obj);
3091 }
3092
3093
3094 /*
3095  * Attachment type has changed. Figure out (and set) the
3096  * new 'fields' of the attachment of the OPPOSITE side.
3097  */
3098 static void     
3099 change_opp_attach_type(
3100     ABObj                       obj,
3101     AB_COMPASS_POINT            dir,
3102     ATTCH_ED_ATTACH_TYPE        attach_type
3103 )
3104 {
3105     DtbAttchEdAttchEdDialogInfo attch_ed_cgen
3106                             = &dtb_attch_ed_attch_ed_dialog;
3107     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3108     int                         offset = 0,
3109                                 position = 0;
3110     ABObj                       attach_obj = NULL;
3111     AB_COMPASS_POINT            opp_dir;
3112     ATTCH_ED_ATTACH_TYPE        opp_attach_type;
3113     PropOptionsSetting          opp_attach_type_setting,
3114                                 opp_objlist_setting;
3115     PropFieldSetting            opp_offset_setting,
3116                                 opp_position_setting;
3117     Widget                      opp_objlist_w,
3118                                 opp_offset_w,
3119                                 opp_position_w;
3120     BOOL                        set_opp_attach = FALSE;
3121
3122     /*
3123      * Based on 'dir', figure out which setting structures and
3124      * widgets are relevant for opposite side attachments.
3125      */
3126     switch (dir)
3127     {
3128         case AB_CP_WEST:
3129             opp_dir = AB_CP_EAST;
3130
3131             opp_attach_type_setting = &(ats->right_attach_type);
3132
3133             opp_offset_setting = &(ats->right_attach_offset);
3134             opp_position_setting = &(ats->right_attach_position);
3135             opp_objlist_setting = &(ats->right_attach_obj);
3136
3137             opp_objlist_w = attch_ed_cgen->right_attach_objmenu;
3138             opp_offset_w = attch_ed_cgen->right_offset_rowcolumn;
3139             opp_position_w = attch_ed_cgen->right_position_rowcolumn;
3140         break;
3141
3142         case AB_CP_EAST:
3143             opp_dir = AB_CP_WEST;
3144
3145             opp_attach_type_setting = &(ats->left_attach_type);
3146
3147             opp_offset_setting = &(ats->left_attach_offset);
3148             opp_position_setting = &(ats->left_attach_position);
3149             opp_objlist_setting = &(ats->left_attach_obj);
3150
3151             opp_objlist_w = attch_ed_cgen->left_attach_objmenu;
3152             opp_offset_w = attch_ed_cgen->left_offset_rowcolumn;
3153             opp_position_w = attch_ed_cgen->left_position_rowcolumn;
3154         break;
3155
3156         case AB_CP_NORTH:
3157             opp_dir = AB_CP_SOUTH;
3158
3159             opp_attach_type_setting = &(ats->bottom_attach_type);
3160
3161             opp_offset_setting = &(ats->bottom_attach_offset);
3162             opp_position_setting = &(ats->bottom_attach_position);
3163             opp_objlist_setting = &(ats->bottom_attach_obj);
3164
3165             opp_objlist_w = attch_ed_cgen->bottom_attach_objmenu;
3166             opp_offset_w = attch_ed_cgen->bottom_offset_rowcolumn;
3167             opp_position_w = attch_ed_cgen->bottom_position_rowcolumn;
3168         break;
3169
3170         case AB_CP_SOUTH:
3171             opp_dir = AB_CP_NORTH;
3172
3173             opp_attach_type_setting = &(ats->top_attach_type);
3174
3175             opp_offset_setting = &(ats->top_attach_offset);
3176             opp_position_setting = &(ats->top_attach_position);
3177             opp_objlist_setting = &(ats->top_attach_obj);
3178
3179             opp_objlist_w = attch_ed_cgen->top_attach_objmenu;
3180             opp_offset_w = attch_ed_cgen->top_offset_rowcolumn;
3181             opp_position_w = attch_ed_cgen->top_position_rowcolumn;
3182         break;
3183     }
3184
3185     /*
3186      * If any of the settings/widgets cannot be determined, return
3187      * immediately
3188      */
3189     if (!opp_attach_type_setting || 
3190         !opp_offset_setting || !opp_position_setting || !opp_objlist_setting ||
3191         !opp_objlist_w || !opp_offset_w || !opp_position_w)
3192         return;
3193
3194
3195     /*
3196      * Get opposite side attachment type
3197      */
3198     opp_attach_type = 
3199         (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(opp_attach_type_setting);
3200
3201     /*
3202      * Check if opposite side attachment needs to be changed
3203      */
3204     if ((attach_type == ATTCH_ED_CENTER_GRIDLINE) &&
3205         (opp_attach_type != ATTCH_ED_NONE))
3206     {
3207         /*
3208          * If attachment type is now ATTCH_ED_CENTER_GRIDLINE,
3209          * make the opposite side's attachment type ATTCH_ED_NONE.
3210          * ATTCH_ED_CENTER_GRIDLINE is an attachment type that
3211          * does not really apply to an edge. It affects the
3212          * object either vertically or horizontally.
3213          */
3214         opp_attach_type = ATTCH_ED_NONE;
3215         set_opp_attach = TRUE;
3216     }
3217     else if ((attach_type == ATTCH_ED_NONE) &&
3218         (opp_attach_type == ATTCH_ED_NONE))
3219     {
3220         /*
3221          * If attachment type is now ATTCH_ED_NONE and the opposite side's
3222          * attachment type is also ATTCH_ED_NONE, make the opposite side's 
3223          * attachment type ATTCH_ED_PARENT. You cannot set both the 
3224          * opposite sides to ATTCH_ED_NONE.
3225          */
3226         opp_attach_type = ATTCH_ED_PARENT;
3227         set_opp_attach = TRUE;
3228     }
3229     else if ((attach_type != ATTCH_ED_NONE) &&
3230         (opp_attach_type == ATTCH_ED_CENTER_GRIDLINE))
3231     {
3232         /*
3233          * If the attachment type is NOT ATTCH_ED_NONE, and
3234          * the opposite side's attachment type is ATTCH_ED_CENTER_GRIDLINE,
3235          * make the opposite side's attachment type ATTCH_ED_NONE.
3236          * ATTCH_ED_CENTER_GRIDLINE cannot be set on a side, if the
3237          * opposite side is not ATTCH_ED_NONE.
3238          */
3239         opp_attach_type = ATTCH_ED_NONE;
3240         set_opp_attach = TRUE;
3241     }
3242
3243     /*
3244      * Was a change to the opposite side's attachment necessary ?
3245      */
3246     if (set_opp_attach)
3247     {
3248         /*
3249          * Set the (in)active state of the fields:
3250          *      object option menu
3251          *      offset
3252          *      percentage/position
3253          * depending on what the new attachment type is
3254          */
3255         set_widget_state(opp_attach_type,
3256                         opp_objlist_w, opp_offset_w, opp_position_w);
3257
3258         /*
3259          * If the attachment type requires a sibling object,
3260          * make sure that the object option menu is current. Get
3261          * default/first sibling object.
3262          */
3263         if (attch_ed_need_obj_menu(opp_attach_type))
3264         {
3265             create_obj_menu_dir(obj, opp_dir);
3266             attach_obj = (ABObj)prop_options_get_value(opp_objlist_setting);
3267         }
3268
3269         /*
3270          * Set the new attachment type
3271          */
3272         prop_options_set_value(opp_attach_type_setting, (XtPointer)opp_attach_type, True);
3273
3274         /*
3275          * Figure out offset/position based on (new) attachment type
3276          */
3277         convert_offset_position(obj, attach_obj, opp_dir, opp_attach_type,
3278                         &offset, &position);
3279     
3280         /*
3281          * Set the new offset/position/sibling object values
3282          */
3283         set_attach_values(opp_attach_type, 
3284                 opp_offset_setting, opp_position_setting, opp_objlist_setting, 
3285                 offset, position, (int)attach_obj);
3286     }
3287 }
3288
3289
3290 static void     
3291 attach_obj_changed(
3292     Widget      widget,
3293     XtPointer   client_data,
3294     XtPointer   calldata
3295 )
3296 {
3297     DtbAttchEdAttchEdDialogInfo attch_ed_cgen
3298                             = &dtb_attch_ed_attch_ed_dialog;
3299     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3300     PropFieldSetting            offset_setting,
3301                                 position_setting;
3302     PropOptionsSetting          objlist_setting,
3303                                 attach_type_setting;
3304     AB_COMPASS_POINT            dir = (AB_COMPASS_POINT)client_data;
3305     ATTCH_ED_ATTACH_TYPE        attach_type = ATTCH_ED_NONE;
3306     ABObj                       attach_obj = NULL;
3307     XtArgVal                    value;
3308
3309     XtVaGetValues(widget, XmNuserData, &value, NULL);
3310     attach_obj = (ABObj)value;
3311
3312     if (!attach_obj)
3313         return;
3314
3315     switch (dir)
3316     {
3317         case AB_CP_WEST:
3318             attach_type_setting = &(ats->left_attach_type);
3319             offset_setting = &(ats->left_attach_offset);
3320             position_setting = &(ats->left_attach_position);
3321             objlist_setting = &(ats->left_attach_obj);
3322         break;
3323
3324         case AB_CP_EAST:
3325             attach_type_setting = &(ats->right_attach_type);
3326             offset_setting = &(ats->right_attach_offset);
3327             position_setting = &(ats->right_attach_position);
3328             objlist_setting = &(ats->right_attach_obj);
3329         break;
3330
3331         case AB_CP_NORTH:
3332             attach_type_setting = &(ats->top_attach_type);
3333             offset_setting = &(ats->top_attach_offset);
3334             position_setting = &(ats->top_attach_position);
3335             objlist_setting = &(ats->top_attach_obj);
3336         break;
3337
3338         case AB_CP_SOUTH:
3339             attach_type_setting = &(ats->bottom_attach_type);
3340             offset_setting = &(ats->bottom_attach_offset);
3341             position_setting = &(ats->bottom_attach_position);
3342             objlist_setting = &(ats->bottom_attach_obj);
3343         break;
3344
3345     }
3346
3347     attach_type = (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(attach_type_setting);
3348
3349     if (attch_ed_need_obj_menu(attach_type))
3350     {
3351         int     offset, position;
3352
3353         convert_offset_position(ats->cur_object, attach_obj, dir, attach_type,
3354                         &offset, &position);
3355         set_attach_values(attach_type, 
3356                 offset_setting, position_setting, objlist_setting, 
3357                 offset, position, (int)attach_obj);
3358     }
3359 }
3360
3361
3362 static void 
3363 attch_ed_view_child_attachments(
3364 )
3365 {
3366     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3367     ABObj                       cur_obj,
3368                                 child;
3369     DTB_MODAL_ANSWER            answer = DTB_ANSWER_ACTION1;
3370  
3371     cur_obj = ats->cur_object;
3372
3373     if (!cur_obj)
3374         return;
3375         
3376     child = obj_get_salient_child(cur_obj, 0);
3377
3378     if (!child)
3379         return;
3380
3381     if (attch_edP_pending()) 
3382     {
3383         answer = get_wrn_response(AB_attch_ed_dialog, 
3384                         ATTCH_ED_WRN_LOAD, child);
3385     }
3386
3387     if (answer != DTB_ANSWER_ACTION1)
3388         return;
3389
3390     attch_editor_load(child);
3391 }
3392
3393
3394 static void 
3395 attch_ed_view_parent_attachments(
3396 )
3397 {
3398     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3399     ABObj                       cur_obj,
3400                                 parent;
3401     DTB_MODAL_ANSWER            answer = DTB_ANSWER_ACTION1;
3402  
3403     cur_obj = ats->cur_object;
3404
3405     if (!cur_obj)
3406         return;
3407         
3408     parent = attch_ed_get_parent(cur_obj);
3409
3410     if (!parent)
3411         return;
3412
3413     parent = obj_get_root(parent);
3414
3415     if (attch_edP_pending()) 
3416     {
3417         answer = get_wrn_response(AB_attch_ed_dialog, 
3418                         ATTCH_ED_WRN_LOAD, parent);
3419     }
3420
3421     if (answer != DTB_ANSWER_ACTION1)
3422         return;
3423
3424     attch_editor_load(parent);
3425 }
3426
3427 static void
3428 attch_ed_activate_parent_child_button(
3429 )
3430 {
3431     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3432     DtbAttchEdAttchEdDialogInfo attch_ed_cgen
3433                             = &dtb_attch_ed_attch_ed_dialog;
3434     ABObj                       cur_obj,
3435                                 parent;
3436     BOOL                        child_state = FALSE,
3437                                 parent_state = FALSE;
3438
3439     cur_obj = ats->cur_object;
3440
3441     if (!cur_obj)
3442         return;
3443     
3444     parent = attch_ed_get_parent(cur_obj);
3445
3446     if (parent)
3447         parent = obj_get_root(parent);
3448
3449     if (obj_is_container(cur_obj) || obj_is_layers(cur_obj))
3450         child_state = TRUE;
3451
3452     if (parent && !obj_is_window(parent))
3453         parent_state = TRUE;
3454
3455     ui_set_active(attch_ed_cgen->parent_attach_button, parent_state);
3456     ui_set_active(attch_ed_cgen->child_attach_button, child_state);
3457
3458 }
3459
3460 /*
3461  * Called when the user attempts to dismiss the Attachments Editor 
3462  * via the Motif window menu.
3463  */
3464 static void
3465 attch_edP_prevent_closeCB(
3466     Widget      widget,
3467     XtPointer   client_data,
3468     XtPointer   call_data
3469 )
3470 {
3471     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3472     DtbAttchEdAttchEdDialogInfo attch_ed_cgen
3473                             = &dtb_attch_ed_attch_ed_dialog;
3474     DTB_MODAL_ANSWER            answer = DTB_ANSWER_ACTION1;
3475
3476     /* 
3477      * If there are pending changes for the current object, handle the
3478      * implied auto-apply.
3479      */
3480     if (attch_edP_pending()) 
3481     {
3482         answer = get_wrn_response(widget, 
3483                         ATTCH_ED_WRN_CLOSE, NULL);
3484     }
3485
3486     if (answer != DTB_ANSWER_ACTION1) 
3487         return;
3488
3489     /* 
3490      * No pending changes OR applied existing changes, so just 
3491      * dismiss the Attachments Editor 
3492      */
3493     ui_win_show(AB_attch_ed_dialog, False, NULL);
3494 }
3495
3496 static DTB_MODAL_ANSWER
3497 get_wrn_response(
3498     Widget              w,
3499     ATTCH_ED_WRN_TYPE   wrn_type,
3500     ABObj               new_obj
3501 )
3502 {
3503     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3504     DTB_MODAL_ANSWER            answer;
3505     XmString                    xm_buf;
3506     DtbObjectHelpData           help_data = NULL;
3507     char                        wrn_string[512],
3508                                 *cur_name = NULL,
3509                                 *new_name = NULL;
3510
3511     if (dtb_app_resource_rec.implied_apply == True)
3512         answer = DTB_ANSWER_ACTION1;
3513     else
3514     {
3515         if (ats->cur_object)
3516         {
3517             cur_name = obj_get_name(ats->cur_object);
3518
3519             if (!cur_name)
3520                 cur_name = "nil";
3521         }
3522         
3523         if (new_obj)
3524         {
3525             new_name = obj_get_name(new_obj);
3526
3527             if (!new_name)
3528                 new_name = "nil";
3529         }
3530
3531         help_data = (DtbObjectHelpData) util_malloc(sizeof(DtbObjectHelpDataRec));
3532         help_data->help_text = help_data->help_volume = help_data->help_locationID = NULL;
3533
3534         /*
3535          * Determine message and help text for each
3536          * case
3537          */
3538         switch(wrn_type)
3539         {
3540             case ATTCH_ED_WRN_LOAD:
3541                 help_data->help_text = XtNewString(catgets(Dtb_project_catd, 100, 93, "Click Apply Changes to apply the changes to the\ncurrent object and load the selected object.\n\nClick Cancel if you don't want to apply the\nchanges to the current object. You can then\nclick Reset to undo the changes before loading\nthe selected object."));
3542                 sprintf(wrn_string, 
3543                     catgets(Dtb_project_catd, 100, 43, 
3544                     "Attachments for \"%s\"\n\
3545                     have been modified but not Applied.\n\n\
3546                     You can Apply the Changes or Cancel the\n\
3547                     Load operation for \"%s\"."),
3548                         cur_name, new_name);
3549                 break;
3550
3551             case ATTCH_ED_WRN_CHANGE_OBJTYPE:
3552                 help_data->help_text = XtNewString(catgets(Dtb_project_catd, 100, 95, "Click Apply Changes to apply the changes to the\ncurrent object and display the new object type.\n\nClick Cancel if you don't want to apply the\nchanges to the current object. You can then\nclick Reset to undo the changes before changing\nto a different object type."));
3553                 sprintf(wrn_string, 
3554                     catgets(Dtb_project_catd, 100, 44, 
3555                     "Attachments for \"%s\"\n\
3556                     have been modified but not Applied.\n\n\
3557                     You can Apply the Changes or Cancel the\n\
3558                     'Change Object-Type' operation."),
3559                         cur_name);
3560                 break;
3561
3562             case ATTCH_ED_WRN_CLOSE:
3563                 help_data->help_text = XtNewString(catgets(Dtb_project_catd, 100, 247, "Click Apply Changes to apply the changes to the\ncurrent object and close the Attachments Editor.\n\nClick Cancel if you don't want to apply the\nchanges to the current object and want the\nAttachments Editor to remain displayed. You can\nthen click Reset to undo the changes before\nclosing the Attachments Editor."));
3564                 sprintf(wrn_string, 
3565                     catgets(Dtb_project_catd, 100, 45, 
3566                     "Attachments for \"%s\"\n\
3567                     have been modified but not Applied.\n\n\
3568                     You can Apply the Changes or Cancel the\n\
3569                     Close operation."),
3570                         cur_name);
3571                 break;
3572
3573             default:
3574                 sprintf(wrn_string, "Attachments Editor warning!!");
3575                 break;
3576         }
3577
3578         xm_buf = XmStringCreateLocalized(wrn_string);
3579         dtb_attch_ed_wrn_msg_initialize(&dtb_attch_ed_wrn_msg);
3580
3581         answer = dtb_show_modal_message(w, &dtb_attch_ed_wrn_msg,
3582                                 xm_buf, help_data, NULL);
3583     
3584         XmStringFree(xm_buf);
3585
3586         if (help_data->help_text)
3587             XtFree(help_data->help_text);
3588         util_free(help_data);
3589     }
3590
3591     switch (answer)
3592     {
3593         case DTB_ANSWER_ACTION1:        /* Apply Changes */
3594             attch_editor_apply(ats->cur_object);
3595         break;
3596
3597         default:                        /* Let caller do the rest */
3598         break;
3599     }
3600
3601     return (answer);
3602 }
3603
3604 BOOL
3605 attch_ed_can_edit_attachments(
3606     ABObj       obj
3607 )
3608 {
3609     ABObj       parent,
3610                 module;
3611     Widget      parent_w;
3612
3613     if (!obj)
3614         return (FALSE);
3615
3616     module = obj_get_module(obj);
3617
3618     if (module && (!obj_has_flag(module, MappedFlag) || !obj_is_defined(module)))
3619         return (FALSE);
3620
3621     if (!obj_is_ui(obj) || obj_is_window(obj) || 
3622          obj_is_menubar(obj) || obj_is_item(obj) || 
3623          obj_is_sub(obj))
3624         return (FALSE);
3625
3626     parent = attch_ed_get_parent(obj);
3627
3628     if (!parent)
3629         return (FALSE);
3630         
3631     parent_w = objxm_get_widget(parent);
3632
3633     if (!parent_w)
3634         return (FALSE);
3635
3636     if (!XtIsSubclass(parent_w, xmFormWidgetClass))
3637         return (FALSE);
3638
3639     return (TRUE);
3640 }
3641
3642 static void
3643 print_attach_type(
3644     ATTCH_ED_ATTACH_TYPE        attach_type
3645 )
3646 {
3647     fprintf(stderr, "Attach type = ");
3648     switch (attach_type)
3649     {
3650         case ATTCH_ED_PARENT:
3651             fprintf(stderr, "ATTCH_ED_PARENT\n");
3652         break;
3653
3654         case ATTCH_ED_OPPOSITE_PARENT:
3655             fprintf(stderr, "ATTCH_ED_OPPOSITE_PARENT\n");
3656         break;
3657
3658         case ATTCH_ED_SIBLING:
3659             fprintf(stderr, "ATTCH_ED_SIBLING\n");
3660         break;
3661
3662         case ATTCH_ED_OPPOSITE_SIBLING:
3663             fprintf(stderr, "ATTCH_ED_OPPOSITE_SIBLING\n");
3664         break;
3665
3666         case ATTCH_ED_GRIDLINE:
3667             fprintf(stderr, "ATTCH_ED_GRIDLINE\n");
3668         break;
3669
3670         case ATTCH_ED_CENTER_GRIDLINE:
3671             fprintf(stderr, "ATTCH_ED_CENTER_GRIDLINE\n");
3672         break;
3673
3674         case ATTCH_ED_NONE:
3675             fprintf(stderr, "ATTCH_ED_NONE\n");
3676         break;
3677     }
3678 }
3679
3680 static BOOL
3681 attch_ed_verify_props(
3682 )
3683 {
3684     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3685     ATTCH_ED_ATTACH_TYPE        attach_type = ATTCH_ED_NONE;
3686     ABObj                       parent;
3687
3688     if (ats->cur_object == NULL)
3689         return TRUE;
3690
3691     /*
3692      * Get parent of current object
3693      */
3694     parent = obj_get_parent(ats->cur_object);
3695     if (parent);
3696         parent = obj_get_root(parent);
3697
3698     /*
3699      * If parent is a group with layout type NOT "As Is"
3700      */
3701     if (parent && obj_is_group(parent) && 
3702         (obj_get_group_type(parent) != AB_GROUP_IGNORE))
3703     {
3704         DTB_MODAL_ANSWER        answer;
3705         DtbObjectHelpData       help_data;
3706         XmString                xm_buf;
3707         char                    *format_str,
3708                                 *obj_name,
3709                                 *parent_name,
3710                                 *msg_buf;
3711
3712         /*
3713          * Get the object and it's parent's names
3714          */
3715         obj_name = obj_get_name(ats->cur_object);
3716         parent_name = obj_get_name(parent);
3717
3718         if (!obj_name || !parent_name)
3719             return TRUE;
3720
3721         /*
3722          * Initialize message object if necessary
3723          */
3724         dtb_attch_ed_grp_member_wrn_initialize(&dtb_attch_ed_grp_member_wrn);
3725
3726         /*
3727          * Fetch format string
3728          */
3729         format_str = XtNewString(catgets(Dtb_project_catd, 100, 245, 
3730                 "Attachments for \"%s\"\ncannot be modified because it is\na member of the group \"%s\"."));
3731
3732         /*
3733          * Malloc space for warning message. It's length is:
3734          *      format str len +
3735          *      object name len +
3736          *      object parent name len +
3737          *      <some padding> (paranoia)
3738          */
3739         msg_buf = (STRING)util_malloc(strlen(format_str) + 
3740                                 strlen(obj_name) + 
3741                                 strlen(parent_name) + 
3742                                 10);
3743
3744         /*
3745          * Construct warning message
3746          */
3747         sprintf(msg_buf, format_str, obj_name, parent_name);
3748
3749         /*
3750          * Create XmString for warning message
3751          */
3752         xm_buf = XmStringCreateLocalized(msg_buf);
3753
3754         /*
3755          * Malloc/setup struct for help text
3756          */
3757         help_data = (DtbObjectHelpData) util_malloc(sizeof(DtbObjectHelpDataRec));
3758         help_data->help_text = catgets(Dtb_project_catd, 100, 246,
3759                 "Group objects have attributes that determine what\nattachments their members will have, therefore setting\nattachments for group members is not allowed. This only\napplies to group objects that have layout type Vertical,\nHorizontal, or Row-column. Click Cancel or Reset to\nundo your changes on the Attachments Editor.");
3760         help_data->help_volume = NULL;
3761         help_data->help_locationID = NULL;
3762
3763         /*
3764          * Show warning message dialog
3765          */
3766         answer = dtb_show_modal_message(AB_attch_ed_dialog, &dtb_attch_ed_grp_member_wrn, 
3767                         xm_buf, help_data, NULL);
3768         
3769         /*
3770          * Free message/format strings
3771          * Free XmString
3772          * Free help struct
3773          */
3774         XtFree(msg_buf);
3775         XtFree(format_str);
3776         XmStringFree(xm_buf);
3777         util_free(help_data);
3778
3779         return FALSE;
3780     }
3781
3782     /*
3783      * Top attachment
3784      */
3785     if (prop_changed(ats->top_attach_type.changebar))
3786     {
3787         attach_type = 
3788                 (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->top_attach_type));
3789
3790         if (!verify_one_attach(attach_type,
3791                 &(ats->top_attach_offset), &(ats->top_attach_position)))
3792             return FALSE;
3793     }
3794
3795     /*
3796      * Bottom attachment
3797      */
3798     if (prop_changed(ats->bottom_attach_type.changebar))
3799     {
3800         attach_type = 
3801                 (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->bottom_attach_type));
3802
3803         if (!verify_one_attach(attach_type,
3804                 &(ats->bottom_attach_offset), &(ats->bottom_attach_position)))
3805             return FALSE;
3806     }
3807
3808     /*
3809      * Left attachment
3810      */
3811     if (prop_changed(ats->left_attach_type.changebar))
3812     {
3813         attach_type = 
3814                 (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->left_attach_type));
3815
3816         if (!verify_one_attach(attach_type,
3817                 &(ats->left_attach_offset), &(ats->left_attach_position)))
3818             return FALSE;
3819     }
3820
3821     /*
3822      * Right attachment - shares changebar with left attachment
3823      */
3824     if (prop_changed(ats->left_attach_type.changebar))
3825     {
3826         attach_type = 
3827                 (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->right_attach_type));
3828
3829         if (!verify_one_attach(attach_type,
3830                 &(ats->right_attach_offset), &(ats->right_attach_position)))
3831             return FALSE;
3832     }
3833
3834     return TRUE;
3835 }
3836
3837 static BOOL
3838 verify_one_attach(
3839     ATTCH_ED_ATTACH_TYPE        attach_type,
3840     PropFieldSetting            offset_setting,
3841     PropFieldSetting            position_setting
3842 )
3843 {
3844     switch (attach_type)
3845     {
3846         case ATTCH_ED_PARENT:
3847         case ATTCH_ED_OPPOSITE_PARENT:
3848         case ATTCH_ED_SIBLING:
3849         case ATTCH_ED_OPPOSITE_SIBLING:
3850             if (!prop_number_ok(offset_setting->field, 
3851                         (STRING)OffsetFieldStr, -SHRT_MAX, SHRT_MAX))
3852                 return FALSE;
3853         break;
3854
3855         case ATTCH_ED_GRIDLINE:
3856             if (!prop_number_ok(offset_setting->field, 
3857                         (STRING)OffsetFieldStr, -SHRT_MAX, SHRT_MAX) || 
3858                 !prop_number_ok(position_setting->field, 
3859                         (STRING)PercentageFieldStr, -SHRT_MAX, SHRT_MAX))
3860                 return FALSE;
3861         break;
3862
3863         case ATTCH_ED_CENTER_GRIDLINE:
3864             if (!prop_number_ok(position_setting->field, 
3865                         (STRING)PercentageFieldStr, -SHRT_MAX, SHRT_MAX))
3866                 return FALSE;
3867         break;
3868
3869         case ATTCH_ED_NONE:
3870         break;
3871     }
3872     
3873     return TRUE;
3874 }
3875
3876
3877 /*** DTB_USER_CODE_END
3878  ***
3879  *** End of user code section
3880  ***
3881  **************************************************************************/
3882
3883
3884
3885 void 
3886 attch_ed_applyCB(
3887     Widget widget,
3888     XtPointer clientData,
3889     XtPointer callData
3890 )
3891 {
3892     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
3893
3894     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3895
3896     attch_editor_apply(ats->cur_object);
3897
3898     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
3899     
3900     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
3901     /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/
3902 }
3903
3904
3905 void 
3906 attch_ed_resetCB(
3907     Widget widget,
3908     XtPointer clientData,
3909     XtPointer callData
3910 )
3911 {
3912     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
3913
3914     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3915
3916     attch_editor_load(ats->cur_object);
3917
3918     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
3919     
3920     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
3921     /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/
3922 }
3923
3924
3925 void 
3926 attch_ed_helpCB(
3927     Widget widget,
3928     XtPointer clientData,
3929     XtPointer callData
3930 )
3931 {
3932     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
3933     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
3934     
3935     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
3936     printf("action: attch_ed_helpCB\n");
3937     /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/
3938 }
3939
3940
3941 void 
3942 attch_ed_okCB(
3943     Widget widget,
3944     XtPointer clientData,
3945     XtPointer callData
3946 )
3947 {
3948     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
3949
3950     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3951
3952     attch_editor_apply(ats->cur_object);
3953     ui_win_show(AB_attch_ed_dialog, False, NULL);
3954
3955     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
3956     
3957     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
3958     /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/
3959 }
3960
3961
3962 void 
3963 attch_ed_cancelCB(
3964     Widget widget,
3965     XtPointer clientData,
3966     XtPointer callData
3967 )
3968 {
3969     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
3970
3971     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3972
3973     attch_editor_load(ats->cur_object);
3974     ui_win_show(AB_attch_ed_dialog, False, NULL); 
3975
3976     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
3977     
3978     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
3979     /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/
3980 }
3981
3982
3983 void 
3984 top_attach_type_changed(
3985     Widget widget,
3986     XtPointer clientData,
3987     XtPointer callData
3988 )
3989 {
3990     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
3991
3992     DtbAttchEdAttchEdDialogInfo attch_ed_cgen
3993                             = &dtb_attch_ed_attch_ed_dialog;
3994     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
3995     ATTCH_ED_ATTACH_TYPE        attach_type = ATTCH_ED_NONE;
3996     XtArgVal                    value;
3997
3998     XtVaGetValues(widget, XmNuserData, &value, NULL);
3999     attach_type = (ATTCH_ED_ATTACH_TYPE)value;
4000
4001     /*
4002     print_attach_type(attach_type);
4003     */
4004
4005     change_attach_type(ats->cur_object, AB_CP_NORTH, attach_type);
4006     change_opp_attach_type(ats->cur_object, AB_CP_NORTH, attach_type);
4007
4008     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
4009     
4010     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
4011     /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/
4012 }
4013
4014
4015 void 
4016 right_attach_type_changed(
4017     Widget widget,
4018     XtPointer clientData,
4019     XtPointer callData
4020 )
4021 {
4022     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
4023
4024     DtbAttchEdAttchEdDialogInfo attch_ed_cgen
4025                             = &dtb_attch_ed_attch_ed_dialog;
4026     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
4027     ATTCH_ED_ATTACH_TYPE        attach_type = ATTCH_ED_NONE;
4028     XtArgVal                    value;
4029
4030     XtVaGetValues(widget, XmNuserData, &value, NULL);
4031     attach_type = (ATTCH_ED_ATTACH_TYPE)value;
4032
4033     /*
4034     print_attach_type(attach_type);
4035     */
4036
4037     change_attach_type(ats->cur_object, AB_CP_EAST, attach_type);
4038     change_opp_attach_type(ats->cur_object, AB_CP_EAST, attach_type);
4039
4040     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
4041     
4042     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
4043     /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/
4044 }
4045
4046
4047 void 
4048 bottom_attach_type_changed(
4049     Widget widget,
4050     XtPointer clientData,
4051     XtPointer callData
4052 )
4053 {
4054     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
4055
4056     DtbAttchEdAttchEdDialogInfo attch_ed_cgen
4057                             = &dtb_attch_ed_attch_ed_dialog;
4058     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
4059     ATTCH_ED_ATTACH_TYPE        attach_type = ATTCH_ED_NONE;
4060     XtArgVal                    value;
4061
4062     XtVaGetValues(widget, XmNuserData, &value, NULL);
4063     attach_type = (ATTCH_ED_ATTACH_TYPE)value;
4064
4065     /*
4066     print_attach_type(attach_type);
4067     */
4068
4069     change_attach_type(ats->cur_object, AB_CP_SOUTH, attach_type);
4070     change_opp_attach_type(ats->cur_object, AB_CP_SOUTH, attach_type);
4071
4072     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
4073     
4074     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
4075     /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/
4076 }
4077
4078
4079 void 
4080 left_attach_type_changed(
4081     Widget widget,
4082     XtPointer clientData,
4083     XtPointer callData
4084 )
4085 {
4086     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
4087
4088     DtbAttchEdAttchEdDialogInfo attch_ed_cgen
4089                             = &dtb_attch_ed_attch_ed_dialog;
4090     AttchEditorSettingsRec      *ats = &attch_editor_settings_rec;
4091     ATTCH_ED_ATTACH_TYPE        attach_type = ATTCH_ED_NONE;
4092     XtArgVal                    value;
4093
4094     XtVaGetValues(widget, XmNuserData, &value, NULL);
4095     attach_type = (ATTCH_ED_ATTACH_TYPE)value;
4096
4097     /*
4098     print_attach_type(attach_type);
4099     */
4100
4101     change_attach_type(ats->cur_object, AB_CP_WEST, attach_type);
4102     change_opp_attach_type(ats->cur_object, AB_CP_WEST, attach_type);
4103
4104     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
4105     
4106     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
4107     /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/
4108 }
4109
4110
4111 void 
4112 parent_attachCB(
4113     Widget widget,
4114     XtPointer clientData,
4115     XtPointer callData
4116 )
4117 {
4118     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
4119     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
4120     
4121     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
4122     attch_ed_view_parent_attachments();
4123     /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/
4124 }
4125
4126
4127 void 
4128 child_attachCB(
4129     Widget widget,
4130     XtPointer clientData,
4131     XtPointer callData
4132 )
4133 {
4134     /*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
4135     /*** DTB_USER_CODE_END   ^^^ Add C variables and code above ^^^ ***/
4136     
4137     /*** DTB_USER_CODE_START vvv Add C code below vvv ***/
4138     attch_ed_view_child_attachments();
4139     /*** DTB_USER_CODE_END   ^^^ Add C code above ^^^ ***/
4140 }
4141
4142
4143
4144 /**************************************************************************
4145  *** DTB_USER_CODE_START
4146  ***
4147  *** All automatically-generated data and functions have been defined.
4148  ***
4149  *** Add new functions here, or at the top of the file.
4150  ***/
4151
4152 /*** DTB_USER_CODE_END
4153  ***
4154  *** End of user code section
4155  ***
4156  **************************************************************************/
4157
4158