Files
cdesktop/cde/programs/dtappbuilder/src/ab/attch_ed_stubs.c
Lev Kujawski 7010b2c11b Centralize catgets() calls through MsgCat
CDE has relied upon catgets() implementations following a relaxed
interpretation of the XPG internationalization standard that ignored
-1, the standard error value returned by catopen, as the catalog
argument. However, this same behavior causes segmentation faults with
the musl C library.

This patch:

- Centralizes (with the exception of ToolTalk) all calls to catopen(),
  catgets(), and catclose() through MsgCat within the DtSvc library.
- Prevents calls to catgets() and catclose() that rely upon
  undefined behavior.
- Eliminates a number of bespoke catgets() wrappers, including multiple
  redundant caching implementations designed to work around a design
  peculiarity in HP/UX.
- Eases building CDE without XPG internationalization support by providing
  the appropriate macros.
2021-01-31 16:17:13 -07:00

4137 lines
102 KiB
C

/*** DTB_USER_CODE_START vvv Add file header below vvv ***/
/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*** DTB_USER_CODE_END ^^^ Add file header above ^^^ ***/
/*
* File: attch_ed_stubs.c
* Contains: Module callbacks and connection functions
*
* This file was generated by dtcodegen, from module attch_ed
*
* Any text may be added between the DTB_USER_CODE_START and
* DTB_USER_CODE_END comments (even non-C code). Descriptive comments
* are provided only as an aid.
*
* ** EDIT ONLY WITHIN SECTIONS MARKED WITH DTB_USER_CODE COMMENTS. **
* ** ALL OTHER MODIFICATIONS WILL BE OVERWRITTEN. DO NOT MODIFY OR **
* ** DELETE THE GENERATED COMMENTS! **
*/
#include <stdint.h>
#include <stdio.h>
#include <Xm/Xm.h>
#include "dtb_utils.h"
#include "dtbuilder.h"
#include "attch_ed_ui.h"
/**************************************************************************
*** DTB_USER_CODE_START
***
*** All necessary header files have been included.
***
*** Add include files, types, macros, externs, and user functions here.
***/
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/PushB.h>
#include <Xm/List.h>
#include <Xm/Separator.h>
#include <ab_private/ab.h>
#include <ab_private/trav.h>
#include <ab_private/abobj_set.h>
#include <ab_private/abobj_list.h>
#include <ab_private/obj_notify.h>
#include <ab_private/pal.h>
#include <ab_private/prop.h>
#include <ab_private/proj.h>
#include <ab_private/attch_ed.h>
#include <ab_private/ui_util.h>
#include <ab_private/abobj_list.h>
#include "dtb_utils.h"
#include "dtbuilder.h"
#include "attch_ed_ui.h"
typedef struct ATTCH_ED_OBJ_TYPE_INFO_REC {
AB_OBJECT_TYPE type;
int subtype;
} AttchEdObjTypeInfoRec;
static AttchEdObjTypeInfoRec AttchEdObjTypeInfo;
/*
* Declarations of global widgets used by callbacks.
*/
/*
* End declarations of global widgets
*/
static Widget attch_editor_props_init(
DtbAttchEdAttchEdDialogInfo attch_ed_cgen,
Widget parent
);
static int attch_editor_load(
ABObj object
);
static int attch_editor_apply(
ABObj object
);
static BOOL attch_edP_pending(
);
static int attch_editor_activate(
BOOL active
);
static BOOL editable_obj_test(
PalEditableObjInfo *ed_obj_info
);
static void load_attch_obj(
ABObj obj,
BOOL turnoff_cb
);
static void create_children_list(
ABObj obj
);
static void update_attch_obj_parent(
ABObj obj
);
static void update_obj_type(
ABObj obj
);
static void update_objlist(
ABObj obj
);
static void create_obj_menu_dir(
ABObj object,
AB_COMPASS_POINT dir
);
static void create_obj_menu(
ABObj object
);
static void delete_from_obj_menu(
ABObj cur_obj,
ABObj deleted_obj
);
static void select_objlist(
ABObj obj
);
static void turnoff_changebars(
);
static void get_attach_info(
ABObj obj,
ABAttachment *attachment,
ATTCH_ED_ATTACH_TYPE *type,
int *offset,
int *position,
ABObj *attach_obj
);
static void set_attach_info(
ABObj obj,
ABAttachment *attachment,
ATTCH_ED_ATTACH_TYPE type,
int offset,
int position,
ABObj attach_obj
);
static void attch_ed_select_itemCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
);
static void populate_obj_menu(
Widget widget,
ABObj object,
AB_COMPASS_POINT dir,
Widget **item,
XtPointer **item_val,
int *n
);
static void attch_change_objecttypePalCB(
Widget widget,
XtPointer client_data,
XtPointer calldata
);
static BOOL attch_objlist_test_func(
ABObj test_obj
);
static BOOL attch_childrenlist_test_func(
ABObj test_obj
);
static void attch_objlist_selectCB(
Widget widget,
XtPointer client_data,
XmListCallbackStruct *listdata
);
static int attch_obj_geom_changedCB(
ObjEvAttChangeInfo evInfo
);
static int attch_obj_renameCB(
ObjEvAttChangeInfo evInfo
);
static int attch_obj_destroyCB(
ObjEvDestroyInfo evInfo
);
static int attch_obj_reparentCB(
ObjEvReparentInfo info
);
static void handle_prop_sheet_obj_destroy(
ObjEvDestroyInfo evInfo
);
static void handle_actual_obj_destroy(
ObjEvDestroyInfo evInfo
);
static void handle_prop_sheet_obj_reparent(
ObjEvReparentInfo evInfo
);
static void handle_actual_obj_reparent(
ObjEvReparentInfo evInfo
);
static void set_widget_state(
ATTCH_ED_ATTACH_TYPE attach_type,
Widget objlist,
Widget offset,
Widget position
);
static void enable_attach_types(
ABObj obj
);
static void set_attach_values(
ATTCH_ED_ATTACH_TYPE attach_type,
PropFieldSetting offset_setting,
PropFieldSetting position_setting,
PropOptionsSetting objlist_setting,
int offset_value,
int position_value,
XtPointer objlist_value
);
static void change_attach_type(
ABObj obj,
AB_COMPASS_POINT dir,
ATTCH_ED_ATTACH_TYPE attach_type
);
static void change_opp_attach_type(
ABObj obj,
AB_COMPASS_POINT dir,
ATTCH_ED_ATTACH_TYPE attach_type
);
static void get_attach_values(
ATTCH_ED_ATTACH_TYPE attach_type,
PropFieldSetting offset_setting,
PropFieldSetting position_setting,
PropOptionsSetting objlist_setting,
int *offset_value,
int *position_value,
XtPointer *objlist_value
);
static void convert_offset_position(
ABObj cur_obj,
ABObj sibling_obj,
AB_COMPASS_POINT dir,
ATTCH_ED_ATTACH_TYPE attach_type,
int *ret_offset,
int *ret_position
);
static void attach_obj_changed(
Widget widget,
XtPointer client_data,
XtPointer calldata
);
static void print_attach_type(
ATTCH_ED_ATTACH_TYPE attach_type
);
static BOOL attch_ed_obj_is_target_type(
ABObj obj
);
static void attch_ed_change_objecttype(
AB_OBJECT_TYPE type,
int subtype
);
static ABObj attch_ed_get_parent(
ABObj obj
);
static void attch_ed_view_child_attachments(
);
static void attch_ed_view_parent_attachments(
);
static void attch_ed_activate_parent_child_button(
);
static void attch_edP_prevent_closeCB(
Widget w,
XtPointer client_data,
XtPointer call_data
);
static void change_attype_from_sib_to_point(
ABObj obj,
ABObj attach_to_sib,
AB_COMPASS_POINT dir,
BOOL reparent
);
static DTB_MODAL_ANSWER get_wrn_response(
Widget w,
ATTCH_ED_WRN_TYPE wrn_type,
ABObj new_obj
);
static BOOL attch_ed_verify_props(
);
static BOOL verify_one_attach(
ATTCH_ED_ATTACH_TYPE attach_type,
PropFieldSetting offset_setting,
PropFieldSetting position_setting
);
static ABObj attch_cur_parent = NULL;
static AB_OBJECT_TYPE cur_type = AB_TYPE_UNDEF;
static int cur_subtype;
AttchEditorSettingsRec attch_editor_settings_rec;
/*
* Declarations of global widgets used by callbacks.
*/
/*
* End declarations of global widgets
*/
static ABObj
attch_ed_get_parent(
ABObj obj
)
{
ABObj tmp;
if (!obj || !(obj_has_flag(obj, XmConfiguredFlag)))
return (NULL);
if (!(tmp = obj_get_parent(obj)))
return (NULL);
return(tmp);
/*
return(objxm_comp_get_subobj(tmp, AB_CFG_PARENT_OBJ));
*/
}
void
attch_ed_init(void)
{
obj_add_destroy_callback(attch_obj_destroyCB, "ATTCH_ED");
obj_add_reparent_callback(attch_obj_reparentCB, "ATTCH_ED");
}
void
attch_ed_show_dialog(
ABObj cur_obj
)
{
/*
* Set busy cursor
*/
ab_set_busy_cursor(TRUE);
/*
* If there is no Attachment Editor, create it
*/
if (AB_attch_ed_dialog == (Widget)NULL)
{
AB_attch_ed_dialog = attch_editor_props_init(&dtb_attch_ed_attch_ed_dialog,
AB_toplevel);
}
if (AB_attch_ed_dialog != NULL)
{
DTB_MODAL_ANSWER answer = DTB_ANSWER_ACTION1;
PalEditableObjInfo *ed_obj_info;
/* Check to make sure cur_obj is an object that can be edited
* by the Attachments editor...
*/
if (cur_obj)
{
if (ed_obj_info = pal_get_editable_obj_info(cur_obj))
{
if (!editable_obj_test(ed_obj_info))
cur_obj = NULL; /* can't edit current obj */
}
else
cur_obj = NULL;
}
if (cur_obj && attch_edP_pending())
{
answer = get_wrn_response(AB_attch_ed_dialog, ATTCH_ED_WRN_LOAD,
cur_obj);
}
if (answer == DTB_ANSWER_ACTION1)
{
if (cur_obj)
attch_editor_load(cur_obj);
else if (AttchEdObjTypeInfo.type == AB_TYPE_UNDEF)
/* First time - start with First object type in menu */
attch_ed_change_objecttype(AB_TYPE_BUTTON, AB_NO_SUBTYPE);
ab_show_window(AB_attch_ed_dialog);
}
}
/*
* Unset busy cursor
*/
ab_set_busy_cursor(FALSE);
}
static BOOL
editable_obj_test(
PalEditableObjInfo *ed_obj_info
)
{
BOOL needed = True;
switch(ed_obj_info->type)
{
case AB_TYPE_BASE_WINDOW:
case AB_TYPE_DIALOG:
case AB_TYPE_FILE_CHOOSER:
case AB_TYPE_ITEM:
case AB_TYPE_MENU:
case AB_TYPE_MESSAGE:
case AB_TYPE_PROJECT:
needed = False;
break;
case AB_TYPE_CONTAINER:
if (ed_obj_info->subtype == AB_CONT_MENU_BAR)
needed = False;
break;
}
return needed;
}
static Widget
attch_editor_props_init(
DtbAttchEdAttchEdDialogInfo attch_ed_cgen,
Widget parent
)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
Widget item[20], ret_value;
XtArgVal item_val[20];
int n;
/*
* Create Dialog widgets...
*/
dtbAttchEdAttchEdDialogInfo_clear(attch_ed_cgen);
if (dtb_attch_ed_attch_ed_dialog_initialize(attch_ed_cgen, parent) == 0)
{
/*
* Setup object type menu
*/
/*
* Destroy dummy item
*/
XtDestroyWidget(attch_ed_cgen->obj_type_opmenu_items.Button_item);
/*
* Add choice items for every palette object type
*/
pal_add_editable_obj_menu_items(attch_ed_cgen->obj_type_opmenu_menu,
attch_change_objecttypePalCB, editable_obj_test);
AttchEdObjTypeInfo.type = AB_TYPE_UNDEF;
AttchEdObjTypeInfo.subtype = AB_NO_SUBTYPE;
XtAddCallback(attch_ed_cgen->objlist, XmNbrowseSelectionCallback,
(XtCallbackProc)attch_objlist_selectCB, (XtPointer)NULL);
/*
* Hook widgets up to Attachment Editor
*/
/*
ats->prop_sheet = attch_ed_cgen->attachments_panel;
*/
ats->prop_sheet = attch_ed_cgen->attach_grp;
ats->cur_object = (ABObj)NULL;
/**********************
* Top Attachments *
**********************/
/*
* Attachment type option menu
*/
n = 0;
item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_form_xbm_item;
item_val[n] = ATTCH_ED_PARENT; n++;
item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_opposite_form_xbm_item;
item_val[n] = ATTCH_ED_OPPOSITE_PARENT; n++;
item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_widget_xbm_item;
item_val[n] = ATTCH_ED_SIBLING; n++;
item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_opposite_widget_xbm_item;
item_val[n] = ATTCH_ED_OPPOSITE_SIBLING; n++;
item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_position_xbm_item;
item_val[n] = ATTCH_ED_GRIDLINE; n++;
item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_top_center_position_xbm_item;
item_val[n] = ATTCH_ED_CENTER_GRIDLINE; n++;
item[n] = attch_ed_cgen->top_attach_items.bitmaps_attach_none_xbm_item;
item_val[n] = ATTCH_ED_NONE; n++;
prop_options_init(&(ats->top_attach_type), NULL,
attch_ed_cgen->top_attach, attch_ed_cgen->top_attach_menu,
n, item, (XtPointer*)item_val,
attch_ed_cgen->top_attach_cb);
/*
* Top offset text field
*/
prop_field_init(&(ats->top_attach_offset), attch_ed_cgen->top_offset_label,
attch_ed_cgen->top_offset,
attch_ed_cgen->top_attach_cb);
/*
* Top position text field
*/
prop_field_init(&(ats->top_attach_position), attch_ed_cgen->top_position_label,
attch_ed_cgen->top_position,
attch_ed_cgen->top_attach_cb);
/**********************
* Bottom Attachments *
**********************/
n = 0;
item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_form_xbm_item;
item_val[n] = ATTCH_ED_PARENT; n++;
item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_opposite_form_xbm_item;
item_val[n] = ATTCH_ED_OPPOSITE_PARENT; n++;
item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_widget_xbm_item;
item_val[n] = ATTCH_ED_SIBLING; n++;
item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_opposite_widget_xbm_item;
item_val[n] = ATTCH_ED_OPPOSITE_SIBLING; n++;
item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_position_xbm_item;
item_val[n] = ATTCH_ED_GRIDLINE; n++;
item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_center_position_xbm_item;
item_val[n] = ATTCH_ED_CENTER_GRIDLINE; n++;
item[n] = attch_ed_cgen->bottom_attach_items.bitmaps_attach_none_xbm_item;
item_val[n] = ATTCH_ED_NONE; n++;
prop_options_init(&(ats->bottom_attach_type), NULL,
attch_ed_cgen->bottom_attach, attch_ed_cgen->bottom_attach_menu,
n, item, (XtPointer*)item_val,
attch_ed_cgen->bottom_attach_cb);
/*
* Bottom offset text field
*/
prop_field_init(&(ats->bottom_attach_offset), attch_ed_cgen->bottom_offset_label,
attch_ed_cgen->bottom_offset,
attch_ed_cgen->bottom_attach_cb);
/*
* Bottom position text field
*/
prop_field_init(&(ats->bottom_attach_position), attch_ed_cgen->bottom_position_label,
attch_ed_cgen->bottom_position,
attch_ed_cgen->bottom_attach_cb);
/**********************
* Left Attachments *
**********************/
n = 0;
item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_form_xbm_item;
item_val[n] = ATTCH_ED_PARENT; n++;
item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_opposite_form_xbm_item;
item_val[n] = ATTCH_ED_OPPOSITE_PARENT; n++;
item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_widget_xbm_item;
item_val[n] = ATTCH_ED_SIBLING; n++;
item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_opposite_widget_xbm_item;
item_val[n] = ATTCH_ED_OPPOSITE_SIBLING; n++;
item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_position_xbm_item;
item_val[n] = ATTCH_ED_GRIDLINE; n++;
item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_left_center_position_xbm_item;
item_val[n] = ATTCH_ED_CENTER_GRIDLINE; n++;
item[n] = attch_ed_cgen->left_attach_items.bitmaps_attach_none_xbm_item;
item_val[n] = ATTCH_ED_NONE; n++;
prop_options_init(&(ats->left_attach_type), NULL,
attch_ed_cgen->left_attach, attch_ed_cgen->left_attach_menu,
n, item, (XtPointer*)item_val,
attch_ed_cgen->left_attach_cb);
/*
* Left offset text field
*/
prop_field_init(&(ats->left_attach_offset), attch_ed_cgen->left_offset_label,
attch_ed_cgen->left_offset,
attch_ed_cgen->left_attach_cb);
/*
* Left position text field
*/
prop_field_init(&(ats->left_attach_position), attch_ed_cgen->left_position_label,
attch_ed_cgen->left_position,
attch_ed_cgen->left_attach_cb);
/**********************
* Right Attachments *
**********************/
n = 0;
item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_form_xbm_item;
item_val[n] = ATTCH_ED_PARENT; n++;
item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_opposite_form_xbm_item;
item_val[n] = ATTCH_ED_OPPOSITE_PARENT; n++;
item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_widget_xbm_item;
item_val[n] = ATTCH_ED_SIBLING; n++;
item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_opposite_widget_xbm_item;
item_val[n] = ATTCH_ED_OPPOSITE_SIBLING; n++;
item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_position_xbm_item;
item_val[n] = ATTCH_ED_GRIDLINE; n++;
item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_right_center_position_xbm_item;
item_val[n] = ATTCH_ED_CENTER_GRIDLINE; n++;
item[n] = attch_ed_cgen->right_attach_items.bitmaps_attach_none_xbm_item;
item_val[n] = ATTCH_ED_NONE; n++;
prop_options_init(&(ats->right_attach_type), NULL,
attch_ed_cgen->right_attach, attch_ed_cgen->right_attach_menu,
n, item, (XtPointer*)item_val,
attch_ed_cgen->left_attach_cb);
/*
* Right offset text field
*/
prop_field_init(&(ats->right_attach_offset), attch_ed_cgen->right_offset_label,
attch_ed_cgen->right_offset,
attch_ed_cgen->left_attach_cb);
/*
* Right position text field
*/
prop_field_init(&(ats->right_attach_position), attch_ed_cgen->right_position_label,
attch_ed_cgen->right_position,
attch_ed_cgen->left_attach_cb);
/*
* Setup dialog to participate in dtbuilder window protocol
*/
ab_register_window(attch_ed_cgen->attch_ed_dialog_shellform,
AB_WIN_DIALOG, WindowHidden, AB_toplevel, AB_WPOS_TILE_HORIZONTAL,
attch_edP_prevent_closeCB, NULL);
ret_value = dtb_attch_ed_attch_ed_dialog.attch_ed_dialog_shellform;
/*
* Add callback to detect change in geometry
*/
obj_add_geometry_change_callback(attch_obj_geom_changedCB, "ATTCH_ED");
obj_add_rename_callback(attch_obj_renameCB, "ATTCH_ED");
}
else
{
util_dprintf(3, "attch_editor_props_init: could not initialize Attachment Editor\n");
ret_value = NULL;
}
return(ret_value);
}
static int
attch_editor_load(
ABObjPtr object
)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
load_attch_obj(object, TRUE);
create_children_list(object);
update_attch_obj_parent(object);
update_obj_type(object);
update_objlist(object);
select_objlist(object);
return(0);
}
static void
load_attch_obj(
ABObj object,
BOOL turnoff_cb
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ABAttachment *top_attachment,
*bottom_attachment,
*left_attachment,
*right_attachment;
ATTCH_ED_ATTACH_TYPE top_attach_type = ATTCH_ED_NONE,
bottom_attach_type = ATTCH_ED_NONE,
left_attach_type = ATTCH_ED_NONE,
right_attach_type = ATTCH_ED_NONE;
int top_offset = 0,
top_position = 0,
bottom_offset = 0,
bottom_position = 0,
left_offset = 0,
left_position = 0,
right_offset = 0,
right_position = 0,
cur_position = 1,
child_count = 0,
n = 0;
ABObj top_obj = NULL,
bottom_obj = NULL,
left_obj = NULL,
right_obj = NULL,
*child_list = NULL;
if (object == NULL)
return;
if (!attch_ed_can_edit_attachments(object))
{
ats->cur_object = NULL;
attch_editor_activate(FALSE);
return;
}
attch_editor_activate(TRUE);
/*
* Get attachment info from ABObj
*/
top_attachment = obj_get_attachment(object, AB_CP_NORTH);
bottom_attachment = obj_get_attachment(object, AB_CP_SOUTH);
left_attachment = obj_get_attachment(object, AB_CP_WEST);
right_attachment = obj_get_attachment(object, AB_CP_EAST);
/*
* Get ATTCH_ED_ATTACH_TYPE, offset, position, attached object
*/
get_attach_info(object, top_attachment,
&top_attach_type, &top_offset, &top_position, &top_obj);
get_attach_info(object, bottom_attachment,
&bottom_attach_type, &bottom_offset, &bottom_position, &bottom_obj);
get_attach_info(object, right_attachment,
&right_attach_type, &right_offset, &right_position, &right_obj);
get_attach_info(object, left_attachment,
&left_attach_type, &left_offset, &left_position, &left_obj);
/*
* (Re)Create option menu that lists which objects this
* object can attach to.
*/
create_obj_menu(object);
/*
* Set attachment types
*/
prop_options_set_value(&(ats->top_attach_type), (XtPointer)top_attach_type, False);
prop_options_set_value(&(ats->bottom_attach_type), (XtPointer)bottom_attach_type, False);
prop_options_set_value(&(ats->right_attach_type), (XtPointer)right_attach_type, False);
prop_options_set_value(&(ats->left_attach_type), (XtPointer)left_attach_type, False);
enable_attach_types(object);
/*
* Activate position/offset/objmenu depending on type of attachment
*/
set_widget_state(left_attach_type,
attch_ed_cgen->left_attach_objmenu,
attch_ed_cgen->left_offset_rowcolumn,
attch_ed_cgen->left_position_rowcolumn);
set_widget_state(right_attach_type,
attch_ed_cgen->right_attach_objmenu,
attch_ed_cgen->right_offset_rowcolumn,
attch_ed_cgen->right_position_rowcolumn);
set_widget_state(top_attach_type,
attch_ed_cgen->top_attach_objmenu,
attch_ed_cgen->top_offset_rowcolumn,
attch_ed_cgen->top_position_rowcolumn);
set_widget_state(bottom_attach_type,
attch_ed_cgen->bottom_attach_objmenu,
attch_ed_cgen->bottom_offset_rowcolumn,
attch_ed_cgen->bottom_position_rowcolumn);
/*
* Set values for position/offset/objmenu depending on type of attachment
* i.e. if attachment is of type ATTCH_ED_PARENT, don't set the position
* value.
*/
set_attach_values(left_attach_type,
&(ats->left_attach_offset),
&(ats->left_attach_position),
&(ats->left_attach_obj),
left_offset,
left_position,
left_obj);
set_attach_values(right_attach_type,
&(ats->right_attach_offset),
&(ats->right_attach_position),
&(ats->right_attach_obj),
right_offset,
right_position,
right_obj);
set_attach_values(top_attach_type,
&(ats->top_attach_offset),
&(ats->top_attach_position),
&(ats->top_attach_obj),
top_offset,
top_position,
top_obj);
set_attach_values(bottom_attach_type,
&(ats->bottom_attach_offset),
&(ats->bottom_attach_position),
&(ats->bottom_attach_obj),
bottom_offset,
bottom_position,
bottom_obj);
/*
* Set object name
*/
ats->cur_object = object;
ui_set_label_string(attch_ed_cgen->obj_label, obj_get_name(object));
attch_ed_activate_parent_child_button();
if (turnoff_cb)
turnoff_changebars();
}
/*
* Update list containing siblings of object that is currently edited
*/
static void
create_children_list(
ABObj obj
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ABObj parent,
*child_list,
cur_child;
AB_TRAVERSAL trav;
int child_count,
i,
cur_position = 0;
if (!obj)
return;
parent = attch_ed_get_parent(obj);
if (!parent)
return;
/*
* Populate siblings list
if ((!ats->cur_object) || (obj_get_parent(ats->cur_object) != parent))
*/
if (1)
{
/*
* Get array of child objects on list widget
*/
XtVaGetValues(attch_ed_cgen->childrenlist,
XmNuserData, &child_list,
NULL);
/*
* List of child objects:
* Free it
* Nullify XmNuserData
*/
if (child_list)
{
util_free(child_list);
XtVaSetValues(attch_ed_cgen->childrenlist, XmNuserData, NULL, NULL);
}
/*
* Get child count
*/
child_count = trav_count(parent, AB_TRAV_SALIENT_CHILDREN);
/*
* Delete all current items in list
*/
XmListDeleteAllItems(attch_ed_cgen->childrenlist);
/*
* Return if no children to insert in list
*/
if (child_count <= 0)
return;
/*
* Alloc new array to store child objects. This will be stored
* as user data on the list.
*/
child_list = (ABObj *)util_malloc(child_count*sizeof(ABObj));
/*
* For all direct children of 'parent'.:
* add to XmList object
* add to ABObj list
* remember position of 'object' in list
*/
for (i = 1, trav_open(&trav, parent, AB_TRAV_SALIENT_CHILDREN);
(cur_child = trav_next(&trav)) != NULL; ++i)
{
if (cur_child == obj)
{
cur_position = i;
}
child_list[i-1] = cur_child;
ui_list_add_item(attch_ed_cgen->childrenlist, obj_get_name(cur_child), 0);
}
/*
* Make current object selected, and visible in list
*/
ui_list_select_pos(attch_ed_cgen->childrenlist, cur_position, False);
/*
* Store ABObj list on XmList object
*/
XtVaSetValues(attch_ed_cgen->childrenlist, XmNuserData, child_list, NULL);
/*
* Register callback on list that will load selected object
*/
XtAddCallback(attch_ed_cgen->childrenlist, XmNbrowseSelectionCallback,
attch_ed_select_itemCB, (XtPointer)NULL);
}
}
static void
update_attch_obj_parent(
ABObj obj
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ABObj parent;
if (!obj)
return;
parent = attch_ed_get_parent(obj);
if (parent)
parent = obj_get_root(parent);
/*
* Set object parent's name
*/
if (parent)
ui_set_label_string(attch_ed_cgen->parent_obj_name,
obj_get_name(parent));
}
static void
update_obj_type(
ABObj obj
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
PalEditableObjInfo *ed_obj_info;
if (!obj)
return;
AttchEdObjTypeInfo.type = obj_get_type(obj);
AttchEdObjTypeInfo.subtype = obj_get_subtype(obj);
if ((ed_obj_info = pal_get_editable_obj_info(obj)) &&
editable_obj_test(ed_obj_info))
{
ui_optionmenu_change_label(attch_ed_cgen->obj_type_opmenu,
istr_string(ed_obj_info->name));
}
}
static void
update_objlist(
ABObj obj
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
ABObj proj = proj_get_project();
int num_items;
if (!obj)
return;
num_items = abobj_list_load(attch_ed_cgen->objlist,
proj,
attch_objlist_test_func);
}
static void
select_objlist(
ABObj obj
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
char *modname = NULL;
if (!obj)
return;
modname = abobj_get_moduled_name(obj);
if (modname)
{
ui_list_select_item(attch_ed_cgen->objlist, modname, FALSE);
util_free(modname);
}
}
static int
attch_editor_apply(
ABObjPtr object
)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ABAttachment attachment;
ATTCH_ED_ATTACH_TYPE attach_type = ATTCH_ED_NONE;
int offset = 0,
position = 0;
ABObj obj = NULL;
if (object == NULL)
return ERROR;
if (!attch_ed_verify_props())
return ERROR;
/*
* Top attachment
*/
if (prop_changed(ats->top_attach_type.changebar))
{
attach_type =
(ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->top_attach_type));
get_attach_values(attach_type,
&(ats->top_attach_offset),
&(ats->top_attach_position),
&(ats->top_attach_obj),
&offset, &position, (XtPointer *)&obj);
set_attach_info(object,
&attachment, attach_type, offset, position, obj);
abobj_set_attachment(object, AB_CP_NORTH, &attachment);
}
/*
* Bottom attachment
*/
if (prop_changed(ats->bottom_attach_type.changebar))
{
attach_type = (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->bottom_attach_type));
get_attach_values(attach_type,
&(ats->bottom_attach_offset),
&(ats->bottom_attach_position),
&(ats->bottom_attach_obj),
&offset, &position, (XtPointer *)&obj);
set_attach_info(object,
&attachment, attach_type, offset, position, obj);
abobj_set_attachment(object, AB_CP_SOUTH, &attachment);
}
/*
* Left attachment
*/
if (prop_changed(ats->left_attach_type.changebar))
{
attach_type = (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->left_attach_type));
get_attach_values(attach_type,
&(ats->left_attach_offset),
&(ats->left_attach_position),
&(ats->left_attach_obj),
&offset, &position, (XtPointer *)&obj);
set_attach_info(object,
&attachment, attach_type, offset, position, obj);
abobj_set_attachment(object, AB_CP_WEST, &attachment);
}
/*
* Right attachment - shares changebar with left attachment
*/
if (prop_changed(ats->left_attach_type.changebar))
{
attach_type = (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->right_attach_type));
get_attach_values(attach_type,
&(ats->right_attach_offset),
&(ats->right_attach_position),
&(ats->right_attach_obj),
&offset, &position, (XtPointer *)&obj);
set_attach_info(object,
&attachment, attach_type, offset, position, obj);
abobj_set_attachment(object, AB_CP_EAST, &attachment);
}
abobj_instantiate_changes(object);
turnoff_changebars();
return OK;
}
static BOOL
attch_edP_pending(void)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
if (ats && ats->cur_object && prop_changebars_pending(ats->prop_sheet))
return (TRUE);
return (FALSE);
}
static int
attch_editor_activate(
BOOL active
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
/*
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ui_set_active(ats->prop_sheet, active);
*/
ui_set_active(attch_ed_cgen->attachments_panel, active);
return(OK);
}
static void
turnoff_changebars(void)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
prop_set_changebar(ats->top_attach_type.changebar, PROP_CB_OFF);
prop_set_changebar(ats->bottom_attach_type.changebar, PROP_CB_OFF);
prop_set_changebar(ats->left_attach_type.changebar, PROP_CB_OFF);
prop_changebars_cleared(ats->prop_sheet);
}
static void
get_attach_info(
ABObj obj,
ABAttachment *attachment,
ATTCH_ED_ATTACH_TYPE *type,
int *offset,
int *position,
ABObj *attach_obj
)
{
if (!obj || !attachment)
return;
*offset = 0;
*position = 0;
*attach_obj = NULL;
switch (attachment->type)
{
case AB_ATTACH_POINT:
*type = ATTCH_ED_PARENT;
*offset = attachment->offset;
break;
case AB_ATTACH_OBJ:
*attach_obj = (ABObj)attachment->value;
if (*attach_obj == attch_ed_get_parent(obj))
*type = ATTCH_ED_PARENT;
else
*type = ATTCH_ED_SIBLING;
*offset = attachment->offset;
break;
case AB_ATTACH_ALIGN_OBJ_EDGE:
*attach_obj = (ABObj)attachment->value;
if (*attach_obj == attch_ed_get_parent(obj))
*type = ATTCH_ED_OPPOSITE_PARENT;
else
*type = ATTCH_ED_OPPOSITE_SIBLING;
*offset = attachment->offset;
break;
case AB_ATTACH_GRIDLINE:
*type = ATTCH_ED_GRIDLINE;
*offset = attachment->offset;
*position = (int)(intptr_t) attachment->value;
break;
case AB_ATTACH_CENTER_GRIDLINE:
*type = ATTCH_ED_CENTER_GRIDLINE;
*position = (int)(intptr_t) attachment->value;
*offset = 0;
break;
case AB_ATTACH_NONE:
*type = ATTCH_ED_NONE;
break;
default:
fprintf(stderr, "get_attach_info: attachment is unresolved\n");
break;
}
}
static void
set_attach_info(
ABObj obj,
ABAttachment *attachment,
ATTCH_ED_ATTACH_TYPE type,
int offset,
int position,
ABObj attach_obj
)
{
switch (type)
{
case ATTCH_ED_PARENT:
/*
attachment->value = (void *)attach_obj;
attachment->value = (void *)attch_ed_get_parent(obj);
*/
attachment->type = AB_ATTACH_POINT;
attachment->offset = offset;
break;
case ATTCH_ED_SIBLING:
attachment->value = (void *)attach_obj;
attachment->type = AB_ATTACH_OBJ;
attachment->offset = offset;
break;
case ATTCH_ED_OPPOSITE_PARENT:
attachment->value = (void *)attch_ed_get_parent(obj);
attachment->type = AB_ATTACH_ALIGN_OBJ_EDGE;
attachment->offset = offset;
break;
case ATTCH_ED_OPPOSITE_SIBLING:
attachment->value = (void *)attach_obj;
attachment->type = AB_ATTACH_ALIGN_OBJ_EDGE;
attachment->offset = offset;
break;
case ATTCH_ED_GRIDLINE:
attachment->type = AB_ATTACH_GRIDLINE;
attachment->value = (void *)(intptr_t) position;
attachment->offset = offset;
break;
case ATTCH_ED_CENTER_GRIDLINE:
attachment->type = AB_ATTACH_CENTER_GRIDLINE;
attachment->value = (void *)(intptr_t) position;
attachment->offset = 0;
break;
case ATTCH_ED_NONE:
attachment->type = AB_ATTACH_NONE;
break;
default:
fprintf(stderr, "set_attach_info: attachment is unresolved\n");
break;
}
}
static void
attch_ed_select_itemCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
)
{
XmListCallbackStruct *listdata = (XmListCallbackStruct *)call_data;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ABObj *child_list = NULL,
new_obj = NULL;
int num_items = 0, pos;
XtVaGetValues(widget,
XmNuserData, &child_list,
XmNitemCount, &num_items,
NULL);
if (!child_list)
return;
pos = ui_list_get_selected_pos(widget);
if (pos > 0)
new_obj = child_list[pos-1];
if (new_obj != ats->cur_object)
{
ABObj old_obj = ats->cur_object;
DTB_MODAL_ANSWER answer = DTB_ANSWER_ACTION1;
if (attch_edP_pending())
{
answer = get_wrn_response(AB_attch_ed_dialog, ATTCH_ED_WRN_LOAD,
new_obj);
if (answer == DTB_ANSWER_CANCEL)
{
char *name;
name = obj_get_name(old_obj);
ui_list_select_item(widget, name, FALSE);
}
}
if (answer != DTB_ANSWER_ACTION1)
return;
load_attch_obj(new_obj, TRUE);
update_obj_type(new_obj);
/*
* Update object list
* If type of object did not change just select new object in list
* otherwise, reload the list
*/
if (old_obj &&
(pal_get_item_info(old_obj) == pal_get_item_info(new_obj)))
{
select_objlist(new_obj);
}
else
{
update_objlist(new_obj);
select_objlist(new_obj);
}
}
}
/*
* create_obj_menu()
* Updates the sibling option menu for all attachments of
* 'object'. This is necessary only for attachments that
* need 'which sibling?' info.
*/
static void
create_obj_menu(
ABObj object
)
{
ABAttachment *attachment;
ATTCH_ED_ATTACH_TYPE attach_type = ATTCH_ED_NONE;
int offset,
position;
ABObj obj;
/*
* Top attachment
*/
attachment = obj_get_attachment(object, AB_CP_NORTH);
get_attach_info(object, attachment,
&attach_type, &offset, &position, &obj);
if (attch_ed_need_obj_menu(attach_type))
create_obj_menu_dir(object, AB_CP_NORTH);
/*
* Bottom attachment
*/
attachment = obj_get_attachment(object, AB_CP_SOUTH);
get_attach_info(object, attachment,
&attach_type, &offset, &position, &obj);
if (attch_ed_need_obj_menu(attach_type))
create_obj_menu_dir(object, AB_CP_SOUTH);
/*
* Left attachment
*/
attachment = obj_get_attachment(object, AB_CP_WEST);
get_attach_info(object, attachment,
&attach_type, &offset, &position, &obj);
if (attch_ed_need_obj_menu(attach_type))
create_obj_menu_dir(object, AB_CP_WEST);
/*
* Right attachment
*/
attachment = obj_get_attachment(object, AB_CP_EAST);
get_attach_info(object, attachment,
&attach_type, &offset, &position, &obj);
if (attch_ed_need_obj_menu(attach_type))
create_obj_menu_dir(object, AB_CP_EAST);
}
/*
* delete_from_obj_menu()
* Deletes the passed object from the object menu setting on the
* editor.
*/
static void
delete_from_obj_menu(
ABObj cur_obj,
ABObj deleted_obj
)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ABAttachment *attachment;
ATTCH_ED_ATTACH_TYPE attach_type = ATTCH_ED_NONE;
int offset,
position;
ABObj obj;
if (!cur_obj || !deleted_obj)
return;
/*
* Top attachment
*/
attachment = obj_get_attachment(cur_obj, AB_CP_NORTH);
get_attach_info(cur_obj, attachment,
&attach_type, &offset, &position, &obj);
if (attch_ed_need_obj_menu(attach_type))
prop_options_remove_value(&(ats->top_attach_obj),
(XtPointer)deleted_obj, False);
/*
* Bottom attachment
*/
attachment = obj_get_attachment(cur_obj, AB_CP_SOUTH);
get_attach_info(cur_obj, attachment,
&attach_type, &offset, &position, &obj);
if (attch_ed_need_obj_menu(attach_type))
prop_options_remove_value(&(ats->bottom_attach_obj),
(XtPointer)deleted_obj, False);
/*
* Left attachment
*/
attachment = obj_get_attachment(cur_obj, AB_CP_WEST);
get_attach_info(cur_obj, attachment,
&attach_type, &offset, &position, &obj);
if (attch_ed_need_obj_menu(attach_type))
prop_options_remove_value(&(ats->left_attach_obj),
(XtPointer)deleted_obj, False);
/*
* Right attachment
*/
attachment = obj_get_attachment(cur_obj, AB_CP_EAST);
get_attach_info(cur_obj, attachment,
&attach_type, &offset, &position, &obj);
if (attch_ed_need_obj_menu(attach_type))
prop_options_remove_value(&(ats->right_attach_obj),
(XtPointer)deleted_obj, False);
}
/*
* create_obj_menu_dir()
* Updates the sibling option menu for one attachment of
* 'object' as specified by 'dir'.
* The option menu is also initialized to have the first
* entry of the menu as it's initial value.
*/
static void
create_obj_menu_dir(
ABObj object,
AB_COMPASS_POINT dir
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
PropOptionsSetting option_setting = NULL;
Widget label = NULL,
optionbox = NULL,
menu = NULL,
changebar = NULL,
*item = NULL;
int item_values = 0,
*item_val = NULL,
n = 0;
/*
* Return immediately if bad params
*/
if (!object)
return;
/*
* Depending on what direction, remember what widgets/settings
* to set.
*/
switch (dir)
{
case AB_CP_NORTH:
option_setting = &(ats->top_attach_obj);
optionbox = attch_ed_cgen->top_attach_objmenu;
menu = attch_ed_cgen->top_attach_objmenu_menu;
changebar = attch_ed_cgen->top_attach_cb;
break;
case AB_CP_SOUTH:
option_setting = &(ats->bottom_attach_obj);
optionbox = attch_ed_cgen->bottom_attach_objmenu;
menu = attch_ed_cgen->bottom_attach_objmenu_menu;
changebar = attch_ed_cgen->bottom_attach_cb;
break;
case AB_CP_WEST:
option_setting = &(ats->left_attach_obj);
optionbox = attch_ed_cgen->left_attach_objmenu;
menu = attch_ed_cgen->left_attach_objmenu_menu;
changebar = attch_ed_cgen->left_attach_cb;
break;
case AB_CP_EAST:
option_setting = &(ats->right_attach_obj);
optionbox = attch_ed_cgen->right_attach_objmenu;
menu = attch_ed_cgen->right_attach_objmenu_menu;
/* right/left menus share changebars */
changebar = attch_ed_cgen->left_attach_cb;
break;
}
/*
* If widgets/prop setting is NULL, return immediately
*/
if (!option_setting || !optionbox || !menu || !changebar)
return;
populate_obj_menu(menu, object, dir, &item, (XtPointer **)&item_val, &n);
prop_options_init(option_setting, NULL,
optionbox,
menu,
n, item, (XtPointer*)item_val,
changebar);
/*
* If there were items, set the value of the setting to be the
* first one
*/
if (n > 0)
prop_options_set_value(option_setting, (XtPointer)(uintptr_t) item_val[0], False);
if (item)
util_free(item);
if (item_val)
util_free(item_val);
}
/*
* populate_obj_menu()
* Inserts/Modifies the children of 'widget' to contain items
* that have, as labels, the names of the sibling objects of
* 'objects'.
* The list of widget items is returned in 'ret_item'.
* The list of ABObj pointers (siblings of 'object') is returned in
* 'ret_item_val'.
* The number of items is returned in 'n'.
* The lists returned are allocated in this function. It is up to
* the caller to free them.
*/
static void
populate_obj_menu(
Widget widget,
ABObj object,
AB_COMPASS_POINT dir,
Widget **ret_item,
XtPointer **ret_item_val,
int *n
)
{
AB_TRAVERSAL trav;
ABObj parent,
cur_obj;
Widget *item_list = NULL;
WidgetList menu_children;
XtPointer *item_val_list = NULL;
int i,
num_menu_children,
num_items_needed,
num_trav_children;
static BOOL first_time = TRUE;
if (!widget || !object)
return;
parent = attch_ed_get_parent(object);
if (!parent)
return;
if (first_time)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
/*
* Set up callabcks for menu items created in _ui.c file
*/
XtAddCallback(attch_ed_cgen->left_attach_objmenu_items.Object1_item,
XmNactivateCallback,
attach_obj_changed, (XtPointer)AB_CP_WEST);
XtAddCallback(attch_ed_cgen->right_attach_objmenu_items.Object1_item,
XmNactivateCallback,
attach_obj_changed, (XtPointer)AB_CP_EAST);
XtAddCallback(attch_ed_cgen->top_attach_objmenu_items.Object1_item,
XmNactivateCallback,
attach_obj_changed, (XtPointer)AB_CP_NORTH);
XtAddCallback(attch_ed_cgen->bottom_attach_objmenu_items.Object1_item,
XmNactivateCallback,
attach_obj_changed, (XtPointer)AB_CP_SOUTH);
first_time = FALSE;
}
num_trav_children = trav_count(parent, AB_TRAV_SALIENT_CHILDREN);
/*
* The number of menu items we need is one less that the total child
* count.
*/
num_items_needed = (num_trav_children > 0)
? num_trav_children - 1
: 0;
/*
* Allocate lists to store widget id's and ABObj pointers
*/
if (num_items_needed > 0)
{
item_list = (Widget *)util_malloc(num_items_needed * sizeof(Widget));
item_val_list = (XtPointer *)
util_malloc(num_items_needed * sizeof(XtPointer));
}
/*
* Get current list of menu items
*/
XtVaGetValues(widget,
XmNnumChildren, &num_menu_children,
XmNchildren, &menu_children,
NULL);
if (num_items_needed > num_menu_children)
{
/*
* Create more menu items if needed
*/
for (i = num_menu_children; i < num_items_needed; ++i)
{
Widget menu_item;
menu_item = XtVaCreateWidget("attach_obj_menu",
xmPushButtonWidgetClass,
widget,
NULL);
XtAddCallback(menu_item, XmNactivateCallback,
attach_obj_changed, (XtPointer)dir);
}
/*
* Re-fetch list of menu items
*/
XtVaGetValues(widget,
XmNnumChildren, &num_menu_children,
XmNchildren, &menu_children,
NULL);
}
/*
* Set the label of the menu items to be the names of the ABObj's
*/
for (i = 0, trav_open(&trav, parent, AB_TRAV_SALIENT_CHILDREN);
i < num_items_needed, (cur_obj = trav_next(&trav)) != NULL; )
{
char *label;
/*
* Skip the passed object.
* We are only interested in the siblings of 'object'
*/
if (cur_obj == object)
continue;
/*
* Get label of ABObj
*/
label = obj_get_name(cur_obj);
/*
* Store the widget id of current menu item
*/
item_list[i] = menu_children[i];
/*
* If label exists, set it on the menu item
*/
if (label)
XtVaSetValues(item_list[i],
XtVaTypedArg, XmNlabelString, XtRString,
label, strlen(label)+1,
NULL);
/*
* Store ABObj ptr
*/
item_val_list[i] = (XtPointer)cur_obj;
++i;
}
/*
* Manage only the needed menu items; hide/unmanage the rest
*/
if (num_items_needed > 0)
{
for (i = 0; i < num_items_needed; ++i)
XtManageChild(menu_children[i]);
for (i = num_items_needed; i < num_menu_children; ++i)
XtUnmanageChild(menu_children[i]);
}
/*
* Special case:
* If no siblings, create/manage one item with "None" label.
*/
if (num_items_needed == 0)
{
Widget none_item;
if (num_menu_children == 0)
{
none_item = XtVaCreateWidget("attach_obj_menu",
xmPushButtonWidgetClass,
widget,
NULL);
}
else
{
none_item = menu_children[0];
}
XtVaSetValues(none_item,
XtVaTypedArg, XmNlabelString, XtRString,
"None", strlen("None")+1,
XmNuserData, NULL,
NULL);
XtManageChild(none_item);
}
*ret_item = item_list;
*ret_item_val = item_val_list;
*n = num_items_needed;
}
static BOOL
attch_objlist_test_func(
ABObj test_obj
)
{
ABObj module;
BOOL b;
if (!test_obj || !obj_is_defined(test_obj))
return (False);
module = obj_get_module(test_obj);
if ((module != NULL) &&
obj_is_salient_ui(test_obj) &&
obj_has_flag(module, MappedFlag))
{
b = attch_ed_obj_is_target_type(test_obj);
return(b);
}
return(False);
}
static BOOL
attch_ed_obj_is_target_type(
ABObj obj
)
{
PalItemInfo *palitem;
AB_OBJECT_TYPE type;
int subtype;
if (!obj)
return (FALSE);
type = obj_get_type(obj);
subtype = obj_get_subtype(obj);
palitem = pal_get_type_item_info(AttchEdObjTypeInfo.type,
AttchEdObjTypeInfo.subtype);
if (palitem && palitem->is_a_test)
return ((*palitem->is_a_test)(obj));
switch (AttchEdObjTypeInfo.type)
{
case AB_TYPE_ITEM:
case AB_TYPE_CONTAINER:
if (type == AttchEdObjTypeInfo.type &&
subtype == AttchEdObjTypeInfo.subtype)
return(TRUE);
else
return(FALSE);
break;
default:
/*
* Otherwise we only need to check object type, and in fact
* don't want to check subtype because it might confuse things
* (e.g. we're looking for any Button palette item, which
* includes several subtypes of type AB_TYPE_BUTTON).
*/
if(type == AttchEdObjTypeInfo.type)
return(TRUE);
else
return(FALSE);
break;
}
/* Should never get here - every test above returns True or False */
}
static BOOL
attch_childrenlist_test_func(
ABObj test_obj
)
{
if (!test_obj || !attch_cur_parent)
return (False);
if (attch_ed_get_parent(test_obj) == attch_cur_parent)
return (True);
return(False);
}
/*
* Callback: a new object type has been selected off object type menu
* This is for 'regular' palette objects
*/
static void
attch_change_objecttypePalCB(
Widget widget,
XtPointer client_data,
XtPointer calldata
)
{
PalEditableObjInfo *ed_obj_info = (PalEditableObjInfo*)client_data;
attch_ed_change_objecttype(ed_obj_info->type, ed_obj_info->subtype);
}
static void
attch_ed_change_objecttype(
AB_OBJECT_TYPE type,
int subtype
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen = &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ABObj proj = proj_get_project();
int num_items;
char *modname = NULL;
DTB_MODAL_ANSWER answer = DTB_ANSWER_ACTION1;
if (!proj || !attch_ed_cgen->objlist)
return;
if (attch_edP_pending())
{
answer = get_wrn_response(AB_attch_ed_dialog, ATTCH_ED_WRN_CHANGE_OBJTYPE,
NULL);
if (answer == DTB_ANSWER_CANCEL)
update_obj_type(ats->cur_object);
}
if (answer != DTB_ANSWER_ACTION1)
return;
/*
* Reset current object
*/
ats->cur_object = NULL;
AttchEdObjTypeInfo.type = type;
AttchEdObjTypeInfo.subtype = subtype;
num_items = abobj_list_load(attch_ed_cgen->objlist, proj, attch_objlist_test_func);
/*
* If number of items in object list is > 0,
* make attachment editor active and edit the
* first object in list the current one.
* Otherwise, make editor inactive.
*/
if (num_items > 0)
{
attch_editor_activate(TRUE);
ui_list_select_pos(attch_ed_cgen->objlist, 1, TRUE);
}
else
{
attch_editor_activate(FALSE);
}
}
static void
attch_objlist_selectCB(
Widget widget,
XtPointer client_data,
XmListCallbackStruct *listdata
)
{
ABObj module;
ABObj selected_obj;
STRING name;
name = objxm_xmstr_to_str(listdata->item);
if (name)
{
abobj_moduled_name_extract(name, &module, &selected_obj);
util_free(name);
if (selected_obj)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
DTB_MODAL_ANSWER answer = DTB_ANSWER_ACTION1;
ABObj parent;
Widget parent_widget;
char *name = obj_get_name(selected_obj);
if (attch_edP_pending())
{
answer = get_wrn_response(AB_attch_ed_dialog,
ATTCH_ED_WRN_LOAD, selected_obj);
if (answer == DTB_ANSWER_CANCEL)
select_objlist(ats->cur_object);
}
if (answer != DTB_ANSWER_ACTION1)
return;
/*
* Load selected object
*/
load_attch_obj(selected_obj, TRUE);
/*
* If load succeeded, create new children list,
* and update parent label
if (ats->cur_object) {
*/
create_children_list(selected_obj);
update_attch_obj_parent(selected_obj);
/*
}
*/
}
}
}
static int
attch_obj_geom_changedCB(
ObjEvAttChangeInfo evInfo
)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ABObj obj = evInfo->obj;
if (!obj)
return 0;
/*
* Do only if position or size changed
*/
if ((evInfo->atts & OBJEV_ATT_POSITION) ||
(evInfo->atts & OBJEV_ATT_SIZE))
{
if (ats->cur_object == obj)
{
/*
* Reload attachments of object into attachments editor,
* keep changebars state as-is
*/
load_attch_obj(obj, FALSE);
}
}
return 0;
}
static int
attch_obj_destroyCB(
ObjEvDestroyInfo info
)
{
handle_actual_obj_destroy(info);
handle_prop_sheet_obj_destroy(info);
return (0);
}
static int
attch_obj_reparentCB(
ObjEvReparentInfo info
)
{
handle_actual_obj_reparent(info);
handle_prop_sheet_obj_reparent(info);
return (0);
}
static void
handle_prop_sheet_obj_destroy(
ObjEvDestroyInfo info
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats
= &attch_editor_settings_rec;
ABObj obj = info->obj;
int num_items, first_viz, last_viz;
if (!AB_attch_ed_dialog ||
!obj_is_salient(obj) || obj_is_item(obj) || !ats->cur_object)
return;
/*
* Update object list only if the renamed object is the same
* type as the one that is currently visible.
*/
abobj_list_obj_destroyed(attch_ed_cgen->objlist, obj,
attch_objlist_test_func);
ui_list_get_info(attch_ed_cgen->objlist, &num_items, &first_viz, &last_viz);
if (num_items == 0)
{
/*
* Deleted last item
* Reset current object and inactivate editor
*/
ats->cur_object = NULL;
attch_editor_activate(FALSE);
}
else if (obj == ats->cur_object)
{
/*
* Delete current object
* Select 1st item in list, and make it the edited object
*/
ui_list_select_pos(attch_ed_cgen->objlist, 1, TRUE);
}
else if (obj_is_sibling(obj, ats->cur_object))
{
/*
* Sibling of current object deleted
* Update attached object - to keep the sibling list option menu
* current.
* Update children list.
* enable/disable sibling attachment types
*
* NOTE: should check if the object deleted is an 'attached-to' object.
*
* REMIND: create_children_list() loads the list
* Should manipulate the children list with the abobj_list_obj_destroyed()
* API. Currently, it is loaded directly using the trav API.
load_attch_obj(ats->cur_object, TRUE);
*/
delete_from_obj_menu(ats->cur_object, obj);
create_children_list(ats->cur_object);
enable_attach_types(ats->cur_object);
}
}
static void
handle_actual_obj_destroy(
ObjEvDestroyInfo info
)
{
ABObjList refList;
ABObj obj,
refObj,
project;
void *voidRefType = NULL;
AB_OBJ_REF_TYPE refType = AB_REF_UNDEF;
ABAttachment *attachment;
ATTCH_ED_ATTACH_TYPE attach_type;
AB_COMPASS_POINT dir;
int i,
numRefs,
offset,
position;
if (!info)
return;
obj = info->obj;
if (!(project = obj_get_project(obj)))
return;
/*
* If the entire project is curently being destroyed,
* skip this
*/
if (obj_has_flag(project, BeingDestroyedFlag))
return;
if (!attch_ed_can_edit_attachments(obj))
return;
refList = obj_get_refs_to(obj);
if (!refList)
return;
numRefs = objlist_get_num_objs(refList);
for (i = 0; i < numRefs; ++i)
{
BOOL attach_ref;
refObj = objlist_get_obj(refList, i, &voidRefType);
if (!refObj || obj_is_descendant_of(refObj, obj))
continue;
refType = (AB_OBJ_REF_TYPE)voidRefType;
switch (refType)
{
/*
* The ref object may have different attachments to
* 'obj'
*/
case AB_REF_ATTACH_EAST:
case AB_REF_ATTACH_NORTH:
case AB_REF_ATTACH_SOUTH:
case AB_REF_ATTACH_WEST:
attach_ref = TRUE;
break;
default:
attach_ref = FALSE;
break;
}
if (attach_ref)
{
/*
* If there are any attachments from this object that involve
* 'obj', change them to AB_ATTACH_POINT
*/
change_attype_from_sib_to_point(refObj, obj, AB_CP_NORTH, FALSE);
change_attype_from_sib_to_point(refObj, obj, AB_CP_SOUTH, FALSE);
change_attype_from_sib_to_point(refObj, obj, AB_CP_EAST, FALSE);
change_attype_from_sib_to_point(refObj, obj, AB_CP_WEST, FALSE);
}
}
}
static void
handle_prop_sheet_obj_reparent(
ObjEvReparentInfo info
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats
= &attch_editor_settings_rec;
ABObj obj = info->obj;
int num_items, first_viz, last_viz;
if (!AB_attch_ed_dialog ||
!obj_is_salient(obj) || obj_is_item(obj) || !ats->cur_object)
return;
}
static void
change_attype_from_sib_to_point(
ABObj obj,
ABObj attach_to_sib,
AB_COMPASS_POINT dir,
BOOL reparent
)
{
ABAttachment *attachment;
AB_ATTACH_TYPE attach_type;
attachment = obj_get_attachment(obj, dir);
if (!attachment)
return;
attach_type = obj_get_attach_type(obj, dir);
if ((attach_type == AB_ATTACH_OBJ) ||
(attach_type == AB_ATTACH_ALIGN_OBJ_EDGE))
{
ABObj attach_obj;
int offset,
position;
/*
* Get sibling obj that this object is attached to
*/
attach_obj = (ABObj)obj_get_attach_value(obj, dir);
/*
* Do not convert attachment type if:
* attach_obj == object (attach to itself)
*
*/
if (!attach_obj || (obj == attach_obj))
return;
/*
* If the triggering event was a reparent, and
* obj and attach_obj are still siblings, do not
* convert
*/
if (reparent && obj_is_sibling(obj, attach_obj))
return;
/*
* If a specific sibling was passed in, make sure
* attach_obj matches it. If not, do not convert.
*/
if (attach_to_sib && (attach_to_sib != attach_obj))
return;
convert_offset_position(obj, NULL, dir, ATTCH_ED_PARENT,
&offset, &position);
obj_set_attachment(obj, dir, AB_ATTACH_POINT,
(void *)(uintptr_t) position, offset);
objxm_obj_set_attachment_args(obj, OBJXM_CONFIG_BUILD);
}
}
static void
handle_actual_obj_reparent(
ObjEvReparentInfo info
)
{
ABObjList refList;
ABObj obj,
refObj,
parent;
void *voidRefType = NULL;
AB_OBJ_REF_TYPE refType = AB_REF_UNDEF;
ABAttachment *attachment;
ATTCH_ED_ATTACH_TYPE attach_type;
AB_COMPASS_POINT dir;
int i,
numRefs,
offset,
position;
if (!info)
return;
obj = info->obj;
/*
* name == NULL
* -> New object dragged off from palette
* Don't need to worry about attachments here
*/
if (obj_get_name(obj) == NULL)
return;
/*
* The old parent is NULL
* Don't need to worry about attachments here
*/
if (!info->old_parent)
return;
if (!attch_ed_can_edit_attachments(obj))
return;
/*
* If there are any attachments from this object that involve
* sibling objects, change them to AB_ATTACH_POINT
*/
change_attype_from_sib_to_point(obj, NULL, AB_CP_NORTH, TRUE);
change_attype_from_sib_to_point(obj, NULL, AB_CP_SOUTH, TRUE);
change_attype_from_sib_to_point(obj, NULL, AB_CP_EAST, TRUE);
change_attype_from_sib_to_point(obj, NULL, AB_CP_WEST, TRUE);
/*
* If there are attachments *to* this object, change them
* to AB_ATTACH_POINT
*/
refList = obj_get_refs_to(obj);
if (!refList)
return;
numRefs = objlist_get_num_objs(refList);
for (i = 0; i < numRefs; ++i)
{
BOOL attach_ref;
refObj = objlist_get_obj(refList, i, &voidRefType);
if (!refObj || obj_is_descendant_of(refObj, obj))
continue;
refType = (AB_OBJ_REF_TYPE)voidRefType;
switch (refType)
{
/*
* The ref object may have different attachments to
* 'obj'
*/
case AB_REF_ATTACH_EAST:
case AB_REF_ATTACH_NORTH:
case AB_REF_ATTACH_SOUTH:
case AB_REF_ATTACH_WEST:
attach_ref = TRUE;
break;
default:
attach_ref = FALSE;
break;
}
if (attach_ref)
{
/*
* If there are any attachments from this object that involve
* 'obj', change them to AB_ATTACH_POINT
*/
change_attype_from_sib_to_point(refObj, obj, AB_CP_NORTH, TRUE);
change_attype_from_sib_to_point(refObj, obj, AB_CP_SOUTH, TRUE);
change_attype_from_sib_to_point(refObj, obj, AB_CP_EAST, TRUE);
change_attype_from_sib_to_point(refObj, obj, AB_CP_WEST, TRUE);
}
}
}
static int
attch_obj_renameCB(
ObjEvAttChangeInfo info
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats
= &attch_editor_settings_rec;
ABObj obj = info->obj,
root_parent;
if (!AB_attch_ed_dialog ||
!obj_is_salient(obj) || obj_is_item(obj) || !ats->cur_object)
return (0);
if (obj_is_module(obj))
{
if ((obj_get_module(ats->cur_object) == obj_get_module(obj)))
{
abobj_list_obj_renamed(attch_ed_cgen->objlist,
obj,
istr_string(info->old_name),
attch_objlist_test_func);
}
}
else
{
/*
* Update object list only if the renamed object is the same
* type as the one that is currently visible.
*/
abobj_list_obj_renamed(attch_ed_cgen->objlist,
obj,
istr_string(info->old_name),
attch_objlist_test_func);
/*
* Update/reload attached object if:
* the attached object was renamed
* any of the attached object's siblings got renamed
*/
if ((obj == ats->cur_object) || obj_is_sibling(obj, ats->cur_object))
{
/*
* REMIND: load_attch_obj() loads the list
* Should manipulate the children list with the
* abobj_list_obj_renamed() API. Currently, it is loaded
* directly using the trav API.
*/
load_attch_obj(ats->cur_object, TRUE);
create_children_list(ats->cur_object);
enable_attach_types(ats->cur_object);
}
root_parent = attch_ed_get_parent(ats->cur_object);
if (root_parent)
root_parent = obj_get_root(root_parent);
/*
* If current object's parent is renamed, update
* parent object label
*/
if (obj == root_parent)
{
update_attch_obj_parent(ats->cur_object);
}
}
return 0;
}
static void
set_widget_state(
ATTCH_ED_ATTACH_TYPE attach_type,
Widget objlist,
Widget offset,
Widget position
)
{
if (!objlist || !offset || !position)
return;
switch(attach_type)
{
case ATTCH_ED_PARENT:
case ATTCH_ED_OPPOSITE_PARENT:
ui_set_active(objlist, False);
ui_set_active(offset, True);
ui_set_active(position, False);
break;
case ATTCH_ED_SIBLING:
case ATTCH_ED_OPPOSITE_SIBLING:
ui_set_active(objlist, True);
ui_set_active(offset, True);
ui_set_active(position, False);
break;
case ATTCH_ED_GRIDLINE:
ui_set_active(objlist, False);
ui_set_active(offset, True);
ui_set_active(position, True);
break;
case ATTCH_ED_CENTER_GRIDLINE:
ui_set_active(objlist, False);
ui_set_active(offset, False);
ui_set_active(position, True);
break;
case ATTCH_ED_NONE:
ui_set_active(objlist, False);
ui_set_active(offset, False);
ui_set_active(position, False);
break;
}
}
static void
enable_attach_types(
ABObj obj
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats
= &attch_editor_settings_rec;
ABObj parent;
BOOL state = FALSE;
int child_count;
if (!obj)
return;
parent = attch_ed_get_parent(obj);
child_count = parent ? trav_count(parent, AB_TRAV_SALIENT_CHILDREN)
: 0;
/*
* If this object has siblings, enable attach sibling
* option menu items
*/
if (child_count > 1)
state = TRUE;
/* left attachment */
ui_set_active(attch_ed_cgen->left_attach_items.bitmaps_attach_left_widget_xbm_item,
state);
ui_set_active(attch_ed_cgen->left_attach_items.bitmaps_attach_left_opposite_widget_xbm_item,
state);
/* right attachment */
ui_set_active(attch_ed_cgen->right_attach_items.bitmaps_attach_right_widget_xbm_item,
state);
ui_set_active(attch_ed_cgen->right_attach_items.bitmaps_attach_right_opposite_widget_xbm_item,
state);
/* top attachment */
ui_set_active(attch_ed_cgen->top_attach_items.bitmaps_attach_top_widget_xbm_item,
state);
ui_set_active(attch_ed_cgen->top_attach_items.bitmaps_attach_top_opposite_widget_xbm_item,
state);
/* bottom attachment */
ui_set_active(attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_widget_xbm_item,
state);
ui_set_active(attch_ed_cgen->bottom_attach_items.bitmaps_attach_bottom_opposite_widget_xbm_item,
state);
}
static void
set_attach_values(
ATTCH_ED_ATTACH_TYPE attach_type,
PropFieldSetting offset_setting,
PropFieldSetting position_setting,
PropOptionsSetting objlist_setting,
int offset_value,
int position_value,
XtPointer objlist_value
)
{
switch (attach_type)
{
case ATTCH_ED_PARENT:
prop_field_set_numeric_value(offset_setting, offset_value, False);
break;
case ATTCH_ED_OPPOSITE_PARENT:
prop_field_set_numeric_value(offset_setting, offset_value, False);
break;
case ATTCH_ED_SIBLING:
prop_field_set_numeric_value(offset_setting, offset_value, False);
prop_options_set_value(objlist_setting, (XtPointer)objlist_value, False);
break;
case ATTCH_ED_OPPOSITE_SIBLING:
prop_field_set_numeric_value(offset_setting, offset_value, False);
prop_options_set_value(objlist_setting, (XtPointer)objlist_value, False);
break;
case ATTCH_ED_GRIDLINE:
prop_field_set_numeric_value(offset_setting, offset_value, False);
prop_field_set_numeric_value(position_setting, position_value, False);
break;
case ATTCH_ED_CENTER_GRIDLINE:
prop_field_set_numeric_value(position_setting, position_value, False);
break;
case ATTCH_ED_NONE:
break;
}
}
static void
get_attach_values(
ATTCH_ED_ATTACH_TYPE attach_type,
PropFieldSetting offset_setting,
PropFieldSetting position_setting,
PropOptionsSetting objlist_setting,
int *offset_value,
int *position_value,
XtPointer *objlist_value
)
{
switch (attach_type)
{
case ATTCH_ED_PARENT:
*offset_value = prop_field_get_numeric_value(offset_setting);
break;
case ATTCH_ED_OPPOSITE_PARENT:
*offset_value = prop_field_get_numeric_value(offset_setting);
break;
case ATTCH_ED_SIBLING:
*offset_value = prop_field_get_numeric_value(offset_setting);
*objlist_value = prop_options_get_value(objlist_setting);
break;
case ATTCH_ED_OPPOSITE_SIBLING:
*offset_value = prop_field_get_numeric_value(offset_setting);
*objlist_value = prop_options_get_value(objlist_setting);
break;
case ATTCH_ED_GRIDLINE:
*offset_value = prop_field_get_numeric_value(offset_setting);
*position_value = prop_field_get_numeric_value(position_setting);
break;
case ATTCH_ED_CENTER_GRIDLINE:
*position_value = prop_field_get_numeric_value(position_setting);
break;
case ATTCH_ED_NONE:
break;
}
}
static void
convert_offset_position(
ABObj cur_obj,
ABObj sibling_obj,
AB_COMPASS_POINT dir,
ATTCH_ED_ATTACH_TYPE attach_type,
int *ret_offset,
int *ret_position
)
{
Widget cur_widget,
sibling_widget,
parent_widget;
ABObj parent_obj;
Position x = 0,
y = 0,
p_x = 0,
p_y = 0,
s_x = 0,
s_y = 0;
Dimension width = 0,
height = 0,
p_width = 0,
p_height = 0,
s_width = 0,
s_height = 0;
int fraction_base = 100,
offset_value = 0,
position_value = 0;
if (!cur_obj || !ret_offset || !ret_position)
return;
/*
parent_obj = attch_ed_get_parent(cur_obj);
*/
parent_obj = obj_get_parent(cur_obj);
*ret_offset = *ret_position = 0;
if (!parent_obj)
return;
cur_widget = objxm_get_widget(cur_obj);
parent_widget = objxm_get_widget(parent_obj);
if (!cur_widget || !parent_widget)
return;
XtVaGetValues(cur_widget,
XmNx, &x,
XmNy, &y,
XmNwidth, &width,
XmNheight, &height,
NULL);
XtVaGetValues(parent_widget,
XmNx, &p_x,
XmNy, &p_y,
XmNwidth, &p_width,
XmNheight, &p_height,
XmNfractionBase,&fraction_base,
NULL);
if (attch_ed_need_obj_menu(attach_type))
{
if (!sibling_obj)
return;
sibling_widget = objxm_get_widget(sibling_obj);
if (!sibling_widget)
return;
XtVaGetValues(sibling_widget,
XmNx, &s_x,
XmNy, &s_y,
XmNwidth, &s_width,
XmNheight, &s_height,
NULL);
}
switch (dir)
{
case AB_CP_WEST:
switch(attach_type)
{
case ATTCH_ED_PARENT:
offset_value = (int)x;
break;
case ATTCH_ED_OPPOSITE_PARENT:
offset_value = (int)(- ((int)p_width - (int)x));
break;
case ATTCH_ED_SIBLING:
offset_value = (int)((int)x - ((int)s_x + (int)s_width));
break;
case ATTCH_ED_OPPOSITE_SIBLING:
offset_value = (int)x - (int)s_x;
break;
case ATTCH_ED_GRIDLINE:
position_value = (fraction_base * (int)x)/(int)p_width;
break;
case ATTCH_ED_CENTER_GRIDLINE:
position_value =
(fraction_base * ((int)x + ((int)width/2)))/(int)p_width;
break;
case ATTCH_ED_NONE:
break;
}
break;
case AB_CP_EAST:
switch(attach_type)
{
case ATTCH_ED_PARENT:
offset_value = (int)p_width - ((int)x + (int)width);
break;
case ATTCH_ED_OPPOSITE_PARENT:
offset_value = (int)(- ((int)p_width - ((int)x + (int)width)));
break;
case ATTCH_ED_SIBLING:
offset_value = (int)s_x - ((int)x + (int)width);
break;
case ATTCH_ED_OPPOSITE_SIBLING:
offset_value = ((int)s_x + (int)s_width) - ((int)x + (int)width);
break;
case ATTCH_ED_GRIDLINE:
position_value = (fraction_base * ((int)x + (int)width))/(int)p_width;
break;
case ATTCH_ED_CENTER_GRIDLINE:
position_value =
(fraction_base * ((int)x + ((int)width/2)))/(int)p_width;
break;
case ATTCH_ED_NONE:
break;
}
break;
case AB_CP_NORTH:
switch(attach_type)
{
case ATTCH_ED_PARENT:
offset_value = (int)y;
break;
case ATTCH_ED_OPPOSITE_PARENT:
offset_value = (int)(- ((int)p_height - (int)y));
break;
case ATTCH_ED_SIBLING:
offset_value = (int)y - ((int)s_y + (int)s_height);
break;
case ATTCH_ED_OPPOSITE_SIBLING:
offset_value = (int)y - (int)s_y;
break;
case ATTCH_ED_GRIDLINE:
position_value = (fraction_base * (int)y)/(int)p_height;
break;
case ATTCH_ED_CENTER_GRIDLINE:
position_value =
(fraction_base * ((int)y + ((int)height/2)))/(int)p_height;
break;
case ATTCH_ED_NONE:
break;
}
break;
case AB_CP_SOUTH:
switch(attach_type)
{
case ATTCH_ED_PARENT:
offset_value = (int)p_height - ((int)y + (int)height);
break;
case ATTCH_ED_OPPOSITE_PARENT:
offset_value = - ((int)y + (int)height);
break;
case ATTCH_ED_SIBLING:
offset_value = (int)s_y - ((int)y + (int)height);
break;
case ATTCH_ED_OPPOSITE_SIBLING:
offset_value = ((int)s_y + (int)s_height) - ((int)y + (int)height);
break;
case ATTCH_ED_GRIDLINE:
position_value = (fraction_base * ((int)y + (int)height))/(int)p_height;
break;
case ATTCH_ED_CENTER_GRIDLINE:
position_value =
(fraction_base * ((int)y + ((int)height/2)))/(int)p_height;
break;
case ATTCH_ED_NONE:
break;
}
break;
}
/*
set_attach_values(attach_type,
offset_setting, position_setting, objlist_setting,
offset_value, position_value, (XtPointer)sibling_obj);
*/
*ret_offset = offset_value;
*ret_position = position_value;
}
/*
* Attachment type has changed. Figure out (and set) the
* new 'fields' of this attachment i.e.
* offset
* position
* attached object
*/
static void
change_attach_type(
ABObj obj,
AB_COMPASS_POINT dir,
ATTCH_ED_ATTACH_TYPE attach_type
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ABAttachment *attachment;
int offset,
position;
ABObj attach_obj = NULL;
PropOptionsSetting objlist_setting = NULL;
PropFieldSetting offset_setting = NULL,
position_setting = NULL;
Widget objlist_w = NULL,
offset_w = NULL,
position_w = NULL;
/*
* Based on 'dir', figure out which setting structures and
* widgets are relevant.
*/
switch (dir)
{
case AB_CP_WEST:
offset_setting = &(ats->left_attach_offset);
position_setting = &(ats->left_attach_position);
objlist_setting = &(ats->left_attach_obj);
objlist_w = attch_ed_cgen->left_attach_objmenu;
offset_w = attch_ed_cgen->left_offset_rowcolumn;
position_w = attch_ed_cgen->left_position_rowcolumn;
break;
case AB_CP_EAST:
offset_setting = &(ats->right_attach_offset);
position_setting = &(ats->right_attach_position);
objlist_setting = &(ats->right_attach_obj);
objlist_w = attch_ed_cgen->right_attach_objmenu;
offset_w = attch_ed_cgen->right_offset_rowcolumn;
position_w = attch_ed_cgen->right_position_rowcolumn;
break;
case AB_CP_NORTH:
offset_setting = &(ats->top_attach_offset);
position_setting = &(ats->top_attach_position);
objlist_setting = &(ats->top_attach_obj);
objlist_w = attch_ed_cgen->top_attach_objmenu;
offset_w = attch_ed_cgen->top_offset_rowcolumn;
position_w = attch_ed_cgen->top_position_rowcolumn;
break;
case AB_CP_SOUTH:
offset_setting = &(ats->bottom_attach_offset);
position_setting = &(ats->bottom_attach_position);
objlist_setting = &(ats->bottom_attach_obj);
objlist_w = attch_ed_cgen->bottom_attach_objmenu;
offset_w = attch_ed_cgen->bottom_offset_rowcolumn;
position_w = attch_ed_cgen->bottom_position_rowcolumn;
break;
}
/*
* If any of the settings/widgets cannot be determined, return
* immediately
*/
if (!offset_setting || !position_setting || !objlist_setting ||
!objlist_w || !offset_w || !position_w)
return;
/*
* Set the (in)active state of the fields:
* object option menu
* offset
* percentage/position
* depending on what the attachment type is
*/
set_widget_state(attach_type,
objlist_w, offset_w, position_w);
/*
* If the attachment type requires a sibling object,
* make sure object option menu is current. Get
* default/first sibling object.
*/
if (attch_ed_need_obj_menu(attach_type))
{
create_obj_menu_dir(obj, dir);
attach_obj = (ABObj)prop_options_get_value(objlist_setting);
}
/*
* Figure out offset/position based on (new) attachment type
*/
convert_offset_position(obj, attach_obj, dir, attach_type,
&offset, &position);
/*
* Set the new offset/position/sibling object values
*/
set_attach_values(attach_type,
offset_setting, position_setting, objlist_setting,
offset, position, (XtPointer)attach_obj);
}
/*
* Attachment type has changed. Figure out (and set) the
* new 'fields' of the attachment of the OPPOSITE side.
*/
static void
change_opp_attach_type(
ABObj obj,
AB_COMPASS_POINT dir,
ATTCH_ED_ATTACH_TYPE attach_type
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
int offset = 0,
position = 0;
ABObj attach_obj = NULL;
AB_COMPASS_POINT opp_dir = AB_CP_UNDEF;
ATTCH_ED_ATTACH_TYPE opp_attach_type;
PropOptionsSetting opp_attach_type_setting = NULL,
opp_objlist_setting = NULL;
PropFieldSetting opp_offset_setting = NULL,
opp_position_setting = NULL;
Widget opp_objlist_w = NULL,
opp_offset_w = NULL,
opp_position_w = NULL;
BOOL set_opp_attach = FALSE;
/*
* Based on 'dir', figure out which setting structures and
* widgets are relevant for opposite side attachments.
*/
switch (dir)
{
case AB_CP_WEST:
opp_dir = AB_CP_EAST;
opp_attach_type_setting = &(ats->right_attach_type);
opp_offset_setting = &(ats->right_attach_offset);
opp_position_setting = &(ats->right_attach_position);
opp_objlist_setting = &(ats->right_attach_obj);
opp_objlist_w = attch_ed_cgen->right_attach_objmenu;
opp_offset_w = attch_ed_cgen->right_offset_rowcolumn;
opp_position_w = attch_ed_cgen->right_position_rowcolumn;
break;
case AB_CP_EAST:
opp_dir = AB_CP_WEST;
opp_attach_type_setting = &(ats->left_attach_type);
opp_offset_setting = &(ats->left_attach_offset);
opp_position_setting = &(ats->left_attach_position);
opp_objlist_setting = &(ats->left_attach_obj);
opp_objlist_w = attch_ed_cgen->left_attach_objmenu;
opp_offset_w = attch_ed_cgen->left_offset_rowcolumn;
opp_position_w = attch_ed_cgen->left_position_rowcolumn;
break;
case AB_CP_NORTH:
opp_dir = AB_CP_SOUTH;
opp_attach_type_setting = &(ats->bottom_attach_type);
opp_offset_setting = &(ats->bottom_attach_offset);
opp_position_setting = &(ats->bottom_attach_position);
opp_objlist_setting = &(ats->bottom_attach_obj);
opp_objlist_w = attch_ed_cgen->bottom_attach_objmenu;
opp_offset_w = attch_ed_cgen->bottom_offset_rowcolumn;
opp_position_w = attch_ed_cgen->bottom_position_rowcolumn;
break;
case AB_CP_SOUTH:
opp_dir = AB_CP_NORTH;
opp_attach_type_setting = &(ats->top_attach_type);
opp_offset_setting = &(ats->top_attach_offset);
opp_position_setting = &(ats->top_attach_position);
opp_objlist_setting = &(ats->top_attach_obj);
opp_objlist_w = attch_ed_cgen->top_attach_objmenu;
opp_offset_w = attch_ed_cgen->top_offset_rowcolumn;
opp_position_w = attch_ed_cgen->top_position_rowcolumn;
break;
}
/*
* If any of the settings/widgets cannot be determined, return
* immediately
*/
if (!opp_attach_type_setting ||
!opp_offset_setting || !opp_position_setting || !opp_objlist_setting ||
!opp_objlist_w || !opp_offset_w || !opp_position_w)
return;
/*
* Get opposite side attachment type
*/
opp_attach_type =
(ATTCH_ED_ATTACH_TYPE)prop_options_get_value(opp_attach_type_setting);
/*
* Check if opposite side attachment needs to be changed
*/
if ((attach_type == ATTCH_ED_CENTER_GRIDLINE) &&
(opp_attach_type != ATTCH_ED_NONE))
{
/*
* If attachment type is now ATTCH_ED_CENTER_GRIDLINE,
* make the opposite side's attachment type ATTCH_ED_NONE.
* ATTCH_ED_CENTER_GRIDLINE is an attachment type that
* does not really apply to an edge. It affects the
* object either vertically or horizontally.
*/
opp_attach_type = ATTCH_ED_NONE;
set_opp_attach = TRUE;
}
else if ((attach_type == ATTCH_ED_NONE) &&
(opp_attach_type == ATTCH_ED_NONE))
{
/*
* If attachment type is now ATTCH_ED_NONE and the opposite side's
* attachment type is also ATTCH_ED_NONE, make the opposite side's
* attachment type ATTCH_ED_PARENT. You cannot set both the
* opposite sides to ATTCH_ED_NONE.
*/
opp_attach_type = ATTCH_ED_PARENT;
set_opp_attach = TRUE;
}
else if ((attach_type != ATTCH_ED_NONE) &&
(opp_attach_type == ATTCH_ED_CENTER_GRIDLINE))
{
/*
* If the attachment type is NOT ATTCH_ED_NONE, and
* the opposite side's attachment type is ATTCH_ED_CENTER_GRIDLINE,
* make the opposite side's attachment type ATTCH_ED_NONE.
* ATTCH_ED_CENTER_GRIDLINE cannot be set on a side, if the
* opposite side is not ATTCH_ED_NONE.
*/
opp_attach_type = ATTCH_ED_NONE;
set_opp_attach = TRUE;
}
/*
* Was a change to the opposite side's attachment necessary ?
*/
if (set_opp_attach)
{
/*
* Set the (in)active state of the fields:
* object option menu
* offset
* percentage/position
* depending on what the new attachment type is
*/
set_widget_state(opp_attach_type,
opp_objlist_w, opp_offset_w, opp_position_w);
/*
* If the attachment type requires a sibling object,
* make sure that the object option menu is current. Get
* default/first sibling object.
*/
if (attch_ed_need_obj_menu(opp_attach_type))
{
create_obj_menu_dir(obj, opp_dir);
attach_obj = (ABObj)prop_options_get_value(opp_objlist_setting);
}
/*
* Set the new attachment type
*/
prop_options_set_value(opp_attach_type_setting, (XtPointer)opp_attach_type, True);
/*
* Figure out offset/position based on (new) attachment type
*/
convert_offset_position(obj, attach_obj, opp_dir, opp_attach_type,
&offset, &position);
/*
* Set the new offset/position/sibling object values
*/
set_attach_values(opp_attach_type,
opp_offset_setting, opp_position_setting, opp_objlist_setting,
offset, position, (XtPointer)attach_obj);
}
}
static void
attach_obj_changed(
Widget widget,
XtPointer client_data,
XtPointer calldata
)
{
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
PropFieldSetting offset_setting = NULL,
position_setting;
PropOptionsSetting objlist_setting = NULL,
attach_type_setting = NULL;
AB_COMPASS_POINT dir = (AB_COMPASS_POINT)client_data;
ATTCH_ED_ATTACH_TYPE attach_type = ATTCH_ED_NONE;
ABObj attach_obj = NULL;
XtArgVal value;
XtVaGetValues(widget, XmNuserData, &value, NULL);
attach_obj = (ABObj)value;
if (!attach_obj)
return;
switch (dir)
{
case AB_CP_WEST:
attach_type_setting = &(ats->left_attach_type);
offset_setting = &(ats->left_attach_offset);
position_setting = &(ats->left_attach_position);
objlist_setting = &(ats->left_attach_obj);
break;
case AB_CP_EAST:
attach_type_setting = &(ats->right_attach_type);
offset_setting = &(ats->right_attach_offset);
position_setting = &(ats->right_attach_position);
objlist_setting = &(ats->right_attach_obj);
break;
case AB_CP_NORTH:
attach_type_setting = &(ats->top_attach_type);
offset_setting = &(ats->top_attach_offset);
position_setting = &(ats->top_attach_position);
objlist_setting = &(ats->top_attach_obj);
break;
case AB_CP_SOUTH:
attach_type_setting = &(ats->bottom_attach_type);
offset_setting = &(ats->bottom_attach_offset);
position_setting = &(ats->bottom_attach_position);
objlist_setting = &(ats->bottom_attach_obj);
break;
default:
return;
}
attach_type = (ATTCH_ED_ATTACH_TYPE)prop_options_get_value(attach_type_setting);
if (attch_ed_need_obj_menu(attach_type))
{
int offset, position;
convert_offset_position(ats->cur_object, attach_obj, dir, attach_type,
&offset, &position);
set_attach_values(attach_type,
offset_setting, position_setting, objlist_setting,
offset, position, (XtPointer)attach_obj);
}
}
static void
attch_ed_view_child_attachments(void)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ABObj cur_obj,
child;
DTB_MODAL_ANSWER answer = DTB_ANSWER_ACTION1;
cur_obj = ats->cur_object;
if (!cur_obj)
return;
child = obj_get_salient_child(cur_obj, 0);
if (!child)
return;
if (attch_edP_pending())
{
answer = get_wrn_response(AB_attch_ed_dialog,
ATTCH_ED_WRN_LOAD, child);
}
if (answer != DTB_ANSWER_ACTION1)
return;
attch_editor_load(child);
}
static void
attch_ed_view_parent_attachments(void)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ABObj cur_obj,
parent;
DTB_MODAL_ANSWER answer = DTB_ANSWER_ACTION1;
cur_obj = ats->cur_object;
if (!cur_obj)
return;
parent = attch_ed_get_parent(cur_obj);
if (!parent)
return;
parent = obj_get_root(parent);
if (attch_edP_pending())
{
answer = get_wrn_response(AB_attch_ed_dialog,
ATTCH_ED_WRN_LOAD, parent);
}
if (answer != DTB_ANSWER_ACTION1)
return;
attch_editor_load(parent);
}
static void
attch_ed_activate_parent_child_button(void)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
ABObj cur_obj,
parent;
BOOL child_state = FALSE,
parent_state = FALSE;
cur_obj = ats->cur_object;
if (!cur_obj)
return;
parent = attch_ed_get_parent(cur_obj);
if (parent)
parent = obj_get_root(parent);
if (obj_is_container(cur_obj) || obj_is_layers(cur_obj))
child_state = TRUE;
if (parent && !obj_is_window(parent))
parent_state = TRUE;
ui_set_active(attch_ed_cgen->parent_attach_button, parent_state);
ui_set_active(attch_ed_cgen->child_attach_button, child_state);
}
/*
* Called when the user attempts to dismiss the Attachments Editor
* via the Motif window menu.
*/
static void
attch_edP_prevent_closeCB(
Widget widget,
XtPointer client_data,
XtPointer call_data
)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
DTB_MODAL_ANSWER answer = DTB_ANSWER_ACTION1;
/*
* If there are pending changes for the current object, handle the
* implied auto-apply.
*/
if (attch_edP_pending())
{
answer = get_wrn_response(widget,
ATTCH_ED_WRN_CLOSE, NULL);
}
if (answer != DTB_ANSWER_ACTION1)
return;
/*
* No pending changes OR applied existing changes, so just
* dismiss the Attachments Editor
*/
ui_win_show(AB_attch_ed_dialog, False, XtGrabNone);
}
static DTB_MODAL_ANSWER
get_wrn_response(
Widget w,
ATTCH_ED_WRN_TYPE wrn_type,
ABObj new_obj
)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
DTB_MODAL_ANSWER answer;
XmString xm_buf;
DtbObjectHelpData help_data = NULL;
char wrn_string[512],
*cur_name = NULL,
*new_name = NULL;
if (dtb_app_resource_rec.implied_apply == True)
answer = DTB_ANSWER_ACTION1;
else
{
if (ats->cur_object)
{
cur_name = obj_get_name(ats->cur_object);
if (!cur_name)
cur_name = "nil";
}
if (new_obj)
{
new_name = obj_get_name(new_obj);
if (!new_name)
new_name = "nil";
}
help_data = (DtbObjectHelpData) util_malloc(sizeof(DtbObjectHelpDataRec));
help_data->help_text = help_data->help_volume = help_data->help_locationID = NULL;
/*
* Determine message and help text for each
* case
*/
switch(wrn_type)
{
case ATTCH_ED_WRN_LOAD:
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."));
sprintf(wrn_string,
CATGETS(Dtb_project_catd, 100, 43,
"Attachments for \"%s\"\n\
have been modified but not Applied.\n\n\
You can Apply the Changes or Cancel the\n\
Load operation for \"%s\"."),
cur_name, new_name);
break;
case ATTCH_ED_WRN_CHANGE_OBJTYPE:
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."));
sprintf(wrn_string,
CATGETS(Dtb_project_catd, 100, 44,
"Attachments for \"%s\"\n\
have been modified but not Applied.\n\n\
You can Apply the Changes or Cancel the\n\
'Change Object-Type' operation."),
cur_name);
break;
case ATTCH_ED_WRN_CLOSE:
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."));
sprintf(wrn_string,
CATGETS(Dtb_project_catd, 100, 45,
"Attachments for \"%s\"\n\
have been modified but not Applied.\n\n\
You can Apply the Changes or Cancel the\n\
Close operation."),
cur_name);
break;
default:
sprintf(wrn_string, "Attachments Editor warning!!");
break;
}
xm_buf = XmStringCreateLocalized(wrn_string);
dtb_attch_ed_wrn_msg_initialize(&dtb_attch_ed_wrn_msg);
answer = dtb_show_modal_message(w, &dtb_attch_ed_wrn_msg,
xm_buf, help_data, NULL);
XmStringFree(xm_buf);
if (help_data->help_text)
XtFree(help_data->help_text);
util_free(help_data);
}
switch (answer)
{
case DTB_ANSWER_ACTION1: /* Apply Changes */
attch_editor_apply(ats->cur_object);
break;
default: /* Let caller do the rest */
break;
}
return (answer);
}
BOOL
attch_ed_can_edit_attachments(
ABObj obj
)
{
ABObj parent,
module;
Widget parent_w;
if (!obj)
return (FALSE);
module = obj_get_module(obj);
if (module && (!obj_has_flag(module, MappedFlag) || !obj_is_defined(module)))
return (FALSE);
if (!obj_is_ui(obj) || obj_is_window(obj) ||
obj_is_menubar(obj) || obj_is_item(obj) ||
obj_is_sub(obj))
return (FALSE);
parent = attch_ed_get_parent(obj);
if (!parent)
return (FALSE);
parent_w = objxm_get_widget(parent);
if (!parent_w)
return (FALSE);
if (!XtIsSubclass(parent_w, xmFormWidgetClass))
return (FALSE);
return (TRUE);
}
static void
print_attach_type(
ATTCH_ED_ATTACH_TYPE attach_type
)
{
fprintf(stderr, "Attach type = ");
switch (attach_type)
{
case ATTCH_ED_PARENT:
fprintf(stderr, "ATTCH_ED_PARENT\n");
break;
case ATTCH_ED_OPPOSITE_PARENT:
fprintf(stderr, "ATTCH_ED_OPPOSITE_PARENT\n");
break;
case ATTCH_ED_SIBLING:
fprintf(stderr, "ATTCH_ED_SIBLING\n");
break;
case ATTCH_ED_OPPOSITE_SIBLING:
fprintf(stderr, "ATTCH_ED_OPPOSITE_SIBLING\n");
break;
case ATTCH_ED_GRIDLINE:
fprintf(stderr, "ATTCH_ED_GRIDLINE\n");
break;
case ATTCH_ED_CENTER_GRIDLINE:
fprintf(stderr, "ATTCH_ED_CENTER_GRIDLINE\n");
break;
case ATTCH_ED_NONE:
fprintf(stderr, "ATTCH_ED_NONE\n");
break;
}
}
static BOOL
attch_ed_verify_props(void)
{
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ATTCH_ED_ATTACH_TYPE attach_type = ATTCH_ED_NONE;
ABObj parent;
if (ats->cur_object == NULL)
return TRUE;
/*
* Get parent of current object
*/
parent = obj_get_parent(ats->cur_object);
if (parent);
parent = obj_get_root(parent);
/*
* If parent is a group with layout type NOT "As Is"
*/
if (parent && obj_is_group(parent) &&
(obj_get_group_type(parent) != AB_GROUP_IGNORE))
{
DTB_MODAL_ANSWER answer;
DtbObjectHelpData help_data;
XmString xm_buf;
char *format_str,
*obj_name,
*parent_name,
*msg_buf;
/*
* Get the object and it's parent's names
*/
obj_name = obj_get_name(ats->cur_object);
parent_name = obj_get_name(parent);
if (!obj_name || !parent_name)
return TRUE;
/*
* Initialize message object if necessary
*/
dtb_attch_ed_grp_member_wrn_initialize(&dtb_attch_ed_grp_member_wrn);
/*
* Fetch format string
*/
format_str = XtNewString(CATGETS(Dtb_project_catd, 100, 245,
"Attachments for \"%s\"\ncannot be modified because it is\na member of the group \"%s\"."));
/*
* Malloc space for warning message. It's length is:
* format str len +
* object name len +
* object parent name len +
* <some padding> (paranoia)
*/
msg_buf = (STRING)util_malloc(strlen(format_str) +
strlen(obj_name) +
strlen(parent_name) +
10);
/*
* Construct warning message
*/
sprintf(msg_buf, format_str, obj_name, parent_name);
/*
* Create XmString for warning message
*/
xm_buf = XmStringCreateLocalized(msg_buf);
/*
* Malloc/setup struct for help text
*/
help_data = (DtbObjectHelpData) util_malloc(sizeof(DtbObjectHelpDataRec));
help_data->help_text = CATGETS(Dtb_project_catd, 100, 246,
"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.");
help_data->help_volume = NULL;
help_data->help_locationID = NULL;
/*
* Show warning message dialog
*/
answer = dtb_show_modal_message(AB_attch_ed_dialog, &dtb_attch_ed_grp_member_wrn,
xm_buf, help_data, NULL);
/*
* Free message/format strings
* Free XmString
* Free help struct
*/
XtFree(msg_buf);
XtFree(format_str);
XmStringFree(xm_buf);
util_free(help_data);
return FALSE;
}
/*
* Top attachment
*/
if (prop_changed(ats->top_attach_type.changebar))
{
attach_type =
(ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->top_attach_type));
if (!verify_one_attach(attach_type,
&(ats->top_attach_offset), &(ats->top_attach_position)))
return FALSE;
}
/*
* Bottom attachment
*/
if (prop_changed(ats->bottom_attach_type.changebar))
{
attach_type =
(ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->bottom_attach_type));
if (!verify_one_attach(attach_type,
&(ats->bottom_attach_offset), &(ats->bottom_attach_position)))
return FALSE;
}
/*
* Left attachment
*/
if (prop_changed(ats->left_attach_type.changebar))
{
attach_type =
(ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->left_attach_type));
if (!verify_one_attach(attach_type,
&(ats->left_attach_offset), &(ats->left_attach_position)))
return FALSE;
}
/*
* Right attachment - shares changebar with left attachment
*/
if (prop_changed(ats->left_attach_type.changebar))
{
attach_type =
(ATTCH_ED_ATTACH_TYPE)prop_options_get_value(&(ats->right_attach_type));
if (!verify_one_attach(attach_type,
&(ats->right_attach_offset), &(ats->right_attach_position)))
return FALSE;
}
return TRUE;
}
static BOOL
verify_one_attach(
ATTCH_ED_ATTACH_TYPE attach_type,
PropFieldSetting offset_setting,
PropFieldSetting position_setting
)
{
switch (attach_type)
{
case ATTCH_ED_PARENT:
case ATTCH_ED_OPPOSITE_PARENT:
case ATTCH_ED_SIBLING:
case ATTCH_ED_OPPOSITE_SIBLING:
if (!prop_number_ok(offset_setting->field,
(STRING)OffsetFieldStr, -SHRT_MAX, SHRT_MAX))
return FALSE;
break;
case ATTCH_ED_GRIDLINE:
if (!prop_number_ok(offset_setting->field,
(STRING)OffsetFieldStr, -SHRT_MAX, SHRT_MAX) ||
!prop_number_ok(position_setting->field,
(STRING)PercentageFieldStr, -SHRT_MAX, SHRT_MAX))
return FALSE;
break;
case ATTCH_ED_CENTER_GRIDLINE:
if (!prop_number_ok(position_setting->field,
(STRING)PercentageFieldStr, -SHRT_MAX, SHRT_MAX))
return FALSE;
break;
case ATTCH_ED_NONE:
break;
}
return TRUE;
}
/*** DTB_USER_CODE_END
***
*** End of user code section
***
**************************************************************************/
void
attch_ed_applyCB(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
attch_editor_apply(ats->cur_object);
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
}
void
attch_ed_resetCB(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
attch_editor_load(ats->cur_object);
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
}
void
attch_ed_helpCB(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
printf("action: attch_ed_helpCB\n");
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
}
void
attch_ed_okCB(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
attch_editor_apply(ats->cur_object);
ui_win_show(AB_attch_ed_dialog, False, XtGrabNone);
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
}
void
attch_ed_cancelCB(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
attch_editor_load(ats->cur_object);
ui_win_show(AB_attch_ed_dialog, False, XtGrabNone);
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
}
void
top_attach_type_changed(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ATTCH_ED_ATTACH_TYPE attach_type = ATTCH_ED_NONE;
XtArgVal value;
XtVaGetValues(widget, XmNuserData, &value, NULL);
attach_type = (ATTCH_ED_ATTACH_TYPE)value;
/*
print_attach_type(attach_type);
*/
change_attach_type(ats->cur_object, AB_CP_NORTH, attach_type);
change_opp_attach_type(ats->cur_object, AB_CP_NORTH, attach_type);
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
}
void
right_attach_type_changed(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ATTCH_ED_ATTACH_TYPE attach_type = ATTCH_ED_NONE;
XtArgVal value;
XtVaGetValues(widget, XmNuserData, &value, NULL);
attach_type = (ATTCH_ED_ATTACH_TYPE)value;
/*
print_attach_type(attach_type);
*/
change_attach_type(ats->cur_object, AB_CP_EAST, attach_type);
change_opp_attach_type(ats->cur_object, AB_CP_EAST, attach_type);
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
}
void
bottom_attach_type_changed(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ATTCH_ED_ATTACH_TYPE attach_type = ATTCH_ED_NONE;
XtArgVal value;
XtVaGetValues(widget, XmNuserData, &value, NULL);
attach_type = (ATTCH_ED_ATTACH_TYPE)value;
/*
print_attach_type(attach_type);
*/
change_attach_type(ats->cur_object, AB_CP_SOUTH, attach_type);
change_opp_attach_type(ats->cur_object, AB_CP_SOUTH, attach_type);
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
}
void
left_attach_type_changed(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
DtbAttchEdAttchEdDialogInfo attch_ed_cgen
= &dtb_attch_ed_attch_ed_dialog;
AttchEditorSettingsRec *ats = &attch_editor_settings_rec;
ATTCH_ED_ATTACH_TYPE attach_type = ATTCH_ED_NONE;
XtArgVal value;
XtVaGetValues(widget, XmNuserData, &value, NULL);
attach_type = (ATTCH_ED_ATTACH_TYPE)value;
/*
print_attach_type(attach_type);
*/
change_attach_type(ats->cur_object, AB_CP_WEST, attach_type);
change_opp_attach_type(ats->cur_object, AB_CP_WEST, attach_type);
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
}
void
parent_attachCB(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
attch_ed_view_parent_attachments();
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
}
void
child_attachCB(
Widget widget,
XtPointer clientData,
XtPointer callData
)
{
/*** DTB_USER_CODE_START vvv Add C variables and code below vvv ***/
/*** DTB_USER_CODE_END ^^^ Add C variables and code above ^^^ ***/
/*** DTB_USER_CODE_START vvv Add C code below vvv ***/
attch_ed_view_child_attachments();
/*** DTB_USER_CODE_END ^^^ Add C code above ^^^ ***/
}
/**************************************************************************
*** DTB_USER_CODE_START
***
*** All automatically-generated data and functions have been defined.
***
*** Add new functions here, or at the top of the file.
***/
/*** DTB_USER_CODE_END
***
*** End of user code section
***
**************************************************************************/