Dylan Smith : richedit: Added more conditional cursor changes.

Alexandre Julliard julliard at winehq.org
Thu Jul 10 08:58:21 CDT 2008


Module: wine
Branch: master
Commit: 7de6c2674a8a82d1169afbb1ceef5b5c0fc85780
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7de6c2674a8a82d1169afbb1ceef5b5c0fc85780

Author: Dylan Smith <dylan.ah.smith at gmail.com>
Date:   Wed Jul  9 09:36:12 2008 -0400

richedit: Added more conditional cursor changes.

Previously the cursor was either an IBEAM, or a reversed arrow when over
the selectionbar.

---

 dlls/riched20/caret.c  |   38 ++++++++++++++++++++++++++++++-----
 dlls/riched20/editor.c |   51 +++++++++++++++++++++++++++++++++++++++--------
 dlls/riched20/editor.h |    2 +-
 3 files changed, 75 insertions(+), 16 deletions(-)

diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 08e9036..da83c9d 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -814,11 +814,21 @@ int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor)
     + pCursor->pRun->member.run.nCharOfs + pCursor->nOffset;
 }
 
-static void ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *result, BOOL *is_eol)
+/* Finds the run and offset from the pixel position.
+ *
+ * x & y are pixel positions in virtual coordinates into the rich edit control,
+ * so client coordinates must first be adjusted by the scroll position.
+ *
+ * returns TRUE if the result was exactly under the cursor, otherwise returns
+ * FALSE, and result is set to the closest position to the coordinates.
+ */
+static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
+                            ME_Cursor *result, BOOL *is_eol)
 {
   ME_DisplayItem *p = editor->pBuffer->pFirst->member.para.next_para;
   ME_DisplayItem *last = NULL;
   int rx = 0;
+  BOOL isExact = TRUE;
 
   if (is_eol)
     *is_eol = 0;
@@ -857,6 +867,7 @@ static void ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *resu
     /* The position is below the last paragraph, so the last row will be used
      * rather than the end of the text, so the x position will be used to
      * determine the offset closest to the pixel position. */
+    isExact = FALSE;
     p = ME_FindItemBack(p, diStartRow);
     if (p != NULL){
       p = ME_FindItemFwd(p, diRun);
@@ -885,16 +896,18 @@ static void ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *resu
           result->pRun = ME_FindItemFwd(editor->pCursors[0].pRun, diRun);
           result->nOffset = 0;
         }
-        return;
+        return isExact;
       }
       break;
     case diStartRow:
+      isExact = FALSE;
       p = ME_FindItemFwd(p, diRun);
       if (is_eol) *is_eol = 1;
       rx = 0; /* FIXME not sure */
       goto found_here;
     case diParagraph:
     case diTextEnd:
+      isExact = FALSE;
       rx = 0; /* FIXME not sure */
       p = last;
       goto found_here;
@@ -905,24 +918,37 @@ static void ME_FindPixelPos(ME_TextEditor *editor, int x, int y, ME_Cursor *resu
   result->pRun = ME_FindItemBack(p, diRun);
   result->nOffset = 0;
   assert(result->pRun->member.run.nFlags & MERF_ENDPARA);
+  return FALSE;
 }
 
 
-int
-ME_CharFromPos(ME_TextEditor *editor, int x, int y)
+/* Returns the character offset closest to the pixel position
+ *
+ * x & y are pixel positions in client coordinates.
+ *
+ * isExact will be set to TRUE if the run is directly under the pixel
+ * position, FALSE if it not, unless isExact is set to NULL.
+ */
+int ME_CharFromPos(ME_TextEditor *editor, int x, int y, BOOL *isExact)
 {
   ME_Cursor cursor;
   RECT rc;
+  BOOL bResult;
 
   GetClientRect(editor->hWnd, &rc);
-  if (x < 0 || y < 0 || x >= rc.right || y >= rc.bottom)
+  if (x < 0 || y < 0 || x >= rc.right || y >= rc.bottom) {
+    if (isExact) *isExact = FALSE;
     return -1;
+  }
   y += ME_GetYScrollPos(editor);
-  ME_FindPixelPos(editor, x, y, &cursor, NULL);
+  bResult = ME_FindPixelPos(editor, x, y, &cursor, NULL);
+  if (isExact) *isExact = bResult;
   return (ME_GetParagraph(cursor.pRun)->member.para.nCharOfs
           + cursor.pRun->member.run.nCharOfs + cursor.nOffset);
 }
 
