[REGEDIT]
[reactos.git] / reactos / base / applications / regedit / hexedit.c
index b84f431..209287a 100644 (file)
 #include <regedit.h>
 typedef struct
 {
-  HWND hWndSelf;
-  HWND hWndParent;
-  HLOCAL hBuffer;
-  DWORD style;
-  DWORD MaxBuffer;
-  INT ColumnsPerLine;
-  INT nLines;
-  INT nVisibleLinesComplete;
-  INT nVisibleLines;
-  INT Index;
-  INT LineHeight;
-  INT CharWidth;
-  HFONT hFont;
-  BOOL SbVisible;
-
-  INT LeftMargin;
-  INT AddressSpacing;
-  INT SplitSpacing;
-
-  BOOL EditingField;
-  INT CaretCol;
-  INT CaretLine;
-  BOOL InMid;
-
-  INT SelStart;
-  INT SelEnd;
-  BOOL SelOnField;
+    HWND hWndSelf;
+    HWND hWndParent;
+    HLOCAL hBuffer;
+    DWORD style;
+    DWORD MaxBuffer;
+    INT ColumnsPerLine;
+    INT nLines;
+    INT nVisibleLinesComplete;
+    INT nVisibleLines;
+    INT Index;
+    INT LineHeight;
+    INT CharWidth;
+    HFONT hFont;
+    BOOL SbVisible;
+
+    INT LeftMargin;
+    INT AddressSpacing;
+    INT SplitSpacing;
+
+    BOOL EditingField;
+    INT CaretCol;
+    INT CaretLine;
+    BOOL InMid;
+
+    INT SelStart;
+    INT SelEnd;
 } HEXEDIT_DATA, *PHEXEDIT_DATA;
 
+static const WCHAR ClipboardFormatName[] = L"RegEdit_HexData";
+static UINT ClipboardFormatID = 0;
+
 /* hit test codes */
-#define HEHT_LEFTMARGIN        (0x1)
-#define HEHT_ADDRESS   (0x2)
-#define HEHT_ADDRESSSPACING    (0x3)
-#define HEHT_HEXDUMP   (0x4)
-#define HEHT_HEXDUMPSPACING    (0x5)
-#define HEHT_ASCIIDUMP (0x6)
-#define HEHT_RIGHTMARGIN       (0x7)
+#define HEHT_LEFTMARGIN     (0x1)
+#define HEHT_ADDRESS        (0x2)
+#define HEHT_ADDRESSSPACING (0x3)
+#define HEHT_HEXDUMP        (0x4)
+#define HEHT_HEXDUMPSPACING (0x5)
+#define HEHT_ASCIIDUMP      (0x6)
+#define HEHT_RIGHTMARGIN    (0x7)
 
 INT_PTR CALLBACK HexEditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
@@ -65,26 +67,28 @@ ATOM
 WINAPI
 RegisterHexEditorClass(HINSTANCE hInstance)
 {
-  WNDCLASSEX WndClass;
-
-  ZeroMemory(&WndClass, sizeof(WNDCLASSEX));
-  WndClass.cbSize = sizeof(WNDCLASSEX);
-  WndClass.style = CS_DBLCLKS;
-  WndClass.lpfnWndProc = (WNDPROC)HexEditWndProc;
-  WndClass.cbWndExtra = sizeof(PHEXEDIT_DATA);
-  WndClass.hInstance = hInstance;
-  WndClass.hCursor = LoadCursor(0, IDC_IBEAM);
-  WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
-  WndClass.lpszClassName = HEX_EDIT_CLASS_NAME;
-
-  return RegisterClassEx(&WndClass);
+    WNDCLASSEXW WndClass;
+
+    ClipboardFormatID = RegisterClipboardFormatW(ClipboardFormatName);
+
+    ZeroMemory(&WndClass, sizeof(WNDCLASSEXW));
+    WndClass.cbSize = sizeof(WNDCLASSEXW);
+    WndClass.style = CS_DBLCLKS;
+    WndClass.lpfnWndProc = (WNDPROC)HexEditWndProc;
+    WndClass.cbWndExtra = sizeof(PHEXEDIT_DATA);
+    WndClass.hInstance = hInstance;
+    WndClass.hCursor = LoadCursorW(NULL, IDC_IBEAM);
+    WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+    WndClass.lpszClassName = HEX_EDIT_CLASS_NAME;
+
+    return RegisterClassEx(&WndClass);
 }
 
 BOOL
 WINAPI
 UnregisterHexEditorClass(HINSTANCE hInstance)
 {
-  return UnregisterClass(HEX_EDIT_CLASS_NAME, hInstance);
+    return UnregisterClassW(HEX_EDIT_CLASS_NAME, hInstance);
 }
 
 /*** Helper functions *********************************************************/
@@ -92,439 +96,582 @@ UnregisterHexEditorClass(HINSTANCE hInstance)
 static VOID
 HEXEDIT_MoveCaret(PHEXEDIT_DATA hed, BOOL Scroll)
 {
-  SCROLLINFO si;
+    SCROLLINFO si;
 
-  si.cbSize = sizeof(SCROLLINFO);
-  si.fMask = SIF_POS;
-  GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+    si.cbSize = sizeof(SCROLLINFO);
+    si.fMask = SIF_POS;
+    GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
 
-  if(Scroll)
-  {
-    if(si.nPos > hed->CaretLine)
+    if(Scroll)
     {
-      si.nPos = hed->CaretLine;
-      SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
-      GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
-      InvalidateRect(hed->hWndSelf, NULL, TRUE);
-    }
-    else if(hed->CaretLine >= (hed->nVisibleLinesComplete + si.nPos))
-    {
-      si.nPos = hed->CaretLine - hed->nVisibleLinesComplete + 1;
-      SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
-      GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
-      InvalidateRect(hed->hWndSelf, NULL, TRUE);
+        if(si.nPos > hed->CaretLine)
+        {
+            si.nPos = hed->CaretLine;
+            SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
+            GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+            InvalidateRect(hed->hWndSelf, NULL, TRUE);
+        }
+        else if(hed->CaretLine >= (hed->nVisibleLinesComplete + si.nPos))
+        {
+            si.nPos = hed->CaretLine - hed->nVisibleLinesComplete + 1;
+            SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
+            GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+            InvalidateRect(hed->hWndSelf, NULL, TRUE);
+        }
     }
-  }
 
-  if(hed->EditingField)
-    SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + (3 * hed->CaretCol) + hed->InMid * 2) * hed->CharWidth) - 1, (hed->CaretLine - si.nPos) * hed->LineHeight);
-  else
-    SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine) + hed->CaretCol) * hed->CharWidth) - 2, (hed->CaretLine - si.nPos) * hed->LineHeight);
+    if(hed->EditingField)
+        SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + (3 * hed->CaretCol) + hed->InMid * 2) * hed->CharWidth) - 1, (hed->CaretLine - si.nPos) * hed->LineHeight);
+    else
+        SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine) + hed->CaretCol) * hed->CharWidth) - 2, (hed->CaretLine - si.nPos) * hed->LineHeight);
 }
 
 static VOID
 HEXEDIT_Update(PHEXEDIT_DATA hed)
 {
-  SCROLLINFO si;
-  RECT rcClient;
-  BOOL SbVisible;
-  INT bufsize, cvislines;
-
-  GetClientRect(hed->hWndSelf, &rcClient);
-  hed->style = GetWindowLongPtr(hed->hWndSelf, GWL_STYLE);
-
-  bufsize = (hed->hBuffer ? (INT) LocalSize(hed->hBuffer) : 0);
-  hed->nLines = max(bufsize / hed->ColumnsPerLine, 1);
-  if(bufsize > hed->ColumnsPerLine && (bufsize % hed->ColumnsPerLine) > 0)
-  {
-    hed->nLines++;
-  }
-
-  if(hed->LineHeight > 0)
-  {
-    hed->nVisibleLinesComplete = cvislines = rcClient.bottom / hed->LineHeight;
-    hed->nVisibleLines = hed->nVisibleLinesComplete;
-    if(rcClient.bottom % hed->LineHeight)
-    {
-      hed->nVisibleLines++;
-    }
-  }
-  else
-  {
-    hed->nVisibleLines = cvislines = 0;
-  }
-
-  SbVisible = bufsize > 0 && cvislines < hed->nLines;
-  ShowScrollBar(hed->hWndSelf, SB_VERT, SbVisible);
-
-  /* update scrollbar */
-  si.cbSize = sizeof(SCROLLINFO);
-  si.fMask = SIF_RANGE | SIF_PAGE;
-  si.nMin = 0;
-  si.nMax = ((bufsize > 0) ? hed->nLines - 1 : 0);
-  si.nPage = ((hed->LineHeight > 0) ? rcClient.bottom / hed->LineHeight : 0);
-  SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
-
-  if(IsWindowVisible(hed->hWndSelf) && SbVisible != hed->SbVisible)
-  {
-    InvalidateRect(hed->hWndSelf, NULL, TRUE);
-  }
+    SCROLLINFO si;
+    RECT rcClient;
+    BOOL SbVisible;
+    INT bufsize, cvislines;
 
-  hed->SbVisible = SbVisible;
+    GetClientRect(hed->hWndSelf, &rcClient);
+    hed->style = GetWindowLongPtr(hed->hWndSelf, GWL_STYLE);
+
+    bufsize = (hed->hBuffer ? (INT) LocalSize(hed->hBuffer) : 0);
+    hed->nLines = max(bufsize / hed->ColumnsPerLine, 1);
+    if(bufsize > hed->ColumnsPerLine && (bufsize % hed->ColumnsPerLine) > 0)
+    {
+        hed->nLines++;
+    }
+
+    if(hed->LineHeight > 0)
+    {
+        hed->nVisibleLinesComplete = cvislines = rcClient.bottom / hed->LineHeight;
+        hed->nVisibleLines = hed->nVisibleLinesComplete;
+        if(rcClient.bottom % hed->LineHeight)
+        {
+            hed->nVisibleLines++;
+        }
+    }
+    else
+    {
+        hed->nVisibleLines = cvislines = 0;
+    }
+
+    SbVisible = bufsize > 0 && cvislines < hed->nLines;
+    ShowScrollBar(hed->hWndSelf, SB_VERT, SbVisible);
+
+    /* update scrollbar */
+    si.cbSize = sizeof(SCROLLINFO);
+    si.fMask = SIF_RANGE | SIF_PAGE;
+    si.nMin = 0;
+    si.nMax = ((bufsize > 0) ? hed->nLines - 1 : 0);
+    si.nPage = ((hed->LineHeight > 0) ? rcClient.bottom / hed->LineHeight : 0);
+    SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
+
+    if(IsWindowVisible(hed->hWndSelf) && SbVisible != hed->SbVisible)
+    {
+        InvalidateRect(hed->hWndSelf, NULL, TRUE);
+    }
+
+    hed->SbVisible = SbVisible;
 }
 
 static HFONT
 HEXEDIT_GetFixedFont(VOID)
 {
-  LOGFONT lf;
-  GetObject(GetStockObject(ANSI_FIXED_FONT), sizeof(LOGFONT), &lf);
-  return CreateFontIndirect(&lf);
+    LOGFONT lf;
+    GetObject(GetStockObject(ANSI_FIXED_FONT), sizeof(LOGFONT), &lf);
+    return CreateFontIndirect(&lf);
 }
 
 static VOID
 HEXEDIT_PaintLines(PHEXEDIT_DATA hed, HDC hDC, DWORD ScrollPos, DWORD First, DWORD Last, RECT *rc)
 {
-  DWORD dx, dy, linestart;
-  INT i, isave, i0, i1, x;
-  PBYTE buf, current, end, line;
-  size_t bufsize;
-  TCHAR hex[3], addr[17];
-  RECT rct, rct2;
-
-  FillRect(hDC, rc, (HBRUSH)(COLOR_WINDOW + 1));
-  SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
-
-  if (hed->SelStart < hed->SelEnd)
-  {
-    i0 = hed->SelStart;
-    i1 = hed->SelEnd;
-  }
-  else
-  {
-    i0 = hed->SelEnd;
-    i1 = hed->SelStart;
-  }
-
-  if(hed->hBuffer)
-  {
-    bufsize = LocalSize(hed->hBuffer);
-    buf = LocalLock(hed->hBuffer);
-  }
-  else
-  {
-    buf = NULL;
-    bufsize = 0;
-
-    if(ScrollPos + First == 0)
-    {
-      /* draw address */
-      _stprintf(addr, _T("%04X"), 0);
-      TextOut(hDC, hed->LeftMargin, First * hed->LineHeight, addr, 4);
-    }
-  }
-
-  if(buf)
-  {
-    end = buf + bufsize;
-    dy = First * hed->LineHeight;
-    linestart = (ScrollPos + First) * hed->ColumnsPerLine;
-    i = linestart;
-    current = buf + linestart;
-    Last = min(hed->nLines - ScrollPos, Last);
-
-    SetBkMode(hDC, TRANSPARENT);
-    while(First <= Last && current < end)
-    {
-      DWORD dh;
-
-      dx = hed->LeftMargin;
-
-      /* draw address */
-      _stprintf(addr, _T("%04lX"), linestart);
-      TextOut(hDC, dx, dy, addr, 4);
-
-      dx += ((4 + hed->AddressSpacing) * hed->CharWidth);
-      dh = (3 * hed->CharWidth);
-
-      rct.left = dx;
-      rct.top = dy;
-      rct.right = rct.left + dh;
-      rct.bottom = dy + hed->LineHeight;
-
-      /* draw hex map */
-      dx += (hed->CharWidth / 2);
-      line = current;
-      isave = i;
-      for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
-      {
-        rct.left += dh;
-        rct.right += dh;
-
-       _stprintf(hex, _T("%02X"), *(current++));
-        if (i0 <= i && i < i1)
+    DWORD dx, dy, linestart;
+    INT i, isave, i0, i1, x;
+    PBYTE buf, current, end, line;
+    size_t bufsize;
+    WCHAR hex[3], addr[17];
+    RECT rct, rct2;
+
+    FillRect(hDC, rc, (HBRUSH)(COLOR_WINDOW + 1));
+    SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
+
+    if (hed->SelStart < hed->SelEnd)
+    {
+        i0 = hed->SelStart;
+        i1 = hed->SelEnd;
+    }
+    else
+    {
+        i0 = hed->SelEnd;
+        i1 = hed->SelStart;
+    }
+
+    if(hed->hBuffer)
+    {
+        bufsize = LocalSize(hed->hBuffer);
+        buf = LocalLock(hed->hBuffer);
+    }
+    else
+    {
+        buf = NULL;
+        bufsize = 0;
+
+        if(ScrollPos + First == 0)
         {
-          rct2.left = dx;
-          rct2.top = dy;
-          rct2.right = dx + hed->CharWidth * 2 + 1;
-          rct2.bottom = dy + hed->LineHeight;
-          InflateRect(&rct2, hed->CharWidth / 2, 0);
-          FillRect(hDC, &rct2, (HBRUSH)(COLOR_HIGHLIGHT + 1));
-          SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
-          ExtTextOut(hDC, dx, dy, 0, &rct, hex, 2, NULL);
-          SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
+            /* draw address */
+            wsprintf(addr, L"%04X", 0);
+            TextOutW(hDC, hed->LeftMargin, First * hed->LineHeight, addr, 4);
         }
-        else
-          ExtTextOut(hDC, dx, dy, ETO_OPAQUE, &rct, hex, 2, NULL);
-       dx += dh;
-        i++;
-      }
-
-      /* draw ascii map */
-      dx = ((4 + hed->AddressSpacing + hed->SplitSpacing + (hed->ColumnsPerLine * 3)) * hed->CharWidth);
-      current = line;
-      i = isave;
-      for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
-      {
-       _stprintf(hex, _T("%C"), *(current++));
-       hex[0] = ((hex[0] & _T('\x007f')) >= _T(' ') ? hex[0] : _T('.'));
-        if (i0 <= i && i < i1)
+    }
+
+    if(buf)
+    {
+        end = buf + bufsize;
+        dy = First * hed->LineHeight;
+        linestart = (ScrollPos + First) * hed->ColumnsPerLine;
+        i = linestart;
+        current = buf + linestart;
+        Last = min(hed->nLines - ScrollPos, Last);
+
+        SetBkMode(hDC, TRANSPARENT);
+        while(First <= Last && current < end)
         {
-          rct2.left = dx;
-          rct2.top = dy;
-          rct2.right = dx + hed->CharWidth;
-          rct2.bottom = dy + hed->LineHeight;
-          FillRect(hDC, &rct2, (HBRUSH)(COLOR_HIGHLIGHT + 1));
-          SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
-          TextOut(hDC, dx, dy, hex, 1);
-          SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
+            DWORD dh;
+
+            dx = hed->LeftMargin;
+
+            /* draw address */
+            wsprintf(addr, L"%04lX", linestart);
+            TextOutW(hDC, dx, dy, addr, 4);
+
+            dx += ((4 + hed->AddressSpacing) * hed->CharWidth);
+            dh = (3 * hed->CharWidth);
+
+            rct.left = dx;
+            rct.top = dy;
+            rct.right = rct.left + dh;
+            rct.bottom = dy + hed->LineHeight;
+
+            /* draw hex map */
+            dx += (hed->CharWidth / 2);
+            line = current;
+            isave = i;
+            for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
+            {
+                rct.left += dh;
+                rct.right += dh;
+
+                wsprintf(hex, L"%02X", *(current++));
+                if (i0 <= i && i < i1)
+                {
+                    rct2.left = dx;
+                    rct2.top = dy;
+                    rct2.right = dx + hed->CharWidth * 2 + 1;
+                    rct2.bottom = dy + hed->LineHeight;
+                    InflateRect(&rct2, hed->CharWidth / 2, 0);
+                    FillRect(hDC, &rct2, (HBRUSH)(COLOR_HIGHLIGHT + 1));
+                    SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
+                    ExtTextOutW(hDC, dx, dy, 0, &rct, hex, 2, NULL);
+                    SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
+                }
+                else
+                    ExtTextOutW(hDC, dx, dy, ETO_OPAQUE, &rct, hex, 2, NULL);
+                dx += dh;
+                i++;
+            }
+
+            /* draw ascii map */
+            dx = ((4 + hed->AddressSpacing + hed->SplitSpacing + (hed->ColumnsPerLine * 3)) * hed->CharWidth);
+            current = line;
+            i = isave;
+            for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
+            {
+                wsprintf(hex, L"%C", *(current++));
+                hex[0] = ((hex[0] & L'\x007f') >= L' ' ? hex[0] : L'.');
+                if (i0 <= i && i < i1)
+                {
+                    rct2.left = dx;
+                    rct2.top = dy;
+                    rct2.right = dx + hed->CharWidth;
+                    rct2.bottom = dy + hed->LineHeight;
+                    FillRect(hDC, &rct2, (HBRUSH)(COLOR_HIGHLIGHT + 1));
+                    SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
+                    TextOutW(hDC, dx, dy, hex, 1);
+                    SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
+                }
+                else
+                    TextOutW(hDC, dx, dy, hex, 1);
+                dx += hed->CharWidth;
+                i++;
+            }
+
+            dy += hed->LineHeight;
+            linestart += hed->ColumnsPerLine;
+            First++;
         }
-        else
-          TextOut(hDC, dx, dy, hex, 1);
-       dx += hed->CharWidth;
-        i++;
-      }
-
-      dy += hed->LineHeight;
-      linestart += hed->ColumnsPerLine;
-      First++;
     }
-  }
 
-  LocalUnlock(hed->hBuffer);
+    LocalUnlock(hed->hBuffer);
 }
 
 static DWORD
 HEXEDIT_HitRegionTest(PHEXEDIT_DATA hed, POINTS pt)
 {
-  int d;
-
-  if(pt.x <= hed->LeftMargin)
-  {
-    return HEHT_LEFTMARGIN;
-  }
-
-  pt.x -= hed->LeftMargin;
-  d = (4 * hed->CharWidth);
-  if(pt.x <= d)
-  {
-    return HEHT_ADDRESS;
-  }
-
-  pt.x -= d;
-  d = (hed->AddressSpacing * hed->CharWidth);
-  if(pt.x <= d)
-  {
-    return HEHT_ADDRESSSPACING;
-  }
-
-  pt.x -= d;
-  d = ((3 * hed->ColumnsPerLine + 1) * hed->CharWidth);
-  if(pt.x <= d)
-  {
-    return HEHT_HEXDUMP;
-  }
-
-  pt.x -= d;
-  d = ((hed->SplitSpacing - 1) * hed->CharWidth);
-  if(pt.x <= d)
-  {
-    return HEHT_HEXDUMPSPACING;
-  }
-
-  pt.x -= d;
-  d = (hed->ColumnsPerLine * hed->CharWidth);
-  if(pt.x <= d)
-  {
-    return HEHT_ASCIIDUMP;
-  }
-
-  return HEHT_RIGHTMARGIN;
+    int d;
+
+    if(pt.x <= hed->LeftMargin)
+    {
+        return HEHT_LEFTMARGIN;
+    }
+
+    pt.x -= hed->LeftMargin;
+    d = (4 * hed->CharWidth);
+    if(pt.x <= d)
+    {
+        return HEHT_ADDRESS;
+    }
+
+    pt.x -= d;
+    d = (hed->AddressSpacing * hed->CharWidth);
+    if(pt.x <= d)
+    {
+        return HEHT_ADDRESSSPACING;
+    }
+
+    pt.x -= d;
+    d = ((3 * hed->ColumnsPerLine + 1) * hed->CharWidth);
+    if(pt.x <= d)
+    {
+        return HEHT_HEXDUMP;
+    }
+
+    pt.x -= d;
+    d = ((hed->SplitSpacing - 1) * hed->CharWidth);
+    if(pt.x <= d)
+    {
+        return HEHT_HEXDUMPSPACING;
+    }
+
+    pt.x -= d;
+    d = (hed->ColumnsPerLine * hed->CharWidth);
+    if(pt.x <= d)
+    {
+        return HEHT_ASCIIDUMP;
+    }
+
+    return HEHT_RIGHTMARGIN;
 }
 
 static DWORD
 HEXEDIT_IndexFromPoint(PHEXEDIT_DATA hed, POINTS pt, DWORD Hit, POINT *EditPos, BOOL *EditField)
 {
-  SCROLLINFO si;
-  DWORD Index, bufsize;
-
-  si.cbSize = sizeof(SCROLLINFO);
-  si.fMask = SIF_POS;
-  GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
-
-  EditPos->x = 0;
-
-  if(hed->LineHeight > 0)
-  {
-    EditPos->y = min(si.nPos + (pt.y / hed->LineHeight), hed->nLines - 1);
-  }
-  else
-  {
-    EditPos->y = si.nPos;
-  }
-
-  switch(Hit)
-  {
+    SCROLLINFO si;
+    DWORD Index, bufsize;
+
+    si.cbSize = sizeof(SCROLLINFO);
+    si.fMask = SIF_POS;
+    GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+
+    EditPos->x = 0;
+
+    if(hed->LineHeight > 0)
+    {
+        EditPos->y = min(si.nPos + (pt.y / hed->LineHeight), hed->nLines - 1);
+    }
+    else
+    {
+        EditPos->y = si.nPos;
+    }
+
+    switch(Hit)
+    {
     case HEHT_LEFTMARGIN:
     case HEHT_ADDRESS:
     case HEHT_ADDRESSSPACING:
     case HEHT_HEXDUMP:
-      pt.x -= (SHORT) hed->LeftMargin + ((4 + hed->AddressSpacing) * hed->CharWidth);
-      *EditField = TRUE;
-      break;
+        pt.x -= (SHORT) hed->LeftMargin + ((4 + hed->AddressSpacing) * hed->CharWidth);
+        *EditField = TRUE;
+        break;
 
     default:
-      pt.x -= hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine)) * hed->CharWidth);
-      *EditField = FALSE;
-      break;
-  }
-
-  if(pt.x > 0)
-  {
-    INT BlockWidth = (*EditField ? hed->CharWidth * 3 : hed->CharWidth);
-    EditPos->x = min(hed->ColumnsPerLine, (pt.x + BlockWidth / 2) / BlockWidth);
-  }
-
-  bufsize = (hed->hBuffer ? (DWORD) LocalSize(hed->hBuffer) : 0);
-  Index = (EditPos->y * hed->ColumnsPerLine) + EditPos->x;
-  if(Index > bufsize)
-  {
-    INT tmp = bufsize % hed->ColumnsPerLine;
-    Index = bufsize;
-    EditPos->x = (tmp == 0 ? hed->ColumnsPerLine : tmp);
-  }
-  return Index;
-}
+        pt.x -= hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine)) * hed->CharWidth);
+        *EditField = FALSE;
+        break;
+    }
 
-/*** Control specific messages ************************************************/
+    if(pt.x > 0)
+    {
+        INT BlockWidth = (*EditField ? hed->CharWidth * 3 : hed->CharWidth);
+        EditPos->x = min(hed->ColumnsPerLine, (pt.x + BlockWidth / 2) / BlockWidth);
+    }
 
-static LRESULT
-HEXEDIT_HEM_LOADBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size)
+    bufsize = (hed->hBuffer ? (DWORD) LocalSize(hed->hBuffer) : 0);
+    Index = (EditPos->y * hed->ColumnsPerLine) + EditPos->x;
+    if(Index > bufsize)
+    {
+        INT tmp = bufsize % hed->ColumnsPerLine;
+        Index = bufsize;
+        EditPos->x = (tmp == 0 ? hed->ColumnsPerLine : tmp);
+    }
+    return Index;
+}
+
+static VOID
+HEXEDIT_Copy(PHEXEDIT_DATA hed)
 {
-  if(Buffer != NULL && Size > 0)
-  {
-    LPVOID buf;
+    PBYTE pb, buf;
+    UINT cb;
+    INT i0, i1;
+    HGLOBAL hGlobal;
 
-    if(hed->MaxBuffer > 0 && Size > hed->MaxBuffer)
+    if (hed->SelStart < hed->SelEnd)
+    {
+        i0 = hed->SelStart;
+        i1 = hed->SelEnd;
+    }
+    else
     {
-      Size = hed->MaxBuffer;
+        i0 = hed->SelEnd;
+        i1 = hed->SelStart;
     }
 
-    if(hed->hBuffer)
+    cb = i1 - i0;
+    if (cb == 0)
+        return;
+
+    hGlobal = GlobalAlloc(GHND | GMEM_SHARE, cb + sizeof(DWORD));
+    if (hGlobal == NULL)
+        return;
+
+    pb = GlobalLock(hGlobal);
+    if (pb)
     {
-      if(Size > 0)
-      {
-        if(LocalSize(hed->hBuffer) != Size)
+        *(PDWORD)pb = cb;
+        pb += sizeof(DWORD);
+        buf = (PBYTE) LocalLock(hed->hBuffer);
+        if (buf)
         {
-          hed->hBuffer = LocalReAlloc(hed->hBuffer, Size, LMEM_MOVEABLE | LMEM_ZEROINIT);
+            CopyMemory(pb, buf + i0, cb);
+            LocalUnlock(hed->hBuffer);
         }
-      }
-      else
-      {
-        hed->hBuffer = LocalFree(hed->hBuffer);
-        hed->Index = 0;
-        HEXEDIT_Update(hed);
+        GlobalUnlock(hGlobal);
 
-        return 0;
-      }
+        if (OpenClipboard(hed->hWndSelf))
+        {
+            EmptyClipboard();
+            SetClipboardData(ClipboardFormatID, hGlobal);
+            CloseClipboard();
+        }
     }
-    else if(Size > 0)
+    else
+        GlobalFree(hGlobal);
+}
+
+static VOID
+HEXEDIT_Delete(PHEXEDIT_DATA hed)
+{
+    PBYTE buf;
+    INT i0, i1;
+    UINT bufsize;
+
+    if (hed->SelStart < hed->SelEnd)
     {
-      hed->hBuffer = LocalAlloc(LHND, Size);
+        i0 = hed->SelStart;
+        i1 = hed->SelEnd;
+    }
+    else
+    {
+        i0 = hed->SelEnd;
+        i1 = hed->SelStart;
     }
 
-    if(Size > 0)
+    if (i0 != i1)
     {
-      buf = LocalLock(hed->hBuffer);
-      if(buf)
-      {
-        memcpy(buf, Buffer, Size);
-      }
-      else
-        Size = 0;
-      LocalUnlock(hed->hBuffer);
+        bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
+        buf = (PBYTE) LocalLock(hed->hBuffer);
+        if (buf)
+        {
+            MoveMemory(buf + i0, buf + i1, bufsize - i1);
+            LocalUnlock(hed->hBuffer);
+        }
+        HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
+        hed->InMid = FALSE;
+        hed->Index = hed->SelStart = hed->SelEnd = i0;
+        hed->CaretCol = hed->Index % hed->ColumnsPerLine;
+        hed->CaretLine = hed->Index / hed->ColumnsPerLine;
+        InvalidateRect(hed->hWndSelf, NULL, TRUE);
+        HEXEDIT_MoveCaret(hed, TRUE);
     }
+}
 
-    hed->Index = 0;
-    HEXEDIT_Update(hed);
-    return Size;
-  }
-  else if(hed->hBuffer)
-  {
-    hed->Index = 0;
-    hed->hBuffer = LocalFree(hed->hBuffer);
-    HEXEDIT_Update(hed);
-  }
+static VOID
+HEXEDIT_Paste(PHEXEDIT_DATA hed)
+{
+    HGLOBAL hGlobal;
+    UINT bufsize;
+    PBYTE pb, buf;
+    DWORD cb;
+
+    HEXEDIT_Delete(hed);
+    bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
 
-  return 0;
+    if (OpenClipboard(hed->hWndSelf))
+    {
+        hGlobal = GetClipboardData(ClipboardFormatID);
+        if (hGlobal != NULL)
+        {
+            pb = (PBYTE) GlobalLock(hGlobal);
+            cb = *(PDWORD) pb;
+            pb += sizeof(DWORD);
+            HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize + cb);
+            buf = (PBYTE) LocalLock(hed->hBuffer);
+            if (buf)
+            {
+                MoveMemory(buf + hed->Index + cb, buf + hed->Index,
+                           bufsize - hed->Index);
+                CopyMemory(buf + hed->Index, pb, cb);
+                LocalUnlock(hed->hBuffer);
+            }
+            GlobalUnlock(hGlobal);
+        }
+        CloseClipboard();
+    }
+    InvalidateRect(hed->hWndSelf, NULL, TRUE);
+    HEXEDIT_MoveCaret(hed, TRUE);
+}
+
+static VOID
+HEXEDIT_Cut(PHEXEDIT_DATA hed)
+{
+    HEXEDIT_Copy(hed);
+    HEXEDIT_Delete(hed);
+}
+
+static VOID
+HEXEDIT_SelectAll(PHEXEDIT_DATA hed)
+{
+    INT bufsize;
+
+    bufsize = (hed->hBuffer ? (INT) LocalSize(hed->hBuffer) : 0);
+    hed->Index = hed->SelStart = 0;
+    hed->SelEnd = bufsize;
+    InvalidateRect(hed->hWndSelf, NULL, TRUE);
+    HEXEDIT_MoveCaret(hed, TRUE);
 }
 
+/*** Control specific messages ************************************************/
+
 static LRESULT
-HEXEDIT_HEM_COPYBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size)
+HEXEDIT_HEM_LOADBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size)
 {
-  size_t nCpy;
+    if(Buffer != NULL && Size > 0)
+    {
+        LPVOID buf;
+
+        if(hed->MaxBuffer > 0 && Size > hed->MaxBuffer)
+        {
+            Size = hed->MaxBuffer;
+        }
+
+        if(hed->hBuffer)
+        {
+            if(Size > 0)
+            {
+                if(LocalSize(hed->hBuffer) != Size)
+                {
+                    hed->hBuffer = LocalReAlloc(hed->hBuffer, Size, LMEM_MOVEABLE | LMEM_ZEROINIT);
+                }
+            }
+            else
+            {
+                hed->hBuffer = LocalFree(hed->hBuffer);
+                hed->Index = 0;
+                HEXEDIT_Update(hed);
+
+                return 0;
+            }
+        }
+        else if(Size > 0)
+        {
+            hed->hBuffer = LocalAlloc(LHND, Size);
+        }
+
+        if(Size > 0)
+        {
+            buf = LocalLock(hed->hBuffer);
+            if(buf)
+            {
+                memcpy(buf, Buffer, Size);
+            }
+            else
+                Size = 0;
+            LocalUnlock(hed->hBuffer);
+        }
+
+        hed->Index = 0;
+        HEXEDIT_Update(hed);
+        return Size;
+    }
+    else if(hed->hBuffer)
+    {
+        hed->Index = 0;
+        hed->hBuffer = LocalFree(hed->hBuffer);
+        HEXEDIT_Update(hed);
+    }
 
-  if(!hed->hBuffer)
-  {
     return 0;
-  }
+}
 
-  if(Buffer != NULL && Size > 0)
-  {
-    nCpy = min(Size, LocalSize(hed->hBuffer));
-    if(nCpy > 0)
+static LRESULT
+HEXEDIT_HEM_COPYBUFFER(PHEXEDIT_DATA hed, PVOID Buffer, DWORD Size)
+{
+    size_t nCpy;
+
+    if(!hed->hBuffer)
     {
-      PVOID buf;
+        return 0;
+    }
 
-      buf = LocalLock(hed->hBuffer);
-      if(buf)
-      {
-        memcpy(Buffer, buf, nCpy);
-      }
-      else
-        nCpy = 0;
-      LocalUnlock(hed->hBuffer);
+    if(Buffer != NULL && Size > 0)
+    {
+        nCpy = min(Size, LocalSize(hed->hBuffer));
+        if(nCpy > 0)
+        {
+            PVOID buf;
+
+            buf = LocalLock(hed->hBuffer);
+            if(buf)
+            {
+                memcpy(Buffer, buf, nCpy);
+            }
+            else
+                nCpy = 0;
+            LocalUnlock(hed->hBuffer);
+        }
+        return nCpy;
     }
-    return nCpy;
-  }
 
-  return (LRESULT)LocalSize(hed->hBuffer);
+    return (LRESULT)LocalSize(hed->hBuffer);
 }
 
 static LRESULT
 HEXEDIT_HEM_SETMAXBUFFERSIZE(PHEXEDIT_DATA hed, DWORD nMaxSize)
 {
-  hed->MaxBuffer = nMaxSize;
-  if (hed->MaxBuffer == 0)
-  {
-    hed->hBuffer = LocalFree(hed->hBuffer);
+    hed->MaxBuffer = nMaxSize;
+    if (hed->MaxBuffer == 0)
+    {
+        hed->hBuffer = LocalFree(hed->hBuffer);
+        return 0;
+    }
+    if (hed->hBuffer)
+        hed->hBuffer = LocalReAlloc(hed->hBuffer, hed->MaxBuffer, LMEM_MOVEABLE);
+    else
+        hed->hBuffer = LocalAlloc(LMEM_MOVEABLE, hed->MaxBuffer);
+    HEXEDIT_Update(hed);
     return 0;
-  }
-  if (hed->hBuffer)
-    hed->hBuffer = LocalReAlloc(hed->hBuffer, hed->MaxBuffer, LMEM_MOVEABLE);
-  else
-    hed->hBuffer = LocalAlloc(LMEM_MOVEABLE, hed->MaxBuffer);
-  HEXEDIT_Update(hed);
-  return 0;
 }
 
 /*** Message Proc *************************************************************/
@@ -532,773 +679,876 @@ HEXEDIT_HEM_SETMAXBUFFERSIZE(PHEXEDIT_DATA hed, DWORD nMaxSize)
 static LRESULT
 HEXEDIT_WM_NCCREATE(HWND hWnd, CREATESTRUCT *cs)
 {
-  PHEXEDIT_DATA hed;
+    PHEXEDIT_DATA hed;
 
-  if(!(hed = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEXEDIT_DATA))))
-  {
-    return FALSE;
-  }
+    if(!(hed = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEXEDIT_DATA))))
+    {
+        return FALSE;
+    }
 
-  hed->hWndSelf = hWnd;
-  hed->hWndParent = cs->hwndParent;
-  hed->style = cs->style;
+    hed->hWndSelf = hWnd;
+    hed->hWndParent = cs->hwndParent;
+    hed->style = cs->style;
 
-  hed->ColumnsPerLine = 8;
-  hed->LeftMargin = 2;
-  hed->AddressSpacing = 2;
-  hed->SplitSpacing = 2;
-  hed->EditingField = TRUE; /* in hexdump field */
+    hed->ColumnsPerLine = 8;
+    hed->LeftMargin = 2;
+    hed->AddressSpacing = 2;
+    hed->SplitSpacing = 2;
+    hed->EditingField = TRUE; /* in hexdump field */
 
-  SetWindowLongPtr(hWnd, 0, (DWORD_PTR)hed);
-  HEXEDIT_Update(hed);
+    SetWindowLongPtr(hWnd, 0, (DWORD_PTR)hed);
+    HEXEDIT_Update(hed);
 
-  return TRUE;
+    return TRUE;
 }
 
 static LRESULT
 HEXEDIT_WM_NCDESTROY(PHEXEDIT_DATA hed)
 {
-  if(hed->hBuffer)
-  {
-    //while(LocalUnlock(hed->hBuffer));
-    LocalFree(hed->hBuffer);
-  }
+    if(hed->hBuffer)
+    {
+        //while(LocalUnlock(hed->hBuffer));
+        LocalFree(hed->hBuffer);
+    }
 
-  if(hed->hFont)
-  {
-    DeleteObject(hed->hFont);
-  }
+    if(hed->hFont)
+    {
+        DeleteObject(hed->hFont);
+    }
 
-  SetWindowLongPtr(hed->hWndSelf, 0, (DWORD_PTR)0);
-  HeapFree(GetProcessHeap(), 0, hed);
+    SetWindowLongPtr(hed->hWndSelf, 0, (DWORD_PTR)0);
+    HeapFree(GetProcessHeap(), 0, hed);
 
-  return 0;
+    return 0;
 }
 
 static LRESULT
 HEXEDIT_WM_CREATE(PHEXEDIT_DATA hed)
 {
-  UNREFERENCED_PARAMETER(hed);
-  return 1;
+    UNREFERENCED_PARAMETER(hed);
+    return 1;
 }
 
 static LRESULT
 HEXEDIT_WM_SETFOCUS(PHEXEDIT_DATA hed)
 {
-  CreateCaret(hed->hWndSelf, 0, 1, hed->LineHeight);
-  HEXEDIT_MoveCaret(hed, FALSE);
-  ShowCaret(hed->hWndSelf);
-  return 0;
+    CreateCaret(hed->hWndSelf, 0, 1, hed->LineHeight);
+    HEXEDIT_MoveCaret(hed, FALSE);
+    ShowCaret(hed->hWndSelf);
+    return 0;
 }
 
 static LRESULT
 HEXEDIT_WM_KILLFOCUS(PHEXEDIT_DATA hed)
 {
-  UNREFERENCED_PARAMETER(hed);
-  DestroyCaret();
-  return 0;
+    UNREFERENCED_PARAMETER(hed);
+    DestroyCaret();
+    return 0;
 }
 
 static LRESULT
 HEXEDIT_WM_VSCROLL(PHEXEDIT_DATA hed, WORD ThumbPosition, WORD SbCmd)
 {
-  int ScrollY;
-  SCROLLINFO si;
+    int ScrollY;
+    SCROLLINFO si;
 
-  UNREFERENCED_PARAMETER(ThumbPosition);
+    UNREFERENCED_PARAMETER(ThumbPosition);
 
-  ZeroMemory(&si, sizeof(SCROLLINFO));
-  si.cbSize = sizeof(SCROLLINFO);
-  si.fMask = SIF_ALL;
-  GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+    ZeroMemory(&si, sizeof(SCROLLINFO));
+    si.cbSize = sizeof(SCROLLINFO);
+    si.fMask = SIF_ALL;
+    GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
 
-  ScrollY = si.nPos;
-  switch(SbCmd)
-  {
+    ScrollY = si.nPos;
+    switch(SbCmd)
+    {
     case SB_TOP:
-      si.nPos = si.nMin;
-      break;
+        si.nPos = si.nMin;
+        break;
 
     case SB_BOTTOM:
-      si.nPos = si.nMax;
-      break;
+        si.nPos = si.nMax;
+        break;
 
     case SB_LINEUP:
-      si.nPos--;
-      break;
+        si.nPos--;
+        break;
 
     case SB_LINEDOWN:
-      si.nPos++;
-      break;
+        si.nPos++;
+        break;
 
     case SB_PAGEUP:
-      si.nPos -= si.nPage;
-      break;
+        si.nPos -= si.nPage;
+        break;
 
     case SB_PAGEDOWN:
-      si.nPos += si.nPage;
-      break;
+        si.nPos += si.nPage;
+        break;
 
     case SB_THUMBTRACK:
-      si.nPos = si.nTrackPos;
-      break;
-  }
+        si.nPos = si.nTrackPos;
+        break;
+    }
 
-  si.fMask = SIF_POS;
-  SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
-  GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+    si.fMask = SIF_POS;
+    SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
+    GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
 
-  if(si.nPos != ScrollY)
-  {
-    ScrollWindow(hed->hWndSelf, 0, (ScrollY - si.nPos) * hed->LineHeight, NULL, NULL);
-    UpdateWindow(hed->hWndSelf);
-  }
+    if(si.nPos != ScrollY)
+    {
+        ScrollWindow(hed->hWndSelf, 0, (ScrollY - si.nPos) * hed->LineHeight, NULL, NULL);
+        UpdateWindow(hed->hWndSelf);
+    }
 
-  return 0;
+    return 0;
 }
 
 static LRESULT
 HEXEDIT_WM_SETFONT(PHEXEDIT_DATA hed, HFONT hFont, BOOL bRedraw)
 {
-  HDC hDC;
-  TEXTMETRIC tm;
-  HFONT hOldFont = 0;
-
-  if(hFont == 0)
-  {
-    hFont = HEXEDIT_GetFixedFont();
-  }
-
-  hed->hFont = hFont;
-  hDC = GetDC(hed->hWndSelf);
-  if(hFont)
-  {
-    hOldFont = SelectObject(hDC, hFont);
-  }
-  GetTextMetrics(hDC, &tm);
-  hed->LineHeight = tm.tmHeight;
-  hed->CharWidth = tm.tmAveCharWidth;
-  if(hOldFont)
-  {
-    SelectObject(hDC, hOldFont);
-  }
-  ReleaseDC(hed->hWndSelf, hDC);
-
-  if(bRedraw)
-  {
-    InvalidateRect(hed->hWndSelf, NULL, TRUE);
-  }
+    HDC hDC;
+    TEXTMETRIC tm;
+    HFONT hOldFont = 0;
+
+    if(hFont == 0)
+    {
+        hFont = HEXEDIT_GetFixedFont();
+    }
+
+    hed->hFont = hFont;
+    hDC = GetDC(hed->hWndSelf);
+    if(hFont)
+    {
+        hOldFont = SelectObject(hDC, hFont);
+    }
+    GetTextMetrics(hDC, &tm);
+    hed->LineHeight = tm.tmHeight;
+    hed->CharWidth = tm.tmAveCharWidth;
+    if(hOldFont)
+    {
+        SelectObject(hDC, hOldFont);
+    }
+    ReleaseDC(hed->hWndSelf, hDC);
 
-  return 0;
+    if(bRedraw)
+    {
+        InvalidateRect(hed->hWndSelf, NULL, TRUE);
+    }
+
+    return 0;
 }
 
 static LRESULT
 HEXEDIT_WM_GETFONT(PHEXEDIT_DATA hed)
 {
-  return (LRESULT)hed->hFont;
+    return (LRESULT)hed->hFont;
 }
 
 static LRESULT
 HEXEDIT_WM_PAINT(PHEXEDIT_DATA hed)
 {
-  PAINTSTRUCT ps;
-  SCROLLINFO si;
-  RECT rc;
-  HBITMAP hbmp, hbmpold;
-  INT nLines, nFirst;
-  HFONT hOldFont;
-  HDC hTempDC;
-  DWORD height;
-
-  if(GetUpdateRect(hed->hWndSelf, &rc, FALSE) && (hed->LineHeight > 0))
-  {
-    ZeroMemory(&si, sizeof(SCROLLINFO));
-    si.cbSize = sizeof(SCROLLINFO);
-    si.fMask = SIF_POS;
-    GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
-
-    height = (rc.bottom - rc.top);
-    nLines = height / hed->LineHeight;
-    if((height % hed->LineHeight) > 0)
-    {
-      nLines++;
-    }
-    if(nLines > hed->nLines - si.nPos)
+    PAINTSTRUCT ps;
+    SCROLLINFO si;
+    RECT rc;
+    HBITMAP hbmp, hbmpold;
+    INT nLines, nFirst;
+    HFONT hOldFont;
+    HDC hTempDC;
+    DWORD height;
+
+    if(GetUpdateRect(hed->hWndSelf, &rc, FALSE) && (hed->LineHeight > 0))
     {
-      nLines = hed->nLines - si.nPos;
-    }
-    nFirst = rc.top / hed->LineHeight;
+        ZeroMemory(&si, sizeof(SCROLLINFO));
+        si.cbSize = sizeof(SCROLLINFO);
+        si.fMask = SIF_POS;
+        GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+
+        height = (rc.bottom - rc.top);
+        nLines = height / hed->LineHeight;
+        if((height % hed->LineHeight) > 0)
+        {
+            nLines++;
+        }
+        if(nLines > hed->nLines - si.nPos)
+        {
+            nLines = hed->nLines - si.nPos;
+        }
+        nFirst = rc.top / hed->LineHeight;
 
-    BeginPaint(hed->hWndSelf, &ps);
-    if(!(hTempDC = CreateCompatibleDC(ps.hdc)))
-    {
-      FillRect(ps.hdc, &rc, (HBRUSH)(COLOR_WINDOW + 1));
-      goto epaint;
-    }
-    if(!(hbmp = CreateCompatibleBitmap(ps.hdc, ps.rcPaint.right, ps.rcPaint.bottom)))
-    {
-      FillRect(ps.hdc, &rc, (HBRUSH)(COLOR_WINDOW + 1));
-      DeleteDC(hTempDC);
-      goto epaint;
-    }
-    hbmpold = SelectObject(hTempDC, hbmp);
-    hOldFont = SelectObject(hTempDC, hed->hFont);
-    HEXEDIT_PaintLines(hed, hTempDC, si.nPos, nFirst, nFirst + nLines, &ps.rcPaint);
-    BitBlt(ps.hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hTempDC, rc.left, rc.top, SRCCOPY);
-    SelectObject(hTempDC, hOldFont);
-    SelectObject(hTempDC, hbmpold);
+        BeginPaint(hed->hWndSelf, &ps);
+        if(!(hTempDC = CreateCompatibleDC(ps.hdc)))
+        {
+            FillRect(ps.hdc, &rc, (HBRUSH)(COLOR_WINDOW + 1));
+            goto epaint;
+        }
+        if(!(hbmp = CreateCompatibleBitmap(ps.hdc, ps.rcPaint.right, ps.rcPaint.bottom)))
+        {
+            FillRect(ps.hdc, &rc, (HBRUSH)(COLOR_WINDOW + 1));
+            DeleteDC(hTempDC);
+            goto epaint;
+        }
+        hbmpold = SelectObject(hTempDC, hbmp);
+        hOldFont = SelectObject(hTempDC, hed->hFont);
+        HEXEDIT_PaintLines(hed, hTempDC, si.nPos, nFirst, nFirst + nLines, &ps.rcPaint);
+        BitBlt(ps.hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, hTempDC, rc.left, rc.top, SRCCOPY);
+        SelectObject(hTempDC, hOldFont);
+        SelectObject(hTempDC, hbmpold);
 
-    DeleteObject(hbmp);
-    DeleteDC(hTempDC);
+        DeleteObject(hbmp);
+        DeleteDC(hTempDC);
 
 epaint:
-    EndPaint(hed->hWndSelf, &ps);
-  }
+        EndPaint(hed->hWndSelf, &ps);
+    }
 
-  return 0;
+    return 0;
 }
 
 static LRESULT
 HEXEDIT_WM_MOUSEWHEEL(PHEXEDIT_DATA hed, int cyMoveLines, WORD ButtonsDown, LPPOINTS MousePos)
 {
-  SCROLLINFO si;
-  int ScrollY;
+    SCROLLINFO si;
+    int ScrollY;
 
-  UNREFERENCED_PARAMETER(ButtonsDown);
-  UNREFERENCED_PARAMETER(MousePos);
+    UNREFERENCED_PARAMETER(ButtonsDown);
+    UNREFERENCED_PARAMETER(MousePos);
 
-  SetFocus(hed->hWndSelf);
+    SetFocus(hed->hWndSelf);
 
-  si.cbSize = sizeof(SCROLLINFO);
-  si.fMask = SIF_ALL;
-  GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+    si.cbSize = sizeof(SCROLLINFO);
+    si.fMask = SIF_ALL;
+    GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
 
-  ScrollY = si.nPos;
+    ScrollY = si.nPos;
 
-  si.fMask = SIF_POS;
-  si.nPos += cyMoveLines;
-  SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
+    si.fMask = SIF_POS;
+    si.nPos += cyMoveLines;
+    SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
 
-  GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
-  if(si.nPos != ScrollY)
-  {
-    ScrollWindow(hed->hWndSelf, 0, (ScrollY - si.nPos) * hed->LineHeight, NULL, NULL);
-    UpdateWindow(hed->hWndSelf);
-  }
+    GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+    if(si.nPos != ScrollY)
+    {
+        ScrollWindow(hed->hWndSelf, 0, (ScrollY - si.nPos) * hed->LineHeight, NULL, NULL);
+        UpdateWindow(hed->hWndSelf);
+    }
 
-  return 0;
+    return 0;
 }
 
 static LRESULT
 HEXEDIT_WM_GETDLGCODE(LPMSG Msg)
 {
-  UNREFERENCED_PARAMETER(Msg);
-  return DLGC_WANTARROWS | DLGC_WANTCHARS;
+    UNREFERENCED_PARAMETER(Msg);
+    return DLGC_WANTARROWS | DLGC_WANTCHARS;
 }
 
 static LRESULT
 HEXEDIT_WM_LBUTTONDOWN(PHEXEDIT_DATA hed, INT Buttons, POINTS Pt)
 {
-  BOOL NewField;
-  POINT EditPos;
-  DWORD Hit;
+    BOOL NewField;
+    POINT EditPos;
+    DWORD Hit;
 
-  UNREFERENCED_PARAMETER(Buttons);
-  SetFocus(hed->hWndSelf);
+    UNREFERENCED_PARAMETER(Buttons);
+    SetFocus(hed->hWndSelf);
 
-  if (GetAsyncKeyState(VK_SHIFT) < 0)
-  {
-    if (hed->SelOnField)
-      hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField);
+    if (GetAsyncKeyState(VK_SHIFT) < 0)
+    {
+        if (hed->EditingField)
+            hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField);
+        else
+            hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField);
+        hed->SelEnd = hed->Index;
+    }
     else
-      hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField);
-    hed->SelEnd = hed->Index;
-    hed->EditingField = hed->SelOnField;
-  }
-  else
-  {
-    Hit = HEXEDIT_HitRegionTest(hed, Pt);
-    hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, Hit, &EditPos, &NewField);
-    hed->SelStart = hed->SelEnd = hed->Index;
-    hed->SelOnField = hed->EditingField = NewField;
-    SetCapture(hed->hWndSelf);
-  }
-  hed->CaretCol = EditPos.x;
-  hed->CaretLine = EditPos.y;
-  hed->InMid = FALSE;
-  InvalidateRect(hed->hWndSelf, NULL, FALSE);
-  HEXEDIT_MoveCaret(hed, TRUE);
-
-  return 0;
+    {
+        Hit = HEXEDIT_HitRegionTest(hed, Pt);
+        hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, Hit, &EditPos, &NewField);
+        hed->SelStart = hed->SelEnd = hed->Index;
+        hed->EditingField = NewField;
+        SetCapture(hed->hWndSelf);
+    }
+    hed->CaretCol = EditPos.x;
+    hed->CaretLine = EditPos.y;
+    hed->InMid = FALSE;
+    InvalidateRect(hed->hWndSelf, NULL, FALSE);
+    HEXEDIT_MoveCaret(hed, TRUE);
+
+    return 0;
 }
 
 static LRESULT
 HEXEDIT_WM_LBUTTONUP(PHEXEDIT_DATA hed, INT Buttons, POINTS Pt)
 {
-  BOOL NewField;
-  POINT EditPos;
-  if (GetCapture() == hed->hWndSelf)
-  {
-    if (hed->SelOnField)
-      hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField);
-    else
-      hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField);
-    hed->CaretCol = EditPos.x;
-    hed->CaretLine = EditPos.y;
-    hed->SelEnd = hed->Index;
-    ReleaseCapture();
-    InvalidateRect(hed->hWndSelf, NULL, FALSE);
-    HEXEDIT_MoveCaret(hed, TRUE);
-  }
-  return 0;
+    BOOL NewField;
+    POINT EditPos;
+    if (GetCapture() == hed->hWndSelf)
+    {
+        if (hed->EditingField)
+            hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField);
+        else
+            hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField);
+        hed->CaretCol = EditPos.x;
+        hed->CaretLine = EditPos.y;
+        hed->SelEnd = hed->Index;
+        ReleaseCapture();
+        InvalidateRect(hed->hWndSelf, NULL, FALSE);
+        HEXEDIT_MoveCaret(hed, TRUE);
+    }
+    return 0;
 }
 
 static LRESULT
 HEXEDIT_WM_MOUSEMOVE(PHEXEDIT_DATA hed, INT Buttons, POINTS Pt)
 {
-  BOOL NewField;
-  POINT EditPos;
-  if (GetCapture() == hed->hWndSelf)
-  {
-    if (hed->SelOnField)
-      hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField);
-    else
-      hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField);
-    hed->CaretCol = EditPos.x;
-    hed->CaretLine = EditPos.y;
-    hed->SelEnd = hed->Index;
-    InvalidateRect(hed->hWndSelf, NULL, FALSE);
-    HEXEDIT_MoveCaret(hed, TRUE);
-  }
-  return 0;
+    BOOL NewField;
+    POINT EditPos;
+    if (GetCapture() == hed->hWndSelf)
+    {
+        if (hed->EditingField)
+            hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_HEXDUMP, &EditPos, &NewField);
+        else
+            hed->Index = HEXEDIT_IndexFromPoint(hed, Pt, HEHT_ASCIIDUMP, &EditPos, &NewField);
+        hed->CaretCol = EditPos.x;
+        hed->CaretLine = EditPos.y;
+        hed->SelEnd = hed->Index;
+        InvalidateRect(hed->hWndSelf, NULL, FALSE);
+        HEXEDIT_MoveCaret(hed, TRUE);
+    }
+    return 0;
 }
 
 static BOOL
 HEXEDIT_WM_KEYDOWN(PHEXEDIT_DATA hed, INT VkCode)
 {
-  size_t bufsize;
-  PBYTE buf;
-  INT i0, i1;
+    size_t bufsize;
+    PBYTE buf;
+    INT i0, i1;
 
-  if(GetKeyState(VK_MENU) & 0x8000)
-  {
-    return FALSE;
-  }
-
-  bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
-
-  if (hed->SelStart < hed->SelEnd)
-  {
-    i0 = hed->SelStart;
-    i1 = hed->SelEnd;
-  }
-  else
-  {
-    i0 = hed->SelEnd;
-    i1 = hed->SelStart;
-  }
-
-  switch(VkCode)
-  {
-    case VK_DELETE:
-      if (hed->SelStart != hed->SelEnd)
-      {
-        buf = (PBYTE) LocalLock(hed->hBuffer);
-        if (buf)
+    if(GetKeyState(VK_MENU) & 0x8000)
+    {
+        return FALSE;
+    }
+
+    bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
+
+    if (hed->SelStart < hed->SelEnd)
+    {
+        i0 = hed->SelStart;
+        i1 = hed->SelEnd;
+    }
+    else
+    {
+        i0 = hed->SelEnd;
+        i1 = hed->SelStart;
+    }
+
+    switch(VkCode)
+    {
+    case 'X':
+        if (GetAsyncKeyState(VK_SHIFT) >= 0 &&
+            GetAsyncKeyState(VK_CONTROL) < 0 && hed->SelStart != hed->SelEnd)
+            HEXEDIT_Cut(hed);
+        else
+            return TRUE;
+        break;
+
+    case 'C':
+        if (GetAsyncKeyState(VK_SHIFT) >= 0 &&
+            GetAsyncKeyState(VK_CONTROL) < 0 && hed->SelStart != hed->SelEnd)
+            HEXEDIT_Copy(hed);
+        else
+            return TRUE;
+        break;
+
+    case 'V':
+        if (GetAsyncKeyState(VK_SHIFT) >= 0 && GetAsyncKeyState(VK_CONTROL) < 0)
+            HEXEDIT_Paste(hed);
+        else
+            return TRUE;
+        break;
+
+    case 'A':
+        if (GetAsyncKeyState(VK_SHIFT) >= 0 && GetAsyncKeyState(VK_CONTROL) < 0)
+            HEXEDIT_SelectAll(hed);
+        else
+            return TRUE;
+        break;
+
+    case VK_INSERT:
+        if (hed->SelStart != hed->SelEnd)
         {
-          MoveMemory(buf + i0, buf + i1, bufsize - i1);
-          LocalUnlock(hed->hBuffer);
+            if (GetAsyncKeyState(VK_SHIFT) >= 0 && GetAsyncKeyState(VK_CONTROL) < 0)
+                HEXEDIT_Copy(hed);
         }
-        HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
-        hed->InMid = FALSE;
-        hed->Index = hed->SelStart = hed->SelEnd = i0;
-        hed->CaretCol = hed->Index % hed->ColumnsPerLine;
-        hed->CaretLine = hed->Index / hed->ColumnsPerLine;
-      }
-      else
-      {
-        if (hed->InMid && hed->EditingField)
+        if (GetAsyncKeyState(VK_SHIFT) < 0 && GetAsyncKeyState(VK_CONTROL) >= 0)
+            HEXEDIT_Paste(hed);
+        break;
+
+    case VK_DELETE:
+        if (GetAsyncKeyState(VK_SHIFT) < 0 && GetAsyncKeyState(VK_CONTROL) >= 0 &&
+            hed->SelStart != hed->SelEnd)
+            HEXEDIT_Copy(hed);
+        if (i0 != i1)
         {
-          buf = (PBYTE) LocalLock(hed->hBuffer);
-          if (buf)
-          {
-            MoveMemory(buf + hed->Index, buf + hed->Index + 1,
-                       bufsize - hed->Index - 1);
-            LocalUnlock(hed->hBuffer);
-          }
-          HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1);
-          hed->InMid = FALSE;
+            buf = (PBYTE) LocalLock(hed->hBuffer);
+            if (buf)
+            {
+                MoveMemory(buf + i0, buf + i1, bufsize - i1);
+                LocalUnlock(hed->hBuffer);
+            }
+            HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
+            hed->InMid = FALSE;
+            hed->Index = hed->SelStart = hed->SelEnd = i0;
+            hed->CaretCol = hed->Index % hed->ColumnsPerLine;
+            hed->CaretLine = hed->Index / hed->ColumnsPerLine;
         }
-        else if (hed->Index < bufsize)
+        else
         {
-          buf = (PBYTE) LocalLock(hed->hBuffer);
-          if (buf)
-          {
-            MoveMemory(buf + hed->Index, buf + hed->Index + 1,
-                       bufsize - hed->Index - 1);
-            LocalUnlock(hed->hBuffer);
-          }
-          HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1);
+            if (hed->InMid && hed->EditingField)
+            {
+                buf = (PBYTE) LocalLock(hed->hBuffer);
+                if (buf)
+                {
+                    MoveMemory(buf + hed->Index, buf + hed->Index + 1,
+                               bufsize - hed->Index - 1);
+                    LocalUnlock(hed->hBuffer);
+                }
+                HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1);
+                hed->InMid = FALSE;
+            }
+            else if (hed->Index < bufsize)
+            {
+                buf = (PBYTE) LocalLock(hed->hBuffer);
+                if (buf)
+                {
+                    MoveMemory(buf + hed->Index, buf + hed->Index + 1,
+                               bufsize - hed->Index - 1);
+                    LocalUnlock(hed->hBuffer);
+                }
+                HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1);
+            }
         }
-      }
-      InvalidateRect(hed->hWndSelf, NULL, TRUE);
-      HEXEDIT_MoveCaret(hed, TRUE);
-      break;
+        InvalidateRect(hed->hWndSelf, NULL, TRUE);
+        HEXEDIT_MoveCaret(hed, TRUE);
+        break;
 
     case VK_BACK:
-      if (hed->SelStart != hed->SelEnd)
-      {
-        buf = (PBYTE) LocalLock(hed->hBuffer);
-        if (buf)
-        {
-          MoveMemory(buf + i0, buf + i1, bufsize - i1);
-          LocalUnlock(hed->hBuffer);
-        }
-        HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
-        hed->InMid = FALSE;
-        hed->Index = hed->SelStart = hed->SelEnd = i0;
-        hed->CaretCol = hed->Index % hed->ColumnsPerLine;
-        hed->CaretLine = hed->Index / hed->ColumnsPerLine;
-      }
-      else
-      {
-        if (hed->InMid && hed->EditingField)
+        if (i0 != i1)
         {
-          buf = (PBYTE) LocalLock(hed->hBuffer);
-          if (buf)
-          {
-            MoveMemory(buf + hed->Index, buf + hed->Index + 1,
-                       bufsize - hed->Index - 1);
-            LocalUnlock(hed->hBuffer);
-          }
+            buf = (PBYTE) LocalLock(hed->hBuffer);
+            if (buf)
+            {
+                MoveMemory(buf + i0, buf + i1, bufsize - i1);
+                LocalUnlock(hed->hBuffer);
+            }
+            HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
+            hed->InMid = FALSE;
+            hed->Index = hed->SelStart = hed->SelEnd = i0;
+            hed->CaretCol = hed->Index % hed->ColumnsPerLine;
+            hed->CaretLine = hed->Index / hed->ColumnsPerLine;
         }
-        else if (hed->Index > 0)
+        else
         {
-          buf = (PBYTE) LocalLock(hed->hBuffer);
-          if (buf)
-          {
-            MoveMemory(buf + hed->Index - 1, buf + hed->Index,
-                       bufsize - hed->Index);
-            LocalUnlock(hed->hBuffer);
-          }
-          hed->Index--;
-          hed->SelStart = hed->SelEnd = hed->Index;
-          hed->CaretCol = hed->Index % hed->ColumnsPerLine;
-          hed->CaretLine = hed->Index / hed->ColumnsPerLine;
+            if (hed->InMid && hed->EditingField)
+            {
+                buf = (PBYTE) LocalLock(hed->hBuffer);
+                if (buf)
+                {
+                    MoveMemory(buf + hed->Index, buf + hed->Index + 1,
+                               bufsize - hed->Index - 1);
+                    LocalUnlock(hed->hBuffer);
+                }
+            }
+            else if (hed->Index > 0)
+            {
+                buf = (PBYTE) LocalLock(hed->hBuffer);
+                if (buf)
+                {
+                    MoveMemory(buf + hed->Index - 1, buf + hed->Index,
+                               bufsize - hed->Index);
+                    LocalUnlock(hed->hBuffer);
+                }
+                hed->Index--;
+                hed->SelStart = hed->SelEnd = hed->Index;
+                hed->CaretCol = hed->Index % hed->ColumnsPerLine;
+                hed->CaretLine = hed->Index / hed->ColumnsPerLine;
+            }
+            else
+                return TRUE;
+            HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1);
+            hed->InMid = FALSE;
         }
-        HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - 1);
-        hed->InMid = FALSE;
-      }
-      InvalidateRect(hed->hWndSelf, NULL, TRUE);
-      HEXEDIT_MoveCaret(hed, TRUE);
-      break;
-
-    case VK_LEFT:
-      if (hed->Index > 0)
-      {
-        hed->Index--;
-        if (GetAsyncKeyState(VK_SHIFT) < 0)
-          hed->SelEnd = hed->Index;
-        else
-          hed->SelStart = hed->SelEnd = hed->Index;
-        hed->CaretCol = hed->Index % hed->ColumnsPerLine;
-        hed->CaretLine = hed->Index / hed->ColumnsPerLine;
-        hed->InMid = FALSE;
         InvalidateRect(hed->hWndSelf, NULL, TRUE);
         HEXEDIT_MoveCaret(hed, TRUE);
-      }
-      break;
+        break;
+
+    case VK_LEFT:
+        if (hed->Index > 0)
+        {
+            hed->Index--;
+            if (GetAsyncKeyState(VK_SHIFT) < 0)
+                hed->SelEnd = hed->Index;
+            else
+                hed->SelStart = hed->SelEnd = hed->Index;
+            hed->CaretCol = hed->Index % hed->ColumnsPerLine;
+            hed->CaretLine = hed->Index / hed->ColumnsPerLine;
+            hed->InMid = FALSE;
+            InvalidateRect(hed->hWndSelf, NULL, TRUE);
+            HEXEDIT_MoveCaret(hed, TRUE);
+        }
+        break;
 
     case VK_RIGHT:
-      if (hed->Index < (INT)bufsize)
-      {
-        hed->Index++;
-        if (GetAsyncKeyState(VK_SHIFT) < 0)
-          hed->SelEnd = hed->Index;
-        else
-          hed->SelStart = hed->SelEnd = hed->Index;
-        hed->CaretCol = hed->Index % hed->ColumnsPerLine;
-        hed->CaretLine = hed->Index / hed->ColumnsPerLine;
-        hed->InMid = FALSE;
-        InvalidateRect(hed->hWndSelf, NULL, TRUE);
-        HEXEDIT_MoveCaret(hed, TRUE);
-      }
-      break;
+        if (hed->Index < (INT)bufsize)
+        {
+            hed->Index++;
+            if (GetAsyncKeyState(VK_SHIFT) < 0)
+                hed->SelEnd = hed->Index;
+            else
+                hed->SelStart = hed->SelEnd = hed->Index;
+            hed->CaretCol = hed->Index % hed->ColumnsPerLine;
+            hed->CaretLine = hed->Index / hed->ColumnsPerLine;
+            hed->InMid = FALSE;
+            InvalidateRect(hed->hWndSelf, NULL, TRUE);
+            HEXEDIT_MoveCaret(hed, TRUE);
+        }
+        break;
 
     case VK_UP:
-      if (hed->Index >= hed->ColumnsPerLine)
-      {
-        hed->Index -= hed->ColumnsPerLine;
-        if (GetAsyncKeyState(VK_SHIFT) < 0)
-          hed->SelEnd = hed->Index;
+        if (hed->Index >= hed->ColumnsPerLine)
+        {
+            hed->Index -= hed->ColumnsPerLine;
+            if (GetAsyncKeyState(VK_SHIFT) < 0)
+                hed->SelEnd = hed->Index;
+            else
+                hed->SelStart = hed->SelEnd = hed->Index;
+            hed->CaretCol = hed->Index % hed->ColumnsPerLine;
+            hed->CaretLine = hed->Index / hed->ColumnsPerLine;
+            hed->InMid = FALSE;
+            InvalidateRect(hed->hWndSelf, NULL, TRUE);
+            HEXEDIT_MoveCaret(hed, TRUE);
+        }
+        break;
+
+    case VK_DOWN:
+        if (hed->Index + hed->ColumnsPerLine <= (INT) bufsize)
+            hed->Index += hed->ColumnsPerLine;
         else
-          hed->SelStart = hed->SelEnd = hed->Index;
+            hed->Index = bufsize;
         hed->CaretCol = hed->Index % hed->ColumnsPerLine;
         hed->CaretLine = hed->Index / hed->ColumnsPerLine;
+        if (GetAsyncKeyState(VK_SHIFT) < 0)
+            hed->SelEnd = hed->Index;
+        else
+            hed->SelStart = hed->SelEnd = hed->Index;
         hed->InMid = FALSE;
         InvalidateRect(hed->hWndSelf, NULL, TRUE);
         HEXEDIT_MoveCaret(hed, TRUE);
-      }
-      break;
+        break;
 
-    case VK_DOWN:
-      if (hed->Index + hed->ColumnsPerLine <= (INT) bufsize)
-        hed->Index += hed->ColumnsPerLine;
-      else
-        hed->Index = bufsize;
-      hed->CaretCol = hed->Index % hed->ColumnsPerLine;
-      hed->CaretLine = hed->Index / hed->ColumnsPerLine;
-      if (GetAsyncKeyState(VK_SHIFT) < 0)
-        hed->SelEnd = hed->Index;
-      else
-        hed->SelStart = hed->SelEnd = hed->Index;
-      hed->InMid = FALSE;
-      InvalidateRect(hed->hWndSelf, NULL, TRUE);
-      HEXEDIT_MoveCaret(hed, TRUE);
-      break;
-  }
+    default:
+        return TRUE;
+    }
 
-  return FALSE;
+    return FALSE;
 }
 
 static BOOL
-HEXEDIT_WM_CHAR(PHEXEDIT_DATA hed, WCHAR ch)
+HEXEDIT_WM_CHAR(PHEXEDIT_DATA hed, WCHAR wch)
 {
-  size_t bufsize;
-  PBYTE buf;
-  INT i0, i1;
-
-  bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
-  if (hed->SelStart < hed->SelEnd)
-  {
-    i0 = hed->SelStart;
-    i1 = hed->SelEnd;
-  }
-  else
-  {
-    i0 = hed->SelEnd;
-    i1 = hed->SelStart;
-  }
-  if (!hed->EditingField)
-  {
-    if (0x20 <= ch && ch <= 0xFF)
-    {
-      if (hed->SelStart != hed->SelEnd)
-      {
-        buf = (PBYTE) LocalLock(hed->hBuffer);
-        if (buf)
-        {
-          MoveMemory(buf + i0, buf + i1, bufsize - i1);
-          LocalUnlock(hed->hBuffer);
-        }
-        HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
-        hed->InMid = FALSE;
-        bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
-        hed->Index = hed->SelStart = hed->SelEnd = i0;
-      }
-      HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize + 1);
-      buf = (PBYTE) LocalLock(hed->hBuffer);
-      if (buf)
-      {
-        MoveMemory(buf + hed->Index + 1, buf + hed->Index,
-                   bufsize - hed->Index);
-        buf[hed->Index] = ch;
-        LocalUnlock(hed->hBuffer);
-      }
-      hed->Index++;
-      hed->CaretCol = hed->Index % hed->ColumnsPerLine;
-      hed->CaretLine = hed->Index / hed->ColumnsPerLine;
-      InvalidateRect(hed->hWndSelf, NULL, TRUE);
-      HEXEDIT_MoveCaret(hed, TRUE);
-      return FALSE;
-    }
-  }
-  else
-  {
-    if (('0' <= ch && ch <= '9') || ('A' <= ch && ch <= 'F') ||
-        ('a' <= ch && ch <= 'f'))
-    {
-      if (hed->SelStart != hed->SelEnd)
-      {
-        buf = (PBYTE) LocalLock(hed->hBuffer);
-        if (buf)
-        {
-          MoveMemory(buf + i0, buf + i1, bufsize - i1);
-          LocalUnlock(hed->hBuffer);
-        }
-        HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
-        hed->InMid = FALSE;
-        bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
-        hed->Index = hed->SelStart = hed->SelEnd = i0;
-      }
-      if (hed->InMid)
-      {
-        buf = (PBYTE) LocalLock(hed->hBuffer);
-        if (buf)
+    size_t bufsize;
+    CHAR ch = (CHAR)wch; // keep the lowest octet.
+    PBYTE buf;
+    INT i0, i1;
+
+    bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
+    if (hed->SelStart < hed->SelEnd)
+    {
+        i0 = hed->SelStart;
+        i1 = hed->SelEnd;
+    }
+    else
+    {
+        i0 = hed->SelEnd;
+        i1 = hed->SelStart;
+    }
+    if (!hed->EditingField)
+    {
+        if (0x20 <= ch && ch <= 0xFF)
         {
-          if ('0' <= ch && ch <= '9')
-            buf[hed->Index] |= ch - '0';
-          else if ('A' <= ch && ch <= 'F')
-            buf[hed->Index] |= ch + 10 - 'A';
-          else if ('a' <= ch && ch <= 'f')
-            buf[hed->Index] |= ch + 10 - 'a';
-          LocalUnlock(hed->hBuffer);
+            if (hed->SelStart != hed->SelEnd)
+            {
+                buf = (PBYTE) LocalLock(hed->hBuffer);
+                if (buf)
+                {
+                    MoveMemory(buf + i0, buf + i1, bufsize - i1);
+                    LocalUnlock(hed->hBuffer);
+                }
+                HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
+                hed->InMid = FALSE;
+                bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
+                hed->Index = hed->SelStart = hed->SelEnd = i0;
+            }
+            HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize + 1);
+            buf = (PBYTE) LocalLock(hed->hBuffer);
+            if (buf)
+            {
+                MoveMemory(buf + hed->Index + 1, buf + hed->Index,
+                           bufsize - hed->Index);
+                buf[hed->Index] = ch;
+                LocalUnlock(hed->hBuffer);
+            }
+            hed->Index++;
+            hed->CaretCol = hed->Index % hed->ColumnsPerLine;
+            hed->CaretLine = hed->Index / hed->ColumnsPerLine;
+            InvalidateRect(hed->hWndSelf, NULL, TRUE);
+            HEXEDIT_MoveCaret(hed, TRUE);
+            return FALSE;
         }
-        hed->InMid = FALSE;
-        hed->Index++;
-      }
-      else
-      {
-        HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize + 1);
-        buf = (PBYTE) LocalLock(hed->hBuffer);
-        if (buf)
+    }
+    else
+    {
+        if (('0' <= ch && ch <= '9') || ('A' <= ch && ch <= 'F') ||
+                ('a' <= ch && ch <= 'f'))
         {
-          MoveMemory(buf + hed->Index + 1, buf + hed->Index,
-                     bufsize - hed->Index);
-          if ('0' <= ch && ch <= '9')
-            buf[hed->Index] = (ch - '0') << 4;
-          else if ('A' <= ch && ch <= 'F')
-            buf[hed->Index] = (ch + 10 - 'A') << 4;
-          else if ('a' <= ch && ch <= 'f')
-            buf[hed->Index] = (ch + 10 - 'a') << 4;
-          LocalUnlock(hed->hBuffer);
+            if (hed->SelStart != hed->SelEnd)
+            {
+                buf = (PBYTE) LocalLock(hed->hBuffer);
+                if (buf)
+                {
+                    MoveMemory(buf + i0, buf + i1, bufsize - i1);
+                    LocalUnlock(hed->hBuffer);
+                }
+                HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize - (i1 - i0));
+                hed->InMid = FALSE;
+                bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
+                hed->Index = hed->SelStart = hed->SelEnd = i0;
+            }
+            if (hed->InMid)
+            {
+                buf = (PBYTE) LocalLock(hed->hBuffer);
+                if (buf)
+                {
+                    if ('0' <= ch && ch <= '9')
+                        buf[hed->Index] |= ch - '0';
+                    else if ('A' <= ch && ch <= 'F')
+                        buf[hed->Index] |= ch + 10 - 'A';
+                    else if ('a' <= ch && ch <= 'f')
+                        buf[hed->Index] |= ch + 10 - 'a';
+                    LocalUnlock(hed->hBuffer);
+                }
+                hed->InMid = FALSE;
+                hed->Index++;
+            }
+            else
+            {
+                HexEdit_SetMaxBufferSize(hed->hWndSelf, bufsize + 1);
+                buf = (PBYTE) LocalLock(hed->hBuffer);
+                if (buf)
+                {
+                    MoveMemory(buf + hed->Index + 1, buf + hed->Index,
+                               bufsize - hed->Index);
+                    if ('0' <= ch && ch <= '9')
+                        buf[hed->Index] = (ch - '0') << 4;
+                    else if ('A' <= ch && ch <= 'F')
+                        buf[hed->Index] = (ch + 10 - 'A') << 4;
+                    else if ('a' <= ch && ch <= 'f')
+                        buf[hed->Index] = (ch + 10 - 'a') << 4;
+                    LocalUnlock(hed->hBuffer);
+                }
+                hed->InMid = TRUE;
+            }
+            hed->CaretCol = hed->Index % hed->ColumnsPerLine;
+            hed->CaretLine = hed->Index / hed->ColumnsPerLine;
+            InvalidateRect(hed->hWndSelf, NULL, TRUE);
+            HEXEDIT_MoveCaret(hed, TRUE);
+            return FALSE;
         }
-        hed->InMid = TRUE;
-      }
-      hed->CaretCol = hed->Index % hed->ColumnsPerLine;
-      hed->CaretLine = hed->Index / hed->ColumnsPerLine;
-      InvalidateRect(hed->hWndSelf, NULL, TRUE);
-      HEXEDIT_MoveCaret(hed, TRUE);
-      return FALSE;
-    }
-  }
-  return TRUE;
+    }
+    return TRUE;
 }
 
 static LRESULT
 HEXEDIT_WM_SIZE(PHEXEDIT_DATA hed, DWORD sType, WORD NewWidth, WORD NewHeight)
 {
-  UNREFERENCED_PARAMETER(sType);
-  UNREFERENCED_PARAMETER(NewHeight);
-  UNREFERENCED_PARAMETER(NewWidth);
-  HEXEDIT_Update(hed);
-  return 0;
+    UNREFERENCED_PARAMETER(sType);
+    UNREFERENCED_PARAMETER(NewHeight);
+    UNREFERENCED_PARAMETER(NewWidth);
+    HEXEDIT_Update(hed);
+    return 0;
+}
+
+static VOID
+HEXEDIT_WM_CONTEXTMENU(PHEXEDIT_DATA hed, INT x, INT y)
+{
+    HMENU hMenu;
+    RECT rc;
+
+    if (x == -1 && y == -1)
+    {
+        GetWindowRect(hed->hWndSelf, &rc);
+        x = rc.left;
+        y = rc.top;
+    }
+
+    hMenu = GetSubMenu(hPopupMenus, PM_HEXEDIT);
+    if (hed->SelStart == hed->SelEnd)
+    {
+        EnableMenuItem(hMenu, ID_HEXEDIT_CUT, MF_GRAYED);
+        EnableMenuItem(hMenu, ID_HEXEDIT_COPY, MF_GRAYED);
+        EnableMenuItem(hMenu, ID_HEXEDIT_PASTE, MF_GRAYED);
+        EnableMenuItem(hMenu, ID_HEXEDIT_DELETE, MF_GRAYED);
+    }
+    else
+    {
+        EnableMenuItem(hMenu, ID_HEXEDIT_CUT, MF_ENABLED);
+        EnableMenuItem(hMenu, ID_HEXEDIT_COPY, MF_ENABLED);
+        EnableMenuItem(hMenu, ID_HEXEDIT_PASTE, MF_ENABLED);
+        EnableMenuItem(hMenu, ID_HEXEDIT_DELETE, MF_ENABLED);
+    }
+
+    SetForegroundWindow(hed->hWndSelf);
+    TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, x, y, 0, hed->hWndSelf, NULL);
+    PostMessageW(hed->hWndSelf, WM_NULL, 0, 0);
 }
 
 INT_PTR CALLBACK
 HexEditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
