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.

2530 lines
60 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1993-1994
  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. break;
  519. default:
  520. return DefWindowProc(hWnd, Message, wParam, lParam);
  521. }
  522. return 0;
  523. }
  524. /*******************************************************************************
  525. *
  526. * HexEdit_OnNcCreate
  527. *
  528. * DESCRIPTION:
  529. *
  530. * PARAMETERS:
  531. * hWnd, handle of HexEdit window.
  532. *
  533. *******************************************************************************/
  534. BOOL
  535. PASCAL
  536. HexEdit_OnNcCreate(
  537. HWND hWnd,
  538. LPCREATESTRUCT lpCreateStruct
  539. )
  540. {
  541. HDC hDC;
  542. HFONT hPrevFont;
  543. TEXTMETRIC TextMetric;
  544. RECT rect;
  545. BOOL fDone = FALSE;
  546. int nPoint = 10; // starting point size
  547. int HexEditIdealWidth;
  548. HEXEDITDATA * pHexEditData = malloc(sizeof(HEXEDITDATA));
  549. if (!pHexEditData)
  550. return FALSE;
  551. SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) pHexEditData);
  552. g_clrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
  553. g_clrHighlight = GetSysColor(COLOR_HIGHLIGHT);
  554. g_clrWindowText = GetSysColor(COLOR_WINDOWTEXT);
  555. g_clrWindow = GetSysColor(COLOR_WINDOW);
  556. pHexEditData->cbBuffer = 0;
  557. pHexEditData->Flags = 0;
  558. pHexEditData->cxWindow = 0;
  559. pHexEditData->cyWindow = 0;
  560. pHexEditData->hFont = NULL;
  561. hDC = GetDC(hWnd);
  562. if (hDC)
  563. {
  564. GetWindowRect(hWnd, &rect);
  565. while (!fDone)
  566. {
  567. s_HexEditFont.lfHeight = -(nPoint * GetDeviceCaps(hDC, LOGPIXELSY) / 72);
  568. if ((pHexEditData->hFont = CreateFontIndirect(&s_HexEditFont)) != NULL)
  569. {
  570. hPrevFont = SelectObject(hDC, pHexEditData->hFont);
  571. GetTextMetrics(hDC, &TextMetric);
  572. SelectObject(hDC, hPrevFont);
  573. pHexEditData->FontHeight = TextMetric.tmHeight;
  574. pHexEditData->LinesVisible = pHexEditData->cyWindow /
  575. pHexEditData->FontHeight;
  576. pHexEditData->FontMaxWidth = TextMetric.tmMaxCharWidth;
  577. pHexEditData->xHexDumpByteWidth = pHexEditData->FontMaxWidth * 3;
  578. pHexEditData->xHexDumpStart = pHexEditData->FontMaxWidth * 11 / 2;
  579. pHexEditData->xAsciiDumpStart = pHexEditData->xHexDumpStart +
  580. BYTES_PER_HEXEDIT_LINE * pHexEditData->xHexDumpByteWidth +
  581. pHexEditData->FontMaxWidth * 3 / 2;
  582. // check to make sure we have room
  583. HexEditIdealWidth = pHexEditData->xAsciiDumpStart +
  584. pHexEditData->FontMaxWidth * (BYTES_PER_HEXEDIT_LINE) +
  585. GetSystemMetrics(SM_CXVSCROLL) + GetSystemMetrics(SM_CXEDGE) * 2;
  586. if (HexEditIdealWidth < (rect.right - rect.left) ||
  587. (nPoint < 5) )
  588. {
  589. fDone = TRUE;
  590. }
  591. else
  592. {
  593. // try a smaller size
  594. DeleteObject(pHexEditData->hFont);
  595. pHexEditData->hFont = NULL;
  596. nPoint--;
  597. }
  598. }
  599. else
  600. {
  601. break;
  602. }
  603. }
  604. ReleaseDC(hWnd, hDC);
  605. }
  606. if (pHexEditData->hFont == NULL)
  607. return FALSE;
  608. return (BOOL) DefWindowProc(hWnd, WM_NCCREATE, 0, (LPARAM) lpCreateStruct);
  609. }
  610. /*******************************************************************************
  611. *
  612. * HexEdit_OnSize
  613. *
  614. * DESCRIPTION:
  615. *
  616. * PARAMETERS:
  617. *
  618. *******************************************************************************/
  619. VOID
  620. PASCAL
  621. HexEdit_OnSize(
  622. HWND hWnd,
  623. UINT State,
  624. int cx,
  625. int cy
  626. )
  627. {
  628. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  629. pHexEditData->cxWindow = cx;
  630. pHexEditData->cyWindow = cy;
  631. pHexEditData->LinesVisible = cy / pHexEditData->FontHeight;
  632. HexEdit_SetScrollInfo(hWnd);
  633. UNREFERENCED_PARAMETER(State);
  634. UNREFERENCED_PARAMETER(cx);
  635. }
  636. /*******************************************************************************
  637. *
  638. * HexEdit_SetScrollInfo
  639. *
  640. * DESCRIPTION:
  641. *
  642. * PARAMETERS:
  643. *
  644. *******************************************************************************/
  645. VOID
  646. PASCAL
  647. HexEdit_SetScrollInfo(
  648. HWND hWnd
  649. )
  650. {
  651. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  652. SCROLLINFO ScrollInfo;
  653. pHexEditData->MaximumLines = (pHexEditData->cbBuffer +
  654. BYTES_PER_HEXEDIT_LINE) / BYTES_PER_HEXEDIT_LINE - 1;
  655. ScrollInfo.cbSize = sizeof(SCROLLINFO);
  656. ScrollInfo.fMask = (SIF_RANGE | SIF_PAGE | SIF_POS);
  657. ScrollInfo.nMin = 0;
  658. ScrollInfo.nMax = pHexEditData->MaximumLines;
  659. ScrollInfo.nPage = pHexEditData->LinesVisible;
  660. ScrollInfo.nPos = pHexEditData->FirstVisibleLine;
  661. SetScrollInfo(hWnd, SB_VERT, &ScrollInfo, TRUE);
  662. }
  663. /*******************************************************************************
  664. *
  665. * HexEdit_OnVScroll
  666. *
  667. * DESCRIPTION:
  668. *
  669. * PARAMETERS:
  670. * hWnd, handle of HexEdit window.
  671. *
  672. *******************************************************************************/
  673. VOID
  674. PASCAL
  675. HexEdit_OnVScroll(
  676. HWND hWnd,
  677. HWND hCtlWnd,
  678. UINT Code,
  679. int Position
  680. )
  681. {
  682. int NewFirstVisibleLine;
  683. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  684. SCROLLINFO ScrollInfo;
  685. NewFirstVisibleLine = pHexEditData->FirstVisibleLine;
  686. switch (Code) {
  687. case SB_LINEUP:
  688. NewFirstVisibleLine--;
  689. break;
  690. case SB_LINEDOWN:
  691. NewFirstVisibleLine++;
  692. break;
  693. case SB_PAGEUP:
  694. NewFirstVisibleLine -= pHexEditData->LinesVisible;
  695. break;
  696. case SB_PAGEDOWN:
  697. NewFirstVisibleLine += pHexEditData->LinesVisible;
  698. break;
  699. case SB_THUMBTRACK:
  700. case SB_THUMBPOSITION:
  701. NewFirstVisibleLine = Position;
  702. break;
  703. }
  704. //
  705. // Change the scroll bar position. Note that SetScrollInfo will take into
  706. // account the clipping between zero and the maximum value. It will also
  707. // return the final scroll bar position.
  708. //
  709. ScrollInfo.cbSize = sizeof(SCROLLINFO);
  710. ScrollInfo.fMask = SIF_POS;
  711. ScrollInfo.nPos = NewFirstVisibleLine;
  712. NewFirstVisibleLine = SetScrollInfo(hWnd, SB_VERT, &ScrollInfo, TRUE);
  713. if (pHexEditData->FirstVisibleLine != NewFirstVisibleLine) {
  714. ScrollWindowEx(hWnd, 0, (pHexEditData->FirstVisibleLine -
  715. NewFirstVisibleLine) * pHexEditData->FontHeight, NULL, NULL, NULL,
  716. NULL, SW_INVALIDATE);
  717. pHexEditData->FirstVisibleLine = NewFirstVisibleLine;
  718. HexEdit_SetCaretPosition(hWnd);
  719. }
  720. UNREFERENCED_PARAMETER(hCtlWnd);
  721. }
  722. /*******************************************************************************
  723. *
  724. * HexEdit_OnPaint
  725. *
  726. * DESCRIPTION:
  727. *
  728. * PARAMETERS:
  729. * hWnd, handle of HexEdit window.
  730. *
  731. *******************************************************************************/
  732. VOID
  733. PASCAL
  734. HexEdit_OnPaint(
  735. HWND hWnd
  736. )
  737. {
  738. PAINTSTRUCT PaintStruct;
  739. BeginPaint(hWnd, &PaintStruct);
  740. HexEdit_PaintRect(hWnd, PaintStruct.hdc, &PaintStruct.rcPaint);
  741. EndPaint(hWnd, &PaintStruct);
  742. }
  743. /*******************************************************************************
  744. *
  745. * HexEdit_PaintRect
  746. *
  747. * DESCRIPTION:
  748. *
  749. * PARAMETERS:
  750. *
  751. *******************************************************************************/
  752. VOID
  753. PASCAL
  754. HexEdit_PaintRect(
  755. HWND hWnd,
  756. HDC hDC,
  757. LPRECT lpUpdateRect
  758. )
  759. {
  760. HFONT hPrevFont;
  761. int CurrentByteIndex;
  762. BYTE Byte;
  763. int CurrentLine;
  764. int LastLine;
  765. int BytesOnLastLine;
  766. int BytesOnLine;
  767. BOOL fUsingHighlight;
  768. int Counter;
  769. TCHAR Buffer[5]; // Room for four hex digits plus null
  770. RECT TextRect;
  771. RECT AsciiTextRect;
  772. int x;
  773. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  774. if (pHexEditData->hFont)
  775. hPrevFont = SelectFont(hDC, pHexEditData->hFont);
  776. SetBkColor(hDC, g_clrWindow);
  777. SetTextColor(hDC, g_clrWindowText);
  778. //
  779. // Figure out the range of lines of the control that must be painted.
  780. // Using this information we can compute the offset into the buffer to
  781. // start reading from.
  782. //
  783. CurrentLine = lpUpdateRect-> top / pHexEditData->FontHeight;
  784. TextRect.bottom = CurrentLine * pHexEditData->FontHeight;
  785. AsciiTextRect.bottom = TextRect.bottom;
  786. CurrentByteIndex = (pHexEditData->FirstVisibleLine + CurrentLine) *
  787. BYTES_PER_HEXEDIT_LINE;
  788. LastLine = lpUpdateRect-> bottom / pHexEditData->FontHeight;
  789. //
  790. // Figure out if there's enough in the buffer to fill up the entire window
  791. // and the last line that we paint.
  792. //
  793. if (LastLine >= pHexEditData->MaximumLines -
  794. pHexEditData->FirstVisibleLine) {
  795. LastLine = pHexEditData->MaximumLines - pHexEditData->FirstVisibleLine;
  796. BytesOnLastLine = pHexEditData->cbBuffer % BYTES_PER_HEXEDIT_LINE;
  797. }
  798. else
  799. BytesOnLastLine = BYTES_PER_HEXEDIT_LINE;
  800. BytesOnLine = BYTES_PER_HEXEDIT_LINE;
  801. fUsingHighlight = FALSE;
  802. //
  803. // Loop through each of the lines to be displayed.
  804. //
  805. while (CurrentLine <= LastLine) {
  806. //
  807. // If we're on the last line of the display and this is at the end
  808. // of the buffer, we may not have a complete line to paint.
  809. //
  810. if (CurrentLine == LastLine)
  811. BytesOnLine = BytesOnLastLine;
  812. TextRect.top = TextRect.bottom;
  813. TextRect.bottom += pHexEditData->FontHeight;
  814. TextRect.left = 0;
  815. TextRect.right = pHexEditData->xHexDumpStart;
  816. x = TextRect.right + pHexEditData->FontMaxWidth / 2;
  817. wsprintf(Buffer, s_HexWordFormatSpec, CurrentByteIndex);
  818. ExtTextOut(hDC, 0, TextRect.top, ETO_OPAQUE, &TextRect, Buffer, 4,
  819. NULL);
  820. AsciiTextRect.top = AsciiTextRect.bottom;
  821. AsciiTextRect.bottom += pHexEditData->FontHeight;
  822. AsciiTextRect.right = pHexEditData->xAsciiDumpStart;
  823. for (Counter = 0; Counter < BytesOnLine; Counter++,
  824. CurrentByteIndex++) {
  825. //
  826. // Determine what colors to use to paint the current byte.
  827. //
  828. if (CurrentByteIndex >= pHexEditData->MinimumSelectedIndex) {
  829. if (CurrentByteIndex >= pHexEditData->MaximumSelectedIndex) {
  830. if (fUsingHighlight) {
  831. fUsingHighlight = FALSE;
  832. SetBkColor(hDC, g_clrWindow);
  833. SetTextColor(hDC, g_clrWindowText);
  834. }
  835. }
  836. else {
  837. if (!fUsingHighlight) {
  838. fUsingHighlight = TRUE;
  839. SetBkColor(hDC, g_clrHighlight);
  840. SetTextColor(hDC, g_clrHighlightText);
  841. }
  842. }
  843. }
  844. Byte = pHexEditData->pBuffer[CurrentByteIndex];
  845. //
  846. // Paint the hexadecimal representation.
  847. //
  848. TextRect.left = TextRect.right;
  849. TextRect.right += pHexEditData->xHexDumpByteWidth;
  850. wsprintf(Buffer, s_HexByteFormatSpec, Byte);
  851. ExtTextOut(hDC, x, TextRect.top, ETO_OPAQUE, &TextRect,
  852. Buffer, 2, NULL);
  853. x += pHexEditData->xHexDumpByteWidth;
  854. //
  855. // Paint the ASCII representation.
  856. //
  857. AsciiTextRect.left = AsciiTextRect.right;
  858. AsciiTextRect.right += pHexEditData->FontMaxWidth;
  859. Buffer[0] = (TCHAR) (((Byte & 0x7F) >= ' ') ? Byte : '.');
  860. ExtTextOut(hDC, AsciiTextRect.left, AsciiTextRect.top, ETO_OPAQUE,
  861. &AsciiTextRect, Buffer, 1, NULL);
  862. }
  863. //
  864. // Paint any leftover strips between the hexadecimal and ASCII columns
  865. // and the ASCII column and the right edge of the window.
  866. //
  867. if (fUsingHighlight) {
  868. fUsingHighlight = FALSE;
  869. SetBkColor(hDC, g_clrWindow);
  870. SetTextColor(hDC, g_clrWindowText);
  871. }
  872. TextRect.left = TextRect.right;
  873. TextRect.right = pHexEditData->xAsciiDumpStart;
  874. ExtTextOut(hDC, TextRect.left, TextRect.top, ETO_OPAQUE, &TextRect,
  875. NULL, 0, NULL);
  876. AsciiTextRect.left = AsciiTextRect.right;
  877. AsciiTextRect.right = pHexEditData->cxWindow;
  878. ExtTextOut(hDC, AsciiTextRect.left, AsciiTextRect.top, ETO_OPAQUE,
  879. &AsciiTextRect, NULL, 0, NULL);
  880. CurrentLine++;
  881. }
  882. //
  883. // Paint any remaining space in the control by filling it with the
  884. // background color.
  885. //
  886. if (TextRect.bottom < lpUpdateRect-> bottom) {
  887. TextRect.left = 0;
  888. TextRect.right = pHexEditData->cxWindow;
  889. TextRect.top = TextRect.bottom;
  890. TextRect.bottom = lpUpdateRect-> bottom;
  891. ExtTextOut(hDC, 0, TextRect.top, ETO_OPAQUE, &TextRect, NULL, 0, NULL);
  892. }
  893. if (pHexEditData->hFont)
  894. SelectFont(hDC, hPrevFont);
  895. }
  896. /*******************************************************************************
  897. *
  898. * HexEdit_OnSetFocus
  899. *
  900. * DESCRIPTION:
  901. *
  902. * PARAMETERS:
  903. * hWnd, handle of HexEdit window.
  904. *
  905. *******************************************************************************/
  906. VOID
  907. PASCAL
  908. HexEdit_OnSetFocus(
  909. HWND hWnd
  910. )
  911. {
  912. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  913. pHexEditData->Flags |= HEF_FOCUS;
  914. CreateCaret(hWnd, NULL, 0, pHexEditData->FontHeight);
  915. HexEdit_SetCaretPosition(hWnd);
  916. ShowCaret(hWnd);
  917. }
  918. /*******************************************************************************
  919. *
  920. * HexEdit_OnKillFocus
  921. *
  922. * DESCRIPTION:
  923. *
  924. * PARAMETERS:
  925. * hWnd, handle of HexEdit window.
  926. *
  927. *******************************************************************************/
  928. VOID
  929. PASCAL
  930. HexEdit_OnKillFocus(
  931. HWND hWnd
  932. )
  933. {
  934. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  935. if (pHexEditData->Flags & HEF_FOCUS) {
  936. pHexEditData->Flags &= ~HEF_FOCUS;
  937. DestroyCaret();
  938. }
  939. }
  940. /*******************************************************************************
  941. *
  942. * HexEdit_OnLButtonDown
  943. *
  944. * DESCRIPTION:
  945. *
  946. * PARAMETERS:
  947. * hWnd, handle of HexEdit window.
  948. * fDoubleClick, TRUE if this is a double-click message, else FALSE.
  949. * x, x-coordinate of the cursor relative to the client area.
  950. * y, y-coordinate of the cursor relative to the client area.
  951. * KeyFlags, state of various virtual keys.
  952. *
  953. *******************************************************************************/
  954. VOID
  955. PASCAL
  956. HexEdit_OnLButtonDown(
  957. HWND hWnd,
  958. BOOL fDoubleClick,
  959. int x,
  960. int y,
  961. UINT KeyFlags
  962. )
  963. {
  964. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  965. int NewCaretIndex;
  966. if (fDoubleClick) {
  967. if (pHexEditData->CaretIndex + 1 <= pHexEditData->cbBuffer)
  968. {
  969. HexEdit_ChangeCaretIndex(hWnd, pHexEditData->CaretIndex + 1, TRUE);
  970. }
  971. return;
  972. }
  973. NewCaretIndex = HexEdit_HitTest(pHexEditData, x, y);
  974. HexEdit_ChangeCaretIndex(hWnd, NewCaretIndex, (KeyFlags & MK_SHIFT));
  975. //
  976. // If we don't already have the focus, try to get it.
  977. //
  978. if (!(pHexEditData->Flags & HEF_FOCUS))
  979. SetFocus(hWnd);
  980. SetCapture(hWnd);
  981. pHexEditData->Flags |= HEF_DRAGGING;
  982. pHexEditData->xPrevMessagePos = x;
  983. pHexEditData->yPrevMessagePos = y;
  984. SetTimer(hWnd, 1, 400, NULL);
  985. UNREFERENCED_PARAMETER(fDoubleClick);
  986. }
  987. /*******************************************************************************
  988. *
  989. * HexEdit_OnMouseMove
  990. *
  991. * DESCRIPTION:
  992. *
  993. * PARAMETERS:
  994. * hWnd, handle of HexEdit window.
  995. * x, x-coordinate of the cursor relative to the client area.
  996. * y, y-coordinate of the cursor relative to the client area.
  997. * KeyFlags, state of various virtual keys.
  998. *
  999. *******************************************************************************/
  1000. VOID
  1001. PASCAL
  1002. HexEdit_OnMouseMove(
  1003. HWND hWnd,
  1004. int x,
  1005. int y,
  1006. UINT KeyFlags
  1007. )
  1008. {
  1009. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1010. int NewCaretIndex;
  1011. if (!(pHexEditData->Flags & HEF_DRAGGING))
  1012. return;
  1013. NewCaretIndex = HexEdit_HitTest(pHexEditData, x, y);
  1014. HexEdit_ChangeCaretIndex(hWnd, NewCaretIndex, TRUE);
  1015. pHexEditData->xPrevMessagePos = x;
  1016. pHexEditData->yPrevMessagePos = y;
  1017. {
  1018. int i, j;
  1019. i = y < 0 ? -y : y - pHexEditData->cyWindow;
  1020. j = 400 - ((UINT)i << 4);
  1021. if (j < 100)
  1022. j = 100;
  1023. SetTimer(hWnd, 1, j, NULL);
  1024. }
  1025. UNREFERENCED_PARAMETER(KeyFlags);
  1026. }
  1027. /*******************************************************************************
  1028. *
  1029. * HexEdit_OnLButtonUp
  1030. *
  1031. * DESCRIPTION:
  1032. *
  1033. * PARAMETERS:
  1034. * hWnd, handle of HexEdit window.
  1035. * x, x-coordinate of the cursor relative to the client area.
  1036. * y, y-coordinate of the cursor relative to the client area.
  1037. * KeyFlags, state of various virtual keys.
  1038. *
  1039. *******************************************************************************/
  1040. VOID
  1041. PASCAL
  1042. HexEdit_OnLButtonUp(
  1043. HWND hWnd,
  1044. int x,
  1045. int y,
  1046. UINT KeyFlags
  1047. )
  1048. {
  1049. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1050. if (!(pHexEditData->Flags & HEF_DRAGGING))
  1051. return;
  1052. KillTimer(hWnd, 1);
  1053. ReleaseCapture();
  1054. pHexEditData->Flags &= ~HEF_DRAGGING;
  1055. UNREFERENCED_PARAMETER(x);
  1056. UNREFERENCED_PARAMETER(y);
  1057. UNREFERENCED_PARAMETER(KeyFlags);
  1058. }
  1059. /*******************************************************************************
  1060. *
  1061. * HexEdit_HitTest
  1062. *
  1063. * DESCRIPTION:
  1064. *
  1065. * PARAMETERS:
  1066. * x, x-coordinate of the cursor relative to the client area.
  1067. * y, y-coordinate of the cursor relative to the client area.
  1068. * (returns), index of "hit" byte.
  1069. *
  1070. *******************************************************************************/
  1071. int
  1072. PASCAL
  1073. HexEdit_HitTest(
  1074. HEXEDITDATA * pHexEditData,
  1075. int x,
  1076. int y
  1077. )
  1078. {
  1079. int HitLine;
  1080. int BytesOnHitLine;
  1081. int HitByte;
  1082. //
  1083. // Figure out which line the user clicked on and how many bytes are on that
  1084. // line.
  1085. //
  1086. if (y < 0)
  1087. HitLine = -1;
  1088. else if (y >= pHexEditData->cyWindow)
  1089. HitLine = pHexEditData->LinesVisible + 1;
  1090. else
  1091. HitLine = y / pHexEditData->FontHeight;
  1092. HitLine += pHexEditData->FirstVisibleLine;
  1093. if (HitLine >= pHexEditData->MaximumLines) {
  1094. HitLine = pHexEditData->MaximumLines;
  1095. BytesOnHitLine = (pHexEditData->cbBuffer + 1) %
  1096. BYTES_PER_HEXEDIT_LINE;
  1097. if (BytesOnHitLine == 0)
  1098. BytesOnHitLine = BYTES_PER_HEXEDIT_LINE;
  1099. }
  1100. else {
  1101. if (HitLine < 0)
  1102. HitLine = 0;
  1103. BytesOnHitLine = BYTES_PER_HEXEDIT_LINE;
  1104. }
  1105. //
  1106. //
  1107. //
  1108. if (x < pHexEditData->xHexDumpStart)
  1109. x = pHexEditData->xHexDumpStart;
  1110. if (x >= pHexEditData->xHexDumpStart && x <
  1111. pHexEditData->xHexDumpStart + pHexEditData->xHexDumpByteWidth *
  1112. BYTES_PER_HEXEDIT_LINE + pHexEditData->FontMaxWidth) {
  1113. x -= pHexEditData->xHexDumpStart;
  1114. HitByte = x / pHexEditData->xHexDumpByteWidth;
  1115. pHexEditData->Flags &= ~HEF_CARETINASCIIDUMP;
  1116. }
  1117. else {
  1118. HitByte = (x - (pHexEditData->xAsciiDumpStart -
  1119. pHexEditData->FontMaxWidth / 2)) / pHexEditData->FontMaxWidth;
  1120. pHexEditData->Flags |= HEF_CARETINASCIIDUMP;
  1121. }
  1122. //
  1123. // We allow the user to "hit" the first byte of any line via two ways:
  1124. // * clicking before the first byte on that line.
  1125. // * clicking beyond the last byte/character of either display of the
  1126. // previous line.
  1127. //
  1128. // We would like to see the latter case so that dragging in the control
  1129. // works naturally-- it's possible to drag to the end of the line to select
  1130. // the entire range.
  1131. //
  1132. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1133. if (HitByte >= BytesOnHitLine) {
  1134. if (BytesOnHitLine == BYTES_PER_HEXEDIT_LINE) {
  1135. HitByte = BYTES_PER_HEXEDIT_LINE;
  1136. pHexEditData->Flags |= HEF_CARETATENDOFLINE;
  1137. }
  1138. else
  1139. HitByte = BytesOnHitLine - 1;
  1140. }
  1141. return HitLine * BYTES_PER_HEXEDIT_LINE + HitByte;
  1142. }
  1143. /*******************************************************************************
  1144. *
  1145. * HexEdit_OnKey
  1146. *
  1147. * DESCRIPTION:
  1148. *
  1149. * PARAMETERS:
  1150. * hWnd, handle of HexEdit window.
  1151. * Char,
  1152. * cRepeat,
  1153. *
  1154. *******************************************************************************/
  1155. VOID
  1156. PASCAL
  1157. HexEdit_OnKey(
  1158. HWND hWnd,
  1159. UINT VirtualKey,
  1160. BOOL fDown,
  1161. int cRepeat,
  1162. UINT Flags
  1163. )
  1164. {
  1165. BOOL fControlDown;
  1166. BOOL fShiftDown;
  1167. int NewCaretIndex;
  1168. UINT ScrollCode;
  1169. BOOL bPrevious = FALSE;
  1170. HWND hTabWnd;
  1171. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1172. fControlDown = (GetKeyState(VK_CONTROL) < 0);
  1173. fShiftDown = (GetKeyState(VK_SHIFT) < 0);
  1174. NewCaretIndex = pHexEditData->CaretIndex;
  1175. switch (VirtualKey) {
  1176. case VK_TAB:
  1177. if (fShiftDown && !fControlDown)
  1178. {
  1179. // tab to the previous control
  1180. bPrevious = TRUE;
  1181. }
  1182. else
  1183. if (!fShiftDown && !fControlDown)
  1184. {
  1185. // tab to the next control
  1186. bPrevious = FALSE;
  1187. }
  1188. hTabWnd = GetNextDlgTabItem(GetParent(hWnd), hWnd, bPrevious);
  1189. SetFocus(hTabWnd);
  1190. break;
  1191. case VK_UP:
  1192. if (fControlDown)
  1193. break;
  1194. NewCaretIndex -= BYTES_PER_HEXEDIT_LINE;
  1195. goto onkey_CheckLowerBound;
  1196. case VK_DOWN:
  1197. if (fControlDown)
  1198. break;
  1199. NewCaretIndex += BYTES_PER_HEXEDIT_LINE;
  1200. if (NewCaretIndex / BYTES_PER_HEXEDIT_LINE >
  1201. pHexEditData->MaximumLines) {
  1202. if (pHexEditData->Flags & HEF_CARETATENDOFLINE)
  1203. goto onkey_MoveToEndOfBuffer;
  1204. break;
  1205. }
  1206. goto onkey_CheckUpperBound;
  1207. case VK_HOME:
  1208. if (fControlDown)
  1209. NewCaretIndex = 0;
  1210. else {
  1211. if (pHexEditData->Flags & HEF_CARETATENDOFLINE)
  1212. NewCaretIndex -= BYTES_PER_HEXEDIT_LINE;
  1213. else
  1214. NewCaretIndex &= (~BYTES_PER_HEXEDIT_LINE_MASK);
  1215. }
  1216. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1217. goto onkey_ChangeCaretIndex;
  1218. case VK_END:
  1219. if (fControlDown) {
  1220. onkey_MoveToEndOfBuffer:
  1221. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1222. NewCaretIndex = pHexEditData->cbBuffer;
  1223. }
  1224. else {
  1225. if (pHexEditData->Flags & HEF_CARETATENDOFLINE)
  1226. break;
  1227. NewCaretIndex = (NewCaretIndex &
  1228. (~BYTES_PER_HEXEDIT_LINE_MASK)) + BYTES_PER_HEXEDIT_LINE;
  1229. if (NewCaretIndex > pHexEditData->cbBuffer)
  1230. NewCaretIndex = pHexEditData->cbBuffer;
  1231. else
  1232. pHexEditData->Flags |= HEF_CARETATENDOFLINE;
  1233. }
  1234. goto onkey_ChangeCaretIndex;
  1235. case VK_PRIOR:
  1236. case VK_NEXT:
  1237. NewCaretIndex -= pHexEditData->FirstVisibleLine *
  1238. BYTES_PER_HEXEDIT_LINE;
  1239. ScrollCode = ((VirtualKey == VK_PRIOR) ? SB_PAGEUP : SB_PAGEDOWN);
  1240. HexEdit_OnVScroll(hWnd, NULL, ScrollCode, 0);
  1241. NewCaretIndex += pHexEditData->FirstVisibleLine *
  1242. BYTES_PER_HEXEDIT_LINE;
  1243. if (VirtualKey == VK_PRIOR)
  1244. goto onkey_CheckLowerBound;
  1245. else
  1246. goto onkey_CheckUpperBound;
  1247. case VK_LEFT:
  1248. if (fControlDown)
  1249. {
  1250. // toggle back and forth between hex and ascii
  1251. if (pHexEditData->Flags & HEF_CARETINASCIIDUMP)
  1252. pHexEditData->Flags &= ~HEF_CARETINASCIIDUMP;
  1253. else
  1254. pHexEditData->Flags |= HEF_CARETINASCIIDUMP;
  1255. goto onkey_ChangeCaretIndex;
  1256. }
  1257. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1258. NewCaretIndex--;
  1259. onkey_CheckLowerBound:
  1260. if (NewCaretIndex < 0)
  1261. break;
  1262. goto onkey_ChangeCaretIndex;
  1263. case VK_RIGHT:
  1264. if (fControlDown)
  1265. {
  1266. // toggle back and forth between hex and ascii
  1267. if (pHexEditData->Flags & HEF_CARETINASCIIDUMP)
  1268. pHexEditData->Flags &= ~HEF_CARETINASCIIDUMP;
  1269. else
  1270. pHexEditData->Flags |= HEF_CARETINASCIIDUMP;
  1271. goto onkey_ChangeCaretIndex;
  1272. }
  1273. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1274. NewCaretIndex++;
  1275. onkey_CheckUpperBound:
  1276. if (NewCaretIndex > pHexEditData->cbBuffer)
  1277. NewCaretIndex = pHexEditData->cbBuffer;
  1278. onkey_ChangeCaretIndex:
  1279. HexEdit_ChangeCaretIndex(hWnd, NewCaretIndex, fShiftDown);
  1280. break;
  1281. case VK_DELETE:
  1282. if (!fControlDown) {
  1283. if (fShiftDown)
  1284. HexEdit_OnChar(hWnd, IDKEY_CUT, 0);
  1285. else
  1286. HexEdit_DeleteRange(hWnd, VK_DELETE);
  1287. }
  1288. break;
  1289. case VK_INSERT:
  1290. if (fShiftDown) {
  1291. if (!fControlDown)
  1292. HexEdit_OnChar(hWnd, IDKEY_PASTE, 0);
  1293. }
  1294. else if (fControlDown)
  1295. HexEdit_OnChar(hWnd, IDKEY_COPY, 0);
  1296. break;
  1297. }
  1298. }
  1299. /*******************************************************************************
  1300. *
  1301. * HexEdit_OnChar
  1302. *
  1303. * DESCRIPTION:
  1304. *
  1305. * PARAMETERS:
  1306. * hWnd, handle of HexEdit window.
  1307. * Char,
  1308. * cRepeat,
  1309. *
  1310. *******************************************************************************/
  1311. VOID
  1312. PASCAL
  1313. HexEdit_OnChar(
  1314. HWND hWnd,
  1315. TCHAR Char,
  1316. int cRepeat
  1317. )
  1318. {
  1319. PBYTE pCaretByte;
  1320. BYTE NewCaretByte;
  1321. int PrevCaretIndex;
  1322. RECT UpdateRect;
  1323. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1324. //
  1325. // Check for any special control characters.
  1326. //
  1327. switch (Char) {
  1328. case IDKEY_COPY:
  1329. HexEdit_OnCopy(hWnd);
  1330. return;
  1331. case IDKEY_PASTE:
  1332. PrevCaretIndex = pHexEditData->CaretIndex;
  1333. if (HexEdit_OnPaste(hWnd))
  1334. goto UpdateDisplay;
  1335. return;
  1336. case IDKEY_CUT:
  1337. if (!HexEdit_OnCopy(hWnd))
  1338. return;
  1339. // FALL THROUGH
  1340. case VK_BACK:
  1341. HexEdit_DeleteRange(hWnd, VK_BACK);
  1342. return;
  1343. case VK_TAB:
  1344. return;
  1345. }
  1346. //
  1347. // Validate and convert the typed character depending on the "column" the
  1348. // user is typing in.
  1349. //
  1350. if (pHexEditData->Flags & HEF_CARETINASCIIDUMP) {
  1351. if (Char < ' ') {
  1352. MessageBeep(MB_OK);
  1353. return;
  1354. }
  1355. NewCaretByte = (BYTE) Char;
  1356. }
  1357. else {
  1358. Char = (TCHAR) CharLower((LPTSTR) Char);
  1359. if (Char >= '0' && Char <= '9')
  1360. NewCaretByte = (BYTE) (Char - '0');
  1361. else if (Char >= 'a' && Char <= 'f')
  1362. NewCaretByte = (BYTE) (Char - 'a' + 10);
  1363. else {
  1364. MessageBeep(MB_OK);
  1365. return;
  1366. }
  1367. }
  1368. if (!(pHexEditData->Flags & HEF_INSERTATLOWNIBBLE)) {
  1369. //
  1370. // Check to see if we're inserting while a range is selected. If so,
  1371. // delete the range and insert at the start of the range.
  1372. //
  1373. if (pHexEditData->MinimumSelectedIndex !=
  1374. pHexEditData->MaximumSelectedIndex)
  1375. HexEdit_DeleteRange(hWnd, 0);
  1376. //
  1377. // Verify that we aren't overruning the value data buffer.
  1378. //
  1379. if (pHexEditData->cbBuffer >= MAXDATA_LENGTH) {
  1380. MessageBeep(MB_OK);
  1381. return;
  1382. }
  1383. //
  1384. // Make room for the new byte by shifting all bytes after the insertion
  1385. // point down one byte.
  1386. //
  1387. pCaretByte = pHexEditData->pBuffer + pHexEditData->CaretIndex;
  1388. MoveMemory(pCaretByte + 1, pCaretByte, pHexEditData->cbBuffer -
  1389. pHexEditData->CaretIndex);
  1390. pHexEditData->cbBuffer++;
  1391. HexEdit_SetScrollInfo(hWnd);
  1392. if (pHexEditData->Flags & HEF_CARETINASCIIDUMP)
  1393. *pCaretByte = NewCaretByte;
  1394. else {
  1395. pHexEditData->Flags |= HEF_INSERTATLOWNIBBLE;
  1396. *pCaretByte = NewCaretByte << 4;
  1397. }
  1398. }
  1399. else {
  1400. pHexEditData->Flags &= ~HEF_INSERTATLOWNIBBLE;
  1401. *(pHexEditData->pBuffer + pHexEditData->CaretIndex) |= NewCaretByte;
  1402. }
  1403. PrevCaretIndex = pHexEditData->CaretIndex;
  1404. if (!(pHexEditData->Flags & HEF_INSERTATLOWNIBBLE)) {
  1405. pHexEditData->CaretIndex++;
  1406. pHexEditData->MinimumSelectedIndex = pHexEditData->CaretIndex;
  1407. pHexEditData->MaximumSelectedIndex = pHexEditData->CaretIndex;
  1408. }
  1409. UpdateDisplay:
  1410. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1411. HexEdit_EnsureCaretVisible(hWnd);
  1412. UpdateRect.left = 0;
  1413. UpdateRect.right = pHexEditData->cxWindow;
  1414. UpdateRect.top = (PrevCaretIndex / BYTES_PER_HEXEDIT_LINE -
  1415. pHexEditData->FirstVisibleLine) * pHexEditData->FontHeight;
  1416. UpdateRect.bottom = pHexEditData->cyWindow;
  1417. SendMessage(GetParent(hWnd), WM_COMMAND,
  1418. MAKEWPARAM(GetWindowLongPtr(hWnd, GWLP_ID), EN_CHANGE), (LPARAM)hWnd);
  1419. InvalidateRect(hWnd, &UpdateRect, FALSE);
  1420. }
  1421. /*******************************************************************************
  1422. *
  1423. * HexEdit_SetCaretPosition
  1424. *
  1425. * DESCRIPTION:
  1426. *
  1427. * PARAMETERS:
  1428. * hWnd, handle of HexEdit window.
  1429. *
  1430. *******************************************************************************/
  1431. VOID
  1432. PASCAL
  1433. HexEdit_SetCaretPosition(
  1434. HWND hWnd
  1435. )
  1436. {
  1437. int CaretByte;
  1438. int xCaret;
  1439. int yCaret;
  1440. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1441. CaretByte = pHexEditData->CaretIndex % BYTES_PER_HEXEDIT_LINE;
  1442. yCaret = (pHexEditData->CaretIndex / BYTES_PER_HEXEDIT_LINE -
  1443. pHexEditData->FirstVisibleLine) * pHexEditData->FontHeight;
  1444. //
  1445. // Check if caret should really be displayed at the end of the previous
  1446. // line.
  1447. //
  1448. if (pHexEditData->Flags & HEF_CARETATENDOFLINE) {
  1449. CaretByte = BYTES_PER_HEXEDIT_LINE;
  1450. yCaret -= pHexEditData->FontHeight;
  1451. }
  1452. //
  1453. // Figure out which "column" the user is editing in and thus should have
  1454. // the caret.
  1455. //
  1456. if (pHexEditData->Flags & HEF_CARETINASCIIDUMP) {
  1457. xCaret = pHexEditData->xAsciiDumpStart + CaretByte *
  1458. pHexEditData->FontMaxWidth;
  1459. }
  1460. else {
  1461. xCaret = pHexEditData->xHexDumpStart + CaretByte *
  1462. pHexEditData->xHexDumpByteWidth;
  1463. if (pHexEditData->Flags & HEF_INSERTATLOWNIBBLE)
  1464. xCaret += pHexEditData->FontMaxWidth * 3 / 2;
  1465. }
  1466. SetCaretPos(xCaret, yCaret);
  1467. }
  1468. /*******************************************************************************
  1469. *
  1470. * HexEdit_EnsureCaretVisible
  1471. *
  1472. * DESCRIPTION:
  1473. *
  1474. * PARAMETERS:
  1475. * hWnd, handle of HexEdit window.
  1476. *
  1477. *******************************************************************************/
  1478. VOID
  1479. PASCAL
  1480. HexEdit_EnsureCaretVisible(
  1481. HWND hWnd
  1482. )
  1483. {
  1484. int CaretLine;
  1485. int LastVisibleLine;
  1486. int Delta;
  1487. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1488. if (!(pHexEditData->Flags & HEF_FOCUS))
  1489. return;
  1490. CaretLine = pHexEditData->CaretIndex / BYTES_PER_HEXEDIT_LINE;
  1491. //
  1492. // Check if caret should really be displayed at the end of the previous
  1493. // line.
  1494. //
  1495. if (pHexEditData->Flags & HEF_CARETATENDOFLINE)
  1496. CaretLine--;
  1497. LastVisibleLine = pHexEditData->FirstVisibleLine +
  1498. pHexEditData->LinesVisible - 1;
  1499. if (CaretLine > LastVisibleLine)
  1500. Delta = LastVisibleLine;
  1501. else if (CaretLine < pHexEditData->FirstVisibleLine)
  1502. Delta = pHexEditData->FirstVisibleLine;
  1503. else
  1504. Delta = -1;
  1505. if (Delta != -1) {
  1506. ScrollWindowEx(hWnd, 0, (Delta - CaretLine) * pHexEditData->FontHeight,
  1507. NULL, NULL, NULL, NULL, SW_INVALIDATE);
  1508. pHexEditData->FirstVisibleLine += CaretLine - Delta;
  1509. HexEdit_SetScrollInfo(hWnd);
  1510. }
  1511. HexEdit_SetCaretPosition(hWnd);
  1512. }
  1513. /*******************************************************************************
  1514. *
  1515. * HexEdit_ChangeCaretIndex
  1516. *
  1517. * DESCRIPTION:
  1518. *
  1519. * PARAMETERS:
  1520. * hWnd, handle of HexEdit window.
  1521. * NewCaretIndex,
  1522. * fExtendSelection,
  1523. *
  1524. *******************************************************************************/
  1525. VOID
  1526. PASCAL
  1527. HexEdit_ChangeCaretIndex(
  1528. HWND hWnd,
  1529. int NewCaretIndex,
  1530. BOOL fExtendSelection
  1531. )
  1532. {
  1533. int PrevMinimumSelectedIndex;
  1534. int PrevMaximumSelectedIndex;
  1535. int Swap;
  1536. int UpdateRectCount;
  1537. RECT UpdateRect[2];
  1538. BOOL fPrevRangeEmpty;
  1539. HDC hDC;
  1540. int Index;
  1541. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1542. pHexEditData->Flags &= ~HEF_INSERTATLOWNIBBLE;
  1543. PrevMinimumSelectedIndex = pHexEditData->MinimumSelectedIndex;
  1544. PrevMaximumSelectedIndex = pHexEditData->MaximumSelectedIndex;
  1545. if (fExtendSelection) {
  1546. if (pHexEditData->CaretIndex == pHexEditData->MaximumSelectedIndex)
  1547. pHexEditData->MaximumSelectedIndex = NewCaretIndex;
  1548. else
  1549. pHexEditData->MinimumSelectedIndex = NewCaretIndex;
  1550. if (pHexEditData->MinimumSelectedIndex >
  1551. pHexEditData->MaximumSelectedIndex) {
  1552. Swap = pHexEditData->MinimumSelectedIndex;
  1553. pHexEditData->MinimumSelectedIndex =
  1554. pHexEditData->MaximumSelectedIndex;
  1555. pHexEditData->MaximumSelectedIndex = Swap;
  1556. }
  1557. }
  1558. else {
  1559. pHexEditData->MinimumSelectedIndex = NewCaretIndex;
  1560. pHexEditData->MaximumSelectedIndex = NewCaretIndex;
  1561. }
  1562. pHexEditData->CaretIndex = NewCaretIndex;
  1563. UpdateRectCount = 0;
  1564. if (pHexEditData->MinimumSelectedIndex > PrevMinimumSelectedIndex) {
  1565. UpdateRect[0].top = PrevMinimumSelectedIndex;
  1566. UpdateRect[0].bottom = pHexEditData->MinimumSelectedIndex;
  1567. UpdateRectCount++;
  1568. }
  1569. else if (pHexEditData->MinimumSelectedIndex < PrevMinimumSelectedIndex) {
  1570. UpdateRect[0].top = pHexEditData->MinimumSelectedIndex;
  1571. UpdateRect[0].bottom = PrevMinimumSelectedIndex;
  1572. UpdateRectCount++;
  1573. }
  1574. if (pHexEditData->MaximumSelectedIndex > PrevMaximumSelectedIndex) {
  1575. UpdateRect[UpdateRectCount].top = PrevMaximumSelectedIndex;
  1576. UpdateRect[UpdateRectCount].bottom = pHexEditData->MaximumSelectedIndex;
  1577. UpdateRectCount++;
  1578. }
  1579. else if (pHexEditData->MaximumSelectedIndex < PrevMaximumSelectedIndex) {
  1580. UpdateRect[UpdateRectCount].top = pHexEditData->MaximumSelectedIndex;
  1581. UpdateRect[UpdateRectCount].bottom = PrevMaximumSelectedIndex;
  1582. UpdateRectCount++;
  1583. }
  1584. if (fPrevRangeEmpty = (PrevMinimumSelectedIndex ==
  1585. PrevMaximumSelectedIndex)) {
  1586. UpdateRect[0].top = pHexEditData->MinimumSelectedIndex;
  1587. UpdateRect[0].bottom = pHexEditData->MaximumSelectedIndex;
  1588. UpdateRectCount = 1;
  1589. }
  1590. if (pHexEditData->MinimumSelectedIndex ==
  1591. pHexEditData->MaximumSelectedIndex) {
  1592. if (!fPrevRangeEmpty) {
  1593. UpdateRect[0].top = PrevMinimumSelectedIndex;
  1594. UpdateRect[0].bottom = PrevMaximumSelectedIndex;
  1595. UpdateRectCount = 1;
  1596. }
  1597. else
  1598. UpdateRectCount = 0;
  1599. }
  1600. if (UpdateRectCount) {
  1601. HideCaret(hWnd);
  1602. hDC = GetDC(hWnd);
  1603. if (hDC)
  1604. {
  1605. for (Index = 0; Index < UpdateRectCount; Index++)
  1606. {
  1607. UpdateRect[Index].top = (UpdateRect[Index].top /
  1608. BYTES_PER_HEXEDIT_LINE - pHexEditData->FirstVisibleLine) *
  1609. pHexEditData->FontHeight;
  1610. UpdateRect[Index].bottom = (UpdateRect[Index].bottom /
  1611. BYTES_PER_HEXEDIT_LINE - pHexEditData->FirstVisibleLine + 1) *
  1612. pHexEditData->FontHeight;
  1613. if (UpdateRect[Index].top >= pHexEditData->cyWindow ||
  1614. UpdateRect[Index].bottom < 0)
  1615. continue;
  1616. if (UpdateRect[Index].top < 0)
  1617. UpdateRect[Index].top = 0;
  1618. if (UpdateRect[Index].bottom > pHexEditData->cyWindow)
  1619. UpdateRect[Index].bottom = pHexEditData->cyWindow;
  1620. HexEdit_PaintRect(hWnd, hDC, &UpdateRect[Index]);
  1621. }
  1622. ReleaseDC(hWnd, hDC);
  1623. }
  1624. ShowCaret(hWnd);
  1625. }
  1626. HexEdit_EnsureCaretVisible(hWnd);
  1627. }
  1628. /*******************************************************************************
  1629. *
  1630. * HexEdit_DeleteRange
  1631. *
  1632. * DESCRIPTION:
  1633. *
  1634. * PARAMETERS:
  1635. *
  1636. *******************************************************************************/
  1637. VOID
  1638. PASCAL
  1639. HexEdit_DeleteRange(
  1640. HWND hWnd,
  1641. UINT SourceKey
  1642. )
  1643. {
  1644. int MinimumSelectedIndex;
  1645. int MaximumSelectedIndex;
  1646. PBYTE pMinimumSelectedByte;
  1647. int Length;
  1648. RECT UpdateRect;
  1649. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1650. pHexEditData->Flags &= ~HEF_CARETATENDOFLINE;
  1651. MinimumSelectedIndex = pHexEditData->MinimumSelectedIndex;
  1652. MaximumSelectedIndex = pHexEditData->MaximumSelectedIndex;
  1653. //
  1654. // Check to see if a range is selected. If not, then artificially create
  1655. // one based on the key that caused this routine to be called.
  1656. //
  1657. if (MinimumSelectedIndex == MaximumSelectedIndex) {
  1658. if (SourceKey == VK_DELETE || pHexEditData->Flags &
  1659. HEF_INSERTATLOWNIBBLE) {
  1660. pHexEditData->Flags &= ~HEF_INSERTATLOWNIBBLE;
  1661. MaximumSelectedIndex++;
  1662. if (MaximumSelectedIndex > pHexEditData->cbBuffer)
  1663. return;
  1664. }
  1665. else if (SourceKey == VK_BACK) {
  1666. MinimumSelectedIndex--;
  1667. if (MinimumSelectedIndex < 0)
  1668. return;
  1669. }
  1670. else
  1671. return;
  1672. }
  1673. //
  1674. // Compute where to start deleting from and the number of bytes to delete.
  1675. //
  1676. pMinimumSelectedByte = pHexEditData->pBuffer + MinimumSelectedIndex;
  1677. Length = MaximumSelectedIndex - MinimumSelectedIndex;
  1678. //
  1679. // Delete the bytes and update all appropriate window data.
  1680. //
  1681. MoveMemory(pMinimumSelectedByte, pMinimumSelectedByte + Length,
  1682. pHexEditData->cbBuffer - MaximumSelectedIndex);
  1683. pHexEditData->cbBuffer -= Length;
  1684. pHexEditData->CaretIndex = MinimumSelectedIndex;
  1685. pHexEditData->MinimumSelectedIndex = MinimumSelectedIndex;
  1686. pHexEditData->MaximumSelectedIndex = MinimumSelectedIndex;
  1687. HexEdit_SetScrollInfo(hWnd);
  1688. HexEdit_EnsureCaretVisible(hWnd);
  1689. UpdateRect.left = 0;
  1690. UpdateRect.right = pHexEditData->cxWindow;
  1691. UpdateRect.top = (MinimumSelectedIndex / BYTES_PER_HEXEDIT_LINE -
  1692. pHexEditData->FirstVisibleLine) * pHexEditData->FontHeight;
  1693. UpdateRect.bottom = pHexEditData->cyWindow;
  1694. SendMessage(GetParent(hWnd), WM_COMMAND,
  1695. MAKEWPARAM(GetWindowLongPtr(hWnd, GWLP_ID), EN_CHANGE), (LPARAM)hWnd);
  1696. InvalidateRect(hWnd, &UpdateRect, FALSE);
  1697. }
  1698. /*******************************************************************************
  1699. *
  1700. * HexEdit_OnCopy
  1701. *
  1702. * DESCRIPTION:
  1703. *
  1704. * PARAMETERS:
  1705. * hWnd, handle of HexEdit window.
  1706. *
  1707. *******************************************************************************/
  1708. BOOL
  1709. PASCAL
  1710. HexEdit_OnCopy(
  1711. HWND hWnd
  1712. )
  1713. {
  1714. BOOL fSuccess;
  1715. int cbClipboardData;
  1716. LPBYTE lpStartByte;
  1717. HANDLE hClipboardData;
  1718. LPHEXEDITCLIPBOARDDATA lpClipboardData;
  1719. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1720. fSuccess = FALSE;
  1721. cbClipboardData = pHexEditData->MaximumSelectedIndex -
  1722. pHexEditData->MinimumSelectedIndex;
  1723. if (cbClipboardData != 0) {
  1724. lpStartByte = pHexEditData->pBuffer +
  1725. pHexEditData->MinimumSelectedIndex;
  1726. if (OpenClipboard(hWnd)) {
  1727. if ((hClipboardData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
  1728. cbClipboardData + sizeof(HEXEDITCLIPBOARDDATA) - 1)) != NULL) {
  1729. lpClipboardData = (LPHEXEDITCLIPBOARDDATA)
  1730. GlobalLock(hClipboardData);
  1731. CopyMemory(lpClipboardData-> Data, lpStartByte,
  1732. cbClipboardData);
  1733. lpClipboardData-> cbSize = cbClipboardData;
  1734. GlobalUnlock(hClipboardData);
  1735. EmptyClipboard();
  1736. SetClipboardData(s_HexEditClipboardFormat, hClipboardData);
  1737. fSuccess = TRUE;
  1738. }
  1739. CloseClipboard();
  1740. }
  1741. }
  1742. return fSuccess;
  1743. }
  1744. /*******************************************************************************
  1745. *
  1746. * HexEdit_OnPaste
  1747. *
  1748. * DESCRIPTION:
  1749. *
  1750. * PARAMETERS:
  1751. * hWnd, handle of HexEdit window.
  1752. *
  1753. *******************************************************************************/
  1754. BOOL
  1755. PASCAL
  1756. HexEdit_OnPaste(
  1757. HWND hWnd
  1758. )
  1759. {
  1760. BOOL fSuccess;
  1761. HANDLE hClipboardData;
  1762. LPHEXEDITCLIPBOARDDATA lpClipboardData;
  1763. PBYTE pCaretByte;
  1764. DWORD cbSize;
  1765. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1766. fSuccess = FALSE;
  1767. if (pHexEditData->Flags & HEF_INSERTATLOWNIBBLE) {
  1768. pHexEditData->Flags &= ~HEF_INSERTATLOWNIBBLE;
  1769. pHexEditData->CaretIndex++;
  1770. }
  1771. if (OpenClipboard(hWnd)) {
  1772. if ((hClipboardData = GetClipboardData(s_HexEditClipboardFormat)) !=
  1773. NULL) {
  1774. lpClipboardData = (LPHEXEDITCLIPBOARDDATA)
  1775. GlobalLock(hClipboardData);
  1776. if (pHexEditData->cbBuffer + lpClipboardData-> cbSize <=
  1777. MAXDATA_LENGTH) {
  1778. if (pHexEditData->MinimumSelectedIndex !=
  1779. pHexEditData->MaximumSelectedIndex)
  1780. HexEdit_DeleteRange(hWnd, VK_BACK);
  1781. //
  1782. // Make room for the new bytes by shifting all bytes after the
  1783. // the insertion point down the necessary amount.
  1784. //
  1785. pCaretByte = pHexEditData->pBuffer + pHexEditData->CaretIndex;
  1786. cbSize = lpClipboardData-> cbSize;
  1787. MoveMemory(pCaretByte + cbSize, pCaretByte,
  1788. pHexEditData->cbBuffer - pHexEditData->CaretIndex);
  1789. CopyMemory(pCaretByte, lpClipboardData-> Data, cbSize);
  1790. pHexEditData->cbBuffer += cbSize;
  1791. pHexEditData->CaretIndex += cbSize;
  1792. HexEdit_SetScrollInfo(hWnd);
  1793. fSuccess = TRUE;
  1794. }
  1795. GlobalUnlock(hClipboardData);
  1796. }
  1797. CloseClipboard();
  1798. }
  1799. return fSuccess;
  1800. }
  1801. /*******************************************************************************
  1802. *
  1803. * HexEdit_OnContextMenu
  1804. *
  1805. * DESCRIPTION:
  1806. *
  1807. * PARAMETERS:
  1808. * hWnd, handle of HexEdit window.
  1809. * x, horizontal position of the cursor.
  1810. * y, vertical position of the cursor.
  1811. *
  1812. *******************************************************************************/
  1813. VOID
  1814. PASCAL
  1815. HexEdit_OnContextMenu(
  1816. HWND hWnd,
  1817. int x,
  1818. int y
  1819. )
  1820. {
  1821. HMENU hContextMenu;
  1822. HMENU hContextPopupMenu;
  1823. int MenuCommand;
  1824. HEXEDITDATA * pHexEditData = (HEXEDITDATA *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
  1825. //
  1826. // Give us the focus if we don't already have it.
  1827. //
  1828. if (!(pHexEditData->Flags & HEF_FOCUS))
  1829. SetFocus(hWnd);
  1830. //
  1831. // Load the HexEdit context menu from our resources.
  1832. //
  1833. if ((hContextMenu = LoadMenu(g_hInstance,
  1834. MAKEINTRESOURCE(IDM_HEXEDIT_CONTEXT))) == NULL)
  1835. return;
  1836. hContextPopupMenu = GetSubMenu(hContextMenu, 0);
  1837. //
  1838. // Disable editing menu options as appropriate.
  1839. //
  1840. if (pHexEditData->MinimumSelectedIndex ==
  1841. pHexEditData->MaximumSelectedIndex) {
  1842. EnableMenuItem(hContextPopupMenu, IDKEY_COPY, MF_BYCOMMAND | MF_GRAYED);
  1843. EnableMenuItem(hContextPopupMenu, IDKEY_CUT, MF_BYCOMMAND | MF_GRAYED);
  1844. EnableMenuItem(hContextPopupMenu, VK_DELETE, MF_BYCOMMAND | MF_GRAYED);
  1845. }
  1846. if (!IsClipboardFormatAvailable(s_HexEditClipboardFormat))
  1847. EnableMenuItem(hContextPopupMenu, IDKEY_PASTE, MF_BYCOMMAND |
  1848. MF_GRAYED);
  1849. if (pHexEditData->MinimumSelectedIndex == 0 &&
  1850. pHexEditData->MaximumSelectedIndex == pHexEditData->cbBuffer)
  1851. EnableMenuItem(hContextPopupMenu, ID_SELECTALL, MF_BYCOMMAND |
  1852. MF_GRAYED);
  1853. //
  1854. // Display and handle the selected command.
  1855. //
  1856. MenuCommand = TrackPopupMenuEx(hContextPopupMenu, TPM_RETURNCMD |
  1857. TPM_RIGHTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, x, y, hWnd, NULL);
  1858. DestroyMenu(hContextMenu);
  1859. switch (MenuCommand) {
  1860. case IDKEY_COPY:
  1861. case IDKEY_PASTE:
  1862. case IDKEY_CUT:
  1863. case VK_DELETE:
  1864. HexEdit_OnChar(hWnd, (TCHAR) MenuCommand, 0);
  1865. break;
  1866. case ID_SELECTALL:
  1867. pHexEditData->MinimumSelectedIndex = 0;
  1868. pHexEditData->MaximumSelectedIndex = pHexEditData->cbBuffer;
  1869. pHexEditData->CaretIndex = pHexEditData->cbBuffer;
  1870. HexEdit_SetCaretPosition(hWnd);
  1871. InvalidateRect(hWnd, NULL, FALSE);
  1872. break;
  1873. }
  1874. }