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