2 added + 14 modified, total 16 files
reactos/subsys/system/explorer
diff -u -r1.13 -r1.14
--- Jamfile 27 Mar 2004 14:02:27 -0000 1.13
+++ Jamfile 4 Apr 2004 16:04:33 -0000 1.14
@@ -31,6 +31,7 @@
taskbar/startmenu.cpp
taskbar/taskbar.cpp
taskbar/traynotify.cpp
+ taskbar/favorites.cpp
desktop/desktop.cpp
# utility/splitpath.c
utility/dragdropimpl.cpp
reactos/subsys/system/explorer
diff -u -r1.31 -r1.32
--- Makefile 24 Mar 2004 10:34:21 -0000 1.31
+++ Makefile 4 Apr 2004 16:04:33 -0000 1.32
@@ -99,6 +99,7 @@
startmenu.o \
traynotify.o \
quicklaunch.o \
+ favorites.o \
searchprogram.o \
settings.o \
i386-stub-win32.o \
reactos/subsys/system/explorer
diff -u -r1.21 -r1.22
--- Makefile.MinGW 27 Mar 2004 14:02:27 -0000 1.21
+++ Makefile.MinGW 4 Apr 2004 16:04:33 -0000 1.22
@@ -68,6 +68,7 @@
startmenu.o \
traynotify.o \
quicklaunch.o \
+ favorites.o \
searchprogram.o \
settings.o \
i386-stub-win32.o \
reactos/subsys/system/explorer
diff -u -r1.11 -r1.12
--- Makefile.Wine 21 Mar 2004 23:36:23 -0000 1.11
+++ Makefile.Wine 4 Apr 2004 16:04:33 -0000 1.12
@@ -39,6 +39,7 @@
taskbar/startmenu.cpp \
taskbar/traynotify.cpp \
taskbar/quicklaunch.cpp \
+ taskbar/favorites.cpp \
dialogs/searchprogram.cpp \
dialogs/settings.cpp
reactos/subsys/system/explorer
diff -u -r1.42 -r1.43
--- doxy-footer.html 28 Mar 2004 12:00:45 -0000 1.42
+++ doxy-footer.html 4 Apr 2004 16:04:33 -0000 1.43
@@ -3,7 +3,7 @@
<tr>
<td><address style="align: right;"><small>
ROS Explorer Source Code Documentation
-<br>generated on 28.03.2004 by <a href="http://www.doxygen.org/index.html">
+<br>generated on 04.04.2004 by <a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0>
</small></address>
</td>
reactos/subsys/system/explorer
diff -u -r1.63 -r1.64
--- explorer.cpp 28 Mar 2004 14:55:17 -0000 1.63
+++ explorer.cpp 4 Apr 2004 16:04:33 -0000 1.64
@@ -82,27 +82,31 @@
}
-bool ExplorerGlobals::read_cfg()
+void ExplorerGlobals::read_persistent()
{
// read configuration file
_cfg_dir.printf(TEXT("%s\\ReactOS"), (LPCTSTR)SpecialFolderFSPath(CSIDL_APPDATA,0));
- _cfg_path.printf(TEXT("%s\\ros-explorer.xml"), _cfg_dir.c_str());
+ _cfg_path.printf(TEXT("%s\\ros-explorer-cfg.xml"), _cfg_dir.c_str());
- if (_cfg.read(_cfg_path))
- return true;
+ if (!_cfg.read(_cfg_path))
+ _cfg.read(TEXT("explorer-cfg-template.xml"));
- if (_cfg.read("explorer-cfg-template.xml"))
- return true;
+ // read bookmarks
+ _favorites_path.printf(TEXT("%s\\ros-explorer-bookmarks.xml"), _cfg_dir.c_str());
- return false;
+ if (!_favorites.read(_favorites_path)) {
+ _favorites.import_IE_favorites(0);
+ _favorites.write(_favorites_path);
+ }
}
-void ExplorerGlobals::write_cfg()
+void ExplorerGlobals::write_persistent()
{
// write configuration file
RecursiveCreateDirectory(_cfg_dir);
_cfg.write(_cfg_path);
+ _favorites.write(_favorites_path);
}
@@ -110,7 +114,7 @@
{
XMLPos pos(&_cfg);
- pos.create("explorer-cfg");
+ pos.smart_create("explorer-cfg");
return pos;
}
@@ -119,8 +123,8 @@
{
XMLPos pos(&_cfg);
- pos.create("explorer-cfg");
- pos.create(name);
+ pos.smart_create("explorer-cfg");
+ pos.smart_create(name);
return pos;
}
@@ -790,7 +794,7 @@
// init common controls library
CommonControlInit usingCmnCtrl;
- g_Globals.read_cfg();
+ g_Globals.read_persistent();
if (startup_desktop) {
g_Globals._desktops.init();
@@ -818,7 +822,7 @@
int ret = explorer_main(hInstance, lpCmdLine, nShowCmd);
// write configuration file
- g_Globals.write_cfg();
+ g_Globals.write_persistent();
return ret;
}
reactos/subsys/system/explorer
diff -u -r1.55 -r1.56
--- explorer.dsp 21 Mar 2004 23:36:23 -0000 1.55
+++ explorer.dsp 4 Apr 2004 16:04:33 -0000 1.56
@@ -554,6 +554,14 @@
# End Source File
# Begin Source File
+SOURCE=.\taskbar\favorites.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\taskbar\favorites.h
+# End Source File
+# Begin Source File
+
SOURCE=.\notifyhook\notifyhook.h
# End Source File
# Begin Source File
reactos/subsys/system/explorer
diff -u -r1.36 -r1.37
--- globals.h 28 Mar 2004 14:55:17 -0000 1.36
+++ globals.h 4 Apr 2004 16:04:33 -0000 1.37
@@ -30,6 +30,8 @@
using namespace XMLStorage;
+#include "taskbar/favorites.h"
+
/// management of file types
struct FileTypeInfo {
@@ -228,8 +230,8 @@
void init(HINSTANCE hInstance);
- bool read_cfg();
- void write_cfg();
+ void read_persistent();
+ void write_persistent();
XMLPos get_cfg();
XMLPos get_cfg(const String& name);
@@ -259,6 +261,9 @@
XMLDoc _cfg;
String _cfg_dir;
String _cfg_path;
+
+ Favorites _favorites;
+ String _favorites_path;
} g_Globals;
reactos/subsys/system/explorer
diff -u -r1.17 -r1.18
--- make_explorer.dsp 28 Mar 2004 09:34:42 -0000 1.17
+++ make_explorer.dsp 4 Apr 2004 16:04:33 -0000 1.18
@@ -108,7 +108,7 @@
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "URelease"
# PROP Intermediate_Dir "URelease"
-# PROP Cmd_Line "msdevfilt -gcc make -f Makefile.MinGW UNICODE=1"
+# PROP Cmd_Line "make -f Makefile.MinGW UNICODE=1"
# PROP Rebuild_Opt "clean all"
# PROP Target_File "explorer.exe"
# PROP Bsc_Name ""
reactos/subsys/system/explorer/shell
diff -u -r1.3 -r1.4
--- fatfs.cpp 14 Mar 2004 12:06:25 -0000 1.3
+++ fatfs.cpp 4 Apr 2004 16:04:34 -0000 1.4
@@ -460,7 +460,7 @@
_CacheDty = NULL;
_Caches = 0;
- _hDrive = CreateFile(path, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
+ _hDrive = CreateFile(path, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (_hDrive != INVALID_HANDLE_VALUE) {
_boot_sector.BytesPerSector = 512;
reactos/subsys/system/explorer/taskbar
diff -N favorites.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ favorites.cpp 4 Apr 2004 16:04:34 -0000 1.1
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2004 Martin Fuchs
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+ //
+ // Explorer and Desktop clone
+ //
+ // favorites.cpp
+ //
+ // Martin Fuchs, 04.04.2004
+ //
+
+
+#include "../utility/utility.h"
+
+#include "../explorer.h"
+#include "../globals.h"
+
+#include "startmenu.h"
+
+
+ /// read .URL file
+bool Bookmark::read_url(LPCTSTR path)
+{
+ char line[BUFFER_LEN];
+
+ tifstream in(path);
+
+ while(in.good()) {
+ in.getline(line, BUFFER_LEN);
+
+ const char* p = line;
+ while(isspace(*p))
+ ++p;
+
+ const char* keyword = p;
+ const char* eq = strchr(p, '=');
+
+ if (eq) {
+ const char* cont = eq + 1;
+ while(isspace(*cont))
+ ++cont;
+
+ if (!strnicmp(keyword, "URL", 3))
+ _url = cont;
+ else if (!strnicmp(keyword, "IconFile", 8))
+ _icon_path = cont;
+ }
+ }
+
+ return true;
+}
+
+ /// convert XBEL bookmark node
+bool Bookmark::read_xbel(const_XMLPos& pos)
+{
+ _url = pos.get("href");
+
+ if (!pos.go_down("title"))
+ return false;
+
+ _name = pos->get_content();
+
+ pos.back();
+
+ return true;
+}
+
+
+BookmarkNode::BookmarkNode(const Bookmark& bm)
+ : _type(BMNT_BOOKMARK)
+{
+ _pbookmark = new Bookmark(bm);
+}
+
+BookmarkNode::BookmarkNode(const BookmarkFolder& bmf)
+ : _type(BMNT_FOLDER)
+{
+ _pfolder = new BookmarkFolder(bmf);
+}
+
+BookmarkNode::BookmarkNode(const BookmarkNode& other)
+ : _type(other._type)
+{
+ if (_type == BMNT_BOOKMARK)
+ _pbookmark = new Bookmark(*other._pbookmark);
+ else
+ _pfolder = new BookmarkFolder(*other._pfolder);
+}
+
+BookmarkNode::~BookmarkNode()
+{
+ if (_type == BMNT_BOOKMARK)
+ delete _pbookmark;
+ else
+ delete _pfolder;
+}
+
+
+ /// read bookmark list from XBEL formated XML tree
+void BookmarkList::read(const_XMLPos& pos)
+{
+ const XMLNode::Children& children = pos->get_children();
+
+ for(XMLNode::Children::const_iterator it=children.begin(); it!=children.end(); ++it) {
+ const XMLNode& node = **it;
+ const_XMLPos sub_pos(&node);
+
+ if (node == "folder") {
+ BookmarkFolder new_folder;
+
+ if (sub_pos.go_down("title")) {
+ new_folder._name = sub_pos->get_content();
+ sub_pos.back();
+ }
+
+ new_folder._bookmarks.read(sub_pos);
+
+ push_back(new_folder);
+ } else if (node == "bookmark") {
+ Bookmark bookmark;
+
+ if (bookmark.read_xbel(sub_pos))
+ push_back(bookmark);
+ }
+ }
+}
+
+ /// write bookmark list into XBEL formated XML tree
+void BookmarkList::write(XMLPos& pos) const
+{
+ for(const_iterator it=begin(); it!=end(); ++it) {
+ const BookmarkNode& node = *it;
+
+ if (node._type == BookmarkNode::BMNT_FOLDER) {
+ BookmarkFolder& folder = *node._pfolder;
+
+ pos.create("folder");
+
+ pos.create("title");
+ pos->set_content(folder._name);
+ pos.back();
+
+ folder._bookmarks.write(pos);
+
+ pos.back();
+ } else { // node._type == BookmarkNode::BMNT_BOOKMARK
+ Bookmark& bookmark = *node._pbookmark;
+
+ if (!bookmark._url.empty()) {
+ pos.create("bookmark");
+
+ pos["href"] = bookmark._url;
+
+ pos.create("title");
+ pos->set_content(bookmark._name);
+ pos.back();
+
+ pos.back();
+ }
+ }
+ }
+}
+
+
+void BookmarkList::import_IE_favorites(ShellDirectory& dir, HWND hwnd)
+{
+ TCHAR path[MAX_PATH], ext[_MAX_EXT];
+
+ dir.smart_scan(SCAN_FILESYSTEM);
+
+ for(Entry*entry=dir._down; entry; entry=entry->_next) {
+ if (entry->_shell_attribs & SFGAO_HIDDEN) // hide files like "desktop.ini"
+ continue;
+
+ String name;
+
+ if (entry->_etype == ET_SHELL)
+ name = dir._folder.get_name(static_cast<ShellEntry*>(entry)->_pidl);
+ else
+ name = entry->_display_name;
+
+ if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ BookmarkFolder new_folder;
+
+ new_folder._name = name;
+
+ if (entry->_etype == ET_SHELL) {
+ ShellDirectory new_dir(dir._folder, static_cast<ShellEntry*>(entry)->_pidl, hwnd);
+ new_folder._bookmarks.import_IE_favorites(new_dir, hwnd);
+ } else {
+ entry->get_path(path);
+ ShellDirectory new_dir(GetDesktopFolder(), path, hwnd);
+ new_folder._bookmarks.import_IE_favorites(new_dir, hwnd);
+ }
+
+ push_back(new_folder);
+ } else {
+ Bookmark bookmark;
+
+ bookmark._name = name;
+
+ entry->get_path(path);
+ _tsplitpath(path, NULL, NULL, NULL, ext);
+
+ if (!_tcsicmp(ext, TEXT(".url"))) {
+ bookmark.read_url(path);
+ push_back(bookmark);
+ } else {
+ ///@todo read shell links
+ assert(0);
+ }
+ }
+ }
+}
+
+
+ /// read XBEL bookmark file
+bool Favorites::read(LPCTSTR path)
+{
+ XMLDoc xbel;
+
+ if (!xbel.read(path))
+ return false;
+
+ const_XMLPos pos(&xbel);
+
+ if (!pos.go_down("xbel"))
+ return false;
+
+ super::read(pos);
+
+ pos.back();
+
+ return true;
+}
+
+ /// write XBEL bookmark file
+void Favorites::write(LPCTSTR path) const
+{
+ XMLDoc xbel;
+
+ XMLPos pos(&xbel);
+ pos.create("xbel");
+ super::write(pos);
+ pos.back();
+
+ xbel.write(path, XMLNode::FORMAT_SMART, XMLHeader("1.0", "UTF-8", "<!DOCTYPE xbel"
+ " PUBLIC \"+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML\"\n"
+ " \"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">"));
+}
+
+ /// import Internet Explorer bookmarks from Favorites folder
+bool Favorites::import_IE_favorites(HWND hwnd)
+{
+ WaitCursor wait;
+
+ StartMenuShellDirs dirs;
+
+ try {
+ dirs.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_COMMON_FAVORITES, hwnd), hwnd));
+ dirs.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_FAVORITES, hwnd), hwnd));
+ } catch(COMException&) {
+ }
+
+ for(StartMenuShellDirs::iterator it=dirs.begin(); it!=dirs.end(); ++it) {
+ StartMenuDirectory& smd = *it;
+ ShellDirectory& dir = smd._dir;
+
+ try {
+ super::import_IE_favorites(dir, hwnd);
+ } catch(COMException&) {
+ }
+ }
+
+ return true;
+}
reactos/subsys/system/explorer/taskbar
diff -N favorites.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ favorites.h 4 Apr 2004 16:04:34 -0000 1.1
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2004 Martin Fuchs
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+ //
+ // Explorer and Desktop clone
+ //
+ // favorites.h
+ //
+ // Martin Fuchs, 04.04.2004
+ //
+
+
+struct Bookmark
+{
+ Bookmark() : _icon_idx(0) {}
+
+ String _name;
+ String _url;
+ String _description;
+ String _icon_path;
+ int _icon_idx;
+
+ bool read_url(LPCTSTR path);
+ bool read_xbel(const_XMLPos& pos);
+};
+
+struct BookmarkFolder;
+
+struct BookmarkNode
+{
+ BookmarkNode(const Bookmark& bm);
+ BookmarkNode(const BookmarkFolder& bmf);
+ BookmarkNode(const BookmarkNode& other);
+ ~BookmarkNode();
+
+ enum BOOKMARKNODE_TYPE {
+ BMNT_BOOKMARK, BMNT_FOLDER
+ };
+
+ BOOKMARKNODE_TYPE _type;
+
+ union {
+ Bookmark* _pbookmark;
+ BookmarkFolder* _pfolder;
+ };
+};
+
+struct BookmarkList : public list<BookmarkNode>
+{
+ void import_IE_favorites(struct ShellDirectory& dir, HWND hwnd);
+
+ void read(const_XMLPos& pos);
+ void write(XMLPos& pos) const;
+};
+
+struct BookmarkFolder
+{
+ String _name;
+ String _description;
+ BookmarkList _bookmarks;
+};
+
+struct Favorites : public BookmarkList
+{
+ typedef BookmarkList super;
+
+ bool read(LPCTSTR path);
+ void write(LPCTSTR path) const;
+
+ bool import_IE_favorites(HWND hwnd);
+};
reactos/subsys/system/explorer/taskbar
diff -u -r1.83 -r1.84
--- startmenu.cpp 20 Mar 2004 13:49:12 -0000 1.83
+++ startmenu.cpp 4 Apr 2004 16:04:34 -0000 1.84
@@ -1616,7 +1616,7 @@
break;
case IDC_FAVORITES:
- CreateSubmenu(id, CSIDL_FAVORITES, ResString(IDS_FAVORITES));
+ CreateSubmenu(id, CSIDL_COMMON_FAVORITES, CSIDL_FAVORITES, ResString(IDS_FAVORITES));
break;
case IDC_BROWSE:
reactos/subsys/system/explorer/taskbar
diff -u -r1.55 -r1.56
--- traynotify.cpp 28 Mar 2004 22:17:48 -0000 1.55
+++ traynotify.cpp 4 Apr 2004 16:04:34 -0000 1.56
@@ -259,11 +259,11 @@
// write notification icon settings to XML configuration file
XMLPos pos = g_Globals.get_cfg();
- pos.create("desktopbar");
+ pos.smart_create("desktopbar");
XMLBoolRef(pos, "options", "show-clock") = _hwndClock!=0;
pos.back();
- pos.create("notify-icons");
+ pos.smart_create("notify-icons");
XMLBoolRef(pos, "options", "hide-inactive") = _hide_inactive;
XMLBoolRef(pos, "options", "show-hidden") = _show_hidden;
@@ -272,7 +272,7 @@
NotifyIconConfig& cfg = *it;
// search for the corresponding node using the original name
- pos.create("icon", "name", cfg._name);
+ pos.smart_create("icon", "name", cfg._name);
// refresh unique name
cfg.create_name();
@@ -293,7 +293,7 @@
if (vis != flag) {
if (flag) {
- // create clock window
+ // smart_create clock window
_hwndClock = ClockWindow::Create(_hwnd);
if (_hwndClock) {
reactos/subsys/system/explorer/utility
diff -u -r1.5 -r1.6
--- xmlstorage.cpp 28 Mar 2004 12:00:46 -0000 1.5
+++ xmlstorage.cpp 4 Apr 2004 16:04:34 -0000 1.6
@@ -54,6 +54,34 @@
}
+ /// read XML stream into XML tree below _pos
+XML_Status XMLReader::read(std::istream& in)
+{
+ XML_Status status = XML_STATUS_OK;
+
+ while(in.good() && status==XML_STATUS_OK) {
+ char* buffer = (char*) XML_GetBuffer(_parser, BUFFER_LEN);
+
+ in.read(buffer, BUFFER_LEN);
+
+ status = XML_ParseBuffer(_parser, in.gcount(), false);
+ }
+
+ if (status != XML_STATUS_ERROR)
+ status = XML_ParseBuffer(_parser, 0, true);
+
+/*
+ if (status == XML_STATUS_ERROR)
+ cerr << get_error_string();
+*/
+
+ _pos->append_trailing(_content.c_str(), _content.length());
+ _content.erase();
+
+ return status;
+}
+
+
/// store XML version and encoding into XML reader
void XMLCALL XMLReader::XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone)
{
@@ -65,12 +93,31 @@
}
}
- /// notifications about XML tag start
+ /// notifications about XML start tag
void XMLCALL XMLReader::XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts)
{
XMLReader* pThis = (XMLReader*) userData;
- XMLNode* node = new XMLNode(String_from_XML_Char(name));
+ // search for end of first line
+ const char* s = pThis->_content.c_str();
+ const char* p = s;
+ const char* e = p + pThis->_content.length();
+
+ for(; p<e; ++p)
+ if (*p == '\n') {
+ ++p;
+ break;
+ }
+
+ if (p != s)
+ pThis->_pos->append_trailing(s, p-s);
+
+ std::string leading;
+
+ if (p != e)
+ leading.assign(p, e-p);
+
+ XMLNode* node = new XMLNode(String_from_XML_Char(name), leading);
pThis->_pos.add_down(node);
@@ -81,17 +128,41 @@
(*node)[String_from_XML_Char(attr_name)] = String_from_XML_Char(attr_value);
}
- pThis->_in_tag = true;
+ pThis->_in_node = true;
+ pThis->_content.erase();
}
- /// notifications about XML tag end
+ /// notifications about XML end tag
void XMLCALL XMLReader::XML_EndElementHandler(void* userData, const XML_Char* name)
{
XMLReader* pThis = (XMLReader*) userData;
+ // search for end of first line
+ const char* s = pThis->_content.c_str();
+ const char* p = s;
+ const char* e = p + pThis->_content.length();
+
+ for(; p<e; ++p)
+ if (*p == '\n') {
+ ++p;
+ break;
+ }
+
+ if (p != s)
+ pThis->_pos->append_content(s, p-s);
+
+ std::string leading;
+
+ if (p != e)
+ leading.assign(p, e-p);
+
+ if (leading.empty())
+ pThis->_pos->_end_leading = leading;
+
pThis->_pos.back();
- pThis->_in_tag = false;
+ pThis->_in_node = false;
+ pThis->_content.erase();
}
/// store content, white space and comments
@@ -99,14 +170,11 @@
{
XMLReader* pThis = (XMLReader*) userData;
- if (pThis->_in_tag)
- pThis->_pos->append_content(s, len);
- else
- pThis->_pos->append_trailing(s, len);
+ pThis->_content.append(s, len);
}
-std::string XMLString(LPCTSTR s)
+std::string EncodeXMLString(LPCTSTR s)
{
TCHAR buffer[BUFFER_LEN];
LPTSTR o = buffer;
@@ -132,22 +200,46 @@
return get_utf8(buffer, o-buffer);
}
+String DecodeXMLString(LPCTSTR s)
+{
+ TCHAR buffer[BUFFER_LEN];
+ LPTSTR o = buffer;
+
+ for(LPCTSTR p=s; *p; ++p)
+ if (*p == '&') {
+ if (!_tcsnicmp(p+1, TEXT("amp;"), 4)) {
+ *o++ = '&';
+ p += 4;
+ } else if (!_tcsnicmp(p+1, TEXT("lt;"), 3)) {
+ *o++ = '<';
+ p += 3;
+ } else if (!_tcsnicmp(p+1, TEXT("gt;"), 3)) {
+ *o++ = '>';
+ p += 3;
+ } else
+ *o++ = *p;
+ } else
+ *o++ = *p;
+
+ return String(buffer, o-buffer);
+}
+
/// write node with children tree to output stream using original white space
-void XMLNode::write_worker(std::ostream& out, WRITE_MODE mode, int indent) const
+void XMLNode::write_worker(std::ostream& out, int indent) const
{
- out << '<' << XMLString(*this);
+ out << _leading << '<' << EncodeXMLString(*this);
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
- out << ' ' << XMLString(it->first) << "=\"" << XMLString(it->second) << "\"";
+ out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
if (!_children.empty() || !_content.empty()) {
out << '>' << _content;
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
- (*it)->write_worker(out, mode, indent+1);
+ (*it)->write_worker(out, indent+1);
- out << "</" << XMLString(*this) << '>';
+ out << _end_leading << "</" << EncodeXMLString(*this) << '>';
} else
out << "/>";
@@ -156,81 +248,73 @@
/// pretty print node with children tree to output stream
-void XMLNode::pretty_write_worker(std::ostream& out, WRITE_MODE mode, int indent) const
+void XMLNode::pretty_write_worker(std::ostream& out, int indent) const
{
for(int i=indent; i--; )
out << XML_INDENT_SPACE;
- out << '<' << XMLString(*this);
+ out << '<' << EncodeXMLString(*this);
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
- out << ' ' << XMLString(it->first) << "=\"" << XMLString(it->second) << "\"";
+ out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
if (!_children.empty() || !_content.empty()) {
out << ">\n";
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
- (*it)->pretty_write_worker(out, mode, indent+1);
+ (*it)->pretty_write_worker(out, indent+1);
for(int i=indent; i--; )
out << XML_INDENT_SPACE;
- out << "</" << XMLString(*this) << ">\n";
+ out << "</" << EncodeXMLString(*this) << ">\n";
} else
out << "/>\n";
}
-
/// write node with children tree to output stream using smart formating
-bool XMLNode::smart_write_worker(std::ostream& out, int indent, bool next_format) const
+void XMLNode::smart_write_worker(std::ostream& out, int indent) const
{
- bool format_pre, format_mid, format_post;
-
- format_pre = next_format;
- format_mid = _content.empty();
- format_post = _trailing.empty();
-
- if (format_pre)
+ if (_leading.empty())
for(int i=indent; i--; )
out << XML_INDENT_SPACE;
+ else
+ out << _leading;
- out << '<' << XMLString(*this);
+ out << '<' << EncodeXMLString(*this);
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
- out << ' ' << XMLString(it->first) << "=\"" << XMLString(it->second) << "\"";
+ out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
if (!_children.empty() || !_content.empty()) {
out << '>';
- if (format_mid)
+ if (_content.empty())
out << '\n';
else
out << _content;
Children::const_iterator it = _children.begin();
- if (it != _children.end()) {
- next_format = (*it)->_content.empty() && (*it)->_trailing.empty();
-
+ if (it != _children.end())
for(; it!=_children.end(); ++it)
- next_format = (*it)->smart_write_worker(out, indent+1, next_format);
- }
+ (*it)->smart_write_worker(out, indent+1);
- if (next_format)
+ if (_end_leading.empty())
for(int i=indent; i--; )
out << XML_INDENT_SPACE;
+ else
+ out << _end_leading;
- out << "</" << XMLString(*this) << '>';
+ out << "</" << EncodeXMLString(*this) << '>';
} else
out << "/>";
- if (format_post)
+ if (_trailing.empty())
out << '\n';
else
out << _trailing;
-
- return format_post;
}
reactos/subsys/system/explorer/utility
diff -u -r1.10 -r1.11
--- xmlstorage.h 28 Mar 2004 22:17:49 -0000 1.10
+++ xmlstorage.h 4 Apr 2004 16:04:34 -0000 1.11
@@ -47,7 +47,7 @@
#include <windows.h> // for LPCTSTR
#ifdef UNICODE
-#define _UNICODE
+#define _UNICODE
#endif
#include <tchar.h>
@@ -202,11 +202,74 @@
return get_utf8(s.c_str(), s.length());
}
-extern std::string XMLString(LPCTSTR s);
+extern std::string EncodeXMLString(LPCTSTR s);
+extern String DecodeXMLString(LPCTSTR s);
+
+
+#ifdef __GNUC__
+#include <ext/stdio_filebuf.h>
+typedef __gnu_cxx::stdio_filebuf<char> STDIO_FILEBUF;
+#else
+typedef std::filebuf STDIO_FILEBUF;
+#endif
+
+struct tifstream : public std::istream
+{
+ typedef std::istream super;
+
+ tifstream(LPCTSTR path)
+ : super(&_buf),
+ _pfile(_tfopen(path, TEXT("r"))),
+#ifdef __GNUC__
+ _buf(_pfile, ios::in)
+#else
+ _buf(_pfile)
+#endif
+ {
+ }
+
+ ~tifstream()
+ {
+ if (_pfile)
+ fclose(_pfile);
+ }
+
+protected:
+ FILE* _pfile;
+ STDIO_FILEBUF _buf;
+};
+
+struct tofstream : public std::ostream
+{
+ typedef std::ostream super;
+
+ tofstream(LPCTSTR path)
+ : super(&_buf),
+ _pfile(_tfopen(path, TEXT("w"))),
+#ifdef __GNUC__
+ _buf(_pfile, ios::out)
+#else
+ _buf(_pfile)
+#endif
+ {
+ }
+
+ ~tofstream()
+ {
+ flush();
+
+ if (_pfile)
+ fclose(_pfile);
+ }
+
+protected:
+ FILE* _pfile;
+ STDIO_FILEBUF _buf;
+};
// write XML files with 2 spaces indenting
-#define XML_INDENT_SPACE " "
+#define XML_INDENT_SPACE " "
#ifdef XML_UNICODE // Are XML_Char strings UTF-16 encoded?
@@ -279,6 +342,7 @@
// access to protected class members for XMLPos and XMLReader
friend struct XMLPos;
+ friend struct const_XMLPos;
friend struct XMLReader;
XMLNode(const String& name)
@@ -286,9 +350,17 @@
{
}
+ XMLNode(const String& name, const std::string& leading)
+ : String(name),
+ _leading(leading)
+ {
+ }
+
XMLNode(const XMLNode& other)
: _attributes(other._attributes),
+ _leading(other._leading),
_content(other._content),
+ _end_leading(other._end_leading),
_trailing(other._trailing)
{
for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
@@ -312,7 +384,9 @@
_attributes = other._attributes;
+ _leading = other._leading;
_content = other._content;
+ _end_leading = other._end_leading;
_trailing = other._trailing;
return *this;
@@ -401,10 +475,24 @@
return _children;
}
+ String get_content() const
+ {
+ String ret;
+
+ assign_utf8(ret, _content.c_str());
+
+ return DecodeXMLString(ret);
+ }
+
+ void set_content(const String& s)
+ {
+ _content.assign(EncodeXMLString(s));
+ }
+
enum WRITE_MODE {
FORMAT_SMART = 0, /// preserve original white space and comments if present; pretty print otherwise
FORMAT_ORIGINAL = 1, /// write XML stream preserving original white space and comments
- FORMAT_PRETTY = 2 /// pretty print node to stream without preserving original white space
+ FORMAT_PRETTY = 2 /// pretty print node to stream without preserving original white space
};
/// write node with children tree to output stream
@@ -412,15 +500,15 @@
{
switch(mode) {
case FORMAT_PRETTY:
- pretty_write_worker(out, mode, indent);
+ pretty_write_worker(out, indent);
break;
case FORMAT_ORIGINAL:
- write_worker(out, mode, indent);
+ write_worker(out, indent);
break;
default: // FORMAT_SMART
- smart_write_worker(out, indent, _content.empty() && _trailing.empty());
+ smart_write_worker(out, indent);
}
return out;
@@ -430,8 +518,10 @@
Children _children;
AttributeMap _attributes;
- std::string _content;
- std::string _trailing;
+ std::string _leading;
+ std::string _content;
+ std::string _end_leading;
+ std::string _trailing;
XMLNode* get_first_child() const
{
@@ -488,10 +578,10 @@
void append_content(const char* s, int l)
{
- if (_children.empty())
+ //if (_children.empty())
_content.append(s, l);
- else
- _children.back()->_content.append(s, l);
+ //else
+ // _children.back()->_content.append(s, l);
}
void append_trailing(const char* s, int l)
@@ -502,9 +592,9 @@
_children.back()->_trailing.append(s, l);
}
- void write_worker(std::ostream& out, WRITE_MODE mode, int indent) const;
- void pretty_write_worker(std::ostream& out, WRITE_MODE mode, int indent) const;
- bool smart_write_worker(std::ostream& out, int indent, bool next_format) const;
+ 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;
};
@@ -606,6 +696,104 @@
};
+ /// read only iterator access to children nodes with name filtering
+struct const_XMLChildrenFilter
+{
+ const_XMLChildrenFilter(const XMLNode::Children& children, const String& name)
+ : _begin(children.begin(), children.end(), name),
+ _end(children.end(), children.end(), name)
+ {
+ }
+
+ const_XMLChildrenFilter(const XMLNode* node, const String& name)
+ : _begin(node->get_children().begin(), node->get_children().end(), name),
+ _end(node->get_children().end(), node->get_children().end(), name)
+ {
+ }
+
+ struct const_iterator
+ {
+ typedef XMLNode::Children::const_iterator BaseIterator;
+
+ const_iterator(BaseIterator begin, BaseIterator end, const String& filter_name)
+ : _cur(begin),
+ _end(end),
+ _filter_name(filter_name)
+ {
+ search_next();
+ }
+
+ operator BaseIterator()
+ {
+ return _cur;
+ }
+
+ const XMLNode* operator*() const
+ {
+ return *_cur;
+ }
+
+ XMLNode* operator*()
+ {
+ return *_cur;
+ }
+
+ const_iterator& operator++()
+ {
+ ++_cur;
+ search_next();
+
+ return *this;
+ }
+
+ const_iterator operator++(int)
+ {
+ const_iterator ret = *this;
+
+ ++_cur;
+ search_next();
+
+ return ret;
+ }
+
+ bool operator==(const BaseIterator& other) const
+ {
+ return _cur == other;
+ }
+
+ bool operator!=(const BaseIterator& other) const
+ {
+ return _cur != other;
+ }
+
+ protected:
+ BaseIterator _cur;
+ BaseIterator _end;
+ String _filter_name;
+
+ void search_next()
+ {
+ while(_cur!=_end && **_cur!=_filter_name)
+ ++_cur;
+ }
+ };
+
+ const_iterator begin()
+ {
+ return _begin;
+ }
+
+ const_iterator end()
+ {
+ return _end;
+ }
+
+protected:
+ const_iterator _begin;
+ const_iterator _end;
+};
+
+
/// iterator for XML trees
struct XMLPos
{
@@ -622,8 +810,8 @@
}
/// access to current node
- operator XMLNode*() {return _cur;}
operator const XMLNode*() const {return _cur;}
+ operator XMLNode*() {return _cur;}
const XMLNode* operator->() const {return _cur;}
XMLNode* operator->() {return _cur;}
@@ -632,8 +820,8 @@
XMLNode& operator*() {return *_cur;}
/// attribute access
- String& operator[](const String& attr_name) {return (*_cur)[attr_name];}
template<typename T> String get(const T& attr_name) const {return (*_cur)[attr_name];}
+ String& operator[](const String& attr_name) {return (*_cur)[attr_name];}
/// insert children when building tree
void add_down(XMLNode* child)
@@ -680,9 +868,15 @@
/// move X-Path like to position in XML tree
bool go(const char* path);
- /// create node if not already existing and move to it
+ /// create node and move to it
void create(const String& name)
{
+ add_down(new XMLNode(name));
+ }
+
+ /// create node if not already existing and move to it
+ void smart_create(const String& name)
+ {
XMLNode* node = _cur->find_first(name);
if (node)
@@ -692,7 +886,7 @@
}
/// search matching child node identified by key name and an attribute value
- void create(const String& name, const String& attr_name, const String& attr_value)
+ void smart_create(const String& name, const String& attr_name, const String& attr_value)
{
XMLNode* node = _cur->find_first(name, attr_name, attr_value);
@@ -718,9 +912,15 @@
return false;
}
- /// create node if not already existing and move to it
+ /// create node and move to it
void create(const char* name)
{
+ add_down(new XMLNode(name));
+ }
+
+ /// create node if not already existing and move to it
+ void smart_create(const char* name)
+ {
XMLNode* node = _cur->find_first(name);
if (node)
@@ -731,7 +931,7 @@
/// search matching child node identified by key name and an attribute value
template<typename T, typename U>
- void create(const char* name, const T& attr_name, const U& attr_value)
+ void smart_create(const char* name, const T& attr_name, const U& attr_value)
{
XMLNode* node = _cur->find_first(name, attr_name, attr_value);
@@ -759,6 +959,97 @@
};
+ /// iterator for XML trees
+struct const_XMLPos
+{
+ const_XMLPos(const XMLNode* root)
+ : _root(root),
+ _cur(root)
+ {
+ }
+
+ const_XMLPos(const const_XMLPos& other)
+ : _root(other._root),
+ _cur(other._cur)
+ { // don't copy _stack
+ }
+
+ /// access to current node
+ operator const XMLNode*() const {return _cur;}
+
+ const XMLNode* operator->() const {return _cur;}
+
+ const XMLNode& operator*() const {return *_cur;}
+
+ /// attribute access
+ template<typename T> String get(const T& attr_name) const {return _cur->get(attr_name);}
+
+ /// go back to previous position
+ bool back()
+ {
+ if (!_stack.empty()) {
+ _cur = _stack.top();
+ _stack.pop();
+ return true;
+ } else
+ return false;
+ }
+
+ /// go down to first child
+ bool go_down()
+ {
+ const XMLNode* node = _cur->get_first_child();
+
+ if (node) {
+ go_to(node);
+ return true;
+ } else
+ return false;
+ }
+
+ /// search for child and go down
+ bool go_down(const String& name)
+ {
+ XMLNode* node = _cur->find_first(name);
+
+ if (node) {
+ go_to(node);
+ return true;
+ } else
+ return false;
+ }
+
+ /// move X-Path like to position in XML tree
+ bool go(const char* path);
+
+#ifdef UNICODE
+ /// search for child and go down
+ bool go_down(const char* name)
+ {
+ XMLNode* node = _cur->find_first(name);
+
+ if (node) {
+ go_to(node);
+ return true;
+ } else
+ return false;
+ }
+#endif
+
+protected:
+ const XMLNode* _root;
+ const XMLNode* _cur;
+ std::stack<const XMLNode*> _stack;
+
+ /// go to specified node
+ void go_to(const XMLNode* child)
+ {
+ _stack.push(_cur);
+ _cur = child;
+ }
+};
+
+
struct XMLBool
{
XMLBool(bool value)
@@ -789,6 +1080,11 @@
return _value;
}
+ bool operator!() const
+ {
+ return !_value;
+ }
+
operator LPCTSTR() const
{
return _value? TEXT("TRUE"): TEXT("FALSE");
@@ -798,7 +1094,7 @@
bool _value;
private:
- void operator=(const XMLBool&); // disallow assignment operations
+ void operator=(const XMLBool&); // disallow assignment operations
};
struct XMLBoolRef
@@ -815,6 +1111,11 @@
return !_tcsicmp(_ref, TEXT("TRUE"));
}
+ bool operator!() const
+ {
+ return _tcsicmp(_ref, TEXT("TRUE"))? true: false;
+ }
+
XMLBoolRef& operator=(bool value)
{
assign(value);
@@ -833,7 +1134,7 @@
}
protected:
- String& _ref;
+ String& _ref;
};
@@ -875,10 +1176,10 @@
}
protected:
- int _value;
+ int _value;
private:
- void operator=(const XMLBool&); // disallow assignment operations
+ void operator=(const XMLBool&); // disallow assignment operations
};
struct XMLNumberRef
@@ -911,7 +1212,7 @@
}
protected:
- String& _ref;
+ String& _ref;
};
@@ -931,7 +1232,7 @@
XML_SetElementHandler(_parser, XML_StartElementHandler, XML_EndElementHandler);
XML_SetDefaultHandler(_parser, XML_DefaultHandler);
- _in_tag = false;
+ _in_node = false;
}
~XMLReader()
@@ -939,28 +1240,7 @@
XML_ParserFree(_parser);
}
- XML_Status read(std::istream& in)
- {
- XML_Status status = XML_STATUS_OK;
-
- while(in.good() && status==XML_STATUS_OK) {
- char* buffer = (char*) XML_GetBuffer(_parser, BUFFER_LEN);
-
- in.read(buffer, BUFFER_LEN);
-
- status = XML_ParseBuffer(_parser, in.gcount(), false);
- }
-
- if (status != XML_STATUS_ERROR)
- status = XML_ParseBuffer(_parser, 0, true);
-
- /*
- if (status == XML_STATUS_ERROR)
- cerr << path << get_error_string();
- */
-
- return status;
- }
+ XML_Status read(std::istream& in);
std::string get_position() const
{
@@ -986,9 +1266,11 @@
protected:
XMLPos _pos;
XML_Parser _parser;
- std::string _xml_version;
- std::string _encoding;
- bool _in_tag;
+ std::string _xml_version;
+ std::string _encoding;
+
+ std::string _content;
+ bool _in_node;
static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone);
static void XMLCALL XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts);
@@ -997,6 +1279,29 @@
};
+struct XMLHeader : public std::string
+{
+ XMLHeader(const std::string& xml_version="1.0", const std::string& encoding="UTF-8", const std::string& doctype="")
+ : _version(xml_version),
+ _encoding(encoding),
+ _doctype(doctype)
+ {
+ }
+
+ void print(std::ostream& out) const
+ {
+ out << "<?xml version=\"" << _version << "\" encoding=\"" << _encoding << "\"?>\n";
+
+ if (!_doctype.empty())
+ out << _doctype << '\n';
+ }
+
+ std::string _version;
+ std::string _encoding;
+ std::string _doctype;
+};
+
+
struct XMLDoc : public XMLNode
{
XMLDoc()
@@ -1004,7 +1309,7 @@
{
}
- XMLDoc(const std::string& path)
+ XMLDoc(LPCTSTR path)
: XMLNode("")
{
read(path);
@@ -1012,23 +1317,33 @@
std::istream& read(std::istream& in)
{
- XMLReader(this).read(in);
+ XMLReader reader(this);
+ /*XML_Status status = */reader.read(in);
+/*
+ if (status == XML_STATUS_ERROR)
+ cerr << reader.get_error_string();
+*/
return in;
}
- bool read(const std::string& path)
+ bool read(LPCTSTR path)
{
- std::ifstream in(path.c_str());
+ tifstream in(path);
+ XMLReader reader(this);
- return XMLReader(this).read(in) != XML_STATUS_ERROR;
+ XML_Status status = reader.read(in);
+/*
+ if (status == XML_STATUS_ERROR)
+ cerr << path << reader.get_error_string();
+*/
+ return status != XML_STATUS_ERROR;
}
/// write XML stream preserving previous white space and comments
- std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART,
- const std::string& xml_version="1.0", const std::string& encoding="UTF-8") const
+ std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART, const XMLHeader& header=XMLHeader()) const
{
- out << "<?xml version=\"" << xml_version << "\" encoding=\"" << encoding << "\"?>\n";
+ header.print(out);
if (!_children.empty())
_children.front()->write(out);
@@ -1042,17 +1357,16 @@
return write(out, FORMAT_PRETTY);
}
- void write(const std::string& path, WRITE_MODE mode=FORMAT_SMART,
- const std::string& xml_version="1.0", const std::string& encoding="UTF-8") const
+ void write(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART, const XMLHeader& header=XMLHeader()) const
{
- std::ofstream out(path.c_str());
+ tofstream out(path);
- write(out, mode, xml_version, encoding);
+ write(out, mode, header);
}
- void write_formating(const std::string& path) const
+ void write_formating(LPCTSTR path) const
{
- std::ofstream out(path.c_str());
+ tofstream out(path);
write_formating(out);
}
CVSspam 0.2.8