+
+
 /* Extends the selection with a word, line, or paragraph selection type.
  *
  * The selection is anchored by editor->pCursors[2-3] such that the text
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index b988372..2dd758a 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -1669,6 +1669,8 @@ static int ME_CalculateClickCount(HWND hWnd, UINT msg, WPARAM wParam,
 static BOOL ME_SetCursor(ME_TextEditor *editor)
 {
   POINT pt;
+  BOOL isExact;
+  int offset;
   DWORD messagePos = GetMessagePos();
   pt.x = (short)LOWORD(messagePos);
   pt.y = (short)HIWORD(messagePos);
@@ -1680,7 +1682,35 @@ static BOOL ME_SetCursor(ME_TextEditor *editor)
       SetCursor(hLeft);
       return TRUE;
   }
-  return FALSE;
+  offset = ME_CharFromPos(editor, pt.x, pt.y, &isExact);
+  if (isExact)
+  {
+      if (editor->AutoURLDetect_bEnable)
+      {
+          ME_Cursor cursor;
+          ME_Run *run;
+          ME_CursorFromCharOfs(editor, offset, &cursor);
+          run = &cursor.pRun->member.run;
+          if (editor->AutoURLDetect_bEnable &&
+              run->style->fmt.dwMask & CFM_LINK &&
+              run->style->fmt.dwEffects & CFE_LINK)
+          {
+              SetCursor(LoadCursorW(NULL, (WCHAR*)IDC_HAND));
+              return TRUE;
+          }
+      }
+      if (ME_IsSelection(editor))
+      {
+          int selStart, selEnd;
+          ME_GetSelection(editor, &selStart, &selEnd);
+          if (selStart <= offset && selEnd >= offset) {
+              SetCursor(LoadCursorW(NULL, (WCHAR*)IDC_ARROW));
+              return TRUE;
+          }
+      }
+  }
+  SetCursor(LoadCursorW(NULL, (WCHAR*)IDC_IBEAM));
+  return TRUE;
 }
 
 static BOOL ME_ShowContextMenu(ME_TextEditor *editor, int x, int y)
@@ -2986,7 +3016,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
   case EM_SETZOOM:
     return ME_SetZoom(editor, wParam, lParam);
   case EM_CHARFROMPOS:
-    return ME_CharFromPos(editor, ((POINTL *)lParam)->x, ((POINTL *)lParam)->y);
+    return ME_CharFromPos(editor, ((POINTL *)lParam)->x, ((POINTL *)lParam)->y, NULL);
   case EM_POSFROMCHAR:
   {
     ME_DisplayItem *pRun;
@@ -3040,8 +3070,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
     return 0;
   case WM_SETCURSOR:
   {
-    if (!ME_SetCursor(editor)) goto do_default;
-    return TRUE;
+    return ME_SetCursor(editor);
   }
   case WM_LBUTTONDBLCLK:
   case WM_LBUTTONDOWN:
@@ -3055,6 +3084,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
                    ME_CalculateClickCount(hWnd, msg, wParam, lParam));
     SetCapture(hWnd);
     ME_LinkNotify(editor,msg,wParam,lParam);
+    if (!ME_SetCursor(editor)) goto do_default;
     break;
   }
   case WM_MOUSEMOVE:
@@ -3064,6 +3094,9 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
     if (GetCapture() == hWnd)
       ME_MouseMove(editor, (short)LOWORD(lParam), (short)HIWORD(lParam));
     ME_LinkNotify(editor,msg,wParam,lParam);
+    /* Set cursor if mouse is captured, since WM_SETCURSOR won't be received. */
+    if (GetCapture() == hWnd)
+        ME_SetCursor(editor);
     break;
   case WM_LBUTTONUP:
     if (GetCapture() == hWnd)
@@ -3075,10 +3108,8 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
       return 0;
     else
     {
-      BOOL ret;
-      ret = ME_SetCursor(editor);
+      ME_SetCursor(editor);
       ME_LinkNotify(editor,msg,wParam,lParam);
-      if (!ret) goto do_default;
     }
     break;
   case WM_RBUTTONUP:
@@ -3202,6 +3233,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
           ME_InsertTextFromCursor(editor, 0, &wstr, 1, style);
         ME_ReleaseStyle(style);
         ME_CommitCoalescingUndo(editor);
+        SetCursor(NULL);
       }
 
       if (editor->AutoURLDetect_bEnable) ME_UpdateSelectionLinkAttribute(editor);
@@ -3504,6 +3536,7 @@ void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam
 {
   int x,y;
   ME_Cursor tmpCursor;
+  BOOL isExact;
   int nCharOfs; /* The start of the clicked text. Absolute character offset */
 
   ME_Run *tmpRun;
@@ -3511,8 +3544,8 @@ void ME_LinkNotify(ME_TextEditor *editor, UINT msg, WPARAM wParam, LPARAM lParam
   ENLINK info;
   x = (short)LOWORD(lParam);
   y = (short)HIWORD(lParam);
-  nCharOfs = ME_CharFromPos(editor, x, y);
-  if (nCharOfs < 0) return;
+  nCharOfs = ME_CharFromPos(editor, x, y, &isExact);
+  if (!isExact) return;
 
   ME_CursorFromCharOfs(editor, nCharOfs, &tmpCursor);
   tmpRun = &tmpCursor.pRun->member.run;
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 786191a..6e07331 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -180,7 +180,7 @@ void ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType);
 void ME_HideCaret(ME_TextEditor *ed);
 void ME_ShowCaret(ME_TextEditor *ed);
 void ME_MoveCaret(ME_TextEditor *ed);
-int ME_CharFromPos(ME_TextEditor *editor, int x, int y);
+int ME_CharFromPos(ME_TextEditor *editor, int x, int y, BOOL *isExact);
 void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum);
 void ME_MouseMove(ME_TextEditor *editor, int x, int y);
 void ME_DeleteTextAtCursor(ME_TextEditor *editor, int nCursor, int nChars);




More information about the wine-cvs mailing list