Eric Pouech : winhlp32: Now manage windows with refcounts.
Alexandre Julliard
julliard at winehq.org
Mon Jun 1 10:01:02 CDT 2009
Module: wine
Branch: master
Commit: 82ffc04ef3b98c0cdc70b0c4ad373dd569c4c082
URL: http://source.winehq.org/git/wine.git/?a=commit;h=82ffc04ef3b98c0cdc70b0c4ad373dd569c4c082
Author: Eric Pouech <eric.pouech at orange.fr>
Date: Sat May 30 14:27:04 2009 +0200
winhlp32: Now manage windows with refcounts.
---
programs/winhlp32/macro.c | 6 ++--
programs/winhlp32/macro.lex.l | 3 +-
programs/winhlp32/winhelp.c | 67 +++++++++++++++++++++++++++++++----------
programs/winhlp32/winhelp.h | 3 ++
4 files changed, 59 insertions(+), 20 deletions(-)
diff --git a/programs/winhlp32/macro.c b/programs/winhlp32/macro.c
index 3383545..c2fc3cc 100644
--- a/programs/winhlp32/macro.c
+++ b/programs/winhlp32/macro.c
@@ -281,7 +281,7 @@ static void CALLBACK MACRO_CloseSecondarys(void)
WINE_TRACE("()\n");
for (win = Globals.win_list; win; win = win->next)
if (lstrcmpi(win->info->name, "main"))
- DestroyWindow(win->hMainWnd);
+ WINHELP_ReleaseWindow(win);
}
static void CALLBACK MACRO_CloseWindow(LPCSTR lpszWindow)
@@ -294,7 +294,7 @@ static void CALLBACK MACRO_CloseWindow(LPCSTR lpszWindow)
for (win = Globals.win_list; win; win = win->next)
if (!lstrcmpi(win->info->name, lpszWindow))
- DestroyWindow(win->hMainWnd);
+ WINHELP_ReleaseWindow(win);
}
static void CALLBACK MACRO_Compare(LPCSTR str)
@@ -367,7 +367,7 @@ void CALLBACK MACRO_Exit(void)
WINE_TRACE("()\n");
while (Globals.win_list)
- DestroyWindow(Globals.win_list->hMainWnd);
+ WINHELP_ReleaseWindow(Globals.win_list);
}
static void CALLBACK MACRO_ExtAbleItem(LPCSTR str, LONG u)
diff --git a/programs/winhlp32/macro.lex.l b/programs/winhlp32/macro.lex.l
index bf65fa0..67926cb 100644
--- a/programs/winhlp32/macro.lex.l
+++ b/programs/winhlp32/macro.lex.l
@@ -285,7 +285,7 @@ BOOL MACRO_ExecuteMacro(WINHELP_WINDOW* window, LPCSTR macro)
memset(lex_data, 0, sizeof(*lex_data));
lex_data->macroptr = macro;
- lex_data->window = window;
+ lex_data->window = WINHELP_GrabWindow(window);
while ((t = yylex()) != EMPTY)
{
@@ -316,6 +316,7 @@ done:
for (t = 0; t < lex_data->cache_used; t++)
HeapFree(GetProcessHeap(), 0, lex_data->cache_string[t]);
lex_data = prev_lex_data;
+ WINHELP_ReleaseWindow(window);
return ret;
}
diff --git a/programs/winhlp32/winhelp.c b/programs/winhlp32/winhelp.c
index 8e6ba50..027bf65 100644
--- a/programs/winhlp32/winhelp.c
+++ b/programs/winhlp32/winhelp.c
@@ -500,11 +500,39 @@ static void WINHELP_DeletePageLinks(HLPFILE_PAGE* page)
/***********************************************************************
*
+ * WINHELP_GrabWindow
+ */
+WINHELP_WINDOW* WINHELP_GrabWindow(WINHELP_WINDOW* win)
+{
+ WINE_TRACE("Grab %p#%d++\n", win, win->ref_count);
+ win->ref_count++;
+ return win;
+}
+
+/***********************************************************************
+ *
+ * WINHELP_RelaseWindow
+ */
+BOOL WINHELP_ReleaseWindow(WINHELP_WINDOW* win)
+{
+ WINE_TRACE("Release %p#%d--\n", win, win->ref_count);
+
+ if (!--win->ref_count)
+ {
+ DestroyWindow(win->hMainWnd);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/***********************************************************************
+ *
* WINHELP_DeleteWindow
*/
static void WINHELP_DeleteWindow(WINHELP_WINDOW* win)
{
WINHELP_WINDOW** w;
+ BOOL bExit;
for (w = &Globals.win_list; *w; w = &(*w)->next)
{
@@ -514,6 +542,7 @@ static void WINHELP_DeleteWindow(WINHELP_WINDOW* win)
break;
}
}
+ bExit = (Globals.wVersion >= 4 && !lstrcmpi(win->info->name, "main"));
if (Globals.active_win == win)
{
@@ -537,6 +566,10 @@ static void WINHELP_DeleteWindow(WINHELP_WINDOW* win)
if (win->page) HLPFILE_FreeHlpFile(win->page->file);
HeapFree(GetProcessHeap(), 0, win);
+
+ if (bExit) MACRO_Exit();
+ if (!Globals.win_list)
+ PostQuitMessage(0);
}
static char* WINHELP_GetCaption(WINHELP_WNDPAGE* wpage)
@@ -706,9 +739,11 @@ BOOL WINHELP_CreateHelpWindow(WINHELP_WNDPAGE* wpage, int nCmdShow, BOOL remembe
win->hHandCur = LoadCursorW(0, (LPWSTR)IDC_HAND);
win->back.index = 0;
win->font_scale = 1;
+ WINHELP_GrabWindow(win);
}
win->page = wpage->page;
win->info = wpage->wininfo;
+ WINHELP_GrabWindow(win);
if (!bPopup && wpage->page && remember)
{
@@ -772,6 +807,14 @@ BOOL WINHELP_CreateHelpWindow(WINHELP_WNDPAGE* wpage, int nCmdShow, BOOL remembe
for (macro = wpage->page->first_macro; macro; macro = macro->next)
MACRO_ExecuteMacro(win, macro->lpszMacro);
}
+ /* See #17681, in some cases, the newly created window is closed by the macros it contains
+ * (braindead), so deal with this case
+ */
+ for (win = Globals.win_list; win; win = win->next)
+ {
+ if (!lstrcmpi(win->info->name, wpage->wininfo->name)) break;
+ }
+ if (!win || !WINHELP_ReleaseWindow(win)) return TRUE;
if (bPopup)
{
@@ -883,7 +926,7 @@ static BOOL WINHELP_HandleTextMouse(WINHELP_WINDOW* win, UINT msg, LPARAM lParam
*/
static BOOL WINHELP_CheckPopup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* lret)
{
- HWND hPopup;
+ WINHELP_WINDOW* popup;
if (!Globals.active_popup) return FALSE;
@@ -916,9 +959,9 @@ static BOOL WINHELP_CheckPopup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam
case WM_NCLBUTTONDOWN:
case WM_NCMBUTTONDOWN:
case WM_NCRBUTTONDOWN:
- hPopup = Globals.active_popup->hMainWnd;
+ popup = Globals.active_popup;
Globals.active_popup = NULL;
- DestroyWindow(hPopup);
+ WINHELP_ReleaseWindow(popup);
return TRUE;
}
return FALSE;
@@ -1422,7 +1465,8 @@ static LRESULT CALLBACK WINHELP_MainWndProc(HWND hWnd, UINT msg, WPARAM wParam,
switch (msgf->msg)
{
case WM_KEYUP:
- if (msgf->wParam == VK_ESCAPE) DestroyWindow(hWnd);
+ if (msgf->wParam == VK_ESCAPE)
+ WINHELP_ReleaseWindow((WINHELP_WINDOW*)GetWindowLongPtr(hWnd, 0));
break;
case WM_RBUTTONDOWN:
{
@@ -1486,18 +1530,9 @@ static LRESULT CALLBACK WINHELP_MainWndProc(HWND hWnd, UINT msg, WPARAM wParam,
CheckMenuItem((HMENU)wParam, MNID_OPTS_FONTS_LARGE,
MF_BYCOMMAND | (win->font_scale == 2) ? MF_CHECKED : 0);
break;
-
- case WM_NCDESTROY:
- {
- BOOL bExit;
- win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
- bExit = (Globals.wVersion >= 4 && !lstrcmpi(win->info->name, "main"));
- WINHELP_DeleteWindow(win);
-
- if (bExit) MACRO_Exit();
- if (!Globals.win_list)
- PostQuitMessage(0);
- }
+ case WM_DESTROY:
+ win = (WINHELP_WINDOW*) GetWindowLongPtr(hWnd, 0);
+ WINHELP_DeleteWindow(win);
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
diff --git a/programs/winhlp32/winhelp.h b/programs/winhlp32/winhelp.h
index 70e2dc2..e770cb5 100644
--- a/programs/winhlp32/winhelp.h
+++ b/programs/winhlp32/winhelp.h
@@ -71,6 +71,7 @@ typedef struct tagPageSet
typedef struct tagWinHelp
{
+ unsigned ref_count;
WINHELP_BUTTON* first_button;
HLPFILE_PAGE* page;
@@ -151,6 +152,8 @@ void WINHELP_DeleteBackSet(WINHELP_WINDOW*);
HLPFILE* WINHELP_LookupHelpFile(LPCSTR lpszFile);
HLPFILE_WINDOWINFO* WINHELP_GetWindowInfo(HLPFILE* hlpfile, LPCSTR name);
void WINHELP_LayoutMainWindow(WINHELP_WINDOW* win);
+WINHELP_WINDOW* WINHELP_GrabWindow(WINHELP_WINDOW*);
+BOOL WINHELP_ReleaseWindow(WINHELP_WINDOW*);
extern const char MAIN_WIN_CLASS_NAME[];
extern const char BUTTON_BOX_WIN_CLASS_NAME[];
More information about the wine-cvs
mailing list