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