4 * Copyright 1996 Ulrich Schmid <uschmid@mail.hh.provi.de>
13 extern const char people[];
17 VOID LIBWINE_Register_De(void);
18 VOID LIBWINE_Register_En(void);
20 static BOOL WINHELP_RegisterWinClasses();
21 static LRESULT WINHELP_MainWndProc(HWND, UINT, WPARAM, LPARAM);
22 static LRESULT WINHELP_TextWndProc(HWND, UINT, WPARAM, LPARAM);
23 static LRESULT WINHELP_ButtonBoxWndProc(HWND, UINT, WPARAM, LPARAM);
24 static VOID WINHELP_CheckPopup(UINT);
25 static BOOL WINHELP_SplitLines(HWND hWnd, LPSIZE);
26 static VOID WINHELP_InitFonts(HWND hWnd);
27 static VOID WINHELP_DeleteLines(WINHELP_WINDOW*);
28 static VOID WINHELP_DeleteWindow(WINHELP_WINDOW*);
29 static VOID WINHELP_SetupText(HWND hWnd);
30 static BOOL WINHELP_AppendText(WINHELP_LINE***, WINHELP_LINE_PART***,
31 LPSIZE, LPSIZE, INT*, INT, LPCSTR, UINT,
32 HFONT, COLORREF, HLPFILE_LINK*);
34 WINHELP_GLOBALS Globals = {3, 0, 0, 0, 0, 0};
36 static BOOL MacroTest = FALSE;
38 /***********************************************************************
43 int PASCAL WinMain (HANDLE hInstance, HANDLE prev, LPSTR cmdline, int show)
45 LPCSTR opt_lang = "En";
51 #if defined(WINELIB) && !defined(HAVE_WINE_CONSTRUCTOR)
52 /* Register resources */
53 LIBWINE_Register_De();
54 LIBWINE_Register_En();
57 Globals.hInstance = hInstance;
60 while (*cmdline && (*cmdline == ' ' || *cmdline == '-'))
64 if (*cmdline++ == ' ') continue;
67 if (option) cmdline++;
68 while (*cmdline && *cmdline == ' ') cmdline++;
74 while (*cmdline && *cmdline != ' ') cmdline++;
75 if (*cmdline) *cmdline++ = '\0';
76 lHash = HLPFILE_Hash(topic_id);
81 Globals.wVersion = option - '0';
91 opt_lang = langNames[Options.language];
94 /* Find language specific string table */
95 for (langnum = 0; langnum <= MAX_LANGUAGE_NUMBER; langnum++)
97 Globals.wStringTableOffset = langnum * 0x100;
98 if (LoadString(hInstance, IDS_LANGUAGE_ID, lang, sizeof(lang)) &&
99 !lstrcmp(opt_lang, lang))
102 if (langnum > MAX_LANGUAGE_NUMBER)
104 /* Find fallback language */
105 for (langnum = 0; langnum <= MAX_LANGUAGE_NUMBER; langnum++)
107 Globals.wStringTableOffset = langnum * 0x100;
108 if (LoadString(hInstance, IDS_LANGUAGE_ID, lang, sizeof(lang)))
111 if (langnum > MAX_LANGUAGE_NUMBER)
113 MessageBox(0, "No language found", "FATAL ERROR", MB_OK);
118 /* Change Resource names */
119 lstrcpyn(STRING_MENU_Xx + lstrlen(STRING_MENU_Xx) - 2, lang, 3);
121 /* Create primary window */
122 WINHELP_RegisterWinClasses();
123 WINHELP_CreateHelpWindow(cmdline, lHash, "main", FALSE, NULL, NULL, show);
126 while (GetMessage (&msg, 0, 0, 0))
128 TranslateMessage (&msg);
129 DispatchMessage (&msg);
134 /***********************************************************************
139 static BOOL WINHELP_RegisterWinClasses()
141 WNDCLASS class_main, class_button_box, class_text, class_shadow;
143 class_main.style = CS_HREDRAW | CS_VREDRAW;
144 class_main.lpfnWndProc = WINHELP_MainWndProc;
145 class_main.cbClsExtra = 0;
146 class_main.cbWndExtra = sizeof(LONG);
147 class_main.hInstance = Globals.hInstance;
148 class_main.hIcon = LoadIcon (0, IDI_APPLICATION);
149 class_main.hCursor = LoadCursor (0, IDC_ARROW);
150 class_main.hbrBackground = GetStockObject (WHITE_BRUSH);
151 class_main.lpszMenuName = 0;
152 class_main.lpszClassName = MAIN_WIN_CLASS_NAME;
154 class_button_box = class_main;
155 class_button_box.lpfnWndProc = WINHELP_ButtonBoxWndProc;
156 class_button_box.hbrBackground = GetStockObject(GRAY_BRUSH);
157 class_button_box.lpszClassName = BUTTON_BOX_WIN_CLASS_NAME;
159 class_text = class_main;
160 class_text.lpfnWndProc = WINHELP_TextWndProc;
161 class_text.lpszClassName = TEXT_WIN_CLASS_NAME;
163 class_shadow = class_main;
164 class_shadow.lpfnWndProc = DefWindowProc;
165 class_shadow.hbrBackground = GetStockObject(GRAY_BRUSH);
166 class_shadow.lpszClassName = SHADOW_WIN_CLASS_NAME;
168 return (RegisterClass(&class_main) &&
169 RegisterClass(&class_button_box) &&
170 RegisterClass(&class_text) &&
171 RegisterClass(&class_shadow));
174 /***********************************************************************
176 * WINHELP_CreateHelpWindow
179 VOID WINHELP_CreateHelpWindow(LPCSTR lpszFile, LONG lHash, LPCSTR lpszWindow,
180 BOOL bPopup, HWND hParentWnd, LPPOINT mouse, INT nCmdShow)
182 CHAR szCaption[MAX_STRING_LEN];
183 CHAR szContents[MAX_STRING_LEN];
184 CHAR szSearch[MAX_STRING_LEN];
185 CHAR szBack[MAX_STRING_LEN];
186 CHAR szHistory[MAX_STRING_LEN];
187 SIZE size = {CW_USEDEFAULT, CW_USEDEFAULT};
188 POINT origin = {240, 0};
191 WINHELP_WINDOW *win, *oldwin;
193 HLPFILE_MACRO *macro;
199 else if (!lpszWindow)
200 lpszWindow = Globals.active_win->lpszName;
201 bPrimary = lpszWindow && !lstrcmpi(lpszWindow, "main");
206 page = lHash ? HLPFILE_PageByHash(lpszFile, lHash) : HLPFILE_Contents(lpszFile);
208 /* Add Suffix `.hlp' */
209 if (!page && lstrcmpi(lpszFile + strlen(lpszFile) - 4, ".hlp"))
211 CHAR szFile_hlp[MAX_PATHNAME_LEN];
213 lstrcpyn(szFile_hlp, lpszFile, sizeof(szFile_hlp) - 4);
214 szFile_hlp[sizeof(szFile_hlp) - 5] = '\0';
215 lstrcat(szFile_hlp, ".hlp");
217 page = lHash ? HLPFILE_PageByHash(szFile_hlp, lHash) : HLPFILE_Contents(szFile_hlp);
220 WINHELP_MessageBoxIDS_s(IDS_HLPFILE_ERROR_s, lpszFile, IDS_ERROR, MB_OK);
221 if (Globals.win_list) return;
227 /* Calculate horizontal size and position of a popup window */
231 GetWindowRect(hParentWnd, &parent_rect);
232 size.cx = (parent_rect.right - parent_rect.left) / 2;
235 ClientToScreen(hParentWnd, &origin);
236 origin.x -= size.cx / 2;
237 origin.x = MIN(origin.x, GetSystemMetrics(SM_CXSCREEN) - size.cx);
238 origin.x = MAX(origin.x, 0);
241 /* Initialize WINHELP_WINDOW struct */
242 handle = GlobalAlloc(GMEM_FIXED, sizeof(WINHELP_WINDOW) +
243 (lpszWindow ? strlen(lpszWindow) + 1 : 0));
245 win = GlobalLock(handle);
247 win->next = Globals.win_list;
248 Globals.win_list = win;
251 ptr = GlobalLock(handle);
252 ptr += sizeof(WINHELP_WINDOW);
253 lstrcpy(ptr, (LPSTR) lpszWindow);
256 else win->lpszName = NULL;
258 win->first_button = 0;
261 win->hButtonBoxWnd = 0;
265 Globals.active_win = win;
267 /* Initialize default pushbuttons */
268 if (MacroTest && !bPopup)
269 MACRO_CreateButton("BTN_TEST", "&Test", "MacroTest");
270 if (bPrimary && page)
272 LoadString(Globals.hInstance, IDS_CONTENTS, szContents, sizeof(szContents));
273 LoadString(Globals.hInstance, IDS_SEARCH, szSearch, sizeof(szSearch));
274 LoadString(Globals.hInstance, IDS_BACK, szBack, sizeof(szBack));
275 LoadString(Globals.hInstance, IDS_HISTORY, szHistory, sizeof(szHistory));
276 MACRO_CreateButton("BTN_CONTENTS", szContents, "Contents()");
277 MACRO_CreateButton("BTN_SEARCH", szSearch, "Search()");
278 MACRO_CreateButton("BTN_BACK", szBack, "Back()");
279 MACRO_CreateButton("BTN_HISTORY", szHistory, "History()");
282 /* Initialize file specific pushbuttons */
284 for (macro = page->file->first_macro; macro; macro = macro->next)
285 MACRO_ExecuteMacro(macro->lpszMacro);
287 /* Reuse existing window */
289 for (oldwin = win->next; oldwin; oldwin = oldwin->next)
290 if (oldwin->lpszName && !lstrcmpi(oldwin->lpszName, lpszWindow))
292 WINHELP_BUTTON *button;
294 win->hMainWnd = oldwin->hMainWnd;
295 win->hButtonBoxWnd = oldwin->hButtonBoxWnd;
296 win->hTextWnd = oldwin->hTextWnd;
297 oldwin->hMainWnd = oldwin->hButtonBoxWnd = oldwin->hTextWnd = 0;
299 SetWindowLong(win->hMainWnd, 0, (LONG) win);
300 SetWindowLong(win->hButtonBoxWnd, 0, (LONG) win);
301 SetWindowLong(win->hTextWnd, 0, (LONG) win);
303 WINHELP_InitFonts(win->hMainWnd);
305 SetWindowText(win->hMainWnd, page->file->lpszTitle);
307 WINHELP_SetupText(win->hTextWnd);
308 InvalidateRect(win->hTextWnd, NULL, TRUE);
309 SendMessage(win->hMainWnd, WM_USER, 0, 0);
310 UpdateWindow(win->hTextWnd);
313 for (button = oldwin->first_button; button; button = button->next)
314 DestroyWindow(button->hWnd);
316 WINHELP_DeleteWindow(oldwin);
320 /* Create main Window */
321 if (!page) LoadString(Globals.hInstance, IDS_WINE_HELP, szCaption, sizeof(szCaption));
322 hWnd = CreateWindow (bPopup ? TEXT_WIN_CLASS_NAME : MAIN_WIN_CLASS_NAME,
323 page ? (SEGPTR) page->file->lpszTitle : (SEGPTR) szCaption,
324 bPopup ? WS_POPUPWINDOW | WS_BORDER : WS_OVERLAPPEDWINDOW,
325 origin.x, origin.y, size.cx, size.cy,
326 0, bPrimary ? LoadMenu(Globals.hInstance, STRING_MENU_Xx) : 0,
327 Globals.hInstance, (SEGPTR) win);
329 ShowWindow (hWnd, nCmdShow);
333 /***********************************************************************
335 * WINHELP_MainWndProc
338 static LRESULT WINHELP_MainWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
341 WINHELP_BUTTON *button;
342 RECT rect, button_box_rect;
345 WINHELP_CheckPopup(msg);
350 win = (WINHELP_WINDOW*) ((LPCREATESTRUCT) lParam)->lpCreateParams;
351 SetWindowLong(hWnd, 0, (LONG) win);
352 win->hMainWnd = hWnd;
356 win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
358 /* Create button box and text Window */
359 CreateWindow(BUTTON_BOX_WIN_CLASS_NAME, "", WS_CHILD | WS_VISIBLE,
360 0, 0, 0, 0, hWnd, 0, Globals.hInstance, (SEGPTR) win);
362 CreateWindow(TEXT_WIN_CLASS_NAME, "", WS_CHILD | WS_VISIBLE,
363 0, 0, 0, 0, hWnd, 0, Globals.hInstance, (SEGPTR) win);
367 case WM_WINDOWPOSCHANGED:
368 win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
369 GetClientRect(hWnd, &rect);
371 /* Update button box and text Window */
372 SetWindowPos(win->hButtonBoxWnd, HWND_TOP,
374 rect.right - rect.left,
375 rect.bottom - rect.top, 0);
377 GetWindowRect(win->hButtonBoxWnd, &button_box_rect);
378 text_top = rect.top + button_box_rect.bottom - button_box_rect.top;
380 SetWindowPos(win->hTextWnd, HWND_TOP,
382 rect.right - rect.left,
383 rect.bottom - text_top, 0);
388 Globals.active_win = win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
392 case WH_OPEN: MACRO_FileOpen(); break;
393 case WH_PRINT: MACRO_Print(); break;
394 case WH_PRINTER_SETUP: MACRO_PrinterSetup(); break;
395 case WH_EXIT: MACRO_Exit(); break;
398 case WH_COPY_DIALOG: MACRO_CopyDialog(); break;
399 case WH_ANNOTATE: MACRO_Annotate(); break;
402 case WH_BOOKMARK_DEFINE: MACRO_BookmarkDefine(); break;
405 case WH_HELP_ON_HELP: MACRO_HelpOn(); break;
406 case WH_HELP_ON_TOP: MACRO_HelpOnTop(); break;
409 case WH_ABOUT: MACRO_About(); break;
412 ShellAbout(hWnd, "WINE", people, 0);
418 for (button = win->first_button; button; button = button->next)
419 if (wParam == button->wParam) break;
421 MACRO_ExecuteMacro(button->lpszMacro);
423 WINHELP_MessageBoxIDS(IDS_NOT_IMPLEMENTED, IDS_ERROR, MB_OK);
429 return DefWindowProc (hWnd, msg, wParam, lParam);
432 /***********************************************************************
434 * WINHELP_ButtonBoxWndProc
437 static LRESULT WINHELP_ButtonBoxWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
441 WINHELP_BUTTON *button;
445 WINHELP_CheckPopup(msg);
450 win = (WINHELP_WINDOW*) ((LPCREATESTRUCT) lParam)->lpCreateParams;
451 SetWindowLong(hWnd, 0, (LONG) win);
452 win->hButtonBoxWnd = hWnd;
455 case WM_WINDOWPOSCHANGING:
456 winpos = (WINDOWPOS*) lParam;
457 win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
462 for (button = win->first_button; button; button = button->next)
467 button->hWnd = CreateWindow(STRING_BUTTON, (LPSTR) button->lpszName,
468 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
470 hWnd, (HMENU) button->wParam,
471 Globals.hInstance, 0);
472 hDc = GetDC(button->hWnd);
473 GetTextExtentPoint(hDc, button->lpszName,
474 lstrlen(button->lpszName), &textsize);
475 ReleaseDC(button->hWnd, hDc);
477 button_size.cx = MAX(button_size.cx, textsize.cx + BUTTON_CX);
478 button_size.cy = MAX(button_size.cy, textsize.cy + BUTTON_CY);
483 for (button = win->first_button; button; button = button->next)
485 SetWindowPos(button->hWnd, HWND_TOP, x, y, button_size.cx, button_size.cy, 0);
487 if (x + 2 * button_size.cx <= winpos->cx)
490 x = 0, y += button_size.cy;
492 winpos->cy = y + (x ? button_size.cy : 0);
496 SendMessage(GetParent(hWnd), msg, wParam, lParam);
500 return(DefWindowProc(hWnd, msg, wParam, lParam));
503 /***********************************************************************
505 * WINHELP_TextWndProc
508 static LRESULT WINHELP_TextWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
512 WINHELP_LINE_PART *part;
521 if (msg != WM_LBUTTONDOWN)
522 WINHELP_CheckPopup(msg);
527 win = (WINHELP_WINDOW*) ((LPCREATESTRUCT) lParam)->lpCreateParams;
528 SetWindowLong(hWnd, 0, (LONG) win);
529 win->hTextWnd = hWnd;
530 if (!win->lpszName) Globals.hPopupWnd = win->hMainWnd = hWnd;
531 WINHELP_InitFonts(hWnd);
535 win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
537 /* Calculate vertical size and position of a popup window */
541 RECT old_window_rect;
542 RECT old_client_rect;
543 SIZE old_window_size;
544 SIZE old_client_size;
545 SIZE new_client_size;
546 SIZE new_window_size;
548 GetWindowRect(hWnd, &old_window_rect);
549 origin.x = old_window_rect.left;
550 origin.y = old_window_rect.top;
551 old_window_size.cx = old_window_rect.right - old_window_rect.left;
552 old_window_size.cy = old_window_rect.bottom - old_window_rect.top;
554 GetClientRect(hWnd, &old_client_rect);
555 old_client_size.cx = old_client_rect.right - old_client_rect.left;
556 old_client_size.cy = old_client_rect.bottom - old_client_rect.top;
558 new_client_size = old_client_size;
559 WINHELP_SplitLines(hWnd, &new_client_size);
561 if (origin.y + POPUP_YDISTANCE + new_client_size.cy <= GetSystemMetrics(SM_CYSCREEN))
562 origin.y += POPUP_YDISTANCE;
564 origin.y -= POPUP_YDISTANCE + new_client_size.cy;
566 new_window_size.cx = old_window_size.cx - old_client_size.cx + new_client_size.cx;
567 new_window_size.cy = old_window_size.cy - old_client_size.cy + new_client_size.cy;
570 CreateWindow(SHADOW_WIN_CLASS_NAME, "", WS_POPUP | WS_VISIBLE,
571 origin.x + SHADOW_DX, origin.y + SHADOW_DY,
572 new_window_size.cx, new_window_size.cy,
573 0, 0, Globals.hInstance, 0);
575 SetWindowPos(hWnd, HWND_TOP, origin.x, origin.y,
576 new_window_size.cx, new_window_size.cy,
577 SWP_NOZORDER | SWP_NOACTIVATE);
578 ShowWindow(win->hShadowWnd, SW_NORMAL);
582 case WM_WINDOWPOSCHANGED:
583 winpos = (WINDOWPOS*) lParam;
584 if (!(winpos->flags & SWP_NOSIZE)) WINHELP_SetupText(hWnd);
592 INT CurPos = GetScrollPos(hWnd, SB_VERT);
593 GetScrollRange(hWnd, SB_VERT, &Min, &Max);
594 GetClientRect(hWnd, &rect);
596 switch (wParam & 0xffff)
599 case SB_THUMBPOSITION: CurPos = wParam >> 16; break;
600 case SB_TOP: CurPos = Min; break;
601 case SB_BOTTOM: CurPos = Max; break;
602 case SB_PAGEUP: CurPos -= (rect.bottom - rect.top) / 2; break;
603 case SB_PAGEDOWN: CurPos += (rect.bottom - rect.top) / 2; break;
604 case SB_LINEUP: CurPos -= GetSystemMetrics(SM_CXVSCROLL); break;
605 case SB_LINEDOWN: CurPos += GetSystemMetrics(SM_CXVSCROLL); break;
606 default: update = FALSE;
610 INT dy = GetScrollPos(hWnd, SB_VERT) - CurPos;
611 SetScrollPos(hWnd, SB_VERT, CurPos, TRUE);
612 ScrollWindow(hWnd, 0, dy, NULL, NULL);
619 hDc = BeginPaint (hWnd, &ps);
620 win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
621 scroll_pos = GetScrollPos(hWnd, SB_VERT);
623 for (line = win->first_line; line; line = line->next)
624 for (part = &line->first_part; part; part = part->next)
626 SelectObject(hDc, part->hFont);
627 SetTextColor(hDc, part->color);
628 TextOut(hDc, part->rect.left, part->rect.top - scroll_pos,
629 (LPSTR) part->lpsText, part->wTextLen);
632 EndPaint (hWnd, &ps);
636 win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
637 scroll_pos = GetScrollPos(hWnd, SB_VERT);
639 hPopupWnd = Globals.hPopupWnd;
640 Globals.hPopupWnd = 0;
642 mouse.x = LOWORD(lParam);
643 mouse.y = HIWORD(lParam);
644 for (line = win->first_line; line; line = line->next)
645 for (part = &line->first_part; part; part = part->next)
646 if (part->link.lpszPath &&
647 part->rect.left <= mouse.x &&
648 part->rect.right >= mouse.x &&
649 part->rect.top <= mouse.y + scroll_pos &&
650 part->rect.bottom >= mouse.y + scroll_pos)
651 WINHELP_CreateHelpWindow(part->link.lpszPath, part->link.lHash, NULL,
652 part->link.bPopup, hWnd, &mouse, SW_NORMAL);
654 DestroyWindow(hPopupWnd);
658 win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
660 if (hWnd == Globals.hPopupWnd) Globals.hPopupWnd = 0;
662 bExit = (Globals.wVersion >= 4 && !lstrcmpi(win->lpszName, "main"));
664 WINHELP_DeleteWindow(win);
666 if (bExit) MACRO_Exit();
668 if (!Globals.win_list)
673 return DefWindowProc (hWnd, msg, wParam, lParam);
676 /***********************************************************************
681 static VOID WINHELP_SetupText(HWND hWnd)
683 HDC hDc = GetDC(hWnd);
687 ShowScrollBar(hWnd, SB_VERT, FALSE);
688 if (!WINHELP_SplitLines(hWnd, NULL))
690 ShowScrollBar(hWnd, SB_VERT, TRUE);
691 GetClientRect(hWnd, &rect);
693 WINHELP_SplitLines(hWnd, &newsize);
694 SetScrollRange(hWnd, SB_VERT, 0, rect.top + newsize.cy - rect.bottom, TRUE);
696 else SetScrollPos(hWnd, SB_VERT, 0, FALSE);
698 ReleaseDC(hWnd, hDc);
701 /***********************************************************************
706 static BOOL WINHELP_SplitLines(HWND hWnd, LPSIZE newsize)
708 WINHELP_WINDOW *win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
709 HLPFILE_PARAGRAPH *p;
710 WINHELP_LINE **line = &win->first_line;
711 WINHELP_LINE_PART **part = 0;
717 if (newsize) newsize->cx = newsize->cy = 0;
719 if (!win->page) return TRUE;
721 WINHELP_DeleteLines(win);
723 GetClientRect(hWnd, &rect);
725 rect.top += INTERNAL_BORDER_WIDTH;
726 rect.left += INTERNAL_BORDER_WIDTH;
727 rect.right -= INTERNAL_BORDER_WIDTH;
728 rect.bottom -= INTERNAL_BORDER_WIDTH;
732 space.cx = rect.left;
736 for (p = win->page->first_paragraph; p; p = p->next)
739 SIZE textsize = {0, 0};
740 LPCSTR text = p->lpszText;
741 UINT len = strlen(text);
744 UINT wFont = (p->wFont < win->fonts_len) ? p->wFont : 0;
745 BOOL bUnderline = p->link && !p->link->bPopup;
746 HFONT hFont = win->fonts[wFont][bUnderline ? 1 : 0];
748 COLORREF color = RGB(0, 0, 0);
749 if (p->link) color = RGB(0, 0x80, 0);
750 if (p->bDebug) color = RGB(0xff, 0, 0);
752 SelectObject(hDc, hFont);
754 GetTextMetrics (hDc, &tm);
758 indent = p->wIndent * 5 * tm.tmAveCharWidth;
760 space.cx = rect.left + indent - 2 * tm.tmAveCharWidth;
766 space.cx = rect.left + indent;
767 space.cy += (p->wVSpace - 1) * tm.tmHeight;
772 space.cx += p->wHSpace * 2 * tm.tmAveCharWidth;
777 INT free_width = rect.right - (part ? (*line)->rect.right : rect.left) - space.cx;
778 UINT low = 0, curr = len, high = len, textlen;
784 GetTextExtentPoint(hDc, text, curr, &textsize);
786 if (textsize.cx <= free_width) low = curr;
789 if (high <= low + 1) break;
791 if (textsize.cx) curr = (curr * free_width) / textsize.cx;
792 if (curr <= low) curr = low + 1;
793 else if (curr >= high) curr = high - 1;
796 while (textlen && text[textlen] && text[textlen] != ' ') textlen--;
798 if (!part && !textlen) textlen = MAX(low, 1);
800 if (free_width <= 0 || !textlen)
803 space.cx = rect.left + indent;
804 space.cx = MIN(space.cx, rect.right - rect.left - 1);
808 if (!WINHELP_AppendText(&line, &part, &space, &textsize,
809 &line_ascent, tm.tmAscent,
810 text, textlen, hFont, color, p->link) ||
811 (!newsize && (*line)->rect.bottom > rect.bottom))
813 ReleaseDC(hWnd, hDc);
818 newsize->cx = MAX(newsize->cx, (*line)->rect.right + INTERNAL_BORDER_WIDTH);
822 if (text[0] == ' ') text++, len--;
827 newsize->cy = (*line)->rect.bottom + INTERNAL_BORDER_WIDTH;
829 ReleaseDC(hWnd, hDc);
833 /***********************************************************************
838 static BOOL WINHELP_AppendText(WINHELP_LINE ***linep, WINHELP_LINE_PART ***partp,
839 LPSIZE space, LPSIZE textsize,
840 INT *line_ascent, INT ascent,
841 LPCSTR text, UINT textlen,
842 HFONT font, COLORREF color, HLPFILE_LINK *link)
846 WINHELP_LINE_PART *part;
849 if (!*partp) /* New line */
851 *line_ascent = ascent;
853 handle = GlobalAlloc(GMEM_FIXED, sizeof(WINHELP_LINE) + textlen +
854 (link ? lstrlen(link->lpszPath) + 1 : 0));
855 if (!handle) return FALSE;
856 line = GlobalLock(handle);
858 part = &line->first_part;
859 ptr = GlobalLock(handle);
860 ptr += sizeof(WINHELP_LINE);
862 line->rect.top = (**linep ? (**linep)->rect.bottom : 0) + space->cy;
863 line->rect.bottom = line->rect.top;
864 line->rect.left = space->cx;
865 line->rect.right = space->cx;
867 if (**linep) *linep = &(**linep)->next;
875 if (*line_ascent < ascent)
877 WINHELP_LINE_PART *p;
878 for (p = &line->first_part; p; p = p->next)
880 p->rect.top += ascent - *line_ascent;
881 p->rect.bottom += ascent - *line_ascent;
883 line->rect.bottom += ascent - *line_ascent;
884 *line_ascent = ascent;
887 handle = GlobalAlloc(GMEM_FIXED, sizeof(WINHELP_LINE_PART) + textlen +
888 (link ? lstrlen(link->lpszPath) + 1 : 0));
889 if (!handle) return FALSE;
890 part = GlobalLock(handle);
892 ptr = GlobalLock(handle);
893 ptr += sizeof(WINHELP_LINE_PART);
896 hmemcpy(ptr, text, textlen);
897 part->rect.left = line->rect.right + (*partp ? space->cx : 0);
898 part->rect.right = part->rect.left + textsize->cx;
899 line->rect.right = part->rect.right;
901 ((*partp) ? line->rect.top : line->rect.bottom) + *line_ascent - ascent;
902 part->rect.bottom = part->rect.top + textsize->cy;
903 line->rect.bottom = MAX(line->rect.bottom, part->rect.bottom);
904 part->hSelf = handle;
906 part->wTextLen = textlen;
911 strcpy(ptr + textlen, link->lpszPath);
912 part->link.lpszPath = ptr + textlen;
913 part->link.lHash = link->lHash;
914 part->link.bPopup = link->bPopup;
916 else part->link.lpszPath = 0;
919 *partp = &part->next;
926 /***********************************************************************
931 static VOID WINHELP_CheckPopup(UINT msg)
933 if (!Globals.hPopupWnd) return;
941 case WM_NCLBUTTONDOWN:
942 case WM_NCMBUTTONDOWN:
943 case WM_NCRBUTTONDOWN:
944 DestroyWindow(Globals.hPopupWnd);
945 Globals.hPopupWnd = 0;
949 /***********************************************************************
951 * WINHELP_DeleteLines
954 static VOID WINHELP_DeleteLines(WINHELP_WINDOW *win)
956 WINHELP_LINE *line, *next_line;
957 WINHELP_LINE_PART *part, *next_part;
958 for(line = win->first_line; line; line = next_line)
960 next_line = line->next;
961 for(part = &line->first_part; part; part = next_part)
963 next_part = part->next;
964 GlobalFree(part->hSelf);
970 /***********************************************************************
972 * WINHELP_DeleteWindow
975 static VOID WINHELP_DeleteWindow(WINHELP_WINDOW *win)
979 for (w = &Globals.win_list; *w; w = &(*w)->next)
986 if (win->hShadowWnd) DestroyWindow(win->hShadowWnd);
987 HLPFILE_FreeHlpFilePage(win->page);
988 WINHELP_DeleteLines(win);
989 GlobalFree(win->hSelf);
992 /***********************************************************************
997 static VOID WINHELP_InitFonts(HWND hWnd)
999 WINHELP_WINDOW *win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0);
1000 LOGFONT logfontlist[] = {
1001 {-10, 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 {-12, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
1004 {-12, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
1005 {-12, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
1006 {-10, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"},
1007 { -8, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 32, "Helv"}};
1008 #define FONTS_LEN (sizeof(logfontlist)/sizeof(*logfontlist))
1010 static HFONT fonts[FONTS_LEN][2];
1011 static BOOL init = 0;
1013 win->fonts_len = FONTS_LEN;
1020 for(i = 0; i < FONTS_LEN; i++)
1022 LOGFONT logfont = logfontlist[i];
1024 fonts[i][0] = CreateFontIndirect(&logfont);
1025 logfont.lfUnderline = 1;
1026 fonts[i][1] = CreateFontIndirect(&logfont);
1033 /***********************************************************************
1035 * WINHELP_MessageBoxIDS
1038 INT WINHELP_MessageBoxIDS(UINT ids_text, UINT ids_title, WORD type)
1040 CHAR text[MAX_STRING_LEN];
1041 CHAR title[MAX_STRING_LEN];
1043 LoadString(Globals.hInstance, ids_text, text, sizeof(text));
1044 LoadString(Globals.hInstance, ids_title, title, sizeof(title));
1046 return(MessageBox(0, text, title, type));
1049 /***********************************************************************
1051 * MAIN_MessageBoxIDS_s
1054 INT WINHELP_MessageBoxIDS_s(UINT ids_text, LPCSTR str, UINT ids_title, WORD type)
1056 CHAR text[MAX_STRING_LEN];
1057 CHAR title[MAX_STRING_LEN];
1058 CHAR newtext[MAX_STRING_LEN + MAX_PATHNAME_LEN];
1060 LoadString(Globals.hInstance, ids_text, text, sizeof(text));
1061 LoadString(Globals.hInstance, ids_title, title, sizeof(title));
1062 wsprintf(newtext, text, str);
1064 return(MessageBox(0, newtext, title, type));
1067 /* Local Variables: */
1068 /* c-file-style: "GNU" */