Implement CryptImport/ExportPublicKeyInfo.
[wine] / dlls / hhctrl.ocx / help.c
1 /*
2  * Help Viewer Implementation
3  *
4  * Copyright 2005 James Hawkins
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "winnls.h"
28 #include "commctrl.h"
29 #include "htmlhelp.h"
30 #include "ole2.h"
31 #include "wine/unicode.h"
32
33 #include "resource.h"
34 #include "chm.h"
35 #include "webbrowser.h"
36
37 /* Window type defaults */
38
39 #define WINTYPE_DEFAULT_X           280
40 #define WINTYPE_DEFAULT_Y           100
41 #define WINTYPE_DEFAULT_WIDTH       740
42 #define WINTYPE_DEFAULT_HEIGHT      640
43 #define WINTYPE_DEFAULT_NAVWIDTH    250
44
45 static const WCHAR szEmpty[] = {0};
46
47 typedef struct tagHHInfo
48 {
49     HH_WINTYPEW *pHHWinType;
50     CHMInfo *pCHMInfo;
51     WBInfo *pWBInfo;
52     HINSTANCE hInstance;
53     LPWSTR szCmdLine;
54     HWND hwndTabCtrl;
55     HWND hwndSizeBar;
56     HFONT hFont;
57 } HHInfo;
58
59 extern HINSTANCE hhctrl_hinstance;
60
61 static LPWSTR HH_ANSIToUnicode(LPCSTR ansi)
62 {
63     LPWSTR unicode;
64     int count;
65
66     count = MultiByteToWideChar(CP_ACP, 0, ansi, -1, NULL, 0);
67     unicode = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
68     MultiByteToWideChar(CP_ACP, 0, ansi, -1, unicode, count);
69
70     return unicode;
71 }
72
73 /* Loads a string from the resource file */
74 static LPWSTR HH_LoadString(DWORD dwID)
75 {
76     LPWSTR string = NULL;
77     int iSize;
78
79     iSize = LoadStringW(hhctrl_hinstance, dwID, NULL, 0);
80     iSize += 2; /* some strings (tab text) needs double-null termination */
81
82     string = HeapAlloc(GetProcessHeap(), 0, iSize * sizeof(WCHAR));
83     LoadStringW(hhctrl_hinstance, dwID, string, iSize);
84
85     return string;
86 }
87
88 /* Size Bar */
89
90 #define SIZEBAR_WIDTH   4
91
92 static const WCHAR szSizeBarClass[] = {
93     'H','H',' ','S','i','z','e','B','a','r',0
94 };
95
96 /* Draw the SizeBar */
97 static void SB_OnPaint(HWND hWnd)
98 {
99     PAINTSTRUCT ps;
100     HDC hdc;
101     RECT rc;
102     
103     hdc = BeginPaint(hWnd, &ps);
104
105     GetClientRect(hWnd, &rc);
106
107     /* dark frame */
108     rc.right += 1;
109     rc.bottom -= 1;
110     FrameRect(hdc, &rc, GetStockObject(GRAY_BRUSH));
111
112     /* white highlight */
113     SelectObject(hdc, GetStockObject(WHITE_PEN));
114     MoveToEx(hdc, rc.right, 1, NULL);
115     LineTo(hdc, 1, 1);
116     LineTo(hdc, 1, rc.bottom - 1);
117
118     
119     MoveToEx(hdc, 0, rc.bottom, NULL);
120     LineTo(hdc, rc.right, rc.bottom);
121
122     EndPaint(hWnd, &ps);
123 }
124
125 LRESULT CALLBACK SizeBar_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
126 {
127     switch (message)
128     {
129         case WM_PAINT:
130             SB_OnPaint(hWnd);
131             break;
132         default:
133             return DefWindowProcW(hWnd, message, wParam, lParam);
134     }
135
136     return 0;
137 }
138
139 static void HH_RegisterSizeBarClass(HHInfo *pHHInfo)
140 {
141     WNDCLASSEXW wcex;
142
143     wcex.cbSize         = sizeof(WNDCLASSEXW);
144     wcex.style          = 0;
145     wcex.lpfnWndProc    = (WNDPROC)SizeBar_WndProc;
146     wcex.cbClsExtra     = 0;
147     wcex.cbWndExtra     = 0;
148     wcex.hInstance      = pHHInfo->hInstance;
149     wcex.hIcon          = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
150     wcex.hCursor        = LoadCursorW(NULL, (LPCWSTR)IDC_SIZEWE);
151     wcex.hbrBackground  = (HBRUSH)(COLOR_MENU + 1);
152     wcex.lpszMenuName   = NULL;
153     wcex.lpszClassName  = szSizeBarClass;
154     wcex.hIconSm        = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
155
156     RegisterClassExW(&wcex);
157 }
158
159 static void SB_GetSizeBarRect(HHInfo *pHHInfo, RECT *rc)
160 {
161     RECT rectWND, rectTB, rectNP;
162
163     GetClientRect(pHHInfo->pHHWinType->hwndHelp, &rectWND);
164     GetClientRect(pHHInfo->pHHWinType->hwndToolBar, &rectTB);
165     GetClientRect(pHHInfo->pHHWinType->hwndNavigation, &rectNP);
166
167     rc->left = rectNP.right;
168     rc->top = rectTB.bottom;
169     rc->bottom = rectWND.bottom - rectTB.bottom;
170     rc->right = SIZEBAR_WIDTH;
171 }
172
173 static BOOL HH_AddSizeBar(HHInfo *pHHInfo)
174 {
175     HWND hWnd;
176     HWND hwndParent = pHHInfo->pHHWinType->hwndHelp;
177     DWORD dwStyles = WS_CHILDWINDOW | WS_VISIBLE | WS_OVERLAPPED;
178     DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
179     RECT rc;
180
181     SB_GetSizeBarRect(pHHInfo, &rc);
182
183     hWnd = CreateWindowExW(dwExStyles, szSizeBarClass, szEmpty, dwStyles,
184                            rc.left, rc.top, rc.right, rc.bottom,
185                            hwndParent, NULL, pHHInfo->hInstance, NULL);
186     if (!hWnd)
187         return FALSE;
188
189     pHHInfo->hwndSizeBar = hWnd;
190     return TRUE;
191 }
192
193 /* Child Window */
194
195 static const WCHAR szChildClass[] = {
196     'H','H',' ','C','h','i','l','d',0
197 };
198
199 static void Child_OnPaint(HWND hWnd)
200 {
201     PAINTSTRUCT ps;
202     HDC hdc;
203     RECT rc;
204
205     hdc = BeginPaint(hWnd, &ps);
206
207     /* Only paint the Navigation pane, identified by the fact
208      * that it has a child window
209      */
210     if (GetWindow(hWnd, GW_CHILD))
211     {
212         GetClientRect(hWnd, &rc);
213
214         /* set the border color */
215         SelectObject(hdc, GetStockObject(DC_PEN));
216         SetDCPenColor(hdc, GetSysColor(COLOR_BTNSHADOW));
217
218         /* Draw the top border */
219         LineTo(hdc, rc.right, 0);
220
221         SelectObject(hdc, GetStockObject(WHITE_PEN));
222         MoveToEx(hdc, 0, 1, NULL);
223         LineTo(hdc, rc.right, 1);
224     }
225
226     EndPaint(hWnd, &ps);
227 }
228
229 LRESULT CALLBACK Child_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
230 {
231     switch (message)
232     {
233         case WM_PAINT:
234             Child_OnPaint(hWnd);
235             break;
236         default:
237             return DefWindowProcW(hWnd, message, wParam, lParam);
238     }
239
240     return 0;
241 }
242
243 static void HH_RegisterChildWndClass(HHInfo *pHHInfo)
244 {
245     WNDCLASSEXW wcex;
246
247     wcex.cbSize         = sizeof(WNDCLASSEXW);
248     wcex.style          = 0;
249     wcex.lpfnWndProc    = (WNDPROC)Child_WndProc;
250     wcex.cbClsExtra     = 0;
251     wcex.cbWndExtra     = 0;
252     wcex.hInstance      = pHHInfo->hInstance;
253     wcex.hIcon          = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
254     wcex.hCursor        = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
255     wcex.hbrBackground  = (HBRUSH)(COLOR_BTNFACE + 1);
256     wcex.lpszMenuName   = NULL;
257     wcex.lpszClassName  = szChildClass;
258     wcex.hIconSm        = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
259
260     RegisterClassExW(&wcex);
261 }
262
263 /* Toolbar */
264
265 #define ICON_SIZE   20
266
267 static void TB_OnClick(HWND hWnd, DWORD dwID)
268 {
269     HHInfo *pHHInfo = (HHInfo *)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
270
271     switch (dwID)
272     {
273         case IDTB_STOP:
274             WB_DoPageAction(pHHInfo->pWBInfo, WB_STOP);
275             break;
276         case IDTB_REFRESH:
277             WB_DoPageAction(pHHInfo->pWBInfo, WB_REFRESH);
278             break;
279         case IDTB_BACK:
280             WB_DoPageAction(pHHInfo->pWBInfo, WB_GOBACK);
281             break;
282         case IDTB_HOME:
283         {
284             WCHAR szUrl[MAX_PATH];
285
286             CHM_CreateITSUrl(pHHInfo->pCHMInfo, pHHInfo->pHHWinType->pszHome, szUrl);
287             WB_Navigate(pHHInfo->pWBInfo, szUrl);
288             break;
289         }
290         case IDTB_FORWARD:
291             WB_DoPageAction(pHHInfo->pWBInfo, WB_GOFORWARD);
292             break;
293         case IDTB_EXPAND:
294         case IDTB_CONTRACT:
295         case IDTB_SYNC:
296         case IDTB_PRINT:
297         case IDTB_OPTIONS:
298         case IDTB_BROWSE_FWD:
299         case IDTB_BROWSE_BACK:
300         case IDTB_JUMP1:
301         case IDTB_JUMP2:
302         case IDTB_CUSTOMIZE:
303         case IDTB_ZOOM:
304         case IDTB_TOC_NEXT:
305         case IDTB_TOC_PREV:
306             break;
307     }
308 }
309
310 static void TB_AddButton(TBBUTTON *pButtons, DWORD dwIndex, DWORD dwID)
311 {
312     /* FIXME: Load the correct button bitmaps */
313     pButtons[dwIndex].iBitmap = STD_PRINT;
314     pButtons[dwIndex].idCommand = dwID;
315     pButtons[dwIndex].fsState = TBSTATE_ENABLED;
316     pButtons[dwIndex].fsStyle = BTNS_BUTTON;
317     pButtons[dwIndex].dwData = 0;
318     pButtons[dwIndex].iString = 0;
319 }
320
321 static void TB_AddButtonsFromFlags(TBBUTTON *pButtons, DWORD dwButtonFlags, LPDWORD pdwNumButtons)
322 {
323     *pdwNumButtons = 0;
324
325     if (dwButtonFlags & HHWIN_BUTTON_EXPAND)
326         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_EXPAND);
327
328     if (dwButtonFlags & HHWIN_BUTTON_BACK)
329         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_BACK);
330
331     if (dwButtonFlags & HHWIN_BUTTON_FORWARD)
332         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_FORWARD);
333
334     if (dwButtonFlags & HHWIN_BUTTON_STOP)
335         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_STOP);
336
337     if (dwButtonFlags & HHWIN_BUTTON_REFRESH)
338         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_REFRESH);
339
340     if (dwButtonFlags & HHWIN_BUTTON_HOME)
341         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_HOME);
342
343     if (dwButtonFlags & HHWIN_BUTTON_SYNC)
344         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_SYNC);
345
346     if (dwButtonFlags & HHWIN_BUTTON_OPTIONS)
347         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_OPTIONS);
348
349     if (dwButtonFlags & HHWIN_BUTTON_PRINT)
350         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_PRINT);
351
352     if (dwButtonFlags & HHWIN_BUTTON_JUMP1)
353         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_JUMP1);
354
355     if (dwButtonFlags & HHWIN_BUTTON_JUMP2)
356         TB_AddButton(pButtons,(*pdwNumButtons)++, IDTB_JUMP2);
357
358     if (dwButtonFlags & HHWIN_BUTTON_ZOOM)
359         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_ZOOM);
360
361     if (dwButtonFlags & HHWIN_BUTTON_TOC_NEXT)
362         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_TOC_NEXT);
363
364     if (dwButtonFlags & HHWIN_BUTTON_TOC_PREV)
365         TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_TOC_PREV);
366 }
367
368 static BOOL HH_AddToolbar(HHInfo *pHHInfo)
369 {
370     HWND hToolbar;
371     HWND hwndParent = pHHInfo->pHHWinType->hwndHelp;
372     DWORD toolbarFlags;
373     TBBUTTON buttons[IDTB_TOC_PREV - IDTB_EXPAND];
374     TBADDBITMAP tbAB;
375     DWORD dwStyles, dwExStyles;
376     DWORD dwNumButtons, dwIndex;
377
378     if (pHHInfo->pHHWinType->fsWinProperties & HHWIN_PARAM_TB_FLAGS)
379         toolbarFlags = pHHInfo->pHHWinType->fsToolBarFlags;
380     else
381         toolbarFlags = HHWIN_DEF_BUTTONS;
382
383     TB_AddButtonsFromFlags(buttons, toolbarFlags, &dwNumButtons);
384
385     dwStyles = WS_CHILDWINDOW | WS_VISIBLE | TBSTYLE_FLAT |
386                TBSTYLE_WRAPABLE | TBSTYLE_TOOLTIPS | CCS_NODIVIDER;
387     dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
388
389     hToolbar = CreateWindowExW(dwExStyles, TOOLBARCLASSNAMEW, NULL, dwStyles,
390                                0, 0, 0, 0, hwndParent, NULL,
391                                pHHInfo->hInstance, NULL);
392     if (!hToolbar)
393         return FALSE;
394
395     SendMessageW(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(ICON_SIZE, ICON_SIZE));
396     SendMessageW(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
397     SendMessageW(hToolbar, WM_SETFONT, (WPARAM)pHHInfo->hFont, TRUE);
398
399     /* FIXME: Load correct icons for all buttons */
400     tbAB.hInst = HINST_COMMCTRL;
401     tbAB.nID = IDB_STD_LARGE_COLOR;
402     SendMessageW(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbAB);
403
404     for (dwIndex = 0; dwIndex < dwNumButtons; dwIndex++)
405     {
406         LPWSTR szBuf = HH_LoadString(buttons[dwIndex].idCommand);
407         DWORD dwLen = strlenW(szBuf);
408         szBuf[dwLen + 2] = 0; /* Double-null terminate */
409
410         buttons[dwIndex].iString = (DWORD)SendMessageW(hToolbar, TB_ADDSTRINGW, 0, (LPARAM)szBuf);
411         HeapFree(GetProcessHeap(), 0, szBuf);
412     }
413
414     SendMessageW(hToolbar, TB_ADDBUTTONSW, dwNumButtons, (LPARAM)&buttons);
415     SendMessageW(hToolbar, TB_AUTOSIZE, 0, 0);
416     ShowWindow(hToolbar, SW_SHOW);
417
418     pHHInfo->pHHWinType->hwndToolBar = hToolbar;
419     return TRUE;
420 }
421
422 /* Navigation Pane */
423
424 #define TAB_TOP_PADDING     8
425 #define TAB_RIGHT_PADDING   4
426
427 static void NP_GetNavigationRect(HHInfo *pHHInfo, RECT *rc)
428 {
429     HWND hwndParent = pHHInfo->pHHWinType->hwndHelp;
430     HWND hwndToolbar = pHHInfo->pHHWinType->hwndToolBar;
431     RECT rectWND, rectTB;
432
433     GetClientRect(hwndParent, &rectWND);
434     GetClientRect(hwndToolbar, &rectTB);
435
436     rc->left = 0;
437     rc->top = rectTB.bottom;
438     rc->bottom = rectWND.bottom - rectTB.bottom;
439
440     if (pHHInfo->pHHWinType->fsValidMembers & HHWIN_PARAM_NAV_WIDTH)
441         rc->right = pHHInfo->pHHWinType->iNavWidth;
442     else
443         rc->right = WINTYPE_DEFAULT_NAVWIDTH;
444 }
445
446 static void NP_CreateTab(HINSTANCE hInstance, HWND hwndTabCtrl, DWORD dwStrID, DWORD dwIndex)
447 {
448     TCITEMW tie;
449     LPWSTR tabText = HH_LoadString(dwStrID);
450
451     tie.mask = TCIF_TEXT;
452     tie.pszText = tabText;
453
454     TabCtrl_InsertItemW(hwndTabCtrl, dwIndex, &tie);
455     HeapFree(GetProcessHeap(), 0, tabText);
456 }
457
458 static BOOL HH_AddNavigationPane(HHInfo *pHHInfo)
459 {
460     HWND hWnd, hwndTabCtrl;
461     HWND hwndParent = pHHInfo->pHHWinType->hwndHelp;
462     DWORD dwStyles = WS_CHILDWINDOW | WS_VISIBLE;
463     DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
464     DWORD dwIndex = 0;
465     RECT rc;
466
467     NP_GetNavigationRect(pHHInfo, &rc);
468
469     hWnd = CreateWindowExW(dwExStyles, szChildClass, szEmpty, dwStyles,
470                            rc.left, rc.top, rc.right, rc.bottom,
471                            hwndParent, NULL, pHHInfo->hInstance, NULL);
472     if (!hWnd)
473         return FALSE;
474
475     hwndTabCtrl = CreateWindowExW(dwExStyles, WC_TABCONTROLW, szEmpty, dwStyles,
476                                   0, TAB_TOP_PADDING,
477                                   rc.right - TAB_RIGHT_PADDING,
478                                   rc.bottom - TAB_TOP_PADDING,
479                                   hWnd, NULL, pHHInfo->hInstance, NULL);
480     if (!hwndTabCtrl)
481         return FALSE;
482
483     if (*pHHInfo->pHHWinType->pszToc)
484         NP_CreateTab(pHHInfo->hInstance, hwndTabCtrl, IDS_CONTENTS, dwIndex++);
485
486     if (*pHHInfo->pHHWinType->pszIndex)
487         NP_CreateTab(pHHInfo->hInstance, hwndTabCtrl, IDS_INDEX, dwIndex++);
488
489     if (pHHInfo->pHHWinType->fsWinProperties & HHWIN_PROP_TAB_SEARCH)
490         NP_CreateTab(pHHInfo->hInstance, hwndTabCtrl, IDS_SEARCH, dwIndex++);
491
492     if (pHHInfo->pHHWinType->fsWinProperties & HHWIN_PROP_TAB_FAVORITES)
493         NP_CreateTab(pHHInfo->hInstance, hwndTabCtrl, IDS_FAVORITES, dwIndex++);
494
495     SendMessageW(hwndTabCtrl, WM_SETFONT, (WPARAM)pHHInfo->hFont, TRUE);
496
497     pHHInfo->hwndTabCtrl = hwndTabCtrl;
498     pHHInfo->pHHWinType->hwndNavigation = hWnd;
499     return TRUE;
500 }
501
502 /* HTML Pane */
503
504 static void HP_GetHTMLRect(HHInfo *pHHInfo, RECT *rc)
505 {
506     RECT rectTB, rectWND, rectNP, rectSB;
507
508     GetClientRect(pHHInfo->pHHWinType->hwndHelp, &rectWND);
509     GetClientRect(pHHInfo->pHHWinType->hwndToolBar, &rectTB);
510     GetClientRect(pHHInfo->pHHWinType->hwndNavigation, &rectNP);
511     GetClientRect(pHHInfo->hwndSizeBar, &rectSB);
512
513     rc->left = rectNP.right + rectSB.right;
514     rc->top = rectTB.bottom;
515     rc->right = rectWND.right - rc->left;
516     rc->bottom = rectWND.bottom - rectTB.bottom;
517 }
518
519 static BOOL HH_AddHTMLPane(HHInfo *pHHInfo)
520 {
521     HWND hWnd;
522     HWND hwndParent = pHHInfo->pHHWinType->hwndHelp;
523     DWORD dwStyles = WS_CHILDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN;
524     DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_CLIENTEDGE;
525     RECT rc;
526
527     HP_GetHTMLRect(pHHInfo, &rc);
528
529     hWnd = CreateWindowExW(dwExStyles, szChildClass, szEmpty, dwStyles,
530                            rc.left, rc.top, rc.right, rc.bottom,
531                            hwndParent, NULL, pHHInfo->hInstance, NULL);
532     if (!hWnd)
533         return FALSE;
534
535     if (!WB_EmbedBrowser(pHHInfo->pWBInfo, hWnd))
536         return FALSE;
537
538     /* store the pointer to the HH info struct */
539     SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)pHHInfo);
540
541     ShowWindow(hWnd, SW_SHOW);
542     UpdateWindow(hWnd);
543
544     pHHInfo->pHHWinType->hwndHTML = hWnd;
545     return TRUE;
546 }
547
548 /* Viewer Window */
549
550 static void Help_OnSize(HWND hWnd)
551 {
552     HHInfo *pHHInfo = (HHInfo *)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
553     DWORD dwSize;
554     RECT rc;
555
556     if (!pHHInfo)
557         return;
558
559     NP_GetNavigationRect(pHHInfo, &rc);
560     SetWindowPos(pHHInfo->pHHWinType->hwndNavigation, HWND_TOP, 0, 0,
561                  rc.right, rc.bottom, SWP_NOMOVE);
562
563     GetClientRect(pHHInfo->pHHWinType->hwndNavigation, &rc);
564     SetWindowPos(pHHInfo->hwndTabCtrl, HWND_TOP, 0, 0,
565                  rc.right - TAB_RIGHT_PADDING,
566                  rc.bottom - TAB_TOP_PADDING, SWP_NOMOVE);
567
568     SB_GetSizeBarRect(pHHInfo, &rc);
569     SetWindowPos(pHHInfo->hwndSizeBar, HWND_TOP, rc.left, rc.top,
570                  rc.right, rc.bottom, SWP_SHOWWINDOW);
571
572     HP_GetHTMLRect(pHHInfo, &rc);
573     SetWindowPos(pHHInfo->pHHWinType->hwndHTML, HWND_TOP, rc.left, rc.top,
574                  rc.right, rc.bottom, SWP_SHOWWINDOW);
575
576     /* Resize browser window taking the frame size into account */
577     dwSize = GetSystemMetrics(SM_CXFRAME);
578     WB_ResizeBrowser(pHHInfo->pWBInfo, rc.right - dwSize, rc.bottom - dwSize);
579 }
580
581 LRESULT CALLBACK Help_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
582 {
583     PAINTSTRUCT ps;
584     HDC hdc;
585
586     switch (message)
587     {
588         case WM_COMMAND:
589             if (HIWORD(wParam) == BN_CLICKED)
590                 TB_OnClick(hWnd, LOWORD(wParam));
591             break;
592         case WM_SIZE:
593             Help_OnSize(hWnd);
594             break;
595         case WM_PAINT:
596             hdc = BeginPaint(hWnd, &ps);
597             EndPaint(hWnd, &ps);
598             break;
599         case WM_DESTROY:
600             PostQuitMessage(0);
601             break;
602
603         default:
604             return DefWindowProcW(hWnd, message, wParam, lParam);
605     }
606
607     return 0;
608 }
609
610 static BOOL HH_CreateHelpWindow(HHInfo *pHHInfo)
611 {
612     HWND hWnd;
613     HINSTANCE hInstance = pHHInfo->hInstance;
614     RECT winPos = pHHInfo->pHHWinType->rcWindowPos;
615     WNDCLASSEXW wcex;
616     DWORD dwStyles, dwExStyles;
617     DWORD x, y, width, height;
618
619     static const WCHAR windowClassW[] = {
620         'H','H',' ', 'P','a','r','e','n','t',0
621     };
622
623     wcex.cbSize         = sizeof(WNDCLASSEXW);
624     wcex.style          = CS_HREDRAW | CS_VREDRAW;
625     wcex.lpfnWndProc    = (WNDPROC)Help_WndProc;
626     wcex.cbClsExtra     = 0;
627     wcex.cbWndExtra     = 0;
628     wcex.hInstance      = hInstance;
629     wcex.hIcon          = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
630     wcex.hCursor        = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
631     wcex.hbrBackground  = (HBRUSH)(COLOR_MENU + 1);
632     wcex.lpszMenuName   = NULL;
633     wcex.lpszClassName  = windowClassW;
634     wcex.hIconSm        = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
635
636     RegisterClassExW(&wcex);
637
638     /* Read in window parameters if available */
639     if (pHHInfo->pHHWinType->fsValidMembers & HHWIN_PARAM_STYLES)
640         dwStyles = pHHInfo->pHHWinType->dwStyles;
641     else
642         dwStyles = WS_OVERLAPPEDWINDOW | WS_VISIBLE |
643                    WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
644
645     if (pHHInfo->pHHWinType->fsValidMembers & HHWIN_PARAM_EXSTYLES)
646         dwExStyles = pHHInfo->pHHWinType->dwExStyles;
647     else
648         dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_APPWINDOW |
649                      WS_EX_WINDOWEDGE | WS_EX_RIGHTSCROLLBAR;
650
651     if (pHHInfo->pHHWinType->fsValidMembers & HHWIN_PARAM_RECT)
652     {
653         x = winPos.left;
654         y = winPos.top;
655         width = winPos.right - x;
656         height = winPos.bottom - y;
657     }
658     else
659     {
660         x = WINTYPE_DEFAULT_X;
661         y = WINTYPE_DEFAULT_Y;
662         width = WINTYPE_DEFAULT_WIDTH;
663         height = WINTYPE_DEFAULT_HEIGHT;
664     }
665
666     hWnd = CreateWindowExW(dwExStyles, windowClassW, pHHInfo->pHHWinType->pszCaption,
667                            dwStyles, x, y, width, height, NULL, NULL, hInstance, NULL);
668     if (!hWnd)
669         return FALSE;
670
671     ShowWindow(hWnd, SW_SHOW);
672     UpdateWindow(hWnd);
673
674     /* store the pointer to the HH info struct */
675     SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)pHHInfo);
676
677     pHHInfo->pHHWinType->hwndHelp = hWnd;
678     return TRUE;
679 }
680
681 static void HH_CreateFont(HHInfo *pHHInfo)
682 {
683     LOGFONTW lf;
684
685     GetObjectW(GetStockObject(ANSI_VAR_FONT), sizeof(LOGFONTW), &lf);
686     lf.lfWeight = FW_NORMAL;
687     lf.lfItalic = FALSE;
688     lf.lfUnderline = FALSE;
689
690     pHHInfo->hFont = CreateFontIndirectW(&lf);
691 }
692
693 static void HH_InitRequiredControls(DWORD dwControls)
694 {
695     INITCOMMONCONTROLSEX icex;
696
697     icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
698     icex.dwICC = dwControls;
699     InitCommonControlsEx(&icex);
700 }
701
702 /* Creates the whole package */
703 static BOOL HH_CreateViewer(HHInfo *pHHInfo)
704 {
705     HH_CreateFont(pHHInfo);
706
707     if (!HH_CreateHelpWindow(pHHInfo))
708         return FALSE;
709
710     HH_InitRequiredControls(ICC_BAR_CLASSES);
711
712     if (!HH_AddToolbar(pHHInfo))
713         return FALSE;
714
715     HH_RegisterChildWndClass(pHHInfo);
716
717     if (!HH_AddNavigationPane(pHHInfo))
718         return FALSE;
719
720     HH_RegisterSizeBarClass(pHHInfo);
721
722     if (!HH_AddSizeBar(pHHInfo))
723         return FALSE;
724
725     if (!HH_AddHTMLPane(pHHInfo))
726         return FALSE;
727
728     return TRUE;
729 }
730
731 static HHInfo *HH_OpenHH(HINSTANCE hInstance, LPWSTR szCmdLine)
732 {
733     HHInfo *pHHInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HHInfo));
734
735     pHHInfo->pHHWinType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HH_WINTYPEW));
736     pHHInfo->pCHMInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(CHMInfo));
737     pHHInfo->pWBInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(WBInfo));
738     pHHInfo->hInstance = hInstance;
739     pHHInfo->szCmdLine = szCmdLine;
740
741     return pHHInfo;
742 }
743
744 static void HH_Close(HHInfo *pHHInfo)
745 {
746     if (!pHHInfo)
747         return;
748
749     /* Free allocated strings */
750     if (pHHInfo->pHHWinType)
751     {
752         HeapFree(GetProcessHeap(), 0, (LPWSTR)pHHInfo->pHHWinType->pszType);
753         HeapFree(GetProcessHeap(), 0, (LPWSTR)pHHInfo->pHHWinType->pszCaption);
754         HeapFree(GetProcessHeap(), 0, (LPWSTR)pHHInfo->pHHWinType->pszToc);
755         HeapFree(GetProcessHeap(), 0, (LPWSTR)pHHInfo->pHHWinType->pszType);
756         HeapFree(GetProcessHeap(), 0, (LPWSTR)pHHInfo->pHHWinType->pszIndex);
757         HeapFree(GetProcessHeap(), 0, (LPWSTR)pHHInfo->pHHWinType->pszFile);
758         HeapFree(GetProcessHeap(), 0, (LPWSTR)pHHInfo->pHHWinType->pszHome);
759         HeapFree(GetProcessHeap(), 0, (LPWSTR)pHHInfo->pHHWinType->pszJump1);
760         HeapFree(GetProcessHeap(), 0, (LPWSTR)pHHInfo->pHHWinType->pszJump2);
761         HeapFree(GetProcessHeap(), 0, (LPWSTR)pHHInfo->pHHWinType->pszUrlJump1);
762         HeapFree(GetProcessHeap(), 0, (LPWSTR)pHHInfo->pHHWinType->pszUrlJump2);
763     }
764
765     HeapFree(GetProcessHeap(), 0, pHHInfo->pHHWinType);
766     HeapFree(GetProcessHeap(), 0, pHHInfo->szCmdLine);
767
768     if (pHHInfo->pCHMInfo)
769     {
770         CHM_CloseCHM(pHHInfo->pCHMInfo);
771         HeapFree(GetProcessHeap(), 0, pHHInfo->pCHMInfo);
772     }
773
774     if (pHHInfo->pWBInfo)
775     {
776         WB_UnEmbedBrowser(pHHInfo->pWBInfo);
777         HeapFree(GetProcessHeap(), 0, pHHInfo->pWBInfo);
778     }
779 }
780
781 static void HH_OpenDefaultTopic(HHInfo *pHHInfo)
782 {
783     WCHAR url[MAX_PATH];
784     LPCWSTR defTopic = pHHInfo->pHHWinType->pszFile;
785
786     CHM_CreateITSUrl(pHHInfo->pCHMInfo, defTopic, url);
787     WB_Navigate(pHHInfo->pWBInfo, url);
788 }
789
790 static BOOL HH_OpenCHM(HHInfo *pHHInfo)
791 {
792     if (!CHM_OpenCHM(pHHInfo->pCHMInfo, pHHInfo->szCmdLine))
793         return FALSE;
794
795     if (!CHM_LoadWinTypeFromCHM(pHHInfo->pCHMInfo, pHHInfo->pHHWinType))
796         return FALSE;
797
798     return TRUE;
799 }
800
801 /* FIXME: Check szCmdLine for bad arguments */
802 int WINAPI doWinMain(HINSTANCE hInstance, LPSTR szCmdLine)
803 {
804     MSG msg;
805     HHInfo *pHHInfo;
806
807     if (OleInitialize(NULL) != S_OK)
808         return -1;
809
810     pHHInfo = HH_OpenHH(hInstance, HH_ANSIToUnicode(szCmdLine));
811     if (!pHHInfo || !HH_OpenCHM(pHHInfo) || !HH_CreateViewer(pHHInfo))
812     {
813         OleUninitialize();
814         return -1;
815     }
816
817     HH_OpenDefaultTopic(pHHInfo);
818     
819     while (GetMessageW(&msg, 0, 0, 0))
820     {
821         TranslateMessage(&msg);
822         DispatchMessageW(&msg);
823     }
824
825     HH_Close(pHHInfo);
826     HeapFree(GetProcessHeap(), 0, pHHInfo);
827     OleUninitialize();
828
829     return 0;
830 }