Commit in reactos/subsys/system/regedit on MAIN
hexedit.c+256-151.5 -> 1.6
some little fixes

reactos/subsys/system/regedit
hexedit.c 1.5 -> 1.6
diff -u -r1.5 -r1.6
--- hexedit.c	20 Jun 2004 19:26:59 -0000	1.5
+++ hexedit.c	20 Jun 2004 22:52:39 -0000	1.6
@@ -35,16 +35,29 @@
   DWORD ColumnsPerLine;
   DWORD nLines;
   DWORD nVisibleLines;
+  INT Position;
   INT LineHeight;
   INT CharWidth;
   HFONT hFont;
   
   INT LeftMargin;
-  INT TopMargin;
   INT AddressSpacing;
   INT SplitSpacing;
+  
+  BOOL EditingField;
+  INT CaretCol;
+  INT CaretLine;
 } HEXEDIT_DATA, *PHEXEDIT_DATA;
 
+/* 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)
+
 LRESULT WINAPI HexEditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
 ATOM
@@ -55,7 +68,7 @@
   
   ZeroMemory(&WndClass, sizeof(WNDCLASSEX));
   WndClass.cbSize = sizeof(WNDCLASSEX);
-  WndClass.style = CS_DBLCLKS;// | CS_PARENTDC;
+  WndClass.style = CS_DBLCLKS;
   WndClass.lpfnWndProc = (WNDPROC)HexEditWndProc;
   WndClass.cbWndExtra = sizeof(PHEXEDIT_DATA);
   WndClass.hInstance = hInstance;
@@ -76,10 +89,33 @@
 /*** Helper functions *********************************************************/
 
 static VOID
-HEXEDIT_MoveCaret(PHEXEDIT_DATA hed, INT Col, INT Line)
+HEXEDIT_MoveCaret(PHEXEDIT_DATA hed, INT Line, INT Column, BOOL HexDump)
 {
-  /* FIXME - include the scroll position */
-  SetCaretPos(hed->LeftMargin + (Col * hed->CharWidth), hed->TopMargin + (Line * hed->LineHeight));
+  SCROLLINFO si;
+  
+  si.cbSize = sizeof(SCROLLINFO);
+  si.fMask = SIF_POS;
+  GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+  
+  if(si.nPos > Line)
+  {
+    si.nPos = Line;
+    SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
+    GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+    InvalidateRect(hed->hWndSelf, NULL, TRUE);
+  }
+  else if((Line - si.nPos) > hed->nVisibleLines)
+  {
+    si.nPos += (Line - si.nPos);
+    SetScrollInfo(hed->hWndSelf, SB_VERT, &si, TRUE);
+    GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+    InvalidateRect(hed->hWndSelf, NULL, TRUE);
+  }
+  
+  if(HexDump)
+    SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing) * hed->CharWidth) - 2, (Line - si.nPos) * hed->LineHeight);
+  else
+    SetCaretPos(hed->LeftMargin + ((4 + hed->AddressSpacing + hed->SplitSpacing + (3 * hed->ColumnsPerLine)) * hed->CharWidth) - 2, (Line - si.nPos) * hed->LineHeight);
 }
 
 static VOID
@@ -136,6 +172,7 @@
   PBYTE buf, current, end, line;
   UINT bufsize;
   TCHAR hex[3], addr[17];
+  RECT rct;
   
   if(hed->hBuffer)
   {
@@ -157,24 +194,35 @@
     current = buf + linestart;
     Last = min(hed->nLines - ScrollPos, Last);
     
-    for(; First <= Last && current < end; First++)
+    while(First <= Last && current < end)
     {
-      int slen;
+      DWORD dh;
       
       dx = hed->LeftMargin;
       
       /* draw address */
       _stprintf(addr, _T("%04X"), linestart);
       TextOut(hDC, dx, dy, addr, 4);
-      dx += (4 + hed->AddressSpacing) * hed->CharWidth;
+      
+      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;
       for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
       {
+        rct.left += dh;
+        rct.right += dh;
+        
 	_stprintf(hex, _T("%02X"), *(current++));
-	TextOut(hDC, dx, dy, hex, 2);
-	dx += (3 * hed->CharWidth);
+	ExtTextOut(hDC, dx, dy, ETO_OPAQUE, &rct, hex, 2, NULL);
+	dx += dh;
       }
       
       /* draw ascii map */
@@ -183,19 +231,117 @@
       for(x = 0; x < hed->ColumnsPerLine && current < end; x++)
       {
 	_stprintf(hex, _T("%C"), *(current++));
-	hex[0] = ((hex[0] & _T('\x007f')) > _T(' ') ? hex[0] : _T('.'));
+	hex[0] = ((hex[0] & _T('\x007f')) >= _T(' ') ? hex[0] : _T('.'));
 	TextOut(hDC, dx, dy, hex, 1);
 	dx += hed->CharWidth;
       }
       
       dy += hed->LineHeight;
       linestart += hed->ColumnsPerLine;
+      First++;
     }
   }
   
   LocalUnlock(hed->hBuffer);
 }
 
