Fix some of the things that break compilation on Windows.
[openafs.git] / src / WINNT / afsapplib / ctl_sockaddr.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 <windowsx.h>
17 #include <commctrl.h>
18 #include <winsock2.h>
19 #include <stdlib.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>
26
27 #ifndef cchRESOURCE
28 #define cchRESOURCE 256
29 #endif
30
31
32 /*
33  * MISCELLANEOUS ______________________________________________________________
34  *
35  */
36
37 #ifndef REALLOC
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)
40 {
41    LPVOID pNew;
42    size_t cNew;
43
44    if (cReq <= *pcTarget)
45       return TRUE;
46
47    if ((cNew = cInc * ((cReq + cInc-1) / cInc)) <= 0)
48       return FALSE;
49
50    if ((pNew = (LPVOID)Allocate (cbElement * cNew)) == NULL)
51       return FALSE;
52    memset (pNew, 0x00, cbElement * cNew);
53
54    if (*pcTarget != 0)
55       {
56       memcpy (pNew, *ppTarget, cbElement * (*pcTarget));
57       Free (*ppTarget);
58       }
59
60    *ppTarget = pNew;
61    *pcTarget = cNew;
62    return TRUE;
63 }
64 #endif
65
66
67 /*
68  * SOCKADDRS __________________________________________________________________
69  *
70  */
71
72 typedef struct
73    {
74    HWND hSockAddr;
75    HWND hE1;
76    HWND hSep1;
77    HWND hE2;
78    HWND hSep2;
79    HWND hE3;
80    HWND hSep3;
81    HWND hE4;
82    HWND hMinutes;
83
84    WORD idE1;
85    WORD idE2;
86    WORD idE3;
87    WORD idE4;
88
89    SOCKADDR_IN addr;
90
91    BOOL  fCallingBack;
92    } SockAddrInfo;
93
94 static CRITICAL_SECTION  csSockAddr;
95 static SockAddrInfo     *aSockAddr = NULL;
96 static size_t            cSockAddr = 0;
97
98 #define cszSOCKADDRCLASS TEXT("SockAddr")
99
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);
103
104 void SockAddr_SendCallback (SockAddrInfo *psai, WORD eln, LPARAM lp);
105
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);
111
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);
115
116 #define cszSOCKSEP TEXT(".")
117
118 BOOL RegisterSockAddrClass (void)
119 {
120    static BOOL fRegistered = FALSE;
121
122    if (!fRegistered)
123       {
124       InitializeCriticalSection (&csSockAddr);
125
126       WNDCLASS wc;
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;
134
135       if (RegisterClass (&wc))
136          fRegistered = TRUE;
137       }
138
139    return fRegistered;
140 }
141
142
143 void SockAddr_SendCallback (SockAddrInfo *psai, WORD san, LPARAM lp)
144 {
145    if (!psai->fCallingBack)
146       {
147       psai->fCallingBack = TRUE;
148
149       SendMessage (GetParent (psai->hSockAddr),
150                    WM_COMMAND,
151                    MAKELONG ((WORD)GetWindowLong (psai->hSockAddr, GWL_ID), san),
152                    lp);
153
154       psai->fCallingBack = FALSE;
155       }
156 }
157
158
159 BOOL CALLBACK SockAddrProc (HWND hSockAddr, UINT msg, WPARAM wp, LPARAM lp)
160 {
161    SockAddrInfo *psai = NULL;
162
163    EnterCriticalSection (&csSockAddr);
164
165    if (msg == WM_CREATE)
166       {
167       for (size_t iSockAddr = 0; iSockAddr < cSockAddr; ++iSockAddr)
168          {
169          if (aSockAddr[ iSockAddr ].hSockAddr == NULL)
170             break;
171          }
172       if (iSockAddr >= cSockAddr)
173          {
174          if (!REALLOC (aSockAddr, cSockAddr, 1+iSockAddr, 4))
175             return FALSE;
176          }
177
178       memset (&aSockAddr[ iSockAddr ], 0x00, sizeof(SockAddrInfo));
179       aSockAddr[ iSockAddr ].hSockAddr = hSockAddr;
180
181       psai = &aSockAddr[ iSockAddr ];
182       }
183    else
184       {
185       for (size_t iSockAddr = 0; !psai && iSockAddr < cSockAddr; ++iSockAddr)
186          {
187          if (aSockAddr[ iSockAddr ].hSockAddr == hSockAddr)
188             psai = &aSockAddr[ iSockAddr ];
189          }
190       }
191
192    LeaveCriticalSection (&csSockAddr);
193
194    if (psai != NULL)
195       {
196       switch (msg)
197          {
198          case WM_CREATE:
199             SockAddr_OnCreate (psai);
200             break;
201
202          case WM_DESTROY:
203             SockAddr_OnDestroy (psai);
204             break;
205
206          case WM_RBUTTONDOWN:
207          case WM_LBUTTONDOWN:
208             SockAddr_OnButtonDown (psai, msg, wp, lp);
209             break;
210
211          case WM_SETFOCUS:
212             PostMessage (GetParent(hSockAddr), WM_NEXTDLGCTL, (WPARAM)psai->hE1, TRUE);
213             break;
214
215          case WM_ENABLE:
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));
223
224             RECT rSockAddr;
225             GetRectInParent (hSockAddr, &rSockAddr);
226             InvalidateRect (GetParent(hSockAddr), &rSockAddr, TRUE);
227             UpdateWindow (GetParent(hSockAddr));
228             break;
229
230          case SAM_GETADDR:
231             return SockAddr_OnGetAddr (psai, wp, lp);
232
233          case SAM_SETADDR:
234             return SockAddr_OnSetAddr (psai, wp, lp);
235          }
236       }
237
238    return DefWindowProc (hSockAddr, msg, wp, lp);
239 }
240
241
242 void SockAddr_OnCreate (SockAddrInfo *psai)
243 {
244    Subclass_AddHook (GetParent(psai->hSockAddr), SockAddrDlgProc);
245
246    RECT rSockAddr;
247    GetClientRect (psai->hSockAddr, &rSockAddr);
248
249    POINT ptSockAddr = {0,0};
250    ClientToScreen (psai->hSockAddr, &ptSockAddr);
251    ScreenToClient (GetParent (psai->hSockAddr), &ptSockAddr);
252
253    SIZE s888; // size of widest likely triple-digit number
254    SIZE sSockSep; // size of "."
255
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);
260
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);
266
267    cxE2 = min (cxE2, (LONG)( 1.4 * s888.cx ));
268    cxE1 = min (cxE1, (LONG)( 1.4 * s888.cx ));  // don't be TOO wide.
269
270    psai->idE1 = 100+NextControlID (GetParent (psai->hSockAddr));
271    psai->hE1 = CreateWindow (
272                 TEXT("EDIT"),
273                 TEXT(""),
274                 WS_CHILD | WS_TABSTOP | ES_RIGHT | ES_NUMBER | ES_MULTILINE,
275                 ptSockAddr.x, yy, cxE1, cy,
276                 GetParent(psai->hSockAddr),
277                 (HMENU)psai->idE1,
278                 THIS_HINST,
279                 0);
280
281    psai->hSep1 = CreateWindow (
282                 TEXT("STATIC"),
283                 cszSOCKSEP,
284                 WS_CHILD | SS_CENTER,
285                 ptSockAddr.x + cxE1, yy, sSockSep.cx, cy,
286                 GetParent(psai->hSockAddr),
287                 (HMENU)-1,
288                 THIS_HINST,
289                 0);
290
291    psai->idE2 = 1 + psai->idE1;
292    psai->hE2 = CreateWindow (
293                 TEXT("EDIT"),
294                 TEXT(""),
295                 WS_CHILD | WS_TABSTOP | ES_RIGHT | ES_NUMBER | ES_MULTILINE,
296                 ptSockAddr.x + cxE1 + sSockSep.cx, yy, cxE2, cy,
297                 GetParent(psai->hSockAddr),
298                 (HMENU)psai->idE2,
299                 THIS_HINST,
300                 0);
301
302    psai->hSep2 = CreateWindow (
303                 TEXT("STATIC"),
304                 cszSOCKSEP,
305                 WS_CHILD | SS_CENTER,
306                 ptSockAddr.x + cxE1 + sSockSep.cx + cxE2, yy, sSockSep.cx, cy,
307                 GetParent(psai->hSockAddr),
308                 (HMENU)-1,
309                 THIS_HINST,
310                 0);
311
312    psai->idE3 = 1 + psai->idE2;
313    psai->hE3 = CreateWindow (
314                 TEXT("EDIT"),
315                 TEXT(""),
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),
319                 (HMENU)psai->idE3,
320                 THIS_HINST,
321                 0);
322
323    psai->hSep3 = CreateWindow (
324                 TEXT("STATIC"),
325                 cszSOCKSEP,
326                 WS_CHILD | SS_CENTER,
327                 ptSockAddr.x + cxE1 + sSockSep.cx*2 + cxE2*2, yy, sSockSep.cx, cy,
328                 GetParent(psai->hSockAddr),
329                 (HMENU)-1,
330                 THIS_HINST,
331                 0);
332
333    psai->idE4 = 1 + psai->idE3;
334    psai->hE4 = CreateWindow (
335                 TEXT("EDIT"),
336                 TEXT(""),
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),
340                 (HMENU)psai->idE4,
341                 THIS_HINST,
342                 0);
343
344    Subclass_AddHook (psai->hE1, SockAddrEditProc);
345    Subclass_AddHook (psai->hE2, SockAddrEditProc);
346    Subclass_AddHook (psai->hE3, SockAddrEditProc);
347    Subclass_AddHook (psai->hE4, SockAddrEditProc);
348
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));
357
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));
365
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);
373
374    RECT rWindow;
375    GetWindowRect (psai->hSockAddr, &rWindow);
376    rWindow.right += (cxE1 + cxE2*3 + sSockSep.cx*3) - cxRECT(rSockAddr);
377
378    SetWindowPos (psai->hSockAddr, NULL, 0, 0, cxRECT(rWindow), cyRECT(rWindow),
379                  SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
380
381    SOCKADDR_IN addrNew;
382    memset (&addrNew, 0x00, sizeof(addrNew));
383    SockAddr_OnSetAddr (psai, 0, (LPARAM)&addrNew);
384 }
385
386
387 void SockAddr_OnDestroy (SockAddrInfo *psai)
388 {
389    Subclass_RemoveHook (GetParent(psai->hSockAddr), SockAddrDlgProc);
390    psai->hSockAddr = NULL;
391 }
392
393
394 void SockAddr_OnButtonDown (SockAddrInfo *psai, UINT msg, WPARAM wp, LPARAM lp)
395 {
396    DWORD dw = GetMessagePos();
397    POINT pt;
398    pt.x = LOWORD(dw);
399    pt.y = HIWORD(dw);  // in screen coordinates
400
401    RECT rTarget;
402    HWND hTarget = 0;
403
404    GetWindowRect (psai->hE1, &rTarget);
405    if (PtInRect (&rTarget, pt))
406       hTarget = psai->hE1;
407
408    GetWindowRect (psai->hE2, &rTarget);
409    if (PtInRect (&rTarget, pt))
410       hTarget = psai->hE2;
411
412    GetWindowRect (psai->hE3, &rTarget);
413    if (PtInRect (&rTarget, pt))
414       hTarget = psai->hE3;
415
416    GetWindowRect (psai->hE4, &rTarget);
417    if (PtInRect (&rTarget, pt))
418       hTarget = psai->hE4;
419
420    if (hTarget != 0)
421       {
422       PostMessage (hTarget, msg, wp, lp);
423       }
424 }
425
426
427 BOOL SockAddr_OnGetAddr (SockAddrInfo *psai, WPARAM wp, LPARAM lp)
428 {
429    SOCKADDR_IN *pAddr = (SOCKADDR_IN*)lp;
430    *pAddr = psai->addr;
431    return TRUE;
432 }
433
434
435 BOOL SockAddr_OnSetAddr (SockAddrInfo *psai, WPARAM wp, LPARAM lp)
436 {
437    SOCKADDR_IN *pAddr = (SOCKADDR_IN*)lp;
438    psai->addr = *pAddr;
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);
443    return TRUE;
444 }
445
446
447 BOOL CALLBACK SockAddrDlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
448 {
449    PVOID oldProc = Subclass_FindNextHook (hDlg, SockAddrDlgProc);
450    size_t iSockAddr;
451
452    switch (msg)
453       {
454       case WM_CTLCOLOREDIT:
455       case WM_CTLCOLORSTATIC:
456          for (iSockAddr = 0; iSockAddr < cSockAddr; ++iSockAddr)
457             {
458             if (aSockAddr[ iSockAddr ].hSockAddr == NULL)
459                continue;
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) )
467                {
468                COLORREF clr;
469                if (IsWindowEnabled (aSockAddr[ iSockAddr ].hSockAddr))
470                   clr = GetSysColor (COLOR_WINDOW);
471                else
472                   clr = GetSysColor (COLOR_BTNFACE);
473                SetBkColor ((HDC)wp, clr);
474                return (BOOL)CreateSolidBrush (clr);
475                }
476             }
477          break;
478
479       case WM_COMMAND:
480          for (iSockAddr = 0; iSockAddr < cSockAddr; ++iSockAddr)
481             {
482             if (aSockAddr[ iSockAddr ].hSockAddr == NULL)
483                continue;
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)) )
488                {
489                static BOOL fInHere = FALSE;
490                if (!fInHere)
491                   {
492                   fInHere = TRUE;
493
494                   if (HIWORD(wp) == EN_CHANGE)
495                      {
496                      SockAddr_Edit_OnChange (&aSockAddr[ iSockAddr ], GetDlgItem (hDlg, LOWORD(wp)));
497                      }
498                   else if (HIWORD(wp) == EN_UPDATE)
499                      {
500                      SockAddr_Edit_OnUpdate (&aSockAddr[ iSockAddr ], GetDlgItem (hDlg, LOWORD(wp)));
501                      }
502
503                   fInHere = FALSE;
504                   }
505                break;
506                }
507             }
508          break;
509       }
510
511    if (oldProc)
512       return CallWindowProc ((WNDPROC)oldProc, hDlg, msg, wp, lp);
513    else
514       return DefWindowProc (hDlg, msg, wp, lp);
515 }
516
517
518 BOOL CALLBACK SockAddrEditProc (HWND hEdit, UINT msg, WPARAM wp, LPARAM lp)
519 {
520    SockAddrInfo *psai = NULL;
521
522    EnterCriticalSection (&csSockAddr);
523
524    for (size_t iSockAddr = 0; !psai && iSockAddr < cSockAddr; ++iSockAddr)
525       {
526       if ( (aSockAddr[ iSockAddr ].hE1 == hEdit) ||
527            (aSockAddr[ iSockAddr ].hE2 == hEdit) ||
528            (aSockAddr[ iSockAddr ].hE3 == hEdit) ||
529            (aSockAddr[ iSockAddr ].hE4 == hEdit) )
530          {
531          psai = &aSockAddr[ iSockAddr ];
532          }
533       }
534
535    LeaveCriticalSection (&csSockAddr);
536
537    if (psai)
538       {
539       switch (msg)
540          {
541          case WM_KILLFOCUS:
542             SockAddr_Edit_SetText (psai, hEdit);
543             break;
544
545          case WM_CHAR:
546             if (wp == TEXT('.'))
547                {
548                // advance to the next field
549                PostMessage (GetParent(hEdit), WM_NEXTDLGCTL, 0, 0);
550                return FALSE;
551                }
552             break;
553          }
554       }
555
556    PVOID oldProc = Subclass_FindNextHook (hEdit, SockAddrEditProc);
557    if (oldProc)
558       return CallWindowProc ((WNDPROC)oldProc, hEdit, msg, wp, lp);
559    else
560       return DefWindowProc (hEdit, msg, wp, lp);
561 }
562
563
564 void SockAddr_Edit_OnChange (SockAddrInfo *psai, HWND hEdit)
565 {
566    TCHAR szText[ cchRESOURCE ];
567    GetWindowText (hEdit, szText, cchRESOURCE);
568
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')) )
575       {
576       DWORD dwMin = (hEdit == psai->hE1) ? 1 : 0;
577       DWORD dwNow = (DWORD)atol(szText);
578       DWORD dwMax = (hEdit == psai->hE1) ? 253 : 255;
579
580       dwNow = limit (dwMin, dwNow, dwMax);
581
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;
590
591       SOCKADDR_IN addrNew = psai->addr;
592       SockAddr_SendCallback (psai, SAN_CHANGE, (LPARAM)&addrNew);
593       if (memcmp (&addrNew, &psai->addr, sizeof(SOCKADDR_IN)))
594          {
595          SockAddr_OnSetAddr (psai, (WPARAM)0, (LPARAM)&addrNew);
596          }
597       }
598
599 // SockAddr_Edit_SetText (psai, hEdit);
600
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) )
606       {
607       SockAddr_Edit_SetText (psai, psai->hE2);
608       SockAddr_Edit_SetText (psai, psai->hE3);
609       SockAddr_Edit_SetText (psai, psai->hE4);
610       }
611 }
612
613
614 void SockAddr_Edit_OnUpdate (SockAddrInfo *psai, HWND hEdit)
615 {
616    SOCKADDR_IN addrNew = psai->addr;
617    SockAddr_SendCallback (psai, SAN_UPDATE, (LPARAM)&addrNew);
618 }
619
620
621 void SockAddr_Edit_SetText (SockAddrInfo *psai, HWND hEdit)
622 {
623    DWORD dwNow;
624
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) )
629       {
630       SetWindowText (hEdit, TEXT(""));
631       }
632    else
633       {
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;
642
643       TCHAR szText[ cchRESOURCE ];
644       wsprintf (szText, TEXT("%lu"), dwNow);
645       SetWindowText (hEdit, szText);
646       }
647 }
648