1 /* 2 * Hex editor control 3 * 4 * Copyright (C) 2004 Thomas Weidenmueller <w3seek@reactos.com> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #include "regedit.h" 22 23 typedef struct 24 { 25 HWND hWndSelf; 26 HWND hWndParent; 27 HLOCAL hBuffer; 28 DWORD style; 29 DWORD MaxBuffer; 30 INT ColumnsPerLine; 31 INT nLines; 32 INT nVisibleLinesComplete; 33 INT nVisibleLines; 34 INT Index; 35 INT LineHeight; 36 INT CharWidth; 37 HFONT hFont; 38 BOOL SbVisible; 39 40 INT LeftMargin; 41 INT AddressSpacing; 42 INT SplitSpacing; 43 44 BOOL EditingField; 45 INT CaretCol; 46 INT CaretLine; 47 BOOL InMid; 48 49 INT SelStart; 50 INT SelEnd; 51 } HEXEDIT_DATA, *PHEXEDIT_DATA; 52 53 static const WCHAR ClipboardFormatName[] = L"RegEdit_HexData"; 54 static UINT ClipboardFormatID = 0; 55 56 /* hit test codes */ 57 #define HEHT_LEFTMARGIN (0x1) 58 #define HEHT_ADDRESS (0x2) 59 #define HEHT_ADDRESSSPACING (0x3) 60 #define HEHT_HEXDUMP (0x4) 61 #define HEHT_HEXDUMPSPACING (0x5) 62 #define HEHT_ASCIIDUMP (0x6) 63 #define HEHT_RIGHTMARGIN (0x7) 64 65 LRESULT CALLBACK HexEditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); 66 67 ATOM 68 WINAPI 69 RegisterHexEditorClass(HINSTANCE hInstance) 70 { 71 WNDCLASSEXW WndClass; 72 73 ClipboardFormatID = RegisterClipboardFormatW(ClipboardFormatName); 74 75 ZeroMemory(&WndClass, sizeof(WNDCLASSEXW)); 76 WndClass.cbSize = sizeof(WNDCLASSEXW); 77 WndClass.style = CS_DBLCLKS; 78 WndClass.lpfnWndProc = HexEditWndProc; 79 WndClass.cbWndExtra = sizeof(PHEXEDIT_DATA); 80 WndClass.hInstance = hInstance; 81 WndClass.hCursor = LoadCursorW(NULL, IDC_IBEAM); 82 WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 83 WndClass.lpszClassName = HEX_EDIT_CLASS_NAME; 84 85 return RegisterClassEx(&WndClass); 86 } 87 88 BOOL 89 WINAPI 90 UnregisterHexEditorClass(HINSTANCE hInstance) 91 { 92 return UnregisterClassW(HEX_EDIT_CLASS_NAME, hInstance); 93 } 94 95 /*** Helper functions *********************************************************/ 96 97 static VOID 98 HEXEDIT_MoveCaret(PHEXEDIT_DATA hed, BOOL Scroll) 99 { 100 SCROLLINFO si; 101 102 si.cbSize = sizeof(SCROLLINFO); 103 si.fMask = SIF_POS; 104 GetScrollInfo(hed->hWndSelf, SB_VERT, &si); 105 106 if(Scroll) 107 { 108 if(si.nPos > hed->CaretLine) 109 { 110 si.nPos = hed->CaretLine; 111 SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE); 112 GetScrollInfo(hed->hWndSelf, SB_VERT, &si); 113 InvalidateRect(hed->hWndSelf, NULL, TRUE); 114 } 115 else if(hed->CaretLine >= (hed->nVisibleLinesComplete + si.nPos)) 116 { 117 si.nPos = hed->CaretLine - hed->nVisibleLinesComplete + 1; 118 SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE); 119 GetScrollInfo(hed->hWndSelf, SB_VERT, &si); 120 InvalidateRect(hed->hWndSelf, NULL, TRUE); 121 } 122 } 123 124 if(hed->EditingField) 125 SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + (3 * hed->CaretCol) + hed->InMid * 2) * hed->CharWidth) - 1, (hed->CaretLine - si.nPos) * hed->LineHeight); 126 else 127 SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine) + hed->CaretCol) * hed->CharWidth) - 2, (hed->CaretLine - si.nPos) * hed->LineHeight); 128 } 129 130 static VOID 131 HEXEDIT_Update(PHEXEDIT_DATA hed) 132 { 133 SCROLLINFO si; 134 RECT rcClient; 135 BOOL SbVisible; 136 INT bufsize, cvislines; 137 138 GetClientRect(hed->hWndSelf, &rcClient); 139 hed->style = GetWindowLongPtr(hed->hWndSelf, GWL_STYLE); 140 141 bufsize = (hed->hBuffer ? (INT) LocalSize(hed->hBuffer) : 0); 142 hed->nLines = max(bufsize / hed->ColumnsPerLine, 1); 143 if(bufsize > hed->ColumnsPerLine && (bufsize % hed->ColumnsPerLine) > 0) 144 { 145 hed->nLines++; 146 } 147 148 if(hed->LineHeight > 0) 149 { 150 hed->nVisibleLinesComplete = cvislines = rcClient.bottom / hed->LineHeight; 151 hed->nVisibleLines = hed->nVisibleLinesComplete; 152 if(rcClient.bottom % hed->LineHeight) 153 { 154 hed->nVisibleLines++; 155 } 156 } 157 else 158 { 159 hed->nVisibleLines = cvislines = 0; 160 } 161 162 SbVisible = bufsize > 0 && cvislines < hed->nLines; 163 ShowScrollBar(hed->hWndSelf, SB_VERT, SbVisible); 164 165 /* update scrollbar */ 166 si.cbSize = sizeof(SCROLLINFO); 167 si.fMask = SIF_RANGE | SIF_PAGE; 168 si.nMin = 0; 169 si.nMax = ((bufsize > 0) ? hed->nLines - 1 : 0); 170 si.nPage = ((hed->LineHeight > 0) ? rcClient.bottom / hed->LineHeight : 0); 171 SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE); 172 173 if(IsWindowVisible(hed->hWndSelf) && SbVisible != hed->SbVisible) 174 { 175 InvalidateRect(hed->hWndSelf, NULL, TRUE); 176 } 177 178 hed->SbVisible = SbVisible; 179 } 180 181 static HFONT 182 HEXEDIT_GetFixedFont(VOID) 183 { 184 LOGFONT lf; 185 GetObject(GetStockObject(ANSI_FIXED_FONT), sizeof(LOGFONT), &lf); 186 return CreateFontIndirect(&lf); 187 } 188 189 static VOID 190 HEXEDIT_PaintLines(PHEXEDIT_DATA hed, HDC hDC, DWORD ScrollPos, DWORD First, DWORD Last, RECT *rc) 191 { 192 DWORD dx, dy, linestart; 193 INT i, isave, i0, i1, x; 194 PBYTE buf, current, end, line; 195 size_t bufsize; 196 WCHAR hex[3], addr[17]; 197 RECT rct, rct2; 198 199 FillRect(hDC, rc, (HBRUSH)(COLOR_WINDOW + 1)); 200 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); 201 202 if (hed->SelStart < hed->SelEnd) 203 { 204 i0 = hed->SelStart; 205 i1 = hed->SelEnd; 206 } 207 else 208 { 209 i0 = hed->SelEnd; 210 i1 = hed->SelStart; 211 } 212 213 if(hed->hBuffer) 214 { 215 bufsize = LocalSize(hed->hBuffer); 216 buf = LocalLock(hed->hBuffer); 217 } 218 else 219 { 220 buf = NULL; 221 bufsize = 0; 222 223 if(ScrollPos + First == 0) 224 { 225 /* draw address */ 226 wsprintf(addr, L"%04X", 0); 227 TextOutW(hDC, hed->LeftMargin, First * hed->LineHeight, addr, 4); 228 } 229 } 230 231 if(buf) 232 { 233 end = buf + bufsize; 234 dy = First * hed->LineHeight; 235 linestart = (ScrollPos + First) * hed->ColumnsPerLine; 236 i = linestart; 237 current = buf + linestart; 238 Last = min(hed->nLines - ScrollPos, Last); 239 240 SetBkMode(hDC, TRANSPARENT); 241 while(First <= Last && current < end) 242 { 243 DWORD dh; 244 245 dx = hed->LeftMargin; 246 247 /* draw address */ 248 wsprintf(addr, L"%04lX", linestart); 249 TextOutW(hDC, dx, dy, addr, 4); 250 251 dx += ((4 + hed->AddressSpacing) * hed->CharWidth); 252 dh = (3 * hed->CharWidth); 253 254 rct.left = dx; 255 rct.top = dy; 256 rct.right = rct.left + dh; 257 rct.bottom = dy + hed->LineHeight; 258 259 /* draw hex map */ 260 dx += (hed->CharWidth / 2); 261 line = current; 262 isave = i; 263 for(x = 0; x < hed->ColumnsPerLine && current < end; x++) 264 { 265 rct.left += dh; 266 rct.right += dh; 267 268 wsprintf(hex, L"%02X", *(current++)); 269 if (i0 <= i && i < i1) 270 { 271 rct2.left = dx; 272 rct2.top = dy; 273 rct2.right = dx + hed->CharWidth * 2 + 1; 274 rct2.bottom = dy + hed->LineHeight; 275 InflateRect(&rct2, hed->CharWidth / 2, 0); 276 FillRect(hDC, &rct2, (HBRUSH)(COLOR_HIGHLIGHT + 1)); 277 SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 278 ExtTextOutW(hDC, dx, dy, 0, &rct, hex, 2, NULL); 279 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); 280 } 281 else 282 ExtTextOutW(hDC, dx, dy, ETO_OPAQUE, &rct, hex, 2, NULL); 283 dx += dh; 284 i++; 285 } 286 287 /* draw ascii map */ 288 dx = ((4 + hed->AddressSpacing + hed->SplitSpacing + (hed->ColumnsPerLine * 3)) * hed->CharWidth); 289 current = line; 290 i = isave; 291 for(x = 0; x < hed->ColumnsPerLine && current < end; x++) 292 { 293 wsprintf(hex, L"%C", *(current++)); 294 hex[0] = ((hex[0] & L'\x007f') >= L' ' ? hex[0] : L'.'); 295 if (i0 <= i && i < i1) 296 { 297 rct2.left = dx; 298 rct2.top = dy; 299 rct2.right = dx + hed->CharWidth; 300 rct2.bottom = dy + hed->LineHeight; 301 FillRect(hDC, &rct2, (HBRUSH)(COLOR_HIGHLIGHT + 1)); 302 SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 303 TextOutW(hDC, dx, dy, hex, 1); 304 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT)); 305 } 306 else 307 TextOutW(hDC, dx, dy, hex, 1); 308 dx += hed->CharWidth; 309 i++; 310 } 311 312 dy += hed->LineHeight; 313 linestart += hed->ColumnsPerLine; 314 First++; 315 } 316 } 317 318 LocalUnlock(hed->hBuffer); 319 } 320 321 static DWORD 322 HEXEDIT_HitRegionTest(PHEXEDIT_DATA hed, POINTS pt) 323 { 324 int d; 325 326 if(pt.x <= hed->LeftMargin) 327 { 328 return HEHT_LEFTMARGIN; 329 } 330 331 pt.x -= hed->LeftMargin; 332 d = (4 * hed->CharWidth); 333 if(pt.x <= d) 334 { 335 return HEHT_ADDRESS; 336 } 337 338 pt.x -= d; 339 d = (hed->AddressSpacing * hed->CharWidth); 340 if(pt.x <= d) 341 { 342 return HEHT_ADDRESSSPACING; 343 } 344 345 pt.x -= d; 346 d = ((3 * hed->ColumnsPerLine + 1) * hed->CharWidth); 347 if(pt.x <= d) 348 { 349 return HEHT_HEXDUMP; 350 } 351 352 pt.x -= d; 353 d = ((hed->SplitSpacing - 1) * hed->CharWidth); 354 if(pt.x <= d) 355 { 356 return HEHT_HEXDUMPSPACING; 357 } 358 359 pt.x -= d; 360 d = (hed->ColumnsPerLine * hed->CharWidth); 361 if(pt.x <= d) 362 { 363 return HEHT_ASCIIDUMP; 364 } 365 366 return HEHT_RIGHTMARGIN; 367 } 368 369 static DWORD 370 HEXEDIT_IndexFromPoint(PHEXEDIT_DATA hed, POINTS pt, DWORD Hit, POINT *EditPos, BOOL *EditField) 371 { 372 SCROLLINFO si; 373 DWORD Index, bufsize; 374 375 si.cbSize = sizeof(SCROLLINFO); 376 si.fMask = SIF_POS; 377 GetScrollInfo(hed->hWndSelf, SB_VERT, &si); 378 379 EditPos->x = 0; 380 381 if(hed->LineHeight > 0) 382 { 383 EditPos->y = min(si.nPos + (pt.y / hed->LineHeight), hed->nLines - 1); 384 } 385 else 386 { 387 EditPos->y = si.nPos; 388 } 389 390 switch(Hit) 391 { 392 case HEHT_LEFTMARGIN: 393 case HEHT_ADDRESS: 394 case HEHT_ADDRESSSPACING: 395 case HEHT_HEXDUMP: 396 pt.x -= (SHORT) hed->LeftMargin + ((4 + hed->AddressSpacing) * hed->CharWidth); 397 *EditField = TRUE; 398 break; 399 400 default: 401 pt.x -= hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine)) * hed->CharWidth); 402 *EditField = FALSE; 403 break; 404 } 405 406 if(pt.x > 0) 407 { 408 INT BlockWidth = (*EditField ? hed->CharWidth * 3 : hed->CharWidth); 409 EditPos->x = min(hed->ColumnsPerLine, (pt.x + BlockWidth / 2) / BlockWidth); 410 } 411 412 bufsize = (hed->hBuffer ? (DWORD) LocalSize(hed->hBuffer) : 0); 413 Index = (EditPos->y * hed->ColumnsPerLine) + EditPos->x; 414 if(Index > bufsize) 415 { 416 INT tmp = bufsize % hed->ColumnsPerLine; 417 Index = bufsize; 418 EditPos->x = (tmp == 0 ? hed->ColumnsPerLine : tmp); 419 } 420 return Index; 421 } 422 423 static VOID 424 HEXEDIT_Copy(PHEXEDIT_DATA hed) 425 { 426 PBYTE pb, buf; 427 UINT cb; 428 INT i0, i1; 429 HGLOBAL hGlobal; 430 431 if (hed->SelStart < hed->SelEnd) 432 { 433 i0 = hed->SelStart; 434 i1 = hed->SelEnd; 435 } 436 else 437 { 438 i0 = hed->SelEnd; 439 i1 = hed->SelStart; 440 } 441 442 cb = i1 - i0; 443 if (cb == 0) 444 return; 445 446 hGlobal = GlobalAlloc(GHND | GMEM_SHARE, cb + sizeof(DWORD)); 447 if (hGlobal == NULL) 448 return; 449 450 pb = GlobalLock(hGlobal); 451 if (pb) 452 { 453 *(PDWORD)pb = cb; 454 pb += sizeof(DWORD); 455 buf = (PBYTE) LocalLock(hed->hBuffer); 456 if (buf) 457 { 458 CopyMemory(pb, buf + i0, cb); 459 LocalUnlock(hed->hBuffer); 460 } 461 GlobalUnlock(hGlobal); 462 463 if (OpenClipboard(hed->hWndSelf)) 464 { 465 EmptyClipboard(); 466 SetClipboardData(ClipboardFormatID, hGlobal); 467 CloseClipboard(); 468 } 469 } 470 else 471 GlobalFree(hGlobal); 472 } 473 474 static VOID 475 HEXEDIT_Delete(PHEXEDIT_DATA hed) 476 { 477 PBYTE buf; 478 INT i0, i1; 479 UINT bufsize; 480 481 if (hed->SelStart < hed->SelEnd) 482 { 483 i0 = hed->SelStart; 484 i1 = hed->SelEnd; 485 } 486 else 487 { 488 i0 = hed->SelEnd; 489 i1 = hed->SelStart; 490 } 491 492 if (i0 != i1) 493 { 494 bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0); 495 buf = (PBYTE) LocalLock(hed->hBuffer); 496 if (buf) 497 { 498 MoveMemory(buf + i0, buf + i1, bufsize - i1); 499 LocalUnlock(hed->hBuffer); 500 } 501 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0)); 502 hed->InMid = FALSE; 503 hed->Index = hed->SelStart = hed->SelEnd = i0; 504 hed->CaretCol = hed->Index % hed->ColumnsPerLine; 505 hed->CaretLine = hed->Index / hed->ColumnsPerLine; 506 InvalidateRect(hed->hWndSelf, NULL, TRUE); 507 HEXEDIT_MoveCaret(hed, TRUE); 508 } 509 } 510 511 static VOID 512 HEXEDIT_Paste(PHEXEDIT_DATA hed) 513 { 514 HGLOBAL hGlobal; 515 UINT bufsize; 516 PBYTE pb, buf; 517 DWORD cb; 518 519 HEXEDIT_Delete(hed); 520 bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0); 521 522 if (OpenClipboard(hed->hWndSelf)) 523 { 524 hGlobal = GetClipboardData(ClipboardFormatID); 525 if (hGlobal != NULL) 526 { 527 pb = (PBYTE) GlobalLock(hGlobal); 528 cb = *(PDWORD) pb; 529 pb += sizeof(DWORD); 530 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize + cb); 531 buf = (PBYTE) LocalLock(hed->hBuffer); 532 if (buf) 533 { 534 MoveMemory(buf + hed->Index + cb, buf + hed->Index, 535 bufsize - hed->Index); 536 CopyMemory(buf + hed->Index, pb, cb); 537 LocalUnlock(hed->hBuffer); 538 } 539 GlobalUnlock(hGlobal); 540 } 541 CloseClipboard(); 542 } 543 InvalidateRect(hed->hWndSelf, NULL, TRUE); 544 HEXEDIT_MoveCaret(hed, TRUE); 545 } 546 547 static VOID 548 HEXEDIT_Cut(PHEXEDIT_DATA hed) 549 { 550 HEXEDIT_Copy(hed); 551 HEXEDIT_Delete(hed); 552 } 553 554 static VOID 555 HEXEDIT_SelectAll(PHEXEDIT_DATA hed) 556 { 557 INT bufsize; 558 559 bufsize = (hed->hBuffer ? (INT) LocalSize(hed->hBuffer) : 0); 560 hed->Index = hed->SelStart = 0; 561 hed->SelEnd = bufsize; 562 InvalidateRect(hed->hWndSelf, NULL, TRUE); 563 HEXEDIT_MoveCaret(hed, TRUE); 564 } 565 566 /*** Control specific messages ************************************************/ 567 568 static LRESULT 569 HEXEDIT_HEM_LOADBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size) 570 { 571 if(Buffer != NULL && Size > 0) 572 { 573 LPVOID buf; 574 575 if(hed->MaxBuffer > 0 && Size > hed->MaxBuffer) 576 { 577 Size = hed->MaxBuffer; 578 } 579 580 if(hed->hBuffer) 581 { 582 if(Size > 0) 583 { 584 if(LocalSize(hed->hBuffer) != Size) 585 { 586 hed->hBuffer = LocalReAlloc(hed->hBuffer, Size, LMEM_MOVEABLE | LMEM_ZEROINIT); 587 } 588 } 589 else 590 { 591 hed->hBuffer = LocalFree(hed->hBuffer); 592 hed->Index = 0; 593 HEXEDIT_Update(hed); 594 595 return 0; 596 } 597 } 598 else if(Size > 0) 599 { 600 hed->hBuffer = LocalAlloc(LHND, Size); 601 } 602 603 if(Size > 0) 604 { 605 buf = LocalLock(hed->hBuffer); 606 if(buf) 607 { 608 memcpy(buf, Buffer, Size); 609 } 610 else 611 Size = 0; 612 LocalUnlock(hed->hBuffer); 613 } 614 615 hed->Index = 0; 616 HEXEDIT_Update(hed); 617 return Size; 618 } 619 else if(hed->hBuffer) 620 { 621 hed->Index = 0; 622 hed->hBuffer = LocalFree(hed->hBuffer); 623 HEXEDIT_Update(hed); 624 } 625 626 return 0; 627 } 628 629 static LRESULT 630 HEXEDIT_HEM_COPYBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size) 631 { 632 size_t nCpy; 633 634 if(!hed->hBuffer) 635 { 636 return 0; 637 } 638 639 if(Buffer != NULL && Size > 0) 640 { 641 nCpy = min(Size, LocalSize(hed->hBuffer)); 642 if(nCpy > 0) 643 { 644 PVOID buf; 645 646 buf = LocalLock(hed->hBuffer); 647 if(buf) 648 { 649 memcpy(Buffer, buf, nCpy); 650 } 651 else 652 nCpy = 0; 653 LocalUnlock(hed->hBuffer); 654 } 655 return nCpy; 656 } 657 658 return (LRESULT)LocalSize(hed->hBuffer); 659 } 660 661 static LRESULT 662 HEXEDIT_HEM_SETMAXBUFFERSIZE(PHEXEDIT_DATA hed, DWORD nMaxSize) 663 { 664 hed->MaxBuffer = nMaxSize; 665 if (hed->MaxBuffer == 0) 666 { 667 hed->hBuffer = LocalFree(hed->hBuffer); 668 return 0; 669 } 670 if (hed->hBuffer) 671 hed->hBuffer = LocalReAlloc(hed->hBuffer, hed->MaxBuffer, LMEM_MOVEABLE); 672 else 673 hed->hBuffer = LocalAlloc(LMEM_MOVEABLE, hed->MaxBuffer); 674 HEXEDIT_Update(hed); 675 return 0; 676 } 677 678 /*** Message Proc *************************************************************/ 679 680 static LRESULT 681 HEXEDIT_WM_NCCREATE(HWND hWnd, CREATESTRUCT *cs) 682 { 683 PHEXEDIT_DATA hed; 684 685 if(!(hed = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEXEDIT_DATA)))) 686 { 687 return FALSE; 688 } 689 690 hed->hWndSelf = hWnd; 691 hed->hWndParent = cs->hwndParent; 692 hed->style = cs->style; 693 694 hed->ColumnsPerLine = 8; 695 hed->LeftMargin = 2; 696 hed->AddressSpacing = 2; 697 hed->SplitSpacing = 2; 698 hed->EditingField = TRUE; /* in hexdump field */ 699 700 SetWindowLongPtr(hWnd, 0, (DWORD_PTR)hed); 701 HEXEDIT_Update(hed); 702 703 return TRUE; 704 } 705 706 static LRESULT 707 HEXEDIT_WM_NCDESTROY(PHEXEDIT_DATA hed) 708 { 709 if(hed->hBuffer) 710 { 711 //while(LocalUnlock(hed->hBuffer)); 712 LocalFree(hed->hBuffer); 713 } 714 715 if(hed->hFont) 716 { 717 DeleteObject(hed->hFont); 718 } 719 720 SetWindowLongPtr(hed->hWndSelf, 0, (DWORD_PTR)0); 721 HeapFree(GetProcessHeap(), 0, hed); 722 723 return 0; 724 } 725 726 static LRESULT 727 HEXEDIT_WM_CREATE(PHEXEDIT_DATA hed) 728 { 729 UNREFERENCED_PARAMETER(hed); 730 return 1; 731 } 732 733 static LRESULT 734 HEXEDIT_WM_SETFOCUS(PHEXEDIT_DATA hed) 735 { 736 CreateCaret(hed->hWndSelf, 0, 1, hed->LineHeight); 737 HEXEDIT_MoveCaret(hed, FALSE); 738 ShowCaret(hed->hWndSelf); 739 return 0; 740 } 741 742 static LRESULT 743 HEXEDIT_WM_KILLFOCUS(PHEXEDIT_DATA hed) 744 { 745 UNREFERENCED_PARAMETER(hed); 746 DestroyCaret(); 747 return 0; 748 } 749 750 static LRESULT 751 HEXEDIT_WM_VSCROLL(PHEXEDIT_DATA hed, WORD ThumbPosition, WORD SbCmd) 752 { 753 int ScrollY; 754 SCROLLINFO si; 755 756 UNREFERENCED_PARAMETER(ThumbPosition); 757 758 ZeroMemory(&si, sizeof(SCROLLINFO)); 759 si.cbSize = sizeof(SCROLLINFO); 760 si.fMask = SIF_ALL; 761 GetScrollInfo(hed->hWndSelf, SB_VERT, &si); 762 763 ScrollY = si.nPos; 764 switch(SbCmd) 765 { 766 case SB_TOP: 767 si.nPos = si.nMin; 768 break; 769 770 case SB_BOTTOM: 771 si.nPos = si.nMax; 772 break; 773 774 case SB_LINEUP: 775 si.nPos--; 776 break; 777 778 case SB_LINEDOWN: 779 si.nPos++; 780 break; 781 782 case SB_PAGEUP: 783 si.nPos -= si.nPage; 784 break; 785 786 case SB_PAGEDOWN: 787 si.nPos += si.nPage; 788 break; 789 790 case SB_THUMBTRACK: 791 si.nPos = si.nTrackPos; 792 break; 793 } 794 795 si.fMask = SIF_POS; 796 SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE); 797 GetScrollInfo(hed->hWndSelf, SB_VERT, &si); 798 799 if(si.nPos != ScrollY) 800 { 801 ScrollWindow(hed->hWndSelf, 0, (ScrollY - si.nPos) * hed->LineHeight, NULL, NULL); 802 UpdateWindow(hed->hWndSelf); 803 } 804 805 return 0; 806 } 807 808 static LRESULT 809 HEXEDIT_WM_SETFONT(PHEXEDIT_DATA hed, HFONT hFont, BOOL bRedraw) 810 { 811 HDC hDC; 812 TEXTMETRIC tm; 813 HFONT hOldFont = 0; 814 815 if(hFont == 0) 816 { 817 hFont = HEXEDIT_GetFixedFont(); 818 } 819 820 hed->hFont = hFont; 821 hDC = GetDC(hed->hWndSelf); 822 if(hFont) 823 { 824 hOldFont = SelectObject(hDC, hFont); 825 } 826 GetTextMetrics(hDC, &tm); 827 hed->LineHeight = tm.tmHeight; 828 hed->CharWidth = tm.tmAveCharWidth; 829 if(hOldFont) 830 { 831 SelectObject(hDC, hOldFont); 832 } 833 ReleaseDC(hed->hWndSelf, hDC); 834 835 if(bRedraw) 836 { 837 InvalidateRect(hed->hWndSelf, NULL, TRUE); 838 } 839 840 return 0; 841 } 842 843 static LRESULT 844 HEXEDIT_WM_GETFONT(PHEXEDIT_DATA hed) 845 { 846 return (LRESULT)hed->hFont; 847 } 848 849 static LRESULT 850 HEXEDIT_WM_PAINT(PHEXEDIT_DATA hed) 851 { 852 PAINTSTRUCT ps; 853 SCROLLINFO si; 854 RECT rc; 855 HBITMAP hbmp, hbmpold; 856 INT nLines, nFirst; 857 HFONT hOldFont; 858 HDC hTempDC; 859 DWORD height; 860 861 if(GetUpdateRect(hed->hWndSelf, &rc, FALSE) && (hed->LineHeight > 0)) 862 { 863 ZeroMemory(&si, sizeof(SCROLLINFO)); 864 si.cbSize = sizeof(SCROLLINFO); 865 si.fMask = SIF_POS; 866 GetScrollInfo(hed->hWndSelf, SB_VERT, &si); 867 868 height = (rc.bottom - rc.top); 869 nLines = height / hed->LineHeight; 870 if((height % hed->LineHeight) > 0) 871 { 872 nLines++; 873 } 874 if(nLines > hed->nLines - si.nPos) 875 { 876 nLines = hed->nLines - si.nPos; 877 } 878 nFirst = rc.top / hed->LineHeight; 879 880 BeginPaint(hed->hWndSelf, &ps); 881 if(!(hTempDC = CreateCompatibleDC(ps.hdc))) 882 { 883 FillRect(ps.hdc, &rc, (HBRUSH)(COLOR_WINDOW + 1)); 884 goto epaint; 885 } 886 if(!(hbmp = CreateCompatibleBitmap(ps.hdc, ps.rcPaint.right, ps.rcPaint.bottom))) 887 { 888 FillRect(ps.hdc, &rc, (HBRUSH)(COLOR_WINDOW + 1)); 889 DeleteDC(hTempDC); 890 goto epaint; 891 } 892 hbmpold = SelectObject(hTempDC, hbmp); 893 hOldFont = SelectObject(hTempDC, hed->hFont); 894 HEXEDIT_PaintLines(hed, hTempDC, si.nPos, nFirst, nFirst + nLines, &ps.rcPaint); 895 BitBlt(ps.hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hTempDC, rc.left, rc.top, SRCCOPY); 896 SelectObject(hTempDC, hOldFont); 897 SelectObject(hTempDC, hbmpold); 898 899 DeleteObject(hbmp); 900 DeleteDC(hTempDC); 901 902 epaint: 903 EndPaint(hed->hWndSelf, &ps); 904 } 905 906 return 0; 907 } 908 909 static LRESULT 910 HEXEDIT_WM_MOUSEWHEEL(PHEXEDIT_DATA hed, int cyMoveLines, WORD ButtonsDown, LPPOINTS MousePos) 911 { 912 SCROLLINFO si; 913 int ScrollY; 914 915 UNREFERENCED_PARAMETER(ButtonsDown); 916 UNREFERENCED_PARAMETER(MousePos); 917 918 SetFocus(hed->hWndSelf); 919 920 si.cbSize = sizeof(SCROLLINFO); 921 si.fMask = SIF_ALL; 922 GetScrollInfo(hed->hWndSelf, SB_VERT, &si); 923 924 ScrollY = si.nPos; 925 926 si.fMask = SIF_POS; 927 si.nPos += cyMoveLines; 928 SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE); 929 930 GetScrollInfo(hed->hWndSelf, SB_VERT, &si); 931 if(si.nPos != ScrollY) 932 { 933 ScrollWindow(hed->hWndSelf, 0, (ScrollY - si.nPos) * hed->LineHeight, NULL, NULL); 934 UpdateWindow(hed->hWndSelf); 935 } 936 937 return 0; 938 } 939 940 static LRESULT 941 HEXEDIT_WM_GETDLGCODE(LPMSG Msg) 942 { 943 UNREFERENCED_PARAMETER(Msg); 944 return DLGC_WANTARROWS | DLGC_WANTCHARS; 945 } 946 947 static LRESULT 948 HEXEDIT_WM_LBUTTONDOWN(PHEXEDIT_DATA hed, INT Buttons, POINTS Pt) 949 { 950 BOOL NewField; 951 POINT EditPos; 952 DWORD Hit; 953 954 UNREFERENCED_PARAMETER(Buttons); 955 SetFocus(hed->hWndSelf); 956 957 if (GetAsyncKeyState(VK_SHIFT) < 0) 958 { 959 if (hed->EditingField) 960 hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField); 961 else 962 hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField); 963 hed->SelEnd = hed->Index; 964 } 965 else 966 { 967 Hit = HEXEDIT_HitRegionTest(hed, Pt); 968 hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, Hit, &EditPos, &NewField); 969 hed->SelStart = hed->SelEnd = hed->Index; 970 hed->EditingField = NewField; 971 SetCapture(hed->hWndSelf); 972 } 973 hed->CaretCol = EditPos.x; 974 hed->CaretLine = EditPos.y; 975 hed->InMid = FALSE; 976 InvalidateRect(hed->hWndSelf, NULL, FALSE); 977 HEXEDIT_MoveCaret(hed, TRUE); 978 979 return 0; 980 } 981 982 static LRESULT 983 HEXEDIT_WM_LBUTTONUP(PHEXEDIT_DATA hed, INT Buttons, POINTS Pt) 984 { 985 BOOL NewField; 986 POINT EditPos; 987 if (GetCapture() == hed->hWndSelf) 988 { 989 if (hed->EditingField) 990 hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField); 991 else 992 hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField); 993 hed->CaretCol = EditPos.x; 994 hed->CaretLine = EditPos.y; 995 hed->SelEnd = hed->Index; 996 ReleaseCapture(); 997 InvalidateRect(hed->hWndSelf, NULL, FALSE); 998 HEXEDIT_MoveCaret(hed, TRUE); 999 } 1000 return 0; 1001 } 1002 1003 static LRESULT 1004 HEXEDIT_WM_MOUSEMOVE(PHEXEDIT_DATA hed, INT Buttons, POINTS Pt) 1005 { 1006 BOOL NewField; 1007 POINT EditPos; 1008 if (GetCapture() == hed->hWndSelf) 1009 { 1010 if (hed->EditingField) 1011 hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField); 1012 else 1013 hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField); 1014 hed->CaretCol = EditPos.x; 1015 hed->CaretLine = EditPos.y; 1016 hed->SelEnd = hed->Index; 1017 InvalidateRect(hed->hWndSelf, NULL, FALSE); 1018 HEXEDIT_MoveCaret(hed, TRUE); 1019 } 1020 return 0; 1021 } 1022 1023 static BOOL 1024 HEXEDIT_WM_KEYDOWN(PHEXEDIT_DATA hed, INT VkCode) 1025 { 1026 size_t bufsize; 1027 PBYTE buf; 1028 INT i0, i1; 1029 1030 if(GetKeyState(VK_MENU) & 0x8000) 1031 { 1032 return FALSE; 1033 } 1034 1035 bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0); 1036 1037 if (hed->SelStart < hed->SelEnd) 1038 { 1039 i0 = hed->SelStart; 1040 i1 = hed->SelEnd; 1041 } 1042 else 1043 { 1044 i0 = hed->SelEnd; 1045 i1 = hed->SelStart; 1046 } 1047 1048 switch(VkCode) 1049 { 1050 case 'X': 1051 if (GetAsyncKeyState(VK_SHIFT) >= 0 && 1052 GetAsyncKeyState(VK_CONTROL) < 0 && hed->SelStart != hed->SelEnd) 1053 HEXEDIT_Cut(hed); 1054 else 1055 return TRUE; 1056 break; 1057 1058 case 'C': 1059 if (GetAsyncKeyState(VK_SHIFT) >= 0 && 1060 GetAsyncKeyState(VK_CONTROL) < 0 && hed->SelStart != hed->SelEnd) 1061 HEXEDIT_Copy(hed); 1062 else 1063 return TRUE; 1064 break; 1065 1066 case 'V': 1067 if (GetAsyncKeyState(VK_SHIFT) >= 0 && GetAsyncKeyState(VK_CONTROL) < 0) 1068 HEXEDIT_Paste(hed); 1069 else 1070 return TRUE; 1071 break; 1072 1073 case 'A': 1074 if (GetAsyncKeyState(VK_SHIFT) >= 0 && GetAsyncKeyState(VK_CONTROL) < 0) 1075 HEXEDIT_SelectAll(hed); 1076 else 1077 return TRUE; 1078 break; 1079 1080 case VK_INSERT: 1081 if (hed->SelStart != hed->SelEnd) 1082 { 1083 if (GetAsyncKeyState(VK_SHIFT) >= 0 && GetAsyncKeyState(VK_CONTROL) < 0) 1084 HEXEDIT_Copy(hed); 1085 } 1086 if (GetAsyncKeyState(VK_SHIFT) < 0 && GetAsyncKeyState(VK_CONTROL) >= 0) 1087 HEXEDIT_Paste(hed); 1088 break; 1089 1090 case VK_DELETE: 1091 if (GetAsyncKeyState(VK_SHIFT) < 0 && GetAsyncKeyState(VK_CONTROL) >= 0 && 1092 hed->SelStart != hed->SelEnd) 1093 HEXEDIT_Copy(hed); 1094 if (i0 != i1) 1095 { 1096 buf = (PBYTE) LocalLock(hed->hBuffer); 1097 if (buf) 1098 { 1099 MoveMemory(buf + i0, buf + i1, bufsize - i1); 1100 LocalUnlock(hed->hBuffer); 1101 } 1102 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0)); 1103 hed->InMid = FALSE; 1104 hed->Index = hed->SelStart = hed->SelEnd = i0; 1105 hed->CaretCol = hed->Index % hed->ColumnsPerLine; 1106 hed->CaretLine = hed->Index / hed->ColumnsPerLine; 1107 } 1108 else 1109 { 1110 if (hed->InMid && hed->EditingField) 1111 { 1112 buf = (PBYTE) LocalLock(hed->hBuffer); 1113 if (buf) 1114 { 1115 MoveMemory(buf + hed->Index, buf + hed->Index + 1, 1116 bufsize - hed->Index - 1); 1117 LocalUnlock(hed->hBuffer); 1118 } 1119 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1); 1120 hed->InMid = FALSE; 1121 } 1122 else if (hed->Index < bufsize) 1123 { 1124 buf = (PBYTE) LocalLock(hed->hBuffer); 1125 if (buf) 1126 { 1127 MoveMemory(buf + hed->Index, buf + hed->Index + 1, 1128 bufsize - hed->Index - 1); 1129 LocalUnlock(hed->hBuffer); 1130 } 1131 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1); 1132 } 1133 } 1134 InvalidateRect(hed->hWndSelf, NULL, TRUE); 1135 HEXEDIT_MoveCaret(hed, TRUE); 1136 break; 1137 1138 case VK_BACK: 1139 if (i0 != i1) 1140 { 1141 buf = (PBYTE) LocalLock(hed->hBuffer); 1142 if (buf) 1143 { 1144 MoveMemory(buf + i0, buf + i1, bufsize - i1); 1145 LocalUnlock(hed->hBuffer); 1146 } 1147 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0)); 1148 hed->InMid = FALSE; 1149 hed->Index = hed->SelStart = hed->SelEnd = i0; 1150 hed->CaretCol = hed->Index % hed->ColumnsPerLine; 1151 hed->CaretLine = hed->Index / hed->ColumnsPerLine; 1152 } 1153 else 1154 { 1155 if (hed->InMid && hed->EditingField) 1156 { 1157 buf = (PBYTE) LocalLock(hed->hBuffer); 1158 if (buf) 1159 { 1160 MoveMemory(buf + hed->Index, buf + hed->Index + 1, 1161 bufsize - hed->Index - 1); 1162 LocalUnlock(hed->hBuffer); 1163 } 1164 } 1165 else if (hed->Index > 0) 1166 { 1167 buf = (PBYTE) LocalLock(hed->hBuffer); 1168 if (buf) 1169 { 1170 MoveMemory(buf + hed->Index - 1, buf + hed->Index, 1171 bufsize - hed->Index); 1172 LocalUnlock(hed->hBuffer); 1173 } 1174 hed->Index--; 1175 hed->SelStart = hed->SelEnd = hed->Index; 1176 hed->CaretCol = hed->Index % hed->ColumnsPerLine; 1177 hed->CaretLine = hed->Index / hed->ColumnsPerLine; 1178 } 1179 else 1180 return TRUE; 1181 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1); 1182 hed->InMid = FALSE; 1183 } 1184 InvalidateRect(hed->hWndSelf, NULL, TRUE); 1185 HEXEDIT_MoveCaret(hed, TRUE); 1186 break; 1187 1188 case VK_LEFT: 1189 if (hed->Index > 0) 1190 { 1191 hed->Index--; 1192 if (GetAsyncKeyState(VK_SHIFT) < 0) 1193 hed->SelEnd = hed->Index; 1194 else 1195 hed->SelStart = hed->SelEnd = hed->Index; 1196 hed->CaretCol = hed->Index % hed->ColumnsPerLine; 1197 hed->CaretLine = hed->Index / hed->ColumnsPerLine; 1198 hed->InMid = FALSE; 1199 InvalidateRect(hed->hWndSelf, NULL, TRUE); 1200 HEXEDIT_MoveCaret(hed, TRUE); 1201 } 1202 break; 1203 1204 case VK_RIGHT: 1205 if (hed->Index < (INT)bufsize) 1206 { 1207 hed->Index++; 1208 if (GetAsyncKeyState(VK_SHIFT) < 0) 1209 hed->SelEnd = hed->Index; 1210 else 1211 hed->SelStart = hed->SelEnd = hed->Index; 1212 hed->CaretCol = hed->Index % hed->ColumnsPerLine; 1213 hed->CaretLine = hed->Index / hed->ColumnsPerLine; 1214 hed->InMid = FALSE; 1215 InvalidateRect(hed->hWndSelf, NULL, TRUE); 1216 HEXEDIT_MoveCaret(hed, TRUE); 1217 } 1218 break; 1219 1220 case VK_UP: 1221 if (hed->Index >= hed->ColumnsPerLine) 1222 { 1223 hed->Index -= hed->ColumnsPerLine; 1224 if (GetAsyncKeyState(VK_SHIFT) < 0) 1225 hed->SelEnd = hed->Index; 1226 else 1227 hed->SelStart = hed->SelEnd = hed->Index; 1228 hed->CaretCol = hed->Index % hed->ColumnsPerLine; 1229 hed->CaretLine = hed->Index / hed->ColumnsPerLine; 1230 hed->InMid = FALSE; 1231 InvalidateRect(hed->hWndSelf, NULL, TRUE); 1232 HEXEDIT_MoveCaret(hed, TRUE); 1233 } 1234 break; 1235 1236 case VK_DOWN: 1237 if (hed->Index + hed->ColumnsPerLine <= (INT) bufsize) 1238 hed->Index += hed->ColumnsPerLine; 1239 else 1240 hed->Index = bufsize; 1241 hed->CaretCol = hed->Index % hed->ColumnsPerLine; 1242 hed->CaretLine = hed->Index / hed->ColumnsPerLine; 1243 if (GetAsyncKeyState(VK_SHIFT) < 0) 1244 hed->SelEnd = hed->Index; 1245 else 1246 hed->SelStart = hed->SelEnd = hed->Index; 1247 hed->InMid = FALSE; 1248 InvalidateRect(hed->hWndSelf, NULL, TRUE); 1249 HEXEDIT_MoveCaret(hed, TRUE); 1250 break; 1251 1252 default: 1253 return TRUE; 1254 } 1255 1256 return FALSE; 1257 } 1258 1259 static BOOL 1260 HEXEDIT_WM_CHAR(PHEXEDIT_DATA hed, WCHAR wch) 1261 { 1262 size_t bufsize; 1263 CHAR ch = (CHAR)wch; // keep the lowest octet. 1264 PBYTE buf; 1265 INT i0, i1; 1266 1267 bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0); 1268 if (hed->SelStart < hed->SelEnd) 1269 { 1270 i0 = hed->SelStart; 1271 i1 = hed->SelEnd; 1272 } 1273 else 1274 { 1275 i0 = hed->SelEnd; 1276 i1 = hed->SelStart; 1277 } 1278 if (!hed->EditingField) 1279 { 1280 if (0x20 <= ch && ch <= 0xFF) 1281 { 1282 if (hed->SelStart != hed->SelEnd) 1283 { 1284 buf = (PBYTE) LocalLock(hed->hBuffer); 1285 if (buf) 1286 { 1287 MoveMemory(buf + i0, buf + i1, bufsize - i1); 1288 LocalUnlock(hed->hBuffer); 1289 } 1290 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0)); 1291 hed->InMid = FALSE; 1292 bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0); 1293 hed->Index = hed->SelStart = hed->SelEnd = i0; 1294 } 1295 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize + 1); 1296 buf = (PBYTE) LocalLock(hed->hBuffer); 1297 if (buf) 1298 { 1299 MoveMemory(buf + hed->Index + 1, buf + hed->Index, 1300 bufsize - hed->Index); 1301 buf[hed->Index] = ch; 1302 LocalUnlock(hed->hBuffer); 1303 } 1304 hed->Index++; 1305 hed->CaretCol = hed->Index % hed->ColumnsPerLine; 1306 hed->CaretLine = hed->Index / hed->ColumnsPerLine; 1307 InvalidateRect(hed->hWndSelf, NULL, TRUE); 1308 HEXEDIT_MoveCaret(hed, TRUE); 1309 return FALSE; 1310 } 1311 } 1312 else 1313 { 1314 if (('0' <= ch && ch <= '9') || ('A' <= ch && ch <= 'F') || 1315 ('a' <= ch && ch <= 'f')) 1316 { 1317 if (hed->SelStart != hed->SelEnd) 1318 { 1319 buf = (PBYTE) LocalLock(hed->hBuffer); 1320 if (buf) 1321 { 1322 MoveMemory(buf + i0, buf + i1, bufsize - i1); 1323 LocalUnlock(hed->hBuffer); 1324 } 1325 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0)); 1326 hed->InMid = FALSE; 1327 bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0); 1328 hed->Index = hed->SelStart = hed->SelEnd = i0; 1329 } 1330 if (hed->InMid) 1331 { 1332 buf = (PBYTE) LocalLock(hed->hBuffer); 1333 if (buf) 1334 { 1335 if ('0' <= ch && ch <= '9') 1336 buf[hed->Index] |= ch - '0'; 1337 else if ('A' <= ch && ch <= 'F') 1338 buf[hed->Index] |= ch + 10 - 'A'; 1339 else if ('a' <= ch && ch <= 'f') 1340 buf[hed->Index] |= ch + 10 - 'a'; 1341 LocalUnlock(hed->hBuffer); 1342 } 1343 hed->InMid = FALSE; 1344 hed->Index++; 1345 } 1346 else 1347 { 1348 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize + 1); 1349 buf = (PBYTE) LocalLock(hed->hBuffer); 1350 if (buf) 1351 { 1352 MoveMemory(buf + hed->Index + 1, buf + hed->Index, 1353 bufsize - hed->Index); 1354 if ('0' <= ch && ch <= '9') 1355 buf[hed->Index] = (ch - '0') << 4; 1356 else if ('A' <= ch && ch <= 'F') 1357 buf[hed->Index] = (ch + 10 - 'A') << 4; 1358 else if ('a' <= ch && ch <= 'f') 1359 buf[hed->Index] = (ch + 10 - 'a') << 4; 1360 LocalUnlock(hed->hBuffer); 1361 } 1362 hed->InMid = TRUE; 1363 } 1364 hed->CaretCol = hed->Index % hed->ColumnsPerLine; 1365 hed->CaretLine = hed->Index / hed->ColumnsPerLine; 1366 InvalidateRect(hed->hWndSelf, NULL, TRUE); 1367 HEXEDIT_MoveCaret(hed, TRUE); 1368 return FALSE; 1369 } 1370 } 1371 return TRUE; 1372 } 1373 1374 static LRESULT 1375 HEXEDIT_WM_SIZE(PHEXEDIT_DATA hed, DWORD sType, WORD NewWidth, WORD NewHeight) 1376 { 1377 UNREFERENCED_PARAMETER(sType); 1378 UNREFERENCED_PARAMETER(NewHeight); 1379 UNREFERENCED_PARAMETER(NewWidth); 1380 HEXEDIT_Update(hed); 1381 return 0; 1382 } 1383 1384 static VOID 1385 HEXEDIT_WM_CONTEXTMENU(PHEXEDIT_DATA hed, INT x, INT y) 1386 { 1387 HMENU hMenu; 1388 RECT rc; 1389 1390 if (x == -1 && y == -1) 1391 { 1392 GetWindowRect(hed->hWndSelf, &rc); 1393 x = rc.left; 1394 y = rc.top; 1395 } 1396 1397 hMenu = GetSubMenu(hPopupMenus, PM_HEXEDIT); 1398 if (hed->SelStart == hed->SelEnd) 1399 { 1400 EnableMenuItem(hMenu, ID_HEXEDIT_CUT, MF_GRAYED); 1401 EnableMenuItem(hMenu, ID_HEXEDIT_COPY, MF_GRAYED); 1402 EnableMenuItem(hMenu, ID_HEXEDIT_PASTE, MF_GRAYED); 1403 EnableMenuItem(hMenu, ID_HEXEDIT_DELETE, MF_GRAYED); 1404 } 1405 else 1406 { 1407 EnableMenuItem(hMenu, ID_HEXEDIT_CUT, MF_ENABLED); 1408 EnableMenuItem(hMenu, ID_HEXEDIT_COPY, MF_ENABLED); 1409 EnableMenuItem(hMenu, ID_HEXEDIT_PASTE, MF_ENABLED); 1410 EnableMenuItem(hMenu, ID_HEXEDIT_DELETE, MF_ENABLED); 1411 } 1412 1413 SetForegroundWindow(hed->hWndSelf); 1414 TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, x, y, 0, hed->hWndSelf, NULL); 1415 PostMessageW(hed->hWndSelf, WM_NULL, 0, 0); 1416 } 1417 1418 LRESULT CALLBACK 1419 HexEditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 1420 { 1421 PHEXEDIT_DATA hed; 1422 POINTS p; 1423 1424 hed = (PHEXEDIT_DATA)GetWindowLongPtr(hWnd, (DWORD_PTR)0); 1425 switch(uMsg) 1426 { 1427 case WM_ERASEBKGND: 1428 return TRUE; 1429 1430 case WM_PAINT: 1431 return HEXEDIT_WM_PAINT(hed); 1432 1433 case WM_KEYDOWN: 1434 return HEXEDIT_WM_KEYDOWN(hed, (INT)wParam); 1435 1436 case WM_CHAR: 1437 return HEXEDIT_WM_CHAR(hed, (WCHAR)wParam); 1438 1439 case WM_VSCROLL: 1440 return HEXEDIT_WM_VSCROLL(hed, HIWORD(wParam), LOWORD(wParam)); 1441 1442 case WM_SIZE: 1443 return HEXEDIT_WM_SIZE(hed, (DWORD)wParam, LOWORD(lParam), HIWORD(lParam)); 1444 1445 case WM_LBUTTONDOWN: 1446 { 1447 p.x = LOWORD(lParam); 1448 p.y = HIWORD(lParam); 1449 return HEXEDIT_WM_LBUTTONDOWN(hed, (INT)wParam, p); 1450 } 1451 1452 case WM_LBUTTONUP: 1453 { 1454 p.x = LOWORD(lParam); 1455 p.y = HIWORD(lParam); 1456 return HEXEDIT_WM_LBUTTONUP(hed, (INT)wParam, p); 1457 } 1458 1459 case WM_MOUSEMOVE: 1460 { 1461 p.x = LOWORD(lParam); 1462 p.y = HIWORD(lParam); 1463 return HEXEDIT_WM_MOUSEMOVE(hed, (INT)wParam, p); 1464 } 1465 1466 case WM_MOUSEWHEEL: 1467 { 1468 UINT nScrollLines = 3; 1469 int delta = 0; 1470 1471 SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &nScrollLines, 0); 1472 delta -= (SHORT)HIWORD(wParam); 1473 if(abs(delta) >= WHEEL_DELTA && nScrollLines != 0) 1474 { 1475 p.x = LOWORD(lParam); 1476 p.y = HIWORD(lParam); 1477 return HEXEDIT_WM_MOUSEWHEEL(hed, nScrollLines * (delta / WHEEL_DELTA), LOWORD(wParam), &p); 1478 } 1479 break; 1480 } 1481 1482 case HEM_LOADBUFFER: 1483 return HEXEDIT_HEM_LOADBUFFER(hed, (PVOID)wParam, (DWORD)lParam); 1484 1485 case HEM_COPYBUFFER: 1486 return HEXEDIT_HEM_COPYBUFFER(hed, (PVOID)wParam, (DWORD)lParam); 1487 1488 case HEM_SETMAXBUFFERSIZE: 1489 return HEXEDIT_HEM_SETMAXBUFFERSIZE(hed, (DWORD)lParam); 1490 1491 case WM_SETFOCUS: 1492 return HEXEDIT_WM_SETFOCUS(hed); 1493 1494 case WM_KILLFOCUS: 1495 return HEXEDIT_WM_KILLFOCUS(hed); 1496 1497 case WM_GETDLGCODE: 1498 return HEXEDIT_WM_GETDLGCODE((LPMSG)lParam); 1499 1500 case WM_SETFONT: 1501 return HEXEDIT_WM_SETFONT(hed, (HFONT)wParam, (BOOL)LOWORD(lParam)); 1502 1503 case WM_GETFONT: 1504 return HEXEDIT_WM_GETFONT(hed); 1505 1506 case WM_CREATE: 1507 return HEXEDIT_WM_CREATE(hed); 1508 1509 case WM_NCCREATE: 1510 if(!hed) 1511 { 1512 return HEXEDIT_WM_NCCREATE(hWnd, (CREATESTRUCT*)lParam); 1513 } 1514 break; 1515 1516 case WM_NCDESTROY: 1517 if(hed) 1518 { 1519 return HEXEDIT_WM_NCDESTROY(hed); 1520 } 1521 break; 1522 1523 case WM_CONTEXTMENU: 1524 HEXEDIT_WM_CONTEXTMENU(hed, (short)LOWORD(lParam), (short)HIWORD(lParam)); 1525 break; 1526 1527 case WM_COMMAND: 1528 switch(LOWORD(wParam)) 1529 { 1530 case ID_HEXEDIT_CUT: 1531 HEXEDIT_Cut(hed); 1532 break; 1533 1534 case ID_HEXEDIT_COPY: 1535 HEXEDIT_Copy(hed); 1536 break; 1537 1538 case ID_HEXEDIT_PASTE: 1539 HEXEDIT_Paste(hed); 1540 break; 1541 1542 case ID_HEXEDIT_DELETE: 1543 HEXEDIT_Delete(hed); 1544 break; 1545 1546 case ID_HEXEDIT_SELECT_ALL: 1547 HEXEDIT_SelectAll(hed); 1548 break; 1549 } 1550 break; 1551 } 1552 1553 return DefWindowProcW(hWnd, uMsg, wParam, lParam); 1554 } 1555