1553 lines
30 KiB
C
1553 lines
30 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 libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/*
|
|
* $XConsortium: utils.c /main/3 1995/11/06 18:16:13 rswiston $
|
|
*
|
|
* @(#)utils.c 3.76 16 Feb 1994 cde_app_builder/src/abmf
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
|
|
/*
|
|
* Main utility functions.
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <ab_private/XmAll.h>
|
|
#include <ab/util_types.h>
|
|
#include <ab_private/istr.h>
|
|
#include <ab_private/abio.h>
|
|
#include <ab_private/trav.h>
|
|
#include <ab_private/objxm.h>
|
|
#include "abmfP.h"
|
|
#include "motifdefsP.h"
|
|
#include "write_cP.h"
|
|
#include "write_codeP.h"
|
|
#include "obj_namesP.h"
|
|
#include "utilsP.h"
|
|
|
|
|
|
STRING nlstr = "\n";
|
|
STRING nlstr2 = "\n\n";
|
|
|
|
static int find_base_file_name(STRING path, int *startPtr, int *lenPtr);
|
|
|
|
/*
|
|
* Miscellaneous utility functions.
|
|
*/
|
|
|
|
/*
|
|
* Return the printed representation of a boolean.
|
|
*/
|
|
STRING
|
|
abmfP_boolean_string(int i)
|
|
{
|
|
return i ? "True" : "False";
|
|
}
|
|
|
|
|
|
/*
|
|
* Check a string to see if contains a legal identifier.
|
|
*/
|
|
int
|
|
abmfP_identifier_ok(STRING s)
|
|
{
|
|
return ab_c_ident_is_ok(s);
|
|
}
|
|
|
|
|
|
/*
|
|
* Capitalize the first letter of the given string.
|
|
*/
|
|
STRING
|
|
abmfP_capitalize_first_char(STRING str)
|
|
{
|
|
static char name[MAXPATHLEN] = "";
|
|
|
|
if (str == NULL)
|
|
return str;
|
|
|
|
if (isupper(str[0]))
|
|
return str;
|
|
|
|
if (str != name) /* if we get called w/our own buffer, don't copy */
|
|
{
|
|
snprintf(name, sizeof(name), "%s", str);
|
|
}
|
|
name[0] = toupper(str[0]);
|
|
|
|
return name;
|
|
}
|
|
|
|
|
|
/*
|
|
* Makes the 1st char lower case
|
|
*/
|
|
STRING
|
|
abmfP_uncapitalize_first_char(STRING str)
|
|
{
|
|
static char name[MAXPATHLEN] = "";
|
|
|
|
if (str == NULL)
|
|
return str;
|
|
|
|
if (islower(str[0]))
|
|
return str;
|
|
|
|
if (str != name) /* if we get called w/our own buffer, don't copy */
|
|
{
|
|
snprintf(name, sizeof(name), "%s", str);
|
|
}
|
|
name[0] = tolower(str[0]);
|
|
|
|
return name;
|
|
}
|
|
|
|
|
|
ABObj
|
|
abmfP_obj_find_codegen_parent(ABObj obj)
|
|
{
|
|
ABObj cgParent = obj->parent;
|
|
while ((cgParent != NULL) && obj_has_flag(cgParent, NoCodeGenFlag))
|
|
{
|
|
cgParent = cgParent->parent;
|
|
}
|
|
return cgParent;
|
|
}
|
|
|
|
/*
|
|
* Return TRUE if all items have the same Widget Class
|
|
*/
|
|
BOOL
|
|
abmfP_items_are_homogeneous(
|
|
ABObj obj
|
|
)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj item;
|
|
BOOL same = TRUE;
|
|
STRING ref_classname;
|
|
|
|
trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
|
|
item = trav_next(&trav);
|
|
if (item != NULL)
|
|
{
|
|
ref_classname = obj_get_class_name(item);
|
|
for (;(item = trav_next(&trav)) != NULL; )
|
|
if (util_strcmp(ref_classname, obj_get_class_name(item)) != 0)
|
|
{
|
|
same = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
return same;
|
|
}
|
|
|
|
BOOL
|
|
abmfP_items_have_mnemonics(
|
|
ABObj obj
|
|
)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj item;
|
|
BOOL has_mnemonics = False;
|
|
|
|
for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
|
|
(item = trav_next(&trav)) != NULL;)
|
|
if (obj_get_mnemonic(item) != NULL)
|
|
{
|
|
has_mnemonics = True;
|
|
break;
|
|
}
|
|
trav_close(&trav);
|
|
return has_mnemonics;
|
|
}
|
|
|
|
BOOL
|
|
abmfP_items_have_accelerators(
|
|
ABObj obj
|
|
)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj item;
|
|
BOOL has_accel = False;
|
|
|
|
for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
|
|
(item = trav_next(&trav)) != NULL;)
|
|
if (obj_get_accelerator(item) != NULL)
|
|
{
|
|
has_accel = True;
|
|
break;
|
|
}
|
|
trav_close(&trav);
|
|
return has_accel;
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns TRUE if the objects represent the same UI element.
|
|
*
|
|
* This shouldn't really be necessary - there should be NO duplicate objects,
|
|
* just multiple references to the same object.
|
|
*/
|
|
int
|
|
abmfP_obj_is_duplicate(ABObj obj, ABObj dupObj)
|
|
{
|
|
return (obj == dupObj);
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_parent_is_class(ABObj obj, STRING classname)
|
|
{
|
|
if ((abmfP_parent(obj) == NULL)
|
|
|| (obj_get_class_name(obj) == NULL)
|
|
|| (obj_get_class_name(abmfP_parent(obj)) == NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (util_streq(obj_get_class_name(abmfP_parent(obj)), classname))
|
|
{
|
|
return TRUE;
|
|
}
|
|
if (abmfP_parent(obj))
|
|
return abmfP_parent_is_class(abmfP_parent(obj), classname);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the actual control object.
|
|
*
|
|
* Since most controls have been converted to multiple toolkit objects (e.g., to
|
|
* add captions) except oblong, menu buttons, get the object that actually
|
|
* implements the type.
|
|
*
|
|
* The opposite of this is abmfP_get_container_object.
|
|
*/
|
|
ABObj
|
|
abmfP_get_actual_control(ABObj parent)
|
|
{
|
|
ABObj obj = objxm_comp_get_subobj(parent, AB_CFG_OBJECT_OBJ);
|
|
return obj;
|
|
} /* abmfP_get_actual_control */
|
|
|
|
|
|
/*
|
|
* Gets the object that is or contains all of the subobjects that make up a
|
|
* particular type of object.
|
|
*
|
|
* For instance, if a gauge is represented by a container that has a label and a
|
|
* gauge, this function will return the container object if any of the
|
|
* subobjects is passed in (or if the container itself is passed in). This
|
|
* function works on any type of object.
|
|
*
|
|
* The opposite function is abmfP_get_actual_control
|
|
*/
|
|
ABObj
|
|
abmfP_get_whole_object(ABObj obj)
|
|
{
|
|
return obj_get_root(obj);
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns the object that the callback has been "associated with."
|
|
* Normally the module it is declare in, or the project for cross-module
|
|
* conn's.
|
|
*
|
|
* Returns NULL if the callback is not found.
|
|
*/
|
|
ABObj
|
|
abmfP_find_callback_scope(ABObj obj, STRING callbackName)
|
|
{
|
|
ABObj scopeObj = NULL;
|
|
ABObj objModule = obj_get_module(obj);
|
|
ABObj objProject= obj_get_project(obj);
|
|
StringList callbackList = NULL;
|
|
AB_TRAVERSAL trav;
|
|
ABObj curModule= NULL;
|
|
|
|
if ((objModule != NULL) && (mfobj_get_module_data(objModule) != NULL))
|
|
{
|
|
callbackList = mfobj_get_module_data(objModule)->callbacks;
|
|
if (strlist_str_exists(callbackList, callbackName))
|
|
{
|
|
scopeObj = objModule;
|
|
}
|
|
}
|
|
|
|
if ((scopeObj == NULL) && (objProject != NULL))
|
|
{
|
|
for (trav_open(&trav, objProject, AB_TRAV_MODULES);
|
|
(scopeObj == NULL) && ((curModule = trav_next(&trav)) != NULL); )
|
|
{
|
|
if (mfobj_get_module_data(curModule) != NULL)
|
|
{
|
|
callbackList = mfobj_get_module_data(curModule)->callbacks;
|
|
if (strlist_str_exists(callbackList, callbackName))
|
|
{
|
|
scopeObj = curModule;
|
|
}
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
|
|
if (scopeObj == NULL)
|
|
{
|
|
callbackList = mfobj_get_proj_data(objProject)->callbacks;
|
|
if (strlist_str_exists(callbackList, callbackName))
|
|
{
|
|
scopeObj = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return scopeObj;
|
|
}
|
|
|
|
int
|
|
find_longest_label(STRING * label)
|
|
{
|
|
int len1,
|
|
len2,
|
|
longest = 0,
|
|
i = 0;
|
|
|
|
len1 = len2 = 0;
|
|
for (; label[i]; i++)
|
|
{
|
|
len1 = strlen(label[i]);
|
|
if (len1 > len2)
|
|
{
|
|
len2 = len1;
|
|
longest = i;
|
|
}
|
|
}
|
|
return longest;
|
|
}
|
|
|
|
/*************************************************************************
|
|
** **
|
|
** MEMORY ALLOCATION **
|
|
** **
|
|
*************************************************************************/
|
|
|
|
/*
|
|
* Version of calloc() with error checking.
|
|
*/
|
|
void *
|
|
abmfP_calloc(size_t n, size_t size)
|
|
{
|
|
char *p;
|
|
|
|
if (p = (STRING) calloc(n, size))
|
|
return p;
|
|
util_error(catgets(Dtb_project_catd, 1, 83, "calloc: out of memory"));
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Version of malloc() with error checking.
|
|
*/
|
|
void *
|
|
abmfP_malloc(size_t size)
|
|
{
|
|
void *p;
|
|
|
|
if (p = malloc(size))
|
|
return p;
|
|
util_error(catgets(Dtb_project_catd, 1, 84, "malloc: out of memory"));
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Version of realloc() with error checking.
|
|
*/
|
|
void *
|
|
abmfP_realloc(void *buf, unsigned int size)
|
|
{
|
|
void *p;
|
|
|
|
if (p = realloc(buf, size))
|
|
return p;
|
|
util_error(catgets(Dtb_project_catd, 1, 85, "realloc: out of memory"));
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the window parent of an object.
|
|
*/
|
|
ABObj
|
|
abmfP_get_window_parent(ABObj obj)
|
|
{
|
|
if (obj_is_top_level(obj))
|
|
return NULL;
|
|
else if (abmfP_parent(obj) && obj_is_top_level(abmfP_parent(obj)))
|
|
return abmfP_parent(obj);
|
|
else if (abmfP_parent(obj))
|
|
return abmfP_get_window_parent(abmfP_parent(obj));
|
|
return ((ABObj) NULL);
|
|
}
|
|
|
|
|
|
/*
|
|
* Return the window pane of an object.
|
|
*/
|
|
ABObj
|
|
abmfP_get_window_pane(ABObj obj)
|
|
{
|
|
if (abmfP_parent(obj) == NULL)
|
|
{
|
|
return ((ABObj) NULL);
|
|
}
|
|
if (obj_is_top_level(obj))
|
|
return NULL;
|
|
else if (obj_is_pane(abmfP_parent(obj)) || obj_is_top_level(abmfP_parent(obj)))
|
|
return abmfP_parent(obj);
|
|
|
|
return abmfP_get_window_pane(abmfP_parent(obj));
|
|
}
|
|
|
|
|
|
/*
|
|
* Copy one file to another.
|
|
*/
|
|
int
|
|
abmfP_filecopy(STRING file1, STRING file2)
|
|
{
|
|
FILE *inp;
|
|
FILE *outp;
|
|
int c;
|
|
|
|
if ((inp = util_fopen_locked(file1, "r")) == NULL ||
|
|
(outp = util_fopen_locked(file2, "w")) == NULL)
|
|
return ERROR;
|
|
|
|
while ((c = fgetc(inp)) != EOF)
|
|
fputc(c, outp);
|
|
|
|
fclose(inp);
|
|
fclose(outp);
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* assigns names to object without them. This is a safty measure.
|
|
*/
|
|
int
|
|
abmfP_assign_widget_names(ABObj root)
|
|
{
|
|
int iReturn = 0;
|
|
ABObj win_obj;
|
|
static int i = 0;
|
|
char Buf[64];
|
|
AB_TRAVERSAL trav;
|
|
|
|
/*
|
|
* Base windows
|
|
*/
|
|
for (trav_open(&trav, root, AB_TRAV_WINDOWS), i = 1;
|
|
(win_obj = trav_next(&trav)) != NULL;)
|
|
{
|
|
if (obj_get_name(win_obj) == NULL)
|
|
{ /* Only assign once */
|
|
sprintf(Buf, "%s%d", "widget", i);
|
|
obj_set_name(win_obj, Buf);
|
|
}
|
|
i++;
|
|
}
|
|
trav_close(&trav);
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
abmfP_tree_set_written(ABObj root, BOOL written)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj obj = NULL;
|
|
|
|
for (trav_open(&trav, root, AB_TRAV_ALL);
|
|
(obj = trav_next(&trav)) != NULL;)
|
|
{
|
|
obj_set_was_written(obj, written);
|
|
}
|
|
trav_close(&trav);
|
|
return 0;
|
|
}
|
|
|
|
|
|
abmfP_obj_set_items_written(ABObj rootObj, BOOL written)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj obj = NULL;
|
|
|
|
for (trav_open(&trav, rootObj, AB_TRAV_ITEMS_FOR_OBJ);
|
|
(obj = trav_next(&trav)) != NULL;)
|
|
{
|
|
obj_set_was_written(obj, written);
|
|
}
|
|
trav_close(&trav);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* gets the #define string for the file
|
|
*/
|
|
STRING
|
|
abmfP_get_define_from_file_name(STRING fileName)
|
|
{
|
|
static char define[MAX_NAME_SIZE];
|
|
int fileNameLen= strlen(fileName);
|
|
int iFileName= 0;
|
|
int iDefine= 0;
|
|
char fileNameChar= 0;
|
|
|
|
strcpy(define, "_");
|
|
iDefine= 1;
|
|
for (iFileName= 0; iFileName < fileNameLen; ++iFileName)
|
|
{
|
|
fileNameChar= fileName[iFileName];
|
|
if (isalnum(fileNameChar))
|
|
{
|
|
define[iDefine++]= toupper(fileNameChar);
|
|
}
|
|
else
|
|
{
|
|
if (define[iDefine-1] != '_')
|
|
{
|
|
define[iDefine++]= '_';
|
|
}
|
|
}
|
|
}
|
|
if ((iDefine > 0) && (define[iDefine-1] != '_'))
|
|
{
|
|
define[iDefine++]= '_';
|
|
}
|
|
define[iDefine]= 0;
|
|
return define;
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_file_name_is_bitmap(STRING fileName)
|
|
{
|
|
return util_file_name_has_extension(fileName, "xbm");
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_file_name_is_xpm(STRING fileName)
|
|
{
|
|
return util_file_name_has_extension(fileName, "pm");
|
|
}
|
|
|
|
|
|
STRING
|
|
abmfP_cvt_file_name_to_bitmap_data_vars(
|
|
STRING path,
|
|
STRING *widthVarPtr,
|
|
STRING *heightVarPtr,
|
|
STRING *bitsVarPtr
|
|
)
|
|
{
|
|
#define widthVar (*widthVarPtr)
|
|
#define heightVar (*heightVarPtr)
|
|
#define bitsVar (*bitsVarPtr)
|
|
static char widthVarBuf[256];
|
|
static char heightVarBuf[256];
|
|
static char bitsVarBuf[256];
|
|
int baseIndex = -1;
|
|
int baseLen = -1;
|
|
char *nameStart = NULL;
|
|
|
|
widthVar = heightVar = bitsVar = NULL;
|
|
|
|
find_base_file_name(path, &baseIndex, &baseLen);
|
|
nameStart = &(path[baseIndex]);
|
|
|
|
strncpy(widthVarBuf, nameStart, baseLen);
|
|
widthVarBuf[baseLen]= 0;
|
|
strcpy(heightVarBuf, widthVarBuf);
|
|
strcpy(bitsVarBuf, widthVarBuf);
|
|
|
|
strcat(widthVarBuf, "_width");
|
|
strcpy(widthVarBuf, ab_make_valid_c_ident(widthVarBuf));
|
|
|
|
strcat(heightVarBuf, "_height");
|
|
strcpy(heightVarBuf, ab_make_valid_c_ident(heightVarBuf));
|
|
|
|
strcat(bitsVarBuf, "_bits");
|
|
strcpy(bitsVarBuf, ab_make_valid_c_ident(bitsVarBuf));
|
|
|
|
widthVar = widthVarBuf;
|
|
heightVar = heightVarBuf;
|
|
bitsVar = bitsVarBuf;
|
|
|
|
return 0;
|
|
#undef widthVar
|
|
#undef heightVar
|
|
#undef bitsVar
|
|
}
|
|
|
|
|
|
STRING
|
|
abmfP_cvt_file_name_to_xpm_data_var(STRING path)
|
|
{
|
|
static char varName[256];
|
|
int baseStart = -1;
|
|
int baseLen = -1;
|
|
|
|
*varName = 0;
|
|
find_base_file_name(path, &baseStart, &baseLen);
|
|
if (baseLen > 0)
|
|
{
|
|
strncpy(varName, path+baseStart, baseLen);
|
|
varName[baseLen]= 0;
|
|
strcat(varName, "_pm");
|
|
}
|
|
return ab_make_valid_c_ident(varName);
|
|
}
|
|
|
|
|
|
int
|
|
abmfP_obj_set_subobjs_written(ABObj obj, BOOL written)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj subObj= NULL;
|
|
|
|
for (trav_open(&trav, obj, AB_TRAV_ALL);
|
|
(subObj= trav_next(&trav)) != NULL; )
|
|
{
|
|
if ( (subObj == obj)
|
|
|| (obj_get_root(subObj) != obj))
|
|
{
|
|
continue;
|
|
}
|
|
obj_set_was_written(subObj, written);
|
|
}
|
|
trav_close(&trav);
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_objs_in_same_struct(ABObj obj1, ABObj obj2)
|
|
{
|
|
ABObj structObj1= abmfP_obj_get_struct_obj(obj1);
|
|
ABObj structObj2= abmfP_obj_get_struct_obj(obj2);
|
|
return ((structObj1 != NULL) && (structObj1 == structObj2));
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_objs_in_same_substruct(ABObj obj1, ABObj obj2)
|
|
{
|
|
ABObj structObj1 = abmfP_obj_get_substruct_obj(obj1);
|
|
ABObj structObj2 = abmfP_obj_get_substruct_obj(obj2);
|
|
return ((structObj1 != NULL) && (structObj1 == structObj2));
|
|
}
|
|
|
|
|
|
/*
|
|
* We have two types of structures:
|
|
* - one structure for each window
|
|
* - one structure for all the menus in an interface
|
|
*/
|
|
ABObj
|
|
abmfP_obj_get_struct_obj(ABObj obj)
|
|
{
|
|
ABObj structObj = NULL;
|
|
|
|
if (mfobj_has_flags(obj, CGenFlagStructObjValid))
|
|
{
|
|
goto epilogue;
|
|
}
|
|
|
|
for (structObj = obj;
|
|
structObj != NULL && !abmfP_obj_is_struct_obj(structObj);
|
|
structObj = abmfP_parent(structObj)
|
|
) ;
|
|
|
|
/*
|
|
* Save the data
|
|
*/
|
|
mfobj_set_flags(obj, CGenFlagStructObjValid);
|
|
mfobj_data(obj)->struct_obj = structObj;
|
|
|
|
epilogue:
|
|
return mfobj_data(obj)->struct_obj;
|
|
}
|
|
|
|
|
|
/*
|
|
* Currently, only items go in substructs. List items don't however,
|
|
* because they don't cause widgets to be created.
|
|
*/
|
|
ABObj
|
|
abmfP_obj_get_substruct_obj(ABObj obj)
|
|
{
|
|
ABObj substructObj = NULL;
|
|
|
|
if (mfobj_has_flags(obj, CGenFlagSubstructObjValid))
|
|
{
|
|
goto epilogue;
|
|
}
|
|
|
|
if (obj_is_item(obj))
|
|
{
|
|
ABObj parent = abmfP_parent(obj);
|
|
if (parent != NULL)
|
|
{
|
|
substructObj = obj_get_root(parent);
|
|
}
|
|
if ( (substructObj != NULL)
|
|
&& (!abmfP_obj_is_substruct_obj(substructObj)) )
|
|
{
|
|
substructObj = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Save the data
|
|
*/
|
|
mfobj_set_flags(obj, CGenFlagSubstructObjValid);
|
|
mfobj_data(obj)->substruct_obj = substructObj;
|
|
|
|
epilogue:
|
|
return mfobj_data(obj)->substruct_obj;
|
|
}
|
|
|
|
|
|
int
|
|
abmfP_get_num_substruct_fields(ABObj obj)
|
|
{
|
|
int numFields = 0;
|
|
ABObj substruct = abmfP_obj_get_substruct_obj(obj);
|
|
AB_TRAVERSAL trav;
|
|
ABObj subobj = NULL;
|
|
|
|
/*
|
|
* Don't
|
|
*/
|
|
for (trav_open(&trav, substruct, AB_TRAV_UI);
|
|
(subobj = trav_next(&trav)) != NULL; )
|
|
{
|
|
if (abmfP_obj_has_substruct_field(subobj))
|
|
{
|
|
if (subobj == obj)
|
|
{
|
|
++numFields;
|
|
}
|
|
else if (abmfP_obj_get_substruct_obj(subobj) == obj)
|
|
{
|
|
++numFields;
|
|
}
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
|
|
return numFields;
|
|
}
|
|
|
|
STRING
|
|
abmfP_convert_wclass_ptr_to_name(WidgetClass wclass)
|
|
{
|
|
STRING wclass_name= NULL;
|
|
|
|
if (wclass == xmCascadeButtonWidgetClass)
|
|
{
|
|
wclass_name= istr_string(abmfP_xmCascadeButton);
|
|
}
|
|
else if (wclass == xmScrolledWindowWidgetClass)
|
|
{
|
|
wclass_name= istr_string(abmfP_xmScrolledWindow);
|
|
}
|
|
else if (wclass == xmToggleButtonWidgetClass)
|
|
{
|
|
wclass_name= istr_string(abmfP_xmToggleButton);
|
|
}
|
|
|
|
return wclass_name;
|
|
}
|
|
|
|
|
|
/*
|
|
* Finds the primary window for the application.
|
|
* Finds the base window whose name is alphabetically first
|
|
*/
|
|
ABObj
|
|
abmfP_get_root_window(ABObj project)
|
|
{
|
|
static ABObj root_window= NULL;
|
|
AB_TRAVERSAL trav;
|
|
ABObj window= NULL;
|
|
|
|
if (root_window != NULL)
|
|
{
|
|
return root_window;
|
|
}
|
|
|
|
if (obj_get_root_window(project) == NULL)
|
|
{
|
|
for (trav_open(&trav, project, AB_TRAV_WINDOWS);
|
|
(window= trav_next(&trav)) != NULL; )
|
|
{
|
|
if (!obj_is_base_win(window))
|
|
{
|
|
continue;
|
|
}
|
|
if (root_window == NULL)
|
|
{
|
|
root_window = window;
|
|
}
|
|
else
|
|
{
|
|
if ( (!obj_is_initially_visible(root_window))
|
|
&& (obj_is_initially_visible(window)) )
|
|
{
|
|
root_window = window;
|
|
}
|
|
else if (util_strcmp(
|
|
obj_get_name(window), obj_get_name(root_window)) < 0)
|
|
{
|
|
root_window= window;
|
|
}
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
} /* root_window == NULL */
|
|
|
|
if (obj_get_root_window(project) != NULL)
|
|
{
|
|
root_window= obj_get_root_window(project);
|
|
}
|
|
|
|
return root_window;
|
|
}
|
|
|
|
|
|
/*
|
|
* Essentially, all salient UI objects have create procs.
|
|
*
|
|
* The exceptions are:
|
|
* - MENU references not salient, but have create procs
|
|
* - ITEMs are salient, but do not have create procs
|
|
* (they are created in their parent's proc)
|
|
*/
|
|
BOOL
|
|
abmfP_obj_has_create_proc(ABObj obj)
|
|
{
|
|
if (obj_is_menu(obj))
|
|
{
|
|
/*
|
|
* menus are considered virtual, in that the "menu" doesn't
|
|
* actually exist - the menu references do. We write a create
|
|
* proc for each menu reference.
|
|
*/
|
|
return (obj_is_ref(obj) && (abmfP_obj_get_struct_obj(obj) != NULL));
|
|
}
|
|
if (obj_is_virtual(obj))
|
|
{
|
|
/* virtual objects never get written */
|
|
return FALSE;
|
|
}
|
|
if (obj_is_item(obj))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return obj_is_salient_ui(obj);
|
|
}
|
|
|
|
|
|
/*
|
|
* create procs take a pointer to the struct we're going to fill in.
|
|
*/
|
|
STRING
|
|
abmfP_obj_get_create_proc_instance_param_type(ABObj obj)
|
|
{
|
|
ABObj structObj = NULL;
|
|
|
|
structObj = abmfP_obj_get_struct_obj(obj);
|
|
if (structObj == NULL)
|
|
{
|
|
return "Widget *";
|
|
}
|
|
|
|
return abmfP_get_c_struct_ptr_type_name(structObj);
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_obj_create_proc_has_instance_param(ABObj obj)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_obj_create_proc_has_name_param(ABObj obj)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* - topmost object in structure requires a parent from client
|
|
* - menus need parents because, if they are shared, each instance
|
|
* will have a different parent
|
|
*/
|
|
BOOL
|
|
abmfP_obj_create_proc_has_parent_param(ABObj obj)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
int
|
|
abmfP_obj_get_num_create_proc_return_widgets(ABObj obj)
|
|
{
|
|
int numWidgets = 0;
|
|
|
|
numWidgets = 0;
|
|
|
|
return numWidgets;
|
|
}
|
|
|
|
|
|
/*
|
|
* which_param is 0..n-1 params
|
|
*/
|
|
STRING
|
|
abmfP_obj_get_create_proc_return_widget_name(ABObj obj, int which_param)
|
|
{
|
|
STRING paramName = NULL;
|
|
|
|
if (which_param > 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (abmfP_obj_is_substruct_obj(obj))
|
|
{
|
|
return abmfP_get_c_substruct_ptr_type_name(obj);
|
|
}
|
|
else if (abmfP_obj_is_struct_obj(obj))
|
|
{
|
|
return abmfP_get_c_struct_ptr_type_name(obj);
|
|
}
|
|
|
|
return paramName;
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_obj_create_proc_has_submenu_params(ABObj obj)
|
|
{
|
|
return FALSE;
|
|
/* return (abmfP_obj_has_menu(obj) || abmfP_obj_has_item_with_menu(obj)); */
|
|
}
|
|
|
|
|
|
int
|
|
abmfP_get_num_cp_submenu_params(ABObj obj)
|
|
{
|
|
return 0;
|
|
/*
|
|
AB_TRAVERSAL trav;
|
|
ABObj item;
|
|
int numSubmenus = 0;
|
|
|
|
if (abmfP_obj_has_menu(obj))
|
|
{
|
|
++numSubmenus;
|
|
}
|
|
|
|
for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
|
|
(item = trav_next(&trav)) != NULL; )
|
|
{
|
|
if (abmfP_obj_has_menu(item))
|
|
{
|
|
++numSubmenus;
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
|
|
return numSubmenus;
|
|
*/
|
|
}
|
|
|
|
|
|
STRING
|
|
abmfP_get_cp_submenu_param_name(ABObj obj, int whichParam)
|
|
{
|
|
ABObj paramObj = abmfP_get_cp_submenu_param_obj(obj, whichParam);
|
|
if (paramObj == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
return abmfP_get_c_field_name(paramObj);
|
|
}
|
|
|
|
|
|
STRING
|
|
abmfP_get_cp_submenu_param_type_name(ABObj obj, int whichParam)
|
|
{
|
|
return abmfP_str_widget;
|
|
}
|
|
|
|
|
|
ABObj
|
|
abmfP_get_cp_submenu_param_obj(ABObj obj, int whichParam)
|
|
{
|
|
int curParam = -1;
|
|
ABObj menu = NULL;
|
|
ABObj paramObj = NULL;
|
|
AB_TRAVERSAL trav;
|
|
ABObj item = NULL;
|
|
|
|
if ((menu = obj_get_menu(obj)) != NULL)
|
|
{
|
|
++curParam;
|
|
if (curParam == whichParam)
|
|
{
|
|
paramObj = menu;
|
|
goto epilogue;
|
|
}
|
|
}
|
|
|
|
for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
|
|
(item = trav_next(&trav)) != NULL; )
|
|
{
|
|
if ((menu = obj_get_menu(item)) != NULL)
|
|
{
|
|
++curParam;
|
|
if (curParam == whichParam)
|
|
{
|
|
paramObj = menu;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
|
|
epilogue:
|
|
return paramObj;
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_obj_has_menu(ABObj obj)
|
|
{
|
|
return (obj_get_menu(obj) != NULL);
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_obj_has_item_with_menu(ABObj obj)
|
|
{
|
|
BOOL itemHasMenu = FALSE;
|
|
AB_TRAVERSAL trav;
|
|
ABObj item;
|
|
|
|
for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
|
|
(item = trav_next(&trav)) != NULL; )
|
|
{
|
|
if (abmfP_obj_has_menu(item))
|
|
{
|
|
itemHasMenu = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
|
|
return itemHasMenu;
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_module_has_menu_struct(ABObj obj)
|
|
{
|
|
static ABObj lastModule = NULL;
|
|
static BOOL lastModuleHadMenuStruct = FALSE;
|
|
ABObj module = obj_get_module(obj);
|
|
BOOL hasMenuStruct = FALSE;
|
|
|
|
if (module == lastModule)
|
|
{
|
|
hasMenuStruct = lastModuleHadMenuStruct;
|
|
}
|
|
else
|
|
{
|
|
hasMenuStruct = (trav_count(module, AB_TRAV_MENUS) > 0);
|
|
lastModule = module;
|
|
lastModuleHadMenuStruct = hasMenuStruct;
|
|
}
|
|
|
|
return hasMenuStruct;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
abmfP_obj_has_glyph_label(ABObj obj)
|
|
{
|
|
return ( (obj_get_label(obj) != NULL)
|
|
&& (obj_get_label_type(obj) == AB_LABEL_GLYPH));
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_obj_has_item_with_glyph_label(ABObj obj)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj item = NULL;
|
|
BOOL doesIt = FALSE;
|
|
|
|
for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
|
|
(item = trav_next(&trav)) != NULL; )
|
|
{
|
|
if (abmfP_obj_has_glyph_label(item))
|
|
{
|
|
doesIt = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
|
|
return doesIt;
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_obj_has_string_label(ABObj obj)
|
|
{
|
|
return ( (obj_get_label(obj) != NULL)
|
|
&& (obj_get_label_type(obj) == AB_LABEL_STRING));
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_obj_has_item_with_string_label(ABObj obj)
|
|
{
|
|
AB_TRAVERSAL trav;
|
|
ABObj item = NULL;
|
|
BOOL doesIt = FALSE;
|
|
|
|
for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
|
|
(item = trav_next(&trav)) != NULL; )
|
|
{
|
|
if (abmfP_obj_has_string_label(item))
|
|
{
|
|
doesIt = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
trav_close(&trav);
|
|
|
|
return doesIt;
|
|
}
|
|
|
|
BOOL
|
|
abmfP_proj_needs_session_save(ABObj proj)
|
|
{
|
|
AB_SESSIONING_METHOD ss_mthd;
|
|
|
|
if (!proj)
|
|
return (FALSE);
|
|
|
|
if (!obj_is_project(proj))
|
|
{
|
|
proj = obj_get_project(proj);
|
|
|
|
if (!proj || !obj_is_project(proj))
|
|
return (FALSE);
|
|
}
|
|
|
|
ss_mthd = obj_get_sessioning_method(proj);
|
|
|
|
switch (ss_mthd) {
|
|
case AB_SESSIONING_UNDEF:
|
|
case AB_SESSIONING_NONE:
|
|
return (FALSE);
|
|
case AB_SESSIONING_CMDLINE:
|
|
case AB_SESSIONING_FILE:
|
|
case AB_SESSIONING_CMDLINE_AND_FILE:
|
|
return (TRUE);
|
|
default:
|
|
return (FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
abmfP_proj_needs_session_restore(ABObj proj)
|
|
{
|
|
AB_SESSIONING_METHOD ss_mthd;
|
|
|
|
if (!proj)
|
|
return (FALSE);
|
|
|
|
if (!obj_is_project(proj))
|
|
{
|
|
proj = obj_get_project(proj);
|
|
|
|
if (!proj || !obj_is_project(proj))
|
|
return (FALSE);
|
|
}
|
|
|
|
ss_mthd = obj_get_sessioning_method(proj);
|
|
|
|
switch (ss_mthd) {
|
|
case AB_SESSIONING_UNDEF:
|
|
case AB_SESSIONING_NONE:
|
|
case AB_SESSIONING_CMDLINE:
|
|
return (FALSE);
|
|
case AB_SESSIONING_FILE:
|
|
case AB_SESSIONING_CMDLINE_AND_FILE:
|
|
return (TRUE);
|
|
default:
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
abmfP_obj_needs_centering_handler(ABObj obj)
|
|
{
|
|
AB_ATTACH_TYPE left_attach_type,
|
|
top_attach_type;
|
|
|
|
if (!obj)
|
|
return (FALSE);
|
|
|
|
left_attach_type = obj_get_attach_type(obj, AB_CP_WEST);
|
|
top_attach_type = obj_get_attach_type(obj, AB_CP_NORTH);
|
|
|
|
if ((left_attach_type == AB_ATTACH_CENTER_GRIDLINE) ||
|
|
(top_attach_type == AB_ATTACH_CENTER_GRIDLINE))
|
|
return (TRUE);
|
|
else
|
|
return (FALSE);
|
|
}
|
|
|
|
STRING
|
|
abmfP_obj_get_centering_type(ABObj obj)
|
|
{
|
|
AB_ATTACH_TYPE left_attach_type,
|
|
top_attach_type;
|
|
|
|
if (!obj || !abmfP_obj_needs_centering_handler(obj))
|
|
return("DTB_CENTER_NONE");
|
|
|
|
left_attach_type = obj_get_attach_type(obj, AB_CP_WEST);
|
|
top_attach_type = obj_get_attach_type(obj, AB_CP_NORTH);
|
|
|
|
if ((left_attach_type == AB_ATTACH_CENTER_GRIDLINE) &&
|
|
(top_attach_type != AB_ATTACH_CENTER_GRIDLINE))
|
|
return("DTB_CENTER_POSITION_VERT");
|
|
|
|
if ((left_attach_type != AB_ATTACH_CENTER_GRIDLINE) &&
|
|
(top_attach_type == AB_ATTACH_CENTER_GRIDLINE))
|
|
return("DTB_CENTER_POSITION_HORIZ");
|
|
|
|
if ((left_attach_type == AB_ATTACH_CENTER_GRIDLINE) &&
|
|
(top_attach_type == AB_ATTACH_CENTER_GRIDLINE))
|
|
return("DTB_CENTER_POSITION_BOTH");
|
|
|
|
return("DTB_CENTER_NONE");
|
|
}
|
|
|
|
BOOL
|
|
abmfP_obj_needs_align_handler(ABObj obj)
|
|
{
|
|
AB_GROUP_TYPE type;
|
|
|
|
if (!obj || !obj_is_group(obj))
|
|
return (FALSE);
|
|
|
|
type = obj_get_group_type(obj);
|
|
|
|
if (type != AB_GROUP_IGNORE)
|
|
return (TRUE);
|
|
else
|
|
return (FALSE);
|
|
}
|
|
|
|
STRING
|
|
abmfP_obj_get_group_type(ABObj obj)
|
|
{
|
|
|
|
AB_GROUP_TYPE type;
|
|
|
|
if (!obj || !abmfP_obj_needs_align_handler(obj))
|
|
return("DTB_GROUP_NONE");
|
|
|
|
type = obj_get_group_type(obj);
|
|
|
|
switch (type)
|
|
{
|
|
case AB_GROUP_IGNORE:
|
|
return("DTB_GROUP_NONE");
|
|
case AB_GROUP_ROWS:
|
|
return("DTB_GROUP_ROWS");
|
|
case AB_GROUP_COLUMNS:
|
|
return("DTB_GROUP_COLUMNS");
|
|
case AB_GROUP_ROWSCOLUMNS:
|
|
return("DTB_GROUP_ROWSCOLUMNS");
|
|
}
|
|
|
|
return("DTB_GROUP_NONE");
|
|
}
|
|
|
|
STRING
|
|
abmfP_obj_get_row_align_type(ABObj obj)
|
|
{
|
|
AB_GROUP_TYPE group_type;
|
|
AB_ALIGNMENT align_type;
|
|
|
|
if (!obj)
|
|
return("DTB_ALIGN_NONE");
|
|
|
|
group_type = obj_get_group_type(obj);
|
|
|
|
if ((group_type == AB_GROUP_COLUMNS) || (group_type == AB_GROUP_IGNORE))
|
|
return("DTB_ALIGN_NONE");
|
|
|
|
align_type = obj_get_row_align(obj);
|
|
|
|
switch (align_type)
|
|
{
|
|
case AB_ALIGN_TOP:
|
|
return("DTB_ALIGN_TOP");
|
|
case AB_ALIGN_HCENTER:
|
|
return("DTB_ALIGN_HCENTER");
|
|
case AB_ALIGN_BOTTOM:
|
|
return("DTB_ALIGN_BOTTOM");
|
|
default:
|
|
return("DTB_ALIGN_NONE");
|
|
}
|
|
}
|
|
|
|
STRING
|
|
abmfP_obj_get_col_align_type(ABObj obj)
|
|
{
|
|
AB_GROUP_TYPE group_type;
|
|
AB_ALIGNMENT align_type;
|
|
|
|
if (!obj)
|
|
return("DTB_ALIGN_NONE");
|
|
|
|
group_type = obj_get_group_type(obj);
|
|
|
|
if ((group_type == AB_GROUP_ROWS) || (group_type == AB_GROUP_IGNORE))
|
|
return("DTB_ALIGN_NONE");
|
|
|
|
align_type = obj_get_col_align(obj);
|
|
|
|
switch (align_type)
|
|
{
|
|
case AB_ALIGN_LEFT:
|
|
return("DTB_ALIGN_LEFT");
|
|
case AB_ALIGN_LABELS:
|
|
return("DTB_ALIGN_LABELS");
|
|
case AB_ALIGN_VCENTER:
|
|
return("DTB_ALIGN_VCENTER");
|
|
case AB_ALIGN_RIGHT:
|
|
return("DTB_ALIGN_RIGHT");
|
|
default:
|
|
return("DTB_ALIGN_NONE");
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Returns the starting index and length of the base file name
|
|
* sans leading path and trailing extension.
|
|
*
|
|
*/
|
|
static int
|
|
find_base_file_name(STRING path, int *startPtr, int *lenPtr)
|
|
{
|
|
#define start (*startPtr)
|
|
#define len (*lenPtr)
|
|
char *slashPtr = NULL;
|
|
char *dotPtr = NULL;
|
|
int slashChar = -1;
|
|
int dotChar = -1;
|
|
|
|
slashPtr = strrchr(path, '/');
|
|
if (slashPtr != NULL)
|
|
{
|
|
/*
|
|
* handle strings of the form subdir//x.ext
|
|
*/
|
|
while (((*slashPtr) == '/') && ((*slashPtr) != 0))
|
|
{
|
|
++slashPtr;
|
|
}
|
|
--slashPtr; /* point to last slash */
|
|
slashChar = *slashPtr;
|
|
*slashPtr = 0;
|
|
}
|
|
|
|
start = 0;
|
|
if (slashPtr != NULL)
|
|
{
|
|
start = ((int)(slashPtr - path)) + 1;
|
|
}
|
|
|
|
dotPtr = strrchr(&(path[start]), '.');
|
|
if (dotPtr != NULL)
|
|
{
|
|
dotChar = *dotPtr;
|
|
*dotPtr = 0;
|
|
}
|
|
|
|
len = strlen(&path[start]);
|
|
|
|
/*
|
|
* Restore the string
|
|
*/
|
|
if (slashPtr != NULL)
|
|
{
|
|
*slashPtr = (char)slashChar;
|
|
}
|
|
if (dotPtr != NULL)
|
|
{
|
|
*dotPtr = (char)dotChar;
|
|
}
|
|
|
|
return 0;
|
|
#undef start
|
|
#undef len
|
|
}
|
|
|
|
BOOL
|
|
abmfP_proj_has_message(ABObj proj)
|
|
{
|
|
ABObj obj = (ABObj) NULL;
|
|
AB_TRAVERSAL trav;
|
|
int i = 0;
|
|
BOOL hasMsg = FALSE;
|
|
|
|
if (!proj)
|
|
return (FALSE);
|
|
|
|
if (!obj_is_project(proj))
|
|
{
|
|
proj = obj_get_project(proj);
|
|
|
|
if (!proj || !obj_is_project(proj))
|
|
return (FALSE);
|
|
}
|
|
|
|
for (trav_open(&trav, proj, AB_TRAV_SALIENT_UI);
|
|
((obj = trav_next(&trav)) != NULL) && !hasMsg; )
|
|
{
|
|
if (obj_is_message(obj))
|
|
hasMsg = TRUE;
|
|
}
|
|
|
|
return (hasMsg);
|
|
}
|
|
|
|
|
|
/*
|
|
** 4/30/95 bfreeman - Temporary. This is obj_get_refs_to's territory! But, I
|
|
** wasn't able to get the refs to menu items out of obj_get_refs_to()...the
|
|
** objects just aren't there.
|
|
**
|
|
** Returns an ABObjList containing all of the references to obj
|
|
**
|
|
** Example use:
|
|
**
|
|
** ABObjList refList = abmfP_find_refs_to(obj);
|
|
** ABObj refObj = NULL;
|
|
** int numRefs = objlist_get_num_objs(refList);
|
|
** int i = 0;
|
|
**
|
|
** if ((refList != NULL) && (numRefs > 0))
|
|
** {
|
|
** for (i = 0; i < numRefs; ++i)
|
|
** {
|
|
** refObj = objlist_get_obj(refList, i, NULL);
|
|
**
|
|
** --- use refObj, it refers to obj ---
|
|
**
|
|
** }
|
|
** }
|
|
** objlist_destroy(refList);
|
|
**
|
|
**
|
|
** Note: May return NULL and it is the responsibility of the caller to
|
|
** destroy the ABObjList.
|
|
*/
|
|
ABObjList
|
|
abmfP_find_refs_to(ABObj obj)
|
|
{
|
|
AB_TRAVERSAL moduleTrav;
|
|
ABObjList refList = NULL;
|
|
ABObj refObj = NULL;
|
|
|
|
if (obj == NULL)
|
|
return NULL;
|
|
|
|
refList = objlist_create();
|
|
|
|
for (trav_open(&moduleTrav, obj_get_module(obj), AB_TRAV_UI);
|
|
((refObj = trav_next(&moduleTrav)) != NULL); )
|
|
{
|
|
if (obj_is_ref(refObj) && (refObj->ref_to == obj))
|
|
{
|
|
objlist_add_obj(refList, refObj, NULL);
|
|
}
|
|
}
|
|
trav_close(&moduleTrav);
|
|
|
|
return refList;
|
|
}
|
|
|
|
|