source: trunk/src/comctl32/ipaddress.c@ 55

Last change on this file since 55 was 55, checked in by achimha, 26 years ago

* empty log message *

File size: 12.7 KB
Line 
1/*
2 * IP Address control
3 *
4 * Copyright 1998, 1999 Eric Kohl
5 * Copyright 1998 Alex Priem <alexp@sci.kun.nl>
6 *
7 * NOTES
8
9 *
10 * TODO:
11 * -Check ranges when changing field-focus.
12 * -Check all notifications/behavior.
13 * -Optimization: include lpipsi in IPADDRESS_INFO.
14 * -CurrentFocus: field that has focus at moment of processing.
15 * -connect Rect32 rcClient.
16 * -handle right and left arrows correctly. Boring.
17 * -split GotoNextField in CheckField and GotoNextField.
18 * -check ipaddress.cpp for missing features.
19 * -refresh: draw '.' instead of setpixel.
20 * -handle VK_ESCAPE.
21 */
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <stdio.h>
26
27#include "winbase.h"
28#include "commctrl.h"
29#include "ipaddress.h"
30#include "heap.h"
31
32
33#define IPADDRESS_GetInfoPtr(hwnd) ((IPADDRESS_INFO *)GetWindowLongA (hwnd, 0))
34
35
36static BOOL
37IPADDRESS_SendNotify (HWND hwnd, UINT command);
38static BOOL
39IPADDRESS_SendIPAddressNotify (HWND hwnd, UINT field, BYTE newValue);
40
41
42/* property name of tooltip window handle */
43#define IP_SUBCLASS_PROP "CCIP32SubclassInfo"
44
45
46static LRESULT CALLBACK
47IPADDRESS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
48
49
50
51
52static VOID
53IPADDRESS_Refresh (HWND hwnd, HDC hdc)
54{
55 RECT rcClient;
56 HBRUSH hbr;
57 COLORREF clr=GetSysColor (COLOR_3DDKSHADOW);
58 int i,x,fieldsize;
59
60 GetClientRect (hwnd, &rcClient);
61 hbr = CreateSolidBrush (RGB(255,255,255));
62 DrawEdge (hdc, &rcClient, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
63 FillRect (hdc, &rcClient, hbr);
64 DeleteObject (hbr);
65
66 x=rcClient.left;
67 fieldsize=(rcClient.right-rcClient.left) /4;
68
69 for (i=0; i<3; i++) { /* Should draw text "." here */
70 x+=fieldsize;
71 SetPixel (hdc, x, 13, clr);
72 SetPixel (hdc, x, 14, clr);
73 SetPixel (hdc, x+1, 13, clr);
74 SetPixel (hdc, x+1, 14, clr);
75
76 }
77
78}
79
80
81
82
83
84static LRESULT
85IPADDRESS_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
86{
87 IPADDRESS_INFO *infoPtr;
88 RECT rcClient, edit;
89 int i,fieldsize;
90 LPIP_SUBCLASS_INFO lpipsi;
91
92
93 infoPtr = (IPADDRESS_INFO *)COMCTL32_Alloc (sizeof(IPADDRESS_INFO));
94 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
95
96 GetClientRect (hwnd, &rcClient);
97
98 fieldsize=(rcClient.right-rcClient.left) /4;
99
100 edit.top =rcClient.top+2;
101 edit.bottom=rcClient.bottom-2;
102
103 lpipsi=(LPIP_SUBCLASS_INFO)
104 GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
105 if (lpipsi == NULL) {
106 lpipsi= (LPIP_SUBCLASS_INFO) COMCTL32_Alloc (sizeof(IP_SUBCLASS_INFO));
107 lpipsi->hwnd = hwnd;
108 lpipsi->uRefCount++;
109 SetPropA ((HWND)hwnd, IP_SUBCLASS_PROP,
110 (HANDLE)lpipsi);
111/* infoPtr->lpipsi= lpipsi; */
112// } else
113 }
114// WARN (ipaddress,"IP-create called twice\n");
115
116 for (i=0; i<=3; i++) {
117 infoPtr->LowerLimit[i]=0;
118 infoPtr->UpperLimit[i]=255;
119 edit.left=rcClient.left+i*fieldsize+3;
120 edit.right=rcClient.left+(i+1)*fieldsize-2;
121 lpipsi->hwndIP[i]= CreateWindowA ("edit", NULL,
122 WS_CHILD | WS_VISIBLE | ES_LEFT,
123 edit.left, edit.top, edit.right-edit.left, edit.bottom-edit.top,
124 hwnd, (HMENU) 1, GetWindowLongA (hwnd, GWL_HINSTANCE), NULL);
125 lpipsi->wpOrigProc[i]= (WNDPROC)
126 SetWindowLongA (lpipsi->hwndIP[i],GWL_WNDPROC, (LONG)
127 IPADDRESS_SubclassProc);
128 SetPropA ((HWND)lpipsi->hwndIP[i], IP_SUBCLASS_PROP,
129 (HANDLE)lpipsi);
130 }
131
132 lpipsi->infoPtr= infoPtr;
133
134 return 0;
135}
136
137
138static LRESULT
139IPADDRESS_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
140{
141 int i;
142 IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
143 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
144 GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
145
146 for (i=0; i<=3; i++) {
147 SetWindowLongA ((HWND)lpipsi->hwndIP[i], GWL_WNDPROC,
148 (LONG)lpipsi->wpOrigProc[i]);
149 }
150
151 COMCTL32_Free (infoPtr);
152 return 0;
153}
154
155
156static LRESULT
157IPADDRESS_KillFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
158{
159 HDC hdc;
160
161// TRACE (ipaddress,"\n");
162 hdc = GetDC (hwnd);
163 IPADDRESS_Refresh (hwnd, hdc);
164 ReleaseDC (hwnd, hdc);
165
166 IPADDRESS_SendIPAddressNotify (hwnd, 0, 0); /* FIXME: should use -1 */
167 IPADDRESS_SendNotify (hwnd, EN_KILLFOCUS);
168 InvalidateRect (hwnd, NULL, TRUE);
169
170 return 0;
171}
172
173
174static LRESULT
175IPADDRESS_Paint (HWND hwnd, WPARAM wParam)
176{
177 HDC hdc;
178 PAINTSTRUCT ps;
179
180 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
181 IPADDRESS_Refresh (hwnd, hdc);
182 if(!wParam)
183 EndPaint (hwnd, &ps);
184 return 0;
185}
186
187
188static LRESULT
189IPADDRESS_SetFocus (HWND hwnd, WPARAM wParam, LPARAM lParam)
190{
191 HDC hdc;
192
193// TRACE (ipaddress,"\n");
194
195 hdc = GetDC (hwnd);
196 IPADDRESS_Refresh (hwnd, hdc);
197 ReleaseDC (hwnd, hdc);
198
199 return 0;
200}
201
202
203static LRESULT
204IPADDRESS_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
205{
206 /* IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd); */
207// TRACE (ipaddress,"\n");
208 return 0;
209}
210
211
212static BOOL
213IPADDRESS_SendNotify (HWND hwnd, UINT command)
214
215{
216// TRACE (ipaddress, "%x\n",command);
217 return (BOOL)SendMessageA (GetParent (hwnd), WM_COMMAND,
218 MAKEWPARAM (GetWindowLongA (hwnd, GWL_ID),command), (LPARAM)hwnd);
219}
220
221
222static BOOL
223IPADDRESS_SendIPAddressNotify (HWND hwnd, UINT field, BYTE newValue)
224{
225 NMIPADDRESS nmip;
226
227// TRACE (ipaddress, "%x %x\n",field,newValue);
228 nmip.hdr.hwndFrom = hwnd;
229 nmip.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
230 nmip.hdr.code = IPN_FIELDCHANGED;
231
232 nmip.iField=field;
233 nmip.iValue=newValue;
234
235 return (BOOL)SendMessageA (GetParent (hwnd), WM_NOTIFY,
236 (WPARAM)nmip.hdr.idFrom, (LPARAM)&nmip);
237}
238
239
240
241
242static LRESULT
243IPADDRESS_ClearAddress (HWND hwnd, WPARAM wParam, LPARAM lParam)
244{
245 int i;
246 HDC hdc;
247 char buf[1];
248 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
249 GetPropA ((HWND)hwnd,IP_SUBCLASS_PROP);
250
251// TRACE (ipaddress,"\n");
252
253 buf[0]=0;
254 for (i=0; i<=3; i++)
255 SetWindowTextA (lpipsi->hwndIP[i],buf);
256
257 hdc = GetDC (hwnd);
258 IPADDRESS_Refresh (hwnd, hdc);
259 ReleaseDC (hwnd, hdc);
260
261 return 0;
262}
263
264static LRESULT
265IPADDRESS_IsBlank (HWND hwnd, WPARAM wParam, LPARAM lParam)
266{
267 int i;
268 char buf[20];
269 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
270 GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
271
272// TRACE (ipaddress,"\n");
273
274 for (i=0; i<=3; i++) {
275 GetWindowTextA (lpipsi->hwndIP[i],buf,5);
276 if (buf[0])
277 return 0;
278 }
279
280 return 1;
281}
282
283static LRESULT
284IPADDRESS_GetAddress (HWND hwnd, WPARAM wParam, LPARAM lParam)
285{
286 char field[20];
287 int i,valid,fieldvalue;
288 DWORD ip_addr;
289 IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
290 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
291 GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
292
293// TRACE (ipaddress,"\n");
294
295 valid=0;
296 ip_addr=0;
297 for (i=0; i<=3; i++) {
298 GetWindowTextA (lpipsi->hwndIP[i],field,4);
299 ip_addr*=256;
300 if (field[0]) {
301 field[3]=0;
302 fieldvalue=atoi(field);
303 if (fieldvalue<infoPtr->LowerLimit[i])
304 fieldvalue=infoPtr->LowerLimit[i];
305 if (fieldvalue>infoPtr->UpperLimit[i])
306 fieldvalue=infoPtr->UpperLimit[i];
307 ip_addr+=fieldvalue;
308 valid++;
309 }
310 }
311
312 *(LPDWORD) lParam=ip_addr;
313
314 return valid;
315}
316
317
318static LRESULT
319IPADDRESS_SetRange (HWND hwnd, WPARAM wParam, LPARAM lParam)
320{
321 IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
322 INT index;
323
324// TRACE (ipaddress,"\n");
325
326 index=(INT) wParam;
327 if ((index<0) || (index>3)) return 0;
328
329 infoPtr->LowerLimit[index]=lParam & 0xff;
330 infoPtr->UpperLimit[index]=(lParam >>8) & 0xff;
331 return 1;
332}
333
334static LRESULT
335IPADDRESS_SetAddress (HWND hwnd, WPARAM wParam, LPARAM lParam)
336{
337 IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd);
338 HDC hdc;
339 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
340 GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
341 int i,ip_address,value;
342 char buf[20];
343
344// TRACE (ipaddress,"\n");
345 ip_address=(DWORD) lParam;
346
347 for (i=3; i>=0; i--) {
348 value=ip_address & 0xff;
349 if ((value>=infoPtr->LowerLimit[i]) && (value<=infoPtr->UpperLimit[i]))
350 {
351 sprintf (buf,"%d",value);
352 SetWindowTextA (lpipsi->hwndIP[i],buf);
353 IPADDRESS_SendNotify (hwnd, EN_CHANGE);
354 }
355 ip_address/=256;
356 }
357
358 hdc = GetDC (hwnd); /* & send notifications */
359 IPADDRESS_Refresh (hwnd, hdc);
360 ReleaseDC (hwnd, hdc);
361
362 return TRUE;
363}
364
365
366
367
368static LRESULT
369IPADDRESS_SetFocusToField (HWND hwnd, WPARAM wParam, LPARAM lParam)
370{
371 /* IPADDRESS_INFO *infoPtr = IPADDRESS_GetInfoPtr (hwnd); */
372 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
373 GetPropA ((HWND)hwnd, IP_SUBCLASS_PROP);
374 INT index;
375
376 index=(INT) wParam;
377// TRACE (ipaddress," %d\n", index);
378 if ((index<0) || (index>3)) return 0;
379
380 SetFocus (lpipsi->hwndIP[index]);
381
382 return 1;
383}
384
385
386static LRESULT
387IPADDRESS_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
388{
389// TRACE (ipaddress, "\n");
390
391 SetFocus (hwnd);
392 IPADDRESS_SendNotify (hwnd, EN_SETFOCUS);
393 IPADDRESS_SetFocusToField (hwnd, 0, 0);
394
395 return TRUE;
396}
397
398
399
400/* tab/shift-tab: IPN_FIELDCHANGED, lose focus.
401 dot, space,right arrow: set focus to next child edit.
402 numerics (0..9), control characters: forward to default edit control
403 other characters: dropped
404*/
405
406
407
408
409static int
410IPADDRESS_GotoNextField (LPIP_SUBCLASS_INFO lpipsi, int currentfield)
411{
412 int newField,fieldvalue;
413 char field[20];
414 IPADDRESS_INFO *infoPtr=lpipsi->infoPtr;
415
416// TRACE (ipaddress,"\n");
417 GetWindowTextA (lpipsi->hwndIP[currentfield],field,4);
418 if (field[0]) {
419 field[3]=0;
420 newField=-1;
421 fieldvalue=atoi(field);
422 if (fieldvalue<infoPtr->LowerLimit[currentfield])
423 newField=infoPtr->LowerLimit[currentfield];
424 if (fieldvalue>infoPtr->UpperLimit[currentfield])
425 newField=infoPtr->UpperLimit[currentfield];
426 if (newField>=0) {
427 sprintf (field,"%d",newField);
428 SetWindowTextA (lpipsi->hwndIP[currentfield], field);
429 return 1;
430 }
431 }
432
433 if (currentfield<3)
434 SetFocus (lpipsi->hwndIP[currentfield+1]);
435 return 0;
436}
437
438
439LRESULT CALLBACK
440IPADDRESS_SubclassProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
441{
442 int i,l,index;
443 IPADDRESS_INFO *infoPtr;
444 LPIP_SUBCLASS_INFO lpipsi=(LPIP_SUBCLASS_INFO)
445 GetPropA ((HWND)hwnd,IP_SUBCLASS_PROP);
446
447 infoPtr = lpipsi->infoPtr;
448 index=0; /* FIXME */
449 for (i=0; i<=3; i++)
450 if (lpipsi->hwndIP[i]==hwnd) index=i;
451
452 switch (uMsg) {
453 case WM_CHAR: break;
454 case WM_KEYDOWN: {
455 char c=(char) wParam;
456 if (c==VK_TAB) {
457 HWND pwnd;
458 int shift;
459 shift = GetKeyState(VK_SHIFT) & 0x8000;
460 if (shift)
461 pwnd=GetNextDlgTabItem (GetParent (hwnd), 0, TRUE);
462 else
463 pwnd=GetNextDlgTabItem (GetParent (hwnd), 0, FALSE);
464 if (pwnd) SetFocus (pwnd);
465 break;
466 }
467
468 if ((c==' ') || (c=='.') || (c==VK_RIGHT)) {
469 IPADDRESS_GotoNextField (lpipsi,index);
470 wParam=0;
471 lParam=0;
472 break;
473 }
474 if (c==VK_LEFT) {
475
476 }
477 if (c==VK_RETURN) {
478 }
479 if (((c>='0') && (c<='9')) || (iscntrl(c))) {
480 l=GetWindowTextLengthA (lpipsi->hwndIP[index]);
481 if (l==3)
482 if (IPADDRESS_GotoNextField (lpipsi,index)) {
483 wParam=0;
484 lParam=0;
485 }
486 break;
487 }
488
489 wParam=0;
490 lParam=0;
491 break;
492 }
493 }
494
495 return CallWindowProcA (lpipsi->wpOrigProc[index], hwnd, uMsg, wParam, lParam);
496}
497
498LRESULT WINAPI
499IPADDRESS_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
500{
501 switch (uMsg)
502 {
503 case IPM_CLEARADDRESS:
504 return IPADDRESS_ClearAddress (hwnd, wParam, lParam);
505
506 case IPM_SETADDRESS:
507 return IPADDRESS_SetAddress (hwnd, wParam, lParam);
508
509 case IPM_GETADDRESS:
510 return IPADDRESS_GetAddress (hwnd, wParam, lParam);
511
512 case IPM_SETRANGE:
513 return IPADDRESS_SetRange (hwnd, wParam, lParam);
514
515 case IPM_SETFOCUS:
516 return IPADDRESS_SetFocusToField (hwnd, wParam, lParam);
517
518 case IPM_ISBLANK:
519 return IPADDRESS_IsBlank (hwnd, wParam, lParam);
520
521 case WM_CREATE:
522 return IPADDRESS_Create (hwnd, wParam, lParam);
523
524 case WM_DESTROY:
525 return IPADDRESS_Destroy (hwnd, wParam, lParam);
526
527 case WM_GETDLGCODE:
528 return DLGC_WANTARROWS | DLGC_WANTCHARS;
529
530 case WM_KILLFOCUS:
531 return IPADDRESS_KillFocus (hwnd, wParam, lParam);
532
533 case WM_LBUTTONDOWN:
534 return IPADDRESS_LButtonDown (hwnd, wParam, lParam);
535
536 case WM_PAINT:
537 return IPADDRESS_Paint (hwnd, wParam);
538
539 case WM_SETFOCUS:
540 return IPADDRESS_SetFocus (hwnd, wParam, lParam);
541
542 case WM_SIZE:
543 return IPADDRESS_Size (hwnd, wParam, lParam);
544
545 default:
546// if (uMsg >= WM_USER)
547// ERR (ipaddress, "unknown msg %04x wp=%08x lp=%08lx\n",
548// uMsg, wParam, lParam);
549 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
550 }
551 return 0;
552}
553
554
555void
556IPADDRESS_Register (void)
557{
558 WNDCLASSA wndClass;
559
560 if (GlobalFindAtomA (WC_IPADDRESSA)) return;
561
562 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
563 wndClass.style = CS_GLOBALCLASS;
564 wndClass.lpfnWndProc = (WNDPROC)IPADDRESS_WindowProc;
565 wndClass.cbClsExtra = 0;
566 wndClass.cbWndExtra = sizeof(IPADDRESS_INFO *);
567 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
568 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
569 wndClass.lpszClassName = WC_IPADDRESSA;
570
571 RegisterClassA (&wndClass);
572}
573
574VOID
575IPADDRESS_Unregister (VOID)
576{
577 if (GlobalFindAtomA (WC_IPADDRESSA))
578 UnregisterClassA (WC_IPADDRESSA, (HINSTANCE)NULL);
579}
580
Note: See TracBrowser for help on using the repository browser.