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

more transparent.
- Remove SubclassWndProc and move its logic to DefSubclassProc.
This commit is contained in:
Filip Navara 2004-05-17 19:48:24 +00:00 committed by Alexandre Julliard
parent 56b5164686
commit c8aba95f50
2 changed files with 41 additions and 73 deletions

View File

@ -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;

View File

@ -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,
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,
/* 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,
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,
/* 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,
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
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
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;
} }
@ -1263,33 +1256,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]
* *
@ -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
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 {
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--;
} }
stackpos = --stack->stackpos; /* We finished the recursion, so let's reinitalize the stack position to
/* call the Subclass procedure from the stack */ * beginning */
ret = stack->SubclassProcs[stackpos].subproc (hWnd, uMsg, wParam, lParam, if ((--stack->wndprocrecursion) == 0) {
stack->SubclassProcs[stackpos].id, stack->SubclassProcs[stackpos].ref); stack->stackpos = 0;
stack->stackpos++;
if ((stack->stackpos == stack->stacknum) && stack->stacknew) {
stack->stacknum += stack->stacknew;
stack->stackpos += stack->stacknew;
stack->stacknew = 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