|
|
|
/*==LICENSE==*
|
|
|
|
|
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools
|
|
|
|
Copyright (C) 2011 Cyan Worlds, Inc.
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
Additional permissions under GNU GPL version 3 section 7
|
|
|
|
|
|
|
|
If you modify this Program, or any covered work, by linking or
|
|
|
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
|
|
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
|
|
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
|
|
|
(or a modified version of those libraries),
|
|
|
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
|
|
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
|
|
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
|
|
|
licensors of this Program grant you additional
|
|
|
|
permission to convey the resulting work. Corresponding Source for a
|
|
|
|
non-source form of such a combination shall include the source code for
|
|
|
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
|
|
|
work.
|
|
|
|
|
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
|
|
|
or by snail mail at:
|
|
|
|
Cyan Worlds, Inc.
|
|
|
|
14617 N Newport Hwy
|
|
|
|
Mead, WA 99021
|
|
|
|
|
|
|
|
*==LICENSE==*/
|
|
|
|
// UserPropMgr.cpp
|
|
|
|
|
|
|
|
#include "HeadSpin.h"
|
|
|
|
#include "UserPropMgr.h"
|
|
|
|
#include "hsStringTokenizer.h"
|
|
|
|
|
|
|
|
#include "hsHashTable.h"
|
|
|
|
|
|
|
|
#define REFMSG_USERPROP (REFMSG_USER + 1)
|
|
|
|
|
|
|
|
const uint32_t UserPropMgr::kQuickSize = 150001;//199999;
|
|
|
|
|
|
|
|
UserPropMgr gUserPropMgr(GetCOREInterface());
|
|
|
|
|
|
|
|
UserPropMgr::UserPropMgr(Interface *ip) :
|
|
|
|
nm(0)
|
|
|
|
{
|
|
|
|
this->ip = ip;
|
|
|
|
|
|
|
|
fQuickTable = nil;
|
|
|
|
fQuickNode = nil;
|
|
|
|
|
|
|
|
vProps = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
UserPropMgr::~UserPropMgr()
|
|
|
|
{
|
|
|
|
CloseQuickTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPropMgr::SetUserPropFlag(INode *node, const char *name, const BOOL setFlag, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
if (setFlag) SetUserProp(node,name,NULL,hFlag);
|
|
|
|
else ClearUserProp(node,name,hFlag);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPropMgr::ClearUserPropALL(const char *name, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
for (int i=0; i<GetSelNodeCount(); i++)
|
|
|
|
{
|
|
|
|
ClearUserProp(GetSelNode(i),name,hFlag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPropMgr::SelectUserPropFlagALL(INode *node, const char *name, const BOOL flag) {
|
|
|
|
if (node)
|
|
|
|
{
|
|
|
|
if (UserPropExists(node,name) == flag) ip->SelectNode(node,false);
|
|
|
|
} else node = ip->GetRootNode();
|
|
|
|
|
|
|
|
for (int i=0; i<node->NumberOfChildren(); i++) {
|
|
|
|
SelectUserPropFlagALL(node->GetChildNode(i),name,flag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UserPropMgr::DeSelectWithOut(const char *name, const char *value) {
|
|
|
|
BOOL oldProps = vProps;
|
|
|
|
vProps=false;
|
|
|
|
TSTR val;
|
|
|
|
INode *nodes[1];
|
|
|
|
INodeTab nodeTab;
|
|
|
|
for (int i=0; i<GetSelNodeCount(); i++) {
|
|
|
|
if (value) {
|
|
|
|
if (!(GetUserProp(GetSelNode(i),name,val) && !stricmp(val,value))) {
|
|
|
|
nodes[0] = GetSelNode(i);
|
|
|
|
nodeTab.Append(1,nodes);
|
|
|
|
}
|
|
|
|
} else if (!UserPropExists(GetSelNode(i),name)) {
|
|
|
|
nodes[0] = GetSelNode(i);
|
|
|
|
nodeTab.Append(1,nodes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vProps=oldProps;
|
|
|
|
if (nodeTab.Count() > 0) ip->SelectNodeTab(nodeTab,false,false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPropMgr::RecursiveSelectAll(INode *node) {
|
|
|
|
if (node) {
|
|
|
|
if (!node->Selected()) ip->SelectNode(node,false);
|
|
|
|
} else node = ip->GetRootNode();
|
|
|
|
|
|
|
|
for (int i=0; i<node->NumberOfChildren(); i++) {
|
|
|
|
RecursiveSelectAll(node->GetChildNode(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UserPropMgr::DeSelectUnAlike(INode *node) {
|
|
|
|
theHold.Begin();
|
|
|
|
|
|
|
|
ip->ThawSelection();
|
|
|
|
|
|
|
|
RecursiveSelectAll();
|
|
|
|
|
|
|
|
TSTR buf;
|
|
|
|
GetUserPropBuffer(node,buf);
|
|
|
|
|
|
|
|
hsStringTokenizer toker(buf," \r\n");
|
|
|
|
toker.ParseQuotes(TRUE);
|
|
|
|
char *tok;
|
|
|
|
TSTR name;
|
|
|
|
bool isName = true;
|
|
|
|
while (tok=toker.next()) {
|
|
|
|
if (isName) {
|
|
|
|
if (*tok != '=') {
|
|
|
|
name = tok;
|
|
|
|
tok = toker.next();
|
|
|
|
if (tok && *tok == '=') {
|
|
|
|
tok = toker.next();
|
|
|
|
} else tok = NULL;
|
|
|
|
DeSelectWithOut(name,tok);
|
|
|
|
} else isName = false;
|
|
|
|
} else {
|
|
|
|
isName = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TSTR undostr; undostr.printf("Select");
|
|
|
|
theHold.Accept(undostr);
|
|
|
|
|
|
|
|
ip->FreezeSelection();
|
|
|
|
|
|
|
|
ip->RedrawViews(ip->GetTime());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int UserPropMgr::RecursiveCountAlike(INode *node, BOOL MatchAll) {
|
|
|
|
int count=0;
|
|
|
|
if (node) {
|
|
|
|
if (!node->IsNodeHidden() && !node->IsFrozen() && IsAlike(node,MatchAll)) count++;
|
|
|
|
} else node = ip->GetRootNode();
|
|
|
|
|
|
|
|
for (int i=0; i<node->NumberOfChildren(); i++) {
|
|
|
|
count += RecursiveCountAlike(node->GetChildNode(i),MatchAll);
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int UserPropMgr::CountAlike(BOOL MatchAll) {
|
|
|
|
return RecursiveCountAlike(NULL, MatchAll);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL UserPropMgr::IsMatch(const char *val1, const char *val2) {
|
|
|
|
if (!stricmp(val1,val2)) return true;
|
|
|
|
hsStringTokenizer toker(val1," ,@");
|
|
|
|
char *tok;
|
|
|
|
|
|
|
|
while (tok=toker.next()) {
|
|
|
|
hsStringTokenizer toker2(val2," ,@");
|
|
|
|
BOOL found = false;
|
|
|
|
char *tok2;
|
|
|
|
while ((tok2=toker2.next()) && !found) {
|
|
|
|
if (tok[0] >= '1' && tok[0] <= '0') {
|
|
|
|
if (!stricmp(tok,tok2)) found = true;
|
|
|
|
} else if (toker.HasMoreTokens()) {
|
|
|
|
if (!stricmp(tok,tok2)) found = true;if (!stricmp(tok,tok2)) found = true;
|
|
|
|
} else {
|
|
|
|
if (!strnicmp(tok,tok2,strlen(tok))) found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL UserPropMgr::IsAlike(INode *node, BOOL MatchAll) {
|
|
|
|
TSTR buf;
|
|
|
|
GetUserPropBuffer(node,buf);
|
|
|
|
|
|
|
|
BOOL oldProps = vProps;
|
|
|
|
vProps=false;
|
|
|
|
|
|
|
|
hsStringTokenizer toker(buf," \r\n");
|
|
|
|
toker.ParseQuotes(TRUE);
|
|
|
|
char *tok;
|
|
|
|
TSTR name;
|
|
|
|
TSTR value;
|
|
|
|
TSTR tval;
|
|
|
|
BOOL match = MatchAll;
|
|
|
|
bool isName = true;
|
|
|
|
tok = toker.next();
|
|
|
|
while (tok && (match==MatchAll)) {
|
|
|
|
if (isName) {
|
|
|
|
if (*tok != '=') {
|
|
|
|
name = tok;
|
|
|
|
tok = toker.next();
|
|
|
|
if (tok && *tok == '=') {
|
|
|
|
tok = toker.next();
|
|
|
|
if (tok) value = tok;
|
|
|
|
else value = "";
|
|
|
|
tok = toker.next();
|
|
|
|
} else value = "";
|
|
|
|
if (GetUserProp(node,name,tval)) match = IsMatch(value,tval);
|
|
|
|
else match = false;
|
|
|
|
continue;
|
|
|
|
} else isName = false;
|
|
|
|
} else {
|
|
|
|
isName = true;
|
|
|
|
}
|
|
|
|
tok=toker.next();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (match==MatchAll) {
|
|
|
|
if (!vname.isNull()) match = IsMatch(vname,node->GetName());
|
|
|
|
}
|
|
|
|
|
|
|
|
vProps = oldProps;
|
|
|
|
return match;
|
|
|
|
}
|
|
|
|
|
|
|
|
int UserPropMgr::GetUserPropCount(INode *node) {
|
|
|
|
TSTR buf;
|
|
|
|
|
|
|
|
GetUserPropBuffer(node,buf);
|
|
|
|
|
|
|
|
int numProps = 0;
|
|
|
|
|
|
|
|
hsStringTokenizer toker(buf," \r\n");
|
|
|
|
toker.ParseQuotes(TRUE);
|
|
|
|
char *tok;
|
|
|
|
bool isName = true;
|
|
|
|
while (tok=toker.next()) {
|
|
|
|
if (isName) {
|
|
|
|
if (*tok != '=') {
|
|
|
|
numProps++;
|
|
|
|
} else isName = false;
|
|
|
|
} else {
|
|
|
|
isName = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return numProps;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPropMgr::GetUserPropBuffer(INode *node, TSTR &buf) {
|
|
|
|
if (vProps) buf = vbuf;
|
|
|
|
else if (node) node->GetUserPropBuffer(buf);
|
|
|
|
else buf = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPropMgr::SetUserPropBuffer(INode *node, const TSTR &buf)
|
|
|
|
{
|
|
|
|
// QuickTable invalidate
|
|
|
|
if (node && node == fQuickNode)
|
|
|
|
{
|
|
|
|
fQuickNode = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vProps)
|
|
|
|
{
|
|
|
|
vbuf = buf;
|
|
|
|
}
|
|
|
|
else if (node)
|
|
|
|
{
|
|
|
|
node->SetUserPropBuffer(buf);
|
|
|
|
node->NotifyDependents(FOREVER, PART_ALL, REFMSG_USERPROP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPropMgr::SetUserPropFlagALL(const char *name, const BOOL setFlag, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
for (int i=0; i<GetSelNodeCount();i++)
|
|
|
|
{
|
|
|
|
SetUserPropFlag(GetSelNode(i),name,setFlag,hFlag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOOL UserPropMgr::GetUserPropFlagALL(const char *name, BOOL &isSet, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
isSet = UserPropMgr::UserPropExists(GetSelNode(0),name,hFlag);
|
|
|
|
|
|
|
|
for (int i=0; i<GetSelNodeCount(); i++) {
|
|
|
|
if (isSet != UserPropMgr::UserPropExists(GetSelNode(i),name,hFlag)) return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
INode* UserPropMgr::GetAncestorIfNeeded(INode* node, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
if (hFlag == kParent)
|
|
|
|
{
|
|
|
|
if (!(node->IsRootNode() || node->GetParentNode()->IsRootNode()))
|
|
|
|
node = node->GetParentNode();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (hFlag == kRoot)
|
|
|
|
{
|
|
|
|
while (!(node->IsRootNode() || node->GetParentNode()->IsRootNode()))
|
|
|
|
node = node->GetParentNode();
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UserPropMgr::ClearUserProp(INode *node, const char *name, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
node = GetAncestorIfNeeded(node,hFlag);
|
|
|
|
|
|
|
|
// QuickTable invalidate
|
|
|
|
if (node && node == fQuickNode)
|
|
|
|
{
|
|
|
|
fQuickNode = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
TSTR buf;
|
|
|
|
GetUserPropBuffer(node,buf);
|
|
|
|
|
|
|
|
hsStringTokenizer toker(buf," \r\n");
|
|
|
|
toker.ParseQuotes(TRUE);
|
|
|
|
char *tok;
|
|
|
|
bool isName = true;
|
|
|
|
while (tok=toker.next())
|
|
|
|
{
|
|
|
|
if (isName)
|
|
|
|
{
|
|
|
|
if (*tok != '=')
|
|
|
|
{
|
|
|
|
if (!stricmp(tok,name))
|
|
|
|
{
|
|
|
|
char *tok2 = toker.next();
|
|
|
|
if (tok2)
|
|
|
|
{
|
|
|
|
if (*tok2 == '=')
|
|
|
|
{
|
|
|
|
tok2 = toker.next();
|
|
|
|
if (tok2)
|
|
|
|
{
|
|
|
|
tok2 = toker.next();
|
|
|
|
if (tok2)
|
|
|
|
{
|
|
|
|
buf.remove(tok-toker.fString,tok2-tok);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf.remove(tok-toker.fString);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf.remove(tok-toker.fString);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf.remove(tok-toker.fString,tok2-tok);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf.remove(tok-toker.fString);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
isName = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
isName = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (vProps)
|
|
|
|
{
|
|
|
|
vbuf = buf;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
node->SetUserPropBuffer(buf);
|
|
|
|
node->NotifyDependents(FOREVER, PART_ALL, REFMSG_USERPROP);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
BOOL UserPropMgr::GetUserProp(INode *node, const char *name, TSTR &value, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
node = GetAncestorIfNeeded(node,hFlag);
|
|
|
|
|
|
|
|
// QuickTable lookup
|
|
|
|
if (node && fQuickTable)
|
|
|
|
{
|
|
|
|
if (node != fQuickNode)
|
|
|
|
IBuildQuickTable(node);
|
|
|
|
return ICheckQuickEntry(name,value);
|
|
|
|
}
|
|
|
|
|
|
|
|
TSTR buf;
|
|
|
|
GetUserPropBuffer(node,buf);
|
|
|
|
|
|
|
|
hsStringTokenizer toker(buf," \r\n");
|
|
|
|
toker.ParseQuotes(TRUE);
|
|
|
|
char *tok;
|
|
|
|
bool isName = true;
|
|
|
|
while (tok=toker.next())
|
|
|
|
{
|
|
|
|
if (isName)
|
|
|
|
{
|
|
|
|
if (*tok != '=')
|
|
|
|
{
|
|
|
|
if (!stricmp(tok,name))
|
|
|
|
{
|
|
|
|
tok = toker.next();
|
|
|
|
if (tok && *tok == '=')
|
|
|
|
{
|
|
|
|
tok = toker.next();
|
|
|
|
if (tok) value = tok;
|
|
|
|
else value = "";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
value = "";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
isName = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
isName = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPropMgr::SetUserProp(INode *node, const char *name, const char *value, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
node = GetAncestorIfNeeded(node,hFlag);
|
|
|
|
|
|
|
|
// QuickTable invalidate
|
|
|
|
if (node && node == fQuickNode)
|
|
|
|
{
|
|
|
|
fQuickNode = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
TSTR buf;
|
|
|
|
GetUserPropBuffer(node,buf);
|
|
|
|
|
|
|
|
hsStringTokenizer toker(buf," \r\n");
|
|
|
|
toker.ParseQuotes(TRUE);
|
|
|
|
char *tok;
|
|
|
|
bool isName = true;
|
|
|
|
while (tok=toker.next())
|
|
|
|
{
|
|
|
|
if (isName)
|
|
|
|
{
|
|
|
|
if (*tok != '=')
|
|
|
|
{
|
|
|
|
if (!stricmp(tok,name))
|
|
|
|
{
|
|
|
|
char *tok2 = toker.next();
|
|
|
|
if (tok2)
|
|
|
|
{
|
|
|
|
if (*tok2 == '=')
|
|
|
|
{
|
|
|
|
tok2 = toker.next();
|
|
|
|
if (tok2)
|
|
|
|
{
|
|
|
|
tok2 = toker.next();
|
|
|
|
if (tok2)
|
|
|
|
{
|
|
|
|
buf.remove(tok-toker.fString,tok2-tok);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf.remove(tok-toker.fString);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf.remove(tok-toker.fString);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf.remove(tok-toker.fString,tok2-tok);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf.remove(tok-toker.fString);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
isName = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
isName = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (buf.last('\n') < buf.length()-1)
|
|
|
|
{
|
|
|
|
// better start with a separator
|
|
|
|
buf += "\r\n";
|
|
|
|
}
|
|
|
|
buf += name;
|
|
|
|
if (value && *value)
|
|
|
|
{
|
|
|
|
buf += " = ";
|
|
|
|
if (strchr(value,' '))
|
|
|
|
{
|
|
|
|
buf += "\"";
|
|
|
|
buf += value;
|
|
|
|
buf += "\"";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buf += value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
buf += "\r\n";
|
|
|
|
if (vProps)
|
|
|
|
{
|
|
|
|
vbuf = buf;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
node->SetUserPropBuffer(buf);
|
|
|
|
node->NotifyDependents(FOREVER, PART_ALL, REFMSG_USERPROP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL UserPropMgr::GetUserPropString(INode *node, const char *name, TSTR &value, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
return GetUserProp(node,name,value,hFlag);
|
|
|
|
}
|
|
|
|
void UserPropMgr::SetUserPropString(INode *node, const char *name, const char *value, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
SetUserProp(node,name,value,hFlag);
|
|
|
|
}
|
|
|
|
BOOL UserPropMgr::GetUserPropFloat(INode *node, const char *name, float &value, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
TSTR valStr;
|
|
|
|
if (GetUserProp(node,name,valStr,hFlag))
|
|
|
|
{
|
|
|
|
value = (float)atof(valStr);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
void UserPropMgr::SetUserPropFloat(INode *node, const char *name, const float value, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
char valStr[50];
|
|
|
|
if (sprintf(valStr,"%g",value)) SetUserProp(node,name,valStr,hFlag);
|
|
|
|
}
|
|
|
|
BOOL UserPropMgr::GetUserPropInt(INode *node, const char *name, int &value, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
TSTR valStr;
|
|
|
|
if (GetUserProp(node,name,valStr,hFlag)) {
|
|
|
|
value = atoi(valStr);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
void UserPropMgr::SetUserPropInt(INode *node, const char *name, const int value, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
char valStr[50];
|
|
|
|
if (sprintf(valStr,"%d",value)) SetUserProp(node,name,valStr,hFlag);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL UserPropMgr::UserPropExists(INode *node, const char *name, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
TSTR value;
|
|
|
|
return GetUserProp(node,name,value,hFlag);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL UserPropMgr::GetUserPropStringList(INode *node, const char *name, int &num, TSTR list[]) {
|
|
|
|
TSTR sdata;
|
|
|
|
if (UserPropMgr::GetUserPropString(node,name,sdata)) {
|
|
|
|
num=0;
|
|
|
|
hsStringTokenizer toker(sdata,", ");
|
|
|
|
char *tok;
|
|
|
|
while ( tok = toker.next() ) {
|
|
|
|
list[num] = tok;
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL UserPropMgr::GetUserPropIntList(INode *node, const char *name, int &num, int list[]) {
|
|
|
|
TSTR sdata;
|
|
|
|
if (UserPropMgr::GetUserPropString(node,name,sdata)) {
|
|
|
|
num=0;
|
|
|
|
hsStringTokenizer toker(sdata,", ");
|
|
|
|
char *tok;
|
|
|
|
while ( tok = toker.next() ) {
|
|
|
|
list[num] = atoi(tok);
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL UserPropMgr::GetUserPropFloatList(INode *node, const char *name, int &num, float list[]) {
|
|
|
|
TSTR sdata;
|
|
|
|
if (UserPropMgr::GetUserPropString(node,name,sdata)) {
|
|
|
|
num=0;
|
|
|
|
hsStringTokenizer toker(sdata,", ");
|
|
|
|
char *tok;
|
|
|
|
while ( tok = toker.next() ) {
|
|
|
|
list[num] = (float)atof(tok);
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL UserPropMgr::GetUserPropStringALL(const char *name, TSTR &value, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
BOOL propSet = UserPropMgr::GetUserPropString(GetSelNode(0),name,value,hFlag);
|
|
|
|
|
|
|
|
TSTR tvalue;
|
|
|
|
int i=1;
|
|
|
|
BOOL propMixed = FALSE;
|
|
|
|
while (i < GetSelNodeCount() && !propMixed) {
|
|
|
|
if (propSet ^ UserPropMgr::GetUserPropString(GetSelNode(i),name,tvalue,hFlag)) propMixed = TRUE;
|
|
|
|
propMixed = (!(value == tvalue));
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (!propMixed);
|
|
|
|
}
|
|
|
|
void UserPropMgr::SetUserPropStringALL(const char *name, const char *value, const int32_t hFlag)
|
|
|
|
{
|
|
|
|
for (int i=0; i<GetSelNodeCount(); i++) {
|
|
|
|
UserPropMgr::SetUserPropString(GetSelNode(i),name,value,hFlag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL UserPropMgr::GetUserPropStringListALL(const char *name, int &num, TSTR list[]) {
|
|
|
|
TSTR val;
|
|
|
|
GetUserPropStringList(GetSelNode(0),name,num,list);
|
|
|
|
return GetUserPropStringALL(name,val);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL UserPropMgr::GetUserPropIntListALL(const char *name, int &num, int *list) {
|
|
|
|
TSTR val;
|
|
|
|
GetUserPropIntList(GetSelNode(0),name,num,list);
|
|
|
|
return GetUserPropStringALL(name,val);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL UserPropMgr::GetUserPropFloatListALL(const char *name, int &num, float *list) {
|
|
|
|
TSTR val;
|
|
|
|
GetUserPropFloatList(GetSelNode(0),name,num,list);
|
|
|
|
return GetUserPropStringALL(name,val);
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL UserPropMgr::GetNodeNameALL(TSTR &name) {
|
|
|
|
if (vProps) name = vname;
|
|
|
|
else if (ip->GetSelNodeCount() == 1) name = ip->GetSelNode(0)->GetName();
|
|
|
|
else return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPropMgr::SetNodeNameALL(const char *name) {
|
|
|
|
if (vProps) {
|
|
|
|
vname = name;
|
|
|
|
} else {
|
|
|
|
if (ip->GetSelNodeCount() > 1) {
|
|
|
|
TSTR uName;
|
|
|
|
for (int i=0; i<ip->GetSelNodeCount(); i++) {
|
|
|
|
uName = name;
|
|
|
|
ip->MakeNameUnique(uName);
|
|
|
|
ip->GetSelNode(i)->SetName(uName);
|
|
|
|
}
|
|
|
|
} else ip->GetSelNode(0)->SetName((char*)name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UserPropMgr::LoadVirtualProps(BOOL reset) {
|
|
|
|
if (reset)
|
|
|
|
{
|
|
|
|
vbuf = "";
|
|
|
|
vname = "";
|
|
|
|
}
|
|
|
|
vProps = true;
|
|
|
|
}
|
|
|
|
void UserPropMgr::DestroyVirtualProps() {
|
|
|
|
vProps = false;
|
|
|
|
}
|
|
|
|
BOOL UserPropMgr::IsVirtual() {
|
|
|
|
return vProps;
|
|
|
|
}
|
|
|
|
|
|
|
|
int UserPropMgr::GetSelNodeCount() {
|
|
|
|
if (vProps) return 1;
|
|
|
|
else return ip->GetSelNodeCount();
|
|
|
|
}
|
|
|
|
INode *UserPropMgr::GetSelNode(int i) {
|
|
|
|
if (vProps) return NULL;
|
|
|
|
else return ip->GetSelNode(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UserPropMgr::OpenQuickTable()
|
|
|
|
{
|
|
|
|
if (!fQuickTable)
|
|
|
|
{
|
|
|
|
fQuickTable = new hsHashTable<QuickPair>(kQuickSize);
|
|
|
|
}
|
|
|
|
fQuickNode = nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPropMgr::CloseQuickTable()
|
|
|
|
{
|
|
|
|
#ifdef HS_DEBUGGING
|
|
|
|
if (fQuickNode && fQuickTable)
|
|
|
|
{
|
|
|
|
char str[256];
|
|
|
|
sprintf(str,"%d Hash Collisions reported\n",fQuickTable->CollisionCount());
|
|
|
|
hsStatusMessage(str);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
delete fQuickTable;
|
|
|
|
fQuickTable = nil;
|
|
|
|
fQuickNode = nil;
|
|
|
|
QuickPair::SetBuffer(nil);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UserPropMgr::IBuildQuickTable(INode* node)
|
|
|
|
{
|
|
|
|
if (fQuickTable && fQuickNode != node)
|
|
|
|
{
|
|
|
|
fQuickNode = node;
|
|
|
|
|
|
|
|
// clear old QuickTable
|
|
|
|
fQuickTable->clear();
|
|
|
|
|
|
|
|
// build new one
|
|
|
|
TSTR buf;
|
|
|
|
GetUserPropBuffer(node,buf);
|
|
|
|
|
|
|
|
hsStringTokenizer toker(buf," \r\n");
|
|
|
|
toker.ParseQuotes(TRUE);
|
|
|
|
|
|
|
|
char *tok;
|
|
|
|
bool inName = false;
|
|
|
|
bool isName = true;
|
|
|
|
while ( inName || (tok=toker.next()) )
|
|
|
|
{
|
|
|
|
if (isName)
|
|
|
|
{
|
|
|
|
if (*tok != '=')
|
|
|
|
{
|
|
|
|
QuickPair qPair;
|
|
|
|
qPair.SetKey(tok);
|
|
|
|
|
|
|
|
tok = toker.next();
|
|
|
|
if (tok && *tok == '=')
|
|
|
|
{
|
|
|
|
tok = toker.next();
|
|
|
|
qPair.SetVal(tok);
|
|
|
|
|
|
|
|
inName = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
qPair.SetVal(nil);
|
|
|
|
inName = (tok != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
fQuickTable->insert(qPair);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
isName = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
isName = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// QuickPair owns the tok'd buffer now
|
|
|
|
QuickPair::SetBuffer(toker.fString);
|
|
|
|
toker.fString = nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL UserPropMgr::ICheckQuickEntry(const char *key, TSTR &value)
|
|
|
|
{
|
|
|
|
QuickPair q;
|
|
|
|
q.SetKey(key);
|
|
|
|
hsHashTableIterator<QuickPair> it = fQuickTable->find(q);
|
|
|
|
return it->GetVal(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char* UserPropMgr::QuickPair::fBuffer = nil;
|
|
|
|
|
|
|
|
void UserPropMgr::QuickPair::SetBuffer(char* buf)
|
|
|
|
{
|
|
|
|
delete [] fBuffer;
|
|
|
|
fBuffer = buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t UserPropMgr::QuickPair::GetHash() const
|
|
|
|
{
|
|
|
|
const char * k = fKey;
|
|
|
|
int len = k ? strlen(k) : 0;
|
|
|
|
int h;
|
|
|
|
for (h=len; len--;)
|
|
|
|
{
|
|
|
|
h = ((h<<5)^(h>>27))^tolower(*k++);
|
|
|
|
}
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
|
|
|
hsBool UserPropMgr::QuickPair::GetVal(TSTR& value)
|
|
|
|
{
|
|
|
|
if (fKey)
|
|
|
|
{
|
|
|
|
value = fVal ? fVal : "";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool UserPropMgr::QuickPair::operator==(const QuickPair& other) const
|
|
|
|
{
|
|
|
|
return !_stricmp(fKey,other.fKey);
|
|
|
|
}
|