Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1701 lines
56 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1995 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. FILE HISTORY:
  7. ipaddr.c - TCP/IP Address custom control
  8. November 9, 1992 Greg Strange
  9. December 13, 1993 Ronald Meijer - Wildcard and readonly style bits
  10. April 18, 1994 Ronald Meijer - Added IP_SETREADONLY, IP_SETFIELD
  11. */
  12. #include <stdafx.h>
  13. //nclude <windows.h>
  14. //nclude <stdlib.h>
  15. #ifdef IP_CUST_CTRL
  16. #include <custcntl.h>
  17. #endif
  18. #include "ipaddr.h" // Global IPAddress definitions
  19. #include "ipadd.h" // Internal IPAddress definitions
  20. /* global static variables */
  21. static HINSTANCE s_hLibInstance = NULL;
  22. #ifdef IP_CUST_CTRL
  23. HANDLE hLibData;
  24. LPFNSTRTOID lpfnVerId;
  25. LPFNIDTOSTR lpfnIdStr;
  26. #endif
  27. /*
  28. Strings loaded at initialization.
  29. */
  30. TCHAR szNoMem[MAX_IPNOMEMSTRING]; // Out of memory string
  31. TCHAR szCaption[MAX_IPCAPTION]; // Alert message box caption
  32. #define IPADDRESS_CLASS TEXT("IPAddress")
  33. // The character that is displayed between address fields.
  34. #define FILLER TEXT('.')
  35. #define SZFILLER TEXT(".")
  36. #define SPACE TEXT(' ')
  37. #define WILDCARD TEXT('*')
  38. #define SZWILDCARD TEXT(" *")
  39. #define BACK_SPACE 8
  40. // Min, max values
  41. #define NUM_FIELDS 4
  42. #define CHARS_PER_FIELD 3
  43. #define HEAD_ROOM 1 // space at top of control
  44. #define LEAD_ROOM 1 // space at front of control
  45. #define MIN_FIELD_VALUE 0 // default minimum allowable field value
  46. #define MAX_FIELD_VALUE 255 // default maximum allowable field value
  47. // All the information unique to one control is stuffed in one of these
  48. // structures in global memory and the handle to the memory is stored in the
  49. // Windows extra space.
  50. typedef struct tagFIELD {
  51. HWND hWnd;
  52. WNDPROC lpfnWndProc;
  53. BYTE byLow; // lowest allowed value for this field.
  54. BYTE byHigh; // Highest allowed value for this field.
  55. HFONT hFont; // Handle to the logical Font
  56. } FIELD;
  57. typedef struct tagCONTROL {
  58. HWND hwndParent;
  59. UINT uiFieldWidth;
  60. UINT uiFillerWidth;
  61. BOOL fEnabled;
  62. BOOL fPainted;
  63. BOOL fAllowWildcards;
  64. BOOL fReadOnly;
  65. BOOL fInMessageBox; // Set when a message box is displayed so that
  66. // we don't send a EN_KILLFOCUS message when
  67. // we receive the EN_KILLFOCUS message for the
  68. // current field.
  69. BOOL fModified ; // Indicates whether field has changed
  70. FIELD Children[NUM_FIELDS];
  71. } CONTROL;
  72. // The following macros extract and store the CONTROL structure for a control.
  73. #define IPADDRESS_EXTRA (2 * sizeof(LONG_PTR))
  74. #define GET_CONTROL_HANDLE(hWnd) ((HGLOBAL)(GetWindowLongPtr((hWnd), GWLP_USERDATA)))
  75. #define SAVE_CONTROL_HANDLE(hWnd,x) (SetWindowLongPtr((hWnd), GWLP_USERDATA, (LONG_PTR)x))
  76. #define IPADDR_GET_SUBSTYLE(hwnd) (GetWindowLongPtr((hwnd), sizeof(LONG_PTR) * 1))
  77. #define IPADDR_SET_SUBSTYLE(hwnd, style) (SetWindowLongPtr((hwnd), sizeof(LONG_PTR) * 1, (style)))
  78. /* internal IPAddress function prototypes */
  79. #ifdef IP_CUST_CTRL
  80. BOOL FAR WINAPI IPAddressDlgFn( HWND, WORD, WORD, LONG );
  81. void GetStyleBit(HWND, LPCTLSTYLE, int, DWORD);
  82. #endif
  83. LRESULT FAR WINAPI IPAddressWndFn( HWND, UINT, WPARAM, LPARAM );
  84. LRESULT FAR WINAPI IPAddressFieldProc(HWND, UINT, WPARAM, LPARAM);
  85. BOOL SwitchFields(CONTROL FAR *, int, int, WORD, WORD);
  86. void EnterField(FIELD FAR *, WORD, WORD);
  87. BOOL ExitField(CONTROL FAR *, int iField);
  88. int GetFieldValue(FIELD FAR *);
  89. int FAR CDECL IPAlertPrintf(HWND hwndParent, UINT ids, int iCurrent, int iLow, int iHigh);
  90. BOOL IPLoadOem(HINSTANCE hInst, UINT idResource, TCHAR* lpszBuffer, int cbBuffer);
  91. /*
  92. LibMain() - Called once before anything else.
  93. call
  94. hInstance = library instance handle
  95. wDataSegment = library data segment
  96. wHeapSize = default heap size
  97. lpszCmdLine = command line arguements
  98. When this file is compiled as a DLL, this function is called by Libentry()
  99. when the library is first loaded. See the SDK docs for details.
  100. */
  101. #ifdef IPDLL
  102. /*
  103. //DLL_BASED BOOL WINAPI IpAddrDllEntry (
  104. DLL_BASED BOOL WINAPI DllMain (
  105. HINSTANCE hDll,
  106. DWORD dwReason,
  107. LPVOID lpReserved
  108. )
  109. {
  110. BOOL bResult = TRUE ;
  111. switch ( dwReason )
  112. {
  113. case DLL_PROCESS_ATTACH:
  114. bResult = IPAddrInit( hDll ) ;
  115. break ;
  116. case DLL_THREAD_ATTACH:
  117. break ;
  118. case DLL_PROCESS_DETACH:
  119. break ;
  120. case DLL_THREAD_DETACH:
  121. break ;
  122. }
  123. return bResult ;
  124. }
  125. */
  126. #endif
  127. #ifdef FE_SB
  128. BYTE
  129. CodePageToCharSet(
  130. UINT CodePage
  131. )
  132. {
  133. CHARSETINFO csi;
  134. if (!TranslateCharsetInfo((DWORD *)ULongToPtr(CodePage), &csi, TCI_SRCCODEPAGE))
  135. csi.ciCharset = OEM_CHARSET;
  136. return (BYTE)csi.ciCharset;
  137. }
  138. #endif // FE_SB
  139. LOGFONT logfont;
  140. void SetDefaultFont( )
  141. {
  142. LANGID langid = PRIMARYLANGID(GetThreadLocale());
  143. BOOL fIsDbcs = (langid == LANG_CHINESE ||
  144. langid == LANG_JAPANESE ||
  145. langid == LANG_KOREAN);
  146. logfont.lfWidth = 0;
  147. logfont.lfEscapement = 0;
  148. logfont.lfOrientation = 0;
  149. logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  150. logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  151. logfont.lfQuality = DEFAULT_QUALITY;
  152. logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
  153. logfont.lfUnderline = 0;
  154. logfont.lfStrikeOut = 0;
  155. logfont.lfItalic = 0;
  156. logfont.lfWeight = FW_NORMAL;
  157. HDC hDC = GetDC(NULL);
  158. if (hDC)
  159. {
  160. if (fIsDbcs)
  161. {
  162. logfont.lfHeight = -(9*GetDeviceCaps(hDC,LOGPIXELSY)/72);
  163. logfont.lfCharSet = DEFAULT_CHARSET;
  164. }
  165. else
  166. {
  167. logfont.lfHeight = -(8*GetDeviceCaps(hDC,LOGPIXELSY)/72);
  168. logfont.lfCharSet = ANSI_CHARSET;
  169. }
  170. // logfont.lfHeight = -(8*GetDeviceCaps(GetDC(NULL),LOGPIXELSY)/72);
  171. //fdef FE_SB
  172. // logfont.lfCharSet = CodePageToCharSet( GetACP() );
  173. //lse
  174. // logfont.lfCharSet = ANSI_CHARSET;
  175. //ndif
  176. lstrcpy(logfont.lfFaceName, TEXT("MS Shell Dlg"));
  177. ReleaseDC(NULL, hDC);
  178. }
  179. }
  180. /*
  181. IPAddrInit() - IPAddress custom control initialization
  182. call
  183. hInstance = library or application instance
  184. return
  185. TRUE on success, FALSE on failure.
  186. This function does all the one time initialization of IPAddress custom
  187. controls. Specifically it creates the IPAddress window class.
  188. */
  189. DLL_BASED int FAR WINAPI IPAddrInit(HINSTANCE hInstance)
  190. {
  191. HGLOBAL hClassStruct;
  192. LPWNDCLASS lpClassStruct;
  193. /* register IPAddress window if necessary */
  194. if ( s_hLibInstance == NULL ) {
  195. /* allocate memory for class structure */
  196. hClassStruct = GlobalAlloc( GHND, (DWORD)sizeof(WNDCLASS) );
  197. if ( hClassStruct ) {
  198. /* lock it down */
  199. lpClassStruct = (LPWNDCLASS)GlobalLock( hClassStruct );
  200. if ( lpClassStruct ) {
  201. /* define class attributes */
  202. lpClassStruct->lpszClassName = IPADDRESS_CLASS;
  203. lpClassStruct->hCursor = LoadCursor(NULL,IDC_IBEAM);
  204. lpClassStruct->lpszMenuName = (LPCTSTR)NULL;
  205. lpClassStruct->style = CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS|CS_GLOBALCLASS;
  206. lpClassStruct->lpfnWndProc = IPAddressWndFn;
  207. lpClassStruct->hInstance = hInstance;
  208. lpClassStruct->hIcon = NULL;
  209. lpClassStruct->cbWndExtra = IPADDRESS_EXTRA;
  210. lpClassStruct->hbrBackground = (HBRUSH)(COLOR_WINDOW + 1 );
  211. /* register IPAddress window class */
  212. s_hLibInstance = ( RegisterClass(lpClassStruct) ) ? hInstance : NULL;
  213. if (hInstance)
  214. {
  215. /* Load caption and out of memory string before we're
  216. out of memory. */
  217. if (!IPLoadOem(hInstance, IDS_IPNOMEM, szNoMem,
  218. sizeof(szNoMem) / sizeof(*szNoMem))
  219. || !IPLoadOem(hInstance, IDS_IPMBCAPTION, szCaption,
  220. sizeof(szCaption) / sizeof(*szCaption)))
  221. return FALSE;
  222. }
  223. GlobalUnlock( hClassStruct );
  224. }
  225. GlobalFree( hClassStruct );
  226. }
  227. }
  228. SetDefaultFont();
  229. return s_hLibInstance != NULL ;
  230. }
  231. // Use this function to force the ip address entered to
  232. // be contiguous (series of 1's followed by a series of 0's).
  233. // This is useful for entering valid submasks
  234. //
  235. // Returns NO_ERROR if successful, error code otherwise
  236. //
  237. DWORD APIENTRY IpAddr_ForceContiguous(HWND hwndIpAddr) {
  238. DWORD_PTR dwOldStyle;
  239. // Set the last error information so that we can
  240. // return an error correctly
  241. SetLastError(NO_ERROR);
  242. // Set the extended style of the given window so
  243. // that it descriminates the address entered.
  244. dwOldStyle = IPADDR_GET_SUBSTYLE(hwndIpAddr);
  245. IPADDR_SET_SUBSTYLE(hwndIpAddr, dwOldStyle | IPADDR_EX_STYLE_CONTIGUOUS);
  246. return GetLastError();
  247. }
  248. /*
  249. IPAddressInfo() - Returns various bits of information about the control.
  250. returns
  251. A handle for a CtlInfo structure.
  252. This function is only included in the DLL and is used by the dialog
  253. editor.
  254. */
  255. #ifdef IP_CUST_CTRL
  256. HANDLE FAR WINAPI IPAddressInfo()
  257. {
  258. HGLOBAL hCtlInfo;
  259. LPCTLINFO lpCtlInfo;
  260. /* allocate space for information structure */
  261. hCtlInfo = GlobalAlloc( GHND, (DWORD)sizeof(CTLINFO) );
  262. if ( hCtlInfo ) {
  263. /* attempt to lock it down */
  264. lpCtlInfo = (LPCTLINFO)GlobalLock( hCtlInfo );
  265. if ( lpCtlInfo ) {
  266. /* define the fixed portion of the structure */
  267. lpCtlInfo->wVersion = 100;
  268. lpCtlInfo->wCtlTypes = 1;
  269. lstrcpy( lpCtlInfo->szClass, IPADDRESS_CLASS );
  270. lstrcpy( lpCtlInfo->szTitle, TEXT("TCP/IP IP Address") );
  271. /* define the variable portion of the structure */
  272. lpCtlInfo->Type[0].wWidth = NUM_FIELDS*(CHARS_PER_FIELD+1) * 4 + 4;
  273. lpCtlInfo->Type[0].wHeight = 13;
  274. lpCtlInfo->Type[0].dwStyle = WS_CHILD | WS_TABSTOP;
  275. lstrcpy( lpCtlInfo->Type[0].szDescr, TEXT("IPAddress") );
  276. /* unlock it */
  277. GlobalUnlock( hCtlInfo );
  278. } else {
  279. GlobalFree( hCtlInfo );
  280. hCtlInfo = NULL;
  281. }
  282. }
  283. /* return result */
  284. return( hCtlInfo );
  285. }
  286. #endif
  287. /*
  288. IPAddressStyle()
  289. call
  290. hWnd handle of parent window
  291. hCtlStyle handle to control style info
  292. lpfnVerifyId pointer to the VerifyId function from dialog editor
  293. lpfnGetIDStr pointer to the GetIdStr function from dialog editor
  294. This function is called by the dialog editor when the user double clicks
  295. on the custom control. Or when the user chooses to edit the control's
  296. styles.
  297. */
  298. #ifdef IP_CUST_CTRL
  299. BOOL FAR WINAPI IPAddressStyle(
  300. HWND hWnd,
  301. HANDLE hCtlStyle,
  302. LPFNSTRTOID lpfnVerifyId,
  303. LPFNIDTOSTR lpfnGetIdStr )
  304. {
  305. FARPROC lpDlgFn;
  306. HANDLE hNewCtlStyle;
  307. // initialization
  308. hLibData = hCtlStyle;
  309. lpfnVerId = lpfnVerifyId;
  310. lpfnIdStr = lpfnGetIdStr;
  311. // display dialog box
  312. lpDlgFn = MakeProcInstance( (FARPROC)IPAddressDlgFn, s_hLibInstance );
  313. hNewCtlStyle = ( DialogBox(s_hLibInstance,TEXT("IPAddressStyle"),hWnd,lpDlgFn) ) ? hLibData : NULL;
  314. FreeProcInstance( lpDlgFn );
  315. // return updated data block
  316. return( hNewCtlStyle );
  317. }
  318. #endif
  319. /*
  320. IPAddressDlgFn() - Dialog editor style dialog
  321. hDlg styles dialog box handle
  322. wMessage window message
  323. wParam word parameter
  324. lParam long parameter
  325. This is the dialog function for the styles dialog that is displayed when
  326. the user wants to edit an IPAddress control's style from the dialog editor.
  327. */
  328. #ifdef IP_CUST_CTRL
  329. BOOL FAR WINAPI IPAddressDlgFn(
  330. HWND hDlg,
  331. WORD wMessage,
  332. WORD wParam,
  333. LONG lParam )
  334. {
  335. BOOL bResult;
  336. /* initialization */
  337. bResult = TRUE;
  338. /* process message */
  339. switch( wMessage )
  340. {
  341. case WM_INITDIALOG :
  342. {
  343. HANDLE hCtlStyle;
  344. LPCTLSTYLE lpCtlStyle;
  345. /* disable Ok button & save dialog data handle */
  346. hCtlStyle = hLibData;
  347. /* retrieve & display style parameters */
  348. if ( hCtlStyle ) {
  349. /* add handle to property list */
  350. SetProp( hDlg, MAKEINTRESOURCE(1), hCtlStyle );
  351. /* update dialog box fields */
  352. lpCtlStyle = (LPCTLSTYLE)GlobalLock( hCtlStyle );
  353. lstrcpy( lpCtlStyle->szClass, IPADDRESS_CLASS );
  354. SendDlgItemMessage(hDlg, ID_VISIBLE, BM_SETCHECK,
  355. (WPARAM)((lpCtlStyle->dwStyle & WS_VISIBLE) != 0), 0L);
  356. SendDlgItemMessage(hDlg, ID_GROUP, BM_SETCHECK,
  357. (WPARAM)((lpCtlStyle->dwStyle & WS_GROUP) != 0), 0L);
  358. SendDlgItemMessage(hDlg, ID_DISABLED, BM_SETCHECK,
  359. (WPARAM)((lpCtlStyle->dwStyle & WS_DISABLED) != 0), 0L);
  360. SendDlgItemMessage(hDlg, ID_TABSTOP, BM_SETCHECK,
  361. (WPARAM)((lpCtlStyle->dwStyle & WS_TABSTOP) != 0), 0L);
  362. GlobalUnlock( hCtlStyle );
  363. } else
  364. EndDialog( hDlg, FALSE );
  365. }
  366. break;
  367. case WM_COMMAND :
  368. switch( wParam )
  369. {
  370. case IDCANCEL:
  371. RemoveProp( hDlg, MAKEINTRESOURCE(1) );
  372. EndDialog( hDlg, FALSE );
  373. break;
  374. case IDOK:
  375. {
  376. HANDLE hCtlStyle;
  377. LPCTLSTYLE lpCtlStyle;
  378. hCtlStyle = GetProp( hDlg, MAKEINTRESOURCE(1) );
  379. lpCtlStyle = (LPCTLSTYLE)GlobalLock( hCtlStyle );
  380. GetStyleBit(hDlg, lpCtlStyle, ID_VISIBLE, WS_VISIBLE);
  381. GetStyleBit(hDlg, lpCtlStyle, ID_DISABLED, WS_DISABLED);
  382. GetStyleBit(hDlg, lpCtlStyle, ID_GROUP, WS_GROUP);
  383. GetStyleBit(hDlg, lpCtlStyle, ID_TABSTOP, WS_TABSTOP);
  384. GlobalUnlock( hCtlStyle );
  385. RemoveProp( hDlg, MAKEINTRESOURCE(1) );
  386. hLibData = hCtlStyle;
  387. EndDialog( hDlg, TRUE );
  388. }
  389. break;
  390. default :
  391. bResult = FALSE;
  392. break;
  393. }
  394. break;
  395. default :
  396. bResult = FALSE;
  397. break;
  398. }
  399. return( bResult );
  400. }
  401. #endif
  402. /*
  403. Get the value of a check box and set the appropriate style bit.
  404. */
  405. #ifdef IP_CUST_CTRL
  406. void GetStyleBit(HWND hDlg, LPCTLSTYLE lpCtlStyle, int iControl, DWORD dwStyle)
  407. {
  408. if (SendDlgItemMessage(hDlg, iControl, BM_GETSTATE, 0, 0L))
  409. lpCtlStyle->dwStyle |= dwStyle;
  410. else
  411. lpCtlStyle->dwStyle &= ~dwStyle;
  412. }
  413. #endif
  414. /*
  415. IPAddressFlags()
  416. call
  417. wFlags class style flags
  418. lpszString class style string
  419. wMaxString maximum size of class style string
  420. This function translates the class style flags provided into a
  421. corresponding text string for output to an RC file. The general
  422. windows flags (contained in the low byte) are not interpreted,
  423. only those in the high byte.
  424. The value returned by this function is the library instance
  425. handle when sucessful, and NULL otherwise.
  426. */
  427. #ifdef IP_CUST_CTRL
  428. WORD FAR WINAPI IPAddressFlags(
  429. WORD wFlags,
  430. LPSTR lpszString,
  431. WORD wMaxString )
  432. {
  433. lpszString[0] = NULL;
  434. return( 0 );
  435. }
  436. #endif
  437. // This function causes the ip address entered into hwndIpAddr to be
  438. // corrected so that it is contiguous.
  439. DWORD IpAddrMakeContiguous(HWND hwndIpAddr) {
  440. DWORD i, dwNewMask, dwMask;
  441. // Read in the current address
  442. SendMessage(hwndIpAddr, IP_GETADDRESS, 0, (LPARAM)&dwMask);
  443. // Find out where the first '1' is in binary going right to left
  444. dwNewMask = 0;
  445. for (i = 0; i < sizeof(dwMask)*8; i++) {
  446. dwNewMask |= 1 << i;
  447. if (dwNewMask & dwMask) {
  448. break;
  449. }
  450. }
  451. // At this point, dwNewMask is 000...0111... If we inverse it,
  452. // we get a mask that can be or'd with dwMask to fill in all of
  453. // the holes.
  454. dwNewMask = dwMask | ~dwNewMask;
  455. // If the new mask is different, correct it here
  456. if (dwMask != dwNewMask) {
  457. // WCHAR pszAddr[32];
  458. // wsprintfW(pszAddr, L"%d.%d.%d.%d", FIRST_IPADDRESS (dwNewMask),
  459. // SECOND_IPADDRESS(dwNewMask),
  460. // THIRD_IPADDRESS (dwNewMask),
  461. // FOURTH_IPADDRESS(dwNewMask));
  462. SendMessage(hwndIpAddr, IP_SETADDRESS, 0, (LPARAM) dwNewMask);
  463. // SendMessage(hwndIpAddr, IP_SETADDRESS, 0, (LPARAM)pszAddr);
  464. }
  465. return NO_ERROR;
  466. }
  467. /*
  468. IPAddressWndFn() - Main window function for an IPAddress control.
  469. call
  470. hWnd handle to IPAddress window
  471. wMsg message number
  472. wParam word parameter
  473. lParam long parameter
  474. */
  475. LRESULT FAR WINAPI IPAddressWndFn( HWND hWnd,
  476. UINT wMsg,
  477. WPARAM wParam,
  478. LPARAM lParam )
  479. {
  480. LONG_PTR lResult;
  481. HGLOBAL hControl;
  482. CONTROL *pControl;
  483. int i;
  484. lResult = TRUE;
  485. switch( wMsg )
  486. {
  487. case WM_SETTEXT:
  488. {
  489. static TCHAR szBuf[CHARS_PER_FIELD+1];
  490. DWORD dwValue[4];
  491. int nField, nPos;
  492. BOOL fFinish = FALSE;
  493. TCHAR *pszString = (TCHAR*)lParam;
  494. dwValue[0]=0;
  495. dwValue[1]=0;
  496. dwValue[2]=0;
  497. dwValue[3]=0;
  498. for( nField = 0, nPos = 0; !fFinish; nPos++)
  499. {
  500. if (( pszString[nPos]<TEXT('0')) || (pszString[nPos]>TEXT('9')))
  501. {
  502. // not a number
  503. nField++;
  504. fFinish = (nField == 4);
  505. }
  506. else
  507. {
  508. dwValue[nField] *= 10;
  509. dwValue[nField] += (pszString[nPos]-TEXT('0'));
  510. }
  511. }
  512. hControl = GET_CONTROL_HANDLE(hWnd);
  513. pControl = (CONTROL *)GlobalLock(hControl);
  514. for (i = 0; i < NUM_FIELDS; ++i)
  515. {
  516. if ( lstrcmp(pszString, TEXT("")) == 0 )
  517. {
  518. wsprintf(szBuf,TEXT(""));
  519. }
  520. else
  521. {
  522. wsprintf(szBuf, TEXT("%d"), dwValue[i]);
  523. }
  524. SendMessage(pControl->Children[i].hWnd, WM_SETTEXT,
  525. 0, (LPARAM) (LPSTR) szBuf);
  526. }
  527. GlobalUnlock(hControl);
  528. }
  529. break;
  530. case WM_GETTEXTLENGTH:
  531. case WM_GETTEXT:
  532. {
  533. int iFieldValue;
  534. int srcPos, desPos;
  535. DWORD dwValue[4];
  536. TCHAR pszResult[30];
  537. TCHAR *pszDest = (TCHAR *)lParam;
  538. hControl = GET_CONTROL_HANDLE(hWnd);
  539. pControl = (CONTROL *)GlobalLock(hControl);
  540. lResult = 0;
  541. dwValue[0] = 0;
  542. dwValue[1] = 0;
  543. dwValue[2] = 0;
  544. dwValue[3] = 0;
  545. for (i = 0; i < NUM_FIELDS; ++i)
  546. {
  547. iFieldValue = GetFieldValue(&(pControl->Children[i]));
  548. if (iFieldValue == -1)
  549. iFieldValue = 0;
  550. else
  551. ++lResult;
  552. dwValue[i] = iFieldValue;
  553. }
  554. wsprintf( pszResult, TEXT("%d.%d.%d.%d"), dwValue[0], dwValue[1], dwValue[2], dwValue[3] );
  555. if ( wMsg == WM_GETTEXTLENGTH )
  556. {
  557. lResult = lstrlen( pszResult );
  558. }
  559. else
  560. {
  561. for ( srcPos=0, desPos=0; (srcPos+1<(INT)wParam) && (pszResult[srcPos]!=TEXT('\0')); )
  562. {
  563. pszDest[desPos++] = pszResult[srcPos++];
  564. }
  565. pszDest[desPos]=TEXT('\0');
  566. lResult = desPos;
  567. }
  568. GlobalUnlock(hControl);
  569. }
  570. break;
  571. case WM_GETDLGCODE :
  572. lResult = DLGC_WANTCHARS;
  573. break;
  574. case WM_CREATE : /* create pallette window */
  575. {
  576. HDC hdc;
  577. UINT uiFieldStart;
  578. FARPROC lpfnFieldProc;
  579. hControl = GlobalAlloc(GMEM_MOVEABLE, sizeof(CONTROL));
  580. if (hControl)
  581. {
  582. HFONT OldFont;
  583. RECT rectClient;
  584. #define LPCS ((CREATESTRUCT *)lParam)
  585. pControl = (CONTROL *)GlobalLock(hControl);
  586. pControl->fEnabled = TRUE;
  587. pControl->fPainted = FALSE;
  588. pControl->fModified = FALSE ;
  589. pControl->fInMessageBox = FALSE;
  590. pControl->hwndParent = LPCS->hwndParent;
  591. pControl->fAllowWildcards = (LPCS->style & IPS_ALLOWWILDCARDS);
  592. pControl->fReadOnly = (LPCS->style & IPS_READONLY);
  593. hdc = GetDC(hWnd);
  594. if (hdc)
  595. {
  596. OldFont = (HFONT) SelectObject( hdc, CreateFontIndirect(&logfont) );
  597. GetCharWidth(hdc, FILLER, FILLER,
  598. (int *)(&pControl->uiFillerWidth));
  599. HGDIOBJ hObj = SelectObject(hdc, OldFont );
  600. if (hObj)
  601. DeleteObject( hObj );
  602. ReleaseDC(hWnd, hdc);
  603. // we need to calculate this with the client rect
  604. // because we may have a 3d look and feel which makes
  605. // the client area smaller than the window
  606. GetClientRect(hWnd, &rectClient);
  607. pControl->uiFieldWidth = (rectClient.right - rectClient.left
  608. - LEAD_ROOM
  609. - pControl->uiFillerWidth
  610. *(NUM_FIELDS-1))
  611. / NUM_FIELDS;
  612. uiFieldStart = LEAD_ROOM;
  613. lpfnFieldProc = MakeProcInstance((FARPROC)IPAddressFieldProc,
  614. LPCS->hInstance);
  615. for (i = 0; i < NUM_FIELDS; ++i)
  616. {
  617. pControl->Children[i].byLow = MIN_FIELD_VALUE;
  618. pControl->Children[i].byHigh = MAX_FIELD_VALUE;
  619. pControl->Children[i].hWnd = CreateWindow(
  620. TEXT("Edit"),
  621. NULL,
  622. WS_CHILD | WS_VISIBLE |
  623. /*ES_MULTILINE |*/ ES_CENTER,
  624. uiFieldStart,
  625. HEAD_ROOM,
  626. pControl->uiFieldWidth,
  627. rectClient.bottom - rectClient.top - (HEAD_ROOM*2),
  628. hWnd,
  629. (HMENU)ULongToPtr(i),
  630. LPCS->hInstance,
  631. (LPVOID)ULongToPtr(NULL));
  632. SendMessage(pControl->Children[i].hWnd, EM_LIMITTEXT,
  633. CHARS_PER_FIELD, 0L);
  634. pControl->Children[i].hFont = CreateFontIndirect(&logfont);
  635. SendMessage(pControl->Children[i].hWnd, WM_SETFONT,
  636. (WPARAM)pControl->Children[i].hFont, TRUE);
  637. pControl->Children[i].lpfnWndProc =
  638. (WNDPROC)GetWindowLongPtr(pControl->Children[i].hWnd,
  639. GWLP_WNDPROC);
  640. SetWindowLongPtr(pControl->Children[i].hWnd,
  641. GWLP_WNDPROC, (LPARAM)lpfnFieldProc);
  642. uiFieldStart += pControl->uiFieldWidth
  643. + pControl->uiFillerWidth;
  644. }
  645. #undef LPCS
  646. }
  647. GlobalUnlock(hControl);
  648. SAVE_CONTROL_HANDLE(hWnd, hControl);
  649. }
  650. else
  651. DestroyWindow(hWnd);
  652. }
  653. lResult = 0;
  654. break;
  655. case WM_PAINT: /* paint control window */
  656. {
  657. PAINTSTRUCT Ps;
  658. RECT rect;
  659. UINT uiFieldStart;
  660. COLORREF TextColor;
  661. HFONT OldFont;
  662. HBRUSH hBrush;
  663. HBRUSH hOldBrush;
  664. BeginPaint(hWnd, (LPPAINTSTRUCT)&Ps);
  665. OldFont = (HFONT) SelectObject( Ps.hdc, CreateFontIndirect(&logfont));
  666. GetClientRect(hWnd, &rect);
  667. hControl = GET_CONTROL_HANDLE(hWnd);
  668. pControl = (CONTROL *)GlobalLock(hControl);
  669. // paint the background depending upon if the control is enabled
  670. if (pControl->fEnabled)
  671. hBrush = CreateSolidBrush( GetSysColor( COLOR_WINDOW ));
  672. else
  673. hBrush = CreateSolidBrush( GetSysColor( COLOR_BTNFACE ));
  674. hOldBrush = (HBRUSH) SelectObject( Ps.hdc, hBrush );
  675. if (!(GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_CLIENTEDGE))
  676. Rectangle(Ps.hdc, 0, 0, rect.right, rect.bottom);
  677. else
  678. FillRect(Ps.hdc, &rect, hBrush);
  679. HGDIOBJ hObj = SelectObject( Ps.hdc, hOldBrush );
  680. if (hObj)
  681. DeleteObject( hObj );
  682. // now set the text color
  683. if (pControl->fEnabled)
  684. TextColor = GetSysColor(COLOR_WINDOWTEXT);
  685. else
  686. TextColor = GetSysColor(COLOR_GRAYTEXT);
  687. if (TextColor)
  688. SetTextColor(Ps.hdc, TextColor);
  689. // and the background color
  690. if (pControl->fEnabled)
  691. SetBkColor(Ps.hdc, GetSysColor(COLOR_WINDOW));
  692. else
  693. SetBkColor(Ps.hdc, GetSysColor(COLOR_BTNFACE));
  694. uiFieldStart = pControl->uiFieldWidth + LEAD_ROOM;
  695. for (i = 0; i < NUM_FIELDS-1; ++i)
  696. {
  697. TextOut(Ps.hdc, uiFieldStart, HEAD_ROOM, SZFILLER, 1);
  698. uiFieldStart +=pControl->uiFieldWidth + pControl->uiFillerWidth;
  699. }
  700. pControl->fPainted = TRUE;
  701. GlobalUnlock(hControl);
  702. DeleteObject(SelectObject(Ps.hdc, OldFont));
  703. EndPaint(hWnd, &Ps);
  704. }
  705. break;
  706. case WM_SETFOCUS : /* get focus - display caret */
  707. hControl = GET_CONTROL_HANDLE(hWnd);
  708. pControl = (CONTROL *)GlobalLock(hControl);
  709. EnterField(&(pControl->Children[0]), 0, CHARS_PER_FIELD);
  710. GlobalUnlock(hControl);
  711. break;
  712. case WM_LBUTTONDOWN : /* left button depressed - fall through */
  713. SetFocus(hWnd);
  714. break;
  715. case WM_ENABLE:
  716. {
  717. hControl = GET_CONTROL_HANDLE(hWnd);
  718. pControl = (CONTROL *)GlobalLock(hControl);
  719. pControl->fEnabled = (BOOL)wParam;
  720. for (i = 0; i < NUM_FIELDS; ++i)
  721. {
  722. EnableWindow(pControl->Children[i].hWnd, (BOOL)wParam);
  723. }
  724. EnableWindow(hWnd, (BOOL) wParam);
  725. if (pControl->fPainted) InvalidateRect(hWnd, NULL, FALSE);
  726. GlobalUnlock(hControl);
  727. }
  728. break;
  729. case WM_DESTROY :
  730. hControl = GET_CONTROL_HANDLE(hWnd);
  731. if (!hControl)
  732. break;
  733. pControl = (CONTROL *)GlobalLock(hControl);
  734. // Restore all the child window procedures before we delete our memory block.
  735. for (i = 0; i < NUM_FIELDS; ++i)
  736. {
  737. SetWindowLongPtr(pControl->Children[i].hWnd, GWLP_WNDPROC,
  738. (LPARAM)pControl->Children[i].lpfnWndProc);
  739. DeleteObject(pControl->Children[i].hFont);
  740. }
  741. GlobalUnlock(hControl);
  742. GlobalFree(hControl);
  743. SAVE_CONTROL_HANDLE(hWnd, NULL);
  744. break;
  745. case WM_COMMAND:
  746. switch (HIWORD(wParam))
  747. {
  748. // One of the fields lost the focus, see if it lost the focus to another field
  749. // of if we've lost the focus altogether. If its lost altogether, we must send
  750. // an EN_KILLFOCUS notification on up the ladder.
  751. case EN_KILLFOCUS:
  752. {
  753. HWND hFocus;
  754. hControl = GET_CONTROL_HANDLE(hWnd);
  755. pControl = (CONTROL *)GlobalLock(hControl);
  756. if (!pControl->fInMessageBox)
  757. {
  758. hFocus = GetFocus();
  759. for (i = 0; i < NUM_FIELDS; ++i)
  760. if (pControl->Children[i].hWnd == hFocus)
  761. break;
  762. if (i >= NUM_FIELDS)
  763. {
  764. // Before sending the address up the
  765. // ladder, make sure that the ip
  766. // address is contiguous, if needed
  767. if (IPADDR_GET_SUBSTYLE(hWnd) &
  768. IPADDR_EX_STYLE_CONTIGUOUS)
  769. IpAddrMakeContiguous(hWnd);
  770. SendMessage(pControl->hwndParent, WM_COMMAND,
  771. MAKEWPARAM(GetWindowLongPtr(hWnd, GWLP_ID),
  772. EN_KILLFOCUS), (LPARAM)hWnd);
  773. }
  774. }
  775. GlobalUnlock(hControl);
  776. }
  777. break;
  778. case EN_CHANGE:
  779. hControl = GET_CONTROL_HANDLE(hWnd);
  780. pControl = (CONTROL *)GlobalLock(hControl);
  781. SendMessage(pControl->hwndParent, WM_COMMAND,
  782. MAKEWPARAM(GetWindowLongPtr(hWnd, GWLP_ID), EN_CHANGE), (LPARAM)hWnd);
  783. GlobalUnlock(hControl);
  784. break;
  785. }
  786. break;
  787. // Get the value of the IP Address. The address is placed in the DWORD pointed
  788. // to by lParam and the number of non-blank fields is returned.
  789. case IP_GETADDRESS:
  790. {
  791. int iFieldValue;
  792. DWORD dwValue;
  793. hControl = GET_CONTROL_HANDLE(hWnd);
  794. pControl = (CONTROL *)GlobalLock(hControl);
  795. lResult = 0;
  796. dwValue = 0;
  797. for (i = 0; i < NUM_FIELDS; ++i)
  798. {
  799. iFieldValue = GetFieldValue(&(pControl->Children[i]));
  800. if (iFieldValue == -1)
  801. iFieldValue = 0;
  802. else
  803. ++lResult;
  804. dwValue = (dwValue << 8) + iFieldValue;
  805. }
  806. *((DWORD *)lParam) = dwValue;
  807. GlobalUnlock(hControl);
  808. }
  809. break;
  810. case IP_GETMASK:
  811. {
  812. TCHAR szBuf[CHARS_PER_FIELD+1];
  813. WORD wLength;
  814. lResult = 0;
  815. hControl = GET_CONTROL_HANDLE(hWnd);
  816. pControl = (CONTROL *)GlobalLock(hControl);
  817. for (i = 0; i < NUM_FIELDS; ++i)
  818. {
  819. *(WORD *)szBuf = (sizeof(szBuf) / sizeof(*szBuf)) - 1;
  820. wLength = (WORD)SendMessage(pControl->Children[i].hWnd,
  821. EM_GETLINE,0, (LPARAM) szBuf);
  822. szBuf[wLength] = TEXT('\0');
  823. if (!lstrcmp(szBuf, SZWILDCARD))
  824. {
  825. lResult |= 1L<<i;
  826. }
  827. }
  828. GlobalUnlock(hControl);
  829. }
  830. break;
  831. case IP_GETMODIFY:
  832. {
  833. hControl = GET_CONTROL_HANDLE(hWnd);
  834. if ( ! hControl )
  835. break ;
  836. pControl = (CONTROL *)GlobalLock(hControl);
  837. lResult = pControl->fModified > 0 ;
  838. for (i = 0 ; i < NUM_FIELDS ; )
  839. {
  840. lResult |= SendMessage( pControl->Children[i++].hWnd, EM_GETMODIFY, 0, 0 ) > 0 ;
  841. }
  842. GlobalUnlock(hControl);
  843. }
  844. break ;
  845. case IP_SETMODIFY:
  846. {
  847. hControl = GET_CONTROL_HANDLE(hWnd);
  848. if ( ! hControl )
  849. break ;
  850. pControl = (CONTROL *)GlobalLock(hControl);
  851. pControl->fModified = wParam > 0 ;
  852. for (i = 0 ; i < NUM_FIELDS ; )
  853. {
  854. SendMessage( pControl->Children[i++].hWnd, EM_GETMODIFY, wParam, 0 ) ;
  855. }
  856. GlobalUnlock(hControl);
  857. }
  858. break ;
  859. // Clear all fields to blanks.
  860. case IP_CLEARADDRESS:
  861. {
  862. hControl = GET_CONTROL_HANDLE(hWnd);
  863. pControl = (CONTROL *)GlobalLock(hControl);
  864. for (i = 0; i < NUM_FIELDS; ++i)
  865. {
  866. SendMessage(pControl->Children[i].hWnd, WM_SETTEXT,
  867. 0, (LPARAM) (LPSTR) TEXT(""));
  868. }
  869. GlobalUnlock(hControl);
  870. }
  871. break;
  872. // Set the value of the IP Address. The address is in the lParam with the
  873. // first address byte being the high byte, the second being the second byte,
  874. // and so on. A lParam value of -1 removes the address.
  875. case IP_SETADDRESS:
  876. {
  877. static TCHAR szBuf[CHARS_PER_FIELD+1];
  878. hControl = GET_CONTROL_HANDLE(hWnd);
  879. pControl = (CONTROL *)GlobalLock(hControl);
  880. for (i = 0; i < NUM_FIELDS; ++i)
  881. {
  882. wsprintf(szBuf, TEXT("%d"), HIBYTE(HIWORD(lParam)));
  883. SendMessage(pControl->Children[i].hWnd, WM_SETTEXT,
  884. 0, (LPARAM) (LPSTR) szBuf);
  885. lParam <<= 8;
  886. }
  887. GlobalUnlock(hControl);
  888. }
  889. break;
  890. case IP_SETREADONLY:
  891. {
  892. hControl = GET_CONTROL_HANDLE(hWnd);
  893. pControl = (CONTROL *)GlobalLock(hControl);
  894. pControl->fReadOnly = (wParam != 0);
  895. GlobalUnlock(hControl);
  896. }
  897. break;
  898. // Set a single field value. The wparam (0-3) indicates the field,
  899. // the lparam (0-255) indicates the value
  900. case IP_SETFIELD:
  901. {
  902. static TCHAR szBuf[CHARS_PER_FIELD+1] = TEXT("");
  903. hControl = GET_CONTROL_HANDLE(hWnd);
  904. pControl = (CONTROL *)GlobalLock(hControl);
  905. if (wParam < NUM_FIELDS)
  906. {
  907. if (lParam != -1)
  908. {
  909. wsprintf(szBuf, TEXT("%d"), HIBYTE(HIWORD(lParam)));
  910. }
  911. SendMessage(pControl->Children[wParam].hWnd, WM_SETTEXT,
  912. 0, (LPARAM) (LPSTR) szBuf);
  913. }
  914. GlobalUnlock(hControl);
  915. }
  916. break;
  917. case IP_SETMASK:
  918. {
  919. BYTE bMask = (BYTE)wParam;
  920. static TCHAR szBuf[CHARS_PER_FIELD+1];
  921. hControl = GET_CONTROL_HANDLE(hWnd);
  922. pControl = (CONTROL *)GlobalLock(hControl);
  923. for (i = 0; i < NUM_FIELDS; ++i)
  924. {
  925. if (bMask & 1<<i)
  926. {
  927. SendMessage(pControl->Children[i].hWnd, WM_SETTEXT,
  928. 0, (LPARAM)SZWILDCARD);
  929. }
  930. else
  931. {
  932. wsprintf(szBuf, TEXT("%d"), HIBYTE(HIWORD(lParam)));
  933. SendMessage(pControl->Children[i].hWnd, WM_SETTEXT,
  934. 0, (LPARAM) (LPSTR) szBuf);
  935. }
  936. lParam <<= 8;
  937. }
  938. GlobalUnlock(hControl);
  939. }
  940. break;
  941. case IP_SETRANGE:
  942. if (wParam < NUM_FIELDS)
  943. {
  944. hControl = GET_CONTROL_HANDLE(hWnd);
  945. pControl = (CONTROL *)GlobalLock(hControl);
  946. pControl->Children[wParam].byLow = LOBYTE(LOWORD(lParam));
  947. pControl->Children[wParam].byHigh = HIBYTE(LOWORD(lParam));
  948. GlobalUnlock(hControl);
  949. }
  950. break;
  951. // Set the focus to this control.
  952. // wParam = the field number to set focus to, or -1 to set the focus to the
  953. // first non-blank field.
  954. case IP_SETFOCUS:
  955. hControl = GET_CONTROL_HANDLE(hWnd);
  956. pControl = (CONTROL *)GlobalLock(hControl);
  957. if (wParam >= NUM_FIELDS)
  958. {
  959. for (wParam = 0; wParam < NUM_FIELDS; ++wParam)
  960. if (GetFieldValue(&(pControl->Children[wParam])) == -1)
  961. break;
  962. if (wParam >= NUM_FIELDS) wParam = 0;
  963. }
  964. //
  965. // 0, -1 select the entire control
  966. //
  967. EnterField(&(pControl->Children[wParam]), 0, (WORD)-1);
  968. GlobalUnlock(hControl);
  969. break;
  970. // Determine whether all four subfields are blank
  971. case IP_ISBLANK:
  972. hControl = GET_CONTROL_HANDLE(hWnd);
  973. pControl = (CONTROL *)GlobalLock(hControl);
  974. lResult = TRUE;
  975. for (i = 0; i < NUM_FIELDS; ++i)
  976. {
  977. if (GetFieldValue(&(pControl->Children[i])) != -1)
  978. {
  979. lResult = FALSE;
  980. break;
  981. }
  982. }
  983. GlobalUnlock(hControl);
  984. break;
  985. default:
  986. lResult = DefWindowProc( hWnd, wMsg, wParam, lParam );
  987. break;
  988. }
  989. return( lResult );
  990. }
  991. /*
  992. IPAddressFieldProc() - Edit field window procedure
  993. This function sub-classes each edit field.
  994. */
  995. LRESULT FAR WINAPI IPAddressFieldProc(HWND hWnd,
  996. UINT wMsg,
  997. WPARAM wParam,
  998. LPARAM lParam)
  999. {
  1000. HANDLE hControl;
  1001. CONTROL *pControl;
  1002. FIELD *pField;
  1003. HWND hControlWindow;
  1004. WORD wChildID;
  1005. LRESULT lresult;
  1006. if (!(hControlWindow = GetParent(hWnd)))
  1007. return 0;
  1008. hControl = GET_CONTROL_HANDLE(hControlWindow);
  1009. pControl = (CONTROL *)GlobalLock(hControl);
  1010. wChildID = (WORD) GetWindowLong(hWnd, GWL_ID);
  1011. pField = &(pControl->Children[wChildID]);
  1012. if (pField->hWnd != hWnd)
  1013. {
  1014. return 0;
  1015. }
  1016. switch (wMsg)
  1017. {
  1018. case WM_DESTROY:
  1019. DeleteObject( (HGDIOBJ) SendMessage( hWnd, WM_GETFONT, 0, 0 ));
  1020. return 0;
  1021. case WM_CHAR:
  1022. if (pControl->fReadOnly)
  1023. {
  1024. MessageBeep((UINT)-1);
  1025. GlobalUnlock( hControl );
  1026. return 0;
  1027. }
  1028. // Typing in the last digit in a field, skips to the next field.
  1029. if (wParam >= TEXT('0') && wParam <= TEXT('9'))
  1030. {
  1031. DWORD_PTR dwResult;
  1032. pControl->fModified = TRUE ;
  1033. dwResult = CallWindowProc(pControl->Children[wChildID].lpfnWndProc,
  1034. hWnd, wMsg, wParam, lParam);
  1035. dwResult = SendMessage(hWnd, EM_GETSEL, 0, 0L);
  1036. if (dwResult == MAKELPARAM(CHARS_PER_FIELD, CHARS_PER_FIELD)
  1037. && ExitField(pControl, wChildID)
  1038. && wChildID < NUM_FIELDS-1)
  1039. {
  1040. EnterField(&(pControl->Children[wChildID+1]),
  1041. 0, CHARS_PER_FIELD);
  1042. }
  1043. GlobalUnlock( hControl );
  1044. return dwResult;
  1045. }
  1046. // spaces and periods fills out the current field and then if possible,
  1047. // goes to the next field.
  1048. else if (wParam == FILLER || wParam == SPACE )
  1049. {
  1050. DWORD_PTR dwResult;
  1051. dwResult = SendMessage(hWnd, EM_GETSEL, 0, 0L);
  1052. if (dwResult != 0L && HIWORD(dwResult) == LOWORD(dwResult)
  1053. && ExitField(pControl, wChildID))
  1054. {
  1055. if (wChildID >= NUM_FIELDS-1)
  1056. MessageBeep((UINT)-1);
  1057. else
  1058. {
  1059. EnterField(&(pControl->Children[wChildID+1]),
  1060. 0, CHARS_PER_FIELD);
  1061. }
  1062. }
  1063. GlobalUnlock( hControl );
  1064. return 0;
  1065. }
  1066. // Backspaces go to the previous field if at the beginning of the current field.
  1067. // Also, if the focus shifts to the previous field, the backspace must be
  1068. // processed by that field.
  1069. else if (wParam == BACK_SPACE)
  1070. {
  1071. pControl->fModified = TRUE ;
  1072. if (wChildID > 0 && SendMessage(hWnd, EM_GETSEL, 0, 0L) == 0L)
  1073. {
  1074. if (SwitchFields(pControl, wChildID, wChildID-1,
  1075. CHARS_PER_FIELD, CHARS_PER_FIELD)
  1076. && SendMessage(pControl->Children[wChildID-1].hWnd,
  1077. EM_LINELENGTH, 0, 0L) != 0L)
  1078. {
  1079. SendMessage(pControl->Children[wChildID-1].hWnd,
  1080. wMsg, wParam, lParam);
  1081. }
  1082. GlobalUnlock( hControl );
  1083. return 0;
  1084. }
  1085. else
  1086. {
  1087. TCHAR szBuf[CHARS_PER_FIELD+1];
  1088. WORD wLength;
  1089. *(WORD *)szBuf = (sizeof(szBuf) / sizeof(*szBuf)) - 1;
  1090. wLength = (WORD)SendMessage(pControl->Children[wChildID].hWnd,
  1091. EM_GETLINE,0, (LPARAM) szBuf);
  1092. szBuf[wLength] = TEXT('\0');
  1093. if (!lstrcmp(szBuf, SZWILDCARD))
  1094. {
  1095. SendMessage(pControl->Children[wChildID].hWnd,
  1096. WM_SETTEXT, 0, (LPARAM)TEXT(""));
  1097. }
  1098. }
  1099. }
  1100. else if ((wParam == WILDCARD) && (pControl->fAllowWildcards))
  1101. {
  1102. // Only works at the beginning of the line.
  1103. if (SendMessage(hWnd, EM_GETSEL, 0, 0L) == 0L)
  1104. {
  1105. pControl->fModified = TRUE;
  1106. SendMessage(pControl->Children[wChildID].hWnd, WM_SETTEXT, 0, (LPARAM)SZWILDCARD);
  1107. if (ExitField(pControl, wChildID) && (wChildID < NUM_FIELDS-1))
  1108. {
  1109. EnterField(&(pControl->Children[wChildID+1]),0, CHARS_PER_FIELD);
  1110. }
  1111. }
  1112. else
  1113. {
  1114. // Not at the beginning of the line, complain
  1115. MessageBeep((UINT)-1);
  1116. }
  1117. GlobalUnlock( hControl );
  1118. return 0;
  1119. }
  1120. // Any other printable characters are not allowed.
  1121. else if (wParam > SPACE)
  1122. {
  1123. MessageBeep((UINT)-1);
  1124. GlobalUnlock( hControl );
  1125. return 0;
  1126. }
  1127. break;
  1128. case WM_KEYDOWN:
  1129. switch (wParam)
  1130. {
  1131. case VK_DELETE:
  1132. {
  1133. TCHAR szBuf[CHARS_PER_FIELD+1];
  1134. WORD wLength;
  1135. if (pControl->fReadOnly)
  1136. {
  1137. MessageBeep((UINT)-1);
  1138. GlobalUnlock( hControl );
  1139. return 0;
  1140. }
  1141. pControl->fModified = TRUE ;
  1142. *(WORD *)szBuf = (sizeof(szBuf) / sizeof(*szBuf)) - 1;
  1143. wLength = (WORD)SendMessage(pControl->Children[wChildID].hWnd,
  1144. EM_GETLINE,0, (LPARAM) szBuf);
  1145. szBuf[wLength] = TEXT('\0');
  1146. if (!lstrcmp(szBuf, SZWILDCARD))
  1147. {
  1148. SendMessage(pControl->Children[wChildID].hWnd,
  1149. WM_SETTEXT, 0, (LPARAM)TEXT(""));
  1150. GlobalUnlock( hControl );
  1151. return 0;
  1152. }
  1153. }
  1154. break;
  1155. // Arrow keys move between fields when the end of a field is reached.
  1156. case VK_LEFT:
  1157. case VK_RIGHT:
  1158. case VK_UP:
  1159. case VK_DOWN:
  1160. if (GetKeyState(VK_CONTROL) < 0)
  1161. {
  1162. if ((wParam == VK_LEFT || wParam == VK_UP) && wChildID > 0)
  1163. {
  1164. SwitchFields(pControl, wChildID, wChildID-1,
  1165. 0, CHARS_PER_FIELD);
  1166. GlobalUnlock( hControl );
  1167. return 0;
  1168. }
  1169. else if ((wParam == VK_RIGHT || wParam == VK_DOWN)
  1170. && wChildID < NUM_FIELDS-1)
  1171. {
  1172. SwitchFields(pControl, wChildID, wChildID+1,
  1173. 0, CHARS_PER_FIELD);
  1174. GlobalUnlock( hControl );
  1175. return 0;
  1176. }
  1177. }
  1178. else
  1179. {
  1180. DWORD_PTR dwResult;
  1181. WORD wStart, wEnd;
  1182. dwResult = SendMessage(hWnd, EM_GETSEL, 0, 0L);
  1183. wStart = LOWORD(dwResult);
  1184. wEnd = HIWORD(dwResult);
  1185. if (wStart == wEnd)
  1186. {
  1187. if ((wParam == VK_LEFT || wParam == VK_UP)
  1188. && wStart == 0
  1189. && wChildID > 0)
  1190. {
  1191. SwitchFields(pControl, wChildID, wChildID-1,
  1192. CHARS_PER_FIELD, CHARS_PER_FIELD);
  1193. GlobalUnlock( hControl );
  1194. return 0;
  1195. }
  1196. else if ((wParam == VK_RIGHT || wParam == VK_DOWN)
  1197. && wChildID < NUM_FIELDS-1)
  1198. {
  1199. dwResult = SendMessage(hWnd, EM_LINELENGTH, 0, 0L);
  1200. if (wStart >= dwResult)
  1201. {
  1202. SwitchFields(pControl, wChildID, wChildID+1, 0, 0);
  1203. GlobalUnlock( hControl );
  1204. return 0;
  1205. }
  1206. }
  1207. }
  1208. }
  1209. break;
  1210. // Home jumps back to the beginning of the first field.
  1211. case VK_HOME:
  1212. if (wChildID > 0)
  1213. {
  1214. SwitchFields(pControl, wChildID, 0, 0, 0);
  1215. GlobalUnlock( hControl );
  1216. return 0;
  1217. }
  1218. break;
  1219. // End scoots to the end of the last field.
  1220. case VK_END:
  1221. if (wChildID < NUM_FIELDS-1)
  1222. {
  1223. SwitchFields(pControl, wChildID, NUM_FIELDS-1,
  1224. CHARS_PER_FIELD, CHARS_PER_FIELD);
  1225. GlobalUnlock( hControl );
  1226. return 0;
  1227. }
  1228. break;
  1229. } // switch (wParam)
  1230. break;
  1231. case WM_KILLFOCUS:
  1232. if ( !ExitField( pControl, wChildID ))
  1233. {
  1234. GlobalUnlock( hControl );
  1235. return 0;
  1236. }
  1237. } // switch (wMsg)
  1238. lresult = CallWindowProc(pControl->Children[wChildID].lpfnWndProc,
  1239. hWnd, wMsg, wParam, lParam);
  1240. GlobalUnlock( hControl );
  1241. return lresult;
  1242. }
  1243. /*
  1244. Switch the focus from one field to another.
  1245. call
  1246. pControl = Pointer to the CONTROL structure.
  1247. iOld = Field we're leaving.
  1248. iNew = Field we're entering.
  1249. hNew = Window of field to goto
  1250. wStart = First character selected
  1251. wEnd = Last character selected + 1
  1252. returns
  1253. TRUE on success, FALSE on failure.
  1254. Only switches fields if the current field can be validated.
  1255. */
  1256. BOOL SwitchFields(CONTROL *pControl, int iOld, int iNew, WORD wStart, WORD wEnd)
  1257. {
  1258. if (!ExitField(pControl, iOld))
  1259. return FALSE;
  1260. EnterField(&(pControl->Children[iNew]), wStart, wEnd);
  1261. return TRUE;
  1262. }
  1263. /*
  1264. Set the focus to a specific field's window.
  1265. call
  1266. pField = pointer to field structure for the field.
  1267. wStart = First character selected
  1268. wEnd = Last character selected + 1
  1269. */
  1270. void EnterField(FIELD *pField, WORD wStart, WORD wEnd)
  1271. {
  1272. SetFocus(pField->hWnd);
  1273. SendMessage(pField->hWnd, EM_SETSEL, wStart, wEnd);
  1274. }
  1275. /*
  1276. Exit a field.
  1277. call
  1278. pControl = pointer to CONTROL structure.
  1279. iField = field number being exited.
  1280. returns
  1281. TRUE if the user may exit the field.
  1282. FALSE if he may not.
  1283. */
  1284. BOOL ExitField(CONTROL *pControl, int iField)
  1285. {
  1286. HWND hControlWnd;
  1287. HWND hDialog;
  1288. WORD wLength;
  1289. FIELD *pField;
  1290. static TCHAR szBuf[CHARS_PER_FIELD+1];
  1291. int i,j;
  1292. pField = &(pControl->Children[iField]);
  1293. *(WORD *)szBuf = (sizeof(szBuf) / sizeof(*szBuf)) - 1;
  1294. wLength = (WORD)SendMessage(pField->hWnd,EM_GETLINE,0,(LPARAM)(LPSTR)szBuf);
  1295. if (wLength != 0)
  1296. {
  1297. szBuf[wLength] = TEXT('\0');
  1298. if (pControl->fAllowWildcards && !lstrcmp(szBuf, SZWILDCARD))
  1299. {
  1300. return TRUE;
  1301. }
  1302. for (j=0,i=0;j<(INT)wLength;j++)
  1303. {
  1304. i=i*10+szBuf[j]-TEXT('0');
  1305. }
  1306. if (i < (int)(UINT)pField->byLow || i > (int)(UINT)pField->byHigh)
  1307. {
  1308. if ( i < (int)(UINT) pField->byLow )
  1309. {
  1310. /* too small */
  1311. wsprintf(szBuf, TEXT("%d"), (int)(UINT)pField->byLow );
  1312. }
  1313. else
  1314. {
  1315. /* must be bigger */
  1316. wsprintf(szBuf, TEXT("%d"), (int)(UINT)pField->byHigh );
  1317. }
  1318. SendMessage(pField->hWnd, WM_SETTEXT, 0, (LPARAM) (LPSTR) szBuf);
  1319. if ((hControlWnd = GetParent(pField->hWnd)) != NULL
  1320. && (hDialog = GetParent(hControlWnd)) != NULL)
  1321. {
  1322. pControl->fInMessageBox = TRUE;
  1323. IPAlertPrintf(hDialog, IDS_IPBAD_FIELD_VALUE, i,
  1324. pField->byLow, pField->byHigh);
  1325. pControl->fInMessageBox = FALSE;
  1326. SendMessage(pField->hWnd, EM_SETSEL, 0, CHARS_PER_FIELD);
  1327. return FALSE;
  1328. }
  1329. }
  1330. }
  1331. if ((hControlWnd = GetParent(pField->hWnd)))
  1332. {
  1333. if (IPADDR_GET_SUBSTYLE(hControlWnd) & IPADDR_EX_STYLE_CONTIGUOUS)
  1334. IpAddrMakeContiguous(hControlWnd);
  1335. }
  1336. return TRUE;
  1337. }
  1338. /*
  1339. Get the value stored in a field.
  1340. call
  1341. pField = pointer to the FIELD structure for the field.
  1342. returns
  1343. The value (0..255) or -1 if the field has not value.
  1344. */
  1345. int GetFieldValue(FIELD *pField)
  1346. {
  1347. WORD wLength;
  1348. static TCHAR szBuf[CHARS_PER_FIELD+1];
  1349. INT i,j;
  1350. //*(WORD *)szBuf = sizeof(szBuf) - 1;
  1351. //wLength = (WORD)SendMessage(pField->hWnd,EM_GETLINE,0,(DWORD)(LPSTR)szBuf);
  1352. wLength = (WORD)SendMessage(pField->hWnd,WM_GETTEXT,(sizeof(szBuf) / sizeof(*szBuf)),(LPARAM)(LPSTR)szBuf);
  1353. if (wLength != 0)
  1354. {
  1355. szBuf[wLength] = TEXT('\0');
  1356. if (!lstrcmp(szBuf, SZWILDCARD))
  1357. {
  1358. return 255;
  1359. }
  1360. for (j=0,i=0;j<(INT)wLength;j++)
  1361. {
  1362. i=i*10+szBuf[j]-TEXT('0');
  1363. }
  1364. return i;
  1365. }
  1366. else
  1367. return -1;
  1368. }
  1369. /*
  1370. IPAlertPrintf() - Does a printf to a message box.
  1371. */
  1372. int FAR CDECL IPAlertPrintf(HWND hwndParent, UINT ids, int iCurrent, int iLow, int iHigh)
  1373. {
  1374. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1375. // Is this large enough?
  1376. static TCHAR szBuf[MAX_IPRES*2];
  1377. static TCHAR szFormat[MAX_IPRES];
  1378. TCHAR * psz;
  1379. if (ids != IDS_IPNOMEM &&
  1380. //
  1381. // Why OEM?
  1382. //
  1383. //IPLoadOem(s_hLibInstance, ids, szFormat, sizeof(szFormat)))
  1384. LoadString(AfxGetResourceHandle(), ids, szFormat, sizeof(szFormat)/sizeof(*szFormat)))
  1385. {
  1386. wsprintf(szBuf, szFormat, iCurrent, iLow, iHigh);
  1387. psz = szBuf;
  1388. }
  1389. else
  1390. {
  1391. psz = szNoMem;
  1392. }
  1393. MessageBeep(MB_ICONEXCLAMATION);
  1394. return MessageBox(hwndParent, psz, szCaption, MB_ICONEXCLAMATION);
  1395. }
  1396. /*
  1397. Load an OEM string and convert it to ANSI.
  1398. call
  1399. hInst = This instance
  1400. idResource = The ID of the string to load
  1401. lpszBuffer = Pointer to buffer to load string into.
  1402. cbBuffer = Length of the buffer.
  1403. returns
  1404. TRUE if the string is loaded, FALSE if it is not.
  1405. */
  1406. BOOL IPLoadOem(HINSTANCE hInst, UINT idResource, TCHAR* lpszBuffer, int cbBuffer)
  1407. {
  1408. if (LoadString(hInst, idResource, lpszBuffer, cbBuffer))
  1409. {
  1410. //OemToAnsi(lpszBuffer, lpszBuffer);
  1411. return TRUE;
  1412. }
  1413. else
  1414. {
  1415. lpszBuffer[0] = 0;
  1416. return FALSE;
  1417. }
  1418. }
  1419. __declspec(dllexport) WCHAR * WINAPI
  1420. inet_ntoaw(
  1421. struct in_addr dwAddress
  1422. ) {
  1423. static WCHAR szAddress[16];
  1424. char* pAddr = inet_ntoa(*(struct in_addr *) &dwAddress);
  1425. if (pAddr)
  1426. {
  1427. // mbstowcs(szAddress, inet_ntoa(*(struct in_addr *)&dwAddress), 16);
  1428. MultiByteToWideChar(CP_ACP, 0, pAddr, -1, szAddress, 16);
  1429. return szAddress;
  1430. }
  1431. else
  1432. return NULL;
  1433. }
  1434. __declspec(dllexport) DWORD WINAPI
  1435. inet_addrw(
  1436. LPCWSTR szAddressW
  1437. ) {
  1438. CHAR szAddressA[16];
  1439. wcstombs(szAddressA, szAddressW, 16);
  1440. return inet_addr(szAddressA);
  1441. }