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