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.

2520 lines
63 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP.
  4. *
  5. * TITLE: CLASSED.C
  6. *
  7. * VERSION: 5.01
  8. *
  9. * AUTHOR: Tracy Sharpe
  10. *
  11. * DATE: 05 Mar 1994
  12. *
  13. * Binary edit dialog for use by the Registry Editor.
  14. *
  15. * Hexadecimal editor control for use by the Registry Editor. Little attempt
  16. * is made to make this a generic control-- only one instance is assumed to
  17. * ever exist.
  18. *
  19. * 02 Oct 1997 modified to work with the DHCP snapin
  20. *
  21. *******************************************************************************/
  22. #include <windows.h>
  23. #include <windowsx.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <mbstring.h>
  27. #include <tchar.h>
  28. #include "resource.h"
  29. #include "classed.h"
  30. #include "dhcpapi.h"
  31. #include "helparr.h"
  32. //
  33. // Following structure and data are used to move the controls of the
  34. // EditBinaryValue dialog so that the HexEdit control fills up the appropriate
  35. // amount of space based on the system metrics.
  36. //
  37. typedef struct _MOVEWND {
  38. int ControlID;
  39. UINT SetWindowPosFlags;
  40. } MOVEWND;
  41. const TCHAR s_HexEditClassName[] = HEXEDIT_CLASSNAME;
  42. const TCHAR s_HexEditClipboardFormatName[] = TEXT("RegEdit_HexData");
  43. const TCHAR s_HexWordFormatSpec[] = TEXT("%04X");
  44. const TCHAR s_HexByteFormatSpec[] = TEXT("%02X");
  45. COLORREF g_clrWindow;
  46. COLORREF g_clrWindowText;
  47. COLORREF g_clrHighlight;
  48. COLORREF g_clrHighlightText;
  49. PTSTR g_pHelpFileName;
  50. HINSTANCE g_hInstance;
  51. const MOVEWND s_EditBinaryValueMoveWnd[] = {
  52. IDOK, SWP_NOSIZE | SWP_NOZORDER,
  53. IDCANCEL, SWP_NOSIZE | SWP_NOZORDER,
  54. IDC_VALUENAME, SWP_NOMOVE | SWP_NOZORDER,
  55. IDC_VALUEDATA, SWP_NOMOVE | SWP_NOZORDER,
  56. IDC_VALUECOMMENT, SWP_NOMOVE | SWP_NOZORDER
  57. };
  58. // Number of bytes that are displayed per line. NOTE: Assumptions have been
  59. // made that this is power of two.
  60. #define BYTES_PER_HEXEDIT_LINE 8
  61. #define BYTES_PER_HEXEDIT_LINE_MASK 0x0007
  62. //
  63. // This font is used by the HexEdit window for all output. The lfHeight
  64. // member is calculated later based on the system configuration.
  65. //
  66. LOGFONT s_HexEditFont = {
  67. 0, // lfHeight
  68. 0, // lfWidth
  69. 0, // lfEscapement
  70. 0, // lfOrientation
  71. FW_NORMAL, // lfWeight
  72. FALSE, // lfItalic
  73. FALSE, // lfUnderline
  74. FALSE, // lfStrikeout
  75. ANSI_CHARSET, // lfCharSet
  76. OUT_DEFAULT_PRECIS, // lfOutPrecision
  77. CLIP_DEFAULT_PRECIS, // lfClipPrecision
  78. DEFAULT_QUALITY, // lfQuality
  79. FIXED_PITCH | FF_DONTCARE, // lfPitchAndFamily
  80. TEXT("Courier") // lfFaceName
  81. };
  82. // Set if window has input focus, clear if not.
  83. #define HEF_FOCUS 0x00000001
  84. #define HEF_NOFOCUS 0x00000000
  85. // Set if dragging a range with mouse, clear if not.
  86. #define HEF_DRAGGING 0x00000002
  87. #define HEF_NOTDRAGGING 0x00000000
  88. // Set if editing ASCII column, clear if editing hexadecimal column.
  89. #define HEF_CARETINASCIIDUMP 0x00000004
  90. #define HEF_CARETINHEXDUMP 0x00000000
  91. //
  92. #define HEF_INSERTATLOWNIBBLE 0x00000008
  93. #define HEF_INSERTATHIGHNIBBLE 0x00000000
  94. // Set if caret should be shown at the end of the previous line instead of at
  95. // the beginning of it's real caret line, clear if not.
  96. #define HEF_CARETATENDOFLINE 0x00000010
  97. HEXEDITDATA s_HexEditData;
  98. typedef struct _HEXEDITCLIPBOARDDATA {
  99. DWORD cbSize;
  100. BYTE Data[1];
  101. } HEXEDITCLIPBOARDDATA, *LPHEXEDITCLIPBOARDDATA;
  102. UINT s_HexEditClipboardFormat;
  103. BOOL
  104. PASCAL
  105. EditBinaryValue_OnInitDialog(
  106. HWND hWnd,
  107. HWND hFocusWnd,
  108. LPARAM lParam
  109. );
  110. LRESULT
  111. PASCAL
  112. HexEditWndProc(
  113. HWND hWnd,
  114. UINT Message,
  115. WPARAM wParam,
  116. LPARAM lParam
  117. );
  118. BOOL
  119. PASCAL
  120. HexEdit_OnNcCreate(
  121. HWND hWnd,
  122. LPCREATESTRUCT lpCreateStruct
  123. );
  124. VOID
  125. PASCAL
  126. HexEdit_OnSize(
  127. HWND hWnd,
  128. UINT State,
  129. int cx,
  130. int cy
  131. );
  132. VOID
  133. PASCAL
  134. HexEdit_SetScrollInfo(
  135. HWND hWnd
  136. );
  137. VOID
  138. PASCAL
  139. HexEdit_OnVScroll(
  140. HWND hWnd,
  141. HWND hCtlWnd,
  142. UINT Code,
  143. int Position
  144. );
  145. VOID
  146. PASCAL
  147. HexEdit_OnPaint(
  148. HWND hWnd
  149. );
  150. VOID
  151. PASCAL
  152. HexEdit_PaintRect(
  153. HWND hWnd,
  154. HDC hDC,
  155. LPRECT lpUpdateRect
  156. );
  157. VOID
  158. PASCAL
  159. HexEdit_OnSetFocus(
  160. HWND hWnd
  161. );
  162. VOID
  163. PASCAL
  164. HexEdit_OnKillFocus(
  165. HWND hWnd
  166. );
  167. VOID
  168. PASCAL
  169. HexEdit_OnLButtonDown(
  170. HWND hWnd,
  171. BOOL fDoubleClick,
  172. int x,
  173. int y,
  174. UINT KeyFlags
  175. );
  176. VOID
  177. PASCAL
  178. HexEdit_OnMouseMove(
  179. HWND hWnd,
  180. int x,
  181. int y,
  182. UINT KeyFlags
  183. );
  184. VOID
  185. PASCAL
  186. HexEdit_OnLButtonUp(
  187. HWND hWnd,
  188. int x,
  189. int y,
  190. UINT KeyFlags
  191. );
  192. int
  193. PASCAL
  194. HexEdit_HitTest(
  195. HEXEDITDATA * pHexEditData,
  196. int x,
  197. int y
  198. );
  199. VOID
  200. PASCAL
  201. HexEdit_OnKey(
  202. HWND hWnd,
  203. UINT VirtualKey,
  204. BOOL fDown,
  205. int cRepeat,
  206. UINT Flags
  207. );
  208. VOID
  209. PASCAL
  210. HexEdit_OnChar(
  211. HWND hWnd,
  212. TCHAR Char,
  213. int cRepeat
  214. );
  215. VOID
  216. PASCAL
  217. HexEdit_SetCaretPosition(
  218. HWND hWnd
  219. );
  220. VOID
  221. PASCAL
  222. HexEdit_EnsureCaretVisible(
  223. HWND hWnd
  224. );
  225. VOID
  226. PASCAL
  227. HexEdit_ChangeCaretIndex(
  228. HWND hWnd,
  229. int NewCaretIndex,
  230. BOOL fExtendSelection
  231. );
  232. VOID
  233. PASCAL
  234. HexEdit_DeleteRange(
  235. HWND hWnd,
  236. UINT SourceKey
  237. );
  238. BOOL
  239. PASCAL
  240. HexEdit_OnCopy(
  241. HWND hWnd
  242. );
  243. BOOL
  244. PASCAL
  245. HexEdit_OnPaste(
  246. HWND hWnd
  247. );
  248. VOID
  249. PASCAL
  250. HexEdit_OnContextMenu(
  251. HWND hWnd,
  252. int x,
  253. int y
  254. );
  255. /*******************************************************************************
  256. *
  257. * EditBinaryValueDlgProc
  258. *
  259. * DESCRIPTION:
  260. *
  261. * PARAMETERS:
  262. *
  263. *******************************************************************************/
  264. BOOL
  265. CALLBACK
  266. EditBinaryValueDlgProc(
  267. HWND hWnd,
  268. UINT Message,
  269. WPARAM wParam,
  270. LPARAM lParam
  271. )
  272. {
  273. LPEDITVALUEPARAM lpEditValueParam;
  274. HEXEDITDATA * pHexEditData;
  275. DWORD dwErr;
  276. DHCP_CLASS_INFO ClassInfo;
  277. switch (Message) {
  278. case WM_INITDIALOG:
  279. return EditBinaryValue_OnInitDialog(hWnd, (HWND)(wParam), lParam);
  280. case WM_COMMAND:
  281. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  282. case IDOK:
  283. lpEditValueParam = (LPEDITVALUEPARAM) GetWindowLongPtr(hWnd, DWLP_USER);
  284. pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(GetDlgItem(hWnd, IDC_VALUEDATA), GWLP_USERDATA);
  285. if (pHexEditData->cbBuffer == 0)
  286. {
  287. // user didn't enter any data to describe the class
  288. TCHAR szText[1024], szCaption[1024];
  289. LoadString(g_hInstance, IDS_CLASSID_NO_DATA, szText, sizeof(szText)/sizeof(TCHAR));
  290. LoadString(g_hInstance, IDS_SNAPIN_DESC, szCaption, sizeof(szCaption)/sizeof(TCHAR));
  291. MessageBox(hWnd, szText, szCaption, MB_OK | MB_ICONSTOP);
  292. SetFocus(GetDlgItem(hWnd, IDC_VALUEDATA));
  293. break;
  294. }
  295. lpEditValueParam->cbValueData = pHexEditData->cbBuffer;
  296. GetDlgItemText(hWnd, IDC_VALUENAME, lpEditValueParam->pValueName, 256);
  297. if ( _tcslen(lpEditValueParam->pValueName) == 0)
  298. {
  299. TCHAR szText[1024], szCaption[1024];
  300. LoadString(g_hInstance, IDS_CLASSID_NO_NAME, szText, sizeof(szText)/sizeof(TCHAR));
  301. LoadString(g_hInstance, IDS_SNAPIN_DESC, szCaption, sizeof(szCaption)/sizeof(TCHAR));
  302. MessageBox(hWnd, szText, szCaption, MB_OK | MB_ICONSTOP);
  303. SetFocus(GetDlgItem(hWnd, IDC_VALUENAME));
  304. break;
  305. }
  306. GetDlgItemText(hWnd, IDC_VALUECOMMENT, lpEditValueParam->pValueComment, 256);
  307. // Everything looks good so far, let's try to create the class on the server
  308. ClassInfo.ClassName = lpEditValueParam->pValueName;
  309. ClassInfo.ClassComment = lpEditValueParam->pValueComment;
  310. ClassInfo.ClassDataLength = lpEditValueParam->cbValueData;
  311. ClassInfo.ClassData = lpEditValueParam->pValueData;
  312. dwErr = DhcpCreateClass((LPTSTR) lpEditValueParam->pServer,
  313. 0,
  314. &ClassInfo);
  315. if (dwErr != ERROR_SUCCESS)
  316. {
  317. DhcpMessageBox(dwErr, MB_OK, NULL, -1);
  318. return FALSE;
  319. }
  320. // FALL THROUGH
  321. case IDCANCEL:
  322. EndDialog(hWnd, GET_WM_COMMAND_ID(wParam, lParam));
  323. break;
  324. default:
  325. return FALSE;
  326. }
  327. break;
  328. case WM_HELP:
  329. WinHelp(((LPHELPINFO) lParam)-> hItemHandle, g_pHelpFileName,
  330. HELP_WM_HELP, (ULONG_PTR) (LPVOID) g_aHelpIDs_IDD_CLASSID_NEW);
  331. break;
  332. case WM_CONTEXTMENU:
  333. WinHelp((HWND) wParam, g_pHelpFileName, HELP_CONTEXTMENU,
  334. (ULONG_PTR) (LPVOID) g_aHelpIDs_IDD_CLASSID_NEW);
  335. break;
  336. default:
  337. return FALSE;
  338. }
  339. return TRUE;
  340. }
  341. /*******************************************************************************
  342. *
  343. * EditBinaryValue_OnInitDialog
  344. *
  345. * DESCRIPTION:
  346. *
  347. * PARAMETERS:
  348. * hWnd,
  349. * hFocusWnd,
  350. * lParam,
  351. *
  352. *******************************************************************************/
  353. BOOL
  354. PASCAL
  355. EditBinaryValue_OnInitDialog(
  356. HWND hWnd,
  357. HWND hFocusWnd,
  358. LPARAM lParam
  359. )
  360. {
  361. LPEDITVALUEPARAM lpEditValueParam;
  362. RECT Rect;
  363. int HexEditIdealWidth;
  364. int dxChange;
  365. HWND hControlWnd;
  366. UINT Counter;
  367. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(GetDlgItem(hWnd, IDC_VALUEDATA), GWLP_USERDATA);
  368. SetWindowLongPtr(hWnd, DWLP_USER, lParam);
  369. lpEditValueParam = (LPEDITVALUEPARAM) lParam;
  370. SetDlgItemText(hWnd, IDC_VALUENAME, lpEditValueParam->pValueName);
  371. SendDlgItemMessage(hWnd, IDC_VALUEDATA, HEM_SETBUFFER, (WPARAM)
  372. lpEditValueParam-> cbValueData, (LPARAM) lpEditValueParam-> pValueData);
  373. //
  374. // Figure out how big the "ideally" size HexEdit should be-- this means
  375. // displaying the address, hex dump, ASCII dump, and potentially a scroll
  376. // bar.
  377. //
  378. GetWindowRect(GetDlgItem(hWnd, IDC_VALUEDATA), &Rect);
  379. HexEditIdealWidth = pHexEditData->xAsciiDumpStart +
  380. pHexEditData->FontMaxWidth * (BYTES_PER_HEXEDIT_LINE + 1) +
  381. GetSystemMetrics(SM_CXVSCROLL) + GetSystemMetrics(SM_CXEDGE) * 2;
  382. dxChange = HexEditIdealWidth - (Rect.right - Rect.left);
  383. //
  384. // Resize the dialog box.
  385. //
  386. GetWindowRect(hWnd, &Rect);
  387. MoveWindow(hWnd, Rect.left, Rect.top, Rect.right - Rect.left + dxChange,
  388. Rect.bottom - Rect.top, FALSE);
  389. //
  390. // Resize or move the controls as necessary.
  391. //
  392. for (Counter = 0; Counter < (sizeof(s_EditBinaryValueMoveWnd) /
  393. sizeof(MOVEWND)); Counter++) {
  394. hControlWnd = GetDlgItem(hWnd,
  395. s_EditBinaryValueMoveWnd[Counter].ControlID);
  396. GetWindowRect(hControlWnd, &Rect);
  397. if (s_EditBinaryValueMoveWnd[Counter].SetWindowPosFlags & SWP_NOSIZE) {
  398. MapWindowPoints(NULL, hWnd, (LPPOINT) &Rect, 2);
  399. Rect.left += dxChange;
  400. }
  401. else
  402. Rect.right += dxChange;
  403. SetWindowPos(hControlWnd, NULL, Rect.left, Rect.top, Rect.right -
  404. Rect.left, Rect.bottom - Rect.top,
  405. s_EditBinaryValueMoveWnd[Counter].SetWindowPosFlags);
  406. }
  407. SetFocus(GetDlgItem(hWnd, IDC_VALUENAME));
  408. return TRUE;
  409. UNREFERENCED_PARAMETER(hFocusWnd);
  410. }
  411. /*******************************************************************************
  412. *
  413. * RegisterHexEditClass
  414. *
  415. * DESCRIPTION:
  416. * Register the HexEdit window class with the system.
  417. *
  418. * PARAMETERS:
  419. * (none).
  420. *
  421. *******************************************************************************/
  422. BOOL
  423. PASCAL
  424. RegisterHexEditClass(
  425. HINSTANCE hInstance
  426. )
  427. {
  428. WNDCLASS WndClass;
  429. g_hInstance = hInstance;
  430. s_HexEditClipboardFormat =
  431. RegisterClipboardFormat(s_HexEditClipboardFormatName);
  432. WndClass.style = CS_DBLCLKS;
  433. WndClass.lpfnWndProc = HexEditWndProc;
  434. WndClass.cbClsExtra = 0;
  435. WndClass.cbWndExtra = 0;
  436. WndClass.hInstance = g_hInstance;
  437. WndClass.hIcon = NULL;
  438. WndClass.hCursor = LoadCursor(NULL, IDC_IBEAM);
  439. WndClass.hbrBackground = NULL;
  440. WndClass.lpszMenuName = NULL;
  441. WndClass.lpszClassName = s_HexEditClassName;
  442. return (RegisterClass(&WndClass) != 0);
  443. }
  444. /*******************************************************************************
  445. *
  446. * HexEditWndProc
  447. *
  448. * DESCRIPTION:
  449. * Callback procedure for the HexEdit window.
  450. *
  451. * PARAMETERS:
  452. * hWnd, handle of HexEdit window.
  453. * Message,
  454. * wParam,
  455. * lParam,
  456. * (returns),
  457. *
  458. *******************************************************************************/
  459. LRESULT
  460. PASCAL
  461. HexEditWndProc(
  462. HWND hWnd,
  463. UINT Message,
  464. WPARAM wParam,
  465. LPARAM lParam
  466. )
  467. {
  468. HEXEDITDATA * pHexEditData;
  469. switch (Message) {
  470. HANDLE_MSG(hWnd, WM_NCCREATE, HexEdit_OnNcCreate);
  471. HANDLE_MSG(hWnd, WM_SIZE, HexEdit_OnSize);
  472. HANDLE_MSG(hWnd, WM_VSCROLL, HexEdit_OnVScroll);
  473. HANDLE_MSG(hWnd, WM_PAINT, HexEdit_OnPaint);
  474. HANDLE_MSG(hWnd, WM_LBUTTONDOWN, HexEdit_OnLButtonDown);
  475. HANDLE_MSG(hWnd, WM_LBUTTONDBLCLK, HexEdit_OnLButtonDown);
  476. HANDLE_MSG(hWnd, WM_MOUSEMOVE, HexEdit_OnMouseMove);
  477. HANDLE_MSG(hWnd, WM_LBUTTONUP, HexEdit_OnLButtonUp);
  478. HANDLE_MSG(hWnd, WM_CHAR, HexEdit_OnChar);
  479. HANDLE_MSG(hWnd, WM_KEYDOWN, HexEdit_OnKey);
  480. case WM_SETFOCUS:
  481. HexEdit_OnSetFocus(hWnd);
  482. break;
  483. case WM_KILLFOCUS:
  484. HexEdit_OnKillFocus(hWnd);
  485. break;
  486. case WM_TIMER:
  487. pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  488. HexEdit_OnMouseMove(hWnd, pHexEditData->xPrevMessagePos,
  489. pHexEditData->yPrevMessagePos, 0);
  490. break;
  491. case WM_GETDLGCODE:
  492. return (LPARAM) (DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_WANTTAB);
  493. case WM_ERASEBKGND:
  494. return TRUE;
  495. case WM_NCDESTROY:
  496. pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  497. if (pHexEditData)
  498. {
  499. DeleteObject(pHexEditData->hFont);
  500. free(pHexEditData);
  501. }
  502. break;
  503. case WM_CONTEXTMENU:
  504. HexEdit_OnContextMenu(hWnd, LOWORD(lParam), HIWORD(lParam));
  505. break;
  506. // Message: HEM_SETBUFFER
  507. // wParam: Number of bytes in the buffer.
  508. // lParam: Pointer to the buffer.
  509. case HEM_SETBUFFER:
  510. pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  511. pHexEditData->pBuffer = (PBYTE) lParam;
  512. pHexEditData->cbBuffer = (int) wParam;
  513. pHexEditData->CaretIndex = 0;
  514. pHexEditData->MinimumSelectedIndex = 0;
  515. pHexEditData->MaximumSelectedIndex = 0;
  516. pHexEditData->FirstVisibleLine = 0;
  517. HexEdit_SetScrollInfo(hWnd);
  518. InvalidateRgn(hWnd, NULL, TRUE);
  519. break;
  520. default:
  521. return DefWindowProc(hWnd, Message, wParam, lParam);
  522. }
  523. return 0;
  524. }
  525. /*******************************************************************************
  526. *
  527. * HexEdit_OnNcCreate
  528. *
  529. * DESCRIPTION:
  530. *
  531. * PARAMETERS:
  532. * hWnd, handle of HexEdit window.
  533. *
  534. *******************************************************************************/
  535. BOOL
  536. PASCAL
  537. HexEdit_OnNcCreate(
  538. HWND hWnd,
  539. LPCREATESTRUCT lpCreateStruct
  540. )
  541. {
  542. HDC hDC;
  543. HFONT hPrevFont;
  544. TEXTMETRIC TextMetric;
  545. RECT rect;
  546. BOOL fDone = FALSE;
  547. int nPoint = 10; // starting point size
  548. int HexEditIdealWidth;
  549. HEXEDITDATA * pHexEditData = malloc(sizeof(HEXEDITDATA));
  550. if (!pHexEditData)
  551. return FALSE;
  552. memset( pHexEditData, 0, sizeof( *pHexEditData ));
  553. SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) pHexEditData);
  554. g_clrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  555. g_clrHighlight = GetSysColor(COLOR_HIGHLIGHT);
  556. g_clrWindowText = GetSysColor(COLOR_WINDOWTEXT);
  557. g_clrWindow = GetSysColor(COLOR_WINDOW);
  558. hDC = GetDC(hWnd);
  559. if (hDC)
  560. {
  561. GetWindowRect(hWnd, &rect);
  562. while (!fDone)
  563. {
  564. s_HexEditFont.lfHeight = -(nPoint * GetDeviceCaps(hDC, LOGPIXELSY) / 72);
  565. if ((pHexEditData->hFont = CreateFontIndirect(&s_HexEditFont)) != NULL)
  566. {
  567. hPrevFont = SelectObject(hDC, pHexEditData->hFont);
  568. GetTextMetrics(hDC, &TextMetric);
  569. SelectObject(hDC, hPrevFont);
  570. pHexEditData->FontHeight = TextMetric.tmHeight;
  571. pHexEditData->LinesVisible = pHexEditData->cyWindow /
  572. pHexEditData->FontHeight;
  573. pHexEditData->FontMaxWidth = TextMetric.tmMaxCharWidth;
  574. pHexEditData->xHexDumpByteWidth = pHexEditData->FontMaxWidth * 3;
  575. pHexEditData->xHexDumpStart = pHexEditData->FontMaxWidth * 11 / 2;
  576. pHexEditData->xAsciiDumpStart = pHexEditData->xHexDumpStart +
  577. BYTES_PER_HEXEDIT_LINE * pHexEditData->xHexDumpByteWidth +
  578. pHexEditData->FontMaxWidth * 3 / 2;
  579. // check to make sure we have room
  580. HexEditIdealWidth = pHexEditData->xAsciiDumpStart +
  581. pHexEditData->FontMaxWidth * (BYTES_PER_HEXEDIT_LINE) +
  582. GetSystemMetrics(SM_CXVSCROLL) + GetSystemMetrics(SM_CXEDGE) * 2;
  583. if (HexEditIdealWidth < (rect.right - rect.left) ||
  584. (nPoint < 5) )
  585. {
  586. fDone = TRUE;
  587. }
  588. else
  589. {
  590. // try a smaller size
  591. DeleteObject(pHexEditData->hFont);
  592. pHexEditData->hFont = NULL;
  593. nPoint--;
  594. }
  595. }
  596. else
  597. {
  598. break;
  599. }
  600. }
  601. ReleaseDC(hWnd, hDC);
  602. }
  603. if (pHexEditData->hFont == NULL)
  604. return FALSE;
  605. return (BOOL) DefWindowProc(hWnd, WM_NCCREATE, 0, (LPARAM) lpCreateStruct);
  606. }
  607. /*******************************************************************************
  608. *
  609. * HexEdit_OnSize
  610. *
  611. * DESCRIPTION:
  612. *
  613. * PARAMETERS:
  614. *
  615. *******************************************************************************/
  616. VOID
  617. PASCAL
  618. HexEdit_OnSize(
  619. HWND hWnd,
  620. UINT State,
  621. int cx,
  622. int cy
  623. )
  624. {
  625. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  626. pHexEditData->cxWindow = cx;
  627. pHexEditData->cyWindow = cy;
  628. pHexEditData->LinesVisible = cy / pHexEditData->FontHeight;
  629. HexEdit_SetScrollInfo(hWnd);
  630. UNREFERENCED_PARAMETER(State);
  631. UNREFERENCED_PARAMETER(cx);
  632. }
  633. /*******************************************************************************
  634. *
  635. * HexEdit_SetScrollInfo
  636. *
  637. * DESCRIPTION:
  638. *
  639. * PARAMETERS:
  640. *
  641. *******************************************************************************/
  642. VOID
  643. PASCAL
  644. HexEdit_SetScrollInfo(
  645. HWND hWnd
  646. )
  647. {
  648. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  649. SCROLLINFO ScrollInfo;
  650. pHexEditData->MaximumLines = (pHexEditData->cbBuffer +
  651. BYTES_PER_HEXEDIT_LINE) / BYTES_PER_HEXEDIT_LINE - 1;
  652. ScrollInfo.cbSize = sizeof(SCROLLINFO);
  653. ScrollInfo.fMask = (SIF_RANGE | SIF_PAGE | SIF_POS);
  654. ScrollInfo.nMin = 0;
  655. ScrollInfo.nMax = pHexEditData->MaximumLines;
  656. ScrollInfo.nPage = pHexEditData->LinesVisible;
  657. ScrollInfo.nPos = pHexEditData->FirstVisibleLine;
  658. SetScrollInfo(hWnd, SB_VERT, &ScrollInfo, TRUE);
  659. }
  660. /*******************************************************************************
  661. *
  662. * HexEdit_OnVScroll
  663. *
  664. * DESCRIPTION:
  665. *
  666. * PARAMETERS:
  667. * hWnd, handle of HexEdit window.
  668. *
  669. *******************************************************************************/
  670. VOID
  671. PASCAL
  672. HexEdit_OnVScroll(
  673. HWND hWnd,
  674. HWND hCtlWnd,
  675. UINT Code,
  676. int Position
  677. )
  678. {
  679. int NewFirstVisibleLine;
  680. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  681. SCROLLINFO ScrollInfo;
  682. NewFirstVisibleLine = pHexEditData->FirstVisibleLine;
  683. switch (Code) {
  684. case SB_LINEUP:
  685. NewFirstVisibleLine--;
  686. break;
  687. case SB_LINEDOWN:
  688. NewFirstVisibleLine++;
  689. break;
  690. case SB_PAGEUP:
  691. NewFirstVisibleLine -= pHexEditData->LinesVisible;
  692. break;
  693. case SB_PAGEDOWN:
  694. NewFirstVisibleLine += pHexEditData->LinesVisible;
  695. break;
  696. case SB_THUMBTRACK:
  697. case SB_THUMBPOSITION:
  698. NewFirstVisibleLine = Position;
  699. break;
  700. }
  701. //
  702. // Change the scroll bar position. Note that SetScrollInfo will take into
  703. // account the clipping between zero and the maximum value. It will also
  704. // return the final scroll bar position.
  705. //
  706. ScrollInfo.cbSize = sizeof(SCROLLINFO);
  707. ScrollInfo.fMask = SIF_POS;
  708. ScrollInfo.nPos = NewFirstVisibleLine;
  709. NewFirstVisibleLine = SetScrollInfo(hWnd, SB_VERT, &ScrollInfo, TRUE);
  710. if (pHexEditData->FirstVisibleLine != NewFirstVisibleLine) {
  711. ScrollWindowEx(hWnd, 0, (pHexEditData->FirstVisibleLine -
  712. NewFirstVisibleLine) * pHexEditData->FontHeight, NULL, NULL, NULL,
  713. NULL, SW_INVALIDATE);
  714. pHexEditData->FirstVisibleLine = NewFirstVisibleLine;
  715. HexEdit_SetCaretPosition(hWnd);
  716. }
  717. UNREFERENCED_PARAMETER(hCtlWnd);
  718. }
  719. /*******************************************************************************
  720. *
  721. * HexEdit_OnPaint
  722. *
  723. * DESCRIPTION:
  724. *
  725. * PARAMETERS:
  726. * hWnd, handle of HexEdit window.
  727. *
  728. *******************************************************************************/
  729. VOID
  730. PASCAL
  731. HexEdit_OnPaint(
  732. HWND hWnd
  733. )
  734. {
  735. PAINTSTRUCT PaintStruct;
  736. BeginPaint(hWnd, &PaintStruct);
  737. HexEdit_PaintRect(hWnd, PaintStruct.hdc, &PaintStruct.rcPaint);
  738. EndPaint(hWnd, &PaintStruct);
  739. }
  740. /*******************************************************************************
  741. *
  742. * HexEdit_PaintRect
  743. *
  744. * DESCRIPTION:
  745. *
  746. * PARAMETERS:
  747. *
  748. *******************************************************************************/
  749. VOID
  750. PASCAL
  751. HexEdit_PaintRect(
  752. HWND hWnd,
  753. HDC hDC,
  754. LPRECT lpUpdateRect
  755. )
  756. {
  757. HFONT hPrevFont;
  758. int CurrentByteIndex;
  759. BYTE Byte;
  760. int CurrentLine;
  761. int LastLine;
  762. int BytesOnLastLine;
  763. int BytesOnLine;
  764. BOOL fUsingHighlight;
  765. int Counter;
  766. TCHAR Buffer[5]; // Room for four hex digits plus null
  767. RECT TextRect;
  768. RECT AsciiTextRect;
  769. int x;
  770. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  771. if (pHexEditData->hFont)
  772. hPrevFont = SelectFont(hDC, pHexEditData->hFont);
  773. SetBkColor(hDC, g_clrWindow);
  774. SetTextColor(hDC, g_clrWindowText);
  775. //
  776. // Figure out the range of lines of the control that must be painted.
  777. // Using this information we can compute the offset into the buffer to
  778. // start reading from.
  779. //
  780. CurrentLine = lpUpdateRect-> top / pHexEditData->FontHeight;
  781. TextRect.bottom = CurrentLine * pHexEditData->FontHeight;
  782. AsciiTextRect.bottom = TextRect.bottom;
  783. CurrentByteIndex = (pHexEditData->FirstVisibleLine + CurrentLine) *
  784. BYTES_PER_HEXEDIT_LINE;
  785. LastLine = lpUpdateRect->bottom / pHexEditData->FontHeight;
  786. //
  787. // Figure out if there's enough in the buffer to fill up the entire window
  788. // and the last line that we paint.
  789. //
  790. if (LastLine >= pHexEditData->MaximumLines -
  791. pHexEditData->FirstVisibleLine) {
  792. LastLine = pHexEditData->MaximumLines - pHexEditData->FirstVisibleLine;
  793. BytesOnLastLine = pHexEditData->cbBuffer % BYTES_PER_HEXEDIT_LINE;
  794. }
  795. else
  796. BytesOnLastLine = BYTES_PER_HEXEDIT_LINE;
  797. BytesOnLine = BYTES_PER_HEXEDIT_LINE;
  798. fUsingHighlight = FALSE;
  799. //
  800. // Loop through each of the lines to be displayed.
  801. //
  802. while (CurrentLine <= LastLine) {
  803. //
  804. // If we're on the last line of the display and this is at the end
  805. // of the buffer, we may not have a complete line to paint.
  806. //
  807. if (CurrentLine == LastLine)
  808. BytesOnLine = BytesOnLastLine;
  809. TextRect.top = TextRect.bottom;
  810. TextRect.bottom += pHexEditData->FontHeight;
  811. TextRect.left = 0;
  812. TextRect.right = pHexEditData->xHexDumpStart;
  813. x = TextRect.right + pHexEditData->FontMaxWidth / 2;
  814. wsprintf(Buffer, s_HexWordFormatSpec, CurrentByteIndex);
  815. ExtTextOut(hDC, 0, TextRect.top, ETO_OPAQUE, &TextRect, Buffer, 4,
  816. NULL);
  817. AsciiTextRect.top = AsciiTextRect.bottom;
  818. AsciiTextRect.bottom += pHexEditData->FontHeight;
  819. AsciiTextRect.right = pHexEditData->xAsciiDumpStart;
  820. for (Counter = 0; Counter < BytesOnLine; Counter++,
  821. CurrentByteIndex++) {
  822. //
  823. // Determine what colors to use to paint the current byte.
  824. //
  825. if (CurrentByteIndex >= pHexEditData->MinimumSelectedIndex) {
  826. if (CurrentByteIndex >= pHexEditData->MaximumSelectedIndex) {
  827. if (fUsingHighlight) {
  828. fUsingHighlight = FALSE;
  829. SetBkColor(hDC, g_clrWindow);
  830. SetTextColor(hDC, g_clrWindowText);
  831. }
  832. }
  833. else {
  834. if (!fUsingHighlight) {
  835. fUsingHighlight = TRUE;
  836. SetBkColor(hDC, g_clrHighlight);
  837. SetTextColor(hDC, g_clrHighlightText);
  838. }
  839. }
  840. }
  841. Byte = pHexEditData->pBuffer[CurrentByteIndex];
  842. //
  843. // Paint the hexadecimal representation.
  844. //
  845. TextRect.left = TextRect.right;
  846. TextRect.right += pHexEditData->xHexDumpByteWidth;
  847. wsprintf(Buffer, s_HexByteFormatSpec, Byte);
  848. ExtTextOut(hDC, x, TextRect.top, ETO_OPAQUE, &TextRect,
  849. Buffer, 2, NULL);
  850. x += pHexEditData->xHexDumpByteWidth;
  851. //
  852. // Paint the ASCII representation.
  853. //
  854. AsciiTextRect.left = AsciiTextRect.right;
  855. AsciiTextRect.right += pHexEditData->FontMaxWidth;
  856. Buffer[0] = (TCHAR) (((Byte & 0x7F) >= ' ') ? Byte : '.');
  857. ExtTextOut(hDC, AsciiTextRect.left, AsciiTextRect.top, ETO_OPAQUE,
  858. &AsciiTextRect, Buffer, 1, NULL);
  859. }
  860. //
  861. // Paint any leftover strips between the hexadecimal and ASCII columns
  862. // and the ASCII column and the right edge of the window.
  863. //
  864. if (fUsingHighlight) {
  865. fUsingHighlight = FALSE;
  866. SetBkColor(hDC, g_clrWindow);
  867. SetTextColor(hDC, g_clrWindowText);
  868. }
  869. TextRect.left = TextRect.right;
  870. TextRect.right = pHexEditData->xAsciiDumpStart;
  871. ExtTextOut(hDC, TextRect.left, TextRect.top, ETO_OPAQUE, &TextRect,
  872. NULL, 0, NULL);
  873. AsciiTextRect.left = AsciiTextRect.right;
  874. AsciiTextRect.right = pHexEditData->cxWindow;
  875. ExtTextOut(hDC, AsciiTextRect.left, AsciiTextRect.top, ETO_OPAQUE,
  876. &AsciiTextRect, NULL, 0, NULL);
  877. CurrentLine++;
  878. }
  879. //
  880. // Paint any remaining space in the control by filling it with the
  881. // background color.
  882. //
  883. if (TextRect.bottom < lpUpdateRect-> bottom) {
  884. TextRect.left = 0;
  885. TextRect.right = pHexEditData->cxWindow;
  886. TextRect.top = TextRect.bottom;
  887. TextRect.bottom = lpUpdateRect-> bottom;
  888. ExtTextOut(hDC, 0, TextRect.top, ETO_OPAQUE, &TextRect, NULL, 0, NULL);
  889. }
  890. if (pHexEditData->hFont)
  891. SelectFont(hDC, hPrevFont);
  892. }
  893. /*******************************************************************************
  894. *
  895. * HexEdit_OnSetFocus
  896. *
  897. * DESCRIPTION:
  898. *
  899. * PARAMETERS:
  900. * hWnd, handle of HexEdit window.
  901. *
  902. *******************************************************************************/
  903. VOID
  904. PASCAL
  905. HexEdit_OnSetFocus(
  906. HWND hWnd
  907. )
  908. {
  909. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  910. pHexEditData->Flags |= HEF_FOCUS;
  911. CreateCaret(hWnd, NULL, 0, pHexEditData->FontHeight);
  912. HexEdit_SetCaretPosition(hWnd);
  913. ShowCaret(hWnd);
  914. }
  915. /*******************************************************************************
  916. *
  917. * HexEdit_OnKillFocus
  918. *
  919. * DESCRIPTION:
  920. *
  921. * PARAMETERS:
  922. * hWnd, handle of HexEdit window.
  923. *
  924. *******************************************************************************/
  925. VOID
  926. PASCAL
  927. HexEdit_OnKillFocus(
  928. HWND hWnd
  929. )
  930. {
  931. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  932. if (pHexEditData->Flags & HEF_FOCUS) {
  933. pHexEditData->Flags &= ~HEF_FOCUS;
  934. DestroyCaret();
  935. }
  936. }
  937. /*******************************************************************************
  938. *
  939. * HexEdit_OnLButtonDown
  940. *
  941. * DESCRIPTION:
  942. *
  943. * PARAMETERS:
  944. * hWnd, handle of HexEdit window.
  945. * fDoubleClick, TRUE if this is a double-click message, else FALSE.
  946. * x, x-coordinate of the cursor relative to the client area.
  947. * y, y-coordinate of the cursor relative to the client area.
  948. * KeyFlags, state of various virtual keys.
  949. *
  950. *******************************************************************************/
  951. VOID
  952. PASCAL
  953. HexEdit_OnLButtonDown(
  954. HWND hWnd,
  955. BOOL fDoubleClick,
  956. int x,
  957. int y,
  958. UINT KeyFlags
  959. )
  960. {
  961. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  962. int NewCaretIndex;
  963. if (fDoubleClick) {
  964. if (pHexEditData->CaretIndex + 1 <= pHexEditData->cbBuffer)
  965. {
  966. HexEdit_ChangeCaretIndex(hWnd, pHexEditData->CaretIndex + 1, TRUE);
  967. }
  968. return;
  969. }
  970. NewCaretIndex = HexEdit_HitTest(pHexEditData, x, y);
  971. HexEdit_ChangeCaretIndex(hWnd, NewCaretIndex, (KeyFlags & MK_SHIFT));
  972. //
  973. // If we don't already have the focus, try to get it.
  974. //
  975. if (!(pHexEditData->Flags & HEF_FOCUS))
  976. SetFocus(hWnd);
  977. SetCapture(hWnd);
  978. pHexEditData->Flags |= HEF_DRAGGING;
  979. pHexEditData->xPrevMessagePos = x;
  980. pHexEditData->yPrevMessagePos = y;
  981. SetTimer(hWnd, 1, 400, NULL);
  982. UNREFERENCED_PARAMETER(fDoubleClick);
  983. }
  984. /*******************************************************************************
  985. *
  986. * HexEdit_OnMouseMove
  987. *
  988. * DESCRIPTION:
  989. *
  990. * PARAMETERS:
  991. * hWnd, handle of HexEdit window.
  992. * x, x-coordinate of the cursor relative to the client area.
  993. * y, y-coordinate of the cursor relative to the client area.
  994. * KeyFlags, state of various virtual keys.
  995. *
  996. *******************************************************************************/
  997. VOID
  998. PASCAL
  999. HexEdit_OnMouseMove(
  1000. HWND hWnd,
  1001. int x,
  1002. int y,
  1003. UINT KeyFlags
  1004. )
  1005. {
  1006. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1007. int NewCaretIndex;
  1008. if (!(pHexEditData->Flags & HEF_DRAGGING))
  1009. return;
  1010. NewCaretIndex = HexEdit_HitTest(pHexEditData, x, y);
  1011. HexEdit_ChangeCaretIndex(hWnd, NewCaretIndex, TRUE);
  1012. pHexEditData->xPrevMessagePos = x;
  1013. pHexEditData->yPrevMessagePos = y;
  1014. {
  1015. int i, j;
  1016. i = y < 0 ? -y : y - pHexEditData->cyWindow;
  1017. j = 400 - ((UINT)i << 4);
  1018. if (j < 100)
  1019. j = 100;
  1020. SetTimer(hWnd, 1, j, NULL);
  1021. }
  1022. UNREFERENCED_PARAMETER(KeyFlags);
  1023. }
  1024. /*******************************************************************************
  1025. *
  1026. * HexEdit_OnLButtonUp
  1027. *
  1028. * DESCRIPTION:
  1029. *
  1030. * PARAMETERS:
  1031. * hWnd, handle of HexEdit window.
  1032. * x, x-coordinate of the cursor relative to the client area.
  1033. * y, y-coordinate of the cursor relative to the client area.
  1034. * KeyFlags, state of various virtual keys.
  1035. *
  1036. *******************************************************************************/
  1037. VOID
  1038. PASCAL
  1039. HexEdit_OnLButtonUp(
  1040. HWND hWnd,
  1041. int x,
  1042. int y,
  1043. UINT KeyFlags
  1044. )
  1045. {
  1046. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1047. if (!(pHexEditData->Flags & HEF_DRAGGING))
  1048. return;
  1049. KillTimer(hWnd, 1);
  1050. ReleaseCapture();
  1051. pHexEditData->Flags &= ~HEF_DRAGGING;
  1052. UNREFERENCED_PARAMETER(x);
  1053. UNREFERENCED_PARAMETER(y);
  1054. UNREFERENCED_PARAMETER(KeyFlags);
  1055. }
  1056. /*******************************************************************************
  1057. *
  1058. * HexEdit_HitTest
  1059. *
  1060. * DESCRIPTION:
  1061. *
  1062. * PARAMETERS:
  1063. * x, x-coordinate of the cursor relative to the client area.
  1064. * y, y-coordinate of the cursor relative to the client area.
  1065. * (returns), index of "hit" byte.
  1066. *
  1067. *******************************************************************************/
  1068. int
  1069. PASCAL
  1070. HexEdit_HitTest(
  1071. HEXEDITDATA * pHexEditData,
  1072. int x,
  1073. int y
  1074. )
  1075. {
  1076. int HitLine;
  1077. int BytesOnHitLine;
  1078. int HitByte;
  1079. //
  1080. // Figure out which line the user clicked on and how many bytes are on that
  1081. // line.
  1082. //
  1083. if (y < 0)
  1084. HitLine = -1;
  1085. else if (y >= pHexEditData->cyWindow)
  1086. HitLine = pHexEditData->LinesVisible + 1;
  1087. else
  1088. HitLine = y / pHexEditData->FontHeight;
  1089. HitLine += pHexEditData->FirstVisibleLine;
  1090. if (HitLine >= pHexEditData->MaximumLines) {
  1091. HitLine = pHexEditData->MaximumLines;
  1092. BytesOnHitLine = (pHexEditData->cbBuffer) %
  1093. BYTES_PER_HEXEDIT_LINE;
  1094. }
  1095. else {
  1096. if (HitLine < 0)
  1097. HitLine = 0;
  1098. BytesOnHitLine = BYTES_PER_HEXEDIT_LINE;
  1099. }
  1100. //
  1101. // Calculate the possible HitByte on the current line.
  1102. //
  1103. if (x < pHexEditData->xHexDumpStart)
  1104. x = pHexEditData->xHexDumpStart;
  1105. if (x >= pHexEditData->xHexDumpStart && x <
  1106. pHexEditData->xHexDumpStart + pHexEditData->xHexDumpByteWidth *
  1107. BYTES_PER_HEXEDIT_LINE + pHexEditData->FontMaxWidth) {
  1108. x -= pHexEditData->xHexDumpStart;
  1109. HitByte = x / pHexEditData->xHexDumpByteWidth;
  1110. pHexEditData->Flags &= ~HEF_CARETINASCIIDUMP;
  1111. }
  1112. else {
  1113. HitByte = (x - (pHexEditData->xAsciiDumpStart -
  1114. pHexEditData->FontMaxWidth / 2)) / pHexEditData->FontMaxWidth;
  1115. pHexEditData->Flags |= HEF_CARETINASCIIDUMP;
  1116. }
  1117. //
  1118. // We allow the user to "hit" the first byte of any line via two ways:
  1119. // * clicking before the first byte on that line.
  1120. // * clicking beyond the last byte/character of either display of the
  1121. // previous line.
  1122. //
  1123. // We would like to see the latter case so that dragging in the control
  1124. // works naturally-- it's possible to drag to the end of the line to select
  1125. // the entire range.
  1126. //
  1127. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1128. if (HitByte >= BytesOnHitLine) {
  1129. if (BytesOnHitLine == BYTES_PER_HEXEDIT_LINE) {
  1130. HitByte = BYTES_PER_HEXEDIT_LINE;
  1131. pHexEditData->Flags |= HEF_CARETATENDOFLINE;
  1132. }
  1133. else {
  1134. HitByte = BytesOnHitLine;
  1135. }
  1136. }
  1137. return HitLine * BYTES_PER_HEXEDIT_LINE + HitByte;
  1138. }
  1139. /*******************************************************************************
  1140. *
  1141. * HexEdit_OnKey
  1142. *
  1143. * DESCRIPTION:
  1144. *
  1145. * PARAMETERS:
  1146. * hWnd, handle of HexEdit window.
  1147. * Char,
  1148. * cRepeat,
  1149. *
  1150. *******************************************************************************/
  1151. VOID
  1152. PASCAL
  1153. HexEdit_OnKey(
  1154. HWND hWnd,
  1155. UINT VirtualKey,
  1156. BOOL fDown,
  1157. int cRepeat,
  1158. UINT Flags
  1159. )
  1160. {
  1161. BOOL fControlDown;
  1162. BOOL fShiftDown;
  1163. int NewCaretIndex;
  1164. UINT ScrollCode;
  1165. BOOL bPrevious = FALSE;
  1166. HWND hTabWnd;
  1167. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1168. fControlDown = (GetKeyState(VK_CONTROL) < 0);
  1169. fShiftDown = (GetKeyState(VK_SHIFT) < 0);
  1170. NewCaretIndex = pHexEditData->CaretIndex;
  1171. switch (VirtualKey) {
  1172. case VK_TAB:
  1173. if (fShiftDown && !fControlDown)
  1174. {
  1175. // tab to the previous control
  1176. bPrevious = TRUE;
  1177. }
  1178. else
  1179. if (!fShiftDown && !fControlDown)
  1180. {
  1181. // tab to the next control
  1182. bPrevious = FALSE;
  1183. }
  1184. hTabWnd = GetNextDlgTabItem(GetParent(hWnd), hWnd, bPrevious);
  1185. SetFocus(hTabWnd);
  1186. break;
  1187. case VK_UP:
  1188. if (fControlDown)
  1189. break;
  1190. NewCaretIndex -= BYTES_PER_HEXEDIT_LINE;
  1191. goto onkey_CheckLowerBound;
  1192. case VK_DOWN:
  1193. if (fControlDown)
  1194. break;
  1195. NewCaretIndex += BYTES_PER_HEXEDIT_LINE;
  1196. if (NewCaretIndex / BYTES_PER_HEXEDIT_LINE >
  1197. pHexEditData->MaximumLines) {
  1198. if (pHexEditData->Flags & HEF_CARETATENDOFLINE)
  1199. goto onkey_MoveToEndOfBuffer;
  1200. break;
  1201. }
  1202. goto onkey_CheckUpperBound;
  1203. case VK_HOME:
  1204. if (fControlDown)
  1205. NewCaretIndex = 0;
  1206. else {
  1207. if (pHexEditData->Flags & HEF_CARETATENDOFLINE)
  1208. NewCaretIndex -= BYTES_PER_HEXEDIT_LINE;
  1209. else
  1210. NewCaretIndex &= (~BYTES_PER_HEXEDIT_LINE_MASK);
  1211. }
  1212. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1213. goto onkey_ChangeCaretIndex;
  1214. case VK_END:
  1215. if (fControlDown) {
  1216. onkey_MoveToEndOfBuffer:
  1217. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1218. NewCaretIndex = pHexEditData->cbBuffer;
  1219. }
  1220. else {
  1221. if (pHexEditData->Flags & HEF_CARETATENDOFLINE)
  1222. break;
  1223. NewCaretIndex = (NewCaretIndex &
  1224. (~BYTES_PER_HEXEDIT_LINE_MASK)) + BYTES_PER_HEXEDIT_LINE;
  1225. if (NewCaretIndex > pHexEditData->cbBuffer)
  1226. NewCaretIndex = pHexEditData->cbBuffer;
  1227. else
  1228. pHexEditData->Flags |= HEF_CARETATENDOFLINE;
  1229. }
  1230. goto onkey_ChangeCaretIndex;
  1231. case VK_PRIOR:
  1232. case VK_NEXT:
  1233. NewCaretIndex -= pHexEditData->FirstVisibleLine *
  1234. BYTES_PER_HEXEDIT_LINE;
  1235. ScrollCode = ((VirtualKey == VK_PRIOR) ? SB_PAGEUP : SB_PAGEDOWN);
  1236. HexEdit_OnVScroll(hWnd, NULL, ScrollCode, 0);
  1237. NewCaretIndex += pHexEditData->FirstVisibleLine *
  1238. BYTES_PER_HEXEDIT_LINE;
  1239. if (VirtualKey == VK_PRIOR)
  1240. goto onkey_CheckLowerBound;
  1241. else
  1242. goto onkey_CheckUpperBound;
  1243. case VK_LEFT:
  1244. if (fControlDown)
  1245. {
  1246. // toggle back and forth between hex and ascii
  1247. if (pHexEditData->Flags & HEF_CARETINASCIIDUMP)
  1248. pHexEditData->Flags &= ~HEF_CARETINASCIIDUMP;
  1249. else
  1250. pHexEditData->Flags |= HEF_CARETINASCIIDUMP;
  1251. goto onkey_ChangeCaretIndex;
  1252. }
  1253. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1254. NewCaretIndex--;
  1255. onkey_CheckLowerBound:
  1256. if (NewCaretIndex < 0)
  1257. break;
  1258. goto onkey_ChangeCaretIndex;
  1259. case VK_RIGHT:
  1260. if (fControlDown)
  1261. {
  1262. // toggle back and forth between hex and ascii
  1263. if (pHexEditData->Flags & HEF_CARETINASCIIDUMP)
  1264. pHexEditData->Flags &= ~HEF_CARETINASCIIDUMP;
  1265. else
  1266. pHexEditData->Flags |= HEF_CARETINASCIIDUMP;
  1267. goto onkey_ChangeCaretIndex;
  1268. }
  1269. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1270. NewCaretIndex++;
  1271. onkey_CheckUpperBound:
  1272. if (NewCaretIndex > pHexEditData->cbBuffer)
  1273. NewCaretIndex = pHexEditData->cbBuffer;
  1274. onkey_ChangeCaretIndex:
  1275. HexEdit_ChangeCaretIndex(hWnd, NewCaretIndex, fShiftDown);
  1276. break;
  1277. case VK_DELETE:
  1278. if (!fControlDown) {
  1279. if (fShiftDown)
  1280. HexEdit_OnChar(hWnd, IDKEY_CUT, 0);
  1281. else
  1282. HexEdit_DeleteRange(hWnd, VK_DELETE);
  1283. }
  1284. break;
  1285. case VK_INSERT:
  1286. if (fShiftDown) {
  1287. if (!fControlDown)
  1288. HexEdit_OnChar(hWnd, IDKEY_PASTE, 0);
  1289. }
  1290. else if (fControlDown)
  1291. HexEdit_OnChar(hWnd, IDKEY_COPY, 0);
  1292. break;
  1293. }
  1294. }
  1295. /*******************************************************************************
  1296. *
  1297. * HexEdit_OnChar
  1298. *
  1299. * DESCRIPTION:
  1300. *
  1301. * PARAMETERS:
  1302. * hWnd, handle of HexEdit window.
  1303. * Char,
  1304. * cRepeat,
  1305. *
  1306. *******************************************************************************/
  1307. VOID
  1308. PASCAL
  1309. HexEdit_OnChar(
  1310. HWND hWnd,
  1311. TCHAR Char,
  1312. int cRepeat
  1313. )
  1314. {
  1315. PBYTE pCaretByte;
  1316. BYTE NewCaretByte;
  1317. int PrevCaretIndex;
  1318. RECT UpdateRect;
  1319. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1320. //
  1321. // Check for any special control characters.
  1322. //
  1323. switch (Char) {
  1324. case IDKEY_COPY:
  1325. HexEdit_OnCopy(hWnd);
  1326. return;
  1327. case IDKEY_PASTE:
  1328. PrevCaretIndex = pHexEditData->CaretIndex;
  1329. if (HexEdit_OnPaste(hWnd))
  1330. goto UpdateDisplay;
  1331. return;
  1332. case IDKEY_CUT:
  1333. if (!HexEdit_OnCopy(hWnd))
  1334. return;
  1335. // FALL THROUGH
  1336. case VK_BACK:
  1337. HexEdit_DeleteRange(hWnd, VK_BACK);
  1338. return;
  1339. case VK_TAB:
  1340. return;
  1341. }
  1342. //
  1343. // Validate and convert the typed character depending on the "column" the
  1344. // user is typing in.
  1345. //
  1346. if (pHexEditData->Flags & HEF_CARETINASCIIDUMP) {
  1347. if (Char < ' ') {
  1348. MessageBeep(MB_OK);
  1349. return;
  1350. }
  1351. NewCaretByte = (BYTE) Char;
  1352. }
  1353. else {
  1354. Char = (TCHAR) CharLower((LPTSTR) Char);
  1355. if (Char >= '0' && Char <= '9')
  1356. NewCaretByte = (BYTE) (Char - '0');
  1357. else if (Char >= 'a' && Char <= 'f')
  1358. NewCaretByte = (BYTE) (Char - 'a' + 10);
  1359. else {
  1360. MessageBeep(MB_OK);
  1361. return;
  1362. }
  1363. }
  1364. if (!(pHexEditData->Flags & HEF_INSERTATLOWNIBBLE)) {
  1365. //
  1366. // Check to see if we're inserting while a range is selected. If so,
  1367. // delete the range and insert at the start of the range.
  1368. //
  1369. if (pHexEditData->MinimumSelectedIndex !=
  1370. pHexEditData->MaximumSelectedIndex)
  1371. HexEdit_DeleteRange(hWnd, 0);
  1372. //
  1373. // Verify that we aren't overruning the value data buffer.
  1374. //
  1375. if (pHexEditData->cbBuffer >= MAXDATA_LENGTH) {
  1376. MessageBeep(MB_OK);
  1377. return;
  1378. }
  1379. //
  1380. // Make room for the new byte by shifting all bytes after the insertion
  1381. // point down one byte.
  1382. //
  1383. pCaretByte = pHexEditData->pBuffer + pHexEditData->CaretIndex;
  1384. MoveMemory(pCaretByte + 1, pCaretByte, pHexEditData->cbBuffer -
  1385. pHexEditData->CaretIndex);
  1386. pHexEditData->cbBuffer++;
  1387. HexEdit_SetScrollInfo(hWnd);
  1388. if (pHexEditData->Flags & HEF_CARETINASCIIDUMP)
  1389. *pCaretByte = NewCaretByte;
  1390. else {
  1391. pHexEditData->Flags |= HEF_INSERTATLOWNIBBLE;
  1392. *pCaretByte = NewCaretByte << 4;
  1393. }
  1394. }
  1395. else {
  1396. pHexEditData->Flags &= ~HEF_INSERTATLOWNIBBLE;
  1397. *(pHexEditData->pBuffer + pHexEditData->CaretIndex) |= NewCaretByte;
  1398. }
  1399. PrevCaretIndex = pHexEditData->CaretIndex;
  1400. if (!(pHexEditData->Flags & HEF_INSERTATLOWNIBBLE)) {
  1401. pHexEditData->CaretIndex++;
  1402. pHexEditData->MinimumSelectedIndex = pHexEditData->CaretIndex;
  1403. pHexEditData->MaximumSelectedIndex = pHexEditData->CaretIndex;
  1404. }
  1405. UpdateDisplay:
  1406. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1407. HexEdit_EnsureCaretVisible(hWnd);
  1408. UpdateRect.left = 0;
  1409. UpdateRect.right = pHexEditData->cxWindow;
  1410. UpdateRect.top = (PrevCaretIndex / BYTES_PER_HEXEDIT_LINE -
  1411. pHexEditData->FirstVisibleLine) * pHexEditData->FontHeight;
  1412. UpdateRect.bottom = pHexEditData->cyWindow;
  1413. SendMessage(GetParent(hWnd), WM_COMMAND,
  1414. MAKEWPARAM(GetWindowLongPtr(hWnd, GWLP_ID), EN_CHANGE), (LPARAM)hWnd);
  1415. InvalidateRect(hWnd, &UpdateRect, FALSE);
  1416. }
  1417. /*******************************************************************************
  1418. *
  1419. * HexEdit_SetCaretPosition
  1420. *
  1421. * DESCRIPTION:
  1422. *
  1423. * PARAMETERS:
  1424. * hWnd, handle of HexEdit window.
  1425. *
  1426. *******************************************************************************/
  1427. VOID
  1428. PASCAL
  1429. HexEdit_SetCaretPosition(
  1430. HWND hWnd
  1431. )
  1432. {
  1433. int CaretByte;
  1434. int xCaret;
  1435. int yCaret;
  1436. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1437. CaretByte = pHexEditData->CaretIndex % BYTES_PER_HEXEDIT_LINE;
  1438. yCaret = (pHexEditData->CaretIndex / BYTES_PER_HEXEDIT_LINE -
  1439. pHexEditData->FirstVisibleLine) * pHexEditData->FontHeight;
  1440. //
  1441. // Check if caret should really be displayed at the end of the previous
  1442. // line.
  1443. //
  1444. if (pHexEditData->Flags & HEF_CARETATENDOFLINE) {
  1445. CaretByte = BYTES_PER_HEXEDIT_LINE;
  1446. yCaret -= pHexEditData->FontHeight;
  1447. }
  1448. //
  1449. // Figure out which "column" the user is editing in and thus should have
  1450. // the caret.
  1451. //
  1452. if (pHexEditData->Flags & HEF_CARETINASCIIDUMP) {
  1453. xCaret = pHexEditData->xAsciiDumpStart + CaretByte *
  1454. pHexEditData->FontMaxWidth;
  1455. }
  1456. else {
  1457. xCaret = pHexEditData->xHexDumpStart + CaretByte *
  1458. pHexEditData->xHexDumpByteWidth;
  1459. if (pHexEditData->Flags & HEF_INSERTATLOWNIBBLE)
  1460. xCaret += pHexEditData->FontMaxWidth * 3 / 2;
  1461. }
  1462. SetCaretPos(xCaret, yCaret);
  1463. }
  1464. /*******************************************************************************
  1465. *
  1466. * HexEdit_EnsureCaretVisible
  1467. *
  1468. * DESCRIPTION:
  1469. *
  1470. * PARAMETERS:
  1471. * hWnd, handle of HexEdit window.
  1472. *
  1473. *******************************************************************************/
  1474. VOID
  1475. PASCAL
  1476. HexEdit_EnsureCaretVisible(
  1477. HWND hWnd
  1478. )
  1479. {
  1480. int CaretLine;
  1481. int LastVisibleLine;
  1482. int Delta;
  1483. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1484. if (!(pHexEditData->Flags & HEF_FOCUS))
  1485. return;
  1486. CaretLine = pHexEditData->CaretIndex / BYTES_PER_HEXEDIT_LINE;
  1487. //
  1488. // Check if caret should really be displayed at the end of the previous
  1489. // line.
  1490. //
  1491. if (pHexEditData->Flags & HEF_CARETATENDOFLINE)
  1492. CaretLine--;
  1493. LastVisibleLine = pHexEditData->FirstVisibleLine +
  1494. pHexEditData->LinesVisible - 1;
  1495. if (CaretLine > LastVisibleLine)
  1496. Delta = LastVisibleLine;
  1497. else if (CaretLine < pHexEditData->FirstVisibleLine)
  1498. Delta = pHexEditData->FirstVisibleLine;
  1499. else
  1500. Delta = -1;
  1501. if (Delta != -1) {
  1502. ScrollWindowEx(hWnd, 0, (Delta - CaretLine) * pHexEditData->FontHeight,
  1503. NULL, NULL, NULL, NULL, SW_INVALIDATE);
  1504. pHexEditData->FirstVisibleLine += CaretLine - Delta;
  1505. HexEdit_SetScrollInfo(hWnd);
  1506. }
  1507. HexEdit_SetCaretPosition(hWnd);
  1508. }
  1509. /*******************************************************************************
  1510. *
  1511. * HexEdit_ChangeCaretIndex
  1512. *
  1513. * DESCRIPTION:
  1514. *
  1515. * PARAMETERS:
  1516. * hWnd, handle of HexEdit window.
  1517. * NewCaretIndex,
  1518. * fExtendSelection,
  1519. *
  1520. *******************************************************************************/
  1521. VOID
  1522. PASCAL
  1523. HexEdit_ChangeCaretIndex(
  1524. HWND hWnd,
  1525. int NewCaretIndex,
  1526. BOOL fExtendSelection
  1527. )
  1528. {
  1529. int PrevMinimumSelectedIndex;
  1530. int PrevMaximumSelectedIndex;
  1531. int Swap;
  1532. int UpdateRectCount;
  1533. RECT UpdateRect[2];
  1534. BOOL fPrevRangeEmpty;
  1535. HDC hDC;
  1536. int Index;
  1537. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1538. pHexEditData->Flags &= ~HEF_INSERTATLOWNIBBLE;
  1539. PrevMinimumSelectedIndex = pHexEditData->MinimumSelectedIndex;
  1540. PrevMaximumSelectedIndex = pHexEditData->MaximumSelectedIndex;
  1541. if (fExtendSelection) {
  1542. if (pHexEditData->CaretIndex == pHexEditData->MaximumSelectedIndex)
  1543. pHexEditData->MaximumSelectedIndex = NewCaretIndex;
  1544. else
  1545. pHexEditData->MinimumSelectedIndex = NewCaretIndex;
  1546. if (pHexEditData->MinimumSelectedIndex >
  1547. pHexEditData->MaximumSelectedIndex) {
  1548. Swap = pHexEditData->MinimumSelectedIndex;
  1549. pHexEditData->MinimumSelectedIndex =
  1550. pHexEditData->MaximumSelectedIndex;
  1551. pHexEditData->MaximumSelectedIndex = Swap;
  1552. }
  1553. }
  1554. else {
  1555. pHexEditData->MinimumSelectedIndex = NewCaretIndex;
  1556. pHexEditData->MaximumSelectedIndex = NewCaretIndex;
  1557. }
  1558. pHexEditData->CaretIndex = NewCaretIndex;
  1559. UpdateRectCount = 0;
  1560. if (pHexEditData->MinimumSelectedIndex > PrevMinimumSelectedIndex) {
  1561. UpdateRect[0].top = PrevMinimumSelectedIndex;
  1562. UpdateRect[0].bottom = pHexEditData->MinimumSelectedIndex;
  1563. UpdateRectCount++;
  1564. }
  1565. else if (pHexEditData->MinimumSelectedIndex < PrevMinimumSelectedIndex) {
  1566. UpdateRect[0].top = pHexEditData->MinimumSelectedIndex;
  1567. UpdateRect[0].bottom = PrevMinimumSelectedIndex;
  1568. UpdateRectCount++;
  1569. }
  1570. if (pHexEditData->MaximumSelectedIndex > PrevMaximumSelectedIndex) {
  1571. UpdateRect[UpdateRectCount].top = PrevMaximumSelectedIndex;
  1572. UpdateRect[UpdateRectCount].bottom = pHexEditData->MaximumSelectedIndex;
  1573. UpdateRectCount++;
  1574. }
  1575. else if (pHexEditData->MaximumSelectedIndex < PrevMaximumSelectedIndex) {
  1576. UpdateRect[UpdateRectCount].top = pHexEditData->MaximumSelectedIndex;
  1577. UpdateRect[UpdateRectCount].bottom = PrevMaximumSelectedIndex;
  1578. UpdateRectCount++;
  1579. }
  1580. if (fPrevRangeEmpty = (PrevMinimumSelectedIndex ==
  1581. PrevMaximumSelectedIndex)) {
  1582. UpdateRect[0].top = pHexEditData->MinimumSelectedIndex;
  1583. UpdateRect[0].bottom = pHexEditData->MaximumSelectedIndex;
  1584. UpdateRectCount = 1;
  1585. }
  1586. if (pHexEditData->MinimumSelectedIndex ==
  1587. pHexEditData->MaximumSelectedIndex) {
  1588. if (!fPrevRangeEmpty) {
  1589. UpdateRect[0].top = PrevMinimumSelectedIndex;
  1590. UpdateRect[0].bottom = PrevMaximumSelectedIndex;
  1591. UpdateRectCount = 1;
  1592. }
  1593. else
  1594. UpdateRectCount = 0;
  1595. }
  1596. if (UpdateRectCount) {
  1597. HideCaret(hWnd);
  1598. hDC = GetDC(hWnd);
  1599. if (hDC)
  1600. {
  1601. for (Index = 0; Index < UpdateRectCount; Index++)
  1602. {
  1603. UpdateRect[Index].top = (UpdateRect[Index].top /
  1604. BYTES_PER_HEXEDIT_LINE - pHexEditData->FirstVisibleLine) *
  1605. pHexEditData->FontHeight;
  1606. UpdateRect[Index].bottom = (UpdateRect[Index].bottom /
  1607. BYTES_PER_HEXEDIT_LINE - pHexEditData->FirstVisibleLine + 1) *
  1608. pHexEditData->FontHeight;
  1609. if (UpdateRect[Index].top >= pHexEditData->cyWindow ||
  1610. UpdateRect[Index].bottom < 0)
  1611. continue;
  1612. if (UpdateRect[Index].top < 0)
  1613. UpdateRect[Index].top = 0;
  1614. if (UpdateRect[Index].bottom > pHexEditData->cyWindow)
  1615. UpdateRect[Index].bottom = pHexEditData->cyWindow;
  1616. HexEdit_PaintRect(hWnd, hDC, &UpdateRect[Index]);
  1617. }
  1618. ReleaseDC(hWnd, hDC);
  1619. }
  1620. ShowCaret(hWnd);
  1621. }
  1622. HexEdit_EnsureCaretVisible(hWnd);
  1623. }
  1624. /*******************************************************************************
  1625. *
  1626. * HexEdit_DeleteRange
  1627. *
  1628. * DESCRIPTION:
  1629. *
  1630. * PARAMETERS:
  1631. *
  1632. *******************************************************************************/
  1633. VOID
  1634. PASCAL
  1635. HexEdit_DeleteRange(
  1636. HWND hWnd,
  1637. UINT SourceKey
  1638. )
  1639. {
  1640. int MinimumSelectedIndex;
  1641. int MaximumSelectedIndex;
  1642. PBYTE pMinimumSelectedByte;
  1643. int Length;
  1644. RECT UpdateRect;
  1645. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1646. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1647. MinimumSelectedIndex = pHexEditData->MinimumSelectedIndex;
  1648. MaximumSelectedIndex = pHexEditData->MaximumSelectedIndex;
  1649. //
  1650. // Check to see if a range is selected. If not, then artificially create
  1651. // one based on the key that caused this routine to be called.
  1652. //
  1653. if (MinimumSelectedIndex == MaximumSelectedIndex) {
  1654. if (SourceKey == VK_DELETE || pHexEditData->Flags &
  1655. HEF_INSERTATLOWNIBBLE) {
  1656. pHexEditData->Flags &= ~HEF_INSERTATLOWNIBBLE;
  1657. MaximumSelectedIndex++;
  1658. if (MaximumSelectedIndex > pHexEditData->cbBuffer)
  1659. return;
  1660. }
  1661. else if (SourceKey == VK_BACK) {
  1662. MinimumSelectedIndex--;
  1663. if (MinimumSelectedIndex < 0)
  1664. return;
  1665. }
  1666. else
  1667. return;
  1668. }
  1669. //
  1670. // Compute where to start deleting from and the number of bytes to delete.
  1671. //
  1672. pMinimumSelectedByte = pHexEditData->pBuffer + MinimumSelectedIndex;
  1673. Length = MaximumSelectedIndex - MinimumSelectedIndex;
  1674. //
  1675. // Delete the bytes and update all appropriate window data.
  1676. //
  1677. MoveMemory(pMinimumSelectedByte, pMinimumSelectedByte + Length,
  1678. pHexEditData->cbBuffer - MaximumSelectedIndex);
  1679. pHexEditData->cbBuffer -= Length;
  1680. pHexEditData->CaretIndex = MinimumSelectedIndex;
  1681. pHexEditData->MinimumSelectedIndex = MinimumSelectedIndex;
  1682. pHexEditData->MaximumSelectedIndex = MinimumSelectedIndex;
  1683. HexEdit_SetScrollInfo(hWnd);
  1684. HexEdit_EnsureCaretVisible(hWnd);
  1685. UpdateRect.left = 0;
  1686. UpdateRect.right = pHexEditData->cxWindow;
  1687. UpdateRect.top = (MinimumSelectedIndex / BYTES_PER_HEXEDIT_LINE -
  1688. pHexEditData->FirstVisibleLine) * pHexEditData->FontHeight;
  1689. UpdateRect.bottom = pHexEditData->cyWindow;
  1690. SendMessage(GetParent(hWnd), WM_COMMAND,
  1691. MAKEWPARAM(GetWindowLongPtr(hWnd, GWLP_ID), EN_CHANGE), (LPARAM)hWnd);
  1692. InvalidateRect(hWnd, &UpdateRect, FALSE);
  1693. }
  1694. /*******************************************************************************
  1695. *
  1696. * HexEdit_OnCopy
  1697. *
  1698. * DESCRIPTION:
  1699. *
  1700. * PARAMETERS:
  1701. * hWnd, handle of HexEdit window.
  1702. *
  1703. *******************************************************************************/
  1704. BOOL
  1705. PASCAL
  1706. HexEdit_OnCopy(
  1707. HWND hWnd
  1708. )
  1709. {
  1710. BOOL fSuccess;
  1711. int cbClipboardData;
  1712. LPBYTE lpStartByte;
  1713. HANDLE hClipboardData;
  1714. LPHEXEDITCLIPBOARDDATA lpClipboardData;
  1715. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1716. fSuccess = FALSE;
  1717. cbClipboardData = pHexEditData->MaximumSelectedIndex -
  1718. pHexEditData->MinimumSelectedIndex;
  1719. if (cbClipboardData != 0) {
  1720. lpStartByte = pHexEditData->pBuffer +
  1721. pHexEditData->MinimumSelectedIndex;
  1722. if (OpenClipboard(hWnd)) {
  1723. if ((hClipboardData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
  1724. cbClipboardData + sizeof(HEXEDITCLIPBOARDDATA) - 1)) != NULL) {
  1725. lpClipboardData = (LPHEXEDITCLIPBOARDDATA)
  1726. GlobalLock(hClipboardData);
  1727. CopyMemory(lpClipboardData-> Data, lpStartByte,
  1728. cbClipboardData);
  1729. lpClipboardData-> cbSize = cbClipboardData;
  1730. GlobalUnlock(hClipboardData);
  1731. EmptyClipboard();
  1732. SetClipboardData(s_HexEditClipboardFormat, hClipboardData);
  1733. fSuccess = TRUE;
  1734. }
  1735. CloseClipboard();
  1736. }
  1737. }
  1738. return fSuccess;
  1739. }
  1740. /*******************************************************************************
  1741. *
  1742. * HexEdit_OnPaste
  1743. *
  1744. * DESCRIPTION:
  1745. *
  1746. * PARAMETERS:
  1747. * hWnd, handle of HexEdit window.
  1748. *
  1749. *******************************************************************************/
  1750. BOOL
  1751. PASCAL
  1752. HexEdit_OnPaste(
  1753. HWND hWnd
  1754. )
  1755. {
  1756. BOOL fSuccess;
  1757. HANDLE hClipboardData;
  1758. LPHEXEDITCLIPBOARDDATA lpClipboardData;
  1759. PBYTE pCaretByte;
  1760. DWORD cbSize;
  1761. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1762. fSuccess = FALSE;
  1763. if (pHexEditData->Flags & HEF_INSERTATLOWNIBBLE) {
  1764. pHexEditData->Flags &= ~HEF_INSERTATLOWNIBBLE;
  1765. pHexEditData->CaretIndex++;
  1766. }
  1767. if (OpenClipboard(hWnd)) {
  1768. if ((hClipboardData = GetClipboardData(s_HexEditClipboardFormat)) !=
  1769. NULL) {
  1770. lpClipboardData = (LPHEXEDITCLIPBOARDDATA)
  1771. GlobalLock(hClipboardData);
  1772. if (pHexEditData->cbBuffer + lpClipboardData-> cbSize <=
  1773. MAXDATA_LENGTH) {
  1774. if (pHexEditData->MinimumSelectedIndex !=
  1775. pHexEditData->MaximumSelectedIndex)
  1776. HexEdit_DeleteRange(hWnd, VK_BACK);
  1777. //
  1778. // Make room for the new bytes by shifting all bytes after the
  1779. // the insertion point down the necessary amount.
  1780. //
  1781. pCaretByte = pHexEditData->pBuffer + pHexEditData->CaretIndex;
  1782. cbSize = lpClipboardData-> cbSize;
  1783. MoveMemory(pCaretByte + cbSize, pCaretByte,
  1784. pHexEditData->cbBuffer - pHexEditData->CaretIndex);
  1785. CopyMemory(pCaretByte, lpClipboardData-> Data, cbSize);
  1786. pHexEditData->cbBuffer += cbSize;
  1787. pHexEditData->CaretIndex += cbSize;
  1788. HexEdit_SetScrollInfo(hWnd);
  1789. fSuccess = TRUE;
  1790. }
  1791. GlobalUnlock(hClipboardData);
  1792. }
  1793. CloseClipboard();
  1794. }
  1795. return fSuccess;
  1796. }
  1797. /*******************************************************************************
  1798. *
  1799. * HexEdit_OnContextMenu
  1800. *
  1801. * DESCRIPTION:
  1802. *
  1803. * PARAMETERS:
  1804. * hWnd, handle of HexEdit window.
  1805. * x, horizontal position of the cursor.
  1806. * y, vertical position of the cursor.
  1807. *
  1808. *******************************************************************************/
  1809. VOID
  1810. PASCAL
  1811. HexEdit_OnContextMenu(
  1812. HWND hWnd,
  1813. int x,
  1814. int y
  1815. )
  1816. {
  1817. HMENU hContextMenu;
  1818. HMENU hContextPopupMenu;
  1819. int MenuCommand;
  1820. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1821. //
  1822. // Give us the focus if we don't already have it.
  1823. //
  1824. if (!(pHexEditData->Flags & HEF_FOCUS))
  1825. SetFocus(hWnd);
  1826. //
  1827. // Load the HexEdit context menu from our resources.
  1828. //
  1829. if ((hContextMenu = LoadMenu(g_hInstance,
  1830. MAKEINTRESOURCE(IDM_HEXEDIT_CONTEXT))) == NULL)
  1831. return;
  1832. hContextPopupMenu = GetSubMenu(hContextMenu, 0);
  1833. //
  1834. // Disable editing menu options as appropriate.
  1835. //
  1836. if (pHexEditData->MinimumSelectedIndex ==
  1837. pHexEditData->MaximumSelectedIndex) {
  1838. EnableMenuItem(hContextPopupMenu, IDKEY_COPY, MF_BYCOMMAND | MF_GRAYED);
  1839. EnableMenuItem(hContextPopupMenu, IDKEY_CUT, MF_BYCOMMAND | MF_GRAYED);
  1840. EnableMenuItem(hContextPopupMenu, VK_DELETE, MF_BYCOMMAND | MF_GRAYED);
  1841. }
  1842. if (!IsClipboardFormatAvailable(s_HexEditClipboardFormat))
  1843. EnableMenuItem(hContextPopupMenu, IDKEY_PASTE, MF_BYCOMMAND |
  1844. MF_GRAYED);
  1845. if (pHexEditData->MinimumSelectedIndex == 0 &&
  1846. pHexEditData->MaximumSelectedIndex == pHexEditData->cbBuffer)
  1847. EnableMenuItem(hContextPopupMenu, ID_SELECTALL, MF_BYCOMMAND |
  1848. MF_GRAYED);
  1849. //
  1850. // Display and handle the selected command.
  1851. //
  1852. MenuCommand = TrackPopupMenuEx(hContextPopupMenu, TPM_RETURNCMD |
  1853. TPM_RIGHTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, x, y, hWnd, NULL);
  1854. DestroyMenu(hContextMenu);
  1855. switch (MenuCommand) {
  1856. case IDKEY_COPY:
  1857. case IDKEY_PASTE:
  1858. case IDKEY_CUT:
  1859. case VK_DELETE:
  1860. HexEdit_OnChar(hWnd, (TCHAR) MenuCommand, 0);
  1861. break;
  1862. case ID_SELECTALL:
  1863. pHexEditData->MinimumSelectedIndex = 0;
  1864. pHexEditData->MaximumSelectedIndex = pHexEditData->cbBuffer;
  1865. pHexEditData->CaretIndex = pHexEditData->cbBuffer;
  1866. HexEdit_SetCaretPosition(hWnd);
  1867. InvalidateRect(hWnd, NULL, FALSE);
  1868. break;
  1869. }
  1870. }