introduce XPath syntax to make handling configuration a bit easier

svn path=/trunk/; revision=11071
This commit is contained in:
Martin Fuchs 2004-09-26 15:13:16 +00:00
parent c8e0c372d9
commit d3f70f50f0
7 changed files with 295 additions and 73 deletions

View file

@ -159,9 +159,9 @@ TaskbarSettingsDlg::TaskbarSettingsDlg(HWND hwnd)
: super(hwnd),
_cfg_org(g_Globals._cfg)
{
XMLPos options(g_Globals.get_cfg("desktopbar"), "options");
XMLPos options = g_Globals.get_cfg("desktopbar/options");
CheckDlgButton(hwnd, ID_SHOW_CLOCK, XMLBool(options, "show-clock", true)? BST_CHECKED: BST_UNCHECKED);
CheckDlgButton(hwnd, ID_SHOW_CLOCK, XMLBool(options, "show-clock", true)? BST_CHECKED: BST_UNCHECKED);
CheckDlgButton(hwnd, ID_HIDE_INACTIVE_ICONS, XMLBool(options, "hide-inactive", true)? BST_CHECKED: BST_UNCHECKED);
}
@ -192,14 +192,14 @@ int TaskbarSettingsDlg::Command(int id, int code)
break;
case ID_SHOW_CLOCK: {
XMLBoolRef boolRef1(XMLPos(g_Globals.get_cfg("desktopbar"),"options"), "show-clock", true);
XMLBoolRef boolRef1(XMLPos(g_Globals.get_cfg("desktopbar/options")), "show-clock", true);
boolRef1.toggle();
SendMessage(g_Globals._hwndDesktopBar, PM_REFRESH_CONFIG, 0, 0);
PropSheet_Changed(GetParent(_hwnd), _hwnd);
break;}
case ID_HIDE_INACTIVE_ICONS: {
XMLBoolRef boolRef2(XMLPos(g_Globals.get_cfg("notify-icons"),"options"), "hide-inactive", true);
XMLBoolRef boolRef2(XMLPos(g_Globals.get_cfg("notify-icons/options")), "hide-inactive", true);
boolRef2.toggle();
SendMessage(g_Globals._hwndDesktopBar, PM_REFRESH_CONFIG, 0, 0);
PropSheet_Changed(GetParent(_hwnd), _hwnd);
@ -236,7 +236,7 @@ MdiSdiDlg::MdiSdiDlg(HWND hwnd)
{
CenterWindow(hwnd);
XMLPos explorer_options(g_Globals.get_cfg("general"), "explorer");
XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
bool mdi = XMLBool(explorer_options, "mdi", true);
int id = mdi? IDC_MDI: IDC_SDI;
@ -250,7 +250,7 @@ int MdiSdiDlg::Command(int id, int code)
switch(id) {
case IDOK: {
bool mdi = IsDlgButtonChecked(_hwnd, IDC_MDI)==BST_CHECKED;
XMLPos explorer_options(g_Globals.get_cfg("general"), "explorer");
XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
XMLBoolRef(explorer_options, "mdi") = mdi;
} // fall through

View file

@ -113,21 +113,21 @@ void ExplorerGlobals::write_persistent()
XMLPos ExplorerGlobals::get_cfg()
{
XMLPos pos(&_cfg);
XMLPos cfg_pos(&_cfg);
pos.smart_create("explorer-cfg");
cfg_pos.smart_create("explorer-cfg");
return pos;
return cfg_pos;
}
XMLPos ExplorerGlobals::get_cfg(const String& name)
XMLPos ExplorerGlobals::get_cfg(const char* path)
{
XMLPos pos(&_cfg);
XMLPos cfg_pos(&_cfg);
pos.smart_create("explorer-cfg");
pos.smart_create(name);
cfg_pos.smart_create("explorer-cfg");
cfg_pos.create_relative(path);
return pos;
return cfg_pos;
}
@ -536,7 +536,7 @@ void explorer_show_frame(int cmdshow, LPTSTR lpCmdLine)
g_Globals._prescan_nodes = false;
XMLPos explorer_options(g_Globals.get_cfg("general"), "explorer");
XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
XS_String mdiStr = XMLString(explorer_options, "mdi");
if (mdiStr.empty())

View file

@ -236,7 +236,7 @@ extern struct ExplorerGlobals
void write_persistent();
XMLPos get_cfg();
XMLPos get_cfg(const String& name);
XMLPos get_cfg(const char* path);
HINSTANCE _hInstance;
ATOM _hframeClass;

View file

@ -112,7 +112,7 @@ int MainFrameBase::OpenShellFolders(LPIDA pida, HWND hFrameWnd)
} else {
HWND hwnd;
#ifndef _NO_MDI
XMLPos explorer_options(g_Globals.get_cfg("general"), "explorer");
XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
bool mdi = XMLBool(explorer_options, "mdi", true);
if (mdi)

View file

@ -209,25 +209,25 @@ void NotifyArea::read_config()
bool clock_visible = true;
// read notification icon settings from XML configuration
XMLPos pos = g_Globals.get_cfg();
XMLPos cfg_pos = g_Globals.get_cfg();
#ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
if (!g_Globals._SHRestricted || !SHRestricted(REST_HIDECLOCK))
#endif
{
if (pos.go_down("desktopbar")) {
clock_visible = XMLBoolRef(XMLPos(pos,"options"), "show-clock", !get_hide_clock_from_registry());
pos.back();
if (cfg_pos.go_down("desktopbar")) {
clock_visible = XMLBoolRef(XMLPos(cfg_pos,"options"), "show-clock", !get_hide_clock_from_registry());
cfg_pos.back();
}
}
if (pos.go_down("notify-icons")) {
XMLPos options(pos, "options");
if (cfg_pos.go_down("notify-icons")) {
XMLPos options(cfg_pos, "options");
_hide_inactive = XMLBool(options, "hide-inactive", true); ///@todo read default setting from registry
_show_hidden = XMLBool(options, "show-hidden", false); ///@todo read default setting from registry
XMLChildrenFilter icons(pos, "icon");
XMLChildrenFilter icons(cfg_pos, "icon");
for(XMLChildrenFilter::iterator it=icons.begin(); it!=icons.end(); ++it) {
const XMLNode& node = **it;
@ -250,7 +250,7 @@ void NotifyArea::read_config()
_cfg.push_back(cfg);
}
pos.back();
cfg_pos.back();
}
show_clock(clock_visible);
@ -259,16 +259,16 @@ void NotifyArea::read_config()
void NotifyArea::write_config()
{
// write notification icon settings to XML configuration file
XMLPos pos = g_Globals.get_cfg();
XMLPos cfg_pos = g_Globals.get_cfg();
pos.smart_create("desktopbar");
XMLBoolRef boolRef(XMLPos(pos,"options"), "show-clock");
cfg_pos.smart_create("desktopbar");
XMLBoolRef boolRef(XMLPos(cfg_pos,"options"), "show-clock");
boolRef = _hwndClock!=0;
pos.back();
cfg_pos.back();
pos.smart_create("notify-icons");
cfg_pos.smart_create("notify-icons");
XMLPos options(pos, "options");
XMLPos options(cfg_pos, "options");
XMLBoolRef(options, "hide-inactive") = _hide_inactive;
XMLBoolRef(options, "show-hidden") = _show_hidden;
@ -276,21 +276,21 @@ void NotifyArea::write_config()
NotifyIconConfig& cfg = *it;
// search for the corresponding node using the original name
pos.smart_create("icon", "name", cfg._name);
cfg_pos.smart_create("icon", "name", cfg._name);
// refresh unique name
cfg.create_name();
pos["name"] = cfg._name.c_str();
pos["text"] = cfg._tipText.c_str();
pos["window"] = cfg._windowTitle.c_str();
pos["module"] = cfg._modulePath.c_str();
pos["show"] = string_from_mode(cfg._mode).c_str();
cfg_pos["name"] = cfg._name.c_str();
cfg_pos["text"] = cfg._tipText.c_str();
cfg_pos["window"] = cfg._windowTitle.c_str();
cfg_pos["module"] = cfg._modulePath.c_str();
cfg_pos["show"] = string_from_mode(cfg._mode).c_str();
pos.back();
cfg_pos.back();
}
pos.back(); // smart_create
cfg_pos.back(); // smart_create
}
void NotifyArea::show_clock(bool flag)
@ -299,7 +299,7 @@ void NotifyArea::show_clock(bool flag)
if (vis != flag) {
if (flag) {
// smart_create clock window
// create clock window
_hwndClock = ClockWindow::Create(_hwnd);
if (_hwndClock) {

View file

@ -51,13 +51,211 @@ const LPCXSSTR XMLStorage::XS_NUMBERFMT = XS_TEXT("%d");
namespace XMLStorage {
/// move X-Path like to position in XML tree
static std::string unescape(const char* s, char b='"', char e='"')
{
const char* end = s + strlen(s);
// if (*s == b)
// ++s;
//
// if (end>s && end[-1]==e)
// --end;
if (*s == b)
if (end>s && end[-1]==e)
++s, --end;
return std::string(s, end-s);
}
static std::string unescape(const char* s, int l, char b='"', char e='"')
{
const char* end = s + l;
// if (*s == b)
// ++s;
//
// if (end>s && end[-1]==e)
// --end;
if (*s == b)
if (end>s && end[-1]==e)
++s, --end;
return std::string(s, end-s);
}
/// move XPath like to position in XML tree
bool XMLPos::go(const char* path)
{
XMLNode* node = _cur;
///@todo
// Is this an absolute path?
if (*path == '/') {
node = _root;
++path;
}
return false;
node = node->find_relative(path);
if (node) {
go_to(node);
return true;
} else
return false;
}
/// move XPath like to position in XML tree
bool const_XMLPos::go(const char* path)
{
const XMLNode* node = _cur;
// Is this an absolute path?
if (*path == '/') {
node = _root;
++path;
}
node = node->find_relative(path);
if (node) {
go_to(node);
return true;
} else
return false;
}
const XMLNode* XMLNode::find_relative(const char* path) const
{
const XMLNode* node = this;
// parse relative path
while(*path) {
const char* slash = strchr(path, '/');
if (slash == path)
return NULL;
int l = slash? slash-path: strlen(path);
std::string comp(path, l);
path += l;
// look for [n] and [@attr_name="attr_value"] expressions in path components
const char* bracket = strchr(comp.c_str(), '[');
l = bracket? bracket-comp.c_str(): comp.length();
std::string child_name(comp.c_str(), l);
std::string attr_name, attr_value;
int n = 0;
if (bracket) {
std::string expr = unescape(bracket, '[', ']');
const char* p = expr.c_str();
n = atoi(p); // read index number
if (n)
n = n - 1; // convert into zero based index
const char* at = strchr(p, '@');
if (at) {
p = at + 1;
const char* equal = strchr(p, '=');
// read attribute name and value
if (equal) {
attr_name = unescape(p, equal-p);
attr_value = unescape(equal+1);
}
}
}
if (attr_name.empty())
// search n.th child node with specified name
node = node->find(child_name, n);
else
// search n.th child node with specified name and matching attribute value
node = node->find(child_name, attr_name, attr_value, n);
if (!node)
return NULL;
if (*path == '/')
++path;
}
return node;
}
XMLNode* XMLNode::create_relative(const char* path)
{
XMLNode* node = this;
// parse relative path
while(*path) {
const char* slash = strchr(path, '/');
if (slash == path)
return NULL;
int l = slash? slash-path: strlen(path);
std::string comp(path, l);
path += l;
// look for [n] and [@attr_name="attr_value"] expressions in path components
const char* bracket = strchr(comp.c_str(), '[');
l = bracket? bracket-comp.c_str(): comp.length();
std::string child_name(comp.c_str(), l);
std::string attr_name, attr_value;
int n = 0;
if (bracket) {
std::string expr = unescape(bracket, '[', ']');
const char* p = expr.c_str();
n = atoi(p); // read index number
if (n)
n = n - 1; // convert into zero based index
const char* at = strchr(p, '@');
if (at) {
p = at + 1;
const char* equal = strchr(p, '=');
// read attribute name and value
if (equal) {
attr_name = unescape(p, equal-p);
attr_value = unescape(equal+1);
}
}
}
XMLNode* child;
if (attr_name.empty())
// search n.th child node with specified name
child = node->find(child_name, n);
else
// search n.th child node with specified name and matching attribute value
child = node->find(child_name, attr_name, attr_value, n);
if (!child) {
child = new XMLNode(child_name);
node->add_child(child);
if (!attr_name.empty())
(*node)[attr_name] = attr_value;
}
node = child;
if (*path == '/')
++path;
}
return node;
}

View file

@ -511,9 +511,9 @@ struct XMLNode : public XS_String
}
/// convenient value access in children node
XS_String subvalue(const XS_String& name, const XS_String& attr_name) const
XS_String subvalue(const XS_String& name, const XS_String& attr_name, int n=0) const
{
const XMLNode* node = find_first(name);
const XMLNode* node = find(name, n);
if (node)
return node->get(attr_name);
@ -522,9 +522,9 @@ struct XMLNode : public XS_String
}
/// convenient storage of distinct values in children node
XS_String& subvalue(const XS_String& name, const XS_String& attr_name)
XS_String& subvalue(const XS_String& name, const XS_String& attr_name, int n=0)
{
XMLNode* node = find_first(name);
XMLNode* node = find(name, n);
if (!node) {
node = new XMLNode(name);
@ -536,9 +536,9 @@ struct XMLNode : public XS_String
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
/// convenient value access in children node
XS_String subvalue(const char* name, const char* attr_name) const
XS_String subvalue(const char* name, const char* attr_name, int n=0) const
{
const XMLNode* node = find_first(name);
const XMLNode* node = find(name, n);
if (node)
return node->get(attr_name);
@ -547,9 +547,9 @@ struct XMLNode : public XS_String
}
/// convenient storage of distinct values in children node
XS_String& subvalue(const char* name, const XS_String& attr_name)
XS_String& subvalue(const char* name, const XS_String& attr_name, int n=0)
{
XMLNode* node = find_first(name);
XMLNode* node = find(name, n);
if (!node) {
node = new XMLNode(name);
@ -629,51 +629,64 @@ protected:
return NULL;
}
XMLNode* find_first(const XS_String& name) const
XMLNode* find(const XS_String& name, int n=0) const
{
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
if (**it == name)
return *it;
if (!n--)
return *it;
return NULL;
}
XMLNode* find_first(const XS_String& name, const XS_String& attr_name, const XS_String& attr_value) const
XMLNode* find(const XS_String& name, const XS_String& attr_name, const XS_String& attr_value, int n=0) const
{
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) {
const XMLNode& node = **it;
if (node==name && node.get(attr_name)==attr_value)
return *it;
if (!n--)
return *it;
}
return NULL;
}
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
XMLNode* find_first(const char* name) const
XMLNode* find(const char* name, int n=0) const
{
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
if (**it == name)
return *it;
if (!n--)
return *it;
return NULL;
}
template<typename T, typename U>
XMLNode* find_first(const char* name, const T& attr_name, const U& attr_value) const
XMLNode* find(const char* name, const T& attr_name, const U& attr_value, int n=0) const
{
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) {
const XMLNode& node = **it;
if (node==name && node.get(attr_name)==attr_value)
return *it;
if (!n--)
return *it;
}
return NULL;
}
#endif
/// XPath find functions
const XMLNode* find_relative(const char* path) const;
XMLNode* find_relative(const char* path)
{return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->find_relative(path));}
/// relative XPath create function
XMLNode* create_relative(const char* path);
void write_worker(std::ostream& out, int indent) const;
void pretty_write_worker(std::ostream& out, int indent) const;
void smart_write_worker(std::ostream& out, int indent) const;
@ -981,9 +994,9 @@ struct XMLPos
}
/// search for child and go down
bool go_down(const XS_String& name)
bool go_down(const XS_String& name, int n=0)
{
XMLNode* node = _cur->find_first(name);
XMLNode* node = _cur->find(name, n);
if (node) {
go_to(node);
@ -992,9 +1005,20 @@ struct XMLPos
return false;
}
/// move X-Path like to position in XML tree
/// move XPath like to position in XML tree
bool go(const char* path);
/// create child nodes using XPath notation and move to the deepest child
bool create_relative(const char* path)
{
XMLNode* node = _cur->create_relative(path);
if (!node)
return false; // invalid path specified
go_to(node);
return true;
}
/// create node and move to it
void create(const XS_String& name)
{
@ -1004,7 +1028,7 @@ struct XMLPos
/// create node if not already existing and move to it
void smart_create(const XS_String& name)
{
XMLNode* node = _cur->find_first(name);
XMLNode* node = _cur->find(name);
if (node)
go_to(node);
@ -1015,7 +1039,7 @@ struct XMLPos
/// search matching child node identified by key name and an attribute value
void smart_create(const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
{
XMLNode* node = _cur->find_first(name, attr_name, attr_value);
XMLNode* node = _cur->find(name, attr_name, attr_value);
if (node)
go_to(node);
@ -1028,9 +1052,9 @@ struct XMLPos
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
/// search for child and go down
bool go_down(const char* name)
bool go_down(const char* name, int n=0)
{
XMLNode* node = _cur->find_first(name);
XMLNode* node = _cur->find(name, n);
if (node) {
go_to(node);
@ -1048,7 +1072,7 @@ struct XMLPos
/// create node if not already existing and move to it
void smart_create(const char* name)
{
XMLNode* node = _cur->find_first(name);
XMLNode* node = _cur->find(name);
if (node)
go_to(node);
@ -1060,7 +1084,7 @@ struct XMLPos
template<typename T, typename U>
void smart_create(const char* name, const T& attr_name, const U& attr_value)
{
XMLNode* node = _cur->find_first(name, attr_name, attr_value);
XMLNode* node = _cur->find(name, attr_name, attr_value);
if (node)
go_to(node);
@ -1150,9 +1174,9 @@ struct const_XMLPos
}
/// search for child and go down
bool go_down(const XS_String& name)
bool go_down(const XS_String& name, int n=0)
{
XMLNode* node = _cur->find_first(name);
XMLNode* node = _cur->find(name, n);
if (node) {
go_to(node);
@ -1161,14 +1185,14 @@ struct const_XMLPos
return false;
}
/// move X-Path like to position in XML tree
/// move XPath like to position in XML tree
bool go(const char* path);
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
/// search for child and go down
bool go_down(const char* name)
bool go_down(const char* name, int n=0)
{
XMLNode* node = _cur->find_first(name);
XMLNode* node = _cur->find(name, n);
if (node) {
go_to(node);