Added preferences to dinput drivers (so we can have two joystick
[wine] / dlls / comctl32 / ipaddress.c
1 /*
2  * IP Address control
3  *
4  * Copyright 1999 Chris Morgan<cmorgan@wpi.edu> and
5  *                James Abbatiello<abbeyj@wpi.edu>
6  * Copyright 1998, 1999 Eric Kohl
7  * Copyright 1998 Alex Priem <alexp@sci.kun.nl>
8  *
9  * NOTES
10  *
11  * TODO:
12  *    -Edit control doesn't support the ES_CENTER style which prevents
13  *     this ipaddress control from having centered text look like the
14  *     windows ipaddress control
15  *    -Check all notifications/behavior.
16  *    -Optimization: 
17  *        -include lpipsi in IPADDRESS_INFO.
18  *        -CurrentFocus: field that has focus at moment of processing.
19  *        -connect Rect32 rcClient.
20  *        -check ipaddress.cpp for missing features.
21  *    -refresh: draw '.' instead of setpixel.
22  */
23
24 #include <ctype.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27
28 #include "winbase.h"
29 #include "commctrl.h"
30 #include "heap.h"
31 #include "debugtools.h"
32
33 DEFAULT_DEBUG_CHANNEL(ipaddress);
34
35 typedef struct
36 {
37         BYTE LowerLimit[4];
38         BYTE UpperLimit[4];
39
40         RECT    rcClient;
41         INT     uFocus;
42 } IPADDRESS_INFO;
43
44 typedef struct
45 {
46     WNDPROC wpOrigProc[4];
47     HWND    hwndIP[4];
48     IPADDRESS_INFO *infoPtr;
49     HWND    hwnd;
50     UINT    uRefCount;
51 } IP_SUBCLASS_INFO, *LPIP_SUBCLASS_INFO;
52
53 #define IPADDRESS_GetInfoPtr(hwnd) ((IPADDRESS_INFO *)GetWindowLongA (hwnd, 0))
54
55 static BOOL 
56 IPADDRESS_SendNotify (HWND hwnd, UINT command);
57 static BOOL 
58 IPADDRESS_SendIPAddressNotify (HWND hwnd, UINT field, BYTE newValue);
59
60 /* property name of tooltip window handle */
61 #define IP_SUBCLASS_PROP "CCIP32SubclassInfo"
62
63
64 static LRESULT CALLBACK
65 IPADDRESS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
66
67
68 static VOID
69 IPADDRESS_Refresh (HWND hwnd, HDC hdc)
70 {
71   RECT rcClient;
72   HBRUSH hbr;
73   COLORREF clr=GetSysColor (COLOR_3DDKSHADOW);
74   int i,x,fieldsize;
75
76   GetClientRect (hwnd, &rcClient);
77   hbr = CreateSolidBrush (RGB(255,255,255));
78   DrawEdge (hdc, &rcClient, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
79   FillRect (hdc, &rcClient, hbr);
80   DeleteObject (hbr);
81
82   x=rcClient.left;
83   fieldsize=(rcClient.right-rcClient.left) / 4;
84
85   for (i=0; i<3; i++) {         /* Should draw text "." here */
86     x+=fieldsize;
87     SetPixel (hdc, x,   13, clr);
88     SetPixel (hdc, x,   14, clr);
89     SetPixel (hdc, x+1, 13, clr);
90     SetPixel (hdc, x+1, 14, clr);
91   }
92 }
93
94
95 static LRESULT
96 IPADDRESS_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
97 {
98   IPADDRESS_INFO *infoPtr;
99   RECT rcClient, edit;
100   int i,fieldsize;
101   LPIP_SUBCLASS_INFO lpipsi;
102         
103
104   infoPtr = (IPADDRESS_INFO *)COMCTL32_Alloc (sizeof(IPADDRESS_INFO));
105   SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
106
107   GetClientRect (hwnd, &rcClient);
108
109   fieldsize=(rcClient.right-rcClient.left) /4;
110
111   edit.top   =rcClient.top+2;
112   edit.bottom=rcClient.bottom-2;
113
114   lpipsi=(LPIP_SUBCLASS_INFO) GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
115   if (lpipsi == NULL)  {
116     lpipsi = (LPIP_SUBCLASS_INFO) COMCTL32_Alloc (sizeof(IP_SUBCLASS_INFO));
117     lpipsi->hwnd = hwnd;
118     lpipsi->uRefCount++;
119     SetPropA ((HWND)hwnd, IP_SUBCLASS_PROP, (HANDLE)lpipsi);
120 /*              infoPtr->lpipsi= lpipsi; */
121   } else 
122     WARN("IP-create called twice\n");
123         
124   for (i=0; i<=3; i++)
125   {
126     infoPtr->LowerLimit[i]=0;
127     infoPtr->UpperLimit[i]=255;
128     edit.left=rcClient.left+i*fieldsize+6;
129     edit.right=rcClient.left+(i+1)*fieldsize-2;
130     lpipsi->hwndIP[i]= CreateWindowA ("edit", NULL, 
131         WS_CHILD | WS_VISIBLE | ES_CENTER,
132         edit.left, edit.top, edit.right-edit.left, edit.bottom-edit.top,
133         hwnd, (HMENU) 1, GetWindowLongA (hwnd, GWL_HINSTANCE), NULL);
134     lpipsi->wpOrigProc[i]= (WNDPROC)
135         SetWindowLongA (lpipsi->hwndIP[i],GWL_WNDPROC, (LONG)
136         IPADDRESS_SubclassProc);
137     SetPropA ((HWND)lpipsi->hwndIP[i], IP_SUBCLASS_PROP, (HANDLE)lpipsi);
138   }
139
140   lpipsi->infoPtr= infoPtr;
141
142   return 0;
143 }
144
145
146 static LRESULT
147 IPADDRESS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
148 {
149   int i;
150   IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
151   LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
152             GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
153
154   for (i=0; i<=3; i++) {
155     SetWindowLongA ((HWND)lpipsi->hwndIP[i], GWL_WNDPROC,
156                   (LONG)lpipsi->wpOrigProc[i]);
157   }
158
159   COMCTL32_Free (infoPtr);
160   SetWindowLongA (hwnd, 0, 0);
161   return 0;
162 }
163
164
165 static LRESULT
166 IPADDRESS_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
167 {
168   HDC hdc;
169
170   TRACE("\n");
171   hdc = GetDC (hwnd);
172   IPADDRESS_Refresh (hwnd, hdc);
173   ReleaseDC (hwnd, hdc);
174
175   IPADDRESS_SendIPAddressNotify (hwnd, 0, 0);  /* FIXME: should use -1 */
176   IPADDRESS_SendNotify (hwnd, EN_KILLFOCUS);       
177   InvalidateRect (hwnd, NULL, TRUE);
178
179   return 0;
180 }
181
182
183 static LRESULT
184 IPADDRESS_Paint (HWND hwnd, WPARAM wParam)
185 {
186   HDC hdc;
187   PAINTSTRUCT ps;
188
189   hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
190   IPADDRESS_Refresh (hwnd, hdc);
191   if(!wParam)
192     EndPaint (hwnd, &ps);
193   return 0;
194 }
195
196
197 static LRESULT
198 IPADDRESS_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
199 {
200   HDC hdc;
201
202   TRACE("\n");
203
204   hdc = GetDC (hwnd);
205   IPADDRESS_Refresh (hwnd, hdc);
206   ReleaseDC (hwnd, hdc);
207
208   return 0;
209 }
210
211
212 static LRESULT
213 IPADDRESS_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
214 {
215   /* IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd); */
216   TRACE("\n");
217   return 0;
218 }
219
220
221 static BOOL
222 IPADDRESS_SendNotify (HWND hwnd, UINT command)
223 {
224   TRACE("%x\n",command);
225   return (BOOL)SendMessageA (GetParent (hwnd), WM_COMMAND,
226               MAKEWPARAM (GetWindowLongA (hwnd, GWL_ID),command), (LPARAM)hwnd);
227 }
228
229
230 static BOOL
231 IPADDRESS_SendIPAddressNotify (HWND hwnd, UINT field, BYTE newValue)
232 {
233   NMIPADDRESS nmip;
234
235   TRACE("%x %x\n",field,newValue);
236   nmip.hdr.hwndFrom = hwnd;
237   nmip.hdr.idFrom   = GetWindowLongA (hwnd, GWL_ID);
238   nmip.hdr.code     = IPN_FIELDCHANGED;
239
240   nmip.iField=field;
241   nmip.iValue=newValue;
242
243   return (BOOL)SendMessageA (GetParent (hwnd), WM_NOTIFY,
244                              (WPARAM)nmip.hdr.idFrom, (LPARAM)&nmip);
245 }
246
247
248 static LRESULT
249 IPADDRESS_ClearAddress (HWND hwnd, WPARAM wParam, LPARAM lParam)
250 {
251   int i;
252   HDC hdc;
253   char buf[1];
254   LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
255             GetPropA ((HWND)hwnd,IP_SUBCLASS_PROP);
256
257   TRACE("\n");
258
259   buf[0]=0;
260   for (i=0; i<=3; i++) 
261     SetWindowTextA (lpipsi->hwndIP[i],buf);
262         
263   hdc = GetDC (hwnd);
264   IPADDRESS_Refresh (hwnd, hdc);
265   ReleaseDC (hwnd, hdc);
266         
267   return 0;
268 }
269
270
271 static LRESULT
272 IPADDRESS_IsBlank (HWND hwnd, WPARAM wParam, LPARAM lParam)
273 {
274   int i;
275   char buf[20];
276   LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
277             GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
278
279   TRACE("\n");
280
281   for (i=0; i<=3; i++) {
282     GetWindowTextA (lpipsi->hwndIP[i],buf,5);
283     if (buf[0])
284       return 0;
285   }
286
287   return 1;
288 }
289
290
291 static LRESULT
292 IPADDRESS_GetAddress (HWND hwnd, WPARAM wParam, LPARAM lParam)
293 {
294   char field[20];
295   int i,valid,fieldvalue;
296   DWORD ip_addr;
297   IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
298   LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
299             GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
300
301   TRACE("\n");
302
303   valid=0;
304   ip_addr=0;
305   for (i=0; i<=3; i++) {
306     GetWindowTextA (lpipsi->hwndIP[i],field,4);
307     ip_addr*=256;
308     if (field[0]) {
309       field[3]=0;
310       fieldvalue=atoi(field);
311       if (fieldvalue<infoPtr->LowerLimit[i]) 
312         fieldvalue=infoPtr->LowerLimit[i];
313       if (fieldvalue>infoPtr->UpperLimit[i]) 
314         fieldvalue=infoPtr->UpperLimit[i];
315       ip_addr+=fieldvalue;
316       valid++;
317     }
318   }
319
320   *(LPDWORD) lParam=ip_addr;
321
322   return valid;
323 }
324
325
326 static LRESULT
327 IPADDRESS_SetRange (HWND hwnd, WPARAM wParam, LPARAM lParam)
328 {
329   IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
330   INT index;
331         
332   TRACE("\n");
333
334   index=(INT) wParam;
335   if ((index<0) || (index>3)) return 0;
336
337   infoPtr->LowerLimit[index]=lParam & 0xff;
338   infoPtr->UpperLimit[index]=(lParam >>8)  & 0xff;
339   return 1;
340 }
341
342
343 static LRESULT
344 IPADDRESS_SetAddress (HWND hwnd, WPARAM wParam, LPARAM lParam)
345 {
346   IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
347   HDC hdc;
348   LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
349             GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
350   int i,ip_address,value;
351   char buf[20];
352
353   TRACE("\n");
354   ip_address=(DWORD) lParam;
355
356   for (i=3; i>=0; i--) {
357     value=ip_address & 0xff;
358     if ((value>=infoPtr->LowerLimit[i]) && (value<=infoPtr->UpperLimit[i])) 
359     {
360       sprintf (buf,"%d",value);
361       SetWindowTextA (lpipsi->hwndIP[i],buf);
362       IPADDRESS_SendNotify (hwnd, EN_CHANGE);
363     }
364     ip_address/=256;
365   }
366
367   hdc = GetDC (hwnd);           /* & send notifications */
368   IPADDRESS_Refresh (hwnd, hdc);
369   ReleaseDC (hwnd, hdc);
370
371   return TRUE;
372 }
373
374
375 static LRESULT
376 IPADDRESS_SetFocusToField (HWND hwnd, WPARAM wParam, LPARAM lParam)
377 {
378   /* IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd); */
379   LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO) GetPropA ((HWND)hwnd,
380                                                    IP_SUBCLASS_PROP);
381   INT index;
382
383   index=(INT) wParam;
384   TRACE(" %d\n", index);
385   if ((index<0) || (index>3)) return 0;
386         
387   SetFocus (lpipsi->hwndIP[index]);
388         
389   return 1;
390 }
391
392
393 static LRESULT
394 IPADDRESS_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
395 {
396   TRACE("\n");
397
398   SetFocus (hwnd);
399   IPADDRESS_SendNotify (hwnd, EN_SETFOCUS);
400   IPADDRESS_SetFocusToField (hwnd, 0, 0);
401
402   return TRUE;
403 }
404
405
406 static INT
407 IPADDRESS_CheckField (LPIP_SUBCLASS_INFO lpipsi, int currentfield)
408 {
409   int newField,fieldvalue;
410   char field[20];
411   IPADDRESS_INFO *infoPtr=lpipsi->infoPtr;
412
413   if(currentfield >= 0 && currentfield < 4)
414   {
415     TRACE("\n");
416     GetWindowTextA (lpipsi->hwndIP[currentfield],field,4);
417     if (field[0])
418     {
419       field[3]=0;       
420       newField=-1;
421       fieldvalue=atoi(field);
422     
423       if (fieldvalue < infoPtr->LowerLimit[currentfield]) 
424         newField=infoPtr->LowerLimit[currentfield];
425     
426       if (fieldvalue > infoPtr->UpperLimit[currentfield])
427         newField=infoPtr->UpperLimit[currentfield];
428     
429       if (newField >= 0)
430       {
431         sprintf (field,"%d",newField);
432         SetWindowTextA (lpipsi->hwndIP[currentfield], field);
433         return TRUE;
434       }
435     }
436   }
437   return FALSE;
438 }
439
440
441 static INT
442 IPADDRESS_GotoNextField (LPIP_SUBCLASS_INFO lpipsi, int currentfield)
443 {
444   if(currentfield >= -1 && currentfield < 4)
445   {
446     IPADDRESS_CheckField(lpipsi, currentfield); /* check the fields value */  
447
448     if(currentfield < 3)
449     { 
450       SetFocus (lpipsi->hwndIP[currentfield+1]);
451       return TRUE; 
452     }
453   }
454   return FALSE;
455 }
456
457
458 /* period: move and select the text in the next field to the right if */
459 /*         the current field is not empty(l!=0), we are not in the */
460 /*         left most position, and nothing is selected(startsel==endsel) */
461
462 /* spacebar: same behavior as period */
463
464 /* alpha characters: completely ignored */
465
466 /* digits: accepted when field text length < 2 ignored otherwise. */
467 /*         when 3 numbers have been entered into the field the value */
468 /*         of the field is checked, if the field value exceeds the */
469 /*         maximum value and is changed the field remains the current */
470 /*         field, otherwise focus moves to the field to the right */
471
472 /* tab: change focus from the current ipaddress control to the next */
473 /*      control in the tab order */
474
475 /* right arrow: move to the field on the right to the left most */
476 /*              position in that field if no text is selected, */
477 /*              we are in the right most position in the field, */
478 /*              we are not in the right most field */
479
480 /* left arrow: move to the field on the left to the right most */
481 /*             position in that field if no text is selected, */
482 /*             we are in the left most position in the current field */
483 /*             and we are not in the left most field */
484
485 /* backspace: delete the character to the left of the cursor position, */
486 /*            if none are present move to the field on the left if */
487 /*            we are not in the left most field and delete the right */
488 /*            most digit in that field while keeping the cursor */
489 /*            on the right side of the field */
490
491
492 LRESULT CALLBACK
493 IPADDRESS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
494 {
495   IPADDRESS_INFO *infoPtr;
496   LPIP_SUBCLASS_INFO lpipsi = (LPIP_SUBCLASS_INFO) GetPropA
497         ((HWND)hwnd,IP_SUBCLASS_PROP); 
498   CHAR c = (CHAR)wParam;
499   INT i, l, index, startsel, endsel;
500
501   infoPtr = lpipsi->infoPtr;
502   index=0;             /* FIXME */
503   for (i=0; i<=3; i++) 
504     if (lpipsi->hwndIP[i]==hwnd) index=i;
505
506   switch (uMsg) {
507   case WM_CHAR: 
508     if(isdigit(c)) /* process all digits */
509     {
510       int return_val;
511       SendMessageA(lpipsi->hwndIP[index], EM_GETSEL, (WPARAM)&startsel, (LPARAM)&endsel); 
512       l = GetWindowTextLengthA (lpipsi->hwndIP[index]);
513       if(l==2 && startsel==endsel) /* field is full after this key is processed */
514       { 
515         /* process the digit press before we check the field */
516         return_val = CallWindowProcA (lpipsi->wpOrigProc[index], hwnd, uMsg, wParam, lParam);
517           
518         /* if the field value was changed stay at the current field */
519         if(!IPADDRESS_CheckField(lpipsi, index))
520           IPADDRESS_GotoNextField (lpipsi,index);
521
522         return return_val;
523       }
524       
525       if(l > 2) /* field is full, stop key messages */
526       {
527         lParam = 0;
528         wParam = 0;
529       }
530       break;
531     }   
532     
533     if(c == '.') /* VK_PERIOD */
534     { 
535       l = GetWindowTextLengthA(lpipsi->hwndIP[index]);
536       SendMessageA(lpipsi->hwndIP[index], EM_GETSEL, (WPARAM)&startsel, (LPARAM)&endsel);
537       if(l != 0 && startsel==endsel && startsel != 0)
538       {
539         IPADDRESS_GotoNextField(lpipsi, index); 
540         SendMessageA(lpipsi->hwndIP[index+1], EM_SETSEL, (WPARAM)0, (LPARAM)3);
541       }
542     }
543         
544     /* stop all other characters */
545     wParam = 0;
546     lParam = 0;
547     break;
548
549   case WM_KEYDOWN:
550     if(c == VK_SPACE)
551     { 
552       l = GetWindowTextLengthA(lpipsi->hwndIP[index]);
553       SendMessageA(lpipsi->hwndIP[index], EM_GETSEL, (WPARAM)&startsel, (LPARAM)&endsel);
554       if(l != 0 && startsel==endsel && startsel != 0)
555       {
556         IPADDRESS_GotoNextField(lpipsi, index); 
557         SendMessageA(lpipsi->hwndIP[index+1], EM_SETSEL, (WPARAM)0, (LPARAM)3);
558       }
559     }
560
561     if(c == VK_RIGHT)
562     {
563       SendMessageA(lpipsi->hwndIP[index], EM_GETSEL, (WPARAM)&startsel, (LPARAM)&endsel);
564       l = GetWindowTextLengthA (lpipsi->hwndIP[index]);
565     
566       if(startsel==endsel && startsel==l)
567       {
568         IPADDRESS_GotoNextField(lpipsi, index);
569         SendMessageA(lpipsi->hwndIP[index+1], EM_SETSEL, (WPARAM)0,(LPARAM)0);
570       }
571     }
572
573     if(c == VK_LEFT)
574     { 
575       SendMessageA(lpipsi->hwndIP[index], EM_GETSEL, (WPARAM)&startsel, (LPARAM)&endsel);
576       if(startsel==0 && startsel==endsel && index > 0)
577       {        
578         IPADDRESS_GotoNextField(lpipsi, index - 2);
579         l = GetWindowTextLengthA(lpipsi->hwndIP[index-1]);
580         SendMessageA(lpipsi->hwndIP[index-1], EM_SETSEL, (WPARAM)l,(LPARAM)l);
581       }     
582     }
583    
584     if(c == VK_BACK) /* VK_BACKSPACE */
585     {
586       CHAR buf[4];
587
588       SendMessageA(lpipsi->hwndIP[index], EM_GETSEL, (WPARAM)&startsel, (LPARAM)&endsel); 
589       l = GetWindowTextLengthA (lpipsi->hwndIP[index]);
590       if(startsel==endsel && startsel==0 && index > 0)
591       {
592         l = GetWindowTextLengthA(lpipsi->hwndIP[index-1]);
593         if(l!=0)
594         {
595           GetWindowTextA (lpipsi->hwndIP[index-1],buf,4);
596           buf[l-1] = '\0'; 
597           SetWindowTextA(lpipsi->hwndIP[index-1], buf);
598           SendMessageA(lpipsi->hwndIP[index-1], EM_SETSEL, (WPARAM)l,(LPARAM)l);
599         } 
600         IPADDRESS_GotoNextField(lpipsi, index - 2);
601       }
602     }
603     break;
604
605   default:
606     break;
607   }
608   return CallWindowProcA (lpipsi->wpOrigProc[index], hwnd, uMsg, wParam, lParam);
609 }
610
611
612 static LRESULT WINAPI
613 IPADDRESS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
614 {
615   TRACE("hwnd=%x msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam);
616   if (!IPADDRESS_GetInfoPtr (hwnd) && (uMsg != WM_CREATE))
617       return DefWindowProcA (hwnd, uMsg, wParam, lParam);
618   switch (uMsg)
619   {
620     case IPM_CLEARADDRESS:
621       return IPADDRESS_ClearAddress (hwnd, wParam, lParam);
622
623     case IPM_SETADDRESS:
624       return IPADDRESS_SetAddress (hwnd, wParam, lParam);
625
626     case IPM_GETADDRESS:
627       return IPADDRESS_GetAddress (hwnd, wParam, lParam);
628
629     case IPM_SETRANGE:
630       return IPADDRESS_SetRange (hwnd, wParam, lParam);
631
632     case IPM_SETFOCUS:
633       return IPADDRESS_SetFocusToField (hwnd, wParam, lParam);
634
635     case IPM_ISBLANK:
636       return IPADDRESS_IsBlank (hwnd, wParam, lParam);
637
638     case WM_CREATE:
639       return IPADDRESS_Create (hwnd, wParam, lParam);
640
641     case WM_DESTROY:
642       return IPADDRESS_Destroy (hwnd, wParam, lParam);
643
644     case WM_GETDLGCODE:
645       return DLGC_WANTARROWS | DLGC_WANTCHARS;
646
647     case WM_KILLFOCUS:
648       return IPADDRESS_KillFocus (hwnd, wParam, lParam);
649
650     case WM_LBUTTONDOWN:
651       return IPADDRESS_LButtonDown (hwnd, wParam, lParam);
652
653     case WM_PAINT:
654       return IPADDRESS_Paint (hwnd, wParam);
655
656     case WM_SETFOCUS:
657       return IPADDRESS_SetFocus (hwnd, wParam, lParam);
658
659     case WM_SIZE:
660       return IPADDRESS_Size (hwnd, wParam, lParam);
661
662     default:
663       if (uMsg >= WM_USER)
664         ERR("unknown msg %04x wp=%08x lp=%08lx\n",
665                      uMsg, wParam, lParam);
666       return DefWindowProcA (hwnd, uMsg, wParam, lParam);
667     }
668     return 0;
669 }
670
671
672 void IPADDRESS_Register (void)
673 {
674   WNDCLASSA wndClass;
675
676   ZeroMemory (&wndClass, sizeof(WNDCLASSA));
677   wndClass.style         = CS_GLOBALCLASS;
678   wndClass.lpfnWndProc   = (WNDPROC)IPADDRESS_WindowProc;
679   wndClass.cbClsExtra    = 0;
680   wndClass.cbWndExtra    = sizeof(IPADDRESS_INFO *);
681   wndClass.hCursor       = LoadCursorA (0, IDC_ARROWA);
682   wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
683   wndClass.lpszClassName = WC_IPADDRESSA;
684  
685   RegisterClassA (&wndClass);
686 }
687
688
689 VOID IPADDRESS_Unregister (void)
690 {
691   UnregisterClassA (WC_IPADDRESSA, (HINSTANCE)NULL);
692 }