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..bfd7767 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);