+static DWORD
+HEXEDIT_HitRegionTest(PHEXEDIT_DATA hed, POINTS pt, POINTS *ptClient)
+{
+  WINDOWINFO wi;
+  int d, x;
+  
+  wi.cbSize = sizeof(WINDOWINFO);
+  GetWindowInfo(hed->hWndSelf, &wi);
+  
+  x = pt.x - wi.rcClient.left;
+  if(ptClient)
+  {
+    ptClient->x = x;
+    ptClient->y = pt.y - wi.rcClient.top;
+  }
+  
+  if(x <= hed->LeftMargin)
+  {
+    return HEHT_LEFTMARGIN;
+  }
+  
+  x -= hed->LeftMargin;
+  d = (4 * hed->CharWidth);
+  if(x <= d)
+  {
+    return HEHT_ADDRESS;
+  }
+  
+  x -= d;
+  d = (hed->AddressSpacing * hed->CharWidth);
+  if(x <= d)
+  {
+    return HEHT_ADDRESSSPACING;
+  }
+  
+  x -= d;
+  d = (3 * hed->ColumnsPerLine * hed->CharWidth);
+  if(x <= d)
+  {
+    return HEHT_HEXDUMP;
+  }
+  
+  x -= d;
+  d = (hed->SplitSpacing * hed->CharWidth);
+  if(x <= d)
+  {
+    return HEHT_HEXDUMPSPACING;
+  }
+  
+  x -= d;
+  d = (hed->ColumnsPerLine * hed->CharWidth);
+  if(x <= d)
+  {
+    return HEHT_ASCIIDUMP;
+  }
+  
+  return HEHT_RIGHTMARGIN;
+}
+
+static DWORD
+HEXEDIT_PositionFromPoint(PHEXEDIT_DATA hed, POINTS pt, DWORD *Hit)
+{
+  SCROLLINFO si;
+  POINTS ptClient;
+  DWORD Line;
+  
+  *Hit = HEXEDIT_HitRegionTest(hed, pt, &ptClient);
+  
+  si.cbSize = sizeof(SCROLLINFO);
+  si.fMask = SIF_POS;
+  GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
+  
+  if(hed->LineHeight > 0)
+  {
+    Line = min(si.nPos + (ptClient.y / hed->LineHeight), hed->nLines);
+  }
+  else
+    return 0;
+  
+  switch(*Hit)
+  {
+    case HEHT_LEFTMARGIN:
+    case HEHT_ADDRESS:
+    case HEHT_ADDRESSSPACING:
+      return Line * hed->ColumnsPerLine;
+    
+    case HEHT_HEXDUMP:
+      return 0;
+    
+    case HEHT_ASCIIDUMP:
+      return 0;
+    
+    case HEHT_RIGHTMARGIN:
+      return (Line + 1) * hed->ColumnsPerLine;
+  }
+}
+
 /*** Control specific messages ************************************************/
 
 static LRESULT
@@ -222,6 +368,7 @@
       else
       {
         hed->hBuffer = LocalFree(hed->hBuffer);
+        hed->Position = 0;
         HEXEDIT_Update(hed);
         
         return 0;
@@ -244,11 +391,13 @@
       LocalUnlock(hed->hBuffer);
     }
     
+    hed->Position = 0;
     HEXEDIT_Update(hed);
     return Size;
   }
   else if(hed->hBuffer)
   {
+    hed->Position = 0;
     hed->hBuffer = LocalFree(hed->hBuffer);
     HEXEDIT_Update(hed);
   }
@@ -318,9 +467,9 @@
   
   hed->ColumnsPerLine = 8;
   hed->LeftMargin = 2;
-  hed->TopMargin = 2;
   hed->AddressSpacing = 2;
   hed->SplitSpacing = 2;
+  hed->EditingField = TRUE; /* in hexdump field */
   
   SetWindowLong(hWnd, 0, (LONG)hed);
   
@@ -351,8 +500,8 @@
 static LRESULT
 HEXEDIT_WM_SETFOCUS(PHEXEDIT_DATA hed)
 {
-  CreateCaret(hed->hWndSelf, 0, 2, hed->LineHeight);
-  HEXEDIT_MoveCaret(hed, 0, 0);
+  CreateCaret(hed->hWndSelf, 0, 1, hed->LineHeight);
+  HEXEDIT_MoveCaret(hed, hed->CaretLine, hed->CaretCol, hed->EditingField);
   ShowCaret(hed->hWndSelf);
   return 0;
 }
@@ -471,6 +620,7 @@
   DWORD nLines, nFirst;
   HFONT hOldFont;
   HDC hTempDC;
+  DWORD height;
   
   if(GetUpdateRect(hed->hWndSelf, &rc, FALSE) && (hed->LineHeight > 0))
   {
@@ -479,7 +629,12 @@
     si.fMask = SIF_POS;
     GetScrollInfo(hed->hWndSelf, SB_VERT, &si);
     
-    nLines = (rc.bottom - rc.top) / hed->LineHeight;
+    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;
@@ -543,6 +698,86 @@
   return 0;
 }
 
+static LRESULT
+HEXEDIT_WM_SETCURSOR(PHEXEDIT_DATA hed)
+{
+  POINTS pt;
+  DWORD Hit, Pos;
+  
+  Pos = GetMessagePos();
+  pt = MAKEPOINTS(Pos);
+  Hit = HEXEDIT_HitRegionTest(hed, pt, NULL);
+  
+  switch(Hit)
+  {
+    case HEHT_HEXDUMP:
+    case HEHT_HEXDUMPSPACING:
+    case HEHT_ASCIIDUMP:
+      SetCursor(LoadCursor(0, MAKEINTRESOURCE(IDC_IBEAM)));
+      break;
+    
+    default:
+      SetCursor(LoadCursor(0, MAKEINTRESOURCE(IDC_ARROW)));
+      break;
+  }
+  return TRUE;
+}
+
+static BOOL
+HEXEDIT_WM_KEYDOWN(PHEXEDIT_DATA hed, INT VkCode)
+{
+  DWORD bufsize;
+  BOOL shift, control, handled;
+  
+  if(GetKeyState(VK_MENU) & 0x8000)
+  {
+    return FALSE;
+  }
+  
+  shift = GetKeyState(VK_SHIFT) & 0x8000;
+  control = GetKeyState(VK_CONTROL) & 0x8000;
+  
+  bufsize = (hed->hBuffer ? LocalSize(hed->hBuffer) : 0);
+  handled = FALSE;
+  
+  switch(VkCode)
+  {
+    case VK_LEFT:MessageBox(0, L"", L"", 0);
+      if(hed->Position > 0)
+      {
+        if(--hed->CaretCol < 0)
+	{
+	  hed->CaretLine--;
+	  hed->CaretCol = hed->ColumnsPerLine;
+	}
+	else
+	  hed->Position--;
+	
+	HEXEDIT_MoveCaret(hed, hed->CaretLine, hed->CaretCol, hed->EditingField);
+      }
+      handled = TRUE;
+      break;
+    
+    case VK_RIGHT:
+      if(hed->Position < bufsize)
+      {
+        if(++hed->CaretCol > hed->ColumnsPerLine)
+	{
+	  hed->CaretLine = 0;
+	  hed->CaretLine++;
+	}
+	else
+	  hed->Position++;
+	
+	HEXEDIT_MoveCaret(hed, hed->CaretLine, hed->CaretCol, hed->EditingField);
+      }
+      handled = TRUE;
+      break;
+  }
+  
+  return FALSE;
+}
+
 LRESULT
 WINAPI
 HexEditWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
@@ -558,6 +793,12 @@
     case WM_PAINT:
       return HEXEDIT_WM_PAINT(hed);
     
+    case WM_SETCURSOR:
+      return HEXEDIT_WM_SETCURSOR(hed);
+    
+    case WM_KEYDOWN:
+      return HEXEDIT_WM_KEYDOWN(hed, (INT)wParam);
+    
     case WM_VSCROLL:
       return HEXEDIT_WM_VSCROLL(hed, HIWORD(wParam), LOWORD(wParam));
     
CVSspam 0.2.8