2 * Copyright 2004 Martin Fuchs
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 // Explorer and Desktop clone
25 // Martin Fuchs, 04.04.2004
32 String
DecodeURLString(const char* s
)
34 TCHAR buffer
[BUFFER_LEN
];
37 for(const char* p
=s
; *p
; ++p
)
39 if (!strncmp(p
+1, "20", 2)) {
47 return String(buffer
, o
-buffer
);
52 bool Bookmark::read_url(LPCTSTR path
)
54 char line
[BUFFER_LEN
];
59 in
.getline(line
, BUFFER_LEN
);
65 const char* keyword
= p
;
66 const char* eq
= strchr(p
, '=');
69 const char* cont
= eq
+ 1;
73 if (!strnicmp(keyword
, "URL", 3))
74 _url
= DecodeURLString(cont
);
75 else if (!strnicmp(keyword
, "IconFile", 8))
76 _icon_path
= DecodeURLString(cont
);
83 /// convert XBEL bookmark node
84 bool Bookmark::read(const_XMLPos
& pos
)
86 _url
= pos
.get("href").c_str();
88 if (pos
.go_down("title")) {
89 _name
= pos
->get_content();
93 if (pos
.go_down("desc")) {
94 _description
= pos
->get_content();
98 if (pos
.go_down("info")) {
99 const_XMLChildrenFilter
metadata(pos
, "metadata");
101 for(const_XMLChildrenFilter::const_iterator it
=metadata
.begin(); it
!=metadata
.end(); ++it
) {
102 const XMLNode
& node
= **it
;
103 const_XMLPos
sub_pos(&node
);
105 if (node
.get("owner") == "ros-explorer") {
106 if (sub_pos
.go_down("icon")) {
107 _icon_path
= sub_pos
.get("path").c_str();
108 _icon_idx
= XS_toi(sub_pos
.get("index"));
110 sub_pos
.back(); // </icon>
115 pos
.back(); // </metadata>
116 pos
.back(); // </info>
119 return !_url
.empty(); // _url is mandatory.
122 /// write XBEL bookmark node
123 void Bookmark::write(XMLPos
& pos
) const
125 pos
.create("bookmark");
127 pos
["href"] = _url
.c_str();
129 if (!_name
.empty()) {
131 pos
->set_content(_name
);
135 if (!_description
.empty()) {
137 pos
->set_content(_description
);
141 if (!_icon_path
.empty()) {
143 pos
.create("metadata");
144 pos
["owner"] = "ros-explorer";
146 pos
["path"] = _icon_path
.c_str();
147 pos
["index"].printf(XS_TEXT("%d"), _icon_idx
);
148 pos
.back(); // </icon>
149 pos
.back(); // </metadata>
150 pos
.back(); // </info>
157 /// read bookmark folder from XBEL formated XML tree
158 void BookmarkFolder::read(const_XMLPos
& pos
)
160 if (pos
.go_down("title")) {
161 _name
= pos
->get_content();
165 if (pos
.go_down("desc")) {
166 _description
= pos
->get_content();
170 _bookmarks
.read(pos
);
173 /// write bookmark folder content from XBEL formated XML tree
174 void BookmarkFolder::write(XMLPos
& pos
) const
176 pos
.create("folder");
178 if (!_name
.empty()) {
180 pos
->set_content(_name
);
184 if (!_description
.empty()) {
186 pos
->set_content(_description
);
190 _bookmarks
.write(pos
);
194 BookmarkNode::BookmarkNode()
200 BookmarkNode::BookmarkNode(const Bookmark
& bm
)
201 : _type(BMNT_BOOKMARK
)
203 _pbookmark
= new Bookmark(bm
);
206 BookmarkNode::BookmarkNode(const BookmarkFolder
& bmf
)
209 _pfolder
= new BookmarkFolder(bmf
);
212 BookmarkNode::BookmarkNode(const BookmarkNode
& other
)
215 if (other
._type
== BMNT_BOOKMARK
)
216 _pbookmark
= new Bookmark(*other
._pbookmark
);
217 else if (other
._type
== BMNT_FOLDER
)
218 _pfolder
= new BookmarkFolder(*other
._pfolder
);
223 BookmarkNode::~BookmarkNode()
225 if (_type
== BMNT_BOOKMARK
)
227 else if (_type
== BMNT_FOLDER
)
231 BookmarkNode
& BookmarkNode::operator=(const Bookmark
& bm
)
235 _pbookmark
= new Bookmark(bm
);
240 BookmarkNode
& BookmarkNode::operator=(const BookmarkFolder
& bmf
)
244 _pfolder
= new BookmarkFolder(bmf
);
249 BookmarkNode
& BookmarkNode::operator=(const BookmarkNode
& other
)
255 if (other
._type
== BMNT_BOOKMARK
)
256 _pbookmark
= new Bookmark(*other
._pbookmark
);
257 else if (other
._type
== BMNT_FOLDER
)
258 _pfolder
= new BookmarkFolder(*other
._pfolder
);
263 void BookmarkNode::clear()
265 if (_type
== BMNT_BOOKMARK
) {
269 else if (_type
== BMNT_FOLDER
) {
278 /// read bookmark list from XBEL formated XML tree
279 void BookmarkList::read(const_XMLPos
& pos
)
281 const XMLNode::Children
& children
= pos
->get_children();
283 for(XMLNode::Children::const_iterator it
=children
.begin(); it
!=children
.end(); ++it
) {
284 const XMLNode
& node
= **it
;
285 const_XMLPos
sub_pos(&node
);
287 if (node
== "folder") {
288 BookmarkFolder folder
;
290 folder
.read(sub_pos
);
293 } else if (node
== "bookmark") {
296 if (bookmark
.read(sub_pos
))
302 /// write bookmark list into XBEL formated XML tree
303 void BookmarkList::write(XMLPos
& pos
) const
305 for(const_iterator it
=begin(); it
!=end(); ++it
) {
306 const BookmarkNode
& node
= *it
;
308 if (node
._type
== BookmarkNode::BMNT_FOLDER
) {
309 const BookmarkFolder
& folder
= *node
._pfolder
;
314 } else if (node
._type
== BookmarkNode::BMNT_BOOKMARK
) {
315 const Bookmark
& bookmark
= *node
._pbookmark
;
317 if (!bookmark
._url
.empty())
324 /// fill treeview control with bookmark tree content
325 void BookmarkList::fill_tree(HWND hwnd
, HTREEITEM parent
, HIMAGELIST himagelist
, HDC hdc_wnd
) const
329 tvi
.hParent
= parent
;
330 tvi
.hInsertAfter
= TVI_LAST
;
332 TV_ITEM
& tv
= tvi
.item
;
333 tv
.mask
= TVIF_TEXT
|TVIF_IMAGE
|TVIF_SELECTEDIMAGE
|TVIF_PARAM
;
335 for(const_iterator it
=begin(); it
!=end(); ++it
) {
336 const BookmarkNode
& node
= *it
;
338 tv
.lParam
= (LPARAM
)&node
;
340 if (node
._type
== BookmarkNode::BMNT_FOLDER
) {
341 const BookmarkFolder
& folder
= *node
._pfolder
;
343 tv
.pszText
= (LPTSTR
)folder
._name
.c_str();
344 tv
.iImage
= 3; // folder
345 tv
.iSelectedImage
= 4; // open folder
346 HTREEITEM hitem
= TreeView_InsertItem(hwnd
, &tvi
);
348 folder
._bookmarks
.fill_tree(hwnd
, hitem
, himagelist
, hdc_wnd
);
349 } else if (node
._type
== BookmarkNode::BMNT_BOOKMARK
) {
350 const Bookmark
& bookmark
= *node
._pbookmark
;
352 tv
.pszText
= (LPTSTR
)bookmark
._name
.c_str();
353 tv
.iImage
= 1; // bookmark
354 tv
.iSelectedImage
= 2; // selected bookmark
356 if (!bookmark
._icon_path
.empty()) {
357 const Icon
& icon
= g_icon_cache
.extract(bookmark
._icon_path
, bookmark
._icon_idx
);
359 if ((ICON_ID
)icon
!= ICID_NONE
)
360 tv
.iImage
= tv
.iSelectedImage
= icon
.add_to_imagelist(himagelist
, hdc_wnd
);
363 (void)TreeView_InsertItem(hwnd
, &tvi
);
371 /// import Internet Explorer bookmarks from Favorites folder into bookmark list
372 void BookmarkList::import_IE_favorites(ShellDirectory& dir, HWND hwnd)
374 TCHAR path[MAX_PATH], ext[_MAX_EXT];
376 dir.smart_scan(SORT_NAME, SCAN_FILESYSTEM);
378 for(Entry*entry=dir._down; entry; entry=entry->_next) {
379 if (entry->_shell_attribs & SFGAO_HIDDEN) // ignore files like "desktop.ini"
384 if (entry->_etype == ET_SHELL)
385 name = dir._folder.get_name(static_cast<ShellEntry*>(entry)->_pidl);
387 name = entry->_display_name;
389 if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
390 BookmarkFolder new_folder;
392 new_folder._name = DecodeXMLString(name);
394 if (entry->_etype == ET_SHELL) {
395 ShellDirectory new_dir(dir._folder, static_cast<ShellEntry*>(entry)->_pidl, hwnd);
396 new_folder._bookmarks.import_IE_favorites(new_dir, hwnd);
398 entry->get_path(path);
399 ShellDirectory new_dir(GetDesktopFolder(), path, hwnd);
400 new_folder._bookmarks.import_IE_favorites(new_dir, hwnd);
403 push_back(new_folder);
407 bookmark._name = DecodeXMLString(name);
409 entry->get_path(path);
410 _tsplitpath(path, NULL, NULL, NULL, ext);
412 if (!_tcsicmp(ext, TEXT(".url"))) {
413 bookmark.read_url(path);
416 ///@todo read shell links
426 /// read XBEL bookmark file
427 bool Favorites::read(LPCTSTR path
)
431 if (!xbel
.read(path
))
432 if (xbel
._last_error
== XML_ERROR_NO_ELEMENTS
)
435 MessageBox(0/*@@g_Globals._hwndDesktop*/, String(xbel
._last_error_msg
.c_str()),
436 TEXT("ROS Explorer - reading bookmark file"), MB_OK
);
438 const_XMLPos
pos(&xbel
);
440 if (!pos
.go_down("xbel"))
450 /// write XBEL bookmark file
451 void Favorites::write(LPCTSTR path
) const
460 xbel
._header
._doctype
= "<!DOCTYPE xbel"
461 " PUBLIC \"+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML\"\n"
462 " \"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">";
470 /// import Internet Explorer bookmarks from Favorites folder
471 bool Favorites::import_IE_favorites(HWND hwnd)
475 StartMenuShellDirs dirs;
478 dirs.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_COMMON_FAVORITES, hwnd), hwnd));
479 dirs.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_FAVORITES, hwnd), hwnd));
480 } catch(COMException&) {
483 for(StartMenuShellDirs::iterator it=dirs.begin(); it!=dirs.end(); ++it) {
484 StartMenuDirectory& smd = *it;
485 ShellDirectory& dir = smd._dir;
488 super::import_IE_favorites(dir, hwnd);
489 } catch(COMException&) {