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
32 INT nVisibleLinesComplete
;
51 } HEXEDIT_DATA
, *PHEXEDIT_DATA
;
53 static const WCHAR ClipboardFormatName
[] = L
"RegEdit_HexData";
54 static UINT ClipboardFormatID
= 0;
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)
65 INT_PTR CALLBACK
HexEditWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
69 RegisterHexEditorClass(HINSTANCE hInstance
)
73 ClipboardFormatID
= RegisterClipboardFormatW(ClipboardFormatName
);
75 ZeroMemory(&WndClass
, sizeof(WNDCLASSEXW
));
76 WndClass
.cbSize
= sizeof(WNDCLASSEXW
);
77 WndClass
.style
= CS_DBLCLKS
;
78 WndClass
.lpfnWndProc
= (WNDPROC
)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
;
85 return RegisterClassEx(&WndClass
);
90 UnregisterHexEditorClass(HINSTANCE hInstance
)
92 return UnregisterClassW(HEX_EDIT_CLASS_NAME
, hInstance
);
95 /*** Helper functions *********************************************************/
98 HEXEDIT_MoveCaret(PHEXEDIT_DATA hed
, BOOL Scroll
)
102 si
.cbSize
= sizeof(SCROLLINFO
);
104 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
108 if(si
.nPos
> hed
->CaretLine
)
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
);
115 else if(hed
->CaretLine
>= (hed
->nVisibleLinesComplete
+ si
.nPos
))
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
);
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
);
127 SetCaretPos(hed
->LeftMargin
+ ((4 + hed
->AddressSpacing
+ hed
->SplitSpacing
+ (3 * hed
->ColumnsPerLine
) + hed
->CaretCol
) * hed
->CharWidth
) - 2, (hed
->CaretLine
- si
.nPos
) * hed
->LineHeight
);
131 HEXEDIT_Update(PHEXEDIT_DATA hed
)
136 INT bufsize
, cvislines
;
138 GetClientRect(hed
->hWndSelf
, &rcClient
);
139 hed
->style
= GetWindowLongPtr(hed
->hWndSelf
, GWL_STYLE
);
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)
148 if(hed
->LineHeight
> 0)
150 hed
->nVisibleLinesComplete
= cvislines
= rcClient
.bottom
/ hed
->LineHeight
;
151 hed
->nVisibleLines
= hed
->nVisibleLinesComplete
;
152 if(rcClient
.bottom
% hed
->LineHeight
)
154 hed
->nVisibleLines
++;
159 hed
->nVisibleLines
= cvislines
= 0;
162 SbVisible
= bufsize
> 0 && cvislines
< hed
->nLines
;
163 ShowScrollBar(hed
->hWndSelf
, SB_VERT
, SbVisible
);
165 /* update scrollbar */
166 si
.cbSize
= sizeof(SCROLLINFO
);
167 si
.fMask
= SIF_RANGE
| SIF_PAGE
;
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
);
173 if(IsWindowVisible(hed
->hWndSelf
) && SbVisible
!= hed
->SbVisible
)
175 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
178 hed
->SbVisible
= SbVisible
;
182 HEXEDIT_GetFixedFont(VOID
)
185 GetObject(GetStockObject(ANSI_FIXED_FONT
), sizeof(LOGFONT
), &lf
);
186 return CreateFontIndirect(&lf
);
190 HEXEDIT_PaintLines(PHEXEDIT_DATA hed
, HDC hDC
, DWORD ScrollPos
, DWORD First
, DWORD Last
, RECT
*rc
)
192 DWORD dx
, dy
, linestart
;
193 INT i
, isave
, i0
, i1
, x
;
194 PBYTE buf
, current
, end
, line
;
196 WCHAR hex
[3], addr
[17];
199 FillRect(hDC
, rc
, (HBRUSH
)(COLOR_WINDOW
+ 1));
200 SetTextColor(hDC
, GetSysColor(COLOR_WINDOWTEXT
));
202 if (hed
->SelStart
< hed
->SelEnd
)
215 bufsize
= LocalSize(hed
->hBuffer
);
216 buf
= LocalLock(hed
->hBuffer
);
223 if(ScrollPos
+ First
== 0)
226 wsprintf(addr
, L
"%04X", 0);
227 TextOutW(hDC
, hed
->LeftMargin
, First
* hed
->LineHeight
, addr
, 4);
234 dy
= First
* hed
->LineHeight
;
235 linestart
= (ScrollPos
+ First
) * hed
->ColumnsPerLine
;
237 current
= buf
+ linestart
;
238 Last
= min(hed
->nLines
- ScrollPos
, Last
);
240 SetBkMode(hDC
, TRANSPARENT
);
241 while(First
<= Last
&& current
< end
)
245 dx
= hed
->LeftMargin
;
248 wsprintf(addr
, L
"%04lX", linestart
);
249 TextOutW(hDC
, dx
, dy
, addr
, 4);
251 dx
+= ((4 + hed
->AddressSpacing
) * hed
->CharWidth
);
252 dh
= (3 * hed
->CharWidth
);
256 rct
.right
= rct
.left
+ dh
;
257 rct
.bottom
= dy
+ hed
->LineHeight
;
260 dx
+= (hed
->CharWidth
/ 2);
263 for(x
= 0; x
< hed
->ColumnsPerLine
&& current
< end
; x
++)
268 wsprintf(hex
, L
"%02X", *(current
++));
269 if (i0
<= i
&& i
< i1
)
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
));
282 ExtTextOutW(hDC
, dx
, dy
, ETO_OPAQUE
, &rct
, hex
, 2, NULL
);
288 dx
= ((4 + hed
->AddressSpacing
+ hed
->SplitSpacing
+ (hed
->ColumnsPerLine
* 3)) * hed
->CharWidth
);
291 for(x
= 0; x
< hed
->ColumnsPerLine
&& current
< end
; x
++)
293 wsprintf(hex
, L
"%C", *(current
++));
294 hex
[0] = ((hex
[0] & L
'\x007f') >= L
' ' ? hex
[0] : L
'.');
295 if (i0
<= i
&& i
< i1
)
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
));
307 TextOutW(hDC
, dx
, dy
, hex
, 1);
308 dx
+= hed
->CharWidth
;
312 dy
+= hed
->LineHeight
;
313 linestart
+= hed
->ColumnsPerLine
;
318 LocalUnlock(hed
->hBuffer
);
322 HEXEDIT_HitRegionTest(PHEXEDIT_DATA hed
, POINTS pt
)
326 if(pt
.x
<= hed
->LeftMargin
)
328 return HEHT_LEFTMARGIN
;
331 pt
.x
-= hed
->LeftMargin
;
332 d
= (4 * hed
->CharWidth
);
339 d
= (hed
->AddressSpacing
* hed
->CharWidth
);
342 return HEHT_ADDRESSSPACING
;
346 d
= ((3 * hed
->ColumnsPerLine
+ 1) * hed
->CharWidth
);
353 d
= ((hed
->SplitSpacing
- 1) * hed
->CharWidth
);
356 return HEHT_HEXDUMPSPACING
;
360 d
= (hed
->ColumnsPerLine
* hed
->CharWidth
);
363 return HEHT_ASCIIDUMP
;
366 return HEHT_RIGHTMARGIN
;
370 HEXEDIT_IndexFromPoint(PHEXEDIT_DATA hed
, POINTS pt
, DWORD Hit
, POINT
*EditPos
, BOOL
*EditField
)
373 DWORD Index
, bufsize
;
375 si
.cbSize
= sizeof(SCROLLINFO
);
377 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
381 if(hed
->LineHeight
> 0)
383 EditPos
->y
= min(si
.nPos
+ (pt
.y
/ hed
->LineHeight
), hed
->nLines
- 1);
387 EditPos
->y
= si
.nPos
;
392 case HEHT_LEFTMARGIN
:
394 case HEHT_ADDRESSSPACING
:
396 pt
.x
-= (SHORT
) hed
->LeftMargin
+ ((4 + hed
->AddressSpacing
) * hed
->CharWidth
);
401 pt
.x
-= hed
->LeftMargin
+ ((4 + hed
->AddressSpacing
+ hed
->SplitSpacing
+ (3 * hed
->ColumnsPerLine
)) * hed
->CharWidth
);
408 INT BlockWidth
= (*EditField
? hed
->CharWidth
* 3 : hed
->CharWidth
);
409 EditPos
->x
= min(hed
->ColumnsPerLine
, (pt
.x
+ BlockWidth
/ 2) / BlockWidth
);
412 bufsize
= (hed
->hBuffer
? (DWORD
) LocalSize(hed
->hBuffer
) : 0);
413 Index
= (EditPos
->y
* hed
->ColumnsPerLine
) + EditPos
->x
;
416 INT tmp
= bufsize
% hed
->ColumnsPerLine
;
418 EditPos
->x
= (tmp
== 0 ? hed
->ColumnsPerLine
: tmp
);
424 HEXEDIT_Copy(PHEXEDIT_DATA hed
)
431 if (hed
->SelStart
< hed
->SelEnd
)
446 hGlobal
= GlobalAlloc(GHND
| GMEM_SHARE
, cb
+ sizeof(DWORD
));
450 pb
= GlobalLock(hGlobal
);
455 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
458 CopyMemory(pb
, buf
+ i0
, cb
);
459 LocalUnlock(hed
->hBuffer
);
461 GlobalUnlock(hGlobal
);
463 if (OpenClipboard(hed
->hWndSelf
))
466 SetClipboardData(ClipboardFormatID
, hGlobal
);
475 HEXEDIT_Delete(PHEXEDIT_DATA hed
)
481 if (hed
->SelStart
< hed
->SelEnd
)
494 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
495 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
498 MoveMemory(buf
+ i0
, buf
+ i1
, bufsize
- i1
);
499 LocalUnlock(hed
->hBuffer
);
501 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- (i1
- i0
));
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
);
512 HEXEDIT_Paste(PHEXEDIT_DATA hed
)
520 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
522 if (OpenClipboard(hed
->hWndSelf
))
524 hGlobal
= GetClipboardData(ClipboardFormatID
);
527 pb
= (PBYTE
) GlobalLock(hGlobal
);
530 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
+ cb
);
531 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
534 MoveMemory(buf
+ hed
->Index
+ cb
, buf
+ hed
->Index
,
535 bufsize
- hed
->Index
);
536 CopyMemory(buf
+ hed
->Index
, pb
, cb
);
537 LocalUnlock(hed
->hBuffer
);
539 GlobalUnlock(hGlobal
);
543 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
544 HEXEDIT_MoveCaret(hed
, TRUE
);
548 HEXEDIT_Cut(PHEXEDIT_DATA hed
)
555 HEXEDIT_SelectAll(PHEXEDIT_DATA hed
)
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
);
566 /*** Control specific messages ************************************************/
569 HEXEDIT_HEM_LOADBUFFER(PHEXEDIT_DATA hed
, PVOID Buffer
, DWORD Size
)
571 if(Buffer
!= NULL
&& Size
> 0)
575 if(hed
->MaxBuffer
> 0 && Size
> hed
->MaxBuffer
)
577 Size
= hed
->MaxBuffer
;
584 if(LocalSize(hed
->hBuffer
) != Size
)
586 hed
->hBuffer
= LocalReAlloc(hed
->hBuffer
, Size
, LMEM_MOVEABLE
| LMEM_ZEROINIT
);
591 hed
->hBuffer
= LocalFree(hed
->hBuffer
);
600 hed
->hBuffer
= LocalAlloc(LHND
, Size
);
605 buf
= LocalLock(hed
->hBuffer
);
608 memcpy(buf
, Buffer
, Size
);
612 LocalUnlock(hed
->hBuffer
);
619 else if(hed
->hBuffer
)
622 hed
->hBuffer
= LocalFree(hed
->hBuffer
);
630 HEXEDIT_HEM_COPYBUFFER(PHEXEDIT_DATA hed
, PVOID Buffer
, DWORD Size
)
639 if(Buffer
!= NULL
&& Size
> 0)
641 nCpy
= min(Size
, LocalSize(hed
->hBuffer
));
646 buf
= LocalLock(hed
->hBuffer
);
649 memcpy(Buffer
, buf
, nCpy
);
653 LocalUnlock(hed
->hBuffer
);
658 return (LRESULT
)LocalSize(hed
->hBuffer
);
662 HEXEDIT_HEM_SETMAXBUFFERSIZE(PHEXEDIT_DATA hed
, DWORD nMaxSize
)
664 hed
->MaxBuffer
= nMaxSize
;
665 if (hed
->MaxBuffer
== 0)
667 hed
->hBuffer
= LocalFree(hed
->hBuffer
);
671 hed
->hBuffer
= LocalReAlloc(hed
->hBuffer
, hed
->MaxBuffer
, LMEM_MOVEABLE
);
673 hed
->hBuffer
= LocalAlloc(LMEM_MOVEABLE
, hed
->MaxBuffer
);
678 /*** Message Proc *************************************************************/
681 HEXEDIT_WM_NCCREATE(HWND hWnd
, CREATESTRUCT
*cs
)
685 if(!(hed
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(HEXEDIT_DATA
))))
690 hed
->hWndSelf
= hWnd
;
691 hed
->hWndParent
= cs
->hwndParent
;
692 hed
->style
= cs
->style
;
694 hed
->ColumnsPerLine
= 8;
696 hed
->AddressSpacing
= 2;
697 hed
->SplitSpacing
= 2;
698 hed
->EditingField
= TRUE
; /* in hexdump field */
700 SetWindowLongPtr(hWnd
, 0, (DWORD_PTR
)hed
);
707 HEXEDIT_WM_NCDESTROY(PHEXEDIT_DATA hed
)
711 //while(LocalUnlock(hed->hBuffer));
712 LocalFree(hed
->hBuffer
);
717 DeleteObject(hed
->hFont
);
720 SetWindowLongPtr(hed
->hWndSelf
, 0, (DWORD_PTR
)0);
721 HeapFree(GetProcessHeap(), 0, hed
);
727 HEXEDIT_WM_CREATE(PHEXEDIT_DATA hed
)
729 UNREFERENCED_PARAMETER(hed
);
734 HEXEDIT_WM_SETFOCUS(PHEXEDIT_DATA hed
)
736 CreateCaret(hed
->hWndSelf
, 0, 1, hed
->LineHeight
);
737 HEXEDIT_MoveCaret(hed
, FALSE
);
738 ShowCaret(hed
->hWndSelf
);
743 HEXEDIT_WM_KILLFOCUS(PHEXEDIT_DATA hed
)
745 UNREFERENCED_PARAMETER(hed
);
751 HEXEDIT_WM_VSCROLL(PHEXEDIT_DATA hed
, WORD ThumbPosition
, WORD SbCmd
)
756 UNREFERENCED_PARAMETER(ThumbPosition
);
758 ZeroMemory(&si
, sizeof(SCROLLINFO
));
759 si
.cbSize
= sizeof(SCROLLINFO
);
761 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
791 si
.nPos
= si
.nTrackPos
;
796 SetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
, TRUE
);
797 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
799 if(si
.nPos
!= ScrollY
)
801 ScrollWindow(hed
->hWndSelf
, 0, (ScrollY
- si
.nPos
) * hed
->LineHeight
, NULL
, NULL
);
802 UpdateWindow(hed
->hWndSelf
);
809 HEXEDIT_WM_SETFONT(PHEXEDIT_DATA hed
, HFONT hFont
, BOOL bRedraw
)
817 hFont
= HEXEDIT_GetFixedFont();
821 hDC
= GetDC(hed
->hWndSelf
);
824 hOldFont
= SelectObject(hDC
, hFont
);
826 GetTextMetrics(hDC
, &tm
);
827 hed
->LineHeight
= tm
.tmHeight
;
828 hed
->CharWidth
= tm
.tmAveCharWidth
;
831 SelectObject(hDC
, hOldFont
);
833 ReleaseDC(hed
->hWndSelf
, hDC
);
837 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
844 HEXEDIT_WM_GETFONT(PHEXEDIT_DATA hed
)
846 return (LRESULT
)hed
->hFont
;
850 HEXEDIT_WM_PAINT(PHEXEDIT_DATA hed
)
855 HBITMAP hbmp
, hbmpold
;
861 if(GetUpdateRect(hed
->hWndSelf
, &rc
, FALSE
) && (hed
->LineHeight
> 0))
863 ZeroMemory(&si
, sizeof(SCROLLINFO
));
864 si
.cbSize
= sizeof(SCROLLINFO
);
866 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
868 height
= (rc
.bottom
- rc
.top
);
869 nLines
= height
/ hed
->LineHeight
;
870 if((height
% hed
->LineHeight
) > 0)
874 if(nLines
> hed
->nLines
- si
.nPos
)
876 nLines
= hed
->nLines
- si
.nPos
;
878 nFirst
= rc
.top
/ hed
->LineHeight
;
880 BeginPaint(hed
->hWndSelf
, &ps
);
881 if(!(hTempDC
= CreateCompatibleDC(ps
.hdc
)))
883 FillRect(ps
.hdc
, &rc
, (HBRUSH
)(COLOR_WINDOW
+ 1));
886 if(!(hbmp
= CreateCompatibleBitmap(ps
.hdc
, ps
.rcPaint
.right
, ps
.rcPaint
.bottom
)))
888 FillRect(ps
.hdc
, &rc
, (HBRUSH
)(COLOR_WINDOW
+ 1));
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
);
903 EndPaint(hed
->hWndSelf
, &ps
);
910 HEXEDIT_WM_MOUSEWHEEL(PHEXEDIT_DATA hed
, int cyMoveLines
, WORD ButtonsDown
, LPPOINTS MousePos
)
915 UNREFERENCED_PARAMETER(ButtonsDown
);
916 UNREFERENCED_PARAMETER(MousePos
);
918 SetFocus(hed
->hWndSelf
);
920 si
.cbSize
= sizeof(SCROLLINFO
);
922 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
927 si
.nPos
+= cyMoveLines
;
928 SetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
, TRUE
);
930 GetScrollInfo(hed
->hWndSelf
, SB_VERT
, &si
);
931 if(si
.nPos
!= ScrollY
)
933 ScrollWindow(hed
->hWndSelf
, 0, (ScrollY
- si
.nPos
) * hed
->LineHeight
, NULL
, NULL
);
934 UpdateWindow(hed
->hWndSelf
);
941 HEXEDIT_WM_GETDLGCODE(LPMSG Msg
)
943 UNREFERENCED_PARAMETER(Msg
);
944 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
948 HEXEDIT_WM_LBUTTONDOWN(PHEXEDIT_DATA hed
, INT Buttons
, POINTS Pt
)
954 UNREFERENCED_PARAMETER(Buttons
);
955 SetFocus(hed
->hWndSelf
);
957 if (GetAsyncKeyState(VK_SHIFT
) < 0)
959 if (hed
->EditingField
)
960 hed
->Index
= HEXEDIT_IndexFromPoint(hed
, Pt
, HEHT_HEXDUMP
, &EditPos
, &NewField
);
962 hed
->Index
= HEXEDIT_IndexFromPoint(hed
, Pt
, HEHT_ASCIIDUMP
, &EditPos
, &NewField
);
963 hed
->SelEnd
= hed
->Index
;
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
);
973 hed
->CaretCol
= EditPos
.x
;
974 hed
->CaretLine
= EditPos
.y
;
976 InvalidateRect(hed
->hWndSelf
, NULL
, FALSE
);
977 HEXEDIT_MoveCaret(hed
, TRUE
);
983 HEXEDIT_WM_LBUTTONUP(PHEXEDIT_DATA hed
, INT Buttons
, POINTS Pt
)
987 if (GetCapture() == hed
->hWndSelf
)
989 if (hed
->EditingField
)
990 hed
->Index
= HEXEDIT_IndexFromPoint(hed
, Pt
, HEHT_HEXDUMP
, &EditPos
, &NewField
);
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
;
997 InvalidateRect(hed
->hWndSelf
, NULL
, FALSE
);
998 HEXEDIT_MoveCaret(hed
, TRUE
);
1004 HEXEDIT_WM_MOUSEMOVE(PHEXEDIT_DATA hed
, INT Buttons
, POINTS Pt
)
1008 if (GetCapture() == hed
->hWndSelf
)
1010 if (hed
->EditingField
)
1011 hed
->Index
= HEXEDIT_IndexFromPoint(hed
, Pt
, HEHT_HEXDUMP
, &EditPos
, &NewField
);
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
);
1024 HEXEDIT_WM_KEYDOWN(PHEXEDIT_DATA hed
, INT VkCode
)
1030 if(GetKeyState(VK_MENU
) & 0x8000)
1035 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
1037 if (hed
->SelStart
< hed
->SelEnd
)
1051 if (GetAsyncKeyState(VK_SHIFT
) >= 0 &&
1052 GetAsyncKeyState(VK_CONTROL
) < 0 && hed
->SelStart
!= hed
->SelEnd
)
1059 if (GetAsyncKeyState(VK_SHIFT
) >= 0 &&
1060 GetAsyncKeyState(VK_CONTROL
) < 0 && hed
->SelStart
!= hed
->SelEnd
)
1067 if (GetAsyncKeyState(VK_SHIFT
) >= 0 && GetAsyncKeyState(VK_CONTROL
) < 0)
1074 if (GetAsyncKeyState(VK_SHIFT
) >= 0 && GetAsyncKeyState(VK_CONTROL
) < 0)
1075 HEXEDIT_SelectAll(hed
);
1081 if (hed
->SelStart
!= hed
->SelEnd
)
1083 if (GetAsyncKeyState(VK_SHIFT
) >= 0 && GetAsyncKeyState(VK_CONTROL
) < 0)
1086 if (GetAsyncKeyState(VK_SHIFT
) < 0 && GetAsyncKeyState(VK_CONTROL
) >= 0)
1091 if (GetAsyncKeyState(VK_SHIFT
) < 0 && GetAsyncKeyState(VK_CONTROL
) >= 0 &&
1092 hed
->SelStart
!= hed
->SelEnd
)
1096 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1099 MoveMemory(buf
+ i0
, buf
+ i1
, bufsize
- i1
);
1100 LocalUnlock(hed
->hBuffer
);
1102 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- (i1
- i0
));
1104 hed
->Index
= hed
->SelStart
= hed
->SelEnd
= i0
;
1105 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1106 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1110 if (hed
->InMid
&& hed
->EditingField
)
1112 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1115 MoveMemory(buf
+ hed
->Index
, buf
+ hed
->Index
+ 1,
1116 bufsize
- hed
->Index
- 1);
1117 LocalUnlock(hed
->hBuffer
);
1119 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- 1);
1122 else if (hed
->Index
< bufsize
)
1124 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1127 MoveMemory(buf
+ hed
->Index
, buf
+ hed
->Index
+ 1,
1128 bufsize
- hed
->Index
- 1);
1129 LocalUnlock(hed
->hBuffer
);
1131 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- 1);
1134 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1135 HEXEDIT_MoveCaret(hed
, TRUE
);
1141 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1144 MoveMemory(buf
+ i0
, buf
+ i1
, bufsize
- i1
);
1145 LocalUnlock(hed
->hBuffer
);
1147 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- (i1
- i0
));
1149 hed
->Index
= hed
->SelStart
= hed
->SelEnd
= i0
;
1150 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1151 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1155 if (hed
->InMid
&& hed
->EditingField
)
1157 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1160 MoveMemory(buf
+ hed
->Index
, buf
+ hed
->Index
+ 1,
1161 bufsize
- hed
->Index
- 1);
1162 LocalUnlock(hed
->hBuffer
);
1165 else if (hed
->Index
> 0)
1167 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1170 MoveMemory(buf
+ hed
->Index
- 1, buf
+ hed
->Index
,
1171 bufsize
- hed
->Index
);
1172 LocalUnlock(hed
->hBuffer
);
1175 hed
->SelStart
= hed
->SelEnd
= hed
->Index
;
1176 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1177 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1181 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- 1);
1184 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1185 HEXEDIT_MoveCaret(hed
, TRUE
);
1192 if (GetAsyncKeyState(VK_SHIFT
) < 0)
1193 hed
->SelEnd
= hed
->Index
;
1195 hed
->SelStart
= hed
->SelEnd
= hed
->Index
;
1196 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1197 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1199 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1200 HEXEDIT_MoveCaret(hed
, TRUE
);
1205 if (hed
->Index
< (INT
)bufsize
)
1208 if (GetAsyncKeyState(VK_SHIFT
) < 0)
1209 hed
->SelEnd
= hed
->Index
;
1211 hed
->SelStart
= hed
->SelEnd
= hed
->Index
;
1212 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1213 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1215 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1216 HEXEDIT_MoveCaret(hed
, TRUE
);
1221 if (hed
->Index
>= hed
->ColumnsPerLine
)
1223 hed
->Index
-= hed
->ColumnsPerLine
;
1224 if (GetAsyncKeyState(VK_SHIFT
) < 0)
1225 hed
->SelEnd
= hed
->Index
;
1227 hed
->SelStart
= hed
->SelEnd
= hed
->Index
;
1228 hed
->CaretCol
= hed
->Index
% hed
->ColumnsPerLine
;
1229 hed
->CaretLine
= hed
->Index
/ hed
->ColumnsPerLine
;
1231 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1232 HEXEDIT_MoveCaret(hed
, TRUE
);
1237 if (hed
->Index
+ hed
->ColumnsPerLine
<= (INT
) bufsize
)
1238 hed
->Index
+= hed
->ColumnsPerLine
;
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
;
1246 hed
->SelStart
= hed
->SelEnd
= hed
->Index
;
1248 InvalidateRect(hed
->hWndSelf
, NULL
, TRUE
);
1249 HEXEDIT_MoveCaret(hed
, TRUE
);
1260 HEXEDIT_WM_CHAR(PHEXEDIT_DATA hed
, WCHAR wch
)
1263 CHAR ch
= (CHAR
)wch
; // keep the lowest octet.
1267 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
1268 if (hed
->SelStart
< hed
->SelEnd
)
1278 if (!hed
->EditingField
)
1280 if (0x20 <= ch
&& ch
<= 0xFF)
1282 if (hed
->SelStart
!= hed
->SelEnd
)
1284 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1287 MoveMemory(buf
+ i0
, buf
+ i1
, bufsize
- i1
);
1288 LocalUnlock(hed
->hBuffer
);
1290 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- (i1
- i0
));
1292 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
1293 hed
->Index
= hed
->SelStart
= hed
->SelEnd
= i0
;
1295 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
+ 1);
1296 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1299 MoveMemory(buf
+ hed
->Index
+ 1, buf
+ hed
->Index
,
1300 bufsize
- hed
->Index
);
1301 buf
[hed
->Index
] = ch
;
1302 LocalUnlock(hed
->hBuffer
);
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
);
1314 if (('0' <= ch
&& ch
<= '9') || ('A' <= ch
&& ch
<= 'F') ||
1315 ('a' <= ch
&& ch
<= 'f'))
1317 if (hed
->SelStart
!= hed
->SelEnd
)
1319 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
1322 MoveMemory(buf
+ i0
, buf
+ i1
, bufsize
- i1
);
1323 LocalUnlock(hed
->hBuffer
);
1325 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
- (i1
- i0
));
1327 bufsize
= (hed
->hBuffer
? LocalSize(hed
->hBuffer
) : 0);
1328 hed
->Index
= hed
->SelStart
= hed
->SelEnd
= i0
;
1332 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
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
);
1348 HexEdit_SetMaxBufferSize(hed
->hWndSelf
, bufsize
+ 1);
1349 buf
= (PBYTE
) LocalLock(hed
->hBuffer
);
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
);
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
);
1375 HEXEDIT_WM_SIZE(PHEXEDIT_DATA hed
, DWORD sType
, WORD NewWidth
, WORD NewHeight
)
1377 UNREFERENCED_PARAMETER(sType
);
1378 UNREFERENCED_PARAMETER(NewHeight
);
1379 UNREFERENCED_PARAMETER(NewWidth
);
1380 HEXEDIT_Update(hed
);
1385 HEXEDIT_WM_CONTEXTMENU(PHEXEDIT_DATA hed
, INT x
, INT y
)
1390 if (x
== -1 && y
== -1)
1392 GetWindowRect(hed
->hWndSelf
, &rc
);
1397 hMenu
= GetSubMenu(hPopupMenus
, PM_HEXEDIT
);
1398 if (hed
->SelStart
== hed
->SelEnd
)
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
);
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
);
1413 SetForegroundWindow(hed
->hWndSelf
);
1414 TrackPopupMenu(hMenu
, TPM_RIGHTBUTTON
, x
, y
, 0, hed
->hWndSelf
, NULL
);
1415 PostMessageW(hed
->hWndSelf
, WM_NULL
, 0, 0);
1419 HexEditWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1424 hed
= (PHEXEDIT_DATA
)(LONG_PTR
)GetWindowLongPtr(hWnd
, (DWORD_PTR
)0);
1431 return HEXEDIT_WM_PAINT(hed
);
1434 return HEXEDIT_WM_KEYDOWN(hed
, (INT
)wParam
);
1437 return HEXEDIT_WM_CHAR(hed
, (WCHAR
)wParam
);
1440 return HEXEDIT_WM_VSCROLL(hed
, HIWORD(wParam
), LOWORD(wParam
));
1443 return HEXEDIT_WM_SIZE(hed
, (DWORD
)wParam
, LOWORD(lParam
), HIWORD(lParam
));
1445 case WM_LBUTTONDOWN
:
1447 p
.x
= LOWORD(lParam
);
1448 p
.y
= HIWORD(lParam
);
1449 return HEXEDIT_WM_LBUTTONDOWN(hed
, (INT
)wParam
, p
);
1454 p
.x
= LOWORD(lParam
);
1455 p
.y
= HIWORD(lParam
);
1456 return HEXEDIT_WM_LBUTTONUP(hed
, (INT
)wParam
, p
);
1461 p
.x
= LOWORD(lParam
);
1462 p
.y
= HIWORD(lParam
);
1463 return HEXEDIT_WM_MOUSEMOVE(hed
, (INT
)wParam
, p
);
1468 UINT nScrollLines
= 3;
1471 SystemParametersInfoW(SPI_GETWHEELSCROLLLINES
, 0, &nScrollLines
, 0);
1472 delta
-= (SHORT
)HIWORD(wParam
);
1473 if(abs(delta
) >= WHEEL_DELTA
&& nScrollLines
!= 0)
1475 p
.x
= LOWORD(lParam
);
1476 p
.y
= HIWORD(lParam
);
1477 return HEXEDIT_WM_MOUSEWHEEL(hed
, nScrollLines
* (delta
/ WHEEL_DELTA
), LOWORD(wParam
), &p
);
1482 case HEM_LOADBUFFER
:
1483 return HEXEDIT_HEM_LOADBUFFER(hed
, (PVOID
)wParam
, (DWORD
)lParam
);
1485 case HEM_COPYBUFFER
:
1486 return HEXEDIT_HEM_COPYBUFFER(hed
, (PVOID
)wParam
, (DWORD
)lParam
);
1488 case HEM_SETMAXBUFFERSIZE
:
1489 return HEXEDIT_HEM_SETMAXBUFFERSIZE(hed
, (DWORD
)lParam
);
1492 return HEXEDIT_WM_SETFOCUS(hed
);
1495 return HEXEDIT_WM_KILLFOCUS(hed
);
1498 return HEXEDIT_WM_GETDLGCODE((LPMSG
)lParam
);
1501 return HEXEDIT_WM_SETFONT(hed
, (HFONT
)wParam
, (BOOL
)LOWORD(lParam
));
1504 return HEXEDIT_WM_GETFONT(hed
);
1507 return HEXEDIT_WM_CREATE(hed
);
1512 return HEXEDIT_WM_NCCREATE(hWnd
, (CREATESTRUCT
*)lParam
);
1519 return HEXEDIT_WM_NCDESTROY(hed
);
1523 case WM_CONTEXTMENU
:
1524 HEXEDIT_WM_CONTEXTMENU(hed
, (short)LOWORD(lParam
), (short)HIWORD(lParam
));
1528 switch(LOWORD(wParam
))
1530 case ID_HEXEDIT_CUT
:
1534 case ID_HEXEDIT_COPY
:
1538 case ID_HEXEDIT_PASTE
:
1542 case ID_HEXEDIT_DELETE
:
1543 HEXEDIT_Delete(hed
);
1546 case ID_HEXEDIT_SELECT_ALL
:
1547 HEXEDIT_SelectAll(hed
);
1553 return DefWindowProcW(hWnd
, uMsg
, wParam
, lParam
);