riched20: implement EM_FINDWORDBREAK and its tests
Brian Chang
brianch at seas.ucla.edu
Thu Mar 16 08:35:19 CST 2006
Hello. My name is Brian Chang and I'm a resident of Los Angeles, CA, USA currently attending
UCLA. I hereby certify that I wrote this code without copying from anyone else's sources,
and I've never seen any secret Microsoft source code.
changelist:
This patch implements EM_FINDWORDBREAK along with its corresponding conformance test.
Changes were made to the WordBreakProc to support EM_FINDWORDBREAk and is tested
through EM_FINDWORDBREAK tests
editor.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
editstr.h | 1 +
string.c | 42 +++++++++++++++++++++++++++++++++++-------
tests/editor.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 138 insertions(+), 9 deletions(-)
Index: dlls/riched20/editor.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/editor.c,v
retrieving revision 1.103
diff -a -u -r1.103 editor.c
--- dlls/riched20/editor.c 2 Mar 2006 17:12:37 -0000 1.103
+++ dlls/riched20/editor.c 16 Mar 2006 14:21:34 -0000
@@ -37,7 +37,7 @@
+ EM_EXSETSEL
+ EM_FINDTEXT (only FR_DOWN flag implemented)
+ EM_FINDTEXTEX (only FR_DOWN flag implemented)
- - EM_FINDWORDBREAK
+ + EM_FINDWORDBREAK (partially implemented)
- EM_FMTLINES
- EM_FORMATRANGE
+ EM_GETAUTOURLDETECT 2.0
@@ -1292,7 +1292,6 @@
UNSUPPORTED_MSG(EM_DISPLAYBAND)
UNSUPPORTED_MSG(EM_EXLIMITTEXT)
- UNSUPPORTED_MSG(EM_FINDWORDBREAK)
UNSUPPORTED_MSG(EM_FMTLINES)
UNSUPPORTED_MSG(EM_FORMATRANGE)
UNSUPPORTED_MSG(EM_GETBIDIOPTIONS)
@@ -1993,6 +1992,52 @@
FINDTEXTEXW *ex = (FINDTEXTEXW *)lParam;
return ME_FindText(editor, wParam, &ex->chrg, ex->lpstrText, &ex->chrgText);
}
+ case EM_FINDWORDBREAK:
+ {
+ ME_DisplayItem *pRun;
+ int runOfs, newRunOfs;
+
+ ME_RunOfsFromCharOfs(editor, lParam, &pRun, &runOfs);
+
+ if (wParam == WB_RIGHT)
+ FIXME("WB_RIGHT not implemented yet!\n");
+ if (wParam == WB_LEFT)
+ FIXME("WB_LEFT not implemented yet!\n");
+ if (wParam == WB_RIGHTBREAK)
+ FIXME("WB_RIGHTBREAK not implemented yet!\n");
+ if (wParam == WB_LEFTBREAK)
+ FIXME("WB_LEFTBREAK not implemented yet!\n");
+ if (wParam == WB_CLASSIFY)
+ FIXME("WB_CLASSIFY not implemented yet!\n");
+
+ /* if we're at the beginning of a run and we want to go left
+ * we should start at the end of the previous run
+ */
+ if (runOfs == 0 && (wParam == WB_MOVEWORDLEFT))
+ ME_RunOfsFromCharOfs(editor, lParam-1, &pRun, &runOfs);
+
+ /* if we're at the end of a run and we want to go right
+ * we should start at the beginning of the next run
+ */
+ if ((runOfs == ((pRun->member.run.strText->nLen)-1))&& (wParam == WB_MOVEWORDRIGHT))
+ ME_RunOfsFromCharOfs(editor, lParam+1, &pRun, &runOfs);
+
+ newRunOfs = ME_CallWordBreakProc(editor, pRun->member.run.strText, runOfs, wParam);
+
+ /* Check if we need to go back a bit more because of whitespace
+ * Will only happen when moving left
+ */
+ if ( (newRunOfs == 0) &&
+ ME_CallWordBreakProc(editor, pRun->member.run.strText, newRunOfs, WB_ISDELIMITER)
+ )
+ {
+ lParam -= runOfs+1;
+ ME_RunOfsFromCharOfs(editor, lParam, &pRun, &runOfs);
+ newRunOfs = ME_CallWordBreakProc(editor, pRun->member.run.strText, runOfs, wParam);
+ }
+
+ return lParam + (newRunOfs - runOfs);
+ }
case EM_GETZOOM:
if (!wParam || !lParam)
return FALSE;
Index: dlls/riched20/editstr.h
===================================================================
RCS file: /home/wine/wine/dlls/riched20/editstr.h,v
retrieving revision 1.27
diff -a -u -r1.27 editstr.h
--- dlls/riched20/editstr.h 2 Mar 2006 11:18:19 -0000 1.27
+++ dlls/riched20/editstr.h 16 Mar 2006 14:21:34 -0000
@@ -44,6 +44,7 @@
#include <commctrl.h>
#include <ole2.h>
#include <richole.h>
+#include <wctype.h>
#include "wine/debug.h"
Index: dlls/riched20/string.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/string.c,v
retrieving revision 1.6
diff -a -u -r1.6 string.c
--- dlls/riched20/string.c 12 Jan 2006 12:46:18 -0000 1.6
+++ dlls/riched20/string.c 16 Mar 2006 14:21:34 -0000
@@ -272,34 +272,62 @@
}
+/* 'chunks' are composed either of all punctuation or all alphabetic chars
+ * a 'chunk' plus all the whitespace to the right of it forms a 'word'
+ */
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);
+
+ /* Windows returns 0 if start is negative and len+1 if start is >= len */
+ if(code != WB_ISDELIMITER)
+ {
+ if(start < 0)
+ return 0;
+ if(start > len)
+ return len+1;
+ }
+
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]))
+ while (start && ME_IsWSpace(s[start-1]))
start--;
+ if (iswpunct(s[start-1]))
+ {
+ while (start && iswpunct(s[start-1]))
+ start--;
+ }
+ else
+ {
+ while (start && !(iswpunct(s[start-1]) || ME_IsWSpace(s[start-1])))
+ start--;
+ }
return start;
case WB_RIGHT:
case WB_MOVEWORDRIGHT:
- if (start && ME_IsWSpace(s[start - 1]))
+ if (ME_IsWSpace(s[start]))
{
while (start < len && ME_IsWSpace(s[start]))
start++;
}
else
{
- while (start < len && !ME_IsWSpace(s[start]))
- start++;
+ if (iswpunct(s[start]))
+ {
+ while (start < len && iswpunct(s[start]))
+ start++;
+ }
+ else
+ {
+ while (start < len && !(iswpunct(s[start]) || ME_IsWSpace(s[start])))
+ start++;
+ }
while (start < len && ME_IsWSpace(s[start]))
start++;
}
Index: dlls/riched20/tests/editor.c
===================================================================
RCS file: /home/wine/wine/dlls/riched20/tests/editor.c,v
retrieving revision 1.11
diff -a -u -r1.11 editor.c
--- dlls/riched20/tests/editor.c 2 Mar 2006 17:12:37 -0000 1.11
+++ dlls/riched20/tests/editor.c 16 Mar 2006 14:21:35 -0000
@@ -744,6 +744,60 @@
DestroyWindow(hwndRichEdit);
}
+static void test_EM_FINDWORDBREAK()
+{
+ HWND hwndRichEdit = new_richedit(NULL);
+ long result;
+ static const char text[] = "Text for wordbreak proc!!! test.member ...";
+ /* 012345678901234567890123456789012345678901234
+ * 10 20 30 40
+ */
+
+ SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) text);
+
+ /* starting position of 'for' */
+ result = SendMessage(hwndRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, 0);
+ ok(result == 5, "EM_FINDWORDBREAK: expected: 5 actual: %ld\n", result);
+
+ /* strating position of '!!!' */
+ result = SendMessage(hwndRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, 21);
+ ok(result == 23, "EM_FINDWORDBREAK: expected: 23 actual: %ld\n", result);
+
+ /* starting position of 'test' */
+ result = SendMessage(hwndRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, 27);
+ ok(result == 30, "EM_FINDWORDBREAK: expected: 30 actual: %ld\n", result);
+
+ /* position right before 'member' */
+ result = SendMessage(hwndRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, 31);
+ ok(result == 34, "EM_FINDWORDBREAK: expected: 34 actual: %ld\n", result);
+
+ /* the position of null char */
+ result = SendMessage(hwndRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDRIGHT, 42);
+ ok(result == 45, "EM_FINDWORDBREAK: expected: 45 actual: %ld\n", result);
+
+ /* starting position of '...' */
+ result = SendMessage(hwndRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDLEFT, 44);
+ ok(result == 42, "EM_FINDWORDBREAK: expected: 42 actual: %ld\n", result);
+
+ /* position right after 'test.' */
+ result = SendMessage(hwndRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDLEFT, 36);
+ ok(result == 35, "EM_FINDWORDBREAK: expected: 35 actual: %ld\n", result);
+
+ /* position right after 'proc' */
+ result = SendMessage(hwndRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDLEFT, 27);
+ ok(result == 23, "EM_FINDWORDBREAK: expected: 23 actual: %ld\n", result);
+
+ /* beginning position */
+ result = SendMessage(hwndRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDLEFT, 5);
+ ok(result == 0, "EM_FINDWORDBREAK: expected: 0 actual: %ld\n", result);
+
+ /* position right after beginning */
+ result = SendMessage(hwndRichEdit, EM_FINDWORDBREAK, WB_MOVEWORDLEFT, 3);
+ ok(result == 0, "EM_FINDWORDBREAK: expected: 0 actual: %ld\n", result);
+
+ DestroyWindow(hwndRichEdit);
+}
+
START_TEST( editor )
{
MSG msg;
@@ -761,6 +815,7 @@
test_EM_SETOPTIONS();
test_WM_GETTEXT();
test_EM_AUTOURLDETECT();
+ test_EM_FINDWORDBREAK();
/* Set the environment variable WINETEST_RICHED20 to keep windows
* responsive and open for 30 seconds. This is useful for debugging.
More information about the wine-patches
mailing list