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)
167 for (size_t iSockAddr = 0; iSockAddr < cSockAddr; ++iSockAddr)
169 if (aSockAddr[ iSockAddr ].hSockAddr == NULL)
172 if (iSockAddr >= cSockAddr)
174 if (!REALLOC (aSockAddr, cSockAddr, 1+iSockAddr, 4))
178 memset (&aSockAddr[ iSockAddr ], 0x00, sizeof(SockAddrInfo));
179 aSockAddr[ iSockAddr ].hSockAddr = hSockAddr;
181 psai = &aSockAddr[ iSockAddr ];
185 for (size_t iSockAddr = 0; !psai && iSockAddr < cSockAddr; ++iSockAddr)
187 if (aSockAddr[ iSockAddr ].hSockAddr == hSockAddr)
188 psai = &aSockAddr[ iSockAddr ];
192 LeaveCriticalSection (&csSockAddr);
199 SockAddr_OnCreate (psai);
203 SockAddr_OnDestroy (psai);
208 SockAddr_OnButtonDown (psai, msg, wp, lp);
212 PostMessage (GetParent(hSockAddr), WM_NEXTDLGCTL, (WPARAM)psai->hE1, TRUE);
216 EnableWindow (psai->hE1, IsWindowEnabled (hSockAddr));
217 EnableWindow (psai->hSep1, IsWindowEnabled (hSockAddr));
218 EnableWindow (psai->hE2, IsWindowEnabled (hSockAddr));
219 EnableWindow (psai->hSep2, IsWindowEnabled (hSockAddr));
220 EnableWindow (psai->hE3, IsWindowEnabled (hSockAddr));
221 EnableWindow (psai->hSep3, IsWindowEnabled (hSockAddr));
222 EnableWindow (psai->hE4, IsWindowEnabled (hSockAddr));
225 GetRectInParent (hSockAddr, &rSockAddr);
226 InvalidateRect (GetParent(hSockAddr), &rSockAddr, TRUE);
227 UpdateWindow (GetParent(hSockAddr));
231 return SockAddr_OnGetAddr (psai, wp, lp);
234 return SockAddr_OnSetAddr (psai, wp, lp);
238 return DefWindowProc (hSockAddr, msg, wp, lp);
242 void SockAddr_OnCreate (SockAddrInfo *psai)
244 Subclass_AddHook (GetParent(psai->hSockAddr), SockAddrDlgProc);
247 GetClientRect (psai->hSockAddr, &rSockAddr);
249 POINT ptSockAddr = {0,0};
250 ClientToScreen (psai->hSockAddr, &ptSockAddr);
251 ScreenToClient (GetParent (psai->hSockAddr), &ptSockAddr);
253 SIZE s888; // size of widest likely triple-digit number
254 SIZE sSockSep; // size of "."
256 HDC hdc = GetDC (GetParent (psai->hSockAddr));
257 GetTextExtentPoint (hdc, TEXT("888"), lstrlen(TEXT("888")), &s888);
258 GetTextExtentPoint (hdc, cszSOCKSEP, lstrlen(cszSOCKSEP), &sSockSep);
259 ReleaseDC (GetParent (psai->hSockAddr), hdc);
261 LONG cxNumbers = cxRECT(rSockAddr) - (3 * sSockSep.cx);
262 LONG cxE2 = cxNumbers/4;
263 LONG cxE1 = cxNumbers - cxE2 * 3;
264 LONG yy = ptSockAddr.y;
265 LONG cy = cyRECT(rSockAddr);
267 cxE2 = min (cxE2, (LONG)( 1.4 * s888.cx ));
268 cxE1 = min (cxE1, (LONG)( 1.4 * s888.cx )); // don't be TOO wide.
270 psai->idE1 = 100+NextControlID (GetParent (psai->hSockAddr));
271 psai->hE1 = CreateWindow (
274 WS_CHILD | WS_TABSTOP | ES_RIGHT | ES_NUMBER | ES_MULTILINE,
275 ptSockAddr.x, yy, cxE1, cy,
276 GetParent(psai->hSockAddr),
281 psai->hSep1 = CreateWindow (
284 WS_CHILD | SS_CENTER,
285 ptSockAddr.x + cxE1, yy, sSockSep.cx, cy,
286 GetParent(psai->hSockAddr),
291 psai->idE2 = 1 + psai->idE1;
292 psai->hE2 = CreateWindow (
295 WS_CHILD | WS_TABSTOP | ES_RIGHT | ES_NUMBER | ES_MULTILINE,
296 ptSockAddr.x + cxE1 + sSockSep.cx, yy, cxE2, cy,
297 GetParent(psai->hSockAddr),
302 psai->hSep2 = CreateWindow (
305 WS_CHILD | SS_CENTER,
306 ptSockAddr.x + cxE1 + sSockSep.cx + cxE2, yy, sSockSep.cx, cy,
307 GetParent(psai->hSockAddr),
312 psai->idE3 = 1 + psai->idE2;
313 psai->hE3 = CreateWindow (
316 WS_CHILD | WS_TABSTOP | ES_RIGHT | ES_NUMBER | ES_MULTILINE,
317 ptSockAddr.x + cxE1 + sSockSep.cx*2 + cxE2, yy, cxE2, cy,
318 GetParent(psai->hSockAddr),
323 psai->hSep3 = CreateWindow (
326 WS_CHILD | SS_CENTER,
327 ptSockAddr.x + cxE1 + sSockSep.cx*2 + cxE2*2, yy, sSockSep.cx, cy,
328 GetParent(psai->hSockAddr),
333 psai->idE4 = 1 + psai->idE3;
334 psai->hE4 = CreateWindow (
337 WS_CHILD | WS_TABSTOP | ES_RIGHT | ES_NUMBER | ES_MULTILINE,
338 ptSockAddr.x + cxE1 + sSockSep.cx*3 + cxE2*2, yy, cxE2, cy,
339 GetParent(psai->hSockAddr),
344 Subclass_AddHook (psai->hE1, SockAddrEditProc);
345 Subclass_AddHook (psai->hE2, SockAddrEditProc);
346 Subclass_AddHook (psai->hE3, SockAddrEditProc);
347 Subclass_AddHook (psai->hE4, SockAddrEditProc);
349 HFONT hf = (HFONT)SendMessage (GetParent (psai->hSockAddr), WM_GETFONT, 0, 0);
350 SendMessage (psai->hE1, WM_SETFONT, (WPARAM)hf, MAKELPARAM(TRUE,0));
351 SendMessage (psai->hSep1, WM_SETFONT, (WPARAM)hf, MAKELPARAM(TRUE,0));
352 SendMessage (psai->hE2, WM_SETFONT, (WPARAM)hf, MAKELPARAM(TRUE,0));
353 SendMessage (psai->hSep2, WM_SETFONT, (WPARAM)hf, MAKELPARAM(TRUE,0));
354 SendMessage (psai->hE3, WM_SETFONT, (WPARAM)hf, MAKELPARAM(TRUE,0));
355 SendMessage (psai->hSep3, WM_SETFONT, (WPARAM)hf, MAKELPARAM(TRUE,0));
356 SendMessage (psai->hE4, WM_SETFONT, (WPARAM)hf, MAKELPARAM(TRUE,0));
358 EnableWindow (psai->hE1, IsWindowEnabled (psai->hSockAddr));
359 EnableWindow (psai->hSep1, IsWindowEnabled (psai->hSockAddr));
360 EnableWindow (psai->hE2, IsWindowEnabled (psai->hSockAddr));
361 EnableWindow (psai->hSep2, IsWindowEnabled (psai->hSockAddr));
362 EnableWindow (psai->hE3, IsWindowEnabled (psai->hSockAddr));
363 EnableWindow (psai->hSep3, IsWindowEnabled (psai->hSockAddr));
364 EnableWindow (psai->hE4, IsWindowEnabled (psai->hSockAddr));
366 ShowWindow (psai->hE1, TRUE);
367 ShowWindow (psai->hSep1, TRUE);
368 ShowWindow (psai->hE2, TRUE);
369 ShowWindow (psai->hSep2, TRUE);
370 ShowWindow (psai->hE3, TRUE);
371 ShowWindow (psai->hSep3, TRUE);
372 ShowWindow (psai->hE4, TRUE);
375 GetWindowRect (psai->hSockAddr, &rWindow);
376 rWindow.right += (cxE1 + cxE2*3 + sSockSep.cx*3) - cxRECT(rSockAddr);
378 SetWindowPos (psai->hSockAddr, NULL, 0, 0, cxRECT(rWindow), cyRECT(rWindow),
379 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
382 memset (&addrNew, 0x00, sizeof(addrNew));
383 SockAddr_OnSetAddr (psai, 0, (LPARAM)&addrNew);
387 void SockAddr_OnDestroy (SockAddrInfo *psai)
389 Subclass_RemoveHook (GetParent(psai->hSockAddr), SockAddrDlgProc);
390 psai->hSockAddr = NULL;
394 void SockAddr_OnButtonDown (SockAddrInfo *psai, UINT msg, WPARAM wp, LPARAM lp)
396 DWORD dw = GetMessagePos();
399 pt.y = HIWORD(dw); // in screen coordinates
404 GetWindowRect (psai->hE1, &rTarget);
405 if (PtInRect (&rTarget, pt))
408 GetWindowRect (psai->hE2, &rTarget);
409 if (PtInRect (&rTarget, pt))
412 GetWindowRect (psai->hE3, &rTarget);
413 if (PtInRect (&rTarget, pt))
416 GetWindowRect (psai->hE4, &rTarget);
417 if (PtInRect (&rTarget, pt))
422 PostMessage (hTarget, msg, wp, lp);
427 BOOL SockAddr_OnGetAddr (SockAddrInfo *psai, WPARAM wp, LPARAM lp)
429 SOCKADDR_IN *pAddr = (SOCKADDR_IN*)lp;
435 BOOL SockAddr_OnSetAddr (SockAddrInfo *psai, WPARAM wp, LPARAM lp)
437 SOCKADDR_IN *pAddr = (SOCKADDR_IN*)lp;
439 SockAddr_Edit_SetText (psai, psai->hE1);
440 SockAddr_Edit_SetText (psai, psai->hE2);
441 SockAddr_Edit_SetText (psai, psai->hE3);
442 SockAddr_Edit_SetText (psai, psai->hE4);
447 BOOL CALLBACK SockAddrDlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
449 PVOID oldProc = Subclass_FindNextHook (hDlg, SockAddrDlgProc);
454 case WM_CTLCOLOREDIT:
455 case WM_CTLCOLORSTATIC:
456 for (iSockAddr = 0; iSockAddr < cSockAddr; ++iSockAddr)
458 if (aSockAddr[ iSockAddr ].hSockAddr == NULL)
460 if ( (aSockAddr[ iSockAddr ].hE1 == (HWND)lp) ||
461 (aSockAddr[ iSockAddr ].hSep1 == (HWND)lp) ||
462 (aSockAddr[ iSockAddr ].hE2 == (HWND)lp) ||
463 (aSockAddr[ iSockAddr ].hSep2 == (HWND)lp) ||
464 (aSockAddr[ iSockAddr ].hE3 == (HWND)lp) ||
465 (aSockAddr[ iSockAddr ].hSep3 == (HWND)lp) ||
466 (aSockAddr[ iSockAddr ].hE4 == (HWND)lp) )
469 if (IsWindowEnabled (aSockAddr[ iSockAddr ].hSockAddr))
470 clr = GetSysColor (COLOR_WINDOW);
472 clr = GetSysColor (COLOR_BTNFACE);
473 SetBkColor ((HDC)wp, clr);
474 return (BOOL)CreateSolidBrush (clr);
480 for (iSockAddr = 0; iSockAddr < cSockAddr; ++iSockAddr)
482 if (aSockAddr[ iSockAddr ].hSockAddr == NULL)
484 if ( (aSockAddr[ iSockAddr ].idE1 == LOWORD(wp)) ||
485 (aSockAddr[ iSockAddr ].idE2 == LOWORD(wp)) ||
486 (aSockAddr[ iSockAddr ].idE3 == LOWORD(wp)) ||
487 (aSockAddr[ iSockAddr ].idE4 == LOWORD(wp)) )
489 static BOOL fInHere = FALSE;
494 if (HIWORD(wp) == EN_CHANGE)
496 SockAddr_Edit_OnChange (&aSockAddr[ iSockAddr ], GetDlgItem (hDlg, LOWORD(wp)));
498 else if (HIWORD(wp) == EN_UPDATE)
500 SockAddr_Edit_OnUpdate (&aSockAddr[ iSockAddr ], GetDlgItem (hDlg, LOWORD(wp)));
512 return CallWindowProc ((WNDPROC)oldProc, hDlg, msg, wp, lp);
514 return DefWindowProc (hDlg, msg, wp, lp);
518 BOOL CALLBACK SockAddrEditProc (HWND hEdit, UINT msg, WPARAM wp, LPARAM lp)
520 SockAddrInfo *psai = NULL;
522 EnterCriticalSection (&csSockAddr);
524 for (size_t iSockAddr = 0; !psai && iSockAddr < cSockAddr; ++iSockAddr)
526 if ( (aSockAddr[ iSockAddr ].hE1 == hEdit) ||
527 (aSockAddr[ iSockAddr ].hE2 == hEdit) ||
528 (aSockAddr[ iSockAddr ].hE3 == hEdit) ||
529 (aSockAddr[ iSockAddr ].hE4 == hEdit) )
531 psai = &aSockAddr[ iSockAddr ];
535 LeaveCriticalSection (&csSockAddr);
542 SockAddr_Edit_SetText (psai, hEdit);
548 // advance to the next field
549 PostMessage (GetParent(hEdit), WM_NEXTDLGCTL, 0, 0);
556 PVOID oldProc = Subclass_FindNextHook (hEdit, SockAddrEditProc);
558 return CallWindowProc ((WNDPROC)oldProc, hEdit, msg, wp, lp);
560 return DefWindowProc (hEdit, msg, wp, lp);
564 void SockAddr_Edit_OnChange (SockAddrInfo *psai, HWND hEdit)
566 TCHAR szText[ cchRESOURCE ];
567 GetWindowText (hEdit, szText, cchRESOURCE);
569 if ( (hEdit != psai->hE1) ||
570 (psai->addr.sin_addr.s_net) ||
571 (psai->addr.sin_addr.s_host) ||
572 (psai->addr.sin_addr.s_lh) ||
573 (psai->addr.sin_addr.s_impno) ||
574 (szText[0] != TEXT('\0')) )
576 DWORD dwMin = (hEdit == psai->hE1) ? 1 : 0;
577 DWORD dwNow = (DWORD)atol(szText);
578 DWORD dwMax = (hEdit == psai->hE1) ? 253 : 255;
580 dwNow = limit (dwMin, dwNow, dwMax);
582 if (hEdit == psai->hE1)
583 psai->addr.sin_addr.s_net = (unsigned char)dwNow;
584 else if (hEdit == psai->hE2)
585 psai->addr.sin_addr.s_host = (unsigned char)dwNow;
586 else if (hEdit == psai->hE3)
587 psai->addr.sin_addr.s_lh = (unsigned char)dwNow;
588 else if (hEdit == psai->hE4)
589 psai->addr.sin_addr.s_impno = (unsigned char)dwNow;
591 SOCKADDR_IN addrNew = psai->addr;
592 SockAddr_SendCallback (psai, SAN_CHANGE, (LPARAM)&addrNew);
593 if (memcmp (&addrNew, &psai->addr, sizeof(SOCKADDR_IN)))
595 SockAddr_OnSetAddr (psai, (WPARAM)0, (LPARAM)&addrNew);
599 // SockAddr_Edit_SetText (psai, hEdit);
601 if ( (hEdit == psai->hE1) &&
602 (psai->addr.sin_addr.s_net) &&
603 (!psai->addr.sin_addr.s_host) &&
604 (!psai->addr.sin_addr.s_lh) &&
605 (!psai->addr.sin_addr.s_impno) )
607 SockAddr_Edit_SetText (psai, psai->hE2);
608 SockAddr_Edit_SetText (psai, psai->hE3);
609 SockAddr_Edit_SetText (psai, psai->hE4);
614 void SockAddr_Edit_OnUpdate (SockAddrInfo *psai, HWND hEdit)
616 SOCKADDR_IN addrNew = psai->addr;
617 SockAddr_SendCallback (psai, SAN_UPDATE, (LPARAM)&addrNew);
621 void SockAddr_Edit_SetText (SockAddrInfo *psai, HWND hEdit)
625 if ( (!psai->addr.sin_addr.s_net) &&
626 (!psai->addr.sin_addr.s_host) &&
627 (!psai->addr.sin_addr.s_lh) &&
628 (!psai->addr.sin_addr.s_impno) )
630 SetWindowText (hEdit, TEXT(""));
634 if (hEdit == psai->hE1)
635 dwNow = (DWORD)psai->addr.sin_addr.s_net;
636 else if (hEdit == psai->hE2)
637 dwNow = (DWORD)psai->addr.sin_addr.s_host;
638 else if (hEdit == psai->hE3)
639 dwNow = (DWORD)psai->addr.sin_addr.s_lh;
640 else if (hEdit == psai->hE4)
641 dwNow = (DWORD)psai->addr.sin_addr.s_impno;
643 TCHAR szText[ cchRESOURCE ];
644 wsprintf (szText, TEXT("%lu"), dwNow);
645 SetWindowText (hEdit, szText);