4 * Copyright 1996 Ulrich Schmid <uschmid@mail.hh.provi.de>
13 static BOOL
WINHELP_RegisterWinClasses();
14 static LRESULT CALLBACK
WINHELP_MainWndProc(HWND
, UINT
, WPARAM
, LPARAM
);
15 static LRESULT CALLBACK
WINHELP_TextWndProc(HWND
, UINT
, WPARAM
, LPARAM
);
16 static LRESULT CALLBACK
WINHELP_ButtonBoxWndProc(HWND
, UINT
, WPARAM
, LPARAM
);
17 static VOID
WINHELP_CheckPopup(UINT
);
18 static BOOL
WINHELP_SplitLines(HWND hWnd
, LPSIZE
);
19 static VOID
WINHELP_InitFonts(HWND hWnd
);
20 static VOID
WINHELP_DeleteLines(WINHELP_WINDOW
*);
21 static VOID
WINHELP_DeleteWindow(WINHELP_WINDOW
*);
22 static VOID
WINHELP_SetupText(HWND hWnd
);
23 static BOOL
WINHELP_AppendText(WINHELP_LINE
***, WINHELP_LINE_PART
***,
24 LPSIZE
, LPSIZE
, INT
*, INT
, LPCSTR
, UINT
,
25 HFONT
, COLORREF
, HLPFILE_LINK
*);
26 static WINHELP_LINE_PART
* WINHELP_IsOverLink(HWND hWnd
, WPARAM wParam
, LPARAM lParam
);
28 WINHELP_GLOBALS Globals
= {3, 0, 0, 0, 0, 0};
30 static BOOL MacroTest
= FALSE
;
32 /***********************************************************************
37 int PASCAL
WinMain (HINSTANCE hInstance
, HINSTANCE prev
, LPSTR cmdline
, int show
)
39 LPCSTR opt_lang
= "En";
45 Globals
.hInstance
= hInstance
;
48 while (*cmdline
&& (*cmdline
== ' ' || *cmdline
== '-'))
52 if (*cmdline
++ == ' ') continue;
55 if (option
) cmdline
++;
56 while (*cmdline
&& *cmdline
== ' ') cmdline
++;
62 while (*cmdline
&& *cmdline
!= ' ') cmdline
++;
63 if (*cmdline
) *cmdline
++ = '\0';
64 lHash
= HLPFILE_Hash(topic_id
);
69 Globals
.wVersion
= option
- '0';
78 /* Find language specific string table */
79 for (langnum
= 0; langnum
<= MAX_LANGUAGE_NUMBER
; langnum
++)
81 Globals
.wStringTableOffset
= langnum
* 0x100;
82 if (LoadString(hInstance
, IDS_LANGUAGE_ID
, lang
, sizeof(lang
)) &&
83 !lstrcmp(opt_lang
, lang
))
86 if (langnum
> MAX_LANGUAGE_NUMBER
)
88 /* Find fallback language */
89 for (langnum
= 0; langnum
<= MAX_LANGUAGE_NUMBER
; langnum
++)
91 Globals
.wStringTableOffset
= langnum
* 0x100;
92 if (LoadString(hInstance
, IDS_LANGUAGE_ID
, lang
, sizeof(lang
)))
95 if (langnum
> MAX_LANGUAGE_NUMBER
)
97 MessageBox(0, "No language found", "FATAL ERROR", MB_OK
);
102 /* Change Resource names */
103 lstrcpyn(STRING_MENU_Xx
+ lstrlen(STRING_MENU_Xx
) - 2, lang
, 3);
105 /* Create primary window */
106 WINHELP_RegisterWinClasses();
107 WINHELP_CreateHelpWindow(cmdline
, lHash
, "main", FALSE
, NULL
, NULL
, show
);
110 while (GetMessage (&msg
, 0, 0, 0))
112 TranslateMessage (&msg
);
113 DispatchMessage (&msg
);
118 /***********************************************************************
123 static BOOL
WINHELP_RegisterWinClasses()
125 WNDCLASS class_main
, class_button_box
, class_text
, class_shadow
;
127 class_main
.style
= CS_HREDRAW
| CS_VREDRAW
;
128 class_main
.lpfnWndProc
= WINHELP_MainWndProc
;
129 class_main
.cbClsExtra
= 0;
130 class_main
.cbWndExtra
= sizeof(LONG
);
131 class_main
.hInstance
= Globals
.hInstance
;
132 class_main
.hIcon
= LoadIcon (0, IDI_APPLICATION
);
133 class_main
.hCursor
= LoadCursor (0, IDC_ARROW
);
134 class_main
.hbrBackground
= GetStockObject (WHITE_BRUSH
);
135 class_main
.lpszMenuName
= 0;
136 class_main
.lpszClassName
= MAIN_WIN_CLASS_NAME
;
138 class_button_box
= class_main
;
139 class_button_box
.lpfnWndProc
= WINHELP_ButtonBoxWndProc
;
140 class_button_box
.hbrBackground
= GetStockObject(GRAY_BRUSH
);
141 class_button_box
.lpszClassName
= BUTTON_BOX_WIN_CLASS_NAME
;
143 class_text
= class_main
;
144 class_text
.lpfnWndProc
= WINHELP_TextWndProc
;
145 class_text
.lpszClassName
= TEXT_WIN_CLASS_NAME
;
147 class_shadow
= class_main
;
148 class_shadow
.lpfnWndProc
= DefWindowProc
;
149 class_shadow
.hbrBackground
= GetStockObject(GRAY_BRUSH
);
150 class_shadow
.lpszClassName
= SHADOW_WIN_CLASS_NAME
;
152 return (RegisterClass(&class_main
) &&
153 RegisterClass(&class_button_box
) &&
154 RegisterClass(&class_text
) &&
155 RegisterClass(&class_shadow
));
158 /***********************************************************************
160 * WINHELP_CreateHelpWindow
163 VOID
WINHELP_CreateHelpWindow(LPCSTR lpszFile
, LONG lHash
, LPCSTR lpszWindow
,
164 BOOL bPopup
, HWND hParentWnd
, LPPOINT mouse
, INT nCmdShow
)
166 CHAR szCaption
[MAX_STRING_LEN
];
167 CHAR szContents
[MAX_STRING_LEN
];
168 CHAR szSearch
[MAX_STRING_LEN
];
169 CHAR szBack
[MAX_STRING_LEN
];
170 CHAR szHistory
[MAX_STRING_LEN
];
171 SIZE size
= {CW_USEDEFAULT
, CW_USEDEFAULT
};
172 POINT origin
= {240, 0};
175 WINHELP_WINDOW
*win
, *oldwin
;
177 HLPFILE_MACRO
*macro
;
183 else if (!lpszWindow
|| !lpszWindow
[0])
184 lpszWindow
= Globals
.active_win
->lpszName
;
185 bPrimary
= lpszWindow
&& !lstrcmpi(lpszWindow
, "main");
190 page
= lHash
? HLPFILE_PageByHash(lpszFile
, lHash
) : HLPFILE_Contents(lpszFile
);
192 /* Add Suffix `.hlp' */
193 if (!page
&& lstrcmpi(lpszFile
+ strlen(lpszFile
) - 4, ".hlp"))
195 CHAR szFile_hlp
[MAX_PATHNAME_LEN
];
197 lstrcpyn(szFile_hlp
, lpszFile
, sizeof(szFile_hlp
) - 4);
198 szFile_hlp
[sizeof(szFile_hlp
) - 5] = '\0';
199 lstrcat(szFile_hlp
, ".hlp");
201 page
= lHash
? HLPFILE_PageByHash(szFile_hlp
, lHash
) : HLPFILE_Contents(szFile_hlp
);
204 WINHELP_MessageBoxIDS_s(IDS_HLPFILE_ERROR_s
, lpszFile
, IDS_ERROR
, MB_OK
);
205 if (Globals
.win_list
) return;
211 /* Calculate horizontal size and position of a popup window */
215 GetWindowRect(hParentWnd
, &parent_rect
);
216 size
.cx
= (parent_rect
.right
- parent_rect
.left
) / 2;
219 ClientToScreen(hParentWnd
, &origin
);
220 origin
.x
-= size
.cx
/ 2;
221 origin
.x
= min(origin
.x
, GetSystemMetrics(SM_CXSCREEN
) - size
.cx
);
222 origin
.x
= max(origin
.x
, 0);
225 /* Initialize WINHELP_WINDOW struct */
226 handle
= GlobalAlloc(GMEM_FIXED
, sizeof(WINHELP_WINDOW
) +
227 (lpszWindow
? strlen(lpszWindow
) + 1 : 0));
229 win
= GlobalLock(handle
);
231 win
->next
= Globals
.win_list
;
232 Globals
.win_list
= win
;
235 ptr
= GlobalLock(handle
);
236 ptr
+= sizeof(WINHELP_WINDOW
);
237 lstrcpy(ptr
, (LPSTR
) lpszWindow
);
240 else win
->lpszName
= NULL
;
243 win
->first_button
= 0;
246 win
->hButtonBoxWnd
= 0;
250 win
->hArrowCur
= LoadCursorA(0, IDC_ARROWA
);
251 win
->hHandCur
= LoadCursorA(0, IDC_HANDA
);
253 Globals
.active_win
= win
;
255 /* Initialize default pushbuttons */
256 if (MacroTest
&& !bPopup
)
257 MACRO_CreateButton("BTN_TEST", "&Test", "MacroTest");
258 if (bPrimary
&& page
)
260 LoadString(Globals
.hInstance
, IDS_CONTENTS
, szContents
, sizeof(szContents
));
261 LoadString(Globals
.hInstance
, IDS_SEARCH
, szSearch
, sizeof(szSearch
));
262 LoadString(Globals
.hInstance
, IDS_BACK
, szBack
, sizeof(szBack
));
263 LoadString(Globals
.hInstance
, IDS_HISTORY
, szHistory
, sizeof(szHistory
));
264 MACRO_CreateButton("BTN_CONTENTS", szContents
, "Contents()");
265 MACRO_CreateButton("BTN_SEARCH", szSearch
, "Search()");
266 MACRO_CreateButton("BTN_BACK", szBack
, "Back()");
267 MACRO_CreateButton("BTN_HISTORY", szHistory
, "History()");
270 /* Initialize file specific pushbuttons */
272 for (macro
= page
->file
->first_macro
; macro
; macro
= macro
->next
)
273 MACRO_ExecuteMacro(macro
->lpszMacro
);
275 /* Reuse existing window */
277 for (oldwin
= win
->next
; oldwin
; oldwin
= oldwin
->next
)
278 if (oldwin
->lpszName
&& !lstrcmpi(oldwin
->lpszName
, lpszWindow
))
280 WINHELP_BUTTON
*button
;
282 win
->hMainWnd
= oldwin
->hMainWnd
;
283 win
->hButtonBoxWnd
= oldwin
->hButtonBoxWnd
;
284 win
->hTextWnd
= oldwin
->hTextWnd
;
285 oldwin
->hMainWnd
= oldwin
->hButtonBoxWnd
= oldwin
->hTextWnd
= 0;
287 SetWindowLong(win
->hMainWnd
, 0, (LONG
) win
);
288 SetWindowLong(win
->hButtonBoxWnd
, 0, (LONG
) win
);
289 SetWindowLong(win
->hTextWnd
, 0, (LONG
) win
);
291 WINHELP_InitFonts(win
->hMainWnd
);
294 SetWindowText(win
->hMainWnd
, page
->file
->lpszTitle
);
297 WINHELP_SetupText(win
->hTextWnd
);
298 InvalidateRect(win
->hTextWnd
, NULL
, TRUE
);
299 SendMessage(win
->hMainWnd
, WM_USER
, 0, 0);
300 UpdateWindow(win
->hTextWnd
);
303 for (button
= oldwin
->first_button
; button
; button
= button
->next
)
304 DestroyWindow(button
->hWnd
);
306 WINHELP_DeleteWindow(oldwin
);
310 /* Create main Window */
311 if (!page
) LoadString(Globals
.hInstance
, IDS_WINE_HELP
, szCaption
, sizeof(szCaption
));
312 hWnd
= CreateWindow (bPopup
? TEXT_WIN_CLASS_NAME
: MAIN_WIN_CLASS_NAME
,
313 page
? page
->file
->lpszTitle
: szCaption
,
314 bPopup
? WS_POPUPWINDOW
| WS_BORDER
: WS_OVERLAPPEDWINDOW
,
315 origin
.x
, origin
.y
, size
.cx
, size
.cy
,
316 0, bPrimary
? LoadMenu(Globals
.hInstance
, STRING_MENU_Xx
) : 0,
317 Globals
.hInstance
, win
);
319 ShowWindow (hWnd
, nCmdShow
);
323 /***********************************************************************
325 * WINHELP_MainWndProc
328 static LRESULT CALLBACK
WINHELP_MainWndProc (HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
331 WINHELP_BUTTON
*button
;
332 RECT rect
, button_box_rect
;
335 WINHELP_CheckPopup(msg
);
340 win
= (WINHELP_WINDOW
*) ((LPCREATESTRUCT
) lParam
)->lpCreateParams
;
341 SetWindowLong(hWnd
, 0, (LONG
) win
);
342 win
->hMainWnd
= hWnd
;
346 win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
348 /* Create button box and text Window */
349 CreateWindow(BUTTON_BOX_WIN_CLASS_NAME
, "", WS_CHILD
| WS_VISIBLE
,
350 0, 0, 0, 0, hWnd
, 0, Globals
.hInstance
, win
);
352 CreateWindow(TEXT_WIN_CLASS_NAME
, "", WS_CHILD
| WS_VISIBLE
,
353 0, 0, 0, 0, hWnd
, 0, Globals
.hInstance
, win
);
357 case WM_WINDOWPOSCHANGED
:
358 win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
359 GetClientRect(hWnd
, &rect
);
361 /* Update button box and text Window */
362 SetWindowPos(win
->hButtonBoxWnd
, HWND_TOP
,
364 rect
.right
- rect
.left
,
365 rect
.bottom
- rect
.top
, 0);
367 GetWindowRect(win
->hButtonBoxWnd
, &button_box_rect
);
368 text_top
= rect
.top
+ button_box_rect
.bottom
- button_box_rect
.top
;
370 SetWindowPos(win
->hTextWnd
, HWND_TOP
,
372 rect
.right
- rect
.left
,
373 rect
.bottom
- text_top
, 0);
378 Globals
.active_win
= win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
382 case WH_OPEN
: MACRO_FileOpen(); break;
383 case WH_PRINT
: MACRO_Print(); break;
384 case WH_PRINTER_SETUP
: MACRO_PrinterSetup(); break;
385 case WH_EXIT
: MACRO_Exit(); break;
388 case WH_COPY_DIALOG
: MACRO_CopyDialog(); break;
389 case WH_ANNOTATE
: MACRO_Annotate(); break;
392 case WH_BOOKMARK_DEFINE
: MACRO_BookmarkDefine(); break;
395 case WH_HELP_ON_HELP
: MACRO_HelpOn(); break;
396 case WH_HELP_ON_TOP
: MACRO_HelpOnTop(); break;
399 case WH_ABOUT
: MACRO_About(); break;
402 ShellAbout(hWnd
, "WINE", "Help", 0);
407 for (button
= win
->first_button
; button
; button
= button
->next
)
408 if (wParam
== button
->wParam
) break;
410 MACRO_ExecuteMacro(button
->lpszMacro
);
412 WINHELP_MessageBoxIDS(IDS_NOT_IMPLEMENTED
, IDS_ERROR
, MB_OK
);
418 return DefWindowProc (hWnd
, msg
, wParam
, lParam
);
421 /***********************************************************************
423 * WINHELP_ButtonBoxWndProc
426 static LRESULT CALLBACK
WINHELP_ButtonBoxWndProc (HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
430 WINHELP_BUTTON
*button
;
434 WINHELP_CheckPopup(msg
);
439 win
= (WINHELP_WINDOW
*) ((LPCREATESTRUCT
) lParam
)->lpCreateParams
;
440 SetWindowLong(hWnd
, 0, (LONG
) win
);
441 win
->hButtonBoxWnd
= hWnd
;
444 case WM_WINDOWPOSCHANGING
:
445 winpos
= (WINDOWPOS
*) lParam
;
446 win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
451 for (button
= win
->first_button
; button
; button
= button
->next
)
456 button
->hWnd
= CreateWindow(STRING_BUTTON
, (LPSTR
) button
->lpszName
,
457 WS_CHILD
| WS_VISIBLE
| BS_PUSHBUTTON
,
459 hWnd
, (HMENU
) button
->wParam
,
460 Globals
.hInstance
, 0);
461 hDc
= GetDC(button
->hWnd
);
462 GetTextExtentPoint(hDc
, button
->lpszName
,
463 lstrlen(button
->lpszName
), &textsize
);
464 ReleaseDC(button
->hWnd
, hDc
);
466 button_size
.cx
= max(button_size
.cx
, textsize
.cx
+ BUTTON_CX
);
467 button_size
.cy
= max(button_size
.cy
, textsize
.cy
+ BUTTON_CY
);
472 for (button
= win
->first_button
; button
; button
= button
->next
)
474 SetWindowPos(button
->hWnd
, HWND_TOP
, x
, y
, button_size
.cx
, button_size
.cy
, 0);
476 if (x
+ 2 * button_size
.cx
<= winpos
->cx
)
479 x
= 0, y
+= button_size
.cy
;
481 winpos
->cy
= y
+ (x
? button_size
.cy
: 0);
485 SendMessage(GetParent(hWnd
), msg
, wParam
, lParam
);
489 return(DefWindowProc(hWnd
, msg
, wParam
, lParam
));
492 /***********************************************************************
494 * WINHELP_TextWndProc
497 static LRESULT CALLBACK
WINHELP_TextWndProc (HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
501 WINHELP_LINE_PART
*part
;
510 if (msg
!= WM_LBUTTONDOWN
)
511 WINHELP_CheckPopup(msg
);
516 win
= (WINHELP_WINDOW
*) ((LPCREATESTRUCT
) lParam
)->lpCreateParams
;
517 SetWindowLong(hWnd
, 0, (LONG
) win
);
518 win
->hTextWnd
= hWnd
;
519 if (!win
->lpszName
) Globals
.hPopupWnd
= win
->hMainWnd
= hWnd
;
520 WINHELP_InitFonts(hWnd
);
524 win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
526 /* Calculate vertical size and position of a popup window */
530 RECT old_window_rect
;
531 RECT old_client_rect
;
532 SIZE old_window_size
;
533 SIZE old_client_size
;
534 SIZE new_client_size
;
535 SIZE new_window_size
;
537 GetWindowRect(hWnd
, &old_window_rect
);
538 origin
.x
= old_window_rect
.left
;
539 origin
.y
= old_window_rect
.top
;
540 old_window_size
.cx
= old_window_rect
.right
- old_window_rect
.left
;
541 old_window_size
.cy
= old_window_rect
.bottom
- old_window_rect
.top
;
543 GetClientRect(hWnd
, &old_client_rect
);
544 old_client_size
.cx
= old_client_rect
.right
- old_client_rect
.left
;
545 old_client_size
.cy
= old_client_rect
.bottom
- old_client_rect
.top
;
547 new_client_size
= old_client_size
;
548 WINHELP_SplitLines(hWnd
, &new_client_size
);
550 if (origin
.y
+ POPUP_YDISTANCE
+ new_client_size
.cy
<= GetSystemMetrics(SM_CYSCREEN
))
551 origin
.y
+= POPUP_YDISTANCE
;
553 origin
.y
-= POPUP_YDISTANCE
+ new_client_size
.cy
;
555 new_window_size
.cx
= old_window_size
.cx
- old_client_size
.cx
+ new_client_size
.cx
;
556 new_window_size
.cy
= old_window_size
.cy
- old_client_size
.cy
+ new_client_size
.cy
;
559 CreateWindow(SHADOW_WIN_CLASS_NAME
, "", WS_POPUP
| WS_VISIBLE
,
560 origin
.x
+ SHADOW_DX
, origin
.y
+ SHADOW_DY
,
561 new_window_size
.cx
, new_window_size
.cy
,
562 0, 0, Globals
.hInstance
, 0);
564 SetWindowPos(hWnd
, HWND_TOP
, origin
.x
, origin
.y
,
565 new_window_size
.cx
, new_window_size
.cy
,
566 SWP_NOZORDER
| SWP_NOACTIVATE
);
567 ShowWindow(win
->hShadowWnd
, SW_NORMAL
);
571 case WM_WINDOWPOSCHANGED
:
572 winpos
= (WINDOWPOS
*) lParam
;
573 if (!(winpos
->flags
& SWP_NOSIZE
)) WINHELP_SetupText(hWnd
);
581 INT CurPos
= GetScrollPos(hWnd
, SB_VERT
);
582 GetScrollRange(hWnd
, SB_VERT
, &Min
, &Max
);
583 GetClientRect(hWnd
, &rect
);
585 switch (wParam
& 0xffff)
588 case SB_THUMBPOSITION
: CurPos
= wParam
>> 16; break;
589 case SB_TOP
: CurPos
= Min
; break;
590 case SB_BOTTOM
: CurPos
= Max
; break;
591 case SB_PAGEUP
: CurPos
-= (rect
.bottom
- rect
.top
) / 2; break;
592 case SB_PAGEDOWN
: CurPos
+= (rect
.bottom
- rect
.top
) / 2; break;
593 case SB_LINEUP
: CurPos
-= GetSystemMetrics(SM_CXVSCROLL
); break;
594 case SB_LINEDOWN
: CurPos
+= GetSystemMetrics(SM_CXVSCROLL
); break;
595 default: update
= FALSE
;
599 INT dy
= GetScrollPos(hWnd
, SB_VERT
) - CurPos
;
600 SetScrollPos(hWnd
, SB_VERT
, CurPos
, TRUE
);
601 ScrollWindow(hWnd
, 0, dy
, NULL
, NULL
);
608 hDc
= BeginPaint (hWnd
, &ps
);
609 win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
610 scroll_pos
= GetScrollPos(hWnd
, SB_VERT
);
612 for (line
= win
->first_line
; line
; line
= line
->next
)
613 for (part
= &line
->first_part
; part
; part
= part
->next
)
615 SelectObject(hDc
, part
->hFont
);
616 SetTextColor(hDc
, part
->color
);
617 TextOut(hDc
, part
->rect
.left
, part
->rect
.top
- scroll_pos
,
618 (LPSTR
) part
->lpsText
, part
->wTextLen
);
621 EndPaint (hWnd
, &ps
);
625 win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
627 if(WINHELP_IsOverLink(hWnd
, wParam
, lParam
))
628 SetCursor(win
->hHandCur
); /* set to hand pointer cursor to indicate a link */
630 SetCursor(win
->hArrowCur
); /* set to hand pointer cursor to indicate a link */
635 win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
637 hPopupWnd
= Globals
.hPopupWnd
;
638 Globals
.hPopupWnd
= 0;
640 part
= WINHELP_IsOverLink(hWnd
, wParam
, lParam
);
643 mouse
.x
= LOWORD(lParam
);
644 mouse
.y
= HIWORD(lParam
);
646 WINHELP_CreateHelpWindow(part
->link
.lpszPath
, part
->link
.lHash
, NULL
,
647 part
->link
.bPopup
, hWnd
, &mouse
, SW_NORMAL
);
651 DestroyWindow(hPopupWnd
);
655 win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
657 if (hWnd
== Globals
.hPopupWnd
) Globals
.hPopupWnd
= 0;
659 bExit
= (Globals
.wVersion
>= 4 && !lstrcmpi(win
->lpszName
, "main"));
661 WINHELP_DeleteWindow(win
);
663 if (bExit
) MACRO_Exit();
665 if (!Globals
.win_list
)
670 return DefWindowProc (hWnd
, msg
, wParam
, lParam
);
673 /***********************************************************************
678 static VOID
WINHELP_SetupText(HWND hWnd
)
680 HDC hDc
= GetDC(hWnd
);
684 ShowScrollBar(hWnd
, SB_VERT
, FALSE
);
685 if (!WINHELP_SplitLines(hWnd
, NULL
))
687 ShowScrollBar(hWnd
, SB_VERT
, TRUE
);
688 GetClientRect(hWnd
, &rect
);
690 WINHELP_SplitLines(hWnd
, &newsize
);
691 SetScrollRange(hWnd
, SB_VERT
, 0, rect
.top
+ newsize
.cy
- rect
.bottom
, TRUE
);
693 else SetScrollPos(hWnd
, SB_VERT
, 0, FALSE
);
695 ReleaseDC(hWnd
, hDc
);
698 /***********************************************************************
703 static BOOL
WINHELP_SplitLines(HWND hWnd
, LPSIZE newsize
)
705 WINHELP_WINDOW
*win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
706 HLPFILE_PARAGRAPH
*p
;
707 WINHELP_LINE
**line
= &win
->first_line
;
708 WINHELP_LINE_PART
**part
= 0;
714 if (newsize
) newsize
->cx
= newsize
->cy
= 0;
716 if (!win
->page
) return TRUE
;
718 WINHELP_DeleteLines(win
);
720 GetClientRect(hWnd
, &rect
);
722 rect
.top
+= INTERNAL_BORDER_WIDTH
;
723 rect
.left
+= INTERNAL_BORDER_WIDTH
;
724 rect
.right
-= INTERNAL_BORDER_WIDTH
;
725 rect
.bottom
-= INTERNAL_BORDER_WIDTH
;
729 space
.cx
= rect
.left
;
733 for (p
= win
->page
->first_paragraph
; p
; p
= p
->next
)
736 SIZE textsize
= {0, 0};
737 LPCSTR text
= p
->lpszText
;
738 UINT len
= strlen(text
);
741 UINT wFont
= (p
->wFont
< win
->fonts_len
) ? p
->wFont
: 0;
742 BOOL bUnderline
= p
->link
&& !p
->link
->bPopup
;
743 HFONT hFont
= win
->fonts
[wFont
][bUnderline
? 1 : 0];
745 COLORREF color
= RGB(0, 0, 0);
746 if (p
->link
) color
= RGB(0, 0x80, 0);
747 if (p
->bDebug
) color
= RGB(0xff, 0, 0);
749 SelectObject(hDc
, hFont
);
751 GetTextMetrics (hDc
, &tm
);
755 indent
= p
->wIndent
* 5 * tm
.tmAveCharWidth
;
757 space
.cx
= rect
.left
+ indent
- 2 * tm
.tmAveCharWidth
;
763 space
.cx
= rect
.left
+ indent
;
764 space
.cy
+= (p
->wVSpace
- 1) * tm
.tmHeight
;
769 space
.cx
+= p
->wHSpace
* 2 * tm
.tmAveCharWidth
;
774 INT free_width
= rect
.right
- (part
? (*line
)->rect
.right
: rect
.left
) - space
.cx
;
775 UINT low
= 0, curr
= len
, high
= len
, textlen
= 0;
781 GetTextExtentPoint(hDc
, text
, curr
, &textsize
);
783 if (textsize
.cx
<= free_width
) low
= curr
;
786 if (high
<= low
+ 1) break;
788 if (textsize
.cx
) curr
= (curr
* free_width
) / textsize
.cx
;
789 if (curr
<= low
) curr
= low
+ 1;
790 else if (curr
>= high
) curr
= high
- 1;
793 while (textlen
&& text
[textlen
] && text
[textlen
] != ' ') textlen
--;
795 if (!part
&& !textlen
) textlen
= max(low
, 1);
797 if (free_width
<= 0 || !textlen
)
800 space
.cx
= rect
.left
+ indent
;
801 space
.cx
= min(space
.cx
, rect
.right
- rect
.left
- 1);
805 if (!WINHELP_AppendText(&line
, &part
, &space
, &textsize
,
806 &line_ascent
, tm
.tmAscent
,
807 text
, textlen
, hFont
, color
, p
->link
) ||
808 (!newsize
&& (*line
)->rect
.bottom
> rect
.bottom
))
810 ReleaseDC(hWnd
, hDc
);
815 newsize
->cx
= max(newsize
->cx
, (*line
)->rect
.right
+ INTERNAL_BORDER_WIDTH
);
819 if (text
[0] == ' ') text
++, len
--;
824 newsize
->cy
= (*line
)->rect
.bottom
+ INTERNAL_BORDER_WIDTH
;
826 ReleaseDC(hWnd
, hDc
);
830 /***********************************************************************
835 static BOOL
WINHELP_AppendText(WINHELP_LINE
***linep
, WINHELP_LINE_PART
***partp
,
836 LPSIZE space
, LPSIZE textsize
,
837 INT
*line_ascent
, INT ascent
,
838 LPCSTR text
, UINT textlen
,
839 HFONT font
, COLORREF color
, HLPFILE_LINK
*link
)
843 WINHELP_LINE_PART
*part
;
846 if (!*partp
) /* New line */
848 *line_ascent
= ascent
;
850 handle
= GlobalAlloc(GMEM_FIXED
, sizeof(WINHELP_LINE
) + textlen
+
851 (link
? lstrlen(link
->lpszPath
) + 1 : 0));
852 if (!handle
) return FALSE
;
853 line
= GlobalLock(handle
);
855 part
= &line
->first_part
;
856 ptr
= GlobalLock(handle
);
857 ptr
+= sizeof(WINHELP_LINE
);
859 line
->rect
.top
= (**linep
? (**linep
)->rect
.bottom
: 0) + space
->cy
;
860 line
->rect
.bottom
= line
->rect
.top
;
861 line
->rect
.left
= space
->cx
;
862 line
->rect
.right
= space
->cx
;
864 if (**linep
) *linep
= &(**linep
)->next
;
872 if (*line_ascent
< ascent
)
874 WINHELP_LINE_PART
*p
;
875 for (p
= &line
->first_part
; p
; p
= p
->next
)
877 p
->rect
.top
+= ascent
- *line_ascent
;
878 p
->rect
.bottom
+= ascent
- *line_ascent
;
880 line
->rect
.bottom
+= ascent
- *line_ascent
;
881 *line_ascent
= ascent
;
884 handle
= GlobalAlloc(GMEM_FIXED
, sizeof(WINHELP_LINE_PART
) + textlen
+
885 (link
? lstrlen(link
->lpszPath
) + 1 : 0));
886 if (!handle
) return FALSE
;
887 part
= GlobalLock(handle
);
889 ptr
= GlobalLock(handle
);
890 ptr
+= sizeof(WINHELP_LINE_PART
);
893 memcpy(ptr
, text
, textlen
);
894 part
->rect
.left
= line
->rect
.right
+ (*partp
? space
->cx
: 0);
895 part
->rect
.right
= part
->rect
.left
+ textsize
->cx
;
896 line
->rect
.right
= part
->rect
.right
;
898 ((*partp
) ? line
->rect
.top
: line
->rect
.bottom
) + *line_ascent
- ascent
;
899 part
->rect
.bottom
= part
->rect
.top
+ textsize
->cy
;
900 line
->rect
.bottom
= max(line
->rect
.bottom
, part
->rect
.bottom
);
901 part
->hSelf
= handle
;
903 part
->wTextLen
= textlen
;
908 strcpy(ptr
+ textlen
, link
->lpszPath
);
909 part
->link
.lpszPath
= ptr
+ textlen
;
910 part
->link
.lHash
= link
->lHash
;
911 part
->link
.bPopup
= link
->bPopup
;
913 else part
->link
.lpszPath
= 0;
916 *partp
= &part
->next
;
923 /***********************************************************************
928 static VOID
WINHELP_CheckPopup(UINT msg
)
930 if (!Globals
.hPopupWnd
) return;
938 case WM_NCLBUTTONDOWN
:
939 case WM_NCMBUTTONDOWN
:
940 case WM_NCRBUTTONDOWN
:
941 DestroyWindow(Globals
.hPopupWnd
);
942 Globals
.hPopupWnd
= 0;
946 /***********************************************************************
948 * WINHELP_DeleteLines
951 static VOID
WINHELP_DeleteLines(WINHELP_WINDOW
*win
)
953 WINHELP_LINE
*line
, *next_line
;
954 WINHELP_LINE_PART
*part
, *next_part
;
955 for(line
= win
->first_line
; line
; line
= next_line
)
957 next_line
= line
->next
;
958 for(part
= &line
->first_part
; part
; part
= next_part
)
960 next_part
= part
->next
;
961 GlobalFree(part
->hSelf
);
967 /***********************************************************************
969 * WINHELP_DeleteWindow
972 static VOID
WINHELP_DeleteWindow(WINHELP_WINDOW
*win
)
976 for (w
= &Globals
.win_list
; *w
; w
= &(*w
)->next
)
983 if (win
->hShadowWnd
) DestroyWindow(win
->hShadowWnd
);
984 HLPFILE_FreeHlpFilePage(win
->page
);
985 WINHELP_DeleteLines(win
);
986 GlobalFree(win
->hSelf
);
989 /***********************************************************************
994 static VOID
WINHELP_InitFonts(HWND hWnd
)
996 WINHELP_WINDOW
*win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
997 LOGFONT logfontlist
[] = {
998 {-10, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
999 {-12, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
1000 {-12, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
1001 {-12, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
1002 {-12, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
1003 {-10, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
1004 { -8, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"}};
1005 #define FONTS_LEN (sizeof(logfontlist)/sizeof(*logfontlist))
1007 static HFONT fonts
[FONTS_LEN
][2];
1008 static BOOL init
= 0;
1010 win
->fonts_len
= FONTS_LEN
;
1017 for(i
= 0; i
< FONTS_LEN
; i
++)
1019 LOGFONT logfont
= logfontlist
[i
];
1021 fonts
[i
][0] = CreateFontIndirect(&logfont
);
1022 logfont
.lfUnderline
= 1;
1023 fonts
[i
][1] = CreateFontIndirect(&logfont
);
1030 /***********************************************************************
1032 * WINHELP_MessageBoxIDS
1035 INT
WINHELP_MessageBoxIDS(UINT ids_text
, UINT ids_title
, WORD type
)
1037 CHAR text
[MAX_STRING_LEN
];
1038 CHAR title
[MAX_STRING_LEN
];
1040 LoadString(Globals
.hInstance
, ids_text
, text
, sizeof(text
));
1041 LoadString(Globals
.hInstance
, ids_title
, title
, sizeof(title
));
1043 return(MessageBox(0, text
, title
, type
));
1046 /***********************************************************************
1048 * MAIN_MessageBoxIDS_s
1051 INT
WINHELP_MessageBoxIDS_s(UINT ids_text
, LPCSTR str
, UINT ids_title
, WORD type
)
1053 CHAR text
[MAX_STRING_LEN
];
1054 CHAR title
[MAX_STRING_LEN
];
1055 CHAR newtext
[MAX_STRING_LEN
+ MAX_PATHNAME_LEN
];
1057 LoadString(Globals
.hInstance
, ids_text
, text
, sizeof(text
));
1058 LoadString(Globals
.hInstance
, ids_title
, title
, sizeof(title
));
1059 wsprintf(newtext
, text
, str
);
1061 return(MessageBox(0, newtext
, title
, type
));
1064 WINHELP_LINE_PART
* WINHELP_IsOverLink(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1066 WINHELP_WINDOW
* win
= (WINHELP_WINDOW
*) GetWindowLong(hWnd
, 0);
1069 WINHELP_LINE_PART
*part
;
1070 int scroll_pos
= GetScrollPos(hWnd
, SB_VERT
);
1072 mouse
.x
= LOWORD(lParam
);
1073 mouse
.y
= HIWORD(lParam
);
1074 for (line
= win
->first_line
; line
; line
= line
->next
)
1076 for (part
= &line
->first_part
; part
; part
= part
->next
)
1078 if (part
->link
.lpszPath
&&
1079 part
->rect
.left
<= mouse
.x
&&
1080 part
->rect
.right
>= mouse
.x
&&
1081 part
->rect
.top
<= mouse
.y
+ scroll_pos
&&
1082 part
->rect
.bottom
>= mouse
.y
+ scroll_pos
)
1092 /* Local Variables: */
1093 /* c-file-style: "GNU" */