ntdll: Work around a conflict between Wine and Solaris list.h.
[wine/multimedia.git] / programs / regedit / hexedit.c
blob103a062306e7e05eca8c8af90cc93a1b43b89929
1 /*
2 * Hex Edit control
4 * Copyright 2005 Robert Shearman
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 St, Fifth Floor, Boston, MA 02110-1301, USA
20 * TODO:
21 * - Selection support
22 * - Cut, copy and paste
23 * - Mouse support
26 #include <stdarg.h>
27 #include <string.h>
28 #include <assert.h>
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "winnls.h"
35 #include "commctrl.h"
37 #include "main.h"
39 /* spaces dividing hex and ASCII */
40 #define DIV_SPACES 4
42 typedef struct tagHEXEDIT_INFO
44 HWND hwndSelf;
45 HFONT hFont;
46 BOOL bFocus : 1;
47 BOOL bFocusHex : 1; /* TRUE if focus is on hex, FALSE if focus on ASCII */
48 BOOL bInsert : 1; /* insert mode if TRUE, overwrite mode if FALSE */
49 INT nHeight; /* height of text */
50 INT nCaretPos; /* caret pos in nibbles */
51 BYTE *pData;
52 INT cbData;
53 INT nBytesPerLine; /* bytes of hex to display per line of the control */
54 INT nScrollPos; /* first visible line */
55 } HEXEDIT_INFO;
57 const WCHAR szHexEditClass[] = {'H','e','x','E','d','i','t',0};
59 static inline LRESULT HexEdit_SetFont (HEXEDIT_INFO *infoPtr, HFONT hFont, BOOL redraw);
61 static inline BYTE hexchar_to_byte(WCHAR ch)
63 if (ch >= '0' && ch <= '9')
64 return ch - '0';
65 else if (ch >= 'a' && ch <= 'f')
66 return ch - 'a' + 10;
67 else if (ch >= 'A' && ch <= 'F')
68 return ch - 'A' + 10;
69 else
70 return -1;
73 static LPWSTR HexEdit_GetLineText(BYTE *pData, LONG cbData, LONG pad)
75 static const WCHAR percent_02xW[] = {'%','0','2','X',' ',0};
77 LPWSTR lpszLine = HeapAlloc(GetProcessHeap(), 0,
78 (cbData * 3 + pad * 3 + DIV_SPACES + cbData + 1) * sizeof(WCHAR));
79 LONG i;
81 if (!lpszLine)
82 return NULL;
84 for (i = 0; i < cbData; i++)
85 wsprintfW(lpszLine + i*3, percent_02xW, pData[i]);
86 for (i = 0; i < pad * 3; i++)
87 lpszLine[cbData * 3 + i] = ' ';
89 for (i = 0; i < DIV_SPACES; i++)
90 lpszLine[cbData * 3 + pad * 3 + i] = ' ';
92 /* attempt an ASCII representation if the characters are printable,
93 * otherwise display a '.' */
94 for (i = 0; i < cbData; i++)
96 /* (C1_ALPHA|C1_BLANK|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER) */
97 if (isprint(pData[i]))
98 lpszLine[cbData * 3 + pad * 3 + DIV_SPACES + i] = pData[i];
99 else
100 lpszLine[cbData * 3 + pad * 3 + DIV_SPACES + i] = '.';
102 lpszLine[cbData * 3 + pad * 3 + DIV_SPACES + cbData] = 0;
103 return lpszLine;
106 static void
107 HexEdit_Paint(HEXEDIT_INFO *infoPtr)
109 PAINTSTRUCT ps;
110 HDC hdc = BeginPaint(infoPtr->hwndSelf, &ps);
111 INT nXStart, nYStart;
112 COLORREF clrOldText;
113 HFONT hOldFont;
114 BYTE *pData;
115 INT iMode;
116 LONG lByteOffset = infoPtr->nScrollPos * infoPtr->nBytesPerLine;
118 /* Make a gap from the frame */
119 nXStart = GetSystemMetrics(SM_CXBORDER);
120 nYStart = GetSystemMetrics(SM_CYBORDER);
122 if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)
123 clrOldText = SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
124 else
125 clrOldText = SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
127 iMode = SetBkMode(hdc, TRANSPARENT);
128 hOldFont = SelectObject(hdc, infoPtr->hFont);
130 for (pData = infoPtr->pData + lByteOffset; pData < infoPtr->pData + infoPtr->cbData; pData += infoPtr->nBytesPerLine)
132 LPWSTR lpszLine;
133 LONG nLineLen = min((LONG)((infoPtr->pData + infoPtr->cbData) - pData),
134 infoPtr->nBytesPerLine);
136 lpszLine = HexEdit_GetLineText(pData, nLineLen, infoPtr->nBytesPerLine - nLineLen);
138 /* FIXME: draw hex <-> ASCII mapping highlighted? */
139 TextOutW(hdc, nXStart, nYStart, lpszLine, infoPtr->nBytesPerLine * 3 + DIV_SPACES + nLineLen);
141 nYStart += infoPtr->nHeight;
142 HeapFree(GetProcessHeap(), 0, lpszLine);
145 SelectObject(hdc, hOldFont);
146 SetBkMode(hdc, iMode);
147 SetTextColor(hdc, clrOldText);
149 EndPaint(infoPtr->hwndSelf, &ps);
152 static void
153 HexEdit_UpdateCaret(HEXEDIT_INFO *infoPtr)
155 HDC hdc;
156 HFONT hOldFont;
157 SIZE size;
158 INT nCaretBytePos = infoPtr->nCaretPos/2;
159 INT nByteLinePos = nCaretBytePos % infoPtr->nBytesPerLine;
160 INT nLine = nCaretBytePos / infoPtr->nBytesPerLine;
161 LONG nLineLen = min(infoPtr->cbData - nLine * infoPtr->nBytesPerLine, infoPtr->nBytesPerLine);
162 LPWSTR lpszLine = HexEdit_GetLineText(infoPtr->pData + nLine * infoPtr->nBytesPerLine, nLineLen, infoPtr->nBytesPerLine - nLineLen);
163 INT nCharOffset;
165 /* calculate offset of character caret is on in the line */
166 if (infoPtr->bFocusHex)
167 nCharOffset = nByteLinePos*3 + infoPtr->nCaretPos % 2;
168 else
169 nCharOffset = infoPtr->nBytesPerLine*3 + DIV_SPACES + nByteLinePos;
171 hdc = GetDC(infoPtr->hwndSelf);
172 hOldFont = SelectObject(hdc, infoPtr->hFont);
174 GetTextExtentPoint32W(hdc, lpszLine, nCharOffset, &size);
176 SelectObject(hdc, hOldFont);
177 ReleaseDC(infoPtr->hwndSelf, hdc);
179 if (!nLineLen) size.cx = 0;
181 HeapFree(GetProcessHeap(), 0, lpszLine);
183 SetCaretPos(
184 GetSystemMetrics(SM_CXBORDER) + size.cx,
185 GetSystemMetrics(SM_CYBORDER) + (nLine - infoPtr->nScrollPos) * infoPtr->nHeight);
188 static void
189 HexEdit_UpdateScrollbars(HEXEDIT_INFO *infoPtr)
191 RECT rcClient;
192 INT nLines = infoPtr->cbData / infoPtr->nBytesPerLine;
193 INT nVisibleLines;
194 SCROLLINFO si;
196 GetClientRect(infoPtr->hwndSelf, &rcClient);
197 InflateRect(&rcClient, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
199 nVisibleLines = (rcClient.bottom - rcClient.top) / infoPtr->nHeight;
200 si.cbSize = sizeof(si);
201 si.fMask = SIF_RANGE | SIF_PAGE;
202 si.nMin = 0;
203 si.nMax = max(nLines - nVisibleLines, nLines);
204 si.nPage = nVisibleLines;
205 SetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si, TRUE);
208 static void
209 HexEdit_EnsureVisible(HEXEDIT_INFO *infoPtr, INT nCaretPos)
211 INT nLine = nCaretPos / (2 * infoPtr->nBytesPerLine);
212 SCROLLINFO si;
214 si.cbSize = sizeof(si);
215 si.fMask = SIF_POS | SIF_PAGE;
216 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
217 if (nLine < si.nPos)
218 si.nPos = nLine;
219 else if (nLine >= si.nPos + si.nPage)
220 si.nPos = nLine - si.nPage + 1;
221 else
222 return;
223 si.fMask = SIF_POS;
225 SetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si, FALSE);
226 SendMessageW(infoPtr->hwndSelf, WM_VSCROLL, MAKELONG(SB_THUMBPOSITION, 0), 0);
230 static LRESULT
231 HexEdit_SetData(HEXEDIT_INFO *infoPtr, INT cbData, const BYTE *pData)
233 HeapFree(GetProcessHeap(), 0, infoPtr->pData);
234 infoPtr->cbData = 0;
236 infoPtr->pData = HeapAlloc(GetProcessHeap(), 0, cbData);
237 if (infoPtr->pData)
239 memcpy(infoPtr->pData, pData, cbData);
240 infoPtr->cbData = cbData;
242 infoPtr->nCaretPos = 0;
243 HexEdit_UpdateScrollbars(infoPtr);
244 HexEdit_UpdateCaret(infoPtr);
245 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
246 return TRUE;
248 return FALSE;
251 static LRESULT
252 HexEdit_GetData(HEXEDIT_INFO *infoPtr, INT cbData, BYTE *pData)
254 if (pData)
255 memcpy(pData, infoPtr->pData, min(cbData, infoPtr->cbData));
256 return infoPtr->cbData;
259 static inline LRESULT
260 HexEdit_Char (HEXEDIT_INFO *infoPtr, WCHAR ch)
262 INT nCaretBytePos = infoPtr->nCaretPos/2;
264 assert(nCaretBytePos >= 0);
266 /* backspace is special */
267 if (ch == '\b')
269 if (infoPtr->nCaretPos == 0)
270 return 0;
272 /* if at end of byte then delete the whole byte */
273 if (infoPtr->bFocusHex && (infoPtr->nCaretPos % 2 == 0))
275 memmove(infoPtr->pData + nCaretBytePos - 1,
276 infoPtr->pData + nCaretBytePos,
277 infoPtr->cbData - nCaretBytePos);
278 infoPtr->cbData--;
279 infoPtr->nCaretPos -= 2; /* backtrack two nibble */
281 else /* blank upper nibble */
283 infoPtr->pData[nCaretBytePos] &= 0x0f;
284 infoPtr->nCaretPos--; /* backtrack one nibble */
287 else
289 if (infoPtr->bFocusHex && hexchar_to_byte(ch) == (BYTE)-1)
291 MessageBeep(MB_ICONWARNING);
292 return 0;
295 if ((infoPtr->bInsert && (infoPtr->nCaretPos % 2 == 0)) || (nCaretBytePos >= infoPtr->cbData))
297 /* make room for another byte */
298 infoPtr->cbData++;
299 infoPtr->pData = HeapReAlloc(GetProcessHeap(), 0, infoPtr->pData, infoPtr->cbData + 1);
300 if (!infoPtr->pData) return 0;
301 /* move everything after caret up one byte */
302 memmove(infoPtr->pData + nCaretBytePos + 1,
303 infoPtr->pData + nCaretBytePos,
304 infoPtr->cbData - nCaretBytePos);
305 /* zero new byte */
306 infoPtr->pData[nCaretBytePos] = 0x0;
309 /* overwrite a byte */
311 assert(nCaretBytePos < infoPtr->cbData);
313 if (infoPtr->bFocusHex)
315 BYTE orig_byte = infoPtr->pData[nCaretBytePos];
316 BYTE digit = hexchar_to_byte(ch);
317 if (infoPtr->nCaretPos % 2) /* set low nibble */
318 infoPtr->pData[nCaretBytePos] = (orig_byte & 0xf0) | digit;
319 else /* set high nibble */
320 infoPtr->pData[nCaretBytePos] = (orig_byte & 0x0f) | digit << 4;
321 infoPtr->nCaretPos++; /* advance one nibble */
323 else
325 infoPtr->pData[nCaretBytePos] = (BYTE)ch;
326 infoPtr->nCaretPos += 2; /* advance two nibbles */
330 HexEdit_UpdateScrollbars(infoPtr);
331 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
332 HexEdit_UpdateCaret(infoPtr);
333 HexEdit_EnsureVisible(infoPtr, infoPtr->nCaretPos);
334 return 0;
337 static inline LRESULT
338 HexEdit_Create (HEXEDIT_INFO *infoPtr, LPCREATESTRUCTW lpcs)
340 HexEdit_SetFont(infoPtr, GetStockObject(SYSTEM_FONT), FALSE);
341 HexEdit_UpdateScrollbars(infoPtr);
343 return 0;
347 static inline LRESULT
348 HexEdit_Destroy (HEXEDIT_INFO *infoPtr)
350 HWND hwnd = infoPtr->hwndSelf;
351 HeapFree(GetProcessHeap(), 0, infoPtr->pData);
352 /* free info data */
353 HeapFree(GetProcessHeap(), 0, infoPtr);
354 SetWindowLongPtrW(hwnd, 0, 0);
355 return 0;
359 static inline LRESULT
360 HexEdit_EraseBackground (HEXEDIT_INFO *infoPtr, HDC hdc)
362 HBRUSH hBrush, hSolidBrush = NULL;
363 RECT rc;
365 if (GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & WS_DISABLED)
366 hBrush = hSolidBrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
367 else
369 hBrush = (HBRUSH)SendMessageW(GetParent(infoPtr->hwndSelf), WM_CTLCOLOREDIT,
370 (WPARAM)hdc, (LPARAM)infoPtr->hwndSelf);
371 if (!hBrush)
372 hBrush = hSolidBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
375 GetClientRect (infoPtr->hwndSelf, &rc);
377 FillRect (hdc, &rc, hBrush);
379 if (hSolidBrush)
380 DeleteObject(hSolidBrush);
382 return -1;
386 static inline LRESULT
387 HexEdit_GetFont (HEXEDIT_INFO *infoPtr)
389 return (LRESULT)infoPtr->hFont;
392 static inline LRESULT
393 HexEdit_KeyDown (HEXEDIT_INFO *infoPtr, DWORD key, DWORD flags)
395 INT nInc = (infoPtr->bFocusHex) ? 1 : 2;
396 SCROLLINFO si;
398 switch (key)
400 case VK_LEFT:
401 infoPtr->nCaretPos -= nInc;
402 if (infoPtr->nCaretPos < 0)
403 infoPtr->nCaretPos = 0;
404 break;
405 case VK_RIGHT:
406 infoPtr->nCaretPos += nInc;
407 if (infoPtr->nCaretPos > infoPtr->cbData*2)
408 infoPtr->nCaretPos = infoPtr->cbData*2;
409 break;
410 case VK_UP:
411 if ((infoPtr->nCaretPos - infoPtr->nBytesPerLine*2) >= 0)
412 infoPtr->nCaretPos -= infoPtr->nBytesPerLine*2;
413 break;
414 case VK_DOWN:
415 if ((infoPtr->nCaretPos + infoPtr->nBytesPerLine*2) <= infoPtr->cbData*2)
416 infoPtr->nCaretPos += infoPtr->nBytesPerLine*2;
417 break;
418 case VK_HOME:
419 infoPtr->nCaretPos = 0;
420 break;
421 case VK_END:
422 infoPtr->nCaretPos = infoPtr->cbData*2;
423 break;
424 case VK_PRIOR: /* page up */
425 si.cbSize = sizeof(si);
426 si.fMask = SIF_PAGE;
427 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
428 if ((infoPtr->nCaretPos - (INT)si.nPage*infoPtr->nBytesPerLine*2) >= 0)
429 infoPtr->nCaretPos -= si.nPage*infoPtr->nBytesPerLine*2;
430 else
431 infoPtr->nCaretPos = 0;
432 break;
433 case VK_NEXT: /* page down */
434 si.cbSize = sizeof(si);
435 si.fMask = SIF_PAGE;
436 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
437 if ((infoPtr->nCaretPos + (INT)si.nPage*infoPtr->nBytesPerLine*2) <= infoPtr->cbData*2)
438 infoPtr->nCaretPos += si.nPage*infoPtr->nBytesPerLine*2;
439 else
440 infoPtr->nCaretPos = infoPtr->cbData*2;
441 break;
442 default:
443 return 0;
446 HexEdit_UpdateCaret(infoPtr);
447 HexEdit_EnsureVisible(infoPtr, infoPtr->nCaretPos);
449 return 0;
453 static inline LRESULT
454 HexEdit_KillFocus (HEXEDIT_INFO *infoPtr, HWND receiveFocus)
456 infoPtr->bFocus = FALSE;
457 DestroyCaret();
459 return 0;
463 static inline LRESULT
464 HexEdit_LButtonDown (HEXEDIT_INFO *infoPtr)
466 SetFocus(infoPtr->hwndSelf);
468 /* FIXME: hittest and set caret */
470 return 0;
474 static inline LRESULT HexEdit_NCCreate (HWND hwnd, LPCREATESTRUCTW lpcs)
476 HEXEDIT_INFO *infoPtr;
477 SetWindowLongW(hwnd, GWL_EXSTYLE,
478 lpcs->dwExStyle | WS_EX_CLIENTEDGE);
480 /* allocate memory for info structure */
481 infoPtr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEXEDIT_INFO));
482 SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)infoPtr);
484 /* initialize info structure */
485 infoPtr->nCaretPos = 0;
486 infoPtr->hwndSelf = hwnd;
487 infoPtr->nBytesPerLine = 2;
488 infoPtr->bFocusHex = TRUE;
489 infoPtr->bInsert = TRUE;
491 return DefWindowProcW(infoPtr->hwndSelf, WM_NCCREATE, 0, (LPARAM)lpcs);
494 static inline LRESULT
495 HexEdit_SetFocus (HEXEDIT_INFO *infoPtr, HWND lostFocus)
497 infoPtr->bFocus = TRUE;
499 CreateCaret(infoPtr->hwndSelf, NULL, 1, infoPtr->nHeight);
500 HexEdit_UpdateCaret(infoPtr);
501 ShowCaret(infoPtr->hwndSelf);
503 return 0;
507 static inline LRESULT
508 HexEdit_SetFont (HEXEDIT_INFO *infoPtr, HFONT hFont, BOOL redraw)
510 TEXTMETRICW tm;
511 HDC hdc;
512 HFONT hOldFont = NULL;
513 LONG i;
514 RECT rcClient;
516 infoPtr->hFont = hFont;
518 hdc = GetDC(infoPtr->hwndSelf);
519 if (infoPtr->hFont)
520 hOldFont = SelectObject(hdc, infoPtr->hFont);
522 GetTextMetricsW(hdc, &tm);
523 infoPtr->nHeight = tm.tmHeight + tm.tmExternalLeading;
525 GetClientRect(infoPtr->hwndSelf, &rcClient);
527 for (i = 0; ; i++)
529 BYTE *pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, i);
530 LPWSTR lpszLine = HexEdit_GetLineText(pData, i, 0);
531 SIZE size;
532 GetTextExtentPoint32W(hdc, lpszLine, lstrlenW(lpszLine), &size);
533 HeapFree(GetProcessHeap(), 0, lpszLine);
534 HeapFree(GetProcessHeap(), 0, pData);
535 if (size.cx > (rcClient.right - rcClient.left))
537 infoPtr->nBytesPerLine = i - 1;
538 break;
542 if (infoPtr->hFont)
543 SelectObject(hdc, hOldFont);
544 ReleaseDC (infoPtr->hwndSelf, hdc);
546 if (redraw)
547 InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
549 return 0;
552 static inline LRESULT
553 HexEdit_VScroll (HEXEDIT_INFO *infoPtr, INT action)
555 SCROLLINFO si;
557 /* get all scroll bar info */
558 si.cbSize = sizeof(si);
559 si.fMask = SIF_ALL;
560 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
562 switch (LOWORD(action))
564 case SB_TOP: /* user pressed the home key */
565 si.nPos = si.nMin;
566 break;
568 case SB_BOTTOM: /* user pressed the end key */
569 si.nPos = si.nMax;
570 break;
572 case SB_LINEUP: /* user clicked the up arrow */
573 si.nPos -= 1;
574 break;
576 case SB_LINEDOWN: /* user clicked the down arrow */
577 si.nPos += 1;
578 break;
580 case SB_PAGEUP: /* user clicked the scroll bar above the scroll thumb */
581 si.nPos -= si.nPage;
582 break;
584 case SB_PAGEDOWN: /* user clicked the scroll bar below the scroll thumb */
585 si.nPos += si.nPage;
586 break;
588 case SB_THUMBTRACK: /* user dragged the scroll thumb */
589 si.nPos = si.nTrackPos;
590 break;
592 default:
593 break;
596 /* set the position and then retrieve it to let the system handle the
597 * cases where the position is out of range */
598 si.fMask = SIF_POS;
599 SetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si, TRUE);
600 GetScrollInfo(infoPtr->hwndSelf, SB_VERT, &si);
602 if (si.nPos != infoPtr->nScrollPos)
604 ScrollWindow(infoPtr->hwndSelf, 0, infoPtr->nHeight * (infoPtr->nScrollPos - si.nPos), NULL, NULL);
605 infoPtr->nScrollPos = si.nPos;
606 UpdateWindow(infoPtr->hwndSelf);
608 /* need to update caret position since it depends on the scroll position */
609 HexEdit_UpdateCaret(infoPtr);
611 return 0;
615 static LRESULT WINAPI
616 HexEdit_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
618 HEXEDIT_INFO *infoPtr = (HEXEDIT_INFO *)GetWindowLongPtrW(hwnd, 0);
620 if (!infoPtr && (uMsg != WM_NCCREATE))
621 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
623 switch (uMsg)
625 case HEM_SETDATA:
626 return HexEdit_SetData (infoPtr, (INT)wParam, (const BYTE *)lParam);
628 case HEM_GETDATA:
629 return HexEdit_GetData (infoPtr, (INT)wParam, (BYTE *)lParam);
631 case WM_CHAR:
632 return HexEdit_Char (infoPtr, (WCHAR)wParam);
634 case WM_CREATE:
635 return HexEdit_Create (infoPtr, (LPCREATESTRUCTW)lParam);
637 case WM_DESTROY:
638 return HexEdit_Destroy (infoPtr);
640 case WM_ERASEBKGND:
641 return HexEdit_EraseBackground (infoPtr, (HDC)wParam);
643 case WM_GETDLGCODE:
644 return DLGC_WANTCHARS | DLGC_WANTARROWS;
646 case WM_GETFONT:
647 return HexEdit_GetFont (infoPtr);
649 case WM_KEYDOWN:
650 return HexEdit_KeyDown (infoPtr, wParam, lParam);
652 case WM_KILLFOCUS:
653 return HexEdit_KillFocus (infoPtr, (HWND)wParam);
655 case WM_LBUTTONDOWN:
656 return HexEdit_LButtonDown (infoPtr);
658 case WM_NCCREATE:
659 return HexEdit_NCCreate (hwnd, (LPCREATESTRUCTW)lParam);
661 case WM_PAINT:
662 HexEdit_Paint(infoPtr);
663 return 0;
665 case WM_SETFOCUS:
666 return HexEdit_SetFocus (infoPtr, (HWND)wParam);
668 case WM_SETFONT:
669 return HexEdit_SetFont (infoPtr, (HFONT)wParam, LOWORD(lParam));
671 case WM_VSCROLL:
672 return HexEdit_VScroll (infoPtr, (INT)wParam);
674 default:
675 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
677 return 0;
680 void HexEdit_Register(void)
682 WNDCLASSW wndClass;
684 ZeroMemory(&wndClass, sizeof(WNDCLASSW));
685 wndClass.style = 0;
686 wndClass.lpfnWndProc = HexEdit_WindowProc;
687 wndClass.cbClsExtra = 0;
688 wndClass.cbWndExtra = sizeof(HEXEDIT_INFO *);
689 wndClass.hCursor = NULL;
690 wndClass.hbrBackground = NULL;
691 wndClass.lpszClassName = szHexEditClass;
693 RegisterClassW(&wndClass);