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