📄 tree_utils.c
字号:
/*------------------------------------------------------------------------------*
* File Name: tree_utils.c *
* Creation: May 07, 2003 *
* Purpose: define tree utility functions *
* Copyright (c)2003 OriginLab Corp. *
* All Rights Reserved *
* *
* Modification Log: *
*------------------------------------------------------------------------------*/
#include <origin.h> // main Origin C header that is precompiled and already include most headers
////////////////////////////////////////////////////////////////////////////////////
#define PAGE_INFO_EXPORT "Export"
////////////////////////////////////////////////////////////////////////////////////
// start your functions here
TreeNode tree_get_ini_section(TreeNode &trIni, LPCSTR lpcszSection)
{
if( !trIni || NULL == lpcszSection )
return false;
TreeNode trIniSection;
foreach(trIniSection in trIni.Children)
{
if( trIniSection.Name.IsValid() && 0 == lstrcmpi(lpcszSection, trIniSection.Name.strVal) )
return trIniSection;
}
TreeNode trNull; // return invalid tree node
return trNull;
}
bool tree_read_ini(TreeNode &trIni, LPCSTR lpcszFile)
{
if( !trIni || NULL == lpcszFile )
return false;
INIFile iniFile(lpcszFile);
return tree_read_ini(trIni, iniFile);
}
bool tree_read_ini(TreeNode &trIni, INIFile &iniFile)
{
if( !trIni )
return false;
StringArray saIniSections;
iniFile.GetSectionNames(saIniSections);
for( int i = 0; i < saIniSections.GetSize(); i++ )
tree_read_ini_section(trIni, iniFile, saIniSections[i]);
return true;
}
bool tree_read_ini_section(TreeNode &trIni, LPCSTR lpcszFile, LPCSTR lpcszSection)
{
if( !trIni || NULL == lpcszFile || NULL == lpcszSection )
return false;
INIFile iniFile(lpcszFile);
return tree_read_ini_section(trIni, iniFile, lpcszSection);
}
bool tree_read_ini_section(TreeNode &trIni, INIFile &iniFile, LPCSTR lpcszSection)
{
if( !trIni || NULL == lpcszSection )
return false;
string str = lpcszSection;
str.MakeValidCName('S');
TreeNode trIniSection = tree_get_ini_section(trIni, str);
if( trIniSection )
{
trIniSection.Reset();
}
else // section not found
{
trIniSection = trIni.AddNode(str);
}
if( !trIniSection )
return false;
// If section name is not a valid identifier name
// then store the original name in the label attribute.
if( str.Compare(lpcszSection) )
{
trIniSection.SetAttribute(STR_LABEL_ATTRIB, lpcszSection);
}
TreeNode trIniKey;
StringArray saIniKeyNames;
iniFile.GetKeyNames(saIniKeyNames, lpcszSection);
for( int i = 0; i < saIniKeyNames.GetSize(); i++ )
{
str = saIniKeyNames[i];
str.MakeValidCName('K');
trIniKey = trIniSection.AddNode(str);
if( trIniKey )
{
if( str.Compare(saIniKeyNames[i]) )
trIniKey.SetAttribute(STR_LABEL_ATTRIB, saIniKeyNames[i]);
trIniKey.strVal = iniFile.ReadString(lpcszSection, saIniKeyNames[i]);
}
}
return true;
}
bool tree_write_ini(TreeNode &trIni, LPCSTR lpcszFile, bool bClearSections)
{
if( !trIni || NULL == lpcszFile )
return false;
INIFile iniFile(lpcszFile);
return tree_write_ini(trIni, iniFile, bClearSections);
}
bool tree_write_ini(TreeNode &trIni, INIFile &iniFile, bool bClearSections)
{
if( !trIni )
return false;
TreeNode trIniSection;
foreach(trIniSection in trIni.Children)
tree_write_ini_section(trIniSection, iniFile, bClearSections);
return true;
}
bool tree_write_ini_section(TreeNode &trIniSection, INIFile &iniFile, bool bClearSection)
{
if( !trIniSection )
return false;
string strSection;
if( !trIniSection.GetAttribute(STR_LABEL_ATTRIB, strSection) || strSection.IsEmpty() )
strSection = trIniSection.tagName;
if( bClearSection )
iniFile.WriteString(strSection, NULL, NULL); // delete ini file section
string strKey;
TreeNode trIniKey;
foreach(trIniKey in trIniSection.Children)
{
if( !trIniKey.GetAttribute(STR_LABEL_ATTRIB, strKey) || strKey.IsEmpty() )
strKey = trIniKey.tagName;
iniFile.WriteString(strSection, strKey, trIniKey.strVal);
}
return true;
}
bool tree_write_ini_section(TreeNode &trIniSection, LPCSTR lpcszFile, bool bClearSection)
{
if( !trIniSection || NULL == lpcszFile )
return false;
INIFile iniFile(lpcszFile);
return tree_write_ini_section(trIniSection, iniFile, bClearSection);
}
///////////////////////////////////////
///// read/write image export settings
///////////////////////////////////////
bool tree_read_image_export_settings(TreeNode &trSettings, LPCSTR lpcszFormat)
{
string str(lpcszFormat);;
LabTalk.Image.Export.GetIni("a", "b", str);
char szFile[MAX_PATH], szSec[MAX_PATH];
if( !LT_get_str("%a", szFile, MAX_PATH) || !LT_get_str("%b", szSec, MAX_PATH) )
return false;
bool bRet;
if( szSec[0] ) // if ini section specified
bRet = tree_read_ini_section(trSettings, szFile, szSec);
else
bRet = tree_read_ini(trSettings, szFile);
return bRet;
}
bool tree_write_image_export_settings(TreeNode &trSettings, LPCSTR lpcszFormat, bool bClearSections)
{
string str(lpcszFormat);;
//LabTalk.Image.Export.GetIni("a", "b", lpcszFormat);
LabTalk.Image.Export.GetIni("a", "b", str);
char szFile[MAX_PATH], szSec[MAX_PATH];
if( !LT_get_str("%a", szFile, MAX_PATH) || !LT_get_str("%a", szSec, MAX_PATH) )
return false;
bool bRet;
if( szSec[0] ) // if ini section specified
bRet = tree_write_ini_section(trSettings, szFile, bClearSections);//, szSec);
else
bRet = tree_write_ini(trSettings, szFile, bClearSections);
return bRet;
}
bool tree_get_page_image_export_settings(TreeNode &trSettings, Page &pg, LPCSTR lpcszFormat)
{
/* This old code used page's ini storage
pg.Info.Add(PAGE_INFO_EXPORT);
storage st;
st = pg.GetStorage(PAGE_INFO_EXPORT);
if( st && st.GetSection(lpcszFormat, trSettings) )
return true;
return false;
*/
string str;
str.Format(PAGE_INFO_EXPORT"%s", lpcszFormat);
vector<byte> vb;
if( pg.GetMemory(str, vb) )
{
if( str.SetBytes(vb) )
{
trSettings.XML = str;
return true;
}
}
return false;
}
bool tree_set_page_image_export_settings(TreeNode &trSettings, Page &pg, LPCSTR lpcszFormat, bool bClearSection)
{
/* This old code used page's ini storage
pg.Info.Add(PAGE_INFO_EXPORT);
storage st;
st = pg.GetStorage(PAGE_INFO_EXPORT);
if( st )
{
if( bClearSection )
{
//---temp code until st.RemoveSection is implemented
string strSection = lpcszFormat;
pg.Info.Export.RemoveSection(strSection);
//---
//st.RemoveSection(lpcszFormat);
}
if( st.SetSection(lpcszFormat, trSettings) )
return true;
}
return false;
*/
string str = trSettings.XML;
vector<byte> vb;
if( str.GetBytes(vb) )
{
str.Format(PAGE_INFO_EXPORT"%s", lpcszFormat);
return pg.SetMemory(str, vb);
}
return false;
}
///////////////////////////////////////
///// general tree related utilities
///////////////////////////////////////
bool out_tree(TreeNode& tr, int nLevel) // = 0
{
if(NULL==tr)
return false;
for(int ii = 0; ii < nLevel; ii++)
printf(" ");
if(tr.GetNodeCount() > 0) // branch node
{
printf("%s\n", tr.tagName);
foreach(TreeNode cNode in tr.Children)
out_tree(cNode, nLevel+1);
}
else // leaf node
printf("%s = %s\n", tr.tagName, tr.Text);
return true;
}
static string get_tree_node_attribute_as_str(const TreeNode& tr)
{
vector<string> vsKnownAttributes = {
STR_ENABLE_ATTRIB, STR_SHOW_ATTRIB, STR_ID_ATTRIB, STR_COMBO_ATTRIB, STR_LABEL_ATTRIB
};
string strRet;
string strTemp;
for(int ii = 0; ii < vsKnownAttributes.GetSize(); ii++)
{
if(tr.GetAttribute(vsKnownAttributes[ii], strTemp))
{
if(!strRet.IsEmpty())
strRet += ",";
strRet += vsKnownAttributes[ii] + "=" + strTemp;
}
}
if(strRet.IsEmpty())
return strRet;
// add ()
strTemp = "(" + strRet + ")";
return strTemp;
}
static bool dump_tree(const TreeNode& tr, LPCSTR lpcsz, int nOutput, int nLevel)
{
if(NULL==tr)
return false;
string strTemp = lpcsz;
if(0==nLevel && lpcsz)
strTemp.WriteLine(nOutput);
for(int ii = 0; ii < nLevel; ii++)
{
strTemp = " ";
strTemp.Write(nOutput);
}
//--- attributes
string strAttrib = get_tree_node_attribute_as_str(tr);
if(tr.GetNodeCount() > 0) // branch node
{
strTemp = tr.tagName;
strTemp += strAttrib;
strTemp.WriteLine(nOutput);
foreach(TreeNode cNode in tr.Children)
dump_tree(cNode, NULL, nOutput, nLevel+1);
}
else // leaf node
{
strTemp.Format("%s%s = %s", tr.tagName, strAttrib, tr.Text);
strTemp.WriteLine(nOutput);
}
return true;
}
bool tree_dump(const TreeNode& tr, LPCSTR lpcsz, int nOutput) // = NULL, WRITE_SCRIPT_WINDOW
{
return dump_tree(tr, lpcsz, nOutput, 0);
}
static void treeNode_count(TreeNode& trNode, int& nLeafs, int& nBranches)
{
if(trNode.GetNodeCount() > 0 || trNode.ID == ONODETYPE_BRANCH) // branch node
{
int nSubBranches = 0;
nBranches++;
nLeafs += tree_count_items(trNode, &nSubBranches);
nBranches += nSubBranches;
}
else
{
DWORD dwID = trNode.ID;
DWORD dwBranchBits = ONODETYPE_BRANCH | ONODETYPE_BRANCH_COMPOSITE | ONODETYPE_BRANCH_DIALOG;
if(dwID && (dwID & dwBranchBits)) // skip branch nodes
{
//out_int("skipped ", dwID);
return;
}
//else
// out_int("not skipped ", dwID);
nLeafs++;
}
}
// count number of leafs in the given tree
// if lpnSections given, then count the number of branches that contain these leafs
int tree_count_items(TreeNode& tr, int* lpnSections)// = NULL);
{
if(NULL==tr)
return -1;
int nLeafs = 0;
//
if(NULL==lpnSections)
{
if(tr.GetAttribute(THEME_COUNT_NAME, nLeafs))
return nLeafs;
}
int nBranches = 0;
foreach(TreeNode trN in tr.Children)
{
treeNode_count(trN, nLeafs, nBranches);
}
if(lpnSections)
*lpnSections = nBranches;
return nLeafs;
}
// consider a linearized tree and return node at given row number, with nRow = 0 to return the root
TreeNode tree_get_node(TreeNode& trRoot, int nRow, int* lpInc) // = NULL
{
TreeNode cNode = trRoot.FirstNode;
if(!cNode)
return cNode;//NULL
int nIndex = (lpInc)? *lpInc : 0;
foreach(TreeNode trN in trRoot.Children)
{
if(nIndex == nRow)
return trN;
nIndex++;
if(trN.GetNodeCount() > 0) // branch node
{
cNode = tree_get_node(trN, nRow, &nIndex);
if(cNode)
return cNode;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -