2 * Copyright 2004, 2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 // Explorer and Desktop clone
25 // Martin Fuchs, 04.04.2004
31 #include "startmenu.h"
34 String
DecodeURLString(const char* s
)
36 TCHAR buffer
[BUFFER_LEN
];
39 for(const char* p
=s
; *p
; ++p
)
41 if (!strncmp(p
+1, "20", 2)) {
49 return String(buffer
, o
-buffer
);
54 bool Bookmark::read_url(LPCTSTR path
)
56 char line
[BUFFER_LEN
];
61 in
.getline(line
, BUFFER_LEN
);
67 const char* keyword
= p
;
68 const char* eq
= strchr(p
, '=');
71 const char* cont
= eq
+ 1;
75 if (!_strnicmp(keyword
, "URL", 3))
76 _url
= DecodeURLString(cont
);
77 else if (!_strnicmp(keyword
, "IconFile", 8))
78 _icon_path
= DecodeURLString(cont
);
85 /// convert XBEL bookmark node
86 bool Bookmark::read(const_XMLPos
& pos
)
88 _url
= pos
.get("href").c_str();
90 if (pos
.go_down("title")) {
91 _name
= pos
->get_content();
95 if (pos
.go_down("desc")) {
96 _description
= pos
->get_content();
100 if (pos
.go_down("info")) {
101 const_XMLChildrenFilter
metadata(pos
, "metadata");
103 for(const_XMLChildrenFilter::const_iterator it
=metadata
.begin(); it
!=metadata
.end(); ++it
) {
104 const XMLNode
& node
= **it
;
105 const_XMLPos
sub_pos(&node
);
107 if (node
.get("owner") == "ros-explorer") {
108 if (sub_pos
.go_down("icon")) {
109 _icon_path
= sub_pos
.get("path").c_str();
110 _icon_idx
= XS_toi(sub_pos
.get("index"));
112 sub_pos
.back(); // </icon>
117 pos
.back(); // </metadata>
118 pos
.back(); // </info>
121 return !_url
.empty(); // _url is mandatory.
124 /// write XBEL bookmark node
125 void Bookmark::write(XMLPos
& pos
) const
127 pos
.create("bookmark");
129 pos
["href"] = _url
.c_str();
131 if (!_name
.empty()) {
133 pos
->set_content(_name
);
137 if (!_description
.empty()) {
139 pos
->set_content(_description
);
143 if (!_icon_path
.empty()) {
145 pos
.create("metadata");
146 pos
["owner"] = "ros-explorer";
148 pos
["path"] = _icon_path
.c_str();
149 pos
["index"].printf(XS_TEXT("%d"), _icon_idx
);
150 pos
.back(); // </icon>
151 pos
.back(); // </metadata>
152 pos
.back(); // </info>
159 /// read bookmark folder from XBEL formated XML tree
160 void BookmarkFolder::read(const_XMLPos
& pos
)
162 if (pos
.go_down("title")) {
163 _name
= pos
->get_content();
167 if (pos
.go_down("desc")) {
168 _description
= pos
->get_content();
172 _bookmarks
.read(pos
);
175 /// write bookmark folder content from XBEL formated XML tree
176 void BookmarkFolder::write(XMLPos
& pos
) const
178 pos
.create("folder");
180 if (!_name
.empty()) {
182 pos
->set_content(_name
);
186 if (!_description
.empty()) {
188 pos
->set_content(_description
);
192 _bookmarks
.write(pos
);
196 BookmarkNode::BookmarkNode()
202 BookmarkNode::BookmarkNode(const Bookmark
& bm
)
203 : _type(BMNT_BOOKMARK
)
205 _pbookmark
= new Bookmark(bm
);
208 BookmarkNode::BookmarkNode(const BookmarkFolder
& bmf
)
211 _pfolder
= new BookmarkFolder(bmf
);
214 BookmarkNode::BookmarkNode(const BookmarkNode
& other
)
217 if (other
._type
== BMNT_BOOKMARK
)
218 _pbookmark
= new Bookmark(*other
._pbookmark
);
219 else if (other
._type
== BMNT_FOLDER
)
220 _pfolder
= new BookmarkFolder(*other
._pfolder
);
225 BookmarkNode::~BookmarkNode()
227 if (_type
== BMNT_BOOKMARK
)
229 else if (_type
== BMNT_FOLDER
)
233 BookmarkNode
& BookmarkNode::operator=(const Bookmark
& bm
)
237 _pbookmark
= new Bookmark(bm
);
242 BookmarkNode
& BookmarkNode::operator=(const BookmarkFolder
& bmf
)
246 _pfolder
= new BookmarkFolder(bmf
);
251 BookmarkNode
& BookmarkNode::operator=(const BookmarkNode
& other
)
257 if (other
._type
== BMNT_BOOKMARK
)
258 _pbookmark
= new Bookmark(*other
._pbookmark
);
259 else if (other
._type
== BMNT_FOLDER
)
260 _pfolder
= new BookmarkFolder(*other
._pfolder
);
265 void BookmarkNode::clear()
267 if (_type
== BMNT_BOOKMARK
) {
271 else if (_type
== BMNT_FOLDER
) {
280 /// read bookmark list from XBEL formated XML tree
281 void BookmarkList::read(const_XMLPos
& pos
)
283 const XMLNode::Children
& children
= pos
->get_children();
285 for(XMLNode::Children::const_iterator it
=children
.begin(); it
!=children
.end(); ++it
) {
286 const XMLNode
& node
= **it
;
287 const_XMLPos
sub_pos(&node
);
289 if (node
== "folder") {
290 BookmarkFolder folder
;
292 folder
.read(sub_pos
);
295 } else if (node
== "bookmark") {
298 if (bookmark
.read(sub_pos
))
304 /// write bookmark list into XBEL formated XML tree
305 void BookmarkList::write(XMLPos
& pos
) const
307 for(const_iterator it
=begin(); it
!=end(); ++it
) {
308 const BookmarkNode
& node
= *it
;
310 if (node
._type
== BookmarkNode::BMNT_FOLDER
) {
311 const BookmarkFolder
& folder
= *node
._pfolder
;
316 } else if (node
._type
== BookmarkNode::BMNT_BOOKMARK
) {
317 const Bookmark
& bookmark
= *node
._pbookmark
;
319 if (!bookmark
._url
.empty())
326 /// fill treeview control with bookmark tree content
327 void BookmarkList::fill_tree(HWND hwnd
, HTREEITEM parent
, HIMAGELIST himagelist
, HDC hdc_wnd
) const
331 tvi
.hParent
= parent
;
332 tvi
.hInsertAfter
= TVI_LAST
;
334 TV_ITEM
& tv
= tvi
.item
;
335 tv
.mask
= TVIF_TEXT
|TVIF_IMAGE
|TVIF_SELECTEDIMAGE
|TVIF_PARAM
;
337 for(const_iterator it
=begin(); it
!=end(); ++it
) {
338 const BookmarkNode
& node
= *it
;
340 tv
.lParam
= (LPARAM
)&node
;
342 if (node
._type
== BookmarkNode::BMNT_FOLDER
) {
343 const BookmarkFolder
& folder
= *node
._pfolder
;
345 tv
.pszText
= (LPTSTR
)folder
._name
.c_str();
346 tv
.iImage
= 3; // folder
347 tv
.iSelectedImage
= 4; // open folder
348 HTREEITEM hitem
= TreeView_InsertItem(hwnd
, &tvi
);
350 folder
._bookmarks
.fill_tree(hwnd
, hitem
, himagelist
, hdc_wnd
);
351 } else if (node
._type
== BookmarkNode::BMNT_BOOKMARK
) {
352 const Bookmark
& bookmark
= *node
._pbookmark
;
354 tv
.pszText
= (LPTSTR
)bookmark
._name
.c_str();
355 tv
.iImage
= 1; // bookmark
356 tv
.iSelectedImage
= 2; // selected bookmark
358 if (!bookmark
._icon_path
.empty()) {
359 const Icon
& icon
= g_Globals
._icon_cache
.extract(bookmark
._icon_path
, bookmark
._icon_idx
);
361 if ((ICON_ID
)icon
!= ICID_NONE
)
362 tv
.iImage
= tv
.iSelectedImage
= icon
.add_to_imagelist(himagelist
, hdc_wnd
);
365 (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_DONT_EXTRACT_ICONS
);
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
, COUNTOF(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
, COUNTOF(path
));
410 _tsplitpath_s(path
, NULL
, 0, NULL
, 0, NULL
, 0, ext
, COUNTOF(ext
));
412 if (!_tcsicmp(ext
, TEXT(".url"))) {
413 bookmark
.read_url(path
);
416 ///@todo read shell links
424 /// read XBEL bookmark file
425 bool Favorites::read(LPCTSTR path
)
429 if (!xbel
.read_file(path
)) {
430 if (!xbel
._errors
.empty())
431 MessageBox(g_Globals
._hwndDesktop
, xbel
._errors
.str(),
432 TEXT("ROS Explorer - reading bookmark file"), MB_OK
);
435 const_XMLPos
pos(&xbel
);
437 if (!pos
.go_down("xbel"))
447 /// write XBEL bookmark file
448 void Favorites::write(LPCTSTR path
) const
457 xbel
._format
._doctype
._name
= "xbel";
458 xbel
._format
._doctype
._public
= "+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML";
459 xbel
._format
._doctype
._system
= "http://www.python.org/topics/xml/dtds/xbel-1.0.dtd";
461 xbel
.write_file(path
);
464 /// import Internet Explorer bookmarks from Favorites folder
465 bool Favorites::import_IE_favorites(HWND hwnd
)
469 StartMenuShellDirs dirs
;
472 dirs
.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_COMMON_FAVORITES
, hwnd
), hwnd
));
473 dirs
.push_back(ShellDirectory(GetDesktopFolder(), SpecialFolderPath(CSIDL_FAVORITES
, hwnd
), hwnd
));
474 } catch(COMException
&) {
477 for(StartMenuShellDirs::iterator it
=dirs
.begin(); it
!=dirs
.end(); ++it
) {
478 StartMenuDirectory
& smd
= *it
;
479 ShellDirectory
& dir
= smd
._dir
;
482 super::import_IE_favorites(dir
, hwnd
);
483 } catch(COMException
&) {