mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
import IE bookmarks and convert into XBEL format bookmark file
svn path=/trunk/; revision=8964
This commit is contained in:
parent
4eb5cb108b
commit
776c1e9696
16 changed files with 929 additions and 131 deletions
|
@ -31,6 +31,7 @@ exe explorer :
|
||||||
taskbar/startmenu.cpp
|
taskbar/startmenu.cpp
|
||||||
taskbar/taskbar.cpp
|
taskbar/taskbar.cpp
|
||||||
taskbar/traynotify.cpp
|
taskbar/traynotify.cpp
|
||||||
|
taskbar/favorites.cpp
|
||||||
desktop/desktop.cpp
|
desktop/desktop.cpp
|
||||||
# utility/splitpath.c
|
# utility/splitpath.c
|
||||||
utility/dragdropimpl.cpp
|
utility/dragdropimpl.cpp
|
||||||
|
|
|
@ -99,6 +99,7 @@ OBJECTS = \
|
||||||
startmenu.o \
|
startmenu.o \
|
||||||
traynotify.o \
|
traynotify.o \
|
||||||
quicklaunch.o \
|
quicklaunch.o \
|
||||||
|
favorites.o \
|
||||||
searchprogram.o \
|
searchprogram.o \
|
||||||
settings.o \
|
settings.o \
|
||||||
i386-stub-win32.o \
|
i386-stub-win32.o \
|
||||||
|
|
|
@ -68,6 +68,7 @@ OBJECTS = \
|
||||||
startmenu.o \
|
startmenu.o \
|
||||||
traynotify.o \
|
traynotify.o \
|
||||||
quicklaunch.o \
|
quicklaunch.o \
|
||||||
|
favorites.o \
|
||||||
searchprogram.o \
|
searchprogram.o \
|
||||||
settings.o \
|
settings.o \
|
||||||
i386-stub-win32.o \
|
i386-stub-win32.o \
|
||||||
|
|
|
@ -39,6 +39,7 @@ CPP_SRCS = \
|
||||||
taskbar/startmenu.cpp \
|
taskbar/startmenu.cpp \
|
||||||
taskbar/traynotify.cpp \
|
taskbar/traynotify.cpp \
|
||||||
taskbar/quicklaunch.cpp \
|
taskbar/quicklaunch.cpp \
|
||||||
|
taskbar/favorites.cpp \
|
||||||
dialogs/searchprogram.cpp \
|
dialogs/searchprogram.cpp \
|
||||||
dialogs/settings.cpp
|
dialogs/settings.cpp
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td><address style="align: right;"><small>
|
<td><address style="align: right;"><small>
|
||||||
ROS Explorer Source Code Documentation
|
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>
|
<img src="doxygen.png" alt="doxygen" align="middle" border=0>
|
||||||
</small></address>
|
</small></address>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -82,27 +82,31 @@ void ExplorerGlobals::init(HINSTANCE hInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ExplorerGlobals::read_cfg()
|
void ExplorerGlobals::read_persistent()
|
||||||
{
|
{
|
||||||
// read configuration file
|
// read configuration file
|
||||||
_cfg_dir.printf(TEXT("%s\\ReactOS"), (LPCTSTR)SpecialFolderFSPath(CSIDL_APPDATA,0));
|
_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))
|
if (!_cfg.read(_cfg_path))
|
||||||
return true;
|
_cfg.read(TEXT("explorer-cfg-template.xml"));
|
||||||
|
|
||||||
if (_cfg.read("explorer-cfg-template.xml"))
|
// read bookmarks
|
||||||
return true;
|
_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
|
// write configuration file
|
||||||
RecursiveCreateDirectory(_cfg_dir);
|
RecursiveCreateDirectory(_cfg_dir);
|
||||||
|
|
||||||
_cfg.write(_cfg_path);
|
_cfg.write(_cfg_path);
|
||||||
|
_favorites.write(_favorites_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,7 +114,7 @@ XMLPos ExplorerGlobals::get_cfg()
|
||||||
{
|
{
|
||||||
XMLPos pos(&_cfg);
|
XMLPos pos(&_cfg);
|
||||||
|
|
||||||
pos.create("explorer-cfg");
|
pos.smart_create("explorer-cfg");
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@ -119,8 +123,8 @@ XMLPos ExplorerGlobals::get_cfg(const String& name)
|
||||||
{
|
{
|
||||||
XMLPos pos(&_cfg);
|
XMLPos pos(&_cfg);
|
||||||
|
|
||||||
pos.create("explorer-cfg");
|
pos.smart_create("explorer-cfg");
|
||||||
pos.create(name);
|
pos.smart_create(name);
|
||||||
|
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@ -790,7 +794,7 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
|
||||||
// init common controls library
|
// init common controls library
|
||||||
CommonControlInit usingCmnCtrl;
|
CommonControlInit usingCmnCtrl;
|
||||||
|
|
||||||
g_Globals.read_cfg();
|
g_Globals.read_persistent();
|
||||||
|
|
||||||
if (startup_desktop) {
|
if (startup_desktop) {
|
||||||
g_Globals._desktops.init();
|
g_Globals._desktops.init();
|
||||||
|
@ -818,7 +822,7 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
|
||||||
int ret = explorer_main(hInstance, lpCmdLine, nShowCmd);
|
int ret = explorer_main(hInstance, lpCmdLine, nShowCmd);
|
||||||
|
|
||||||
// write configuration file
|
// write configuration file
|
||||||
g_Globals.write_cfg();
|
g_Globals.write_persistent();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -554,6 +554,14 @@ SOURCE=.\taskbar\desktopbar.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin 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
|
SOURCE=.\notifyhook\notifyhook.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
|
|
||||||
using namespace XMLStorage;
|
using namespace XMLStorage;
|
||||||
|
|
||||||
|
#include "taskbar/favorites.h"
|
||||||
|
|
||||||
|
|
||||||
/// management of file types
|
/// management of file types
|
||||||
struct FileTypeInfo {
|
struct FileTypeInfo {
|
||||||
|
@ -228,8 +230,8 @@ extern struct ExplorerGlobals
|
||||||
|
|
||||||
void init(HINSTANCE hInstance);
|
void init(HINSTANCE hInstance);
|
||||||
|
|
||||||
bool read_cfg();
|
void read_persistent();
|
||||||
void write_cfg();
|
void write_persistent();
|
||||||
|
|
||||||
XMLPos get_cfg();
|
XMLPos get_cfg();
|
||||||
XMLPos get_cfg(const String& name);
|
XMLPos get_cfg(const String& name);
|
||||||
|
@ -259,6 +261,9 @@ extern struct ExplorerGlobals
|
||||||
XMLDoc _cfg;
|
XMLDoc _cfg;
|
||||||
String _cfg_dir;
|
String _cfg_dir;
|
||||||
String _cfg_path;
|
String _cfg_path;
|
||||||
|
|
||||||
|
Favorites _favorites;
|
||||||
|
String _favorites_path;
|
||||||
} g_Globals;
|
} g_Globals;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ CFG=make_explorer - Win32 bjam
|
||||||
# PROP Use_Debug_Libraries 0
|
# PROP Use_Debug_Libraries 0
|
||||||
# PROP Output_Dir "URelease"
|
# PROP Output_Dir "URelease"
|
||||||
# PROP Intermediate_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 Rebuild_Opt "clean all"
|
||||||
# PROP Target_File "explorer.exe"
|
# PROP Target_File "explorer.exe"
|
||||||
# PROP Bsc_Name ""
|
# PROP Bsc_Name ""
|
||||||
|
|
|
@ -460,7 +460,7 @@ FATDrive::FATDrive(LPCTSTR path)
|
||||||
_CacheDty = NULL;
|
_CacheDty = NULL;
|
||||||
_Caches = 0;
|
_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) {
|
if (_hDrive != INVALID_HANDLE_VALUE) {
|
||||||
_boot_sector.BytesPerSector = 512;
|
_boot_sector.BytesPerSector = 512;
|
||||||
|
|
292
reactos/subsys/system/explorer/taskbar/favorites.cpp
Normal file
292
reactos/subsys/system/explorer/taskbar/favorites.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
87
reactos/subsys/system/explorer/taskbar/favorites.h
Normal file
87
reactos/subsys/system/explorer/taskbar/favorites.h
Normal file
|
@ -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);
|
||||||
|
};
|
|
@ -1616,7 +1616,7 @@ int StartMenuHandler::Command(int id, int code)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_FAVORITES:
|
case IDC_FAVORITES:
|
||||||
CreateSubmenu(id, CSIDL_FAVORITES, ResString(IDS_FAVORITES));
|
CreateSubmenu(id, CSIDL_COMMON_FAVORITES, CSIDL_FAVORITES, ResString(IDS_FAVORITES));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_BROWSE:
|
case IDC_BROWSE:
|
||||||
|
|
|
@ -259,11 +259,11 @@ void NotifyArea::write_config()
|
||||||
// write notification icon settings to XML configuration file
|
// write notification icon settings to XML configuration file
|
||||||
XMLPos pos = g_Globals.get_cfg();
|
XMLPos pos = g_Globals.get_cfg();
|
||||||
|
|
||||||
pos.create("desktopbar");
|
pos.smart_create("desktopbar");
|
||||||
XMLBoolRef(pos, "options", "show-clock") = _hwndClock!=0;
|
XMLBoolRef(pos, "options", "show-clock") = _hwndClock!=0;
|
||||||
pos.back();
|
pos.back();
|
||||||
|
|
||||||
pos.create("notify-icons");
|
pos.smart_create("notify-icons");
|
||||||
|
|
||||||
XMLBoolRef(pos, "options", "hide-inactive") = _hide_inactive;
|
XMLBoolRef(pos, "options", "hide-inactive") = _hide_inactive;
|
||||||
XMLBoolRef(pos, "options", "show-hidden") = _show_hidden;
|
XMLBoolRef(pos, "options", "show-hidden") = _show_hidden;
|
||||||
|
@ -272,7 +272,7 @@ void NotifyArea::write_config()
|
||||||
NotifyIconConfig& cfg = *it;
|
NotifyIconConfig& cfg = *it;
|
||||||
|
|
||||||
// search for the corresponding node using the original name
|
// 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
|
// refresh unique name
|
||||||
cfg.create_name();
|
cfg.create_name();
|
||||||
|
@ -293,7 +293,7 @@ void NotifyArea::show_clock(bool flag)
|
||||||
|
|
||||||
if (vis != flag) {
|
if (vis != flag) {
|
||||||
if (flag) {
|
if (flag) {
|
||||||
// create clock window
|
// smart_create clock window
|
||||||
_hwndClock = ClockWindow::Create(_hwnd);
|
_hwndClock = ClockWindow::Create(_hwnd);
|
||||||
|
|
||||||
if (_hwndClock) {
|
if (_hwndClock) {
|
||||||
|
|
|
@ -54,6 +54,34 @@ bool XMLPos::go(const char* path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// 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
|
/// 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)
|
void XMLCALL XMLReader::XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone)
|
||||||
{
|
{
|
||||||
|
@ -65,12 +93,31 @@ void XMLCALL XMLReader::XML_XmlDeclHandler(void* userData, const XML_Char* versi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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)
|
void XMLCALL XMLReader::XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts)
|
||||||
{
|
{
|
||||||
XMLReader* pThis = (XMLReader*) userData;
|
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);
|
pThis->_pos.add_down(node);
|
||||||
|
|
||||||
|
@ -81,17 +128,41 @@ void XMLCALL XMLReader::XML_StartElementHandler(void* userData, const XML_Char*
|
||||||
(*node)[String_from_XML_Char(attr_name)] = String_from_XML_Char(attr_value);
|
(*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)
|
void XMLCALL XMLReader::XML_EndElementHandler(void* userData, const XML_Char* name)
|
||||||
{
|
{
|
||||||
XMLReader* pThis = (XMLReader*) userData;
|
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->_pos.back();
|
||||||
|
|
||||||
pThis->_in_tag = false;
|
pThis->_in_node = false;
|
||||||
|
pThis->_content.erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// store content, white space and comments
|
/// store content, white space and comments
|
||||||
|
@ -99,14 +170,11 @@ void XMLCALL XMLReader::XML_DefaultHandler(void* userData, const XML_Char* s, in
|
||||||
{
|
{
|
||||||
XMLReader* pThis = (XMLReader*) userData;
|
XMLReader* pThis = (XMLReader*) userData;
|
||||||
|
|
||||||
if (pThis->_in_tag)
|
pThis->_content.append(s, len);
|
||||||
pThis->_pos->append_content(s, len);
|
|
||||||
else
|
|
||||||
pThis->_pos->append_trailing(s, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string XMLString(LPCTSTR s)
|
std::string EncodeXMLString(LPCTSTR s)
|
||||||
{
|
{
|
||||||
TCHAR buffer[BUFFER_LEN];
|
TCHAR buffer[BUFFER_LEN];
|
||||||
LPTSTR o = buffer;
|
LPTSTR o = buffer;
|
||||||
|
@ -132,22 +200,46 @@ std::string XMLString(LPCTSTR s)
|
||||||
return get_utf8(buffer, o-buffer);
|
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
|
/// 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)
|
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()) {
|
if (!_children.empty() || !_content.empty()) {
|
||||||
out << '>' << _content;
|
out << '>' << _content;
|
||||||
|
|
||||||
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
|
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
|
} else
|
||||||
out << "/>";
|
out << "/>";
|
||||||
|
|
||||||
|
@ -156,81 +248,73 @@ void XMLNode::write_worker(std::ostream& out, WRITE_MODE mode, int indent) const
|
||||||
|
|
||||||
|
|
||||||
/// pretty print node with children tree to output stream
|
/// 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--; )
|
for(int i=indent; i--; )
|
||||||
out << XML_INDENT_SPACE;
|
out << XML_INDENT_SPACE;
|
||||||
|
|
||||||
out << '<' << XMLString(*this);
|
out << '<' << EncodeXMLString(*this);
|
||||||
|
|
||||||
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
|
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()) {
|
if (!_children.empty() || !_content.empty()) {
|
||||||
out << ">\n";
|
out << ">\n";
|
||||||
|
|
||||||
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
|
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--; )
|
for(int i=indent; i--; )
|
||||||
out << XML_INDENT_SPACE;
|
out << XML_INDENT_SPACE;
|
||||||
|
|
||||||
out << "</" << XMLString(*this) << ">\n";
|
out << "</" << EncodeXMLString(*this) << ">\n";
|
||||||
} else
|
} else
|
||||||
out << "/>\n";
|
out << "/>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// write node with children tree to output stream using smart formating
|
/// 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;
|
if (_leading.empty())
|
||||||
|
|
||||||
format_pre = next_format;
|
|
||||||
format_mid = _content.empty();
|
|
||||||
format_post = _trailing.empty();
|
|
||||||
|
|
||||||
if (format_pre)
|
|
||||||
for(int i=indent; i--; )
|
for(int i=indent; i--; )
|
||||||
out << XML_INDENT_SPACE;
|
out << XML_INDENT_SPACE;
|
||||||
|
else
|
||||||
|
out << _leading;
|
||||||
|
|
||||||
out << '<' << XMLString(*this);
|
out << '<' << EncodeXMLString(*this);
|
||||||
|
|
||||||
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
|
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()) {
|
if (!_children.empty() || !_content.empty()) {
|
||||||
out << '>';
|
out << '>';
|
||||||
|
|
||||||
if (format_mid)
|
if (_content.empty())
|
||||||
out << '\n';
|
out << '\n';
|
||||||
else
|
else
|
||||||
out << _content;
|
out << _content;
|
||||||
|
|
||||||
Children::const_iterator it = _children.begin();
|
Children::const_iterator it = _children.begin();
|
||||||
|
|
||||||
if (it != _children.end()) {
|
if (it != _children.end())
|
||||||
next_format = (*it)->_content.empty() && (*it)->_trailing.empty();
|
|
||||||
|
|
||||||
for(; it!=_children.end(); ++it)
|
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--; )
|
for(int i=indent; i--; )
|
||||||
out << XML_INDENT_SPACE;
|
out << XML_INDENT_SPACE;
|
||||||
|
else
|
||||||
|
out << _end_leading;
|
||||||
|
|
||||||
out << "</" << XMLString(*this) << '>';
|
out << "</" << EncodeXMLString(*this) << '>';
|
||||||
} else
|
} else
|
||||||
out << "/>";
|
out << "/>";
|
||||||
|
|
||||||
if (format_post)
|
if (_trailing.empty())
|
||||||
out << '\n';
|
out << '\n';
|
||||||
else
|
else
|
||||||
out << _trailing;
|
out << _trailing;
|
||||||
|
|
||||||
return format_post;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -202,7 +202,70 @@ inline std::string get_utf8(const String& s)
|
||||||
return get_utf8(s.c_str(), s.length());
|
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
|
// write XML files with 2 spaces indenting
|
||||||
|
@ -279,6 +342,7 @@ struct XMLNode : public String
|
||||||
|
|
||||||
// access to protected class members for XMLPos and XMLReader
|
// access to protected class members for XMLPos and XMLReader
|
||||||
friend struct XMLPos;
|
friend struct XMLPos;
|
||||||
|
friend struct const_XMLPos;
|
||||||
friend struct XMLReader;
|
friend struct XMLReader;
|
||||||
|
|
||||||
XMLNode(const String& name)
|
XMLNode(const String& name)
|
||||||
|
@ -286,9 +350,17 @@ struct XMLNode : public String
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XMLNode(const String& name, const std::string& leading)
|
||||||
|
: String(name),
|
||||||
|
_leading(leading)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
XMLNode(const XMLNode& other)
|
XMLNode(const XMLNode& other)
|
||||||
: _attributes(other._attributes),
|
: _attributes(other._attributes),
|
||||||
|
_leading(other._leading),
|
||||||
_content(other._content),
|
_content(other._content),
|
||||||
|
_end_leading(other._end_leading),
|
||||||
_trailing(other._trailing)
|
_trailing(other._trailing)
|
||||||
{
|
{
|
||||||
for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
|
for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
|
||||||
|
@ -312,7 +384,9 @@ struct XMLNode : public String
|
||||||
|
|
||||||
_attributes = other._attributes;
|
_attributes = other._attributes;
|
||||||
|
|
||||||
|
_leading = other._leading;
|
||||||
_content = other._content;
|
_content = other._content;
|
||||||
|
_end_leading = other._end_leading;
|
||||||
_trailing = other._trailing;
|
_trailing = other._trailing;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -401,6 +475,20 @@ struct XMLNode : public String
|
||||||
return _children;
|
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 {
|
enum WRITE_MODE {
|
||||||
FORMAT_SMART = 0, /// preserve original white space and comments if present; pretty print otherwise
|
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_ORIGINAL = 1, /// write XML stream preserving original white space and comments
|
||||||
|
@ -412,15 +500,15 @@ struct XMLNode : public String
|
||||||
{
|
{
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case FORMAT_PRETTY:
|
case FORMAT_PRETTY:
|
||||||
pretty_write_worker(out, mode, indent);
|
pretty_write_worker(out, indent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FORMAT_ORIGINAL:
|
case FORMAT_ORIGINAL:
|
||||||
write_worker(out, mode, indent);
|
write_worker(out, indent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: // FORMAT_SMART
|
default: // FORMAT_SMART
|
||||||
smart_write_worker(out, indent, _content.empty() && _trailing.empty());
|
smart_write_worker(out, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
@ -430,7 +518,9 @@ protected:
|
||||||
Children _children;
|
Children _children;
|
||||||
AttributeMap _attributes;
|
AttributeMap _attributes;
|
||||||
|
|
||||||
|
std::string _leading;
|
||||||
std::string _content;
|
std::string _content;
|
||||||
|
std::string _end_leading;
|
||||||
std::string _trailing;
|
std::string _trailing;
|
||||||
|
|
||||||
XMLNode* get_first_child() const
|
XMLNode* get_first_child() const
|
||||||
|
@ -488,10 +578,10 @@ protected:
|
||||||
|
|
||||||
void append_content(const char* s, int l)
|
void append_content(const char* s, int l)
|
||||||
{
|
{
|
||||||
if (_children.empty())
|
//if (_children.empty())
|
||||||
_content.append(s, l);
|
_content.append(s, l);
|
||||||
else
|
//else
|
||||||
_children.back()->_content.append(s, l);
|
// _children.back()->_content.append(s, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void append_trailing(const char* s, int l)
|
void append_trailing(const char* s, int l)
|
||||||
|
@ -502,9 +592,9 @@ protected:
|
||||||
_children.back()->_trailing.append(s, l);
|
_children.back()->_trailing.append(s, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_worker(std::ostream& out, WRITE_MODE mode, int indent) const;
|
void write_worker(std::ostream& out, int indent) const;
|
||||||
void pretty_write_worker(std::ostream& out, WRITE_MODE mode, int indent) const;
|
void pretty_write_worker(std::ostream& out, int indent) const;
|
||||||
bool smart_write_worker(std::ostream& out, int indent, bool next_format) const;
|
void smart_write_worker(std::ostream& out, int indent) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -606,6 +696,104 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// 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
|
/// iterator for XML trees
|
||||||
struct XMLPos
|
struct XMLPos
|
||||||
{
|
{
|
||||||
|
@ -622,8 +810,8 @@ struct XMLPos
|
||||||
}
|
}
|
||||||
|
|
||||||
/// access to current node
|
/// access to current node
|
||||||
operator XMLNode*() {return _cur;}
|
|
||||||
operator const XMLNode*() const {return _cur;}
|
operator const XMLNode*() const {return _cur;}
|
||||||
|
operator XMLNode*() {return _cur;}
|
||||||
|
|
||||||
const XMLNode* operator->() const {return _cur;}
|
const XMLNode* operator->() const {return _cur;}
|
||||||
XMLNode* operator->() {return _cur;}
|
XMLNode* operator->() {return _cur;}
|
||||||
|
@ -632,8 +820,8 @@ struct XMLPos
|
||||||
XMLNode& operator*() {return *_cur;}
|
XMLNode& operator*() {return *_cur;}
|
||||||
|
|
||||||
/// attribute access
|
/// 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];}
|
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
|
/// insert children when building tree
|
||||||
void add_down(XMLNode* child)
|
void add_down(XMLNode* child)
|
||||||
|
@ -680,8 +868,14 @@ struct XMLPos
|
||||||
/// move X-Path like to position in XML tree
|
/// move X-Path like to position in XML tree
|
||||||
bool go(const char* path);
|
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)
|
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);
|
XMLNode* node = _cur->find_first(name);
|
||||||
|
|
||||||
|
@ -692,7 +886,7 @@ struct XMLPos
|
||||||
}
|
}
|
||||||
|
|
||||||
/// search matching child node identified by key name and an attribute value
|
/// 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);
|
XMLNode* node = _cur->find_first(name, attr_name, attr_value);
|
||||||
|
|
||||||
|
@ -718,8 +912,14 @@ struct XMLPos
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// create node if not already existing and move to it
|
/// create node and move to it
|
||||||
void create(const char* name)
|
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);
|
XMLNode* node = _cur->find_first(name);
|
||||||
|
|
||||||
|
@ -731,7 +931,7 @@ struct XMLPos
|
||||||
|
|
||||||
/// search matching child node identified by key name and an attribute value
|
/// search matching child node identified by key name and an attribute value
|
||||||
template<typename T, typename U>
|
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);
|
XMLNode* node = _cur->find_first(name, attr_name, attr_value);
|
||||||
|
|
||||||
|
@ -759,6 +959,97 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// 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
|
struct XMLBool
|
||||||
{
|
{
|
||||||
XMLBool(bool value)
|
XMLBool(bool value)
|
||||||
|
@ -789,6 +1080,11 @@ struct XMLBool
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator!() const
|
||||||
|
{
|
||||||
|
return !_value;
|
||||||
|
}
|
||||||
|
|
||||||
operator LPCTSTR() const
|
operator LPCTSTR() const
|
||||||
{
|
{
|
||||||
return _value? TEXT("TRUE"): TEXT("FALSE");
|
return _value? TEXT("TRUE"): TEXT("FALSE");
|
||||||
|
@ -815,6 +1111,11 @@ struct XMLBoolRef
|
||||||
return !_tcsicmp(_ref, TEXT("TRUE"));
|
return !_tcsicmp(_ref, TEXT("TRUE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator!() const
|
||||||
|
{
|
||||||
|
return _tcsicmp(_ref, TEXT("TRUE"))? true: false;
|
||||||
|
}
|
||||||
|
|
||||||
XMLBoolRef& operator=(bool value)
|
XMLBoolRef& operator=(bool value)
|
||||||
{
|
{
|
||||||
assign(value);
|
assign(value);
|
||||||
|
@ -931,7 +1232,7 @@ struct XMLReader
|
||||||
XML_SetElementHandler(_parser, XML_StartElementHandler, XML_EndElementHandler);
|
XML_SetElementHandler(_parser, XML_StartElementHandler, XML_EndElementHandler);
|
||||||
XML_SetDefaultHandler(_parser, XML_DefaultHandler);
|
XML_SetDefaultHandler(_parser, XML_DefaultHandler);
|
||||||
|
|
||||||
_in_tag = false;
|
_in_node = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
~XMLReader()
|
~XMLReader()
|
||||||
|
@ -939,28 +1240,7 @@ struct XMLReader
|
||||||
XML_ParserFree(_parser);
|
XML_ParserFree(_parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
XML_Status read(std::istream& in)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string get_position() const
|
std::string get_position() const
|
||||||
{
|
{
|
||||||
|
@ -988,7 +1268,9 @@ protected:
|
||||||
XML_Parser _parser;
|
XML_Parser _parser;
|
||||||
std::string _xml_version;
|
std::string _xml_version;
|
||||||
std::string _encoding;
|
std::string _encoding;
|
||||||
bool _in_tag;
|
|
||||||
|
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_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);
|
static void XMLCALL XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts);
|
||||||
|
@ -997,6 +1279,29 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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
|
struct XMLDoc : public XMLNode
|
||||||
{
|
{
|
||||||
XMLDoc()
|
XMLDoc()
|
||||||
|
@ -1004,7 +1309,7 @@ struct XMLDoc : public XMLNode
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
XMLDoc(const std::string& path)
|
XMLDoc(LPCTSTR path)
|
||||||
: XMLNode("")
|
: XMLNode("")
|
||||||
{
|
{
|
||||||
read(path);
|
read(path);
|
||||||
|
@ -1012,23 +1317,33 @@ struct XMLDoc : public XMLNode
|
||||||
|
|
||||||
std::istream& read(std::istream& in)
|
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;
|
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
|
/// write XML stream preserving previous white space and comments
|
||||||
std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART,
|
std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART, const XMLHeader& header=XMLHeader()) const
|
||||||
const std::string& xml_version="1.0", const std::string& encoding="UTF-8") const
|
|
||||||
{
|
{
|
||||||
out << "<?xml version=\"" << xml_version << "\" encoding=\"" << encoding << "\"?>\n";
|
header.print(out);
|
||||||
|
|
||||||
if (!_children.empty())
|
if (!_children.empty())
|
||||||
_children.front()->write(out);
|
_children.front()->write(out);
|
||||||
|
@ -1042,17 +1357,16 @@ struct XMLDoc : public XMLNode
|
||||||
return write(out, FORMAT_PRETTY);
|
return write(out, FORMAT_PRETTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const std::string& path, WRITE_MODE mode=FORMAT_SMART,
|
void write(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART, const XMLHeader& header=XMLHeader()) const
|
||||||
const std::string& xml_version="1.0", const std::string& encoding="UTF-8") 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);
|
write_formating(out);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue