Commit 49eecf51 authored by Phil Krylov's avatar Phil Krylov Committed by Alexandre Julliard

riched20: Initial support for word break callback procedures.

parent 777d9bfa
......@@ -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, ME_Cursor *pCursor, int nRelOfs)
}
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 *editor)
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 nVKey, BOOL extend)
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 nVKey, BOOL extend)
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 nVKey, BOOL extend)
break;
}
case VK_END:
if (GetKeyState(VK_CONTROL)<0)
if (ctrl)
ME_ArrowCtrlEnd(editor, &tmp_curs);
else
ME_ArrowEnd(editor, &tmp_curs);
......
......@@ -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 nKey)
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 nKey)
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 hWnd, UINT msg, WPARAM wParam, LPARAM lP
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 hWnd, UINT msg, WPARAM wParam, LPARAM lP
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 hWnd, UINT msg, WPARAM wParam, LPARAM lP
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);
......
......@@ -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 *editor, int nCursor, int nChars);
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);
......
......@@ -286,6 +286,7 @@ typedef struct tagME_TextEditor
RECT rcFormat;
BOOL bRedraw;
int nInvalidOfs;
EDITWORDBREAKPROCW pfnWordBreak;
} ME_TextEditor;
typedef struct tagME_Context
......
......@@ -271,6 +271,54 @@ int ME_ReverseFindWhitespaceV(ME_String *s, int nVChar) {
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))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment