riched20: Initial word break procedure implementation
Phil Krylov
phil at newstar.rinet.ru
Wed Jan 11 20:52:51 CST 2006
ChangeLog:
Implemented initial support for word break callback procedures in riched20.
---
dlls/riched20/caret.c | 101 +++++++++++++++++++++++++++++++++++++++++++++--
dlls/riched20/editor.c | 20 +++++++--
dlls/riched20/editor.h | 3 +
dlls/riched20/editstr.h | 1
dlls/riched20/string.c | 48 ++++++++++++++++++++++
5 files changed, 161 insertions(+), 12 deletions(-)
f62baa4b4517f74426a08d477b6dc744f03cc4b7
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index a4232f6..74e17e0 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -2,6 +2,7 @@
* RichEdit - Caret and selection functions.
*
* Copyright 2004 by Krzysztof Foltman
+ * Copyright 2005 by Phil Krylov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -491,6 +492,90 @@ ME_MoveCursorChars(ME_TextEditor *editor
}
+static BOOL
+ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
+{
+ ME_DisplayItem *pRun = cursor->pRun, *pOtherRun;
+ int nOffset = cursor->nOffset;
+
+ if (nRelOfs == -1)
+ {
+ /* Backward movement */
+ while (TRUE)
+ {
+ nOffset = ME_CallWordBreakProc(editor, pRun->member.run.strText,
+ nOffset, WB_MOVEWORDLEFT);
+ if (nOffset)
+ break;
+ pOtherRun = ME_FindItemBack(pRun, diRunOrParagraph);
+ if (pOtherRun->type == diRun)
+ {
+ if (ME_CallWordBreakProc(editor, pOtherRun->member.run.strText,
+ pOtherRun->member.run.strText->nLen - 1,
+ WB_ISDELIMITER)
+ && !(pRun->member.run.nFlags & MERF_ENDPARA)
+ && !(cursor->pRun == pRun && cursor->nOffset == 0)
+ && !ME_CallWordBreakProc(editor, pRun->member.run.strText, 0,
+ WB_ISDELIMITER))
+ break;
+ pRun = pOtherRun;
+ nOffset = pOtherRun->member.run.strText->nLen;
+ }
+ else if (pOtherRun->type == diParagraph)
+ {
+ if (cursor->pRun == pRun && cursor->nOffset == 0)
+ {
+ /* Paragraph breaks are treated as separate words */
+ if (pOtherRun->member.para.prev_para->type == diTextStart)
+ return FALSE;
+ pRun = ME_FindItemBack(pOtherRun, diRunOrParagraph);
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Forward movement */
+ BOOL last_delim = FALSE;
+
+ while (TRUE)
+ {
+ if (last_delim && !ME_CallWordBreakProc(editor, pRun->member.run.strText,
+ nOffset, WB_ISDELIMITER))
+ break;
+ nOffset = ME_CallWordBreakProc(editor, pRun->member.run.strText,
+ nOffset, WB_MOVEWORDRIGHT);
+ if (nOffset < pRun->member.run.strText->nLen)
+ break;
+ pOtherRun = ME_FindItemFwd(pRun, diRunOrParagraphOrEnd);
+ if (pOtherRun->type == diRun)
+ {
+ last_delim = ME_CallWordBreakProc(editor, pRun->member.run.strText,
+ nOffset - 1, WB_ISDELIMITER);
+ pRun = pOtherRun;
+ nOffset = 0;
+ }
+ else if (pOtherRun->type == diParagraph)
+ {
+ if (cursor->pRun == pRun)
+ pRun = ME_FindItemFwd(pOtherRun, diRun);
+ nOffset = 0;
+ break;
+ }
+ else /* diTextEnd */
+ {
+ if (cursor->pRun == pRun)
+ return FALSE;
+ nOffset = 0;
+ break;
+ }
+ }
+ }
+ cursor->pRun = pRun;
+ cursor->nOffset = nOffset;
+ return TRUE;
+}
int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor)
@@ -1032,7 +1117,7 @@ void ME_SendSelChange(ME_TextEditor *edi
BOOL
-ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend)
+ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
{
int nCursor = 0;
ME_Cursor *p = &editor->pCursors[nCursor];
@@ -1046,11 +1131,17 @@ ME_ArrowKey(ME_TextEditor *editor, int n
switch(nVKey) {
case VK_LEFT:
editor->bCaretAtEnd = 0;
- success = ME_MoveCursorChars(editor, &tmp_curs, -1);
+ if (ctrl)
+ success = ME_MoveCursorWords(editor, &tmp_curs, -1);
+ else
+ success = ME_MoveCursorChars(editor, &tmp_curs, -1);
break;
case VK_RIGHT:
editor->bCaretAtEnd = 0;
- success = ME_MoveCursorChars(editor, &tmp_curs, +1);
+ if (ctrl)
+ success = ME_MoveCursorWords(editor, &tmp_curs, +1);
+ else
+ success = ME_MoveCursorChars(editor, &tmp_curs, +1);
break;
case VK_UP:
ME_MoveCursorLines(editor, &tmp_curs, -1);
@@ -1065,7 +1156,7 @@ ME_ArrowKey(ME_TextEditor *editor, int n
ME_ArrowPageDown(editor, &tmp_curs);
break;
case VK_HOME: {
- if (GetKeyState(VK_CONTROL)<0)
+ if (ctrl)
ME_ArrowCtrlHome(editor, &tmp_curs);
else
ME_ArrowHome(editor, &tmp_curs);
@@ -1073,7 +1164,7 @@ ME_ArrowKey(ME_TextEditor *editor, int n
break;
}
case VK_END:
- if (GetKeyState(VK_CONTROL)<0)
+ if (ctrl)
ME_ArrowCtrlEnd(editor, &tmp_curs);
else
ME_ArrowEnd(editor, &tmp_curs);
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 723b69b..98ffd9c 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -71,7 +71,7 @@
? + EM_GETTEXTRANGE (ANSI&Unicode)
- EM_GETTYPOGRAPHYOPTIONS 3.0
- EM_GETUNDONAME
- - EM_GETWORDBREAKPROC
+ + EM_GETWORDBREAKPROC
- EM_GETWORDBREAKPROCEX
- EM_GETWORDWRAPMODE 1.0asian
+ EM_GETZOOM 3.0
@@ -117,7 +117,7 @@
- EM_SETTEXTMODE 2.0
- EM_SETTYPOGRAPHYOPTIONS 3.0
- EM_SETUNDOLIMIT 2.0
- - EM_SETWORDBREAKPROC
+ + EM_SETWORDBREAKPROC (used only for word movement at the moment)
- EM_SETWORDBREAKPROCEX
- EM_SETWORDWRAPMODE 1.0asian
+ EM_SETZOOM 3.0
@@ -815,7 +815,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD n
case VK_END:
case VK_PRIOR:
case VK_NEXT:
- ME_ArrowKey(editor, nKey, shift_is_down);
+ ME_ArrowKey(editor, nKey, shift_is_down, ctrl_is_down);
return TRUE;
case VK_BACK:
case VK_DELETE:
@@ -824,7 +824,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD n
return FALSE;
if (ME_IsSelection(editor))
ME_DeleteSelection(editor);
- else if (nKey == VK_DELETE || ME_ArrowKey(editor, VK_LEFT, FALSE))
+ else if (nKey == VK_DELETE || ME_ArrowKey(editor, VK_LEFT, FALSE, FALSE))
ME_DeleteTextAtCursor(editor, 1, 1);
else
return TRUE;
@@ -888,6 +888,7 @@ ME_TextEditor *ME_MakeEditor(HWND hWnd)
ed->nZoomNumerator = ed->nZoomDenominator = 0;
ed->bRedraw = TRUE;
ed->nInvalidOfs = -1;
+ ed->pfnWordBreak = NULL;
GetClientRect(hWnd, &ed->rcFormat);
for (i=0; i<HFONT_CACHE_SIZE; i++)
{
@@ -1194,7 +1195,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND
UNSUPPORTED_MSG(EM_GETTEXTMODE)
UNSUPPORTED_MSG(EM_GETTYPOGRAPHYOPTIONS)
UNSUPPORTED_MSG(EM_GETUNDONAME)
- UNSUPPORTED_MSG(EM_GETWORDBREAKPROC)
UNSUPPORTED_MSG(EM_GETWORDBREAKPROCEX)
UNSUPPORTED_MSG(EM_HIDESELECTION)
UNSUPPORTED_MSG(EM_LIMITTEXT) /* also known as EM_SETLIMITTEXT */
@@ -1216,7 +1216,6 @@ LRESULT WINAPI RichEditANSIWndProc(HWND
UNSUPPORTED_MSG(EM_SETTEXTMODE)
UNSUPPORTED_MSG(EM_SETTYPOGRAPHYOPTIONS)
UNSUPPORTED_MSG(EM_SETUNDOLIMIT)
- UNSUPPORTED_MSG(EM_SETWORDBREAKPROC)
UNSUPPORTED_MSG(EM_SETWORDBREAKPROCEX)
UNSUPPORTED_MSG(EM_SHOWSCROLLBAR)
UNSUPPORTED_MSG(WM_SETFONT)
@@ -2041,6 +2040,15 @@ LRESULT WINAPI RichEditANSIWndProc(HWND
FIXME("EM_GETOLEINTERFACE %p: stub\n", ppvObj);
return CreateIRichEditOle(ppvObj);
}
+ case EM_GETWORDBREAKPROC:
+ return (LRESULT)editor->pfnWordBreak;
+ case EM_SETWORDBREAKPROC:
+ {
+ EDITWORDBREAKPROCW pfnOld = editor->pfnWordBreak;
+
+ editor->pfnWordBreak = (EDITWORDBREAKPROCW)lParam;
+ return (LRESULT)pfnOld;
+ }
default:
do_default:
return DefWindowProcW(hWnd, msg, wParam, lParam);
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 5243552..3ead3c0 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -72,6 +72,7 @@ int ME_StrLen(ME_String *s);
int ME_StrVLen(ME_String *s);
int ME_FindNonWhitespaceV(ME_String *s, int nVChar);
int ME_FindWhitespaceV(ME_String *s, int nVChar);
+int ME_CallWordBreakProc(ME_TextEditor *editor, ME_String *str, INT start, INT code);
int ME_GetCharFwd(ME_String *s, int nPos); /* get char starting from start */
int ME_GetCharBack(ME_String *s, int nPos); /* get char starting from \0 */
int ME_StrRelPos(ME_String *s, int nVChar, int *pRelChars);
@@ -150,7 +151,7 @@ void ME_DeleteTextAtCursor(ME_TextEditor
void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
const WCHAR *str, int len, ME_Style *style);
void ME_SetCharFormat(ME_TextEditor *editor, int nOfs, int nChars, CHARFORMAT2W *pFmt);
-BOOL ME_ArrowKey(ME_TextEditor *ed, int nVKey, BOOL extend);
+BOOL ME_ArrowKey(ME_TextEditor *ed, int nVKey, BOOL extend, BOOL ctrl);
void ME_InitContext(ME_Context *c, ME_TextEditor *editor, HDC hDC);
void ME_DestroyContext(ME_Context *c);
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index 86dcfdb..37af096 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -286,6 +286,7 @@ typedef struct tagME_TextEditor
RECT rcFormat;
BOOL bRedraw;
int nInvalidOfs;
+ EDITWORDBREAKPROCW pfnWordBreak;
} ME_TextEditor;
typedef struct tagME_Context
diff --git a/dlls/riched20/string.c b/dlls/riched20/string.c
index 6d23e2f..ad385d4 100644
--- a/dlls/riched20/string.c
+++ b/dlls/riched20/string.c
@@ -271,6 +271,54 @@ int ME_ReverseFindWhitespaceV(ME_String
return i;
}
+
+static int
+ME_WordBreakProc(LPWSTR s, INT start, INT len, INT code)
+{
+ /* FIXME: Native also knows about punctuation */
+ TRACE("s==%s, start==%d, len==%d, code==%d\n",
+ debugstr_wn(s, len), start, len, code);
+ switch (code)
+ {
+ case WB_ISDELIMITER:
+ return ME_IsWSpace(s[start]);
+ case WB_LEFT:
+ case WB_MOVEWORDLEFT:
+ while (start && ME_IsWSpace(s[start - 1]))
+ start--;
+ while (start && !ME_IsWSpace(s[start - 1]))
+ start--;
+ return start;
+ case WB_RIGHT:
+ case WB_MOVEWORDRIGHT:
+ if (start && ME_IsWSpace(s[start - 1]))
+ {
+ while (start < len && ME_IsWSpace(s[start]))
+ start++;
+ }
+ else
+ {
+ while (start < len && !ME_IsWSpace(s[start]))
+ start++;
+ while (start < len && ME_IsWSpace(s[start]))
+ start++;
+ }
+ return start;
+ }
+ return 0;
+}
+
+
+int
+ME_CallWordBreakProc(ME_TextEditor *editor, ME_String *str, INT start, INT code)
+{
+ /* FIXME: ANSIfy the string when bEmulateVersion10 is TRUE */
+ if (!editor->pfnWordBreak)
+ return ME_WordBreakProc(str->szData, start, str->nLen, code);
+ else
+ return editor->pfnWordBreak(str->szData, start, str->nLen, code);
+}
+
LPWSTR ME_ToUnicode(HWND hWnd, LPVOID psz)
{
if (IsWindowUnicode(hWnd))
--
1.0.GIT
More information about the wine-patches
mailing list