Commit c8aba95f authored by Filip Navara's avatar Filip Navara Committed by Alexandre Julliard

- Let the subclassing stack grow the opposite way to make the code

more transparent. - Remove SubclassWndProc and move its logic to DefSubclassProc.
parent 56b51646
...@@ -154,7 +154,7 @@ typedef struct ...@@ -154,7 +154,7 @@ typedef struct
} SubclassProcs[31]; } SubclassProcs[31];
int stackpos; int stackpos;
int stacknum; int stacknum;
int stacknew; int wndprocrecursion;
WNDPROC origproc; WNDPROC origproc;
} SUBCLASS_INFO, *LPSUBCLASS_INFO; } SUBCLASS_INFO, *LPSUBCLASS_INFO;
......
...@@ -114,7 +114,6 @@ extern void TREEVIEW_Unregister(void); ...@@ -114,7 +114,6 @@ extern void TREEVIEW_Unregister(void);
extern void UPDOWN_Register(void); extern void UPDOWN_Register(void);
extern void UPDOWN_Unregister(void); extern void UPDOWN_Unregister(void);
static LRESULT WINAPI SubclassWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
LPSTR COMCTL32_aSubclass = NULL; LPSTR COMCTL32_aSubclass = NULL;
HMODULE COMCTL32_hModule = 0; HMODULE COMCTL32_hModule = 0;
...@@ -1085,7 +1084,7 @@ BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass, ...@@ -1085,7 +1084,7 @@ BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
UINT_PTR uIDSubclass, DWORD_PTR dwRef) UINT_PTR uIDSubclass, DWORD_PTR dwRef)
{ {
LPSUBCLASS_INFO stack; LPSUBCLASS_INFO stack;
int newnum, n; int n;
TRACE ("(%p, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef); TRACE ("(%p, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
...@@ -1109,10 +1108,10 @@ BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass, ...@@ -1109,10 +1108,10 @@ BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
/* set window procedure to our own and save the current one */ /* set window procedure to our own and save the current one */
if (IsWindowUnicode (hWnd)) if (IsWindowUnicode (hWnd))
stack->origproc = (WNDPROC)SetWindowLongW (hWnd, GWL_WNDPROC, stack->origproc = (WNDPROC)SetWindowLongW (hWnd, GWL_WNDPROC,
(LONG)SubclassWndProc); (LONG)DefSubclassProc);
else else
stack->origproc = (WNDPROC)SetWindowLongA (hWnd, GWL_WNDPROC, stack->origproc = (WNDPROC)SetWindowLongA (hWnd, GWL_WNDPROC,
(LONG)SubclassWndProc); (LONG)DefSubclassProc);
} else { } else {
WNDPROC current; WNDPROC current;
if (IsWindowUnicode (hWnd)) if (IsWindowUnicode (hWnd))
...@@ -1120,7 +1119,7 @@ BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass, ...@@ -1120,7 +1119,7 @@ BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
else else
current = (WNDPROC)GetWindowLongA (hWnd, GWL_WNDPROC); current = (WNDPROC)GetWindowLongA (hWnd, GWL_WNDPROC);
if (current != SubclassWndProc) { if (current != DefSubclassProc) {
ERR ("Application has subclassed with our procedure, then manually, then with us again. The current implementation can't handle this.\n"); ERR ("Application has subclassed with our procedure, then manually, then with us again. The current implementation can't handle this.\n");
return FALSE; return FALSE;
} }
...@@ -1128,32 +1127,28 @@ BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass, ...@@ -1128,32 +1127,28 @@ BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
/* Check to see if we have called this function with the same uIDSubClass /* Check to see if we have called this function with the same uIDSubClass
* and pfnSubclass */ * and pfnSubclass */
for (n = 0; n <= stack->stacknum + stack->stacknew - 1; n++) for (n = 0; n < stack->stacknum; n++)
if ((stack->SubclassProcs[n].id == uIDSubclass) && if ((stack->SubclassProcs[n].id == uIDSubclass) &&
(stack->SubclassProcs[n].subproc == pfnSubclass)) { (stack->SubclassProcs[n].subproc == pfnSubclass)) {
stack->SubclassProcs[n].ref = dwRef; stack->SubclassProcs[n].ref = dwRef;
return TRUE; return TRUE;
} }
if ((stack->stacknum + stack->stacknew) >= 32) { if (stack->stacknum >= 32) {
ERR ("We have a Subclass stack overflow, please increment size\n"); ERR ("We have a Subclass stack overflow, please increment size\n");
return FALSE; return FALSE;
} }
/* we can't simply increment both stackpos and stacknum because there might memmove (&stack->SubclassProcs[1], &stack->SubclassProcs[0],
* be a window procedure running lower in the stack, we can only get them sizeof(stack->SubclassProcs[0]) * stack->stacknum);
* up to date once the last window procedure has run */
if (stack->stacknum == stack->stackpos) {
stack->stacknum++; stack->stacknum++;
if (stack->wndprocrecursion)
stack->stackpos++; stack->stackpos++;
} else
stack->stacknew++;
newnum = stack->stacknew + stack->stacknum - 1; stack->SubclassProcs[0].subproc = pfnSubclass;
stack->SubclassProcs[0].ref = dwRef;
stack->SubclassProcs[newnum].subproc = pfnSubclass; stack->SubclassProcs[0].id = uIDSubclass;
stack->SubclassProcs[newnum].ref = dwRef;
stack->SubclassProcs[newnum].id = uIDSubclass;
return TRUE; return TRUE;
} }
...@@ -1188,7 +1183,7 @@ BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass, ...@@ -1188,7 +1183,7 @@ BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
if (!stack) if (!stack)
return FALSE; return FALSE;
for (n = 0; n <= stack->stacknum + stack->stacknew - 1; n++) for (n = 0; n < stack->stacknum; n++)
if ((stack->SubclassProcs[n].id == uID) && if ((stack->SubclassProcs[n].id == uID) &&
(stack->SubclassProcs[n].subproc == pfnSubclass)) { (stack->SubclassProcs[n].subproc == pfnSubclass)) {
*pdwRef = stack->SubclassProcs[n].ref; *pdwRef = stack->SubclassProcs[n].ref;
...@@ -1226,7 +1221,8 @@ BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR u ...@@ -1226,7 +1221,8 @@ BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR u
if (!stack) if (!stack)
return FALSE; return FALSE;
if ((stack->stacknum == 1) && (stack->stackpos == 1) && !stack->stacknew) { if ((stack->stacknum == 1) && (stack->stackpos == 1) &&
!stack->wndprocrecursion) {
TRACE("Last Subclass removed, cleaning up\n"); TRACE("Last Subclass removed, cleaning up\n");
/* clean up our heap and reset the origional window procedure */ /* clean up our heap and reset the origional window procedure */
if (IsWindowUnicode (hWnd)) if (IsWindowUnicode (hWnd))
...@@ -1238,24 +1234,21 @@ BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR u ...@@ -1238,24 +1234,21 @@ BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR u
return TRUE; return TRUE;
} }
for (n = stack->stacknum + stack->stacknew - 1; n >= 0; n--) for (n = stack->stacknum - 1; n >= 0; n--)
if ((stack->SubclassProcs[n].id == uID) && if ((stack->SubclassProcs[n].id == uID) &&
(stack->SubclassProcs[n].subproc == pfnSubclass)) { (stack->SubclassProcs[n].subproc == pfnSubclass)) {
if (n != (stack->stacknum + stack->stacknew)) if (n != stack->stacknum)
/* Fill the hole in the stack */ /* Fill the hole in the stack */
memmove (&stack->SubclassProcs[n], &stack->SubclassProcs[n + 1], memmove (&stack->SubclassProcs[n], &stack->SubclassProcs[n + 1],
sizeof(stack->SubclassProcs[0]) * (stack->stacknew + stack->stacknum - n)); sizeof(stack->SubclassProcs[0]) * (stack->stacknum - n));
stack->SubclassProcs[n].subproc = NULL; stack->SubclassProcs[n].subproc = NULL;
stack->SubclassProcs[n].ref = 0; stack->SubclassProcs[n].ref = 0;
stack->SubclassProcs[n].id = 0; stack->SubclassProcs[n].id = 0;
/* If we are currently running a window procedure we have to manipulate
* the stack position pointers so that we don't corrupt the stack */
if ((n < stack->stackpos) || (stack->stackpos == stack->stacknum)) {
stack->stacknum--; stack->stacknum--;
if (n < stack->stackpos && stack->wndprocrecursion)
stack->stackpos--; stack->stackpos--;
} else if (n >= stack->stackpos)
stack->stacknew--;
return TRUE; return TRUE;
} }
...@@ -1264,33 +1257,6 @@ BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR u ...@@ -1264,33 +1257,6 @@ BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR u
/*********************************************************************** /***********************************************************************
* SubclassWndProc (internal)
*
* Window procedure for all subclassed windows.
* Saves the current subclassing stack position to support nested messages
*/
static LRESULT WINAPI SubclassWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPSUBCLASS_INFO stack;
int stackpos;
LRESULT ret;
/* retrieve our little stack from the Properties */
stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
if (!stack) {
ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
return 0;
}
stackpos = stack->stackpos;
stack->stackpos = stack->stacknum;
ret = DefSubclassProc(hWnd,uMsg,wParam,lParam);
stack->stackpos = stackpos;
return ret;
}
/***********************************************************************
* DefSubclassProc [COMCTL32.413] * DefSubclassProc [COMCTL32.413]
* *
* Calls the next window procedure (ie. the one before this subclass) * Calls the next window procedure (ie. the one before this subclass)
...@@ -1309,7 +1275,6 @@ static LRESULT WINAPI SubclassWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPAR ...@@ -1309,7 +1275,6 @@ static LRESULT WINAPI SubclassWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
LPSUBCLASS_INFO stack; LPSUBCLASS_INFO stack;
int stackpos;
LRESULT ret; LRESULT ret;
/* retrieve our little stack from the Properties */ /* retrieve our little stack from the Properties */
...@@ -1319,24 +1284,27 @@ LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar ...@@ -1319,24 +1284,27 @@ LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
return 0; return 0;
} }
/* If we are at pos 0 then we have to call the origional window procedure */ stack->wndprocrecursion++;
if (stack->stackpos == 0) {
/* If we are at the end of stack then we have to call the original
* window procedure */
if (stack->stackpos == stack->stacknum) {
if (IsWindowUnicode (hWnd)) if (IsWindowUnicode (hWnd))
return CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam); ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
else else
return CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam); ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
} } else {
stackpos = --stack->stackpos;
/* call the Subclass procedure from the stack */
ret = stack->SubclassProcs[stackpos].subproc (hWnd, uMsg, wParam, lParam,
stack->SubclassProcs[stackpos].id, stack->SubclassProcs[stackpos].ref);
stack->stackpos++; stack->stackpos++;
/* call the Subclass procedure from the stack */
ret = stack->SubclassProcs[stack->stackpos - 1].subproc (hWnd, uMsg, wParam, lParam,
stack->SubclassProcs[stack->stackpos - 1].id, stack->SubclassProcs[stack->stackpos - 1].ref);
stack->stackpos--;
}
if ((stack->stackpos == stack->stacknum) && stack->stacknew) { /* We finished the recursion, so let's reinitalize the stack position to
stack->stacknum += stack->stacknew; * beginning */
stack->stackpos += stack->stacknew; if ((--stack->wndprocrecursion) == 0) {
stack->stacknew = 0; stack->stackpos = 0;
} }
/* If we removed the last entry in our stack while a window procedure was /* If we removed the last entry in our stack while a window procedure was
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment