ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

hexedit.c
Go to the documentation of this file.
00001 /*
00002  * Hex editor control
00003  *
00004  * Copyright (C) 2004 Thomas Weidenmueller <w3seek@reactos.com>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019  */
00020 
00021 #include <regedit.h>
00022 typedef struct
00023 {
00024     HWND hWndSelf;
00025     HWND hWndParent;
00026     HLOCAL hBuffer;
00027     DWORD style;
00028     DWORD MaxBuffer;
00029     INT ColumnsPerLine;
00030     INT nLines;
00031     INT nVisibleLinesComplete;
00032     INT nVisibleLines;
00033     INT Index;
00034     INT LineHeight;
00035     INT CharWidth;
00036     HFONT hFont;
00037     BOOL SbVisible;
00038 
00039     INT LeftMargin;
00040     INT AddressSpacing;
00041     INT SplitSpacing;
00042 
00043     BOOL EditingField;
00044     INT CaretCol;
00045     INT CaretLine;
00046     BOOL InMid;
00047 
00048     INT SelStart;
00049     INT SelEnd;
00050 } HEXEDIT_DATA, *PHEXEDIT_DATA;
00051 
00052 static const TCHAR ClipboardFormatName[] = TEXT("RegEdit_HexData");
00053 static UINT ClipboardFormatID = 0;
00054 
00055 /* hit test codes */
00056 #define HEHT_LEFTMARGIN (0x1)
00057 #define HEHT_ADDRESS    (0x2)
00058 #define HEHT_ADDRESSSPACING (0x3)
00059 #define HEHT_HEXDUMP    (0x4)
00060 #define HEHT_HEXDUMPSPACING (0x5)
00061 #define HEHT_ASCIIDUMP  (0x6)
00062 #define HEHT_RIGHTMARGIN    (0x7)
00063 
00064 INT_PTR CALLBACK HexEditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
00065 
00066 ATOM
00067 WINAPI
00068 RegisterHexEditorClass(HINSTANCE hInstance)
00069 {
00070     WNDCLASSEX WndClass;
00071 
00072     ClipboardFormatID = RegisterClipboardFormat(ClipboardFormatName);
00073 
00074     ZeroMemory(&WndClass, sizeof(WNDCLASSEX));
00075     WndClass.cbSize = sizeof(WNDCLASSEX);
00076     WndClass.style = CS_DBLCLKS;
00077     WndClass.lpfnWndProc = (WNDPROC)HexEditWndProc;
00078     WndClass.cbWndExtra = sizeof(PHEXEDIT_DATA);
00079     WndClass.hInstance = hInstance;
00080     WndClass.hCursor = LoadCursor(0, IDC_IBEAM);
00081     WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
00082     WndClass.lpszClassName = HEX_EDIT_CLASS_NAME;
00083 
00084     return RegisterClassEx(&WndClass);
00085 }
00086 
00087 BOOL
00088 WINAPI
00089 UnregisterHexEditorClass(HINSTANCE hInstance)
00090 {
00091     return UnregisterClass(HEX_EDIT_CLASS_NAME, hInstance);
00092 }
00093 
00094 /*** Helper functions *********************************************************/
00095 
00096 static VOID
00097 HEXEDIT_MoveCaret(PHEXEDIT_DATA hed, BOOL Scroll)
00098 {
00099     SCROLLINFO si;
00100 
00101     si.cbSize = sizeof(SCROLLINFO);
00102     si.fMask = SIF_POS;
00103     GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
00104 
00105     if(Scroll)
00106     {
00107         if(si.nPos > hed->CaretLine)
00108         {
00109             si.nPos = hed->CaretLine;
00110             SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
00111             GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
00112             InvalidateRect(hed->hWndSelf, NULL, TRUE);
00113         }
00114         else if(hed->CaretLine >= (hed->nVisibleLinesComplete + si.nPos))
00115         {
00116             si.nPos = hed->CaretLine - hed->nVisibleLinesComplete + 1;
00117             SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
00118             GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
00119             InvalidateRect(hed->hWndSelf, NULL, TRUE);
00120         }
00121     }
00122 
00123     if(hed->EditingField)
00124         SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + (3 * hed->CaretCol) + hed->InMid * 2) * hed->CharWidth) - 1, (hed->CaretLine - si.nPos) * hed->LineHeight);
00125     else
00126         SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine) + hed->CaretCol) * hed->CharWidth) - 2, (hed->CaretLine - si.nPos) * hed->LineHeight);
00127 }
00128 
00129 static VOID
00130 HEXEDIT_Update(PHEXEDIT_DATA hed)
00131 {
00132     SCROLLINFO si;
00133     RECT rcClient;
00134     BOOL SbVisible;
00135     INT bufsize, cvislines;
00136 
00137     GetClientRect(hed->hWndSelf, &rcClient);
00138     hed->style = GetWindowLongPtr(hed->hWndSelf, GWL_STYLE);
00139 
00140     bufsize = (hed->hBuffer ? (INT) LocalSize(hed->hBuffer) : 0);
00141     hed->nLines = max(bufsize / hed->ColumnsPerLine, 1);
00142     if(bufsize > hed->ColumnsPerLine && (bufsize % hed->ColumnsPerLine) > 0)
00143     {
00144         hed->nLines++;
00145     }
00146 
00147     if(hed->LineHeight > 0)
00148     {
00149         hed->nVisibleLinesComplete = cvislines = rcClient.bottom / hed->LineHeight;
00150         hed->nVisibleLines = hed->nVisibleLinesComplete;
00151         if(rcClient.bottom % hed->LineHeight)
00152         {
00153             hed->nVisibleLines++;
00154         }
00155     }
00156     else
00157     {
00158         hed->nVisibleLines = cvislines = 0;
00159     }
00160 
00161     SbVisible = bufsize > 0 && cvislines < hed->nLines;
00162     ShowScrollBar(hed->hWndSelf, SB_VERT, SbVisible);
00163 
00164     /* update scrollbar */
00165     si.cbSize = sizeof(SCROLLINFO);
00166     si.fMask = SIF_RANGE | SIF_PAGE;
00167     si.nMin = 0;
00168     si.nMax = ((bufsize > 0) ? hed->nLines - 1 : 0);
00169     si.nPage = ((hed->LineHeight > 0) ? rcClient.bottom / hed->LineHeight : 0);
00170     SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
00171 
00172     if(IsWindowVisible(hed->hWndSelf) && SbVisible != hed->SbVisible)
00173     {
00174         InvalidateRect(hed->hWndSelf, NULL, TRUE);
00175     }
00176 
00177     hed->SbVisible = SbVisible;
00178 }
00179 
00180 static HFONT
00181 HEXEDIT_GetFixedFont(VOID)
00182 {
00183     LOGFONT lf;
00184     GetObject(GetStockObject(ANSI_FIXED_FONT), sizeof(LOGFONT), &lf);
00185     return CreateFontIndirect(&lf);
00186 }
00187 
00188 static VOID
00189 HEXEDIT_PaintLines(PHEXEDIT_DATA hed, HDC hDC, DWORD ScrollPos, DWORD First, DWORD Last, RECT *rc)
00190 {
00191     DWORD dx, dy, linestart;
00192     INT i, isave, i0, i1, x;
00193     PBYTE buf, current, end, line;
00194     size_t bufsize;
00195     TCHAR hex[3], addr[17];
00196     RECT rct, rct2;
00197 
00198     FillRect(hDC, rc, (HBRUSH)(COLOR_WINDOW + 1));
00199     SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
00200 
00201     if (hed->SelStart < hed->SelEnd)
00202     {
00203         i0 = hed->SelStart;
00204         i1 = hed->SelEnd;
00205     }
00206     else
00207     {
00208         i0 = hed->SelEnd;
00209         i1 = hed->SelStart;
00210     }
00211 
00212     if(hed->hBuffer)
00213     {
00214         bufsize = LocalSize(hed->hBuffer);
00215         buf = LocalLock(hed->hBuffer);
00216     }
00217     else
00218     {
00219         buf = NULL;
00220         bufsize = 0;
00221 
00222         if(ScrollPos + First == 0)
00223         {
00224             /* draw address */
00225             wsprintf(addr, TEXT("%04X"), 0);
00226             TextOut(hDC, hed->LeftMargin, First * hed->LineHeight, addr, 4);
00227         }
00228     }
00229 
00230     if(buf)
00231     {
00232         end = buf + bufsize;
00233         dy = First * hed->LineHeight;
00234         linestart = (ScrollPos + First) * hed->ColumnsPerLine;
00235         i = linestart;
00236         current = buf + linestart;
00237         Last = min(hed->nLines - ScrollPos, Last);
00238 
00239         SetBkMode(hDC, TRANSPARENT);
00240         while(First <= Last && current < end)
00241         {
00242             DWORD dh;
00243 
00244             dx = hed->LeftMargin;
00245 
00246             /* draw address */
00247             wsprintf(addr, TEXT("%04lX"), linestart);
00248             TextOut(hDC, dx, dy, addr, 4);
00249 
00250             dx += ((4 + hed->AddressSpacing) * hed->CharWidth);
00251             dh = (3 * hed->CharWidth);
00252 
00253             rct.left = dx;
00254             rct.top = dy;
00255             rct.right = rct.left + dh;
00256             rct.bottom = dy + hed->LineHeight;
00257 
00258             /* draw hex map */
00259             dx += (hed->CharWidth / 2);
00260             line = current;
00261             isave = i;
00262             for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
00263             {
00264                 rct.left += dh;
00265                 rct.right += dh;
00266 
00267                 wsprintf(hex, TEXT("%02X"), *(current++));
00268                 if (i0 <= i && i < i1)
00269                 {
00270                     rct2.left = dx;
00271                     rct2.top = dy;
00272                     rct2.right = dx + hed->CharWidth * 2 + 1;
00273                     rct2.bottom = dy + hed->LineHeight;
00274                     InflateRect(&rct2, hed->CharWidth / 2, 0);
00275                     FillRect(hDC, &rct2, (HBRUSH)(COLOR_HIGHLIGHT + 1));
00276                     SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
00277                     ExtTextOut(hDC, dx, dy, 0, &rct, hex, 2, NULL);
00278                     SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
00279                 }
00280                 else
00281                     ExtTextOut(hDC, dx, dy, ETO_OPAQUE, &rct, hex, 2, NULL);
00282                 dx += dh;
00283                 i++;
00284             }
00285 
00286             /* draw ascii map */
00287             dx = ((4 + hed->AddressSpacing + hed->SplitSpacing + (hed->ColumnsPerLine * 3)) * hed->CharWidth);
00288             current = line;
00289             i = isave;
00290             for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
00291             {
00292                 wsprintf(hex, _T("%C"), *(current++));
00293                 hex[0] = ((hex[0] & _T('\x007f')) >= _T(' ') ? hex[0] : _T('.'));
00294                 if (i0 <= i && i < i1)
00295                 {
00296                     rct2.left = dx;
00297                     rct2.top = dy;
00298                     rct2.right = dx + hed->CharWidth;
00299                     rct2.bottom = dy + hed->LineHeight;
00300                     FillRect(hDC, &rct2, (HBRUSH)(COLOR_HIGHLIGHT + 1));
00301                     SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
00302                     TextOut(hDC, dx, dy, hex, 1);
00303                     SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
00304                 }
00305                 else
00306                     TextOut(hDC, dx, dy, hex, 1);
00307                 dx += hed->CharWidth;
00308                 i++;
00309             }
00310 
00311             dy += hed->LineHeight;
00312             linestart += hed->ColumnsPerLine;
00313             First++;
00314         }
00315     }
00316 
00317     LocalUnlock(hed->hBuffer);
00318 }
00319 
00320 static DWORD
00321 HEXEDIT_HitRegionTest(PHEXEDIT_DATA hed, POINTS pt)
00322 {
00323     int d;
00324 
00325     if(pt.x <= hed->LeftMargin)
00326     {
00327         return HEHT_LEFTMARGIN;
00328     }
00329 
00330     pt.x -= hed->LeftMargin;
00331     d = (4 * hed->CharWidth);
00332     if(pt.x <= d)
00333     {
00334         return HEHT_ADDRESS;
00335     }
00336 
00337     pt.x -= d;
00338     d = (hed->AddressSpacing * hed->CharWidth);
00339     if(pt.x <= d)
00340     {
00341         return HEHT_ADDRESSSPACING;
00342     }
00343 
00344     pt.x -= d;
00345     d = ((3 * hed->ColumnsPerLine + 1) * hed->CharWidth);
00346     if(pt.x <= d)
00347     {
00348         return HEHT_HEXDUMP;
00349     }
00350 
00351     pt.x -= d;
00352     d = ((hed->SplitSpacing - 1) * hed->CharWidth);
00353     if(pt.x <= d)
00354     {
00355         return HEHT_HEXDUMPSPACING;
00356     }
00357 
00358     pt.x -= d;
00359     d = (hed->ColumnsPerLine * hed->CharWidth);
00360     if(pt.x <= d)
00361     {
00362         return HEHT_ASCIIDUMP;
00363     }
00364 
00365     return HEHT_RIGHTMARGIN;
00366 }
00367 
00368 static DWORD
00369 HEXEDIT_IndexFromPoint(PHEXEDIT_DATA hed, POINTS pt, DWORD Hit, POINT *EditPos, BOOL *EditField)
00370 {
00371     SCROLLINFO si;
00372     DWORD Index, bufsize;
00373 
00374     si.cbSize = sizeof(SCROLLINFO);
00375     si.fMask = SIF_POS;
00376     GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
00377 
00378     EditPos->x = 0;
00379 
00380     if(hed->LineHeight > 0)
00381     {
00382         EditPos->y = min(si.nPos + (pt.y / hed->LineHeight), hed->nLines - 1);
00383     }
00384     else
00385     {
00386         EditPos->y = si.nPos;
00387     }
00388 
00389     switch(Hit)
00390     {
00391     case HEHT_LEFTMARGIN:
00392     case HEHT_ADDRESS:
00393     case HEHT_ADDRESSSPACING:
00394     case HEHT_HEXDUMP:
00395         pt.x -= (SHORT) hed->LeftMargin + ((4 + hed->AddressSpacing) * hed->CharWidth);
00396         *EditField = TRUE;
00397         break;
00398 
00399     default:
00400         pt.x -= hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine)) * hed->CharWidth);
00401         *EditField = FALSE;
00402         break;
00403     }
00404 
00405     if(pt.x > 0)
00406     {
00407         INT BlockWidth = (*EditField ? hed->CharWidth * 3 : hed->CharWidth);
00408         EditPos->x = min(hed->ColumnsPerLine, (pt.x + BlockWidth / 2) / BlockWidth);
00409     }
00410 
00411     bufsize = (hed->hBuffer ? (DWORD) LocalSize(hed->hBuffer) : 0);
00412     Index = (EditPos->y * hed->ColumnsPerLine) + EditPos->x;
00413     if(Index > bufsize)
00414     {
00415         INT tmp = bufsize % hed->ColumnsPerLine;
00416         Index = bufsize;
00417         EditPos->x = (tmp == 0 ? hed->ColumnsPerLine : tmp);
00418     }
00419     return Index;
00420 }
00421 
00422 static VOID
00423 HEXEDIT_Copy(PHEXEDIT_DATA hed)
00424 {
00425     PBYTE pb, buf;
00426     UINT cb;
00427     INT i0, i1;
00428     HGLOBAL hGlobal;
00429 
00430     if (hed->SelStart < hed->SelEnd)
00431     {
00432         i0 = hed->SelStart;
00433         i1 = hed->SelEnd;
00434     }
00435     else
00436     {
00437         i0 = hed->SelEnd;
00438         i1 = hed->SelStart;
00439     }
00440 
00441     cb = i1 - i0;
00442     if (cb == 0)
00443         return;
00444 
00445     hGlobal = GlobalAlloc(GHND | GMEM_SHARE, cb + sizeof(DWORD));
00446     if (hGlobal == NULL)
00447         return;
00448 
00449     pb = GlobalLock(hGlobal);
00450     if (pb)
00451     {
00452         *(PDWORD)pb = cb;
00453         pb += sizeof(DWORD);
00454         buf = (PBYTE) LocalLock(hed->hBuffer);
00455         if (buf)
00456         {
00457             CopyMemory(pb, buf + i0, cb);
00458             LocalUnlock(hed->hBuffer);
00459         }
00460         GlobalUnlock(hGlobal);
00461 
00462         if (OpenClipboard(hed->hWndSelf))
00463         {
00464             EmptyClipboard();
00465             SetClipboardData(ClipboardFormatID, hGlobal);
00466             CloseClipboard();
00467         }
00468     }
00469     else
00470         GlobalFree(hGlobal);
00471 }
00472 
00473 static VOID
00474 HEXEDIT_Delete(PHEXEDIT_DATA hed)
00475 {
00476     PBYTE buf;
00477     INT i0, i1;
00478     UINT bufsize;
00479 
00480     if (hed->SelStart < hed->SelEnd)
00481     {
00482         i0 = hed->SelStart;
00483         i1 = hed->SelEnd;
00484     }
00485     else
00486     {
00487         i0 = hed->SelEnd;
00488         i1 = hed->SelStart;
00489     }
00490 
00491     if (i0 != i1)
00492     {
00493         bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
00494         buf = (PBYTE) LocalLock(hed->hBuffer);
00495         if (buf)
00496         {
00497             MoveMemory(buf + i0, buf + i1, bufsize - i1);
00498             LocalUnlock(hed->hBuffer);
00499         }
00500         HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
00501         hed->InMid = FALSE;
00502         hed->Index = hed->SelStart = hed->SelEnd = i0;
00503         hed->CaretCol = hed->Index % hed->ColumnsPerLine;
00504         hed->CaretLine = hed->Index / hed->ColumnsPerLine;
00505         InvalidateRect(hed->hWndSelf, NULL, TRUE);
00506         HEXEDIT_MoveCaret(hed, TRUE);
00507     }
00508 }
00509 
00510 static VOID
00511 HEXEDIT_Paste(PHEXEDIT_DATA hed)
00512 {
00513     HGLOBAL hGlobal;
00514     UINT bufsize;
00515     PBYTE pb, buf;
00516     DWORD cb;
00517 
00518     HEXEDIT_Delete(hed);
00519     bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
00520 
00521     if (OpenClipboard(hed->hWndSelf))
00522     {
00523         hGlobal = GetClipboardData(ClipboardFormatID);
00524         if (hGlobal != NULL)
00525         {
00526             pb = (PBYTE) GlobalLock(hGlobal);
00527             cb = *(PDWORD) pb;
00528             pb += sizeof(DWORD);
00529             HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize + cb);
00530             buf = (PBYTE) LocalLock(hed->hBuffer);
00531             if (buf)
00532             {
00533                 MoveMemory(buf + hed->Index + cb, buf + hed->Index,
00534                            bufsize - hed->Index);
00535                 CopyMemory(buf + hed->Index, pb, cb);
00536                 LocalUnlock(hed->hBuffer);
00537             }
00538             GlobalUnlock(hGlobal);
00539         }
00540         CloseClipboard();
00541     }
00542     InvalidateRect(hed->hWndSelf, NULL, TRUE);
00543     HEXEDIT_MoveCaret(hed, TRUE);
00544 }
00545 
00546 static VOID
00547 HEXEDIT_Cut(PHEXEDIT_DATA hed)
00548 {
00549     HEXEDIT_Copy(hed);
00550     HEXEDIT_Delete(hed);
00551 }
00552 
00553 static VOID
00554 HEXEDIT_SelectAll(PHEXEDIT_DATA hed)
00555 {
00556     INT bufsize;
00557 
00558     bufsize = (hed->hBuffer ? (INT) LocalSize(hed->hBuffer) : 0);
00559     hed->Index = hed->SelStart = 0;
00560     hed->SelEnd = bufsize;
00561     InvalidateRect(hed->hWndSelf, NULL, TRUE);
00562     HEXEDIT_MoveCaret(hed, TRUE);
00563 }
00564 
00565 /*** Control specific messages ************************************************/
00566 
00567 static LRESULT
00568 HEXEDIT_HEM_LOADBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size)
00569 {
00570     if(Buffer != NULL && Size > 0)
00571     {
00572         LPVOID buf;
00573 
00574         if(hed->MaxBuffer > 0 && Size > hed->MaxBuffer)
00575         {
00576             Size = hed->MaxBuffer;
00577         }
00578 
00579         if(hed->hBuffer)
00580         {
00581             if(Size > 0)
00582             {
00583                 if(LocalSize(hed->hBuffer) != Size)
00584                 {
00585                     hed->hBuffer = LocalReAlloc(hed->hBuffer, Size, LMEM_MOVEABLE | LMEM_ZEROINIT);
00586                 }
00587             }
00588             else
00589             {
00590                 hed->hBuffer = LocalFree(hed->hBuffer);
00591                 hed->Index = 0;
00592                 HEXEDIT_Update(hed);
00593 
00594                 return 0;
00595             }
00596         }
00597         else if(Size > 0)
00598         {
00599             hed->hBuffer = LocalAlloc(LHND, Size);
00600         }
00601 
00602         if(Size > 0)
00603         {
00604             buf = LocalLock(hed->hBuffer);
00605             if(buf)
00606             {
00607                 memcpy(buf, Buffer, Size);
00608             }
00609             else
00610                 Size = 0;
00611             LocalUnlock(hed->hBuffer);
00612         }
00613 
00614         hed->Index = 0;
00615         HEXEDIT_Update(hed);
00616         return Size;
00617     }
00618     else if(hed->hBuffer)
00619     {
00620         hed->Index = 0;
00621         hed->hBuffer = LocalFree(hed->hBuffer);
00622         HEXEDIT_Update(hed);
00623     }
00624 
00625     return 0;
00626 }
00627 
00628 static LRESULT
00629 HEXEDIT_HEM_COPYBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size)
00630 {
00631     size_t nCpy;
00632 
00633     if(!hed->hBuffer)
00634     {
00635         return 0;
00636     }
00637 
00638     if(Buffer != NULL && Size > 0)
00639     {
00640         nCpy = min(Size, LocalSize(hed->hBuffer));
00641         if(nCpy > 0)
00642         {
00643             PVOID buf;
00644 
00645             buf = LocalLock(hed->hBuffer);
00646             if(buf)
00647             {
00648                 memcpy(Buffer, buf, nCpy);
00649             }
00650             else
00651                 nCpy = 0;
00652             LocalUnlock(hed->hBuffer);
00653         }
00654         return nCpy;
00655     }
00656 
00657     return (LRESULT)LocalSize(hed->hBuffer);
00658 }
00659 
00660 static LRESULT
00661 HEXEDIT_HEM_SETMAXBUFFERSIZE(PHEXEDIT_DATA hed, DWORD nMaxSize)
00662 {
00663     hed->MaxBuffer = nMaxSize;
00664     if (hed->MaxBuffer == 0)
00665     {
00666         hed->hBuffer = LocalFree(hed->hBuffer);
00667         return 0;
00668     }
00669     if (hed->hBuffer)
00670         hed->hBuffer = LocalReAlloc(hed->hBuffer, hed->MaxBuffer, LMEM_MOVEABLE);
00671     else
00672         hed->hBuffer = LocalAlloc(LMEM_MOVEABLE, hed->MaxBuffer);
00673     HEXEDIT_Update(hed);
00674     return 0;
00675 }
00676 
00677 /*** Message Proc *************************************************************/
00678 
00679 static LRESULT
00680 HEXEDIT_WM_NCCREATE(HWND hWnd, CREATESTRUCT *cs)
00681 {
00682     PHEXEDIT_DATA hed;
00683 
00684     if(!(hed = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEXEDIT_DATA))))
00685     {
00686         return FALSE;
00687     }
00688 
00689     hed->hWndSelf = hWnd;
00690     hed->hWndParent = cs->hwndParent;
00691     hed->style = cs->style;
00692 
00693     hed->ColumnsPerLine = 8;
00694     hed->LeftMargin = 2;
00695     hed->AddressSpacing = 2;
00696     hed->SplitSpacing = 2;
00697     hed->EditingField = TRUE; /* in hexdump field */
00698 
00699     SetWindowLongPtr(hWnd, 0, (DWORD_PTR)hed);
00700     HEXEDIT_Update(hed);
00701 
00702     return TRUE;
00703 }
00704 
00705 static LRESULT
00706 HEXEDIT_WM_NCDESTROY(PHEXEDIT_DATA hed)
00707 {
00708     if(hed->hBuffer)
00709     {
00710         //while(LocalUnlock(hed->hBuffer));
00711         LocalFree(hed->hBuffer);
00712     }
00713 
00714     if(hed->hFont)
00715     {
00716         DeleteObject(hed->hFont);
00717     }
00718 
00719     SetWindowLongPtr(hed->hWndSelf, 0, (DWORD_PTR)0);
00720     HeapFree(GetProcessHeap(), 0, hed);
00721 
00722     return 0;
00723 }
00724 
00725 static LRESULT
00726 HEXEDIT_WM_CREATE(PHEXEDIT_DATA hed)
00727 {
00728     UNREFERENCED_PARAMETER(hed);
00729     return 1;
00730 }
00731 
00732 static LRESULT
00733 HEXEDIT_WM_SETFOCUS(PHEXEDIT_DATA hed)
00734 {
00735     CreateCaret(hed->hWndSelf, 0, 1, hed->LineHeight);
00736     HEXEDIT_MoveCaret(hed, FALSE);
00737     ShowCaret(hed->hWndSelf);
00738     return 0;
00739 }
00740 
00741 static LRESULT
00742 HEXEDIT_WM_KILLFOCUS(PHEXEDIT_DATA hed)
00743 {
00744     UNREFERENCED_PARAMETER(hed);
00745     DestroyCaret();
00746     return 0;
00747 }
00748 
00749 static LRESULT
00750 HEXEDIT_WM_VSCROLL(PHEXEDIT_DATA hed, WORD ThumbPosition, WORD SbCmd)
00751 {
00752     int ScrollY;
00753     SCROLLINFO si;
00754 
00755     UNREFERENCED_PARAMETER(ThumbPosition);
00756 
00757     ZeroMemory(&si, sizeof(SCROLLINFO));
00758     si.cbSize = sizeof(SCROLLINFO);
00759     si.fMask = SIF_ALL;
00760     GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
00761 
00762     ScrollY = si.nPos;
00763     switch(SbCmd)
00764     {
00765     case SB_TOP:
00766         si.nPos = si.nMin;
00767         break;
00768 
00769     case SB_BOTTOM:
00770         si.nPos = si.nMax;
00771         break;
00772 
00773     case SB_LINEUP:
00774         si.nPos--;
00775         break;
00776 
00777     case SB_LINEDOWN:
00778         si.nPos++;
00779         break;
00780 
00781     case SB_PAGEUP:
00782         si.nPos -= si.nPage;
00783         break;
00784 
00785     case SB_PAGEDOWN:
00786         si.nPos += si.nPage;
00787         break;
00788 
00789     case SB_THUMBTRACK:
00790         si.nPos = si.nTrackPos;
00791         break;
00792     }
00793 
00794     si.fMask = SIF_POS;
00795     SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
00796     GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
00797 
00798     if(si.nPos != ScrollY)
00799     {
00800         ScrollWindow(hed->hWndSelf, 0, (ScrollY - si.nPos) * hed->LineHeight, NULL, NULL);
00801         UpdateWindow(hed->hWndSelf);
00802     }
00803 
00804     return 0;
00805 }
00806 
00807 static LRESULT
00808 HEXEDIT_WM_SETFONT(PHEXEDIT_DATA hed, HFONT hFont, BOOL bRedraw)
00809 {
00810     HDC hDC;
00811     TEXTMETRIC tm;
00812     HFONT hOldFont = 0;
00813 
00814     if(hFont == 0)
00815     {
00816         hFont = HEXEDIT_GetFixedFont();
00817     }
00818 
00819     hed->hFont = hFont;
00820     hDC = GetDC(hed->hWndSelf);
00821     if(hFont)
00822     {
00823         hOldFont = SelectObject(hDC, hFont);
00824     }
00825     GetTextMetrics(hDC, &tm);
00826     hed->LineHeight = tm.tmHeight;
00827     hed->CharWidth = tm.tmAveCharWidth;
00828     if(hOldFont)
00829     {
00830         SelectObject(hDC, hOldFont);
00831     }
00832     ReleaseDC(hed->hWndSelf, hDC);
00833 
00834     if(bRedraw)
00835     {
00836         InvalidateRect(hed->hWndSelf, NULL, TRUE);
00837     }
00838 
00839     return 0;
00840 }
00841 
00842 static LRESULT
00843 HEXEDIT_WM_GETFONT(PHEXEDIT_DATA hed)
00844 {
00845     return (LRESULT)hed->hFont;
00846 }
00847 
00848 static LRESULT
00849 HEXEDIT_WM_PAINT(PHEXEDIT_DATA hed)
00850 {
00851     PAINTSTRUCT ps;
00852     SCROLLINFO si;
00853     RECT rc;
00854     HBITMAP hbmp, hbmpold;
00855     INT nLines, nFirst;
00856     HFONT hOldFont;
00857     HDC hTempDC;
00858     DWORD height;
00859 
00860     if(GetUpdateRect(hed->hWndSelf, &rc, FALSE) && (hed->LineHeight > 0))
00861     {
00862         ZeroMemory(&si, sizeof(SCROLLINFO));
00863         si.cbSize = sizeof(SCROLLINFO);
00864         si.fMask = SIF_POS;
00865         GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
00866 
00867         height = (rc.bottom - rc.top);
00868         nLines = height / hed->LineHeight;
00869         if((height % hed->LineHeight) > 0)
00870         {
00871             nLines++;
00872         }
00873         if(nLines > hed->nLines - si.nPos)
00874         {
00875             nLines = hed->nLines - si.nPos;
00876         }
00877         nFirst = rc.top / hed->LineHeight;
00878 
00879         BeginPaint(hed->hWndSelf, &ps);
00880         if(!(hTempDC = CreateCompatibleDC(ps.hdc)))
00881         {
00882             FillRect(ps.hdc, &rc, (HBRUSH)(COLOR_WINDOW + 1));
00883             goto epaint;
00884         }
00885         if(!(hbmp = CreateCompatibleBitmap(ps.hdc, ps.rcPaint.right, ps.rcPaint.bottom)))
00886         {
00887             FillRect(ps.hdc, &rc, (HBRUSH)(COLOR_WINDOW + 1));
00888             DeleteDC(hTempDC);
00889             goto epaint;
00890         }
00891         hbmpold = SelectObject(hTempDC, hbmp);
00892         hOldFont = SelectObject(hTempDC, hed->hFont);
00893         HEXEDIT_PaintLines(hed, hTempDC, si.nPos, nFirst, nFirst + nLines, &ps.rcPaint);
00894         BitBlt(ps.hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hTempDC, rc.left, rc.top, SRCCOPY);
00895         SelectObject(hTempDC, hOldFont);
00896         SelectObject(hTempDC, hbmpold);
00897 
00898         DeleteObject(hbmp);
00899         DeleteDC(hTempDC);
00900 
00901 epaint:
00902         EndPaint(hed->hWndSelf, &ps);
00903     }
00904 
00905     return 0;
00906 }
00907 
00908 static LRESULT
00909 HEXEDIT_WM_MOUSEWHEEL(PHEXEDIT_DATA hed, int cyMoveLines, WORD ButtonsDown, LPPOINTS MousePos)
00910 {
00911     SCROLLINFO si;
00912     int ScrollY;
00913 
00914     UNREFERENCED_PARAMETER(ButtonsDown);
00915     UNREFERENCED_PARAMETER(MousePos);
00916 
00917     SetFocus(hed->hWndSelf);
00918 
00919     si.cbSize = sizeof(SCROLLINFO);
00920     si.fMask = SIF_ALL;
00921     GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
00922 
00923     ScrollY = si.nPos;
00924 
00925     si.fMask = SIF_POS;
00926     si.nPos += cyMoveLines;
00927     SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
00928 
00929     GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
00930     if(si.nPos != ScrollY)
00931     {
00932         ScrollWindow(hed->hWndSelf, 0, (ScrollY - si.nPos) * hed->LineHeight, NULL, NULL);
00933         UpdateWindow(hed->hWndSelf);
00934     }
00935 
00936     return 0;
00937 }
00938 
00939 static LRESULT
00940 HEXEDIT_WM_GETDLGCODE(LPMSG Msg)
00941 {
00942     UNREFERENCED_PARAMETER(Msg);
00943     return DLGC_WANTARROWS | DLGC_WANTCHARS;
00944 }
00945 
00946 static LRESULT
00947 HEXEDIT_WM_LBUTTONDOWN(PHEXEDIT_DATA hed, INT Buttons, POINTS Pt)
00948 {
00949     BOOL NewField;
00950     POINT EditPos;
00951     DWORD Hit;
00952 
00953     UNREFERENCED_PARAMETER(Buttons);
00954     SetFocus(hed->hWndSelf);
00955 
00956     if (GetAsyncKeyState(VK_SHIFT) < 0)
00957     {
00958         if (hed->EditingField)
00959             hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField);
00960         else
00961             hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField);
00962         hed->SelEnd = hed->Index;
00963     }
00964     else
00965     {
00966         Hit = HEXEDIT_HitRegionTest(hed, Pt);
00967         hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, Hit, &EditPos, &NewField);
00968         hed->SelStart = hed->SelEnd = hed->Index;
00969         hed->EditingField = NewField;
00970         SetCapture(hed->hWndSelf);
00971     }
00972     hed->CaretCol = EditPos.x;
00973     hed->CaretLine = EditPos.y;
00974     hed->InMid = FALSE;
00975     InvalidateRect(hed->hWndSelf, NULL, FALSE);
00976     HEXEDIT_MoveCaret(hed, TRUE);
00977 
00978     return 0;
00979 }
00980 
00981 static LRESULT
00982 HEXEDIT_WM_LBUTTONUP(PHEXEDIT_DATA hed, INT Buttons, POINTS Pt)
00983 {
00984     BOOL NewField;
00985     POINT EditPos;
00986     if (GetCapture() == hed->hWndSelf)
00987     {
00988         if (hed->EditingField)
00989             hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField);
00990         else
00991             hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField);
00992         hed->CaretCol = EditPos.x;
00993         hed->CaretLine = EditPos.y;
00994         hed->SelEnd = hed->Index;
00995         ReleaseCapture();
00996         InvalidateRect(hed->hWndSelf, NULL, FALSE);
00997         HEXEDIT_MoveCaret(hed, TRUE);
00998     }
00999     return 0;
01000 }
01001 
01002 static LRESULT
01003 HEXEDIT_WM_MOUSEMOVE(PHEXEDIT_DATA hed, INT Buttons, POINTS Pt)
01004 {
01005     BOOL NewField;
01006     POINT EditPos;
01007     if (GetCapture() == hed->hWndSelf)
01008     {
01009         if (hed->EditingField)
01010             hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField);
01011         else
01012             hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField);
01013         hed->CaretCol = EditPos.x;
01014         hed->CaretLine = EditPos.y;
01015         hed->SelEnd = hed->Index;
01016         InvalidateRect(hed->hWndSelf, NULL, FALSE);
01017         HEXEDIT_MoveCaret(hed, TRUE);
01018     }
01019     return 0;
01020 }
01021 
01022 static BOOL
01023 HEXEDIT_WM_KEYDOWN(PHEXEDIT_DATA hed, INT VkCode)
01024 {
01025     size_t bufsize;
01026     PBYTE buf;
01027     INT i0, i1;
01028 
01029     if(GetKeyState(VK_MENU) & 0x8000)
01030     {
01031         return FALSE;
01032     }
01033 
01034     bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
01035 
01036     if (hed->SelStart < hed->SelEnd)
01037     {
01038         i0 = hed->SelStart;
01039         i1 = hed->SelEnd;
01040     }
01041     else
01042     {
01043         i0 = hed->SelEnd;
01044         i1 = hed->SelStart;
01045     }
01046 
01047     switch(VkCode)
01048     {
01049     case 'X':
01050         if (GetAsyncKeyState(VK_SHIFT) >= 0 &&
01051                 GetAsyncKeyState(VK_CONTROL) < 0 && hed->SelStart != hed->SelEnd)
01052             HEXEDIT_Cut(hed);
01053         else
01054             return TRUE;
01055         break;
01056 
01057     case 'C':
01058         if (GetAsyncKeyState(VK_SHIFT) >= 0 &&
01059                 GetAsyncKeyState(VK_CONTROL) < 0 && hed->SelStart != hed->SelEnd)
01060             HEXEDIT_Copy(hed);
01061         else
01062             return TRUE;
01063         break;
01064 
01065     case 'V':
01066         if (GetAsyncKeyState(VK_SHIFT) >= 0 && GetAsyncKeyState(VK_CONTROL) < 0)
01067             HEXEDIT_Paste(hed);
01068         else
01069             return TRUE;
01070         break;
01071 
01072     case 'A':
01073         if (GetAsyncKeyState(VK_SHIFT) >= 0 && GetAsyncKeyState(VK_CONTROL) < 0)
01074             HEXEDIT_SelectAll(hed);
01075         else
01076             return TRUE;
01077         break;
01078 
01079     case VK_INSERT:
01080         if (hed->SelStart != hed->SelEnd)
01081         {
01082             if (GetAsyncKeyState(VK_SHIFT) >= 0 && GetAsyncKeyState(VK_CONTROL) < 0)
01083                 HEXEDIT_Copy(hed);
01084         }
01085         if (GetAsyncKeyState(VK_SHIFT) < 0 && GetAsyncKeyState(VK_CONTROL) >= 0)
01086             HEXEDIT_Paste(hed);
01087         break;
01088 
01089     case VK_DELETE:
01090         if (GetAsyncKeyState(VK_SHIFT) < 0 && GetAsyncKeyState(VK_CONTROL) >= 0 &&
01091                 hed->SelStart != hed->SelEnd)
01092             HEXEDIT_Copy(hed);
01093         if (i0 != i1)
01094         {
01095             buf = (PBYTE) LocalLock(hed->hBuffer);
01096             if (buf)
01097             {
01098                 MoveMemory(buf + i0, buf + i1, bufsize - i1);
01099                 LocalUnlock(hed->hBuffer);
01100             }
01101             HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
01102             hed->InMid = FALSE;
01103             hed->Index = hed->SelStart = hed->SelEnd = i0;
01104             hed->CaretCol = hed->Index % hed->ColumnsPerLine;
01105             hed->CaretLine = hed->Index / hed->ColumnsPerLine;
01106         }
01107         else
01108         {
01109             if (hed->InMid && hed->EditingField)
01110             {
01111                 buf = (PBYTE) LocalLock(hed->hBuffer);
01112                 if (buf)
01113                 {
01114                     MoveMemory(buf + hed->Index, buf + hed->Index + 1,
01115                                bufsize - hed->Index - 1);
01116                     LocalUnlock(hed->hBuffer);
01117                 }
01118                 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1);
01119                 hed->InMid = FALSE;
01120             }
01121             else if (hed->Index < bufsize)
01122             {
01123                 buf = (PBYTE) LocalLock(hed->hBuffer);
01124                 if (buf)
01125                 {
01126                     MoveMemory(buf + hed->Index, buf + hed->Index + 1,
01127                                bufsize - hed->Index - 1);
01128                     LocalUnlock(hed->hBuffer);
01129                 }
01130                 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1);
01131             }
01132         }
01133         InvalidateRect(hed->hWndSelf, NULL, TRUE);
01134         HEXEDIT_MoveCaret(hed, TRUE);
01135         break;
01136 
01137     case VK_BACK:
01138         if (i0 != i1)
01139         {
01140             buf = (PBYTE) LocalLock(hed->hBuffer);
01141             if (buf)
01142             {
01143                 MoveMemory(buf + i0, buf + i1, bufsize - i1);
01144                 LocalUnlock(hed->hBuffer);
01145             }
01146             HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
01147             hed->InMid = FALSE;
01148             hed->Index = hed->SelStart = hed->SelEnd = i0;
01149             hed->CaretCol = hed->Index % hed->ColumnsPerLine;
01150             hed->CaretLine = hed->Index / hed->ColumnsPerLine;
01151         }
01152         else
01153         {
01154             if (hed->InMid && hed->EditingField)
01155             {
01156                 buf = (PBYTE) LocalLock(hed->hBuffer);
01157                 if (buf)
01158                 {
01159                     MoveMemory(buf + hed->Index, buf + hed->Index + 1,
01160                                bufsize - hed->Index - 1);
01161                     LocalUnlock(hed->hBuffer);
01162                 }
01163             }
01164             else if (hed->Index > 0)
01165             {
01166                 buf = (PBYTE) LocalLock(hed->hBuffer);
01167                 if (buf)
01168                 {
01169                     MoveMemory(buf + hed->Index - 1, buf + hed->Index,
01170                                bufsize - hed->Index);
01171                     LocalUnlock(hed->hBuffer);
01172                 }
01173                 hed->Index--;
01174                 hed->SelStart = hed->SelEnd = hed->Index;
01175                 hed->CaretCol = hed->Index % hed->ColumnsPerLine;
01176                 hed->CaretLine = hed->Index / hed->ColumnsPerLine;
01177             }
01178             else
01179                 return TRUE;
01180             HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1);
01181             hed->InMid = FALSE;
01182         }
01183         InvalidateRect(hed->hWndSelf, NULL, TRUE);
01184         HEXEDIT_MoveCaret(hed, TRUE);
01185         break;
01186 
01187     case VK_LEFT:
01188         if (hed->Index > 0)
01189         {
01190             hed->Index--;
01191             if (GetAsyncKeyState(VK_SHIFT) < 0)
01192                 hed->SelEnd = hed->Index;
01193             else
01194                 hed->SelStart = hed->SelEnd = hed->Index;
01195             hed->CaretCol = hed->Index % hed->ColumnsPerLine;
01196             hed->CaretLine = hed->Index / hed->ColumnsPerLine;
01197             hed->InMid = FALSE;
01198             InvalidateRect(hed->hWndSelf, NULL, TRUE);
01199             HEXEDIT_MoveCaret(hed, TRUE);
01200         }
01201         break;
01202 
01203     case VK_RIGHT:
01204         if (hed->Index < (INT)bufsize)
01205         {
01206             hed->Index++;
01207             if (GetAsyncKeyState(VK_SHIFT) < 0)
01208                 hed->SelEnd = hed->Index;
01209             else
01210                 hed->SelStart = hed->SelEnd = hed->Index;
01211             hed->CaretCol = hed->Index % hed->ColumnsPerLine;
01212             hed->CaretLine = hed->Index / hed->ColumnsPerLine;
01213             hed->InMid = FALSE;
01214             InvalidateRect(hed->hWndSelf, NULL, TRUE);
01215             HEXEDIT_MoveCaret(hed, TRUE);
01216         }
01217         break;
01218 
01219     case VK_UP:
01220         if (hed->Index >= hed->ColumnsPerLine)
01221         {
01222             hed->Index -= hed->ColumnsPerLine;
01223             if (GetAsyncKeyState(VK_SHIFT) < 0)
01224                 hed->SelEnd = hed->Index;
01225             else
01226                 hed->SelStart = hed->SelEnd = hed->Index;
01227             hed->CaretCol = hed->Index % hed->ColumnsPerLine;
01228             hed->CaretLine = hed->Index / hed->ColumnsPerLine;
01229             hed->InMid = FALSE;
01230             InvalidateRect(hed->hWndSelf, NULL, TRUE);
01231             HEXEDIT_MoveCaret(hed, TRUE);
01232         }
01233         break;
01234 
01235     case VK_DOWN:
01236         if (hed->Index + hed->ColumnsPerLine <= (INT) bufsize)
01237             hed->Index += hed->ColumnsPerLine;
01238         else
01239             hed->Index = bufsize;
01240         hed->CaretCol = hed->Index % hed->ColumnsPerLine;
01241         hed->CaretLine = hed->Index / hed->ColumnsPerLine;
01242         if (GetAsyncKeyState(VK_SHIFT) < 0)
01243             hed->SelEnd = hed->Index;
01244         else
01245             hed->SelStart = hed->SelEnd = hed->Index;
01246         hed->InMid = FALSE;
01247         InvalidateRect(hed->hWndSelf, NULL, TRUE);
01248         HEXEDIT_MoveCaret(hed, TRUE);
01249         break;
01250 
01251     default:
01252         return TRUE;
01253     }
01254 
01255     return FALSE;
01256 }
01257 
01258 static BOOL
01259 HEXEDIT_WM_CHAR(PHEXEDIT_DATA hed, WCHAR ch)
01260 {
01261     size_t bufsize;
01262     PBYTE buf;
01263     INT i0, i1;
01264 
01265     bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
01266     if (hed->SelStart < hed->SelEnd)
01267     {
01268         i0 = hed->SelStart;
01269         i1 = hed->SelEnd;
01270     }
01271     else
01272     {
01273         i0 = hed->SelEnd;
01274         i1 = hed->SelStart;
01275     }
01276     if (!hed->EditingField)
01277     {
01278         if (0x20 <= ch && ch <= 0xFF)
01279         {
01280             if (hed->SelStart != hed->SelEnd)
01281             {
01282                 buf = (PBYTE) LocalLock(hed->hBuffer);
01283                 if (buf)
01284                 {
01285                     MoveMemory(buf + i0, buf + i1, bufsize - i1);
01286                     LocalUnlock(hed->hBuffer);
01287                 }
01288                 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
01289                 hed->InMid = FALSE;
01290                 bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
01291                 hed->Index = hed->SelStart = hed->SelEnd = i0;
01292             }
01293             HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize + 1);
01294             buf = (PBYTE) LocalLock(hed->hBuffer);
01295             if (buf)
01296             {
01297                 MoveMemory(buf + hed->Index + 1, buf + hed->Index,
01298                            bufsize - hed->Index);
01299                 buf[hed->Index] = ch;
01300                 LocalUnlock(hed->hBuffer);
01301             }
01302             hed->Index++;
01303             hed->CaretCol = hed->Index % hed->ColumnsPerLine;
01304             hed->CaretLine = hed->Index / hed->ColumnsPerLine;
01305             InvalidateRect(hed->hWndSelf, NULL, TRUE);
01306             HEXEDIT_MoveCaret(hed, TRUE);
01307             return FALSE;
01308         }
01309     }
01310     else
01311     {
01312         if (('0' <= ch && ch <= '9') || ('A' <= ch && ch <= 'F') ||
01313                 ('a' <= ch && ch <= 'f'))
01314         {
01315             if (hed->SelStart != hed->SelEnd)
01316             {
01317                 buf = (PBYTE) LocalLock(hed->hBuffer);
01318                 if (buf)
01319                 {
01320                     MoveMemory(buf + i0, buf + i1, bufsize - i1);
01321                     LocalUnlock(hed->hBuffer);
01322                 }
01323                 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
01324                 hed->InMid = FALSE;
01325                 bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
01326                 hed->Index = hed->SelStart = hed->SelEnd = i0;
01327             }
01328             if (hed->InMid)
01329             {
01330                 buf = (PBYTE) LocalLock(hed->hBuffer);
01331                 if (buf)
01332                 {
01333                     if ('0' <= ch && ch <= '9')
01334                         buf[hed->Index] |= ch - '0';
01335                     else if ('A' <= ch && ch <= 'F')
01336                         buf[hed->Index] |= ch + 10 - 'A';
01337                     else if ('a' <= ch && ch <= 'f')
01338                         buf[hed->Index] |= ch + 10 - 'a';
01339                     LocalUnlock(hed->hBuffer);
01340                 }
01341                 hed->InMid = FALSE;
01342                 hed->Index++;
01343             }
01344             else
01345             {
01346                 HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize + 1);
01347                 buf = (PBYTE) LocalLock(hed->hBuffer);
01348                 if (buf)
01349                 {
01350                     MoveMemory(buf + hed->Index + 1, buf + hed->Index,
01351                                bufsize - hed->Index);
01352                     if ('0' <= ch && ch <= '9')
01353                         buf[hed->Index] = (ch - '0') << 4;
01354                     else if ('A' <= ch && ch <= 'F')
01355                         buf[hed->Index] = (ch + 10 - 'A') << 4;
01356                     else if ('a' <= ch && ch <= 'f')
01357                         buf[hed->Index] = (ch + 10 - 'a') << 4;
01358                     LocalUnlock(hed->hBuffer);
01359                 }
01360                 hed->InMid = TRUE;
01361             }
01362             hed->CaretCol = hed->Index % hed->ColumnsPerLine;
01363             hed->CaretLine = hed->Index / hed->ColumnsPerLine;
01364             InvalidateRect(hed->hWndSelf, NULL, TRUE);
01365             HEXEDIT_MoveCaret(hed, TRUE);
01366             return FALSE;
01367         }
01368     }
01369     return TRUE;
01370 }
01371 
01372 static LRESULT
01373 HEXEDIT_WM_SIZE(PHEXEDIT_DATA hed, DWORD sType, WORD NewWidth, WORD NewHeight)
01374 {
01375     UNREFERENCED_PARAMETER(sType);
01376     UNREFERENCED_PARAMETER(NewHeight);
01377     UNREFERENCED_PARAMETER(NewWidth);
01378     HEXEDIT_Update(hed);
01379     return 0;
01380 }
01381 
01382 static VOID
01383 HEXEDIT_WM_CONTEXTMENU(PHEXEDIT_DATA hed, INT x, INT y)
01384 {
01385     HMENU hMenu;
01386     RECT rc;
01387 
01388     if (x == -1 && y == -1)
01389     {
01390         GetWindowRect(hed->hWndSelf, &rc);
01391         x = rc.left;
01392         y = rc.top;
01393     }
01394 
01395     hMenu = GetSubMenu(hPopupMenus, PM_HEXEDIT);
01396     if (hed->SelStart == hed->SelEnd)
01397     {
01398         EnableMenuItem(hMenu, ID_HEXEDIT_CUT, MF_GRAYED);
01399         EnableMenuItem(hMenu, ID_HEXEDIT_COPY, MF_GRAYED);
01400         EnableMenuItem(hMenu, ID_HEXEDIT_PASTE, MF_GRAYED);
01401         EnableMenuItem(hMenu, ID_HEXEDIT_DELETE, MF_GRAYED);
01402     }
01403     else
01404     {
01405         EnableMenuItem(hMenu, ID_HEXEDIT_CUT, MF_ENABLED);
01406         EnableMenuItem(hMenu, ID_HEXEDIT_COPY, MF_ENABLED);
01407         EnableMenuItem(hMenu, ID_HEXEDIT_PASTE, MF_ENABLED);
01408         EnableMenuItem(hMenu, ID_HEXEDIT_DELETE, MF_ENABLED);
01409     }
01410 
01411     SetForegroundWindow(hed->hWndSelf);
01412     TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, x, y, 0, hed->hWndSelf, NULL);
01413     PostMessage(hed->hWndSelf, WM_NULL, 0, 0);
01414 }
01415 
01416 INT_PTR CALLBACK
01417 HexEditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
01418 {
01419     PHEXEDIT_DATA hed;
01420     POINTS p;
01421 
01422     hed = (PHEXEDIT_DATA)(LONG_PTR)GetWindowLongPtr(hWnd, (DWORD_PTR)0);
01423     switch(uMsg)
01424     {
01425     case WM_ERASEBKGND:
01426         return TRUE;
01427 
01428     case WM_PAINT:
01429         return HEXEDIT_WM_PAINT(hed);
01430 
01431     case WM_KEYDOWN:
01432         return HEXEDIT_WM_KEYDOWN(hed, (INT)wParam);
01433 
01434     case WM_CHAR:
01435         return HEXEDIT_WM_CHAR(hed, (WCHAR)wParam);
01436 
01437     case WM_VSCROLL:
01438         return HEXEDIT_WM_VSCROLL(hed, HIWORD(wParam), LOWORD(wParam));
01439 
01440     case WM_SIZE:
01441         return HEXEDIT_WM_SIZE(hed, (DWORD)wParam, LOWORD(lParam), HIWORD(lParam));
01442 
01443     case WM_LBUTTONDOWN:
01444     {
01445         p.x = LOWORD(lParam);
01446         p.y = HIWORD(lParam);
01447         return HEXEDIT_WM_LBUTTONDOWN(hed, (INT)wParam, p);
01448     }
01449 
01450     case WM_LBUTTONUP:
01451     {
01452         p.x = LOWORD(lParam);
01453         p.y = HIWORD(lParam);
01454         return HEXEDIT_WM_LBUTTONUP(hed, (INT)wParam, p);
01455     }
01456 
01457     case WM_MOUSEMOVE:
01458     {
01459         p.x = LOWORD(lParam);
01460         p.y = HIWORD(lParam);
01461         return HEXEDIT_WM_MOUSEMOVE(hed, (INT)wParam, p);
01462     }
01463 
01464     case WM_MOUSEWHEEL:
01465     {
01466         UINT nScrollLines = 3;
01467         int delta = 0;
01468 
01469         SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &nScrollLines, 0);
01470         delta -= (SHORT)HIWORD(wParam);
01471         if(abs(delta) >= WHEEL_DELTA && nScrollLines != 0)
01472         {
01473             p.x = LOWORD(lParam);
01474             p.y = HIWORD(lParam);
01475             return HEXEDIT_WM_MOUSEWHEEL(hed, nScrollLines * (delta / WHEEL_DELTA), LOWORD(wParam), &p);
01476         }
01477         break;
01478     }
01479 
01480     case HEM_LOADBUFFER:
01481         return HEXEDIT_HEM_LOADBUFFER(hed, (PVOID)wParam, (DWORD)lParam);
01482 
01483     case HEM_COPYBUFFER:
01484         return HEXEDIT_HEM_COPYBUFFER(hed, (PVOID)wParam, (DWORD)lParam);
01485 
01486     case HEM_SETMAXBUFFERSIZE:
01487         return HEXEDIT_HEM_SETMAXBUFFERSIZE(hed, (DWORD)lParam);
01488 
01489     case WM_SETFOCUS:
01490         return HEXEDIT_WM_SETFOCUS(hed);
01491 
01492     case WM_KILLFOCUS:
01493         return HEXEDIT_WM_KILLFOCUS(hed);
01494 
01495     case WM_GETDLGCODE:
01496         return HEXEDIT_WM_GETDLGCODE((LPMSG)lParam);
01497 
01498     case WM_SETFONT:
01499         return HEXEDIT_WM_SETFONT(hed, (HFONT)wParam, (BOOL)LOWORD(lParam));
01500 
01501     case WM_GETFONT:
01502         return HEXEDIT_WM_GETFONT(hed);
01503 
01504     case WM_CREATE:
01505         return HEXEDIT_WM_CREATE(hed);
01506 
01507     case WM_NCCREATE:
01508         if(!hed)
01509         {
01510             return HEXEDIT_WM_NCCREATE(hWnd, (CREATESTRUCT*)lParam);
01511         }
01512         break;
01513 
01514     case WM_NCDESTROY:
01515         if(hed)
01516         {
01517             return HEXEDIT_WM_NCDESTROY(hed);
01518         }
01519         break;
01520 
01521     case WM_CONTEXTMENU:
01522         HEXEDIT_WM_CONTEXTMENU(hed, (short)LOWORD(lParam), (short)HIWORD(lParam));
01523         break;
01524 
01525     case WM_COMMAND:
01526         switch(LOWORD(wParam))
01527         {
01528         case ID_HEXEDIT_CUT:
01529             HEXEDIT_Cut(hed);
01530             break;
01531 
01532         case ID_HEXEDIT_COPY:
01533             HEXEDIT_Copy(hed);
01534             break;
01535 
01536         case ID_HEXEDIT_PASTE:
01537             HEXEDIT_Paste(hed);
01538             break;
01539 
01540         case ID_HEXEDIT_DELETE:
01541             HEXEDIT_Delete(hed);
01542             break;
01543 
01544         case ID_HEXEDIT_SELECT_ALL:
01545             HEXEDIT_SelectAll(hed);
01546             break;
01547         }
01548         break;
01549     }
01550 
01551     return DefWindowProc(hWnd, uMsg, wParam, lParam);
01552 }
01553 

Generated on Fri May 25 2012 04:15:47 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.