diff --git a/reactos/subsys/system/explorer/dialogs/settings.cpp b/reactos/subsys/system/explorer/dialogs/settings.cpp index 9b9ca347822..0b02019307d 100644 --- a/reactos/subsys/system/explorer/dialogs/settings.cpp +++ b/reactos/subsys/system/explorer/dialogs/settings.cpp @@ -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 diff --git a/reactos/subsys/system/explorer/explorer.cpp b/reactos/subsys/system/explorer/explorer.cpp index c7c475ce995..83d1f02fc0f 100644 --- a/reactos/subsys/system/explorer/explorer.cpp +++ b/reactos/subsys/system/explorer/explorer.cpp @@ -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()) diff --git a/reactos/subsys/system/explorer/globals.h b/reactos/subsys/system/explorer/globals.h index e0d65ed2b22..5cc9371657c 100644 --- a/reactos/subsys/system/explorer/globals.h +++ b/reactos/subsys/system/explorer/globals.h @@ -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; diff --git a/reactos/subsys/system/explorer/shell/mainframe.cpp b/reactos/subsys/system/explorer/shell/mainframe.cpp index 492ebef7468..38df78cd364 100644 --- a/reactos/subsys/system/explorer/shell/mainframe.cpp +++ b/reactos/subsys/system/explorer/shell/mainframe.cpp @@ -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) diff --git a/reactos/subsys/system/explorer/taskbar/traynotify.cpp b/reactos/subsys/system/explorer/taskbar/traynotify.cpp index df3dbecf394..5929501e806 100644 --- a/reactos/subsys/system/explorer/taskbar/traynotify.cpp +++ b/reactos/subsys/system/explorer/taskbar/traynotify.cpp @@ -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) { diff --git a/reactos/subsys/system/explorer/utility/xmlstorage.cpp b/reactos/subsys/system/explorer/utility/xmlstorage.cpp index dd2a6f0f015..51019f3ebab 100644 --- a/reactos/subsys/system/explorer/utility/xmlstorage.cpp +++ b/reactos/subsys/system/explorer/utility/xmlstorage.cpp @@ -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; } diff --git a/reactos/subsys/system/explorer/utility/xmlstorage.h b/reactos/subsys/system/explorer/utility/xmlstorage.h index edd00d7dc80..76b2e46d3af 100644 --- a/reactos/subsys/system/explorer/utility/xmlstorage.h +++ b/reactos/subsys/system/explorer/utility/xmlstorage.h @@ -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 - 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(const_cast(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 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);