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

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

* empty log message *

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