1571 lines
27 KiB
C++
1571 lines
27 KiB
C++
//-------------------------------------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, SH Software Co. Ltd.
|
|
// = FileName : Entity 类
|
|
// = Version : ver2.0
|
|
// = Author : zjq
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: Entity 定义
|
|
// = Maintainers:
|
|
//
|
|
//-------------------------------------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "Entity.h"
|
|
#include "XArc.h"
|
|
#include "XAString.h"
|
|
#include "PickSet.h"
|
|
#include "DragPickEntSet.h"
|
|
#include "XPoly2D.h"
|
|
#include "XDbObject.h"
|
|
#include "X3DFace.h"
|
|
#include "XPushVar.h"
|
|
#include "SymbolTable.h"
|
|
#include "DragPickEntSet.h"
|
|
#include "XBlockTable.h"
|
|
#include "XGlobalFunc.h"
|
|
#include "XPrivateGlobalFunc.h"
|
|
|
|
static const TCHAR *sMsgPrompt[] =
|
|
{
|
|
/*MSG0*/ _T("\n选择无效, 重新选择!"),
|
|
/*MSG1*/ _T("\n请重新选择!"),
|
|
/*MSG2*/ _T("\n发现不可变形的对象: "),
|
|
/*MSG3*/ _T("\n图块内有延伸方向不同于Z轴的对象,不能打散!"),
|
|
/*MSG4*/ _T("\n是否为该对象"),
|
|
};
|
|
|
|
const TCHAR* Entity::ApplicationName=_T("_ASH");
|
|
|
|
|
|
Entity::~Entity()
|
|
{
|
|
|
|
}
|
|
|
|
int Entity::MatchEx(int tag, const Groups *data)
|
|
{
|
|
if (!groups)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
if (!groupsEx || !data)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Groups *rbData = SearchDataByTag(tag);
|
|
if (!rbData)
|
|
{
|
|
return 0;
|
|
}
|
|
return (*rbData) == (*data);
|
|
}
|
|
|
|
int Entity::MatchEx(int tag, int data)
|
|
{
|
|
if (!groups)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
if (!groupsEx)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Groups *rbData = SearchDataByTag(tag);
|
|
if (!rbData || rbData->code != XD_SHORT)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return (rbData->shortInt == data);
|
|
}
|
|
|
|
int Entity::MatchEx(int tag, const TCHAR *data)
|
|
{
|
|
if (!groups)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
if (!groupsEx || !data)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Groups *rbData = SearchDataByTag(tag);
|
|
if (!rbData || rbData->code != XD_STR || !rbData->string)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return !_tcscmp(rbData->string, data);
|
|
}
|
|
|
|
int Entity::MatchEx(int tag, ads_real data)
|
|
{
|
|
if (!groups)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
if (!groupsEx)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Groups *rbData = SearchDataByTag(tag);
|
|
if (!rbData || rbData->code != XD_REAL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return rbData->real == data;
|
|
}
|
|
|
|
|
|
int Entity::MatchEx(const Groups *tag, const Groups *data)
|
|
{
|
|
if (!tag || tag->code != XD_SHORT)
|
|
{
|
|
return 0;
|
|
}
|
|
return MatchEx(tag->shortInt, data);
|
|
}
|
|
|
|
int Entity::MatchBase(const Groups &rb)
|
|
{
|
|
if (rb.code == 1001)
|
|
{
|
|
OPENOBJ_BEGIN(*this, AcDb::kForRead, AcDbEntity, pEnt);
|
|
if (pEnt)
|
|
{
|
|
resbuf *xData = pEnt->xData(rb.string);
|
|
if (xData)
|
|
{
|
|
ads_relrb(xData);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
OPENOBJ_END();
|
|
}
|
|
if (!groups)
|
|
{
|
|
GetGroups(0);
|
|
}
|
|
|
|
Groups *pg = SearchNode(rb.code);
|
|
if (!pg)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (TypeOfCode(rb.code) == RTSTR)
|
|
{
|
|
XString s1, s2;
|
|
s1 = pg->string;
|
|
s2 = rb.string;
|
|
_tcsupr(s1);
|
|
_tcsupr(s2);
|
|
return (ads_wcmatch(s1, s2) == RTNORM);
|
|
}
|
|
return *pg == rb;
|
|
}
|
|
|
|
int Entity::SetData(int code,...)
|
|
{
|
|
if (!groups) _GetGroups();
|
|
#ifdef _WIN64
|
|
va_list args;
|
|
va_start(args, code);
|
|
int rc = _SetData(code, args);
|
|
va_end(args);
|
|
return rc;
|
|
#else
|
|
void *buf=(char *)&code+sizeof(int);
|
|
return _SetData(code,buf);
|
|
#endif
|
|
/*if (!groups)
|
|
{
|
|
_GetGroups();
|
|
}
|
|
|
|
void *buf = (TCHAR *)&code + sizeof(int);
|
|
return _SetData(code,buf);*/
|
|
}
|
|
|
|
// 两个Resubf 节点成对的Match方可以
|
|
int Entity::Match(const RBList &exlist)
|
|
{
|
|
if (!groups)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
Groups *exList = exlist.groups;
|
|
if (!groupsEx || !exList || !exList->next)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Groups *rb1 = exList, *rb2 = exList->next;
|
|
while(MatchEx(rb1, rb2))
|
|
{
|
|
rb1 = rb2->next;
|
|
if (!rb1)
|
|
{
|
|
return 1;
|
|
}
|
|
rb2 = rb1->next;
|
|
if (!rb2)
|
|
{
|
|
ads_fail(_T("\nBad Extend data list!"));
|
|
return 0;
|
|
}
|
|
if (ads_usrbrk())
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Entity::_GetGroups()
|
|
{
|
|
if (groups)
|
|
{
|
|
Release(groups);
|
|
groups = groupsEx = NULL;
|
|
}
|
|
// else groupsEx set to NULL ??
|
|
groups = (PGroups)ads_entget(name);
|
|
return (groups ? RTNORM : RTERROR);
|
|
}
|
|
|
|
int Entity::FilterSelect(const TCHAR *prompt, const RBList &mask)
|
|
{
|
|
const TCHAR *szPrompts[2] = { prompt, _T("") };
|
|
PickSet ss(SS_FREE);
|
|
int nRet = ss.Get(_T(":S:$"), szPrompts, NULL, mask);
|
|
|
|
if (nRet == RTNORM)
|
|
{
|
|
long lCount = ss.Length();
|
|
if (lCount == 1)
|
|
{
|
|
*this = ss[0L];
|
|
}
|
|
else
|
|
{
|
|
for (long i = 0; i < lCount; i++)
|
|
{
|
|
Entity ent = ss[i];
|
|
ent.Redraw(3);
|
|
|
|
int rc = YesNoQuestion(sMsgPrompt[4], Q_YES);
|
|
ent.Redraw(4);
|
|
if (rc == RTCAN)
|
|
{
|
|
return rc;
|
|
}
|
|
else if (rc == Q_YES)
|
|
{
|
|
*this = ent;
|
|
return RTNORM;
|
|
}
|
|
}
|
|
|
|
return RTNONE;
|
|
}
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
int Entity::FilterSelect(const TCHAR *prompt, const RBList &mask, ads_point res)
|
|
{
|
|
do
|
|
{
|
|
Entity ent;
|
|
int rc = res ? ent.UserSelect(prompt, res) : ent.UserSelect(prompt);
|
|
if (rc != RTNORM)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
if (ent.MatchBase(mask))
|
|
{
|
|
*this = ent;
|
|
return RTNORM;
|
|
}
|
|
|
|
XGeLib::adsout << sMsgPrompt[0];
|
|
} while(1);
|
|
}
|
|
|
|
int Entity::FilterSelect1(ads_real distPrec, const TCHAR *prompt, const RBList &mask, ads_point res)
|
|
{
|
|
XPushVar<int> osmode(_T("OSMODE"), 512);
|
|
do
|
|
{
|
|
XPoint pickPt;
|
|
int rc = ads_getpoint(NULL, prompt, pickPt);
|
|
if (rc != RTNORM)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
XPoint lowCorner = pickPt - XPoint(distPrec, distPrec);
|
|
XPoint upCorner = pickPt + XPoint(distPrec, distPrec);
|
|
|
|
PickSet ss(SS_FREE);
|
|
if (ss.Get(_T("C"), &lowCorner, upCorner, mask) != RTNORM)
|
|
{
|
|
XGeLib::adsout << sMsgPrompt[0];
|
|
continue;
|
|
}
|
|
|
|
if (ss.Length() == 1)
|
|
{
|
|
*this = ss[0L];
|
|
if (res)
|
|
{
|
|
pickPt > res;
|
|
}
|
|
|
|
return RTNORM;
|
|
}
|
|
|
|
long len = ss.Length();
|
|
for (long i = 0; i < len; i++)
|
|
{
|
|
Entity ent = ss[i];
|
|
ent.Redraw(3);
|
|
rc = YesNoQuestion(sMsgPrompt[4]);
|
|
ent.Redraw(4);
|
|
|
|
if (rc == RTCAN)
|
|
{
|
|
return rc;
|
|
}
|
|
else if (rc == Q_YES)
|
|
{
|
|
*this = ent;
|
|
if (res)
|
|
{
|
|
pickPt > res;
|
|
}
|
|
|
|
return RTNORM;
|
|
}
|
|
}
|
|
|
|
XGeLib::adsout << sMsgPrompt[1];
|
|
} while(1);
|
|
}
|
|
|
|
int Entity::RedrawAll(int mode) const
|
|
{
|
|
int nTileMode = 0;
|
|
xg_getvar(_T("TILEMODE"), &nTileMode);
|
|
|
|
resbuf * rbViewports = NULL;
|
|
VERIFY(ads_vports(&rbViewports) == RTNORM && rbViewports);
|
|
int nCurVp = rbViewports->rbnext->resval.rint;
|
|
|
|
resbuf *rbNext = rbViewports->rbnext->rbnext->rbnext->rbnext->rbnext;
|
|
while(rbNext && !(nTileMode == 0 && nCurVp == 1))
|
|
{
|
|
ASSERT(rbNext->restype == RTLB && rbNext->rbnext->restype == RTSHORT);
|
|
if (xg_setvar(_T("CVPORT"), rbNext->rbnext->resval.rint) == RTNORM)
|
|
{
|
|
Redraw(mode);
|
|
}
|
|
|
|
rbNext = rbNext->rbnext->rbnext->rbnext->rbnext->rbnext;
|
|
}
|
|
ads_relrb(rbViewports);
|
|
|
|
xg_setvar(_T("CVPORT"), nCurVp);
|
|
int nRet = Redraw(mode);
|
|
return nRet;
|
|
}
|
|
|
|
int Entity::Move(const XPoint & basept, XPoint & res) const
|
|
{
|
|
if (!name[0] && !name[1])
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
DragPickEntSet picks(basept);
|
|
picks += *this;
|
|
return picks.Move(basept, res);
|
|
}
|
|
|
|
int Entity::Rotate(const XPoint & basept, ads_real *res) const
|
|
{
|
|
if (!name[0] && !name[1])
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
DragPickEntSet picks(basept);
|
|
picks += *this;
|
|
return picks.Rotate(basept, res);
|
|
}
|
|
|
|
int Entity::Scale(const XPoint & basept, ads_real *res) const
|
|
{
|
|
if (!name[0] && !name[1])
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
DragPickEntSet picks(basept);
|
|
picks += *this;
|
|
return picks.Scale(basept, res);
|
|
}
|
|
|
|
int Entity::AssignAppName(const TCHAR *s)
|
|
{
|
|
if (s && s[0])
|
|
{
|
|
ApplicationName = s;
|
|
XSymbolTable appId(_T("APPID"), ApplicationName);
|
|
if (!appId)
|
|
{
|
|
return ads_regapp(ApplicationName);
|
|
}
|
|
return RTNORM;
|
|
}
|
|
ApplicationError(_T("Bad Application Name\n"));
|
|
return RTERROR;
|
|
}
|
|
|
|
// 创建扩充实体数据
|
|
void Entity::_MakeExGroups()
|
|
{
|
|
if (groups)
|
|
{
|
|
groupsEx = groups;
|
|
while (groupsEx->next && (groupsEx->code != -3))
|
|
{
|
|
groupsEx = groupsEx->next;
|
|
}
|
|
if (groupsEx->next)
|
|
{ // I got it; code = -3
|
|
groupsEx = groupsEx->next;
|
|
}
|
|
else
|
|
{ // make a -3 head
|
|
groupsEx->next = (PGroups)ads_buildlist(-3,1001,ApplicationName,0);
|
|
if (!groupsEx->next)
|
|
{
|
|
ApplicationError(_T("Error in Ex::GetGroups\n"));
|
|
return;
|
|
}
|
|
groupsEx = (groupsEx->next)->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
int Entity::GetGroups(int getEx)
|
|
{
|
|
if (groups)
|
|
{
|
|
Release(groups);
|
|
groups = groupsEx = 0;
|
|
}
|
|
if (getEx && ApplicationName)
|
|
{
|
|
PGroups agroup = (PGroups)ads_newrb(RTSTR);
|
|
if (!agroup)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
agroup->string = _tcsdup(ApplicationName);
|
|
groups = (PGroups)ads_entgetx(name,(struct resbuf*)agroup);
|
|
ads_relrb((resbuf *)agroup);
|
|
if (!groups)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
else
|
|
{
|
|
_MakeExGroups();
|
|
}
|
|
return RTNORM;
|
|
}
|
|
return _GetGroups();
|
|
}
|
|
|
|
int Entity::GetGroups(const TCHAR *appname)
|
|
{
|
|
const TCHAR *oldApp = ApplicationName;
|
|
ApplicationName = appname;
|
|
int rc = GetGroups();
|
|
ApplicationName = oldApp;
|
|
if (!groupsEx)
|
|
{
|
|
rc = RTERROR;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
PGroups Entity::SearchByTagCode(int tagCode)
|
|
{
|
|
PGroups group;
|
|
group = groupsEx;
|
|
while (group)
|
|
{
|
|
if (group->code == 1070 && group->shortInt == tagCode)
|
|
{
|
|
return group;
|
|
}
|
|
group = group->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int Entity::RemoveXData()
|
|
{
|
|
GetGroups(0);
|
|
_MakeExGroups();
|
|
Modify();
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::Erase() const
|
|
{
|
|
XDbObject dbObj(name, AcDb::kForWrite);
|
|
if (!dbObj)
|
|
{
|
|
;
|
|
}
|
|
else
|
|
{
|
|
AcDbEntity &dbEnt = dbObj;
|
|
if (dbEnt.erase() == Acad::eOk)
|
|
{
|
|
return RTNORM;
|
|
}
|
|
}
|
|
return RTERROR;
|
|
}
|
|
|
|
int Entity::DeleteTag(int tagCode)
|
|
{
|
|
PGroups g = groupsEx,g1,g2,g3;
|
|
if (!g)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
g1 = g;
|
|
while (g)
|
|
{
|
|
if (g->code == 1070 && g->shortInt == tagCode)
|
|
{
|
|
break;
|
|
}
|
|
g1 = g;
|
|
g = g->next;
|
|
}
|
|
|
|
if (!g)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
g2 = g->next;
|
|
if (!g2)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
if (g2->code == 1002 && g2->string[0] == _T('{'))
|
|
{
|
|
while (g2)
|
|
{
|
|
if (g2->code == 1002 && g2->string[0] == _T('}'))
|
|
{
|
|
break;
|
|
}
|
|
g2 = g2->next;
|
|
}
|
|
if (!g2)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
}
|
|
g3 = g2->next;
|
|
g2->next = 0;
|
|
g1->next = g3;
|
|
Release(g);
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::CreateTag(void *buf,int tagCode,int type)
|
|
{
|
|
PGroups list = groupsEx;
|
|
if (!list)
|
|
{
|
|
ApplicationError(_T("Error in ::CreateTag"));
|
|
return RTERROR;
|
|
}
|
|
|
|
while (list->next)
|
|
{
|
|
list = list->next;
|
|
}
|
|
list->next = (PGroups)ads_newrb(1070);
|
|
if (!list->next)
|
|
{
|
|
ApplicationError(_T("Error in ::CreateTag"));
|
|
return RTERROR;
|
|
}
|
|
list = list->next;
|
|
list->shortInt = tagCode;
|
|
list->next = (PGroups)ads_newrb(0);
|
|
if (!list->next)
|
|
{
|
|
ApplicationError(_T("Error in ::CreateTag"));
|
|
return RTERROR;
|
|
}
|
|
list = list->next;
|
|
list->next = NULL;
|
|
if (type == RTSTR)
|
|
{
|
|
list->code = XD_STR;
|
|
list->string = _tcsdup(*(TCHAR **)buf);
|
|
}
|
|
else if (type == RTREAL)
|
|
{ // real
|
|
list->code = XD_REAL;
|
|
list->real = *((ads_real *)buf);
|
|
}
|
|
else
|
|
{ // int
|
|
list->code = XD_SHORT;
|
|
list->shortInt = *((short *)buf);
|
|
}
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::SetExData(int tagCode,...)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
int type = TypeOfCode(tagCode);
|
|
|
|
void *buf = (int *)&tagCode + 1;
|
|
if (type != RTSTR && type != RTREAL && type != RTSHORT)
|
|
{
|
|
ApplicationError(_T("This tag code %d is not support by the::SetExdata.\n"),tagCode);
|
|
return RTERROR;
|
|
}
|
|
PGroups group = SearchByTagCode(tagCode);
|
|
if (!group)
|
|
{ // add on the whole thing
|
|
CreateTag(buf,tagCode,type);
|
|
}
|
|
else
|
|
{ // replace it
|
|
PGroups list = group->next;
|
|
int t1 = TypeOfCode(list->code);
|
|
if (t1 != type)
|
|
{
|
|
ApplicationError(_T("Tag Code type does not match the group code type.::SetExData\n"));
|
|
return RTERROR;
|
|
}
|
|
if (type == RTSTR)
|
|
{
|
|
free(list->string);
|
|
list->string = _tcsdup(*(TCHAR **)buf);
|
|
}
|
|
else if (type == RTREAL)
|
|
{ // real
|
|
list->real = *((ads_real *)buf);
|
|
}
|
|
else
|
|
{ //int
|
|
list->shortInt = *((short *)buf);
|
|
}
|
|
}
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::GetExData(int tagCode,void *buf)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
int type = TypeOfCode(tagCode);
|
|
if (type != RTSTR && type != RTREAL && type != RTSHORT)
|
|
{
|
|
ApplicationError(_T("This tag code %d is not support by the::GetExdata.\n"),tagCode);
|
|
return RTERROR;
|
|
}
|
|
PGroups group = SearchByTagCode(tagCode);
|
|
if (group)
|
|
{ // replace it
|
|
PGroups list = group->next;
|
|
int t1 = TypeOfCode(list->code);
|
|
if (t1 != type)
|
|
{
|
|
ApplicationError(_T("Tag Code type does not match the group code type.::SetExData\n"));
|
|
return RTERROR;
|
|
}
|
|
if (type == RTSTR)
|
|
{
|
|
_tcscpy((TCHAR *)buf,list->string);
|
|
}
|
|
else if (type == RTREAL)
|
|
{ // real
|
|
*((ads_real *)buf) = list->real;
|
|
}
|
|
else
|
|
{ //int
|
|
*((short *)buf) = list->shortInt;
|
|
}
|
|
return RTNORM;
|
|
}
|
|
return RTERROR;
|
|
}
|
|
|
|
// Get 系列都没有检查类型的匹配 ------------------------------------!!!
|
|
int Entity::GetInt(int tag_code,int &buf)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
Groups *list;
|
|
if ((list = (PGroups)XPrivate::get_xdata_tag_item((resbuf *)groupsEx, tag_code, NULL)) == NULL)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
list = list->next;
|
|
buf = list->shortInt;
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::GetReal(int tag_code,ads_real &buf)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
Groups *list;
|
|
if ((list = (PGroups)XPrivate::get_xdata_tag_item((resbuf *)groupsEx, tag_code, NULL)) == NULL)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
list = list->next;
|
|
buf = list->real;
|
|
return RTNORM;
|
|
}
|
|
|
|
// don't free buf
|
|
int Entity::GetRBinary(int tag_code, short &nBufLen, const char * &buf)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
Groups *list;
|
|
if ((list = (PGroups)XPrivate::get_xdata_tag_item((resbuf *)groupsEx, tag_code, NULL)) == NULL)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
list = list->next;
|
|
nBufLen = list->binary.length;
|
|
buf = list->binary.buffer;
|
|
return RTNORM;
|
|
}
|
|
|
|
// NOTE:
|
|
// This function return a pointer equal to string pointer in the resbuf
|
|
// When the Groups released,referrence to that string would be a disaster.
|
|
int Entity::GetRString(int tag_code,TCHAR *&buf)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
Groups *list;
|
|
if ((list = (PGroups)XPrivate::get_xdata_tag_item((resbuf *)groupsEx, tag_code, NULL)) == NULL)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
list = list->next;
|
|
buf = list->string;
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::GetString(int tag_code,TCHAR *buf)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
TCHAR *temp;
|
|
int rt = GetRString(tag_code,temp);
|
|
if (rt == RTNORM)
|
|
{
|
|
_tcscpy(buf,temp);
|
|
}
|
|
return rt;
|
|
}
|
|
|
|
int Entity::GetPoint(int tag_code, XPoint &res)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
Groups *list;
|
|
if ((list = (PGroups)XPrivate::get_xdata_tag_item((resbuf *)groupsEx, tag_code, NULL)) == NULL)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
list = list->next;
|
|
res = list->point;
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::SetReal(int tag_code,ads_real val)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
PGroups tag_xdata = (PGroups)ads_newrb(XD_REAL);
|
|
tag_xdata->real = val;
|
|
XPrivate::set_xdata_tag_item((resbuf **)&groupsEx, tag_code, (resbuf*)tag_xdata, Entity::ApplicationName);
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::SetInt(int tag_code,int val)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
PGroups tag_xdata = (PGroups)ads_newrb(XD_INT);
|
|
tag_xdata->shortInt = val;
|
|
XPrivate::set_xdata_tag_item((resbuf **)&groupsEx, tag_code, (resbuf*)tag_xdata, Entity::ApplicationName);
|
|
return RTNORM;
|
|
}
|
|
|
|
|
|
int Entity::SetString(int tag_code, const TCHAR *val, int isHandle)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
int xdCode = isHandle ? XD_HANDLE : XD_STR;
|
|
PGroups tag_xdata = (PGroups)ads_newrb(xdCode);
|
|
tag_xdata->string = _tcsdup(val);
|
|
XPrivate::set_xdata_tag_item((resbuf **)&groupsEx, tag_code, (resbuf*)tag_xdata, Entity::ApplicationName);
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::SetPoint(int tag_code, const XPoint &pt)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
PGroups tag_xdata = (PGroups)ads_newrb(XD_POINT);
|
|
pt > tag_xdata->point;
|
|
XPrivate::set_xdata_tag_item((resbuf **)&groupsEx, tag_code, (resbuf*)tag_xdata, Entity::ApplicationName);
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::SetBinary(int tag_code, short nBufLen, const char *buf)
|
|
{
|
|
assert(nBufLen<128 && nBufLen>0);
|
|
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
PGroups tag_xdata = (PGroups)ads_newrb(1004);
|
|
tag_xdata->binary.length = nBufLen;
|
|
tag_xdata->binary.buffer = new char [nBufLen];
|
|
memcpy(tag_xdata->binary.buffer, buf, nBufLen);
|
|
XPrivate::set_xdata_tag_item((resbuf **)&groupsEx, tag_code, (resbuf*)tag_xdata, Entity::ApplicationName);
|
|
return RTNORM;
|
|
}
|
|
|
|
// API 2.0
|
|
int Entity::SetStruct(void *buf,int len, int tagCode)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
long *lp;
|
|
int v;
|
|
long ll;
|
|
TCHAR *p;
|
|
int base;
|
|
int i;
|
|
|
|
if (len <= 0)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
DeleteTag(tagCode);
|
|
|
|
PGroups l = groupsEx;
|
|
if (!l)
|
|
{
|
|
ApplicationError(_T("Error in ::SetStruct.\n"));
|
|
return RTERROR;
|
|
}
|
|
|
|
while (l->next)
|
|
{
|
|
l = l->next;
|
|
}
|
|
l->next = (PGroups)ads_newrb(1070);
|
|
if (!l->next)
|
|
{
|
|
ApplicationError(_T("Error in ::SetStruct.\n"));
|
|
return RTERROR;
|
|
}
|
|
|
|
l = l->next;
|
|
l->shortInt = tagCode;
|
|
|
|
l->next = (PGroups)ads_newrb(1002);
|
|
if (!l->next)
|
|
{
|
|
ApplicationError(_T("Error in ::SetStruct.\n"));
|
|
return RTERROR;
|
|
}
|
|
|
|
l = l->next;
|
|
l->string = _tcsdup(_T("{"));
|
|
|
|
l->next = (PGroups)ads_newrb(XD_INT);
|
|
if (!l->next)
|
|
{
|
|
ApplicationError(_T("Error in ::SetStruct.\n"));
|
|
return RTERROR;
|
|
}
|
|
|
|
l = l->next;
|
|
l->shortInt = len;
|
|
|
|
lp = (long *)buf;
|
|
for (i = 0; i < len / 4; i++)
|
|
{
|
|
l->next = (PGroups)ads_newrb(XD_LONG);
|
|
if (!l->next)
|
|
{
|
|
ApplicationError(_T("Error in ::SetStruct.\n"));
|
|
return RTERROR;
|
|
}
|
|
|
|
l = l->next;
|
|
l->longInt = lp[i];
|
|
}
|
|
|
|
v = len % 4;
|
|
if (v)
|
|
{ //v = 1,2,3
|
|
p = (TCHAR *)≪
|
|
base = len / 4 * 4;
|
|
for (i = 0; i < v; i++)
|
|
{
|
|
p[i] = ((TCHAR *)buf)[base + i];
|
|
}
|
|
l->next = (PGroups)ads_newrb(XD_LONG);
|
|
if (!l->next)
|
|
{
|
|
ApplicationError(_T("Error in ::SetStruct.\n"));
|
|
return RTERROR;
|
|
}
|
|
|
|
l = l->next;
|
|
l->longInt = ll;
|
|
}
|
|
|
|
l->next = (PGroups)ads_newrb(1002);
|
|
if (!l->next)
|
|
{
|
|
ApplicationError(_T("Error in ::SetStruct.\n"));
|
|
return RTERROR;
|
|
}
|
|
|
|
l = l->next;
|
|
l->string = _tcsdup(_T("}"));
|
|
l->next = 0;
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::GetStruct(void *buf,int len, int tagCode)
|
|
{
|
|
if (!groups || !groupsEx)
|
|
{
|
|
GetGroups();
|
|
}
|
|
|
|
PGroups l = SearchByTagCode(tagCode);
|
|
if (!l)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
l = l->next;
|
|
if (!l)
|
|
{
|
|
ApplicationError(_T("Error in ::GetStruct\n"));
|
|
return RTERROR;
|
|
}
|
|
if (l->code == 1002 && l->string[0] == _T('{'))
|
|
{
|
|
l = l->next;
|
|
if (!l)
|
|
{
|
|
ApplicationError(_T("Error in ::GetStruct\n"));
|
|
return RTERROR;
|
|
}
|
|
|
|
// get the len
|
|
int len1;
|
|
if (l->code != XD_INT)
|
|
{
|
|
ApplicationError(_T("Error in ::GetStruct\n"));
|
|
return RTERROR;
|
|
}
|
|
|
|
len1 = l->shortInt;
|
|
len = len < len1 ? len : len1;
|
|
l = l->next;
|
|
if (!l)
|
|
{
|
|
ApplicationError(_T("Error in ::GetStruct\n"));
|
|
return RTERROR;
|
|
}
|
|
|
|
long *lp = (long *)buf;
|
|
while (len && l->code == XD_LONG)
|
|
{
|
|
if (len >= 4)
|
|
{
|
|
*lp = l->longInt;
|
|
lp++;
|
|
len -= 4;
|
|
}
|
|
else
|
|
{
|
|
TCHAR *cp1 = (TCHAR *)lp;
|
|
TCHAR *cp2 = (TCHAR *)&l->longInt;
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
cp1[i] = cp2[i];
|
|
}
|
|
len = 0;
|
|
}
|
|
l = l->next;
|
|
if (!l)
|
|
{
|
|
ApplicationError(_T("Error in ::GetStruct\n"));
|
|
return RTERROR;
|
|
}
|
|
}
|
|
return RTNORM;
|
|
}
|
|
|
|
return RTERROR;
|
|
}
|
|
|
|
int Entity::Make()
|
|
{
|
|
if (!groups)
|
|
{
|
|
GetGroups(0);
|
|
}
|
|
|
|
if (groups)
|
|
{
|
|
return (ads_entmake((struct resbuf *)groups));
|
|
}
|
|
else
|
|
{
|
|
ApplicationError(_T("\nError in Entity::Make().\nZero groups.\n"));
|
|
return RTERROR;
|
|
}
|
|
}
|
|
|
|
int Entity::Make(int type,...)
|
|
{
|
|
if (groups)
|
|
{
|
|
Release(groups);
|
|
groups = groupsEx = NULL;
|
|
}
|
|
groups = VBuildList(&type);
|
|
if (!groups)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
if (ads_entmake((struct resbuf *)groups) != RTNORM || GetLast() != RTNORM)
|
|
{
|
|
ads_printf(_T("\nEntity::Make(...) Error!"));
|
|
return RTERROR;
|
|
}
|
|
|
|
return RTNORM;
|
|
}
|
|
|
|
int Entity::MakeEx(int type,...)
|
|
{
|
|
if (groups)
|
|
{
|
|
Release(groups);
|
|
groups = groupsEx = NULL;
|
|
}
|
|
groups = VBuildList(&type);
|
|
if (!groups) return RTERROR;
|
|
if (ads_entmake((struct resbuf *)groups) == RTERROR || GetLast() != RTNORM)
|
|
{
|
|
ads_printf(_T("\nEntity::Make(...) Error!"));
|
|
return RTERROR;
|
|
}
|
|
_MakeExGroups();
|
|
return RTNORM;
|
|
}
|
|
|
|
|
|
// 求模型的边界(忽略图纸实体: POINT, TEXT, ATTRIB, ATTDEF, DIMENSION)
|
|
// tranMat -- 当前实体为图块中的子实体时,需左乘的变换矩阵
|
|
// Status: When it's POLYLINE, the result still not verified
|
|
// return: RTNORM--确切求得边界; RTERROR--不能确切求得边界; RTNONE--模型边界不可求
|
|
int Entity::GetExtend(ads_point lowPt, ads_point upPt, ads_matrix tranMat)
|
|
{
|
|
if (!tranMat)
|
|
{
|
|
AcDbExtents geomExt;
|
|
XDbObject obj(name, AcDb::kForRead);
|
|
if (!obj)
|
|
{
|
|
return RTNONE;
|
|
}
|
|
AcDbEntity &objEnt = obj;
|
|
Acad::ErrorStatus es = objEnt.getGeomExtents(geomExt);
|
|
if (es == Acad::eOk)
|
|
{
|
|
XPoint ptLow = geomExt.minPoint();
|
|
XPoint ptUp = geomExt.maxPoint();
|
|
ptLow > lowPt;
|
|
ptUp > upPt;
|
|
return RTNORM;
|
|
}
|
|
}
|
|
|
|
if (!(*this))
|
|
{
|
|
return RTNONE;
|
|
}
|
|
XString eType;
|
|
if (GetData(0, eType) != RTNORM)
|
|
{
|
|
return RTNONE;
|
|
}
|
|
|
|
XPoint extrusion(0, 0, 1);
|
|
ads_real thickness = 0;
|
|
GetData(210, extrusion);
|
|
if (!(extrusion == Point(0,0,1)))
|
|
{
|
|
return RTNONE;
|
|
}
|
|
GetData(39, &thickness);
|
|
if (eType == _T("LINE"))
|
|
{
|
|
XLine aLine(*this, LS_FINITE, tranMat);
|
|
*(XPoint *)lowPt = Min(aLine.StartPoint(), aLine.EndPoint());
|
|
*(XPoint *)upPt = Max(aLine.StartPoint(), aLine.EndPoint());
|
|
upPt[Z] += thickness;
|
|
if (fabs(thickness) > 1E-6 && tranMat)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
}
|
|
else if (eType == _T("3DFACE"))
|
|
{
|
|
X3DFace face(*this, tranMat);
|
|
return face.GetExtend(lowPt, upPt);
|
|
}
|
|
else if (eType == _T("ATTDEF") || eType == _T("ATTRIB") || eType == _T("TEXT") || eType == _T("DIMENSION"))
|
|
{
|
|
return RTNONE;
|
|
}
|
|
else if (eType == _T("ARC"))
|
|
{
|
|
XArc arc(*this, tranMat);
|
|
arc.GetExtend(lowPt, upPt);
|
|
upPt[Z] += thickness;
|
|
if (fabs(thickness) > 1E-6 && tranMat)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
}
|
|
else if (eType == _T("CIRCLE"))
|
|
{
|
|
XCircle cir(*this, tranMat);
|
|
cir.GetExtend(lowPt, upPt);
|
|
upPt[Z] += thickness;
|
|
if (fabs(thickness) > 1E-6 && tranMat)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
}
|
|
else if (eType == _T("INSERT"))
|
|
{
|
|
ads_matrix mat, mat1;
|
|
if (GetInsertMatrix(*this, mat) != RTNORM)
|
|
{
|
|
return RTNONE;
|
|
}
|
|
|
|
TCHAR blk[80]=_T("");
|
|
GetData(2, blk);
|
|
|
|
XBlockTable blkTab(blk);
|
|
if (tranMat)
|
|
{
|
|
AT_multiply_matrix(tranMat, mat, mat1);
|
|
}
|
|
else
|
|
{
|
|
memcpy(mat1, mat, sizeof(ads_matrix));
|
|
}
|
|
|
|
return blkTab.GetExtend(lowPt, upPt, mat1);
|
|
}
|
|
else if (eType == _T("POINT"))
|
|
{
|
|
return RTNONE;
|
|
}
|
|
else if (eType == _T("POLYLINE"))
|
|
{ // 不包含弧段时可求
|
|
int polyFlag;
|
|
GetData(70, &polyFlag);
|
|
if (polyFlag <= 1 && !tranMat)
|
|
{ // do not take ECS-Vertex into account
|
|
XPoly2D poly(*this);
|
|
poly.GetExtend(lowPt, upPt);
|
|
upPt[Z] += thickness;
|
|
return RTNORM;
|
|
}
|
|
|
|
Entity subEnt, nextEnt;
|
|
ads_entnext(*this, nextEnt);
|
|
XPoint ptm, ptn;
|
|
int rt = RTNORM;
|
|
int index = 0;
|
|
do
|
|
{
|
|
nextEnt.GetGroups(0);
|
|
if (!nextEnt.Is(_T("VERTEX")))
|
|
{
|
|
break;
|
|
}
|
|
|
|
int flg = 0;
|
|
ads_real bulge = 0;
|
|
nextEnt.GetData(70, &flg);
|
|
if ((flg&128) && !(flg&64))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (nextEnt.GetData(42, &bulge) == RTNORM && fabs(bulge)>0.0001)
|
|
{
|
|
rt = RTERROR;
|
|
}
|
|
|
|
XPoint vertex;
|
|
nextEnt.GetData(10, vertex);
|
|
|
|
{
|
|
XPoint vtPt = vertex;
|
|
if (tranMat)
|
|
{
|
|
AT_xformpt(tranMat, vtPt, vertex);
|
|
}
|
|
else
|
|
{
|
|
vertex = vtPt;
|
|
}
|
|
}
|
|
|
|
if (!index)
|
|
{
|
|
ptm = ptn = vertex;
|
|
}
|
|
else
|
|
{
|
|
ptm = Max(ptm, vertex); ptn = Min(ptn, vertex);
|
|
}
|
|
subEnt = nextEnt;
|
|
index ++;
|
|
} while(ads_entnext(subEnt, nextEnt) == RTNORM);
|
|
|
|
ptm.z += thickness;
|
|
ptm > upPt; ptn > lowPt;
|
|
return rt;
|
|
}
|
|
else if (eType == _T("SOLID") || eType == _T("TRACE"))
|
|
{
|
|
X3DFace notFace;
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
XPoint vertex;
|
|
GetData(10+i, vertex);
|
|
if (tranMat)
|
|
{
|
|
XPoint ptNew;
|
|
AT_xformpt(tranMat, vertex, ptNew);
|
|
notFace.SetVertex(i,ptNew);
|
|
}
|
|
else
|
|
{
|
|
notFace.SetVertex(i, vertex);
|
|
}
|
|
}
|
|
return notFace.GetExtend(lowPt, upPt);
|
|
}
|
|
else
|
|
{
|
|
return RTNONE;
|
|
}
|
|
return RTNORM;
|
|
}
|
|
|
|
// 实体变换: 允许不等比缩放
|
|
int Entity::XTransform(ads_matrix mat)
|
|
{
|
|
XString eType;
|
|
ads_real thickness;
|
|
XPoint extrusion;
|
|
if (!(*this) || GetData(0, eType) != RTNORM)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
if (eType == _T("LWPOLYLINE"))
|
|
{
|
|
XDbObject obj(name, AcDb::kForWrite);
|
|
if (!!obj)
|
|
{
|
|
AcDbPolyline *pline = AcDbPolyline::cast(obj.m_pObject);
|
|
if (pline)
|
|
{
|
|
//只对顶点进行变换, 不考虑弧度的变化
|
|
int nVerts = pline->numVerts();
|
|
for (int i = 0; i < nVerts; i++)
|
|
{
|
|
AcGePoint2d pt;
|
|
if (pline->getPointAt(i, pt) == Acad::eOk)
|
|
{
|
|
XPoint pt1 = pt;
|
|
XPoint pt2;
|
|
AT_xformpt(mat, pt1, pt2);
|
|
pline->setPointAt(i, pt2);
|
|
}
|
|
}
|
|
return RTNORM;
|
|
}
|
|
}
|
|
return RTERROR;
|
|
}
|
|
|
|
if (GetData(39, &thickness) == RTNORM || (GetData(210, extrusion) == RTNORM && !(extrusion == XPoint(0,0,1))))
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
if (eType == _T("LINE"))
|
|
{
|
|
XLine aLine(*this, LS_FINITE, mat);
|
|
return aLine.Modify(this);
|
|
}
|
|
else if (eType == _T("3DFACE"))
|
|
{
|
|
X3DFace face(*this, mat);
|
|
return face.Modify(*this);
|
|
}
|
|
else if (eType == _T("POINT"))
|
|
{
|
|
XPoint pt, npt;
|
|
GetData(10, &pt.x);
|
|
AT_xformpt(mat, pt, npt);
|
|
SetData(10, &npt.x);
|
|
return Modify();
|
|
}
|
|
else if (eType == _T("SOLID") || eType == _T("TRACE"))
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
XPoint vertex, nVertex;
|
|
GetData(10 + i, (ads_real *)vertex);
|
|
AT_xformpt(mat, vertex, nVertex);
|
|
SetData(10 + i, (ads_real *)nVertex);
|
|
}
|
|
return Modify();
|
|
}
|
|
else if (eType == _T("POLYLINE"))
|
|
{
|
|
Entity subEnt, nextEnt;
|
|
XPoint base, nBase;
|
|
ads_entnext(*this, nextEnt);
|
|
GetData(10, base);
|
|
AT_xformpt(mat, base, nBase);
|
|
XPoint ptm, ptn;
|
|
int rt = RTNORM;
|
|
do
|
|
{
|
|
nextEnt.GetGroups(0);
|
|
if (!nextEnt.Is(_T("VERTEX"))) break;
|
|
int flg = 0;
|
|
ads_real bulge = 0;
|
|
nextEnt.GetData(70, &flg);
|
|
if ((flg&128) && !(flg&64))
|
|
{
|
|
break;
|
|
}
|
|
if (nextEnt.GetData(42, &bulge) == RTNORM && fabs(bulge) > 0.0001)
|
|
{
|
|
rt = RTERROR;
|
|
}
|
|
XPoint vertex, nVertex;
|
|
nextEnt.GetData(10, vertex);
|
|
AT_xformpt(mat, vertex, nVertex);
|
|
nextEnt.SetData(10, &nVertex.x);
|
|
nextEnt.Modify();
|
|
subEnt = nextEnt;
|
|
} while(ads_entnext(subEnt, nextEnt) == RTNORM);
|
|
|
|
SetData(10, &nBase);
|
|
Modify();
|
|
return rt;
|
|
}
|
|
else if (eType == _T("ARC"))
|
|
{
|
|
XArc ar(*this);
|
|
XPoint ptStart, ptEnd, ptMid;
|
|
ar.GetStartPoint(ptStart);
|
|
ar.GetEndPoint(ptEnd);
|
|
ar.MidPoint(ptMid);
|
|
|
|
XPoint ptNewStart, ptNewEnd, ptNewMid;
|
|
AT_xformpt(mat, ptStart, ptNewStart);
|
|
AT_xformpt(mat, ptEnd, ptNewEnd);
|
|
AT_xformpt(mat, ptMid, ptNewMid);
|
|
|
|
XArc arNew(ptNewStart, ptNewMid, ptNewEnd);
|
|
arNew.Modify(this);
|
|
|
|
return RTERROR;
|
|
}
|
|
|
|
XGeLib::adsout << sMsgPrompt[2] << eType;
|
|
return RTERROR;
|
|
}
|
|
|
|
// 求实体的范围
|
|
int Entity::GetExtend(ads_point cen, ads_real *x, ads_real *y, ads_real *z)
|
|
{
|
|
XPoint lowPt, upPt;
|
|
int rc = GetExtend(lowPt, upPt);
|
|
if (rc == RTNONE)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
XPoint extSize = upPt-lowPt;
|
|
if (cen)
|
|
{
|
|
Midpoint(lowPt, upPt, cen);
|
|
}
|
|
|
|
if (x)
|
|
{
|
|
*x = extSize.x;
|
|
}
|
|
|
|
if (y)
|
|
{
|
|
*y = extSize.y;
|
|
}
|
|
|
|
if (z)
|
|
{
|
|
*z = extSize.z;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
int Entity::MatchBase(const RBList &baseList)
|
|
{
|
|
for (Groups *rb = baseList.groups; rb != NULL; rb = rb->next)
|
|
{
|
|
if (!MatchBase(*rb))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int Entity::In(const PickSet *pSelectionSet)
|
|
{
|
|
ASSERT(pSelectionSet != NULL);
|
|
|
|
ads_name entT;
|
|
Adesk::Int32 lLen = 0L;
|
|
acedSSLength(pSelectionSet->name,&lLen);
|
|
for (long j = 0;j < lLen;j++)
|
|
{
|
|
acedSSName(pSelectionSet->name,j,entT);
|
|
|
|
if (entT[0] == name[0] &&
|
|
entT[1] == name[1])
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
// return (ads_ssmemb(name,pSelectionSet->name) == RTNORM ? TRACE:FALSE);
|
|
}
|