2 * Copyright 2000, International Business Machines Corporation and others.
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
11 #include <afs/param.h>
20 #include <WINNT/dialog.h>
21 #include <WINNT/resize.h> // for GetRectInParent()
22 #include <WINNT/subclass.h>
23 #include <WINNT/ctl_spinner.h>
24 #include <WINNT/ctl_sockaddr.h>
25 #include <WINNT/TaLocale.h>
28 #define cchRESOURCE 256
33 * MISCELLANEOUS ______________________________________________________________
38 #define REALLOC(_a,_c,_r,_i) SockAddrReallocFunction ((LPVOID*)&_a,sizeof(*_a),&_c,_r,_i)
39 BOOL
SockAddrReallocFunction (LPVOID
*ppTarget
, size_t cbElement
, size_t *pcTarget
, size_t cReq
, size_t cInc
)
44 if (cReq
<= *pcTarget
)
47 if ((cNew
= cInc
* ((cReq
+ cInc
-1) / cInc
)) <= 0)
50 if ((pNew
= (LPVOID
)Allocate (cbElement
* cNew
)) == NULL
)
52 memset (pNew
, 0x00, cbElement
* cNew
);
56 memcpy (pNew
, *ppTarget
, cbElement
* (*pcTarget
));
68 * SOCKADDRS __________________________________________________________________
94 static CRITICAL_SECTION csSockAddr
;
95 static SockAddrInfo
*aSockAddr
= NULL
;
96 static size_t cSockAddr
= 0;
98 #define cszSOCKADDRCLASS TEXT("SockAddr")
100 HRESULT CALLBACK
SockAddrProc (HWND hSockAddr
, UINT msg
, WPARAM wp
, LPARAM lp
);
101 HRESULT CALLBACK
SockAddrEditProc (HWND hEdit
, UINT msg
, WPARAM wp
, LPARAM lp
);
102 HRESULT CALLBACK
SockAddrDlgProc (HWND hDlg
, UINT msg
, WPARAM wp
, LPARAM lp
);
104 void SockAddr_SendCallback (SockAddrInfo
*psai
, WORD eln
, LPARAM lp
);
106 void SockAddr_OnCreate (SockAddrInfo
*psai
);
107 void SockAddr_OnDestroy (SockAddrInfo
*psai
);
108 void SockAddr_OnButtonDown (SockAddrInfo
*psai
, UINT msg
, WPARAM wp
, LPARAM lp
);
109 BOOL
SockAddr_OnGetAddr (SockAddrInfo
*psai
, WPARAM wp
, LPARAM lp
);
110 BOOL
SockAddr_OnSetAddr (SockAddrInfo
*psai
, WPARAM wp
, LPARAM lp
);
112 void SockAddr_Edit_OnChange (SockAddrInfo
*psai
, HWND hEdit
);
113 void SockAddr_Edit_OnUpdate (SockAddrInfo
*psai
, HWND hEdit
);
114 void SockAddr_Edit_SetText (SockAddrInfo
*psai
, HWND hEdit
);
116 #define cszSOCKSEP TEXT(".")
118 BOOL
RegisterSockAddrClass (void)
120 static BOOL fRegistered
= FALSE
;
124 InitializeCriticalSection (&csSockAddr
);
127 memset (&wc
, 0x00, sizeof(wc
));
128 wc
.style
= CS_GLOBALCLASS
;
129 wc
.lpfnWndProc
= (WNDPROC
)SockAddrProc
;
130 wc
.hInstance
= THIS_HINST
;
131 wc
.hCursor
= LoadCursor (NULL
, MAKEINTRESOURCE (IDC_ARROW
));
132 wc
.hbrBackground
= CreateSolidBrush (GetSysColor (COLOR_BTNFACE
));
133 wc
.lpszClassName
= cszSOCKADDRCLASS
;
135 if (RegisterClass (&wc
))
143 void SockAddr_SendCallback (SockAddrInfo
*psai
, WORD san
, LPARAM lp
)
145 if (!psai
->fCallingBack
)
147 psai
->fCallingBack
= TRUE
;
149 SendMessage (GetParent (psai
->hSockAddr
),
151 MAKELONG ((WORD
)GetWindowLong (psai
->hSockAddr
, GWL_ID
), san
),
154 psai
->fCallingBack
= FALSE
;
159 HRESULT CALLBACK
SockAddrProc (HWND hSockAddr
, UINT msg
, WPARAM wp
, LPARAM lp
)
161 SockAddrInfo
*psai
= NULL
;
163 EnterCriticalSection (&csSockAddr
);
165 if (msg
== WM_CREATE
)
168 for (iSockAddr
= 0; iSockAddr
< cSockAddr
; ++iSockAddr
)
170 if (aSockAddr
[ iSockAddr
].hSockAddr
== NULL
)
173 if (iSockAddr
>= cSockAddr
)
175 if (!REALLOC (aSockAddr
, cSockAddr
, 1+iSockAddr
, 4))
179 memset (&aSockAddr
[ iSockAddr
], 0x00, sizeof(SockAddrInfo
));
180 aSockAddr
[ iSockAddr
].hSockAddr
= hSockAddr
;
182 psai
= &aSockAddr
[ iSockAddr
];
186 for (size_t iSockAddr
= 0; !psai
&& iSockAddr
< cSockAddr
; ++iSockAddr
)
188 if (aSockAddr
[ iSockAddr
].hSockAddr
== hSockAddr
)
189 psai
= &aSockAddr
[ iSockAddr
];
193 LeaveCriticalSection (&csSockAddr
);
200 SockAddr_OnCreate (psai
);
204 SockAddr_OnDestroy (psai
);
209 SockAddr_OnButtonDown (psai
, msg
, wp
, lp
);
213 PostMessage (GetParent(hSockAddr
), WM_NEXTDLGCTL
, (WPARAM
)psai
->hE1
, TRUE
);
217 EnableWindow (psai
->hE1
, IsWindowEnabled (hSockAddr
));
218 EnableWindow (psai
->hSep1
, IsWindowEnabled (hSockAddr
));
219 EnableWindow (psai
->hE2
, IsWindowEnabled (hSockAddr
));
220 EnableWindow (psai
->hSep2
, IsWindowEnabled (hSockAddr
));
221 EnableWindow (psai
->hE3
, IsWindowEnabled (hSockAddr
));
222 EnableWindow (psai
->hSep3
, IsWindowEnabled (hSockAddr
));
223 EnableWindow (psai
->hE4
, IsWindowEnabled (hSockAddr
));
226 GetRectInParent (hSockAddr
, &rSockAddr
);
227 InvalidateRect (GetParent(hSockAddr
), &rSockAddr
, TRUE
);
228 UpdateWindow (GetParent(hSockAddr
));
232 return SockAddr_OnGetAddr (psai
, wp
, lp
);
235 return SockAddr_OnSetAddr (psai
, wp
, lp
);
239 return DefWindowProc (hSockAddr
, msg
, wp
, lp
);
243 void SockAddr_OnCreate (SockAddrInfo
*psai
)
245 Subclass_AddHook (GetParent(psai
->hSockAddr
), SockAddrDlgProc
);
248 GetClientRect (psai
->hSockAddr
, &rSockAddr
);
250 POINT ptSockAddr
= {0,0};
251 ClientToScreen (psai
->hSockAddr
, &ptSockAddr
);
252 ScreenToClient (GetParent (psai
->hSockAddr
), &ptSockAddr
);
254 SIZE s888
; // size of widest likely triple-digit number
255 SIZE sSockSep
; // size of "."
257 HDC hdc
= GetDC (GetParent (psai
->hSockAddr
));
258 GetTextExtentPoint (hdc
, TEXT("888"), lstrlen(TEXT("888")), &s888
);
259 GetTextExtentPoint (hdc
, cszSOCKSEP
, lstrlen(cszSOCKSEP
), &sSockSep
);
260 ReleaseDC (GetParent (psai
->hSockAddr
), hdc
);
262 LONG cxNumbers
= cxRECT(rSockAddr
) - (3 * sSockSep
.cx
);
263 LONG cxE2
= cxNumbers
/4;
264 LONG cxE1
= cxNumbers
- cxE2
* 3;
265 LONG yy
= ptSockAddr
.y
;
266 LONG cy
= cyRECT(rSockAddr
);
268 cxE2
= min (cxE2
, (LONG
)( 1.4 * s888
.cx
));
269 cxE1
= min (cxE1
, (LONG
)( 1.4 * s888
.cx
)); // don't be TOO wide.
271 psai
->idE1
= 100+NextControlID (GetParent (psai
->hSockAddr
));
272 psai
->hE1
= CreateWindow (
275 WS_CHILD
| WS_TABSTOP
| ES_RIGHT
| ES_NUMBER
| ES_MULTILINE
,
276 ptSockAddr
.x
, yy
, cxE1
, cy
,
277 GetParent(psai
->hSockAddr
),
282 psai
->hSep1
= CreateWindow (
285 WS_CHILD
| SS_CENTER
,
286 ptSockAddr
.x
+ cxE1
, yy
, sSockSep
.cx
, cy
,
287 GetParent(psai
->hSockAddr
),
292 psai
->idE2
= 1 + psai
->idE1
;
293 psai
->hE2
= CreateWindow (
296 WS_CHILD
| WS_TABSTOP
| ES_RIGHT
| ES_NUMBER
| ES_MULTILINE
,
297 ptSockAddr
.x
+ cxE1
+ sSockSep
.cx
, yy
, cxE2
, cy
,
298 GetParent(psai
->hSockAddr
),
303 psai
->hSep2
= CreateWindow (
306 WS_CHILD
| SS_CENTER
,
307 ptSockAddr
.x
+ cxE1
+ sSockSep
.cx
+ cxE2
, yy
, sSockSep
.cx
, cy
,
308 GetParent(psai
->hSockAddr
),
313 psai
->idE3
= 1 + psai
->idE2
;
314 psai
->hE3
= CreateWindow (
317 WS_CHILD
| WS_TABSTOP
| ES_RIGHT
| ES_NUMBER
| ES_MULTILINE
,
318 ptSockAddr
.x
+ cxE1
+ sSockSep
.cx
*2 + cxE2
, yy
, cxE2
, cy
,
319 GetParent(psai
->hSockAddr
),
324 psai
->hSep3
= CreateWindow (
327 WS_CHILD
| SS_CENTER
,
328 ptSockAddr
.x
+ cxE1
+ sSockSep
.cx
*2 + cxE2
*2, yy
, sSockSep
.cx
, cy
,
329 GetParent(psai
->hSockAddr
),
334 psai
->idE4
= 1 + psai
->idE3
;
335 psai
->hE4
= CreateWindow (
338 WS_CHILD
| WS_TABSTOP
| ES_RIGHT
| ES_NUMBER
| ES_MULTILINE
,
339 ptSockAddr
.x
+ cxE1
+ sSockSep
.cx
*3 + cxE2
*2, yy
, cxE2
, cy
,
340 GetParent(psai
->hSockAddr
),
345 Subclass_AddHook (psai
->hE1
, SockAddrEditProc
);
346 Subclass_AddHook (psai
->hE2
, SockAddrEditProc
);
347 Subclass_AddHook (psai
->hE3
, SockAddrEditProc
);
348 Subclass_AddHook (psai
->hE4
, SockAddrEditProc
);
350 HFONT hf
= (HFONT
)SendMessage (GetParent (psai
->hSockAddr
), WM_GETFONT
, 0, 0);
351 SendMessage (psai
->hE1
, WM_SETFONT
, (WPARAM
)hf
, MAKELPARAM(TRUE
,0));
352 SendMessage (psai
->hSep1
, WM_SETFONT
, (WPARAM
)hf
, MAKELPARAM(TRUE
,0));
353 SendMessage (psai
->hE2
, WM_SETFONT
, (WPARAM
)hf
, MAKELPARAM(TRUE
,0));
354 SendMessage (psai
->hSep2
, WM_SETFONT
, (WPARAM
)hf
, MAKELPARAM(TRUE
,0));
355 SendMessage (psai
->hE3
, WM_SETFONT
, (WPARAM
)hf
, MAKELPARAM(TRUE
,0));
356 SendMessage (psai
->hSep3
, WM_SETFONT
, (WPARAM
)hf
, MAKELPARAM(TRUE
,0));
357 SendMessage (psai
->hE4
, WM_SETFONT
, (WPARAM
)hf
, MAKELPARAM(TRUE
,0));
359 EnableWindow (psai
->hE1
, IsWindowEnabled (psai
->hSockAddr
));
360 EnableWindow (psai
->hSep1
, IsWindowEnabled (psai
->hSockAddr
));
361 EnableWindow (psai
->hE2
, IsWindowEnabled (psai
->hSockAddr
));
362 EnableWindow (psai
->hSep2
, IsWindowEnabled (psai
->hSockAddr
));
363 EnableWindow (psai
->hE3
, IsWindowEnabled (psai
->hSockAddr
));
364 EnableWindow (psai
->hSep3
, IsWindowEnabled (psai
->hSockAddr
));
365 EnableWindow (psai
->hE4
, IsWindowEnabled (psai
->hSockAddr
));
367 ShowWindow (psai
->hE1
, TRUE
);
368 ShowWindow (psai
->hSep1
, TRUE
);
369 ShowWindow (psai
->hE2
, TRUE
);
370 ShowWindow (psai
->hSep2
, TRUE
);
371 ShowWindow (psai
->hE3
, TRUE
);
372 ShowWindow (psai
->hSep3
, TRUE
);
373 ShowWindow (psai
->hE4
, TRUE
);
376 GetWindowRect (psai
->hSockAddr
, &rWindow
);
377 rWindow
.right
+= (cxE1
+ cxE2
*3 + sSockSep
.cx
*3) - cxRECT(rSockAddr
);
379 SetWindowPos (psai
->hSockAddr
, NULL
, 0, 0, cxRECT(rWindow
), cyRECT(rWindow
),
380 SWP_NOMOVE
| SWP_NOACTIVATE
| SWP_NOZORDER
);
383 memset (&addrNew
, 0x00, sizeof(addrNew
));
384 SockAddr_OnSetAddr (psai
, 0, (LPARAM
)&addrNew
);
388 void SockAddr_OnDestroy (SockAddrInfo
*psai
)
390 Subclass_RemoveHook (GetParent(psai
->hSockAddr
), SockAddrDlgProc
);
391 psai
->hSockAddr
= NULL
;
395 void SockAddr_OnButtonDown (SockAddrInfo
*psai
, UINT msg
, WPARAM wp
, LPARAM lp
)
397 DWORD dw
= GetMessagePos();
400 pt
.y
= HIWORD(dw
); // in screen coordinates
405 GetWindowRect (psai
->hE1
, &rTarget
);
406 if (PtInRect (&rTarget
, pt
))
409 GetWindowRect (psai
->hE2
, &rTarget
);
410 if (PtInRect (&rTarget
, pt
))
413 GetWindowRect (psai
->hE3
, &rTarget
);
414 if (PtInRect (&rTarget
, pt
))
417 GetWindowRect (psai
->hE4
, &rTarget
);
418 if (PtInRect (&rTarget
, pt
))
423 PostMessage (hTarget
, msg
, wp
, lp
);
428 BOOL
SockAddr_OnGetAddr (SockAddrInfo
*psai
, WPARAM wp
, LPARAM lp
)
430 SOCKADDR_IN
*pAddr
= (SOCKADDR_IN
*)lp
;
436 BOOL
SockAddr_OnSetAddr (SockAddrInfo
*psai
, WPARAM wp
, LPARAM lp
)
438 SOCKADDR_IN
*pAddr
= (SOCKADDR_IN
*)lp
;
440 SockAddr_Edit_SetText (psai
, psai
->hE1
);
441 SockAddr_Edit_SetText (psai
, psai
->hE2
);
442 SockAddr_Edit_SetText (psai
, psai
->hE3
);
443 SockAddr_Edit_SetText (psai
, psai
->hE4
);
448 HRESULT CALLBACK
SockAddrDlgProc (HWND hDlg
, UINT msg
, WPARAM wp
, LPARAM lp
)
450 PVOID oldProc
= Subclass_FindNextHook (hDlg
, SockAddrDlgProc
);
455 case WM_CTLCOLOREDIT
:
456 case WM_CTLCOLORSTATIC
:
457 for (iSockAddr
= 0; iSockAddr
< cSockAddr
; ++iSockAddr
)
459 if (aSockAddr
[ iSockAddr
].hSockAddr
== NULL
)
461 if ( (aSockAddr
[ iSockAddr
].hE1
== (HWND
)lp
) ||
462 (aSockAddr
[ iSockAddr
].hSep1
== (HWND
)lp
) ||
463 (aSockAddr
[ iSockAddr
].hE2
== (HWND
)lp
) ||
464 (aSockAddr
[ iSockAddr
].hSep2
== (HWND
)lp
) ||
465 (aSockAddr
[ iSockAddr
].hE3
== (HWND
)lp
) ||
466 (aSockAddr
[ iSockAddr
].hSep3
== (HWND
)lp
) ||
467 (aSockAddr
[ iSockAddr
].hE4
== (HWND
)lp
) )
470 if (IsWindowEnabled (aSockAddr
[ iSockAddr
].hSockAddr
))
471 clr
= GetSysColor (COLOR_WINDOW
);
473 clr
= GetSysColor (COLOR_BTNFACE
);
474 SetBkColor ((HDC
)wp
, clr
);
475 return (HRESULT
)(INT_PTR
)CreateSolidBrush (clr
);
481 for (iSockAddr
= 0; iSockAddr
< cSockAddr
; ++iSockAddr
)
483 if (aSockAddr
[ iSockAddr
].hSockAddr
== NULL
)
485 if ( (aSockAddr
[ iSockAddr
].idE1
== LOWORD(wp
)) ||
486 (aSockAddr
[ iSockAddr
].idE2
== LOWORD(wp
)) ||
487 (aSockAddr
[ iSockAddr
].idE3
== LOWORD(wp
)) ||
488 (aSockAddr
[ iSockAddr
].idE4
== LOWORD(wp
)) )
490 static BOOL fInHere
= FALSE
;
495 if (HIWORD(wp
) == EN_CHANGE
)
497 SockAddr_Edit_OnChange (&aSockAddr
[ iSockAddr
], GetDlgItem (hDlg
, LOWORD(wp
)));
499 else if (HIWORD(wp
) == EN_UPDATE
)
501 SockAddr_Edit_OnUpdate (&aSockAddr
[ iSockAddr
], GetDlgItem (hDlg
, LOWORD(wp
)));
513 return CallWindowProc ((WNDPROC
)oldProc
, hDlg
, msg
, wp
, lp
);
515 return DefWindowProc (hDlg
, msg
, wp
, lp
);
519 HRESULT CALLBACK
SockAddrEditProc (HWND hEdit
, UINT msg
, WPARAM wp
, LPARAM lp
)
521 SockAddrInfo
*psai
= NULL
;
523 EnterCriticalSection (&csSockAddr
);
525 for (size_t iSockAddr
= 0; !psai
&& iSockAddr
< cSockAddr
; ++iSockAddr
)
527 if ( (aSockAddr
[ iSockAddr
].hE1
== hEdit
) ||
528 (aSockAddr
[ iSockAddr
].hE2
== hEdit
) ||
529 (aSockAddr
[ iSockAddr
].hE3
== hEdit
) ||
530 (aSockAddr
[ iSockAddr
].hE4
== hEdit
) )
532 psai
= &aSockAddr
[ iSockAddr
];
536 LeaveCriticalSection (&csSockAddr
);
543 SockAddr_Edit_SetText (psai
, hEdit
);
549 // advance to the next field
550 PostMessage (GetParent(hEdit
), WM_NEXTDLGCTL
, 0, 0);
557 PVOID oldProc
= Subclass_FindNextHook (hEdit
, SockAddrEditProc
);
559 return CallWindowProc ((WNDPROC
)oldProc
, hEdit
, msg
, wp
, lp
);
561 return DefWindowProc (hEdit
, msg
, wp
, lp
);
565 void SockAddr_Edit_OnChange (SockAddrInfo
*psai
, HWND hEdit
)
567 TCHAR szText
[ cchRESOURCE
];
568 GetWindowText (hEdit
, szText
, cchRESOURCE
);
570 if ( (hEdit
!= psai
->hE1
) ||
571 (psai
->addr
.sin_addr
.s_net
) ||
572 (psai
->addr
.sin_addr
.s_host
) ||
573 (psai
->addr
.sin_addr
.s_lh
) ||
574 (psai
->addr
.sin_addr
.s_impno
) ||
575 (szText
[0] != TEXT('\0')) )
577 DWORD dwMin
= (hEdit
== psai
->hE1
) ? 1 : 0;
578 DWORD dwNow
= (DWORD
)atol(szText
);
579 DWORD dwMax
= (hEdit
== psai
->hE1
) ? 253 : 255;
581 dwNow
= limit (dwMin
, dwNow
, dwMax
);
583 if (hEdit
== psai
->hE1
)
584 psai
->addr
.sin_addr
.s_net
= (unsigned char)dwNow
;
585 else if (hEdit
== psai
->hE2
)
586 psai
->addr
.sin_addr
.s_host
= (unsigned char)dwNow
;
587 else if (hEdit
== psai
->hE3
)
588 psai
->addr
.sin_addr
.s_lh
= (unsigned char)dwNow
;
589 else if (hEdit
== psai
->hE4
)
590 psai
->addr
.sin_addr
.s_impno
= (unsigned char)dwNow
;
592 SOCKADDR_IN addrNew
= psai
->addr
;
593 SockAddr_SendCallback (psai
, SAN_CHANGE
, (LPARAM
)&addrNew
);
594 if (memcmp (&addrNew
, &psai
->addr
, sizeof(SOCKADDR_IN
)))
596 SockAddr_OnSetAddr (psai
, (WPARAM
)0, (LPARAM
)&addrNew
);
600 // SockAddr_Edit_SetText (psai, hEdit);
602 if ( (hEdit
== psai
->hE1
) &&
603 (psai
->addr
.sin_addr
.s_net
) &&
604 (!psai
->addr
.sin_addr
.s_host
) &&
605 (!psai
->addr
.sin_addr
.s_lh
) &&
606 (!psai
->addr
.sin_addr
.s_impno
) )
608 SockAddr_Edit_SetText (psai
, psai
->hE2
);
609 SockAddr_Edit_SetText (psai
, psai
->hE3
);
610 SockAddr_Edit_SetText (psai
, psai
->hE4
);
615 void SockAddr_Edit_OnUpdate (SockAddrInfo
*psai
, HWND hEdit
)
617 SOCKADDR_IN addrNew
= psai
->addr
;
618 SockAddr_SendCallback (psai
, SAN_UPDATE
, (LPARAM
)&addrNew
);
622 void SockAddr_Edit_SetText (SockAddrInfo
*psai
, HWND hEdit
)
626 if ( (!psai
->addr
.sin_addr
.s_net
) &&
627 (!psai
->addr
.sin_addr
.s_host
) &&
628 (!psai
->addr
.sin_addr
.s_lh
) &&
629 (!psai
->addr
.sin_addr
.s_impno
) )
631 SetWindowText (hEdit
, TEXT(""));
635 if (hEdit
== psai
->hE1
)
636 dwNow
= (DWORD
)psai
->addr
.sin_addr
.s_net
;
637 else if (hEdit
== psai
->hE2
)
638 dwNow
= (DWORD
)psai
->addr
.sin_addr
.s_host
;
639 else if (hEdit
== psai
->hE3
)
640 dwNow
= (DWORD
)psai
->addr
.sin_addr
.s_lh
;
641 else if (hEdit
== psai
->hE4
)
642 dwNow
= (DWORD
)psai
->addr
.sin_addr
.s_impno
;
644 TCHAR szText
[ cchRESOURCE
];
645 wsprintf (szText
, TEXT("%lu"), dwNow
);
646 SetWindowText (hEdit
, szText
);