windows-vs2005b2-20050706
[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    size_t iTarget;
97    for (iTarget = 0; iTarget < nTargets; ++iTarget)
98       {
99       if (aTargets[ iTarget ].hTarget == hTarget)
100          break;
101       }
102    if (iTarget >= nTargets)
103       {
104       for (iTarget = 0; iTarget < nTargets; ++iTarget)
105          {
106          if (aTargets[ iTarget ].hTarget == NULL)
107             break;
108          }
109       }
110    if (iTarget >= nTargets)
111       {
112       if (!REALLOC (aTargets, nTargets, 1+iTarget, cREALLOC_SUBCLASS_TARGETS))
113          return FALSE;
114       }
115
116    aTargets[ iTarget ].hTarget = hTarget;
117
118    size_t iHook;
119    for (iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
120       {
121       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == wndProc)
122          break;
123       }
124    if (iHook >= aTargets[ iTarget ].nHooks)
125       {
126       for (iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
127          {
128          if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == NULL)
129             break;
130          }
131       }
132    if (iHook >= aTargets[ iTarget ].nHooks)
133       {
134       if (!REALLOC (aTargets[ iTarget ].aHooks, aTargets[ iTarget ].nHooks, 1+iHook, cREALLOC_SUBCLASS_HOOKS))
135          return FALSE;
136       }
137
138    aTargets[ iTarget ].aHooks[ iHook ].wndProc = wndProc;
139    aTargets[ iTarget ].aHooks[ iHook ].nReq ++;
140    aTargets[ iTarget ].nHooksActive ++;
141
142    if (aTargets[ iTarget ].nHooksActive == 1)
143       {
144       aTargets[ iTarget ].procOrig = (PVOID)GetWindowLong (hTarget, GWL_WNDPROC);
145       SetWindowLong (hTarget, GWL_WNDPROC, (LONG)Subclass_WndProc);
146       }
147
148    return TRUE;
149 }
150
151
152 void Subclass_RemoveHook (HWND hTarget, PVOID wndProc)
153 {
154    size_t iTarget;
155    for (iTarget = 0; iTarget < nTargets; ++iTarget)
156       {
157       if (aTargets[ iTarget ].hTarget == hTarget)
158          break;
159       }
160    if (iTarget < nTargets)
161       {
162       size_t iHook;
163       for (iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
164          {
165          if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == wndProc)
166             break;
167          }
168       if (iHook < aTargets[ iTarget ].nHooks)
169          {
170          aTargets[ iTarget ].aHooks[ iHook ].nReq --;
171          if (aTargets[ iTarget ].aHooks[ iHook ].nReq == 0)
172             {
173             memset (&aTargets[ iTarget ].aHooks[ iHook ], 0x00, sizeof(aTargets[ iTarget ].aHooks[ iHook ]));
174             }
175          }
176
177       aTargets[ iTarget ].nHooksActive --;
178       if (aTargets[ iTarget ].nHooksActive == 0)
179          {
180          SetWindowLong (aTargets[ iTarget ].hTarget, GWL_WNDPROC, (LONG)aTargets[ iTarget ].procOrig);
181          memset (&aTargets[ iTarget ], 0x00, sizeof(aTargets[ iTarget ]));
182          }
183       }
184 }
185
186
187 PVOID Subclass_FindNextHook (HWND hTarget, PVOID wndProc)
188 {
189    size_t iTarget;
190    for (iTarget = 0; iTarget < nTargets; ++iTarget)
191       {
192       if (aTargets[ iTarget ].hTarget == hTarget)
193          break;
194       }
195    if (iTarget >= nTargets)
196       return NULL;
197
198    size_t iHook;
199    for (iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
200       {
201       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc == wndProc)
202          break;
203       }
204    if (iHook >= aTargets[ iTarget ].nHooks)
205       return aTargets[ iTarget ].procOrig;
206
207    for (++iHook; iHook < aTargets[iTarget].nHooks; ++iHook)
208       {
209       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc != NULL)
210          return aTargets[ iTarget ].aHooks[ iHook ].wndProc;
211       }
212
213    return aTargets[ iTarget ].procOrig;
214 }
215
216
217 LONG CALLBACK Subclass_WndProc (HWND hTarget, UINT msg, WPARAM wp, LPARAM lp)
218 {
219    size_t iTarget;
220    for (iTarget = 0; iTarget < nTargets; ++iTarget)
221       {
222       if (aTargets[ iTarget ].hTarget == hTarget)
223          break;
224       }
225    if (iTarget >= nTargets)
226       return DefWindowProc (hTarget, msg, wp, lp);
227
228    size_t iHook;
229    for (iHook = 0; iHook < aTargets[iTarget].nHooks; ++iHook)
230       {
231       if (aTargets[ iTarget ].aHooks[ iHook ].wndProc != NULL)
232          break;
233       }
234
235    if (iHook >= aTargets[iTarget].nHooks)
236       return CallWindowProc ((WNDPROC)aTargets[ iTarget ].procOrig, hTarget, msg, wp, lp);
237    else
238       return CallWindowProc ((WNDPROC)aTargets[ iTarget ].aHooks[ iHook ].wndProc, hTarget, msg, wp, lp);
239 }
240