Source code of Windows XP (NT5)
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.

2403 lines
56 KiB

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