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 BOOL CALLBACK SockAddrProc (HWND hSockAddr, UINT msg, WPARAM wp, LPARAM lp);
101 BOOL CALLBACK SockAddrEditProc (HWND hEdit, UINT msg, WPARAM wp, LPARAM lp);
102 BOOL 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 BOOL 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 BOOL 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 (BOOL)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 BOOL 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);