4 * Copyright (C) 2004 Thomas Weidenmueller <w3seek@reactos.com>
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.
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.
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
31 INT nVisibleLinesComplete
;
50 } HEXEDIT_DATA
, *PHEXEDIT_DATA
;
52 static const WCHAR ClipboardFormatName
[] = L
"RegEdit_HexData";
53 static UINT ClipboardFormatID
= 0;
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)
64 INT_PTR CALLBACK
HexEditWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
68 RegisterHexEditorClass(HINSTANCE hInstance
)
72 ClipboardFormatID
= RegisterClipboardFormatW(ClipboardFormatName
);
74 ZeroMemory(&WndClass
, sizeof(WNDCLASSEXW
));
75 WndClass
.cbSize
= sizeof(WNDCLASSEXW
);
76 WndClass
.style
= CS_DBLCLKS
;
77 WndClass
.lpfnWndProc
= (WNDPROC
)HexEditWndProc
;
78 WndClass
.cbWndExtra
= sizeof(PHEXEDIT_DATA
);
79 WndClass
.hInstance
= hInstance
;
80 WndClass
.hCursor
= LoadCursorW(NULL
, IDC_IBEAM
);
81 WndClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
82 WndClass
.lpszClassName
= HEX_EDIT_CLASS_NAME
;
84 return RegisterClassEx(&WndClass
);
89 UnregisterHexEditorClass(HINSTANCE hInstance
)
91 return UnregisterClassW(HEX_EDIT_CLASS_NAME
, hInstance
);
94 /*** Helper functions *********************************************************/
97 HEXEDIT_MoveCaret(PHEXEDIT_DATA hed
, BOOL Scroll
)
101 si
.cbSize
= sizeof(SCROLLINFO
);
103 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
107 if(si
.nPos
> hed
->CaretLine
)
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
);
114 else if(hed
->CaretLine
>= (hed
->nVisibleLinesComplete
+ si
.nPos
))
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
);
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
);
126 SetCaretPos(hed
->LeftMargin
+ ((4 + hed
->AddressSpacing
+ hed
->SplitSpacing
+ (3 * hed
->ColumnsPerLine
) + hed
->CaretCol
) * hed
->CharWidth
) - 2, (hed
->CaretLine
- si
.nPos
) * hed
->LineHeight
);
130 HEXEDIT_Update(PHEXEDIT_DATA hed
)
135 INT bufsize
, cvislines
;
137 GetClientRect(hed
->hWndSelf
, &rcClient
);
138 hed
->style
= GetWindowLongPtr(hed
->hWndSelf
, GWL_STYLE
);
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)
147 if(hed
->LineHeight
> 0)
149 hed
->nVisibleLinesComplete
= cvislines
= rcClient
.bottom
/ hed
->LineHeight
;
150 hed
->nVisibleLines
= hed
->nVisibleLinesComplete
;
151 if(rcClient
.bottom
% hed
->LineHeight
)
153 hed
->nVisibleLines
++;
158 hed
->nVisibleLines
= cvislines
= 0;
161 SbVisible
= bufsize
> 0 && cvislines
< hed
->nLines
;
162 ShowScrollBar(hed
->hWndSelf
, SB_VERT
, SbVisible
);
164 /* update scrollbar */
165 si
.cbSize
= sizeof(SCROLLINFO
);
166 si
.fMask
= SIF_RANGE
| SIF_PAGE
;
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
);
172 if(IsWindowVisible(hed
->hWndSelf
) && SbVisible
!= hed
->SbVisible
)
174 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
177 hed
->SbVisible
= SbVisible
;
181 HEXEDIT_GetFixedFont(VOID
)
184 GetObject(GetStockObject(ANSI_FIXED_FONT
), sizeof(LOGFONT
), &lf
);
185 return CreateFontIndirect(&lf
);
189 HEXEDIT_PaintLines(PHEXEDIT_DATA hed
, HDC hDC
, DWORD ScrollPos
, DWORD First
, DWORD Last
, RECT
*rc
)
191 DWORD dx
, dy
, linestart
;
192 INT i
, isave
, i0
, i1
, x
;
193 PBYTE buf
, current
, end
, line
;
195 WCHAR hex
[3], addr
[17];
198 FillRect(hDC
, rc
, (HBRUSH
)(COLOR_WINDOW
+ 1));
199 SetTextColor(hDC
, GetSysColor(COLOR_WINDOWTEXT
));
201 if (hed
->SelStart
< hed
->SelEnd
)
214 bufsize
= LocalSize(hed
->hBuffer
);
215 buf
= LocalLock(hed
->hBuffer
);
222 if(ScrollPos
+ First
== 0)
225 wsprintf(addr
, L
"%04X", 0);
226 TextOutW(hDC
, hed
->LeftMargin
, First
* hed
->LineHeight
, addr
, 4);
233 dy
= First
* hed
->LineHeight
;
234 linestart
= (ScrollPos
+ First
) * hed
->ColumnsPerLine
;
236 current
= buf
+ linestart
;
237 Last
= min(hed
->nLines
- ScrollPos
, Last
);
239 SetBkMode(hDC
, TRANSPARENT
);
240 while(First
<= Last
&& current
< end
)
244 dx
= hed
->LeftMargin
;
247 wsprintf(addr
, L
"%04lX", linestart
);
248 TextOutW(hDC
, dx
, dy
, addr
, 4);
250 dx
+= ((4 + hed
->AddressSpacing
) * hed
->CharWidth
);
251 dh
= (3 * hed
->CharWidth
);
255 rct
.right
= rct
.left
+ dh
;
256 rct
.bottom
= dy
+ hed
->LineHeight
;
259 dx
+= (hed
->CharWidth
/ 2);
262 for(x
= 0; x
< hed
->ColumnsPerLine
&& current
< end
; x
++)
267 wsprintf(hex
, L
"%02X", *(current
++));
268 if (i0
<= i
&& i
< i1
)
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 ExtTextOutW(hDC
, dx
, dy
, 0, &rct
, hex
, 2, NULL
);
278 SetTextColor(hDC
, GetSysColor(COLOR_WINDOWTEXT
));
281 ExtTextOutW(hDC
, dx
, dy
, ETO_OPAQUE
, &rct
, hex
, 2, NULL
);
287 dx
= ((4 + hed
->AddressSpacing
+ hed
->SplitSpacing
+ (hed
->ColumnsPerLine
* 3)) * hed
->CharWidth
);
290 for(x
= 0; x
< hed
->ColumnsPerLine
&& current
< end
; x
++)
292 wsprintf(hex
, L
"%C", *(current
++));
293 hex
[0] = ((hex
[0] & L
'\x007f') >= L
' ' ? hex
[0] : L
'.');
294 if (i0
<= i
&& i
< i1
)
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 TextOutW(hDC
, dx
, dy
, hex
, 1);
303 SetTextColor(hDC
, GetSysColor(COLOR_WINDOWTEXT
));
306 TextOutW(hDC
, dx
, dy
, hex
, 1);
307 dx
+= hed
->CharWidth
;
311 dy
+= hed
->LineHeight
;
312 linestart
+= hed
->ColumnsPerLine
;
317 LocalUnlock(hed
->hBuffer
);
321 HEXEDIT_HitRegionTest(PHEXEDIT_DATA hed
, POINTS pt
)
325 if(pt
.x
<= hed
->LeftMargin
)
327 return HEHT_LEFTMARGIN
;
330 pt
.x
-= hed
->LeftMargin
;
331 d
= (4 * hed
->CharWidth
);
338 d
= (hed
->AddressSpacing
* hed
->CharWidth
);
341 return HEHT_ADDRESSSPACING
;
345 d
= ((3 * hed
->ColumnsPerLine
+ 1) * hed
->CharWidth
);
352 d
= ((hed
->SplitSpacing
- 1) * hed
->CharWidth
);
355 return HEHT_HEXDUMPSPACING
;
359 d
= (hed
->ColumnsPerLine
* hed
->CharWidth
);
362 return HEHT_ASCIIDUMP
;
365 return HEHT_RIGHTMARGIN
;
369 HEXEDIT_IndexFromPoint(PHEXEDIT_DATA hed
, POINTS pt
, DWORD Hit
, POINT
*EditPos
, BOOL
*EditField
)
372 DWORD Index
, bufsize
;
374 si
.cbSize
= sizeof(SCROLLINFO
);
376 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
380 if(hed
->LineHeight
> 0)
382 EditPos
->y
= min(si
.nPos
+ (pt
.y
/ hed
->LineHeight
), hed
->nLines
- 1);
386 EditPos
->y
= si
.nPos
;
391 case HEHT_LEFTMARGIN
:
393 case HEHT_ADDRESSSPACING
:
395 pt
.x
-= (SHORT
) hed
->LeftMargin
+ ((4 + hed
->AddressSpacing
) * hed
->CharWidth
);
400 pt
.x
-= hed
->LeftMargin
+ ((4 + hed
->AddressSpacing
+ hed
->SplitSpacing
+ (3 * hed
->ColumnsPerLine
)) * hed
->CharWidth
);
407 INT BlockWidth
= (*EditField
? hed
->CharWidth
* 3 : hed
->CharWidth
);
408 EditPos
->x
= min(hed
->ColumnsPerLine
, (pt
.x
+ BlockWidth
/ 2) / BlockWidth
);
411 bufsize
= (hed
->hBuffer
? (DWORD
) LocalSize(hed
->hBuffer
) : 0);
412 Index
= (EditPos
->y
* hed
->ColumnsPerLine
) + EditPos
->x
;
415 INT tmp
= bufsize
% hed
->ColumnsPerLine
;
417 EditPos
->x
= (tmp
== 0 ? hed
->ColumnsPerLine
: tmp
);
423 HEXEDIT_Copy(PHEXEDIT_DATA hed
)
430 if (hed
->SelStart
< hed
->SelEnd
)
445 hGlobal
= GlobalAlloc(GHND
| GMEM_SHARE
, cb
+ sizeof(DWORD
));
449 pb
= GlobalLock(hGlobal
);
454 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
457 CopyMemory(pb
, buf
+ i0
, cb
);
458 LocalUnlock(hed
->hBuffer
);
460 GlobalUnlock(hGlobal
);
462 if (OpenClipboard(hed
->hWndSelf
))
465 SetClipboardData(ClipboardFormatID
, hGlobal
);
474 HEXEDIT_Delete(PHEXEDIT_DATA hed
)
480 if (hed
->SelStart
< hed
->SelEnd
)
493 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
494 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
497 MoveMemory(buf
+ i0
, buf
+ i1
, bufsize
- i1
);
498 LocalUnlock(hed
->hBuffer
);
500 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- (i1
- i0
));
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
);
511 HEXEDIT_Paste(PHEXEDIT_DATA hed
)
519 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
521 if (OpenClipboard(hed
->hWndSelf
))
523 hGlobal
= GetClipboardData(ClipboardFormatID
);
526 pb
= (PBYTE
) GlobalLock(hGlobal
);
529 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
+ cb
);
530 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
533 MoveMemory(buf
+ hed
->Index
+ cb
, buf
+ hed
->Index
,
534 bufsize
- hed
->Index
);
535 CopyMemory(buf
+ hed
->Index
, pb
, cb
);
536 LocalUnlock(hed
->hBuffer
);
538 GlobalUnlock(hGlobal
);
542 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
543 HEXEDIT_MoveCaret(hed
, TRUE
);
547 HEXEDIT_Cut(PHEXEDIT_DATA hed
)
554 HEXEDIT_SelectAll(PHEXEDIT_DATA hed
)
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
);
565 /*** Control specific messages ************************************************/
568 HEXEDIT_HEM_LOADBUFFER(PHEXEDIT_DATA hed
, PVOID Buffer
, DWORD Size
)
570 if(Buffer
!= NULL
&& Size
> 0)
574 if(hed
->MaxBuffer
> 0 && Size
> hed
->MaxBuffer
)
576 Size
= hed
->MaxBuffer
;
583 if(LocalSize(hed
->hBuffer
) != Size
)
585 hed
->hBuffer
= LocalReAlloc(hed
->hBuffer
, Size
, LMEM_MOVEABLE
| LMEM_ZEROINIT
);
590 hed
->hBuffer
= LocalFree(hed
->hBuffer
);
599 hed
->hBuffer
= LocalAlloc(LHND
, Size
);
604 buf
= LocalLock(hed
->hBuffer
);
607 memcpy(buf
, Buffer
, Size
);
611 LocalUnlock(hed
->hBuffer
);
618 else if(hed
->hBuffer
)
621 hed
->hBuffer
= LocalFree(hed
->hBuffer
);
629 HEXEDIT_HEM_COPYBUFFER(PHEXEDIT_DATA hed
, PVOID Buffer
, DWORD Size
)
638 if(Buffer
!= NULL
&& Size
> 0)
640 nCpy
= min(Size
, LocalSize(hed
->hBuffer
));
645 buf
= LocalLock(hed
->hBuffer
);
648 memcpy(Buffer
, buf
, nCpy
);
652 LocalUnlock(hed
->hBuffer
);
657 return (LRESULT
)LocalSize(hed
->hBuffer
);
661 HEXEDIT_HEM_SETMAXBUFFERSIZE(PHEXEDIT_DATA hed
, DWORD nMaxSize
)
663 hed
->MaxBuffer
= nMaxSize
;
664 if (hed
->MaxBuffer
== 0)
666 hed
->hBuffer
= LocalFree(hed
->hBuffer
);
670 hed
->hBuffer
= LocalReAlloc(hed
->hBuffer
, hed
->MaxBuffer
, LMEM_MOVEABLE
);
672 hed
->hBuffer
= LocalAlloc(LMEM_MOVEABLE
, hed
->MaxBuffer
);
677 /*** Message Proc *************************************************************/
680 HEXEDIT_WM_NCCREATE(HWND hWnd
, CREATESTRUCT
*cs
)
684 if(!(hed
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(HEXEDIT_DATA
))))
689 hed
->hWndSelf
= hWnd
;
690 hed
->hWndParent
= cs
->hwndParent
;
691 hed
->style
= cs
->style
;
693 hed
->ColumnsPerLine
= 8;
695 hed
->AddressSpacing
= 2;
696 hed
->SplitSpacing
= 2;
697 hed
->EditingField
= TRUE
; /* in hexdump field */
699 SetWindowLongPtr(hWnd
, 0, (DWORD_PTR
)hed
);
706 HEXEDIT_WM_NCDESTROY(PHEXEDIT_DATA hed
)
710 //while(LocalUnlock(hed->hBuffer));
711 LocalFree(hed
->hBuffer
);
716 DeleteObject(hed
->hFont
);
719 SetWindowLongPtr(hed
->hWndSelf
, 0, (DWORD_PTR
)0);
720 HeapFree(GetProcessHeap(), 0, hed
);
726 HEXEDIT_WM_CREATE(PHEXEDIT_DATA hed
)
728 UNREFERENCED_PARAMETER(hed
);
733 HEXEDIT_WM_SETFOCUS(PHEXEDIT_DATA hed
)
735 CreateCaret(hed
->hWndSelf
, 0, 1, hed
->LineHeight
);
736 HEXEDIT_MoveCaret(hed
, FALSE
);
737 ShowCaret(hed
->hWndSelf
);
742 HEXEDIT_WM_KILLFOCUS(PHEXEDIT_DATA hed
)
744 UNREFERENCED_PARAMETER(hed
);
750 HEXEDIT_WM_VSCROLL(PHEXEDIT_DATA hed
, WORD ThumbPosition
, WORD SbCmd
)
755 UNREFERENCED_PARAMETER(ThumbPosition
);
757 ZeroMemory(&si
, sizeof(SCROLLINFO
));
758 si
.cbSize
= sizeof(SCROLLINFO
);
760 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
790 si
.nPos
= si
.nTrackPos
;
795 SetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
, TRUE
);
796 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
798 if(si
.nPos
!= ScrollY
)
800 ScrollWindow(hed
->hWndSelf
, 0, (ScrollY
- si
.nPos
) * hed
->LineHeight
, NULL
, NULL
);
801 UpdateWindow(hed
->hWndSelf
);
808 HEXEDIT_WM_SETFONT(PHEXEDIT_DATA hed
, HFONT hFont
, BOOL bRedraw
)
816 hFont
= HEXEDIT_GetFixedFont();
820 hDC
= GetDC(hed
->hWndSelf
);
823 hOldFont
= SelectObject(hDC
, hFont
);
825 GetTextMetrics(hDC
, &tm
);
826 hed
->LineHeight
= tm
.tmHeight
;
827 hed
->CharWidth
= tm
.tmAveCharWidth
;
830 SelectObject(hDC
, hOldFont
);
832 ReleaseDC(hed
->hWndSelf
, hDC
);
836 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
843 HEXEDIT_WM_GETFONT(PHEXEDIT_DATA hed
)
845 return (LRESULT
)hed
->hFont
;
849 HEXEDIT_WM_PAINT(PHEXEDIT_DATA hed
)
854 HBITMAP hbmp
, hbmpold
;
860 if(GetUpdateRect(hed
->hWndSelf
, &rc
, FALSE
) && (hed
->LineHeight
> 0))
862 ZeroMemory(&si
, sizeof(SCROLLINFO
));
863 si
.cbSize
= sizeof(SCROLLINFO
);
865 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
867 height
= (rc
.bottom
- rc
.top
);
868 nLines
= height
/ hed
->LineHeight
;
869 if((height
% hed
->LineHeight
) > 0)
873 if(nLines
> hed
->nLines
- si
.nPos
)
875 nLines
= hed
->nLines
- si
.nPos
;
877 nFirst
= rc
.top
/ hed
->LineHeight
;
879 BeginPaint(hed
->hWndSelf
, &ps
);
880 if(!(hTempDC
= CreateCompatibleDC(ps
.hdc
)))
882 FillRect(ps
.hdc
, &rc
, (HBRUSH
)(COLOR_WINDOW
+ 1));
885 if(!(hbmp
= CreateCompatibleBitmap(ps
.hdc
, ps
.rcPaint
.right
, ps
.rcPaint
.bottom
)))
887 FillRect(ps
.hdc
, &rc
, (HBRUSH
)(COLOR_WINDOW
+ 1));
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
);
902 EndPaint(hed
->hWndSelf
, &ps
);
909 HEXEDIT_WM_MOUSEWHEEL(PHEXEDIT_DATA hed
, int cyMoveLines
, WORD ButtonsDown
, LPPOINTS MousePos
)
914 UNREFERENCED_PARAMETER(ButtonsDown
);
915 UNREFERENCED_PARAMETER(MousePos
);
917 SetFocus(hed
->hWndSelf
);
919 si
.cbSize
= sizeof(SCROLLINFO
);
921 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
926 si
.nPos
+= cyMoveLines
;
927 SetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
, TRUE
);
929 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
930 if(si
.nPos
!= ScrollY
)
932 ScrollWindow(hed
->hWndSelf
, 0, (ScrollY
- si
.nPos
) * hed
->LineHeight
, NULL
, NULL
);
933 UpdateWindow(hed
->hWndSelf
);
940 HEXEDIT_WM_GETDLGCODE(LPMSG Msg
)
942 UNREFERENCED_PARAMETER(Msg
);
943 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
947 HEXEDIT_WM_LBUTTONDOWN(PHEXEDIT_DATA hed
, INT Buttons
, POINTS Pt
)
953 UNREFERENCED_PARAMETER(Buttons
);
954 SetFocus(hed
->hWndSelf
);
956 if (GetAsyncKeyState(VK_SHIFT
) < 0)
958 if (hed
->EditingField
)
959 hed
->Index
= HEXEDIT_IndexFromPoint(hed
, Pt
, HEHT_HEXDUMP
, &EditPos
, &NewField
);
961 hed
->Index
= HEXEDIT_IndexFromPoint(hed
, Pt
, HEHT_ASCIIDUMP
, &EditPos
, &NewField
);
962 hed
->SelEnd
= hed
->Index
;
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
);
972 hed
->CaretCol
= EditPos
.x
;
973 hed
->CaretLine
= EditPos
.y
;
975 InvalidateRect(hed
->hWndSelf
, NULL
, FALSE
);
976 HEXEDIT_MoveCaret(hed
, TRUE
);
982 HEXEDIT_WM_LBUTTONUP(PHEXEDIT_DATA hed
, INT Buttons
, POINTS Pt
)
986 if (GetCapture() == hed
->hWndSelf
)
988 if (hed
->EditingField
)
989 hed
->Index
= HEXEDIT_IndexFromPoint(hed
, Pt
, HEHT_HEXDUMP
, &EditPos
, &NewField
);
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
;
996 InvalidateRect(hed
->hWndSelf
, NULL
, FALSE
);
997 HEXEDIT_MoveCaret(hed
, TRUE
);
1003 HEXEDIT_WM_MOUSEMOVE(PHEXEDIT_DATA hed
, INT Buttons
, POINTS Pt
)
1007 if (GetCapture() == hed
->hWndSelf
)
1009 if (hed
->EditingField
)
1010 hed
->Index
= HEXEDIT_IndexFromPoint(hed
, Pt
, HEHT_HEXDUMP
, &EditPos
, &NewField
);
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
);
1023 HEXEDIT_WM_KEYDOWN(PHEXEDIT_DATA hed
, INT VkCode
)
1029 if(GetKeyState(VK_MENU
) & 0x8000)
1034 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
1036 if (hed
->SelStart
< hed
->SelEnd
)
1050 if (GetAsyncKeyState(VK_SHIFT
) >= 0 &&
1051 GetAsyncKeyState(VK_CONTROL
) < 0 && hed
->SelStart
!= hed
->SelEnd
)
1058 if (GetAsyncKeyState(VK_SHIFT
) >= 0 &&
1059 GetAsyncKeyState(VK_CONTROL
) < 0 && hed
->SelStart
!= hed
->SelEnd
)
1066 if (GetAsyncKeyState(VK_SHIFT
) >= 0 && GetAsyncKeyState(VK_CONTROL
) < 0)
1073 if (GetAsyncKeyState(VK_SHIFT
) >= 0 && GetAsyncKeyState(VK_CONTROL
) < 0)
1074 HEXEDIT_SelectAll(hed
);
1080 if (hed
->SelStart
!= hed
->SelEnd
)
1082 if (GetAsyncKeyState(VK_SHIFT
) >= 0 && GetAsyncKeyState(VK_CONTROL
) < 0)
1085 if (GetAsyncKeyState(VK_SHIFT
) < 0 && GetAsyncKeyState(VK_CONTROL
) >= 0)
1090 if (GetAsyncKeyState(VK_SHIFT
) < 0 && GetAsyncKeyState(VK_CONTROL
) >= 0 &&
1091 hed
->SelStart
!= hed
->SelEnd
)
1095 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1098 MoveMemory(buf
+ i0
, buf
+ i1
, bufsize
- i1
);
1099 LocalUnlock(hed
->hBuffer
);
1101 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- (i1
- i0
));
1103 hed
->Index
= hed
->SelStart
= hed
->SelEnd
= i0
;
1104 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1105 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1109 if (hed
->InMid
&& hed
->EditingField
)
1111 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1114 MoveMemory(buf
+ hed
->Index
, buf
+ hed
->Index
+ 1,
1115 bufsize
- hed
->Index
- 1);
1116 LocalUnlock(hed
->hBuffer
);
1118 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- 1);
1121 else if (hed
->Index
< bufsize
)
1123 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1126 MoveMemory(buf
+ hed
->Index
, buf
+ hed
->Index
+ 1,
1127 bufsize
- hed
->Index
- 1);
1128 LocalUnlock(hed
->hBuffer
);
1130 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- 1);
1133 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1134 HEXEDIT_MoveCaret(hed
, TRUE
);
1140 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1143 MoveMemory(buf
+ i0
, buf
+ i1
, bufsize
- i1
);
1144 LocalUnlock(hed
->hBuffer
);
1146 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- (i1
- i0
));
1148 hed
->Index
= hed
->SelStart
= hed
->SelEnd
= i0
;
1149 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1150 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1154 if (hed
->InMid
&& hed
->EditingField
)
1156 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1159 MoveMemory(buf
+ hed
->Index
, buf
+ hed
->Index
+ 1,
1160 bufsize
- hed
->Index
- 1);
1161 LocalUnlock(hed
->hBuffer
);
1164 else if (hed
->Index
> 0)
1166 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1169 MoveMemory(buf
+ hed
->Index
- 1, buf
+ hed
->Index
,
1170 bufsize
- hed
->Index
);
1171 LocalUnlock(hed
->hBuffer
);
1174 hed
->SelStart
= hed
->SelEnd
= hed
->Index
;
1175 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1176 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1180 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- 1);
1183 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1184 HEXEDIT_MoveCaret(hed
, TRUE
);
1191 if (GetAsyncKeyState(VK_SHIFT
) < 0)
1192 hed
->SelEnd
= hed
->Index
;
1194 hed
->SelStart
= hed
->SelEnd
= hed
->Index
;
1195 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1196 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1198 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1199 HEXEDIT_MoveCaret(hed
, TRUE
);
1204 if (hed
->Index
< (INT
)bufsize
)
1207 if (GetAsyncKeyState(VK_SHIFT
) < 0)
1208 hed
->SelEnd
= hed
->Index
;
1210 hed
->SelStart
= hed
->SelEnd
= hed
->Index
;
1211 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1212 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1214 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1215 HEXEDIT_MoveCaret(hed
, TRUE
);
1220 if (hed
->Index
>= hed
->ColumnsPerLine
)
1222 hed
->Index
-= hed
->ColumnsPerLine
;
1223 if (GetAsyncKeyState(VK_SHIFT
) < 0)
1224 hed
->SelEnd
= hed
->Index
;
1226 hed
->SelStart
= hed
->SelEnd
= hed
->Index
;
1227 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1228 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1230 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1231 HEXEDIT_MoveCaret(hed
, TRUE
);
1236 if (hed
->Index
+ hed
->ColumnsPerLine
<= (INT
) bufsize
)
1237 hed
->Index
+= hed
->ColumnsPerLine
;
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
;
1245 hed
->SelStart
= hed
->SelEnd
= hed
->Index
;
1247 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1248 HEXEDIT_MoveCaret(hed
, TRUE
);
1259 HEXEDIT_WM_CHAR(PHEXEDIT_DATA hed
, WCHAR wch
)
1262 CHAR ch
= (CHAR
)wch
; // keep the lowest octet.
1266 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
1267 if (hed
->SelStart
< hed
->SelEnd
)
1277 if (!hed
->EditingField
)
1279 if (0x20 <= ch
&& ch
<= 0xFF)
1281 if (hed
->SelStart
!= hed
->SelEnd
)
1283 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1286 MoveMemory(buf
+ i0
, buf
+ i1
, bufsize
- i1
);
1287 LocalUnlock(hed
->hBuffer
);
1289 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- (i1
- i0
));
1291 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
1292 hed
->Index
= hed
->SelStart
= hed
->SelEnd
= i0
;
1294 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
+ 1);
1295 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1298 MoveMemory(buf
+ hed
->Index
+ 1, buf
+ hed
->Index
,
1299 bufsize
- hed
->Index
);
1300 buf
[hed
->Index
] = ch
;
1301 LocalUnlock(hed
->hBuffer
);
1304 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1305 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1306 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1307 HEXEDIT_MoveCaret(hed
, TRUE
);
1313 if (('0' <= ch
&& ch
<= '9') || ('A' <= ch
&& ch
<= 'F') ||
1314 ('a' <= ch
&& ch
<= 'f'))
1316 if (hed
->SelStart
!= hed
->SelEnd
)
1318 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1321 MoveMemory(buf
+ i0
, buf
+ i1
, bufsize
- i1
);
1322 LocalUnlock(hed
->hBuffer
);
1324 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- (i1
- i0
));
1326 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
1327 hed
->Index
= hed
->SelStart
= hed
->SelEnd
= i0
;
1331 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1334 if ('0' <= ch
&& ch
<= '9')
1335 buf
[hed
->Index
] |= ch
- '0';
1336 else if ('A' <= ch
&& ch
<= 'F')
1337 buf
[hed
->Index
] |= ch
+ 10 - 'A';
1338 else if ('a' <= ch
&& ch
<= 'f')
1339 buf
[hed
->Index
] |= ch
+ 10 - 'a';
1340 LocalUnlock(hed
->hBuffer
);
1347 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
+ 1);
1348 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1351 MoveMemory(buf
+ hed
->Index
+ 1, buf
+ hed
->Index
,
1352 bufsize
- hed
->Index
);
1353 if ('0' <= ch
&& ch
<= '9')
1354 buf
[hed
->Index
] = (ch
- '0') << 4;
1355 else if ('A' <= ch
&& ch
<= 'F')
1356 buf
[hed
->Index
] = (ch
+ 10 - 'A') << 4;
1357 else if ('a' <= ch
&& ch
<= 'f')
1358 buf
[hed
->Index
] = (ch
+ 10 - 'a') << 4;
1359 LocalUnlock(hed
->hBuffer
);
1363 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1364 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1365 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1366 HEXEDIT_MoveCaret(hed
, TRUE
);
1374 HEXEDIT_WM_SIZE(PHEXEDIT_DATA hed
, DWORD sType
, WORD NewWidth
, WORD NewHeight
)
1376 UNREFERENCED_PARAMETER(sType
);
1377 UNREFERENCED_PARAMETER(NewHeight
);
1378 UNREFERENCED_PARAMETER(NewWidth
);
1379 HEXEDIT_Update(hed
);
1384 HEXEDIT_WM_CONTEXTMENU(PHEXEDIT_DATA hed
, INT x
, INT y
)
1389 if (x
== -1 && y
== -1)
1391 GetWindowRect(hed
->hWndSelf
, &rc
);
1396 hMenu
= GetSubMenu(hPopupMenus
, PM_HEXEDIT
);
1397 if (hed
->SelStart
== hed
->SelEnd
)
1399 EnableMenuItem(hMenu
, ID_HEXEDIT_CUT
, MF_GRAYED
);
1400 EnableMenuItem(hMenu
, ID_HEXEDIT_COPY
, MF_GRAYED
);
1401 EnableMenuItem(hMenu
, ID_HEXEDIT_PASTE
, MF_GRAYED
);
1402 EnableMenuItem(hMenu
, ID_HEXEDIT_DELETE
, MF_GRAYED
);
1406 EnableMenuItem(hMenu
, ID_HEXEDIT_CUT
, MF_ENABLED
);
1407 EnableMenuItem(hMenu
, ID_HEXEDIT_COPY
, MF_ENABLED
);
1408 EnableMenuItem(hMenu
, ID_HEXEDIT_PASTE
, MF_ENABLED
);
1409 EnableMenuItem(hMenu
, ID_HEXEDIT_DELETE
, MF_ENABLED
);
1412 SetForegroundWindow(hed
->hWndSelf
);
1413 TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, x
, y
, 0, hed
->hWndSelf
, NULL
);
1414 PostMessageW(hed
->hWndSelf
, WM_NULL
, 0, 0);
1418 HexEditWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1423 hed
= (PHEXEDIT_DATA
)(LONG_PTR
)GetWindowLongPtr(hWnd
, (DWORD_PTR
)0);
1430 return HEXEDIT_WM_PAINT(hed
);
1433 return HEXEDIT_WM_KEYDOWN(hed
, (INT
)wParam
);
1436 return HEXEDIT_WM_CHAR(hed
, (WCHAR
)wParam
);
1439 return HEXEDIT_WM_VSCROLL(hed
, HIWORD(wParam
), LOWORD(wParam
));
1442 return HEXEDIT_WM_SIZE(hed
, (DWORD
)wParam
, LOWORD(lParam
), HIWORD(lParam
));
1444 case WM_LBUTTONDOWN
:
1446 p
.x
= LOWORD(lParam
);
1447 p
.y
= HIWORD(lParam
);
1448 return HEXEDIT_WM_LBUTTONDOWN(hed
, (INT
)wParam
, p
);
1453 p
.x
= LOWORD(lParam
);
1454 p
.y
= HIWORD(lParam
);
1455 return HEXEDIT_WM_LBUTTONUP(hed
, (INT
)wParam
, p
);
1460 p
.x
= LOWORD(lParam
);
1461 p
.y
= HIWORD(lParam
);
1462 return HEXEDIT_WM_MOUSEMOVE(hed
, (INT
)wParam
, p
);
1467 UINT nScrollLines
= 3;
1470 SystemParametersInfoW(SPI_GETWHEELSCROLLLINES
, 0, &nScrollLines
, 0);
1471 delta
-= (SHORT
)HIWORD(wParam
);
1472 if(abs(delta
) >= WHEEL_DELTA
&& nScrollLines
!= 0)
1474 p
.x
= LOWORD(lParam
);
1475 p
.y
= HIWORD(lParam
);
1476 return HEXEDIT_WM_MOUSEWHEEL(hed
, nScrollLines
* (delta
/ WHEEL_DELTA
), LOWORD(wParam
), &p
);
1481 case HEM_LOADBUFFER
:
1482 return HEXEDIT_HEM_LOADBUFFER(hed
, (PVOID
)wParam
, (DWORD
)lParam
);
1484 case HEM_COPYBUFFER
:
1485 return HEXEDIT_HEM_COPYBUFFER(hed
, (PVOID
)wParam
, (DWORD
)lParam
);
1487 case HEM_SETMAXBUFFERSIZE
:
1488 return HEXEDIT_HEM_SETMAXBUFFERSIZE(hed
, (DWORD
)lParam
);
1491 return HEXEDIT_WM_SETFOCUS(hed
);
1494 return HEXEDIT_WM_KILLFOCUS(hed
);
1497 return HEXEDIT_WM_GETDLGCODE((LPMSG
)lParam
);
1500 return HEXEDIT_WM_SETFONT(hed
, (HFONT
)wParam
, (BOOL
)LOWORD(lParam
));
1503 return HEXEDIT_WM_GETFONT(hed
);
1506 return HEXEDIT_WM_CREATE(hed
);
1511 return HEXEDIT_WM_NCCREATE(hWnd
, (CREATESTRUCT
*)lParam
);
1518 return HEXEDIT_WM_NCDESTROY(hed
);
1522 case WM_CONTEXTMENU
:
1523 HEXEDIT_WM_CONTEXTMENU(hed
, (short)LOWORD(lParam
), (short)HIWORD(lParam
));
1527 switch(LOWORD(wParam
))
1529 case ID_HEXEDIT_CUT
:
1533 case ID_HEXEDIT_COPY
:
1537 case ID_HEXEDIT_PASTE
:
1541 case ID_HEXEDIT_DELETE
:
1542 HEXEDIT_Delete(hed
);
1545 case ID_HEXEDIT_SELECT_ALL
:
1546 HEXEDIT_SelectAll(hed
);
1552 return DefWindowProcW(hWnd
, uMsg
, wParam
, lParam
);