-  PHEXEDIT_DATA hed;
-  POINTS p;
+    PHEXEDIT_DATA hed;
+    POINTS p;
 
-  hed = (PHEXEDIT_DATA)(LONG_PTR)GetWindowLongPtr(hWnd, (DWORD_PTR)0);
-  switch(uMsg)
-  {
+    hed = (PHEXEDIT_DATA)(LONG_PTR)GetWindowLongPtr(hWnd, (DWORD_PTR)0);
+    switch(uMsg)
+    {
     case WM_ERASEBKGND:
-      return TRUE;
+        return TRUE;
 
     case WM_PAINT:
-      return HEXEDIT_WM_PAINT(hed);
+        return HEXEDIT_WM_PAINT(hed);
 
     case WM_KEYDOWN:
-      return HEXEDIT_WM_KEYDOWN(hed, (INT)wParam);
+        return HEXEDIT_WM_KEYDOWN(hed, (INT)wParam);
 
     case WM_CHAR:
-      return HEXEDIT_WM_CHAR(hed, (WCHAR)wParam);
+        return HEXEDIT_WM_CHAR(hed, (WCHAR)wParam);
 
     case WM_VSCROLL:
-      return HEXEDIT_WM_VSCROLL(hed, HIWORD(wParam), LOWORD(wParam));
+        return HEXEDIT_WM_VSCROLL(hed, HIWORD(wParam), LOWORD(wParam));
 
     case WM_SIZE:
-      return HEXEDIT_WM_SIZE(hed, (DWORD)wParam, LOWORD(lParam), HIWORD(lParam));
+        return HEXEDIT_WM_SIZE(hed, (DWORD)wParam, LOWORD(lParam), HIWORD(lParam));
 
     case WM_LBUTTONDOWN:
     {
-      p.x = LOWORD(lParam);
-      p.y = HIWORD(lParam);
-      return HEXEDIT_WM_LBUTTONDOWN(hed, (INT)wParam, p);
+        p.x = LOWORD(lParam);
+        p.y = HIWORD(lParam);
+        return HEXEDIT_WM_LBUTTONDOWN(hed, (INT)wParam, p);
     }
 
     case WM_LBUTTONUP:
     {
-      p.x = LOWORD(lParam);
-      p.y = HIWORD(lParam);
-      return HEXEDIT_WM_LBUTTONUP(hed, (INT)wParam, p);
+        p.x = LOWORD(lParam);
+        p.y = HIWORD(lParam);
+        return HEXEDIT_WM_LBUTTONUP(hed, (INT)wParam, p);
     }
 
     case WM_MOUSEMOVE:
     {
-      p.x = LOWORD(lParam);
-      p.y = HIWORD(lParam);
-      return HEXEDIT_WM_MOUSEMOVE(hed, (INT)wParam, p);
+        p.x = LOWORD(lParam);
+        p.y = HIWORD(lParam);
+        return HEXEDIT_WM_MOUSEMOVE(hed, (INT)wParam, p);
     }
 
     case WM_MOUSEWHEEL:
     {
-      UINT nScrollLines = 3;
-      int delta = 0;
+        UINT nScrollLines = 3;
+        int delta = 0;
 
-      SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &nScrollLines, 0);
-      delta -= (SHORT)HIWORD(wParam);
-      if(abs(delta) >= WHEEL_DELTA && nScrollLines != 0)
-      {
-        p.x = LOWORD(lParam);
-        p.y = HIWORD(lParam);
-        return HEXEDIT_WM_MOUSEWHEEL(hed, nScrollLines * (delta / WHEEL_DELTA), LOWORD(wParam), &p);
-      }
-      break;
+        SystemParametersInfoW(SPI_GETWHEELSCROLLLINES, 0, &nScrollLines, 0);
+        delta -= (SHORT)HIWORD(wParam);
+        if(abs(delta) >= WHEEL_DELTA && nScrollLines != 0)
+        {
+            p.x = LOWORD(lParam);
+            p.y = HIWORD(lParam);
+            return HEXEDIT_WM_MOUSEWHEEL(hed, nScrollLines * (delta / WHEEL_DELTA), LOWORD(wParam), &p);
+        }
+        break;
     }
 
     case HEM_LOADBUFFER:
-      return HEXEDIT_HEM_LOADBUFFER(hed, (PVOID)wParam, (DWORD)lParam);
+        return HEXEDIT_HEM_LOADBUFFER(hed, (PVOID)wParam, (DWORD)lParam);
 
     case HEM_COPYBUFFER:
-      return HEXEDIT_HEM_COPYBUFFER(hed, (PVOID)wParam, (DWORD)lParam);
+        return HEXEDIT_HEM_COPYBUFFER(hed, (PVOID)wParam, (DWORD)lParam);
 
     case HEM_SETMAXBUFFERSIZE:
-      return HEXEDIT_HEM_SETMAXBUFFERSIZE(hed, (DWORD)lParam);
+        return HEXEDIT_HEM_SETMAXBUFFERSIZE(hed, (DWORD)lParam);
 
     case WM_SETFOCUS:
-      return HEXEDIT_WM_SETFOCUS(hed);
+        return HEXEDIT_WM_SETFOCUS(hed);
 
     case WM_KILLFOCUS:
-      return HEXEDIT_WM_KILLFOCUS(hed);
+        return HEXEDIT_WM_KILLFOCUS(hed);
 
     case WM_GETDLGCODE:
-      return HEXEDIT_WM_GETDLGCODE((LPMSG)lParam);
+        return HEXEDIT_WM_GETDLGCODE((LPMSG)lParam);
 
     case WM_SETFONT:
-      return HEXEDIT_WM_SETFONT(hed, (HFONT)wParam, (BOOL)LOWORD(lParam));
+        return HEXEDIT_WM_SETFONT(hed, (HFONT)wParam, (BOOL)LOWORD(lParam));
 
     case WM_GETFONT:
-      return HEXEDIT_WM_GETFONT(hed);
+        return HEXEDIT_WM_GETFONT(hed);
 
     case WM_CREATE:
-      return HEXEDIT_WM_CREATE(hed);
+        return HEXEDIT_WM_CREATE(hed);
 
     case WM_NCCREATE:
-      if(!hed)
-      {
-        return HEXEDIT_WM_NCCREATE(hWnd, (CREATESTRUCT*)lParam);
-      }
-      break;
+        if(!hed)
+        {
+            return HEXEDIT_WM_NCCREATE(hWnd, (CREATESTRUCT*)lParam);
+        }
+        break;
 
     case WM_NCDESTROY:
-      if(hed)
-      {
-        return HEXEDIT_WM_NCDESTROY(hed);
-      }
-      break;
+        if(hed)
+        {
+            return HEXEDIT_WM_NCDESTROY(hed);
+        }
+        break;
 
     case WM_CONTEXTMENU:
-      /* FIXME: Implement Cut, Copy, Paste, Delete and Select All */
-      break;
+        HEXEDIT_WM_CONTEXTMENU(hed, (short)LOWORD(lParam), (short)HIWORD(lParam));
+        break;
 
     case WM_COMMAND:
-      /* FIXME: Implement Cut, Copy, Paste, Delete and Select All */
-      break;
-  }
+        switch(LOWORD(wParam))
+        {
+        case ID_HEXEDIT_CUT:
+            HEXEDIT_Cut(hed);
+            break;
+
+        case ID_HEXEDIT_COPY:
+            HEXEDIT_Copy(hed);
+            break;
+
+        case ID_HEXEDIT_PASTE:
+            HEXEDIT_Paste(hed);
+            break;
+
+        case ID_HEXEDIT_DELETE:
+            HEXEDIT_Delete(hed);
+            break;
+
+        case ID_HEXEDIT_SELECT_ALL:
+            HEXEDIT_SelectAll(hed);
+            break;
+        }
+        break;
+    }
 
-  return DefWindowProc(hWnd, uMsg, wParam, lParam);
+    return DefWindowProcW(hWnd, uMsg, wParam, lParam);
 }