skyrope-mit-merge-hell-20040226
[openafs.git] / src / WINNT / afsapplib / subclass.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 }
14
15 #include <windows.h>
16 #include <WINNT/subclass.h>
17
18
19 /*
20  * PROTOTYPES _________________________________________________________________
21  *
22  */
23
24 LONG CALLBACK Subclass_WndProc (HWND hTarget, UINT msg, WPARAM wp, LPARAM lp);
25
26
27 /*
28  * MISCELLANEOUS ______________________________________________________________
29  *
30  */
31
32 #ifndef REALLOC
33 #define REALLOC(_a,_c,_r,_i) SubclassReallocFunction ((LPVOID*)&_a,sizeof(*_a),&_c,_r,_i)
34 BOOL SubclassReallocFunction (LPVOID *ppTarget, size_t cbElement, size_t *pcTarget, size_t cReq, size_t cInc)
35 {
36    LPVOID pNew;
37    size_t cNew;
38
39    if (cReq <= *pcTarget)
40       return TRUE;
41
42    if ((cNew = cInc * ((cReq + cInc-1) / cInc)) <= 0)
43       return FALSE;
44
45    if ((pNew = (LPVOID)GlobalAlloc (GMEM_FIXED, cbElement * cNew)) == NULL)
46       return FALSE;
47    memset (pNew, 0x00, cbElement * cNew);
48
49    if (*pcTarget != 0)
50       {
51       memcpy (pNew, *ppTarget, cbElement * (*pcTarget));
52       GlobalFree ((HGLOBAL)*ppTarget);
53       }
54
55    *ppTarget = pNew;
56    *pcTarget = cNew;
57    return TRUE;
58 }
59 #endif
60
61
62 /*
63  * VARIABLES __________________________________________________________________
64  *
65  */
66
67 typedef struct
68    {
69    HWND hTarget;        // window being subclassed
70    PVOID procOrig;      // original pre-SubclassProc proc
71
72    struct
73       {
74       PVOID wndProc;
75       size_t nReq;
76       } *aHooks;
77
78    size_t nHooks;       // number of entries in aHooks
79    size_t nHooksActive; // number of hooks in use
80    } SubclassWindow;
81
82 SubclassWindow *aTargets = NULL;
83 size_t nTargets = 0;
84
85 #define cREALLOC_SUBCLASS_TARGETS  8
86 #define cREALLOC_SUBCLASS_HOOKS    4
87
88
89 /*
90  * ROUTINES ___________________________________________________________________
91  *
92  */
93
94 BOOL Subclass_AddHook (HWND hTarget, PVOID wndProc)
95 {
96    for (size_t iTarget = 0; iTarget < nTargets; ++iTarget)
97       {
98       if (aTargets[ iTarget ].hTarget == hTarget)
99          break;
100       }
101    if (iTarget >= nTargets)
102       {
103       for (iTarget = 0; iTarget < nTargets; ++iTarget)
104          {
105          if (aTargets[ iTarget ].hTarget == NULL)
106             break;
107          }
108       }
109    if (iTarget >= nTargets)
110       {
111       if (!REALLOC (aTargets, nTargets, 1+iTarget, cREALLOC_SUBCLASS_TARGETS))
112          return FALSE;
113       }
114
115    aTargets[ iTarget ].hTarget = hTarget;
116
117
118    for (size_t iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
119       {
120       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == wndProc)
121          break;
122       }
123    if (iHook >= aTargets[ iTarget ].nHooks)
124       {
125       for (iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
126          {
127          if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == NULL)
128             break;
129          }
130       }
131    if (iHook >= aTargets[ iTarget ].nHooks)
132       {
133       if (!REALLOC (aTargets[ iTarget ].aHooks, aTargets[ iTarget ].nHooks, 1+iHook, cREALLOC_SUBCLASS_HOOKS))
134          return FALSE;
135       }
136
137    aTargets[ iTarget ].aHooks[ iHook ].wndProc = wndProc;
138    aTargets[ iTarget ].aHooks[ iHook ].nReq ++;
139    aTargets[ iTarget ].nHooksActive ++;
140
141    if (aTargets[ iTarget ].nHooksActive == 1)
142       {
143       aTargets[ iTarget ].procOrig = (PVOID)GetWindowLong (hTarget, GWL_WNDPROC);
144       SetWindowLong (hTarget, GWL_WNDPROC, (LONG)Subclass_WndProc);
145       }
146
147    return TRUE;
148 }
149
150
151 void Subclass_RemoveHook (HWND hTarget, PVOID wndProc)
152 {
153    for (size_t iTarget = 0; iTarget < nTargets; ++iTarget)
154       {
155       if (aTargets[ iTarget ].hTarget == hTarget)
156          break;
157       }
158    if (iTarget < nTargets)
159       {
160       for (size_t iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
161          {
162          if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == wndProc)
163             break;
164          }
165       if (iHook < aTargets[ iTarget ].nHooks)
166          {
167          aTargets[ iTarget ].aHooks[ iHook ].nReq --;
168          if (aTargets[ iTarget ].aHooks[ iHook ].nReq == 0)
169             {
170             memset (&aTargets[ iTarget ].aHooks[ iHook ], 0x00, sizeof(aTargets[ iTarget ].aHooks[ iHook ]));
171             }
172          }
173
174       aTargets[ iTarget ].nHooksActive --;
175       if (aTargets[ iTarget ].nHooksActive == 0)
176          {
177          SetWindowLong (aTargets[ iTarget ].hTarget, GWL_WNDPROC, (LONG)aTargets[ iTarget ].procOrig);
178          memset (&aTargets[ iTarget ], 0x00, sizeof(aTargets[ iTarget ]));
179          }
180       }
181 }
182
183
184 PVOID Subclass_FindNextHook (HWND hTarget, PVOID wndProc)
185 {
186    for (size_t iTarget = 0; iTarget < nTargets; ++iTarget)
187       {
188       if (aTargets[ iTarget ].hTarget == hTarget)
189          break;
190       }
191    if (iTarget >= nTargets)
192       return NULL;
193
194    for (size_t iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
195       {
196       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == wndProc)
197          break;
198       }
199    if (iHook >= aTargets[ iTarget ].nHooks)
200       return aTargets[ iTarget ].procOrig;
201
202    for (++iHook; iHook < aTargets[iTarget].nHooks; ++iHook)
203       {
204       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc != NULL)
205          return aTargets[ iTarget ].aHooks[ iHook ].wndProc;
206       }
207
208    return aTargets[ iTarget ].procOrig;
209 }
210
211
212 LONG CALLBACK Subclass_WndProc (HWND hTarget, UINT msg, WPARAM wp, LPARAM lp)
213 {
214    for (size_t iTarget = 0; iTarget < nTargets; ++iTarget)
215       {
216       if (aTargets[ iTarget ].hTarget == hTarget)
217          break;
218       }
219    if (iTarget >= nTargets)
220       return DefWindowProc (hTarget, msg, wp, lp);
221
222    for (size_t iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
223       {
224       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc != NULL)
225          break;
226       }
227
228    if (iHook >= aTargets[iTarget].nHooks)
229       return CallWindowProc ((WNDPROC)aTargets[ iTarget ].procOrig, hTarget, msg, wp, lp);
230    else
231       return CallWindowProc ((WNDPROC)aTargets[ iTarget ].aHooks[ iHook ].wndProc, hTarget, msg, wp, lp);
232 }
233