Revert, thx Thomas, wasnt sure.
[reactos.git] / reactos / subsys / system / ibrowser / ibrowser.cpp
1 /*
2 * Copyright 2005 Martin Fuchs
3 *
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.
8 *
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.
13 *
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
17 */
18
19
20 //
21 // ROS Internet Web Browser
22 //
23 // ibrowser.cpp
24 //
25 // Martin Fuchs, 24.01.2005
26 //
27
28
29 #include <precomp.h>
30
31 #include "ibrowser_intres.h"
32
33 #include <locale.h> // for setlocale()
34
35 #ifndef __WINE__
36 #include <io.h> // for dup2()
37 #include <fcntl.h> // for _O_RDONLY
38 #endif
39
40
41 // globals
42
43 HINSTANCE g_hInstance;
44 IconCache g_icon_cache;
45 ATOM g_hframeClass;
46
47
48 /*@@
49 void ExplorerGlobals::read_persistent()
50 {
51 // read configuration file
52 _cfg_dir.printf(TEXT("%s\\ReactOS"), (LPCTSTR)SpecialFolderFSPath(CSIDL_APPDATA,0));
53 _cfg_path.printf(TEXT("%s\\ros-ibrowser-cfg.xml"), _cfg_dir.c_str());
54
55 if (!_cfg.read(_cfg_path)) {
56 if (_cfg._last_error != XML_ERROR_NO_ELEMENTS)
57 MessageBox(g_Globals._hwndDesktop, String(_cfg._last_error_msg.c_str()),
58 TEXT("ROS Explorer - reading user settings"), MB_OK);
59
60 _cfg.read(TEXT("ibrowser-cfg-template.xml"));
61 }
62
63 // read bookmarks
64 _favorites_path.printf(TEXT("%s\\ros-ibrowser-bookmarks.xml"), _cfg_dir.c_str());
65
66 if (!_favorites.read(_favorites_path)) {
67 _favorites.import_IE_favorites(0);
68 _favorites.write(_favorites_path);
69 }
70 }
71
72 void ExplorerGlobals::write_persistent()
73 {
74 // write configuration file
75 RecursiveCreateDirectory(_cfg_dir);
76
77 _cfg.write(_cfg_path);
78 _favorites.write(_favorites_path);
79 }
80
81
82 XMLPos ExplorerGlobals::get_cfg()
83 {
84 XMLPos cfg_pos(&_cfg);
85
86 cfg_pos.smart_create("ibrowser-cfg");
87
88 return cfg_pos;
89 }
90
91 XMLPos ExplorerGlobals::get_cfg(const char* path)
92 {
93 XMLPos cfg_pos(&_cfg);
94
95 cfg_pos.smart_create("ibrowser-cfg");
96 cfg_pos.create_relative(path);
97
98 return cfg_pos;
99 }
100 */
101
102
103 Icon::Icon()
104 : _id(ICID_UNKNOWN),
105 _itype(IT_STATIC),
106 _hicon(0)
107 {
108 }
109
110 Icon::Icon(ICON_ID id, UINT nid)
111 : _id(id),
112 _itype(IT_STATIC),
113 _hicon(SmallIcon(nid))
114 {
115 }
116
117 Icon::Icon(ICON_TYPE itype, int id, HICON hIcon)
118 : _id((ICON_ID)id),
119 _itype(itype),
120 _hicon(hIcon)
121 {
122 }
123
124 Icon::Icon(ICON_TYPE itype, int id, int sys_idx)
125 : _id((ICON_ID)id),
126 _itype(itype),
127 _sys_idx(sys_idx)
128 {
129 }
130
131 void Icon::draw(HDC hdc, int x, int y, int cx, int cy, COLORREF bk_color, HBRUSH bk_brush) const
132 {
133 if (_itype == IT_SYSCACHE)
134 ImageList_DrawEx(g_icon_cache.get_sys_imagelist(), _sys_idx, hdc, x, y, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL);
135 else
136 DrawIconEx(hdc, x, y, _hicon, cx, cy, 0, bk_brush, DI_NORMAL);
137 }
138
139 HBITMAP Icon::create_bitmap(COLORREF bk_color, HBRUSH hbrBkgnd, HDC hdc_wnd) const
140 {
141 if (_itype == IT_SYSCACHE) {
142 HIMAGELIST himl = g_icon_cache.get_sys_imagelist();
143
144 int cx, cy;
145 ImageList_GetIconSize(himl, &cx, &cy);
146
147 HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy);
148 HDC hdc = CreateCompatibleDC(hdc_wnd);
149 HBITMAP hbmp_old = SelectBitmap(hdc, hbmp);
150 ImageList_DrawEx(himl, _sys_idx, hdc, 0, 0, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL);
151 SelectBitmap(hdc, hbmp_old);
152 DeleteDC(hdc);
153
154 return hbmp;
155 } else
156 return create_bitmap_from_icon(_hicon, hbrBkgnd, hdc_wnd);
157 }
158
159
160 int Icon::add_to_imagelist(HIMAGELIST himl, HDC hdc_wnd, COLORREF bk_color, HBRUSH bk_brush) const
161 {
162 int ret;
163
164 if (_itype == IT_SYSCACHE) {
165 HIMAGELIST himl = g_icon_cache.get_sys_imagelist();
166
167 int cx, cy;
168 ImageList_GetIconSize(himl, &cx, &cy);
169
170 HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy);
171 HDC hdc = CreateCompatibleDC(hdc_wnd);
172 HBITMAP hbmp_old = SelectBitmap(hdc, hbmp);
173 ImageList_DrawEx(himl, _sys_idx, hdc, 0, 0, cx, cy, bk_color, CLR_DEFAULT, ILD_NORMAL);
174 SelectBitmap(hdc, hbmp_old);
175 DeleteDC(hdc);
176
177 ret = ImageList_Add(himl, hbmp, 0);
178
179 DeleteObject(hbmp);
180 } else
181 ret = ImageList_AddAlphaIcon(himl, _hicon, bk_brush, hdc_wnd);
182
183 return ret;
184 }
185
186 HBITMAP create_bitmap_from_icon(HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd)
187 {
188 int cx = GetSystemMetrics(SM_CXSMICON);
189 int cy = GetSystemMetrics(SM_CYSMICON);
190 HBITMAP hbmp = CreateCompatibleBitmap(hdc_wnd, cx, cy);
191
192 MemCanvas canvas;
193 BitmapSelection sel(canvas, hbmp);
194
195 RECT rect = {0, 0, cx, cy};
196 FillRect(canvas, &rect, hbrush_bkgnd);
197
198 DrawIconEx(canvas, 0, 0, hIcon, cx, cy, 0, hbrush_bkgnd, DI_NORMAL);
199
200 return hbmp;
201 }
202
203 int ImageList_AddAlphaIcon(HIMAGELIST himl, HICON hIcon, HBRUSH hbrush_bkgnd, HDC hdc_wnd)
204 {
205 HBITMAP hbmp = create_bitmap_from_icon(hIcon, hbrush_bkgnd, hdc_wnd);
206
207 int ret = ImageList_Add(himl, hbmp, 0);
208
209 DeleteObject(hbmp);
210
211 return ret;
212 }
213
214
215 int IconCache::s_next_id = ICID_DYNAMIC;
216
217
218 void IconCache::init()
219 {
220 _icons[ICID_NONE] = Icon(IT_STATIC, ICID_NONE, (HICON)0);
221
222 _icons[ICID_IBROWSER] = Icon(ICID_IBROWSER, IDI_IBROWSER);
223 _icons[ICID_BOOKMARK] = Icon(ICID_BOOKMARK, IDI_DOT_TRANS);
224 }
225
226
227 const Icon& IconCache::extract(const String& path)
228 {
229 PathMap::iterator found = _pathMap.find(path);
230
231 if (found != _pathMap.end())
232 return _icons[found->second];
233
234 SHFILEINFO sfi;
235
236 #if 1 // use system image list
237 HIMAGELIST himlSys = (HIMAGELIST) SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX|SHGFI_SMALLICON);
238
239 if (himlSys) {
240 _himlSys = himlSys;
241
242 const Icon& icon = add(sfi.iIcon/*, IT_SYSCACHE*/);
243 #else
244 if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON)) {
245 const Icon& icon = add(sfi.hIcon, IT_CACHED);
246 #endif
247
248 ///@todo limit cache size
249 _pathMap[path] = icon;
250
251 return icon;
252 } else
253 return _icons[ICID_NONE];
254 }
255
256 const Icon& IconCache::extract(LPCTSTR path, int idx)
257 {
258 CachePair key(path, idx);
259
260 #ifndef __WINE__ ///@todo _tcslwr() for Wine
261 _tcslwr((LPTSTR)key.first.c_str());
262 #endif
263
264 PathIdxMap::iterator found = _pathIdxMap.find(key);
265
266 if (found != _pathIdxMap.end())
267 return _icons[found->second];
268
269 HICON hIcon;
270
271 if ((int)ExtractIconEx(path, idx, NULL, &hIcon, 1) > 0) {
272 const Icon& icon = add(hIcon, IT_CACHED);
273
274 _pathIdxMap[key] = icon;
275
276 return icon;
277 } else {
278
279 ///@todo retreive "http://.../favicon.ico" format icons
280
281 return _icons[ICID_NONE];
282 }
283 }
284
285
286 const Icon& IconCache::add(HICON hIcon, ICON_TYPE type)
287 {
288 int id = ++s_next_id;
289
290 return _icons[id] = Icon(type, id, hIcon);
291 }
292
293 const Icon& IconCache::add(int sys_idx/*, ICON_TYPE type=IT_SYSCACHE*/)
294 {
295 int id = ++s_next_id;
296
297 return _icons[id] = SysCacheIcon(id, sys_idx);
298 }
299
300 const Icon& IconCache::get_icon(int id)
301 {
302 return _icons[id];
303 }
304
305 void IconCache::free_icon(int icon_id)
306 {
307 IconMap::iterator found = _icons.find(icon_id);
308
309 if (found != _icons.end()) {
310 Icon& icon = found->second;
311
312 if (icon.destroy())
313 _icons.erase(found);
314 }
315 }
316
317
318 ResString::ResString(UINT nid)
319 {
320 TCHAR buffer[BUFFER_LEN];
321
322 int len = LoadString(g_hInstance, nid, buffer, sizeof(buffer)/sizeof(TCHAR));
323
324 super::assign(buffer, len);
325 }
326
327
328 ResIcon::ResIcon(UINT nid)
329 {
330 _hicon = LoadIcon(g_hInstance, MAKEINTRESOURCE(nid));
331 }
332
333 SmallIcon::SmallIcon(UINT nid)
334 {
335 _hicon = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED);
336 }
337
338 ResIconEx::ResIconEx(UINT nid, int w, int h)
339 {
340 _hicon = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(nid), IMAGE_ICON, w, h, LR_SHARED);
341 }
342
343
344 void SetWindowIcon(HWND hwnd, UINT nid)
345 {
346 HICON hIcon = ResIcon(nid);
347 (void)Window_SetIcon(hwnd, ICON_BIG, hIcon);
348
349 HICON hIconSmall = SmallIcon(nid);
350 (void)Window_SetIcon(hwnd, ICON_SMALL, hIconSmall);
351 }
352
353
354 ResBitmap::ResBitmap(UINT nid)
355 {
356 _hBmp = LoadBitmap(g_hInstance, MAKEINTRESOURCE(nid));
357 }
358
359
360 void ibrowser_show_frame(int cmdshow, LPTSTR lpCmdLine)
361 {
362 MainFrameBase::Create(lpCmdLine, cmdshow);
363 }
364
365
366 PopupMenu::PopupMenu(UINT nid)
367 {
368 HMENU hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(nid));
369 _hmenu = GetSubMenu(hMenu, 0);
370 }
371
372
373 /// "About" Dialog
374 struct ExplorerAboutDlg : public
375 CtlColorParent<
376 OwnerDrawParent<Dialog>
377 >
378 {
379 typedef CtlColorParent<
380 OwnerDrawParent<Dialog>
381 > super;
382
383 ExplorerAboutDlg(HWND hwnd)
384 : super(hwnd)
385 {
386 SetWindowIcon(hwnd, IDI_REACTOS);
387
388 new FlatButton(hwnd, IDOK);
389
390 _hfont = CreateFont(20, 0, 0, 0, FW_BOLD, TRUE, 0, 0, 0, 0, 0, 0, 0, TEXT("Sans Serif"));
391 new ColorStatic(hwnd, IDC_ROS_IBROWSER, RGB(32,32,128), 0, _hfont);
392
393 new HyperlinkCtrl(hwnd, IDC_WWW);
394
395 FmtString ver_txt(ResString(IDS_IBROWSER_VERSION_STR), (LPCTSTR)ResString(IDS_VERSION_STR));
396 SetWindowText(GetDlgItem(hwnd, IDC_VERSION_TXT), ver_txt);
397
398 /*@@
399 HWND hwnd_winver = GetDlgItem(hwnd, IDC_WIN_VERSION);
400 SetWindowText(hwnd_winver, get_windows_version_str());
401 SetWindowFont(hwnd_winver, GetStockFont(DEFAULT_GUI_FONT), FALSE);
402 */
403
404 CenterWindow(hwnd);
405 }
406
407 ~ExplorerAboutDlg()
408 {
409 DeleteObject(_hfont);
410 }
411
412 protected:
413 HFONT _hfont;
414 };
415
416 void ibrowser_about(HWND hwndParent)
417 {
418 Dialog::DoModal(IDD_ABOUT_IBROWSER, WINDOW_CREATOR(ExplorerAboutDlg), hwndParent);
419 }
420 void ibrowser_open(HWND hwndParent)
421 {
422 HMODULE hShell32;
423 RUNFILEDLG RunFileDlg;
424 OSVERSIONINFO versionInfo;
425 WCHAR wTitle[40];
426 WCHAR wText[256];
427 char szTitle[40] = "Open";
428 char szText[256] = "Type the Internet Address of a document or folder and IBrowser will open it for you.";
429
430 hShell32 = LoadLibrary(_T("SHELL32.DLL"));
431 RunFileDlg = (RUNFILEDLG)(FARPROC)GetProcAddress(hShell32, (char*)((long)0x3D));
432
433 /* Show "Run..." dialog */
434 if (RunFileDlg)
435 {
436 versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
437 GetVersionEx(&versionInfo);
438
439 if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
440 {
441 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szTitle, -1, wTitle, 40);
442 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szText, -1, wText, 256);
443 RunFileDlg(hwndParent, 0, NULL, (LPCSTR)wTitle, (LPCSTR)wText, RFF_CALCDIRECTORY);
444 }
445 else
446 RunFileDlg(hwndParent, 0, NULL, szTitle, szText, RFF_CALCDIRECTORY);
447 }
448
449 FreeLibrary(hShell32);
450 }
451
452 static void InitInstance(HINSTANCE hInstance)
453 {
454 CONTEXT("InitInstance");
455
456 // register frame window class
457 g_hframeClass = IconWindowClass(CLASSNAME_FRAME,IDI_IBROWSER);
458
459 // register child window class
460 WindowClass(CLASSNAME_CHILDWND, CS_CLASSDC|CS_VREDRAW).Register();
461 }
462
463
464 int ibrowser_main(HINSTANCE hInstance, LPTSTR lpCmdLine, int cmdshow)
465 {
466 CONTEXT("ibrowser_main");
467
468 // initialize Common Controls library
469 CommonControlInit usingCmnCtrl;
470
471 try {
472 InitInstance(hInstance);
473 } catch(COMException& e) {
474 HandleException(e, GetDesktopWindow());
475 return -1;
476 }
477
478 if (cmdshow != SW_HIDE) {
479 /* // don't maximize if being called from the ROS desktop
480 if (cmdshow == SW_SHOWNORMAL)
481 ///@todo read window placement from registry
482 cmdshow = SW_MAXIMIZE;
483 */
484
485 ibrowser_show_frame(cmdshow, lpCmdLine);
486 }
487
488 return Window::MessageLoop();
489 }
490
491
492 // MinGW does not provide a Unicode startup routine, so we have to implement an own.
493 #if defined(__MINGW32__) && defined(UNICODE)
494
495 #define _tWinMain wWinMain
496 int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int);
497
498 int main(int argc, char* argv[])
499 {
500 CONTEXT("main");
501
502 STARTUPINFO startupinfo;
503 int nShowCmd = SW_SHOWNORMAL;
504
505 GetStartupInfo(&startupinfo);
506
507 if (startupinfo.dwFlags & STARTF_USESHOWWINDOW)
508 nShowCmd = startupinfo.wShowWindow;
509
510 LPWSTR cmdline = GetCommandLineW();
511
512 while(*cmdline && !_istspace(*cmdline))
513 ++cmdline;
514
515 while(_istspace(*cmdline))
516 ++cmdline;
517
518 return wWinMain(GetModuleHandle(NULL), 0, cmdline, nShowCmd);
519 }
520
521 #endif // __MINGW && UNICODE
522
523
524 int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
525 {
526 CONTEXT("WinMain()");
527
528 g_hInstance = hInstance;
529
530 // initialize COM and OLE before creating the desktop window
531 OleInit usingCOM;
532
533 // init common controls library
534 CommonControlInit usingCmnCtrl;
535
536 //@@ g_Globals.read_persistent();
537
538 /**TODO fix command line handling */
539 if (*lpCmdLine=='"' && lpCmdLine[_tcslen(lpCmdLine)-1]=='"') {
540 ++lpCmdLine;
541 lpCmdLine[_tcslen(lpCmdLine)-1] = '\0';
542 }
543
544 int ret = ibrowser_main(hInstance, lpCmdLine, nShowCmd);
545
546 // write configuration file
547 //@@ g_Globals.write_persistent();
548
549 return ret;
550 }