some little fixes
[reactos.git] / reactos / subsys / system / 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #define WIN32_LEAN_AND_MEAN /* Exclude rarely-used stuff from Windows headers */
22 #include <windows.h>
23 #include <commctrl.h>
24 #include <tchar.h>
25
26 #include "hexedit.h"
27
28 typedef struct
29 {
30 HWND hWndSelf;
31 HWND hWndParent;
32 HLOCAL hBuffer;
33 DWORD style;
34 DWORD MaxBuffer;
35 DWORD ColumnsPerLine;
36 DWORD nLines;
37 DWORD nVisibleLines;
38 INT Position;
39 INT LineHeight;
40 INT CharWidth;
41 HFONT hFont;
42
43 INT LeftMargin;
44 INT AddressSpacing;
45 INT SplitSpacing;
46
47 BOOL EditingField;
48 INT CaretCol;
49 INT CaretLine;
50 } HEXEDIT_DATA, *PHEXEDIT_DATA;
51
52 /* hit test codes */
53 #define HEHT_LEFTMARGIN (0x1)
54 #define HEHT_ADDRESS (0x2)
55 #define HEHT_ADDRESSSPACING (0x3)
56 #define HEHT_HEXDUMP (0x4)
57 #define HEHT_HEXDUMPSPACING (0x5)
58 #define HEHT_ASCIIDUMP (0x6)
59 #define HEHT_RIGHTMARGIN (0x7)
60
61 LRESULT WINAPI HexEditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
62
63 ATOM
64 STDCALL
65 RegisterHexEditorClass(HINSTANCE hInstance)
66 {
67 WNDCLASSEX WndClass;
68
69 ZeroMemory(&WndClass, sizeof(WNDCLASSEX));
70 WndClass.cbSize = sizeof(WNDCLASSEX);
71 WndClass.style = CS_DBLCLKS;
72 WndClass.lpfnWndProc = (WNDPROC)HexEditWndProc;
73 WndClass.cbWndExtra = sizeof(PHEXEDIT_DATA);
74 WndClass.hInstance = hInstance;
75 WndClass.hCursor = LoadCursor(0, IDC_IBEAM);
76 WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
77 WndClass.lpszClassName = HEX_EDIT_CLASS_NAME;
78
79 return RegisterClassEx(&WndClass);
80 }
81
82 BOOL
83 STDCALL
84 UnregisterHexEditorClass(HINSTANCE hInstance)
85 {
86 return UnregisterClass(HEX_EDIT_CLASS_NAME, hInstance);
87 }
88
89 /*** Helper functions *********************************************************/
90
91 static VOID
92 HEXEDIT_MoveCaret(PHEXEDIT_DATA hed, INT Line, INT Column, BOOL HexDump)
93 {
94 SCROLLINFO si;
95
96 si.cbSize = sizeof(SCROLLINFO);
97 si.fMask = SIF_POS;
98 GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
99
100 if(si.nPos > Line)
101 {
102 si.nPos = Line;
103 SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
104 GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
105 InvalidateRect(hed->hWndSelf, NULL, TRUE);
106 }
107 else if((Line - si.nPos) > hed->nVisibleLines)
108 {
109 si.nPos += (Line - si.nPos);
110 SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
111 GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
112 InvalidateRect(hed->hWndSelf, NULL, TRUE);
113 }
114
115 if(HexDump)
116 SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing) * hed->CharWidth) - 2, (Line - si.nPos) * hed->LineHeight);
117 else
118 SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine)) * hed->CharWidth) - 2, (Line - si.nPos) * hed->LineHeight);
119 }
120
121 static VOID
122 HEXEDIT_Update(PHEXEDIT_DATA hed)
123 {
124 SCROLLINFO si;
125 RECT rcClient;
126
127 GetClientRect(hed->hWndSelf, &rcClient);
128 hed->style = GetWindowLong(hed->hWndSelf, GWL_STYLE);
129
130 hed->nLines = max((hed->hBuffer ? LocalSize(hed->hBuffer) / hed->ColumnsPerLine : 1), 1);
131
132 if(hed->LineHeight > 0)
133 {
134 hed->nVisibleLines = rcClient.bottom / hed->LineHeight;
135 if(rcClient.bottom % hed->LineHeight)
136 {
137 hed->nVisibleLines++;
138 }
139 }
140 else
141 hed->nVisibleLines = 0;
142
143 /* update scrollbar */
144 si.cbSize = sizeof(SCROLLINFO);
145 si.fMask = SIF_RANGE | SIF_PAGE;
146 si.nMin = 0;
147 si.nMax = hed->nLines;
148 if(hed->LineHeight > 0)
149 si.nPage = rcClient.bottom / hed->LineHeight;
150 else
151 si.nPage = 0;
152 SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
153
154 if(hed->style & WS_VISIBLE)
155 {
156 InvalidateRect(hed->hWndSelf, NULL, TRUE);
157 }
158 }
159
160 static HFONT
161 HEXEDIT_GetFixedFont(VOID)
162 {
163 LOGFONT lf;
164 GetObject(GetStockObject(ANSI_FIXED_FONT), sizeof(LOGFONT), &lf);
165 return CreateFontIndirect(&lf);
166 }
167
168 static VOID
169 HEXEDIT_PaintLines(PHEXEDIT_DATA hed, HDC hDC, DWORD ScrollPos, DWORD First, DWORD Last, RECT *rc)
170 {
171 DWORD x, dx, dy, linestart;
172 PBYTE buf, current, end, line;
173 UINT bufsize;
174 TCHAR hex[3], addr[17];
175 RECT rct;
176
177 if(hed->hBuffer)
178 {
179 bufsize = LocalSize(hed->hBuffer);
180 buf = LocalLock(hed->hBuffer);
181 }
182 else
183 {
184 buf = NULL;
185 bufsize = 0;
186 }
187
188 FillRect(hDC, rc, (HBRUSH)(COLOR_WINDOW + 1));
189 if(buf)
190 {
191 end = buf + bufsize;
192 dy = First * hed->LineHeight;
193 linestart = (ScrollPos + First) * hed->ColumnsPerLine;
194 current = buf + linestart;
195 Last = min(hed->nLines - ScrollPos, Last);
196
197 while(First <= Last && current < end)
198 {
199 DWORD dh;
200
201 dx = hed->LeftMargin;
202
203 /* draw address */
204 _stprintf(addr, _T("%04X"), linestart);
205 TextOut(hDC, dx, dy, addr, 4);
206
207 dx += ((4 + hed->AddressSpacing) * hed->CharWidth);
208 dh = (3 * hed->CharWidth);
209
210 rct.left = dx;
211 rct.top = dy;
212 rct.right = rct.left + dh;
213 rct.bottom = dy + hed->LineHeight;
214
215 /* draw hex map */
216 dx += (hed->CharWidth / 2);
217 line = current;
218 for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
219 {
220 rct.left += dh;
221 rct.right += dh;
222
223 _stprintf(hex, _T("%02X"), *(current++));
224 ExtTextOut(hDC, dx, dy, ETO_OPAQUE, &rct, hex, 2, NULL);
225 dx += dh;
226 }
227
228 /* draw ascii map */
229 dx = ((4 + hed->AddressSpacing + hed->SplitSpacing + (hed->ColumnsPerLine * 3)) * hed->CharWidth);
230 current = line;
231 for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
232 {
233 _stprintf(hex, _T("%C"), *(current++));
234 hex[0] = ((hex[0] & _T('\x007f')) >= _T(' ') ? hex[0] : _T('.'));
235 TextOut(hDC, dx, dy, hex, 1);
236 dx += hed->CharWidth;
237 }
238
239 dy += hed->LineHeight;
240 linestart += hed->ColumnsPerLine;
241 First++;
242 }
243 }
244
245 LocalUnlock(hed->hBuffer);
246 }
247
248 static DWORD
249 HEXEDIT_HitRegionTest(PHEXEDIT_DATA hed, POINTS pt, POINTS *ptClient)
250 {
251 WINDOWINFO wi;
252 int d, x;
253
254 wi.cbSize = sizeof(WINDOWINFO);
255 GetWindowInfo(hed->hWndSelf, &wi);
256
257 x = pt.x - wi.rcClient.left;
258 if(ptClient)
259 {
260 ptClient->x = x;
261 ptClient->y = pt.y - wi.rcClient.top;
262 }
263
264 if(x <= hed->LeftMargin)
265 {
266 return HEHT_LEFTMARGIN;
267 }
268
269 x -= hed->LeftMargin;
270 d = (4 * hed->CharWidth);
271 if(x <= d)
272 {
273 return HEHT_ADDRESS;
274 }
275
276 x -= d;
277 d = (hed->AddressSpacing * hed->CharWidth);
278 if(x <= d)
279 {
280 return HEHT_ADDRESSSPACING;
281 }
282
283 x -= d;
284 d = (3 * hed->ColumnsPerLine * hed->CharWidth);
285 if(x <= d)
286 {
287 return HEHT_HEXDUMP;
288 }
289
290 x -= d;
291 d = (hed->SplitSpacing * hed->CharWidth);
292 if(x <= d)
293 {
294 return HEHT_HEXDUMPSPACING;
295 }
296
297 x -= d;
298 d = (hed->ColumnsPerLine * hed->CharWidth);
299 if(x <= d)
300 {
301 return HEHT_ASCIIDUMP;
302 }
303
304 return HEHT_RIGHTMARGIN;
305 }
306
307 static DWORD
308 HEXEDIT_PositionFromPoint(PHEXEDIT_DATA hed, POINTS pt, DWORD *Hit)
309 {
310 SCROLLINFO si;
311 POINTS ptClient;
312 DWORD Line;
313
314 *Hit = HEXEDIT_HitRegionTest(hed, pt, &ptClient);
315
316 si.cbSize = sizeof(SCROLLINFO);
317 si.fMask = SIF_POS;
318 GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
319
320 if(hed->LineHeight > 0)
321 {
322 Line = min(si.nPos + (ptClient.y / hed->LineHeight), hed->nLines);
323 }
324 else
325 return 0;
326
327 switch(*Hit)
328 {
329 case HEHT_LEFTMARGIN:
330 case HEHT_ADDRESS:
331 case HEHT_ADDRESSSPACING:
332 return Line * hed->ColumnsPerLine;
333
334 case HEHT_HEXDUMP:
335 return 0;
336
337 case HEHT_ASCIIDUMP:
338 return 0;
339
340 case HEHT_RIGHTMARGIN:
341 return (Line + 1) * hed->ColumnsPerLine;
342 }
343 }
344
345 /*** Control specific messages ************************************************/
346
347 static LRESULT
348 HEXEDIT_HEM_LOADBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size)
349 {
350 if(Buffer != NULL && Size > 0)
351 {
352 LPVOID buf;
353
354 if(hed->MaxBuffer > 0 && Size > hed->MaxBuffer)
355 {
356 Size = hed->MaxBuffer;
357 }
358
359 if(hed->hBuffer)
360 {
361 if(Size > 0)
362 {
363 if(LocalSize(hed->hBuffer) != Size)
364 {
365 hed->hBuffer = LocalReAlloc(hed->hBuffer, Size, LMEM_MOVEABLE | LMEM_ZEROINIT);
366 }
367 }
368 else
369 {
370 hed->hBuffer = LocalFree(hed->hBuffer);
371 hed->Position = 0;
372 HEXEDIT_Update(hed);
373
374 return 0;
375 }
376 }
377 else if(Size > 0)
378 {
379 hed->hBuffer = LocalAlloc(LHND, Size);
380 }
381
382 if(Size > 0)
383 {
384 buf = LocalLock(hed->hBuffer);
385 if(buf)
386 {
387 memcpy(buf, Buffer, Size);
388 }
389 else
390 Size = 0;
391 LocalUnlock(hed->hBuffer);
392 }
393
394 hed->Position = 0;
395 HEXEDIT_Update(hed);
396 return Size;
397 }
398 else if(hed->hBuffer)
399 {
400 hed->Position = 0;
401 hed->hBuffer = LocalFree(hed->hBuffer);
402 HEXEDIT_Update(hed);
403 }
404
405 return 0;
406 }
407
408 static LRESULT
409 HEXEDIT_HEM_COPYBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size)
410 {
411 DWORD nCpy;
412
413 if(!hed->hBuffer)
414 {
415 return 0;
416 }
417
418 if(Buffer != NULL && Size > 0)
419 {
420 nCpy = min(Size, LocalSize(hed->hBuffer));
421 if(nCpy > 0)
422 {
423 PVOID buf;
424
425 buf = LocalLock(hed->hBuffer);
426 if(buf)
427 {
428 memcpy(Buffer, buf, nCpy);
429 }
430 else
431 nCpy = 0;
432 LocalUnlock(hed->hBuffer);
433 }
434 return nCpy;
435 }
436
437 return (LRESULT)LocalSize(hed->hBuffer);
438 }
439
440 static LRESULT
441 HEXEDIT_HEM_SETMAXBUFFERSIZE(PHEXEDIT_DATA hed, DWORD nMaxSize)
442 {
443 hed->MaxBuffer = nMaxSize;
444 if(hed->MaxBuffer > 0 && hed->hBuffer && LocalSize(hed->hBuffer) > hed->MaxBuffer)
445 {
446 /* truncate the buffer */
447 hed->hBuffer = LocalReAlloc(hed->hBuffer, hed->MaxBuffer, LMEM_MOVEABLE);
448 HEXEDIT_Update(hed);
449 }
450 }
451
452 /*** Message Proc *************************************************************/
453
454 static LRESULT
455 HEXEDIT_WM_NCCREATE(HWND hWnd, CREATESTRUCT *cs)
456 {
457 PHEXEDIT_DATA hed;
458
459 if(!(hed = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEXEDIT_DATA))))
460 {
461 return FALSE;
462 }
463
464 hed->hWndSelf = hWnd;
465 hed->hWndParent = cs->hwndParent;
466 hed->style = cs->style;
467
468 hed->ColumnsPerLine = 8;
469 hed->LeftMargin = 2;
470 hed->AddressSpacing = 2;
471 hed->SplitSpacing = 2;
472 hed->EditingField = TRUE; /* in hexdump field */
473
474 SetWindowLong(hWnd, 0, (LONG)hed);
475
476 return TRUE;
477 }
478
479 static LRESULT
480 HEXEDIT_WM_NCDESTROY(PHEXEDIT_DATA hed)
481 {
482 if(hed->hBuffer)
483 {
484 while(LocalUnlock(hed->hBuffer));
485 LocalFree(hed->hBuffer);
486 }
487
488 SetWindowLong(hed->hWndSelf, 0, 0);
489 HeapFree(GetProcessHeap(), 0, hed);
490
491 return 0;
492 }
493
494 static LRESULT
495 HEXEDIT_WM_CREATE(PHEXEDIT_DATA hed)
496 {
497 return 1;
498 }
499
500 static LRESULT
501 HEXEDIT_WM_SETFOCUS(PHEXEDIT_DATA hed)
502 {
503 CreateCaret(hed->hWndSelf, 0, 1, hed->LineHeight);
504 HEXEDIT_MoveCaret(hed, hed->CaretLine, hed->CaretCol, hed->EditingField);
505 ShowCaret(hed->hWndSelf);
506 return 0;
507 }
508
509 static LRESULT
510 HEXEDIT_WM_KILLFOCUS(PHEXEDIT_DATA hed)
511 {
512 DestroyCaret();
513 return 0;
514 }
515
516 static LRESULT
517 HEXEDIT_WM_VSCROLL(PHEXEDIT_DATA hed, WORD ThumbPosition, WORD SbCmd)
518 {
519 int ScrollY;
520 SCROLLINFO si;
521
522 ZeroMemory(&si, sizeof(SCROLLINFO));
523 si.cbSize = sizeof(SCROLLINFO);
524 si.fMask = SIF_ALL;
525 GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
526
527 ScrollY = si.nPos;
528 switch(SbCmd)
529 {
530 case SB_TOP:
531 si.nPos = si.nMin;
532 break;
533
534 case SB_BOTTOM:
535 si.nPos = si.nMax;
536 break;
537
538 case SB_LINEUP:
539 si.nPos--;
540 break;
541
542 case SB_LINEDOWN:
543 si.nPos++;
544 break;
545
546 case SB_PAGEUP:
547 si.nPos -= si.nPage;
548 break;
549
550 case SB_PAGEDOWN:
551 si.nPos += si.nPage;
552 break;
553
554 case SB_THUMBTRACK:
555 si.nPos = si.nTrackPos;
556 break;
557 }
558
559 si.fMask = SIF_POS;
560 SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
561 GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
562
563 if(si.nPos != ScrollY)
564 {
565 ScrollWindow(hed->hWndSelf, 0, (ScrollY - si.nPos) * hed->LineHeight, NULL, NULL);
566 UpdateWindow(hed->hWndSelf);
567 }
568
569 return 0;
570 }
571
572 static LRESULT
573 HEXEDIT_WM_SETFONT(PHEXEDIT_DATA hed, HFONT hFont, BOOL bRedraw)
574 {
575 HDC hDC;
576 TEXTMETRIC tm;
577 HFONT hOldFont = 0;
578
579 if(hFont == 0)
580 {
581 hFont = HEXEDIT_GetFixedFont();
582 }
583
584 hed->hFont = hFont;
585 hDC = GetDC(hed->hWndSelf);
586 if(hFont)
587 {
588 hOldFont = SelectObject(hDC, hFont);
589 }
590 GetTextMetrics(hDC, &tm);
591 hed->LineHeight = tm.tmHeight;
592 hed->CharWidth = tm.tmAveCharWidth;
593 if(hOldFont)
594 {
595 SelectObject(hDC, hOldFont);
596 }
597 ReleaseDC(hed->hWndSelf, hDC);
598
599 if(bRedraw)
600 {
601 InvalidateRect(hed->hWndSelf, NULL, TRUE);
602 }
603
604 return 0;
605 }
606
607 static LRESULT
608 HEXEDIT_WM_GETFONT(PHEXEDIT_DATA hed)
609 {
610 return (LRESULT)hed->hFont;
611 }
612
613 static LRESULT
614 HEXEDIT_WM_PAINT(PHEXEDIT_DATA hed)
615 {
616 PAINTSTRUCT ps;
617 SCROLLINFO si;
618 RECT rc;
619 HBITMAP hbmp, hbmpold;
620 DWORD nLines, nFirst;
621 HFONT hOldFont;
622 HDC hTempDC;
623 DWORD height;
624
625 if(GetUpdateRect(hed->hWndSelf, &rc, FALSE) && (hed->LineHeight > 0))
626 {
627 ZeroMemory(&si, sizeof(SCROLLINFO));
628 si.cbSize = sizeof(SCROLLINFO);
629 si.fMask = SIF_POS;
630 GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
631
632 height = (rc.bottom - rc.top);
633 nLines = height / hed->LineHeight;
634 if((height % hed->LineHeight) > 0)
635 {
636 nLines++;
637 }
638 if(nLines > hed->nLines - si.nPos)
639 {
640 nLines = hed->nLines - si.nPos;
641 }
642 nFirst = rc.top / hed->LineHeight;
643
644 BeginPaint(hed->hWndSelf, &ps);
645 if(!(hTempDC = CreateCompatibleDC(ps.hdc)))
646 {
647 FillRect(ps.hdc, &rc, (HBRUSH)(COLOR_WINDOW + 1));
648 goto epaint;
649 }
650 if(!(hbmp = CreateCompatibleBitmap(hTempDC, ps.rcPaint.right, ps.rcPaint.bottom)))
651 {
652 FillRect(ps.hdc, &rc, (HBRUSH)(COLOR_WINDOW + 1));
653 DeleteDC(hTempDC);
654 goto epaint;
655 }
656 hbmpold = SelectObject(hTempDC, hbmp);
657 hOldFont = SelectObject(hTempDC, hed->hFont);
658 HEXEDIT_PaintLines(hed, hTempDC, si.nPos, nFirst, nFirst + nLines, &ps.rcPaint);
659 BitBlt(ps.hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hTempDC, rc.left, rc.top, SRCCOPY);
660 SelectObject(hTempDC, hOldFont);
661 SelectObject(hTempDC, hbmpold);
662
663 DeleteObject(hbmp);
664 DeleteDC(hTempDC);
665
666 epaint:
667 EndPaint(hed->hWndSelf, &ps);
668 }
669
670 return 0;
671 }
672
673 static LRESULT
674 HEXEDIT_WM_MOUSEWHEEL(PHEXEDIT_DATA hed, int cyMoveLines, WORD ButtonsDown, LPPOINTS MousePos)
675 {
676 SCROLLINFO si;
677 int ScrollY;
678
679 SetFocus(hed->hWndSelf);
680
681 si.cbSize = sizeof(SCROLLINFO);
682 si.fMask = SIF_ALL;
683 GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
684
685 ScrollY = si.nPos;
686
687 si.fMask = SIF_POS;
688 si.nPos += cyMoveLines;
689 SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
690
691 GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
692 if(si.nPos != ScrollY)
693 {
694 ScrollWindow(hed->hWndSelf, 0, (ScrollY - si.nPos) * hed->LineHeight, NULL, NULL);
695 UpdateWindow(hed->hWndSelf);
696 }
697
698 return 0;
699 }
700
701 static LRESULT
702 HEXEDIT_WM_SETCURSOR(PHEXEDIT_DATA hed)
703 {
704 POINTS pt;
705 DWORD Hit, Pos;
706
707 Pos = GetMessagePos();
708 pt = MAKEPOINTS(Pos);
709 Hit = HEXEDIT_HitRegionTest(hed, pt, NULL);
710
711 switch(Hit)
712 {
713 case HEHT_HEXDUMP:
714 case HEHT_HEXDUMPSPACING:
715 case HEHT_ASCIIDUMP:
716 SetCursor(LoadCursor(0, MAKEINTRESOURCE(IDC_IBEAM)));
717 break;
718
719 default:
720 SetCursor(LoadCursor(0, MAKEINTRESOURCE(IDC_ARROW)));
721 break;
722 }
723 return TRUE;
724 }
725
726 static BOOL
727 HEXEDIT_WM_KEYDOWN(PHEXEDIT_DATA hed, INT VkCode)
728 {
729 DWORD bufsize;
730 BOOL shift, control, handled;
731
732 if(GetKeyState(VK_MENU) & 0x8000)
733 {
734 return FALSE;
735 }
736
737 shift = GetKeyState(VK_SHIFT) & 0x8000;
738 control = GetKeyState(VK_CONTROL) & 0x8000;
739
740 bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
741 handled = FALSE;
742
743 switch(VkCode)
744 {
745 case VK_LEFT:MessageBox(0, L"", L"", 0);
746 if(hed->Position > 0)
747 {
748 if(--hed->CaretCol < 0)
749 {
750 hed->CaretLine--;
751 hed->CaretCol = hed->ColumnsPerLine;
752 }
753 else
754 hed->Position--;
755
756 HEXEDIT_MoveCaret(hed, hed->CaretLine, hed->CaretCol, hed->EditingField);
757 }
758 handled = TRUE;
759 break;
760
761 case VK_RIGHT:
762 if(hed->Position < bufsize)
763 {
764 if(++hed->CaretCol > hed->ColumnsPerLine)
765 {
766 hed->CaretLine = 0;
767 hed->CaretLine++;
768 }
769 else
770 hed->Position++;
771
772 HEXEDIT_MoveCaret(hed, hed->CaretLine, hed->CaretCol, hed->EditingField);
773 }
774 handled = TRUE;
775 break;
776 }
777
778 return FALSE;
779 }
780
781 LRESULT
782 WINAPI
783 HexEditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
784 {
785 PHEXEDIT_DATA hed;
786
787 hed = (PHEXEDIT_DATA)GetWindowLong(hWnd, 0);
788 switch(uMsg)
789 {
790 case WM_ERASEBKGND:
791 return TRUE;
792
793 case WM_PAINT:
794 return HEXEDIT_WM_PAINT(hed);
795
796 case WM_SETCURSOR:
797 return HEXEDIT_WM_SETCURSOR(hed);
798
799 case WM_KEYDOWN:
800 return HEXEDIT_WM_KEYDOWN(hed, (INT)wParam);
801
802 case WM_VSCROLL:
803 return HEXEDIT_WM_VSCROLL(hed, HIWORD(wParam), LOWORD(wParam));
804
805 case WM_MOUSEWHEEL:
806 return HEXEDIT_WM_MOUSEWHEEL(hed, ((SHORT)(wParam >> 16) < 0 ? 3 : -3), LOWORD(wParam), &MAKEPOINTS(lParam));
807
808 case HEM_LOADBUFFER:
809 return HEXEDIT_HEM_LOADBUFFER(hed, (PVOID)wParam, (DWORD)lParam);
810
811 case HEM_COPYBUFFER:
812 return HEXEDIT_HEM_COPYBUFFER(hed, (PVOID)wParam, (DWORD)lParam);
813
814 case HEM_SETMAXBUFFERSIZE:
815 return HEXEDIT_HEM_SETMAXBUFFERSIZE(hed, (DWORD)lParam);
816
817 case WM_SETFOCUS:
818 return HEXEDIT_WM_SETFOCUS(hed);
819
820 case WM_KILLFOCUS:
821 return HEXEDIT_WM_KILLFOCUS(hed);
822
823 case WM_SETFONT:
824 return HEXEDIT_WM_SETFONT(hed, (HFONT)wParam, (BOOL)LOWORD(lParam));
825
826 case WM_GETFONT:
827 return HEXEDIT_WM_GETFONT(hed);
828
829 case WM_CREATE:
830 return HEXEDIT_WM_CREATE(hed);
831
832 case WM_NCCREATE:
833 if(!hed)
834 {
835 return HEXEDIT_WM_NCCREATE(hWnd, (CREATESTRUCT*)lParam);
836 }
837 break;
838
839 case WM_NCDESTROY:
840 if(hed)
841 {
842 return HEXEDIT_WM_NCDESTROY(hed);
843 }
844 break;
845 }
846
847 return CallWindowProc(DefWindowProc, hWnd, uMsg, wParam, lParam);
848 }
849