From 2b855deddba9576b715cc5496845cd2c3d34fa60 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Wed, 20 Nov 2002 19:46:18 +0000 Subject: [PATCH] Wrote back & history support. Correctly implemented << and >> buttons. Added support for page level macros. --- programs/winhelp/hlpfile.c | 191 ++++++++++++++++------------ programs/winhelp/hlpfile.h | 27 ++-- programs/winhelp/macro.c | 41 +++++- programs/winhelp/string.c | 1 + programs/winhelp/winhelp.c | 251 ++++++++++++++++++++++++++++++------- programs/winhelp/winhelp.h | 8 ++ 6 files changed, 378 insertions(+), 141 deletions(-) diff --git a/programs/winhelp/hlpfile.c b/programs/winhelp/hlpfile.c index ea53270363d..60e815934e9 100644 --- a/programs/winhelp/hlpfile.c +++ b/programs/winhelp/hlpfile.c @@ -84,23 +84,6 @@ static BOOL HLPFILE_Uncompress3(char*, const char*, const BYTE*, const BYTE*); static void HLPFILE_UncompressRLE(const BYTE* src, unsigned sz, BYTE** dst); static BOOL HLPFILE_ReadFont(HLPFILE* hlpfile); -/*********************************************************************** - * - * HLPFILE_Contents - */ -HLPFILE_PAGE *HLPFILE_Contents(HLPFILE *hlpfile) -{ - if (!hlpfile) return 0; -#if 1 - return hlpfile->first_page; -#else - if (hlpfile->contents_start) - return HLPFILE_PageByHash(hlpfile, hlpfile->contents_start); - else - return hlpfile->first_page; -#endif -} - /*********************************************************************** * * HLPFILE_PageByNumber @@ -119,53 +102,80 @@ HLPFILE_PAGE *HLPFILE_PageByNumber(LPCSTR lpszPath, UINT wNum) return page; } +/* FIXME: + * this finds the page containing the offset. The offset can either + * refer to the top of the page (offset == page->offset), or + * to some paragraph inside the page... + * As of today, we only return the page... we should also return + * a paragraph, and then, while opening a new page, compute the + * y-offset of the paragraph to be shown and scroll the window + * accordinly + */ +/****************************************************************** + * HLPFILE_PageByOffset + * + * + */ +HLPFILE_PAGE *HLPFILE_PageByOffset(HLPFILE* hlpfile, LONG offset) +{ + HLPFILE_PAGE* page; + HLPFILE_PAGE* found; + + if (!hlpfile) return 0; + + WINE_TRACE("<%s>[%lx]\n", hlpfile->lpszPath, offset); + + if (offset == 0xFFFFFFFF) return NULL; + page = NULL; + + for (found = NULL, page = hlpfile->first_page; page; page = page->next) + { + if (page->offset <= offset && (!found || found->offset < page->offset)) + found = page; + } + if (!found) + WINE_ERR("Page of offset %lu not found in file %s\n", + offset, hlpfile->lpszPath); + return found; +} + /*********************************************************************** * * HLPFILE_HlpFilePageByHash */ HLPFILE_PAGE *HLPFILE_PageByHash(HLPFILE* hlpfile, LONG lHash) { - HLPFILE_PAGE* page; - HLPFILE_PAGE* found; int i; - WINE_TRACE("path<%s>[%lx]\n", hlpfile->lpszPath, lHash); - if (!hlpfile) return 0; - page = NULL; + WINE_TRACE("<%s>[%lx]\n", hlpfile->lpszPath, lHash); + for (i = 0; i < hlpfile->wContextLen; i++) { - if (hlpfile->Context[i].lHash != lHash) continue; - - /* FIXME: - * this finds the page containing the offset. The offset can either - * refer to the top of the page (offset == page->offset), or - * to some paragraph inside the page... - * As of today, we only return the page... we should also return - * a paragraph, and then, while opening a new page, compute the - * y-offset of the paragraph to be shown and scroll the window - * accordinly - */ - found = NULL; - for (page = hlpfile->first_page; page; page = page->next) - { - if (page->offset <= hlpfile->Context[i].offset) - { - if (!found || found->offset < page->offset) - found = page; - } - } - if (found) return found; - - WINE_ERR("Page of offset %lu not found in file %s\n", - hlpfile->Context[i].offset, hlpfile->lpszPath); - return NULL; + if (hlpfile->Context[i].lHash == lHash) + return HLPFILE_PageByOffset(hlpfile, hlpfile->Context[i].offset); } + WINE_ERR("Page of hash %lx not found in file %s\n", lHash, hlpfile->lpszPath); return NULL; } +/*********************************************************************** + * + * HLPFILE_Contents + */ +HLPFILE_PAGE* HLPFILE_Contents(HLPFILE *hlpfile) +{ + HLPFILE_PAGE* page = NULL; + + if (!hlpfile) return NULL; + + page = HLPFILE_PageByOffset(hlpfile, hlpfile->contents_start); + if (!page) page = hlpfile->first_page; + return page; +} + /*********************************************************************** * * HLPFILE_Hash @@ -216,7 +226,7 @@ HLPFILE *HLPFILE_ReadHlpFile(LPCSTR lpszPath) hlpfile->first_macro = NULL; hlpfile->wContextLen = 0; hlpfile->Context = NULL; - hlpfile->contents_start = 0; + hlpfile->contents_start = 0xFFFFFFFF; hlpfile->prev = NULL; hlpfile->next = first_hlpfile; hlpfile->wRefCount = 1; @@ -338,35 +348,37 @@ static BOOL HLPFILE_AddPage(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigned off HLPFILE_PAGE* page; BYTE* title; UINT titlesize; + char* ptr; + HLPFILE_MACRO*macro; if (buf + 0x31 > end) {WINE_WARN("page1\n"); return FALSE;}; title = buf + GET_UINT(buf, 0x10); if (title > end) {WINE_WARN("page2\n"); return FALSE;}; - titlesize = GET_UINT(buf, 4) + 1; - page = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_PAGE) + titlesize); + titlesize = GET_UINT(buf, 4); + page = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_PAGE) + titlesize + 1); if (!page) return FALSE; page->lpszTitle = (char*)page + sizeof(HLPFILE_PAGE); if (hlpfile->hasPhrases) { - HLPFILE_Uncompress2(title, end, page->lpszTitle, page->lpszTitle + titlesize - 1); + HLPFILE_Uncompress2(title, end, page->lpszTitle, page->lpszTitle + titlesize); } else { if (GET_UINT(buf, 0x4) > GET_UINT(buf, 0) - GET_UINT(buf, 0x10)) { /* need to decompress */ - HLPFILE_Uncompress3(page->lpszTitle, page->lpszTitle + titlesize - 1, + HLPFILE_Uncompress3(page->lpszTitle, page->lpszTitle + titlesize, title, end); } else { - memcpy(page->lpszTitle, title, titlesize - 1); + memcpy(page->lpszTitle, title, titlesize); } } - page->lpszTitle[titlesize - 1] = 0; + page->lpszTitle[titlesize] = '\0'; if (hlpfile->first_page) { @@ -385,14 +397,36 @@ static BOOL HLPFILE_AddPage(HLPFILE *hlpfile, BYTE *buf, BYTE *end, unsigned off page->file = hlpfile; page->next = NULL; page->first_paragraph = NULL; + page->first_macro = NULL; page->wNumber = GET_UINT(buf, 0x21); page->offset = offset; - WINE_TRACE("Added page[%d]: title='%s' offset=%08x\n", - page->wNumber, page->lpszTitle, page->offset); + page->browse_bwd = GET_UINT(buf, 0x19); + page->browse_fwd = GET_UINT(buf, 0x1D); + + WINE_TRACE("Added page[%d]: title='%s' %08lx << %08x >> %08lx\n", + page->wNumber, page->lpszTitle, + page->browse_bwd, page->offset, page->browse_fwd); memset(&attributes, 0, sizeof(attributes)); + /* now load macros */ + ptr = page->lpszTitle + strlen(page->lpszTitle) + 1; + while (ptr < page->lpszTitle + titlesize) + { + unsigned len = strlen(ptr); + WINE_TRACE("macro: %s\n", ptr); + macro = HeapAlloc(GetProcessHeap(), 0, sizeof(HLPFILE_MACRO) + len + 1); + macro->lpszMacro = (char*)(macro + 1); + memcpy((char*)macro->lpszMacro, ptr, len + 1); + /* FIXME: shall we really link macro in reverse order ?? + * may produce strange results when played at page opening + */ + macro->next = page->first_macro; + page->first_macro = macro; + ptr += len + 1; + } + return TRUE; } @@ -1762,23 +1796,6 @@ static void HLPFILE_DeleteParagraph(HLPFILE_PARAGRAPH* paragraph) } } -/*********************************************************************** - * - * DeletePage - */ -static void HLPFILE_DeletePage(HLPFILE_PAGE* page) -{ - HLPFILE_PAGE* next; - - while (page) - { - next = page->next; - HLPFILE_DeleteParagraph(page->first_paragraph); - HeapFree(GetProcessHeap(), 0, page); - page = next; - } -} - /*********************************************************************** * * DeleteMacro @@ -1795,6 +1812,24 @@ static void HLPFILE_DeleteMacro(HLPFILE_MACRO* macro) } } +/*********************************************************************** + * + * DeletePage + */ +static void HLPFILE_DeletePage(HLPFILE_PAGE* page) +{ + HLPFILE_PAGE* next; + + while (page) + { + next = page->next; + HLPFILE_DeleteParagraph(page->first_paragraph); + HLPFILE_DeleteMacro(page->first_macro); + HeapFree(GetProcessHeap(), 0, page); + page = next; + } +} + /*********************************************************************** * * HLPFILE_FreeHlpFile @@ -1836,13 +1871,3 @@ void HLPFILE_FreeHlpFile(HLPFILE* hlpfile) if (hlpfile->lpszCopyright) HeapFree(GetProcessHeap(), 0, hlpfile->lpszCopyright); HeapFree(GetProcessHeap(), 0, hlpfile); } - -/*********************************************************************** - * - * FreeHlpFilePage - */ -void HLPFILE_FreeHlpFilePage(HLPFILE_PAGE* page) -{ - if (!page) return; - HLPFILE_FreeHlpFile(page->file); -} diff --git a/programs/winhelp/hlpfile.h b/programs/winhelp/hlpfile.h index f8a6f07561b..f5a4ef94047 100644 --- a/programs/winhelp/hlpfile.h +++ b/programs/winhelp/hlpfile.h @@ -71,15 +71,26 @@ typedef struct tagHlpFileParagraph struct tagHlpFileParagraph* next; } HLPFILE_PARAGRAPH; +typedef struct tagHlpFileMacro +{ + LPCSTR lpszMacro; + struct tagHlpFileMacro* next; +} HLPFILE_MACRO; + typedef struct tagHlpFilePage { LPSTR lpszTitle; HLPFILE_PARAGRAPH* first_paragraph; + HLPFILE_MACRO* first_macro; unsigned wNumber; unsigned offset; struct tagHlpFilePage* next; struct tagHlpFilePage* prev; + + DWORD browse_bwd; + DWORD browse_fwd; + struct tagHlpFileFile* file; } HLPFILE_PAGE; @@ -89,12 +100,6 @@ typedef struct unsigned long offset; } HLPFILE_CONTEXT; -typedef struct tagHlpFileMacro -{ - LPCSTR lpszMacro; - struct tagHlpFileMacro* next; -} HLPFILE_MACRO; - typedef struct { LOGFONT LogFont; @@ -132,9 +137,9 @@ typedef struct tagHlpFileFile HLPFILE_WINDOWINFO* windows; } HLPFILE; -HLPFILE *HLPFILE_ReadHlpFile(LPCSTR lpszPath); -HLPFILE_PAGE *HLPFILE_Contents(HLPFILE* hlpfile); -HLPFILE_PAGE *HLPFILE_PageByHash(HLPFILE* hlpfile, LONG wNum); +HLPFILE* HLPFILE_ReadHlpFile(LPCSTR lpszPath); +HLPFILE_PAGE* HLPFILE_Contents(HLPFILE* hlpfile); +HLPFILE_PAGE* HLPFILE_PageByHash(HLPFILE* hlpfile, LONG lHash); +HLPFILE_PAGE* HLPFILE_PageByOffset(HLPFILE* hlpfile, LONG offset); LONG HLPFILE_Hash(LPCSTR lpszContext); -VOID HLPFILE_FreeHlpFilePage(HLPFILE_PAGE*); -VOID HLPFILE_FreeHlpFile(HLPFILE*); +void HLPFILE_FreeHlpFile(HLPFILE*); diff --git a/programs/winhelp/macro.c b/programs/winhelp/macro.c index fb3b39696a3..dcf87502d47 100644 --- a/programs/winhelp/macro.c +++ b/programs/winhelp/macro.c @@ -222,12 +222,32 @@ void MACRO_AppendItem(LPCSTR str1, LPCSTR str2, LPCSTR str3, LPCSTR str4) void MACRO_Back(void) { - WINE_FIXME("()\n"); + WINHELP_WINDOW* win = Globals.active_win; + + WINE_TRACE("()\n"); + + if (win && win->backIndex >= 2) + WINHELP_CreateHelpWindow(win->back[--win->backIndex - 1], + win->info, SW_SHOW); } void MACRO_BackFlush(void) { - WINE_FIXME("()\n"); + WINHELP_WINDOW* win = Globals.active_win; + + WINE_TRACE("()\n"); + + if (win) + { + int i; + + for (i = 0; i < win->backIndex; i++) + { + HLPFILE_FreeHlpFile(win->back[i]->file); + win->back[i] = NULL; + } + win->backIndex = 0; + } } void MACRO_BookmarkDefine(void) @@ -599,7 +619,14 @@ void MACRO_HelpOnTop(void) void MACRO_History(void) { - WINE_FIXME("()\n"); + WINE_TRACE("()\n"); + + if (Globals.active_win && !Globals.active_win->hHistoryWnd) + { + HWND hWnd = CreateWindow(HISTORY_WIN_CLASS_NAME, "History", WS_OVERLAPPEDWINDOW, + 0, 0, 0, 0, 0, 0, Globals.hInstance, Globals.active_win); + ShowWindow(hWnd, SW_NORMAL); + } } void MACRO_IfThen(BOOL b, LPCSTR t) @@ -717,7 +744,9 @@ void MACRO_Next(void) HLPFILE_PAGE* page; WINE_TRACE("()\n"); - if ((page = Globals.active_win->page->next) != NULL) + page = Globals.active_win->page; + page = HLPFILE_PageByOffset(page->file, page->browse_fwd); + if (page) { page->file->wRefCount++; WINHELP_CreateHelpWindow(page, Globals.active_win->info, SW_NORMAL); @@ -754,7 +783,9 @@ void MACRO_Prev(void) HLPFILE_PAGE* page; WINE_TRACE("()\n"); - if ((page = Globals.active_win->page->prev) != NULL) + page = Globals.active_win->page; + page = HLPFILE_PageByOffset(page->file, page->browse_bwd); + if (page) { page->file->wRefCount++; WINHELP_CreateHelpWindow(page, Globals.active_win->info, SW_NORMAL); diff --git a/programs/winhelp/string.c b/programs/winhelp/string.c index 17da0f88fd8..4809739d65c 100644 --- a/programs/winhelp/string.c +++ b/programs/winhelp/string.c @@ -24,6 +24,7 @@ char MAIN_WIN_CLASS_NAME[] = "MS_WINHELP"; char BUTTON_BOX_WIN_CLASS_NAME[] = "WHButtonBox"; char TEXT_WIN_CLASS_NAME[] = "WHText"; char SHADOW_WIN_CLASS_NAME[] = "WHShadow"; +char HISTORY_WIN_CLASS_NAME[] = "WHHistory"; char STRING_BUTTON[] = "BUTTON"; /* Resource names */ diff --git a/programs/winhelp/winhelp.c b/programs/winhelp/winhelp.c index 8fa8446f544..3d9c08161f6 100644 --- a/programs/winhelp/winhelp.c +++ b/programs/winhelp/winhelp.c @@ -38,6 +38,7 @@ static BOOL WINHELP_RegisterWinClasses(void); static LRESULT CALLBACK WINHELP_MainWndProc(HWND, UINT, WPARAM, LPARAM); static LRESULT CALLBACK WINHELP_TextWndProc(HWND, UINT, WPARAM, LPARAM); static LRESULT CALLBACK WINHELP_ButtonBoxWndProc(HWND, UINT, WPARAM, LPARAM); +static LRESULT CALLBACK WINHELP_HistoryWndProc(HWND, UINT, WPARAM, LPARAM); static void WINHELP_CheckPopup(UINT); static BOOL WINHELP_SplitLines(HWND hWnd, LPSIZE); static void WINHELP_InitFonts(HWND hWnd); @@ -104,9 +105,9 @@ HLPFILE_WINDOWINFO* WINHELP_GetWindowInfo(HLPFILE* hlpfile, LPCSTR name) { strcpy(mwi.type, "primary"); strcpy(mwi.name, "main"); - LoadString(Globals.hInstance, STID_WINE_HELP, - mwi.caption, sizeof(mwi.caption)); - /*strcpy(mwi.caption, hlpfile->lpszTitle); */ + if (!LoadString(Globals.hInstance, STID_WINE_HELP, + mwi.caption, sizeof(mwi.caption))) + strcpy(mwi.caption, hlpfile->lpszTitle); mwi.origin.x = mwi.origin.y = mwi.size.cx = mwi.size.cy = CW_USEDEFAULT; mwi.style = SW_SHOW; mwi.sr_color = mwi.sr_color = 0xFFFFFF; @@ -214,7 +215,7 @@ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR cmdline, int show) */ static BOOL WINHELP_RegisterWinClasses(void) { - WNDCLASS class_main, class_button_box, class_text, class_shadow; + WNDCLASS class_main, class_button_box, class_text, class_shadow, class_history; class_main.style = CS_HREDRAW | CS_VREDRAW; class_main.lpfnWndProc = WINHELP_MainWndProc; @@ -241,10 +242,15 @@ static BOOL WINHELP_RegisterWinClasses(void) class_shadow.hbrBackground = GetStockObject(GRAY_BRUSH); class_shadow.lpszClassName = SHADOW_WIN_CLASS_NAME; + class_history = class_main; + class_history.lpfnWndProc = WINHELP_HistoryWndProc; + class_history.lpszClassName = HISTORY_WIN_CLASS_NAME; + return (RegisterClass(&class_main) && RegisterClass(&class_button_box) && RegisterClass(&class_text) && - RegisterClass(&class_shadow)); + RegisterClass(&class_shadow) && + RegisterClass(&class_history)); } typedef struct @@ -310,6 +316,96 @@ static LRESULT WINHELP_HandleCommand(HWND hSrcWnd, LPARAM lParam) return 0L; } +/****************************************************************** + * WINHELP_ReuseWindow + * + * + */ +static BOOL WINHELP_ReuseWindow(WINHELP_WINDOW* win, WINHELP_WINDOW* oldwin, + HLPFILE_PAGE* page, int nCmdShow) +{ + int i; + + win->hMainWnd = oldwin->hMainWnd; + win->hButtonBoxWnd = oldwin->hButtonBoxWnd; + win->hTextWnd = oldwin->hTextWnd; + win->hHistoryWnd = oldwin->hHistoryWnd; + oldwin->hMainWnd = oldwin->hButtonBoxWnd = oldwin->hTextWnd = oldwin->hHistoryWnd = 0; + + SetWindowLong(win->hMainWnd, 0, (LONG)win); + SetWindowLong(win->hButtonBoxWnd, 0, (LONG)win); + SetWindowLong(win->hTextWnd, 0, (LONG)win); + SetWindowLong(win->hHistoryWnd, 0, (LONG)win); + + WINHELP_InitFonts(win->hMainWnd); + + if (page) + SetWindowText(win->hMainWnd, page->file->lpszTitle); + + WINHELP_SetupText(win->hTextWnd); + InvalidateRect(win->hTextWnd, NULL, TRUE); + SendMessage(win->hMainWnd, WM_USER, 0, 0); + ShowWindow(win->hMainWnd, nCmdShow); + UpdateWindow(win->hTextWnd); + + if (!(win->info->win_style & WS_POPUP)) + { + unsigned num; + + memcpy(win->history, oldwin->history, sizeof(win->history)); + win->histIndex = oldwin->histIndex; + + /* FIXME: when using back, we shouldn't update the history... */ + + if (page) + { + for (i = 0; i < win->histIndex; i++) + if (win->history[i] == page) break; + + /* if the new page is already in the history, do nothing */ + if (i == win->histIndex) + { + num = sizeof(win->history) / sizeof(win->history[0]); + if (win->histIndex == num) + { + /* we're full, remove latest entry */ + HLPFILE_FreeHlpFile(win->history[0]->file); + memmove(&win->history[0], &win->history[1], + (num - 1) * sizeof(win->history[0])); + win->histIndex--; + } + win->history[win->histIndex++] = page; + page->file->wRefCount++; + if (win->hHistoryWnd) InvalidateRect(win->hHistoryWnd, NULL, TRUE); + } + } + + memcpy(win->back, oldwin->back, sizeof(win->back)); + win->backIndex = oldwin->backIndex; + + if (page) + { + num = sizeof(win->back) / sizeof(win->back[0]); + if (win->backIndex == num) + { + /* we're full, remove latest entry */ + HLPFILE_FreeHlpFile(win->back[0]->file); + memmove(&win->back[0], &win->back[1], + (num - 1) * sizeof(win->back[0])); + win->backIndex--; + } + win->back[win->backIndex++] = page; + page->file->wRefCount++; + } + } + else + win->backIndex = win->histIndex = 0; + + oldwin->histIndex = oldwin->backIndex = 0; + WINHELP_DeleteWindow(oldwin); + return TRUE; +} + /*********************************************************************** * * WINHELP_CreateHelpWindow @@ -320,8 +416,10 @@ BOOL WINHELP_CreateHelpWindow(HLPFILE_PAGE* page, HLPFILE_WINDOWINFO* wi, WINHELP_WINDOW *win, *oldwin; HWND hWnd; BOOL bPrimary; + BOOL bPopup; bPrimary = !lstrcmpi(wi->name, "main"); + bPopup = wi->win_style & WS_POPUP; /* Initialize WINHELP_WINDOW struct */ win = HeapAlloc(GetProcessHeap(), 0, @@ -341,6 +439,7 @@ BOOL WINHELP_CreateHelpWindow(HLPFILE_PAGE* page, HLPFILE_WINDOWINFO* wi, win->hButtonBoxWnd = 0; win->hTextWnd = 0; win->hShadowWnd = 0; + win->hHistoryWnd = 0; win->hArrowCur = LoadCursorA(0, IDC_ARROWA); win->hHandCur = LoadCursorA(0, IDC_HANDA); @@ -372,49 +471,30 @@ BOOL WINHELP_CreateHelpWindow(HLPFILE_PAGE* page, HLPFILE_WINDOWINFO* wi, HLPFILE_MACRO *macro; for (macro = page->file->first_macro; macro; macro = macro->next) MACRO_ExecuteMacro(macro->lpszMacro); + + for (macro = page->first_macro; macro; macro = macro->next) + MACRO_ExecuteMacro(macro->lpszMacro); } /* Reuse existing window */ - if (!(wi->win_style & WS_POPUP)) + if (!bPopup) { for (oldwin = win->next; oldwin; oldwin = oldwin->next) { if (!lstrcmpi(oldwin->lpszName, wi->name)) { - WINHELP_BUTTON *button; - - win->hMainWnd = oldwin->hMainWnd; - win->hButtonBoxWnd = oldwin->hButtonBoxWnd; - win->hTextWnd = oldwin->hTextWnd; - oldwin->hMainWnd = oldwin->hButtonBoxWnd = oldwin->hTextWnd = 0; - - SetWindowLong(win->hMainWnd, 0, (LONG)win); - SetWindowLong(win->hButtonBoxWnd, 0, (LONG)win); - SetWindowLong(win->hTextWnd, 0, (LONG)win); - - WINHELP_InitFonts(win->hMainWnd); - - if (page) { - SetWindowText(win->hMainWnd, page->file->lpszTitle); - } - - WINHELP_SetupText(win->hTextWnd); - InvalidateRect(win->hTextWnd, NULL, TRUE); - SendMessage(win->hMainWnd, WM_USER, 0, 0); - ShowWindow(win->hMainWnd, nCmdShow); - UpdateWindow(win->hTextWnd); - - - for (button = oldwin->first_button; button; button = button->next) - DestroyWindow(button->hWnd); - - WINHELP_DeleteWindow(oldwin); - return TRUE; + return WINHELP_ReuseWindow(win, oldwin, page, nCmdShow); } } - } - hWnd = CreateWindow((wi->win_style & WS_POPUP) ? TEXT_WIN_CLASS_NAME : MAIN_WIN_CLASS_NAME, + win->histIndex = win->backIndex = 1; + win->history[0] = win->back[0] = page; + page->file->wRefCount += 2; + } + else + win->histIndex = win->backIndex = 0; + + hWnd = CreateWindow(bPopup ? TEXT_WIN_CLASS_NAME : MAIN_WIN_CLASS_NAME, wi->caption, wi->win_style, wi->origin.x, wi->origin.y, wi->size.cx, wi->size.cy, 0, bPrimary ? LoadMenu(Globals.hInstance, MAKEINTRESOURCE(MAIN_MENU)) : 0, @@ -854,7 +934,6 @@ static LRESULT CALLBACK WINHELP_TextWndProc(HWND hWnd, UINT msg, WPARAM wParam, win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0); if (hWnd == Globals.hPopupWnd) Globals.hPopupWnd = 0; - if (win->hShadowWnd) DestroyWindow(win->hShadowWnd); bExit = (Globals.wVersion >= 4 && !lstrcmpi(win->lpszName, "main")); @@ -870,6 +949,72 @@ static LRESULT CALLBACK WINHELP_TextWndProc(HWND hWnd, UINT msg, WPARAM wParam, return DefWindowProc(hWnd, msg, wParam, lParam); } +/****************************************************************** + * WINHELP_HistoryWndProc + * + * + */ +static LRESULT CALLBACK WINHELP_HistoryWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WINHELP_WINDOW* win; + PAINTSTRUCT ps; + HDC hDc; + TEXTMETRIC tm; + int i; + RECT r; + + switch (msg) + { + case WM_NCCREATE: + win = (WINHELP_WINDOW*)((LPCREATESTRUCT)lParam)->lpCreateParams; + SetWindowLong(hWnd, 0, (LONG)win); + win->hHistoryWnd = hWnd; + break; + case WM_CREATE: + win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0); + hDc = GetDC(hWnd); + GetTextMetrics(hDc, &tm); + GetWindowRect(hWnd, &r); + + r.right = r.left + 30 * tm.tmAveCharWidth; + r.bottom = r.top + (sizeof(win->history) / sizeof(win->history[0])) * tm.tmHeight; + AdjustWindowRect(&r, GetWindowLong(hWnd, GWL_STYLE), FALSE); + if (r.left < 0) {r.right -= r.left; r.left = 0;} + if (r.top < 0) {r.bottom -= r.top; r.top = 0;} + + MoveWindow(hWnd, r.left, r.top, r.right, r.bottom, TRUE); + ReleaseDC(hWnd, hDc); + break; + case WM_LBUTTONDOWN: + win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0); + hDc = GetDC(hWnd); + GetTextMetrics(hDc, &tm); + i = HIWORD(lParam) / tm.tmHeight; + if (i < win->histIndex) + WINHELP_CreateHelpWindow(win->history[i], win->info, SW_SHOW); + ReleaseDC(hWnd, hDc); + break; + case WM_PAINT: + hDc = BeginPaint(hWnd, &ps); + win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0); + GetTextMetrics(hDc, &tm); + + for (i = 0; i < win->histIndex; i++) + { + TextOut(hDc, 0, i * tm.tmHeight, win->history[i]->lpszTitle, + strlen(win->history[i]->lpszTitle)); + } + EndPaint(hWnd, &ps); + break; + case WM_DESTROY: + win = (WINHELP_WINDOW*) GetWindowLong(hWnd, 0); + if (hWnd == win->hHistoryWnd) + win->hHistoryWnd = 0; + break; + } + return DefWindowProc(hWnd, msg, wParam, lParam); +} + /*********************************************************************** * * SetupText @@ -1315,19 +1460,41 @@ static void WINHELP_DeleteLines(WINHELP_WINDOW *win) * * WINHELP_DeleteWindow */ -static void WINHELP_DeleteWindow(WINHELP_WINDOW *win) +static void WINHELP_DeleteWindow(WINHELP_WINDOW* win) { - WINHELP_WINDOW **w; + WINHELP_WINDOW** w; + int i; + WINHELP_BUTTON* b; + WINHELP_BUTTON* bp; for (w = &Globals.win_list; *w; w = &(*w)->next) + { if (*w == win) { *w = win->next; break; } + } + + for (b = win->first_button; b; b = bp) + { + DestroyWindow(b->hWnd); + bp = b->next; + HeapFree(GetProcessHeap(), 0, b); + } if (win->hShadowWnd) DestroyWindow(win->hShadowWnd); - HLPFILE_FreeHlpFilePage(win->page); + if (win->hHistoryWnd) DestroyWindow(win->hHistoryWnd); + + for (i = 0; i < win->histIndex; i++) + { + HLPFILE_FreeHlpFile(win->history[i]->file); + } + + for (i = 0; i < win->backIndex; i++) + HLPFILE_FreeHlpFile(win->back[i]->file); + + if (win->page) HLPFILE_FreeHlpFile(win->page->file); WINHELP_DeleteLines(win); HeapFree(GetProcessHeap(), 0, win); } @@ -1359,7 +1526,7 @@ static void WINHELP_InitFonts(HWND hWnd) { INT i; - for(i = 0; i < FONTS_LEN; i++) + for (i = 0; i < FONTS_LEN; i++) { fonts[i] = CreateFontIndirect(&logfontlist[i]); } diff --git a/programs/winhelp/winhelp.h b/programs/winhelp/winhelp.h index 9669561b955..cb21d1b6113 100644 --- a/programs/winhelp/winhelp.h +++ b/programs/winhelp/winhelp.h @@ -95,6 +95,7 @@ typedef struct tagWinHelp HWND hButtonBoxWnd; HWND hTextWnd; HWND hShadowWnd; + HWND hHistoryWnd; HFONT* fonts; UINT fonts_len; @@ -104,6 +105,12 @@ typedef struct tagWinHelp HLPFILE_WINDOWINFO* info; + /* FIXME: for now it's a fixed size */ + HLPFILE_PAGE* history[40]; + unsigned histIndex; + HLPFILE_PAGE* back[40]; + unsigned backIndex; + struct tagWinHelp* next; } WINHELP_WINDOW; @@ -131,6 +138,7 @@ extern char MAIN_WIN_CLASS_NAME[]; extern char BUTTON_BOX_WIN_CLASS_NAME[]; extern char TEXT_WIN_CLASS_NAME[]; extern char SHADOW_WIN_CLASS_NAME[]; +extern char HISTORY_WIN_CLASS_NAME[]; extern char STRING_BUTTON[]; extern char STRING_MENU_Xx[]; extern char STRING_DIALOG_TEST[];