718 lines
17 KiB
C
718 lines
17 KiB
C
/*
|
|
* 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 librararies and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/*
|
|
* $XConsortium: objxm_config.c /main/4 1995/11/06 18:45:06 rswiston $
|
|
*
|
|
* @(#)objxm_config.c 1.27 15 Feb 1994 cde_app_builder/src/libABobjXm
|
|
*
|
|
* RESTRICTED CONFIDENTIAL INFORMATION:
|
|
*
|
|
* The information in this document is subject to special
|
|
* restrictions in a confidential disclosure agreement between
|
|
* HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
|
|
* document outside HP, IBM, Sun, USL, SCO, or Univel without
|
|
* Sun's specific written approval. This document and all copies
|
|
* and derivative works thereof must be returned or destroyed at
|
|
* Sun's request.
|
|
*
|
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
* objxm_config.c - Implements configuring an object into the
|
|
* appropriate Motif hierarchy
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <Xm/Xm.h>
|
|
#include <ab_private/trav.h>
|
|
#include "objxmP.h"
|
|
|
|
#define MAX_XMCONFIG_INFOS 35
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** Private Data **
|
|
** **
|
|
**************************************************************************/
|
|
static XmConfigInfo config_info_table[MAX_XMCONFIG_INFOS];
|
|
static int config_info_count = 0;
|
|
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** Private Function Declarations **
|
|
** **
|
|
**************************************************************************/
|
|
static int xm_configure_tree(
|
|
ABObj root,
|
|
OBJXM_CONFIG_TYPE ctype
|
|
);
|
|
static int xm_configure_tree_attachments(
|
|
ABObj root
|
|
);
|
|
|
|
static int config_attachment(
|
|
ABObj obj,
|
|
ABObj parent_obj,
|
|
AB_COMPASS_POINT dir
|
|
);
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** Function Definitions **
|
|
** **
|
|
**************************************************************************/
|
|
|
|
/*
|
|
* Add XmConfigure info for a given object type to the XmConfigInfo table
|
|
*/
|
|
void
|
|
objxm_register_config_info(
|
|
XmConfigInfo cfginfo
|
|
)
|
|
{
|
|
int i;
|
|
Boolean exists = FALSE;
|
|
|
|
/* Search to make sure it doesn't already exist in the table */
|
|
for (i = 0; i < config_info_count; i++)
|
|
if (config_info_table[i] == cfginfo)
|
|
{
|
|
exists = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (!exists)
|
|
{
|
|
if (config_info_count < MAX_XMCONFIG_INFOS)
|
|
config_info_table[config_info_count++] = cfginfo;
|
|
else
|
|
{
|
|
if (util_get_verbosity() > 0)
|
|
fprintf(stderr,"objxm_register_config_info: config_info table full\n");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* return the XmConfigInfo corresponding to the Object
|
|
*/
|
|
XmConfigInfo
|
|
objxmP_get_config_info(
|
|
ABObj obj
|
|
)
|
|
{
|
|
int i;
|
|
XmConfigInfo cfginfo = NULL;
|
|
ABObj vobj;
|
|
|
|
vobj = obj_get_root(obj);
|
|
|
|
for (i=0; i < config_info_count; i++)
|
|
if ((*config_info_table[i]->is_a_test)(vobj))
|
|
{
|
|
cfginfo = config_info_table[i];
|
|
break;
|
|
}
|
|
|
|
return(cfginfo);
|
|
|
|
}
|
|
|
|
/*
|
|
* XmConfigure an Object into its Composite Object hierarchy
|
|
*/
|
|
int
|
|
objxm_obj_configure(
|
|
ABObj obj,
|
|
OBJXM_CONFIG_TYPE ctype,
|
|
BOOL set_args
|
|
)
|
|
{
|
|
int iReturn = OK;
|
|
XmConfigInfo cfginfo;
|
|
|
|
if (!obj_has_flag(obj, XmConfiguredFlag))
|
|
{
|
|
obj = obj_get_root(obj);
|
|
|
|
if (obj_is_project(obj) ||
|
|
obj_is_module(obj) || obj_is_message(obj))
|
|
obj_set_flag(obj, XmConfiguredFlag);
|
|
else
|
|
{
|
|
cfginfo = objxmP_get_config_info(obj);
|
|
|
|
if (cfginfo != NULL && cfginfo->xmconfig != NULL)
|
|
iReturn = (*cfginfo->xmconfig)(obj);
|
|
else
|
|
iReturn = -1;
|
|
|
|
if (iReturn == OK)
|
|
{
|
|
obj_comp_set_flag(obj, XmConfiguredFlag);
|
|
/*
|
|
if (set_args)
|
|
objxm_comp_set_ui_args(obj, ctype, TRUE);
|
|
*/
|
|
}
|
|
|
|
}
|
|
}
|
|
return iReturn;
|
|
}
|
|
|
|
/*
|
|
* Collapse a Composite Object hierarchy back into a SINGLE
|
|
* UnConfigured object
|
|
*/
|
|
int
|
|
objxm_obj_unconfigure(
|
|
ABObj obj
|
|
)
|
|
{
|
|
int iReturn= -1;
|
|
XmConfigInfo cfginfo;
|
|
|
|
if (obj_has_flag(obj, XmConfiguredFlag))
|
|
{
|
|
obj = obj_get_root(obj);
|
|
|
|
if (obj_is_project(obj) || obj_is_module(obj))
|
|
{
|
|
obj_clear_flag(obj, XmConfiguredFlag);
|
|
iReturn = 0;
|
|
}
|
|
else
|
|
{
|
|
cfginfo = objxmP_get_config_info(obj);
|
|
|
|
if (cfginfo != NULL && cfginfo->xmunconfig != NULL)
|
|
iReturn = (*cfginfo->xmunconfig)(obj);
|
|
|
|
if (iReturn == OK) /* Reset common fields */
|
|
{
|
|
obj->part_of = NULL;
|
|
obj_set_class_name(obj, NULL);
|
|
obj_clear_flag(obj, XmConfiguredFlag);
|
|
}
|
|
}
|
|
}
|
|
else if (util_get_verbosity() > 2)
|
|
{
|
|
fprintf(stderr,"objxm_obj_unconfigure: %s not XmConfigured\n",
|
|
util_strsafe(obj_get_name(obj)));
|
|
}
|
|
|
|
return iReturn;
|
|
}
|
|
|
|
/*
|
|
* XmConfigures all salient objects in the tree. Objects already
|
|
* configured are ignored.
|
|
*/
|
|
int
|
|
objxm_tree_configure(
|
|
ABObj root,
|
|
OBJXM_CONFIG_TYPE ctype
|
|
)
|
|
{
|
|
/* Phase I */
|
|
xm_configure_tree(root, ctype);
|
|
|
|
/* Phase II (Phase I *MUST* happen first)*/
|
|
xm_configure_tree_attachments(root);
|
|
|
|
/* Phase III */
|
|
objxm_tree_set_ui_args(root, ctype, TRUE);
|
|
|
|
/* Phase IV (ONLY happens here for Code-generation! */
|
|
if (ctype == OBJXM_CONFIG_CODEGEN)
|
|
objxm_tree_set_post_inst_args(root, ctype);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
* Collapses all salient Objects back down into their
|
|
* UnConfigured state
|
|
*/
|
|
int
|
|
objxm_tree_unconfigure(
|
|
ABObj root
|
|
)
|
|
{
|
|
int iRetVal= 0;
|
|
AB_TRAVERSAL trav;
|
|
ABObj obj= NULL;
|
|
|
|
/* MUST be BOTTOM-UP Traversal */
|
|
for (trav_open(&trav, root, AB_TRAV_CHILDREN);
|
|
(obj= trav_next(&trav)) != NULL; )
|
|
objxm_tree_unconfigure(obj);
|
|
|
|
if (obj_is_salient(root))
|
|
objxm_obj_unconfigure(root);
|
|
|
|
trav_close(&trav);
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
xm_configure_tree(
|
|
ABObj root,
|
|
OBJXM_CONFIG_TYPE ctype
|
|
)
|
|
{
|
|
int iRetVal= 0;
|
|
AB_TRAVERSAL trav;
|
|
ABObj obj= NULL;
|
|
int numSalientObjs= 0;
|
|
int configCount= 0;
|
|
|
|
/* Must be TOP-DOWN traversal */
|
|
numSalientObjs= trav_count(root, AB_TRAV_SALIENT);
|
|
for (trav_open(&trav, root,
|
|
AB_TRAV_SALIENT | AB_TRAV_MOD_PARENTS_FIRST | AB_TRAV_MOD_SAFE);
|
|
(obj= trav_next(&trav)) != NULL; )
|
|
{
|
|
++configCount;
|
|
objxm_obj_configure(obj, ctype, FALSE);
|
|
}
|
|
trav_close(&trav);
|
|
|
|
if (configCount!= numSalientObjs)
|
|
{
|
|
fprintf(stderr,
|
|
catgets(OBJXM_MESSAGE_CATD, OBJXM_MESSAGE_SET, 8,
|
|
"INTERNAL ERROR: salient counts don't match.\n") );
|
|
iRetVal= -1;
|
|
goto epilogue;
|
|
}
|
|
|
|
epilogue:
|
|
return iRetVal;
|
|
}
|
|
|
|
static int
|
|
xm_configure_tree_attachments(
|
|
ABObj root
|
|
)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj obj;
|
|
|
|
for (trav_open(&trav, root, AB_TRAV_UI);
|
|
(obj= trav_next(&trav)) != NULL; )
|
|
if (obj->attachments)
|
|
objxmP_obj_config_attachments(obj);
|
|
|
|
trav_close(&trav);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
* Call method for setting object-type specific Resources
|
|
* for a Composite Object hierarchy
|
|
*/
|
|
int
|
|
objxmP_comp_set_type_args(
|
|
ABObj obj,
|
|
OBJXM_CONFIG_TYPE ctype
|
|
)
|
|
{
|
|
XmConfigInfo cfginfo;
|
|
|
|
if (obj_has_flag(obj, XmConfiguredFlag))
|
|
{
|
|
cfginfo = objxmP_get_config_info(obj);
|
|
|
|
if (cfginfo != NULL && cfginfo->set_args != NULL)
|
|
return((*cfginfo->set_args)(obj_get_root(obj),ctype));
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Call method for Post-instantiation-handling specific
|
|
* to an object-type
|
|
*/
|
|
int
|
|
objxmP_comp_type_post_instantiate(
|
|
ABObj obj,
|
|
OBJXM_CONFIG_TYPE ctype
|
|
)
|
|
{
|
|
XmConfigInfo cfginfo;
|
|
|
|
cfginfo = objxmP_get_config_info(obj);
|
|
|
|
if (cfginfo != NULL && cfginfo->post_instantiate != NULL)
|
|
return((*cfginfo->post_instantiate)(obj_get_root(obj), ctype));
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Convert Attachment fields for an UnConfigured object
|
|
* into Attachments appropriate for its XmConfigured
|
|
* Composite Object hierarchy
|
|
*/
|
|
int
|
|
objxmP_obj_config_attachments(
|
|
ABObj obj
|
|
)
|
|
{
|
|
ABObj parent_obj = obj_get_parent(obj);
|
|
|
|
if (obj->attachments)
|
|
{
|
|
config_attachment(obj, parent_obj, AB_CP_NORTH);
|
|
config_attachment(obj, parent_obj, AB_CP_WEST);
|
|
config_attachment(obj, parent_obj, AB_CP_EAST);
|
|
config_attachment(obj, parent_obj, AB_CP_SOUTH);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
config_attachment(
|
|
ABObj obj,
|
|
ABObj parent_obj,
|
|
AB_COMPASS_POINT dir
|
|
)
|
|
{
|
|
ABObj attobj;
|
|
ABAttachment *attachment;
|
|
|
|
switch(dir)
|
|
{
|
|
case AB_CP_NORTH:
|
|
attachment = &(obj->attachments->north);
|
|
break;
|
|
case AB_CP_WEST:
|
|
attachment = &(obj->attachments->west);
|
|
break;
|
|
case AB_CP_EAST:
|
|
attachment = &(obj->attachments->east);
|
|
break;
|
|
case AB_CP_SOUTH:
|
|
attachment = &(obj->attachments->south);
|
|
break;
|
|
}
|
|
if (attachment->type == AB_ATTACH_OBJ)
|
|
{
|
|
attobj = (ABObj)(attachment->value);
|
|
|
|
if (attobj == obj_get_root(parent_obj))
|
|
{
|
|
attobj = objxm_comp_get_subobj(attobj, AB_CFG_PARENT_OBJ);
|
|
attachment->value = (void*)attobj;
|
|
}
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*
|
|
* Call method for object-type which retreives the Composite
|
|
* Object's SubObj responsible for 'AB_CFG_OBJ_TYPE' (ie. SIZE,
|
|
* POSITION, etc)
|
|
*/
|
|
ABObj
|
|
objxm_comp_get_subobj(
|
|
ABObj obj,
|
|
AB_CFG_OBJ_TYPE type
|
|
)
|
|
{
|
|
XmConfigInfo cfginfo;
|
|
ABObj cfgobj = NULL;
|
|
|
|
if (obj_has_flag(obj, XmConfiguredFlag))
|
|
{
|
|
cfginfo = objxmP_get_config_info(obj);
|
|
|
|
if (cfginfo != NULL && cfginfo->get_config_obj != NULL)
|
|
cfgobj=
|
|
((*cfginfo->get_config_obj)(obj_get_root(obj), type));
|
|
}
|
|
else if (util_get_verbosity() >= 3)
|
|
{
|
|
char name[256];
|
|
obj_get_safe_name(obj, name, 256);
|
|
fprintf(stderr,
|
|
catgets(OBJXM_MESSAGE_CATD, OBJXM_MESSAGE_SET, 9,
|
|
"ERROR: objxm_comp_get_subobj - object not xmconfigured: %s\n"),
|
|
name);
|
|
|
|
}
|
|
|
|
return cfgobj;
|
|
}
|
|
|
|
ABObj
|
|
objxmP_create_direct_subobj(
|
|
ABObj root,
|
|
AB_OBJECT_TYPE type,
|
|
STRING subname
|
|
)
|
|
{
|
|
ABObj subobj;
|
|
|
|
subobj = obj_create(type, NULL);
|
|
subobj->part_of = root;
|
|
|
|
/* Move children from root to immediate SubObj */
|
|
/* NOTE: obj must NOT have a MenuRef SubObj at this
|
|
* point!
|
|
*/
|
|
if (obj_get_num_children(root) > 0)
|
|
obj_move_children(subobj, root);
|
|
|
|
obj_append_child(root, subobj);
|
|
/*
|
|
obj_set_name_from_parent(subobj, subname);
|
|
*/
|
|
obj_set_unique_name(subobj,
|
|
ab_ident_from_name_and_label(obj_get_name(root), subname));
|
|
|
|
return subobj;
|
|
|
|
}
|
|
|
|
/*
|
|
* If the Obj should have a border-frame, sets the RootObj
|
|
* to be a Frame and creates a SubObj directly under the Obj
|
|
* to represent the actual Object inside the Frame, and
|
|
* returns a handle to the SubObj
|
|
* If the Obj does not have a border-frame, return NULL
|
|
*/
|
|
ABObj
|
|
objxm_comp_config_border_frame(
|
|
ABObj obj
|
|
)
|
|
{
|
|
ABObj subobj = NULL;
|
|
|
|
if (obj_has_border_frame(obj))
|
|
{
|
|
/* Make the RootObj the Frame */
|
|
obj->part_of = obj;
|
|
obj_set_class_name(obj, _xmFrame);
|
|
|
|
/* Create a SubObj directly under the Frame */
|
|
subobj = objxmP_create_direct_subobj(obj, AB_TYPE_CONTAINER, "obj");
|
|
}
|
|
return subobj;
|
|
|
|
}
|
|
|
|
/*
|
|
* If Obj is XmConfigured with a Frame, collapse it
|
|
* back down to remove the Frame
|
|
*/
|
|
int
|
|
objxm_comp_unconfig_border_frame(
|
|
ABObj obj
|
|
)
|
|
{
|
|
ABObj subobj;
|
|
|
|
if (obj_has_border_frame(obj))
|
|
{
|
|
subobj = obj_get_child(obj, 0);
|
|
|
|
/* If First child is Menu-ref, then SubObj
|
|
* should be next child
|
|
*/
|
|
if (obj_is_menu_ref(subobj))
|
|
subobj = obj_get_child(obj, 1);
|
|
|
|
if (subobj)
|
|
{
|
|
if (obj_get_num_children(subobj) > 0)
|
|
obj_move_children(obj, subobj);
|
|
|
|
obj_destroy(subobj);
|
|
}
|
|
else if (util_get_verbosity() > 2)
|
|
{
|
|
fprintf(stderr,"objxm_comp_unconfig_border_frame: %s : can't find SubObj\n",
|
|
util_strsafe(obj_get_name(obj)));
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
int
|
|
objxm_comp_config_labeled_obj(
|
|
ABObj obj,
|
|
AB_OBJECT_TYPE obj_type,
|
|
STRING obj_suffix,
|
|
STRING obj_classname
|
|
)
|
|
{
|
|
ABObj lbl_obj = NULL;
|
|
ABObj real_obj;
|
|
|
|
if (obj_has_label(obj))
|
|
{
|
|
obj->part_of = obj;
|
|
|
|
/* Set Container RootObj class */
|
|
obj_set_class_name(obj, _xmRowColumn);
|
|
|
|
/* Create Label SubObj */
|
|
lbl_obj = obj_create(AB_TYPE_LABEL, NULL);
|
|
lbl_obj->part_of = obj;
|
|
obj_set_unique_name(lbl_obj,
|
|
ab_ident_from_name_and_label(obj_get_name(obj), "label"));
|
|
obj_set_class_name(lbl_obj, _xmLabel);
|
|
|
|
/* Create Real *Object* SubObj */
|
|
real_obj = obj_create(obj_type, NULL);
|
|
real_obj->part_of = obj;
|
|
obj_set_unique_name(real_obj,
|
|
ab_ident_from_name_and_label(obj_get_name(obj), obj_suffix));
|
|
obj_set_class_name(real_obj, obj_classname);
|
|
|
|
if (obj_get_num_children(obj) > 0)
|
|
obj_move_children(real_obj, obj);
|
|
|
|
obj_append_child(obj, lbl_obj);
|
|
obj_append_child(obj, real_obj);
|
|
|
|
}
|
|
else
|
|
obj_set_class_name(obj, obj_classname);
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
int
|
|
objxm_comp_unconfig_labeled_obj(
|
|
ABObj obj
|
|
)
|
|
{
|
|
ABObj lbl_obj;
|
|
ABObj real_obj;
|
|
|
|
if (obj_has_label(obj)) /* Has Label */
|
|
{
|
|
/* Destroy Label & Field SubObjs */
|
|
lbl_obj = obj_get_child(obj, 0);
|
|
real_obj = obj_get_child(obj, 1);
|
|
|
|
if (obj_get_num_children(obj) > 0)
|
|
obj_move_children(obj, real_obj);
|
|
|
|
obj_destroy(lbl_obj);
|
|
obj_destroy(real_obj);
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*
|
|
* If the Obj has a Menu, create a Menu-reference SubObj
|
|
* as the FIRST child of the Obj and return a handle to
|
|
* the Menu-reference. If Obj has no menu, or the menu
|
|
* is not found, return NULL.
|
|
*/
|
|
ABObj
|
|
objxm_comp_config_menu_ref(
|
|
ABObj obj
|
|
)
|
|
{
|
|
ABObj menu_obj;
|
|
ABObj menu_ref = NULL;
|
|
STRING menuname = obj_get_menu_name(obj);
|
|
|
|
if (menuname != NULL)
|
|
{
|
|
/* Make sure Virtual Menu obj exists in module */
|
|
if ((menu_obj = obj_find_menu_by_name(obj_get_module(obj), menuname)) != NULL)
|
|
{
|
|
/* ALWAYS make Menu Reference FIRST child! */
|
|
menu_ref = obj_create_ref(menu_obj);
|
|
obj_insert_child(obj, menu_ref, 0);
|
|
/*
|
|
REMIND: aim, 9/13/94 - The Menu Ref should not really be a "part of" an object
|
|
But, leaving this in (commented out) for now in case change
|
|
causes problems
|
|
|
|
menu_ref->part_of = obj;
|
|
*/
|
|
|
|
/* Menu Reference must point to Virtual menu object */
|
|
obj_set_unique_name(menu_ref,
|
|
ab_ident_from_name_and_label(obj_get_name(obj), menuname));
|
|
|
|
/*
|
|
** Set the object class of the Menu Reference to be that of the
|
|
** virtual menu object to which it refers. This makes it easier
|
|
** later on to figure out some of the aspects of handling the Menu
|
|
** Reference.
|
|
*/
|
|
if(obj_is_menubar_item(obj) || obj_is_menu_item(obj)) {
|
|
obj_set_class_name(menu_ref, _xmPulldownMenu);
|
|
}
|
|
else {
|
|
obj_set_class_name(menu_ref, _xmPopupMenu);
|
|
}
|
|
}
|
|
}
|
|
return menu_ref;
|
|
}
|
|
|
|
/*
|
|
* If Obj has a Menu-ref, remove it
|
|
*/
|
|
int
|
|
objxm_comp_unconfig_menu_ref(
|
|
ABObj obj
|
|
)
|
|
{
|
|
ABObj menu_ref;
|
|
|
|
if (obj_has_menu(obj))
|
|
{
|
|
menu_ref = objxm_comp_get_subobj(obj, AB_CFG_MENU_OBJ);
|
|
|
|
if (obj_is_ref(menu_ref))
|
|
obj_destroy(menu_ref);
|
|
}
|
|
return 0;
|
|
|
|
}
|