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

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

Added CVS tag to many files (comctl32 and headers) .

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