Alex Villacís Lasso : richedit: Flip the big switch and encode actual CR and LF into end-of-paragraph runs .

Alexandre Julliard julliard at winehq.org
Tue Apr 29 08:54:47 CDT 2008


Module: wine
Branch: master
Commit: 4047df0f564786437cdf9a0712fbee603f5f3d2f
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=4047df0f564786437cdf9a0712fbee603f5f3d2f

Author: Alex Villacís Lasso <a_villacis at palosanto.com>
Date:   Sat Apr 26 22:49:35 2008 -0500

richedit: Flip the big switch and encode actual CR and LF into end-of-paragraph runs.

Document remaining uses of bEmulateVersion10 and other checks for CRLF in editor.c.
Make RTF reader emit a \r or a \r\n according to emulation, not a \n, which breaks streaming tests.
Remove todo_wine from a bunch of riched32 tests that now succeed.

---

 dlls/riched20/caret.c        |   43 ++++++++++++++++++++++++++---------------
 dlls/riched20/editor.c       |   26 +++++++++++++++++++++++-
 dlls/riched20/reader.c       |    3 +-
 dlls/riched32/tests/editor.c |   34 ++++++++++++++++----------------
 4 files changed, 70 insertions(+), 36 deletions(-)

diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index a8e51db..bf53aff 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -524,6 +524,8 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
     if (pos-str < len) {   /* handle EOLs */
       ME_DisplayItem *tp, *end_run;
       ME_Style *tmp_style;
+      int numCR, numLF;
+
       if (pos!=str)
         ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
       p = &editor->pCursors[nCursor];
@@ -534,38 +536,47 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
       tmp_style = ME_GetInsertStyle(editor, nCursor);
       /* ME_SplitParagraph increases style refcount */
 
-      /* TODO: move here and fix logic for pos updating according to emulation,
-         so that number of CR and LF encoded are a result of such logic, instead
-         of hardcoded as below.
-       */
-      if (editor->bEmulateVersion10)
-        tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, 1, 1);
-      else
-        tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, 1, 0);
-      p->pRun = ME_FindItemFwd(tp, diRun);
-      end_run = ME_FindItemBack(tp, diRun);
-      ME_ReleaseStyle(end_run->member.run.style);
-      end_run->member.run.style = tmp_style;
-      p->nOffset = 0;
+      /* Encode and fill number of CR and LF according to emulation mode */
       if (editor->bEmulateVersion10) {
         const WCHAR * tpos;
 
+        /* We have to find out how many consecutive \r are there, and if there
+           is a \n terminating the run of \r's. */
+        numCR = 0; numLF = 0;
         tpos = pos;
         while (tpos-str < len && *tpos == '\r') {
           tpos++;
+          numCR++;
         }
         if (tpos-str >= len) {
-          if (tpos != pos) pos++;
-        } else if (*tpos == '\n')
+          /* Reached end of text without finding anything but '\r' */
+          if (tpos != pos) {
+            pos++;
+          }
+          numCR = 1; numLF = 0;
+        } else if (*tpos == '\n') {
+          /* The entire run of \r's plus the one \n is one single line break */
           pos = tpos + 1;
-        else
+          numLF = 1;
+        } else {
+          /* Found some other content past the run of \r's */
           pos++;
+          numCR = 1; numLF = 0;
+        }
       } else {
         if(pos-str < len && *pos =='\r')
           pos++;
         if(pos-str < len && *pos =='\n')
           pos++;
+        numCR = 1; numLF = 0;
       }
+      tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, numCR, numLF);
+      p->pRun = ME_FindItemFwd(tp, diRun);
+      end_run = ME_FindItemBack(tp, diRun);
+      ME_ReleaseStyle(end_run->member.run.style);
+      end_run->member.run.style = tmp_style;
+      p->nOffset = 0;
+
       if(pos-str <= len) {
         len -= pos - str;
         str = pos;
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index d0d6195..4b4db9f 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -1101,7 +1101,10 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
       if (parser.lpRichEditOle)
         IRichEditOle_Release(parser.lpRichEditOle);
 
-      /* Remove last line break, as mandated by tests */
+      /* Remove last line break, as mandated by tests. This is not affected by
+         CR/LF counters, since RTF streaming presents only \para tokens, which
+         are converted according to the standard rules: \r for 2.0, \r\n for 1.0
+       */
       if (stripLastCR) {
         int newfrom, newto;
         ME_GetSelection(editor, &newfrom, &newto);
@@ -1213,6 +1216,21 @@ ME_FindItemAtOffset(ME_TextEditor *editor, ME_DIType nItemType, int nOffset, int
   } while (item && (item->member.run.nCharOfs + runLength <= nOffset));
   if (item) {
     nOffset -= item->member.run.nCharOfs;
+
+    /* Special case: nOffset may not point exactly at the division between the
+       \r and the \n in 1.0 emulation. If such a case happens, it is sent
+       into the next run, if one exists
+     */
+    if (   item->member.run.nFlags & MERF_ENDPARA
+        && nOffset == item->member.run.nCR
+        && item->member.run.nLF > 0) {
+      ME_DisplayItem *nextItem;
+      nextItem = ME_FindItemFwd(item, diRun);
+      if (nextItem) {
+        nOffset = 0;
+        item = nextItem;
+      }
+    }
     if (nItemOffset)
       *nItemOffset = nOffset;
   }
@@ -2487,6 +2505,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
   {
     GETTEXTLENGTHEX how;
 
+    /* CR/LF conversion required in 2.0 mode, verbatim in 1.0 mode */
     how.flags = GTL_CLOSE | (editor->bEmulateVersion10 ? 0 : GTL_USECRLF) | GTL_NUMCHARS;
     how.codepage = unicode ? 1200 : CP_ACP;
     return ME_GetTextLengthEx(editor, &how);
@@ -2552,7 +2571,10 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
     else
     {
       /* potentially each char may be a CR, why calculate the exact value with O(N) when
-        we can just take a bigger buffer? :) */
+        we can just take a bigger buffer? :)
+        The above assumption still holds with CR/LF counters, since CR->CRLF expansion
+        occurs only in richedit 2.0 mode, in which line breaks have only one CR
+       */
       int crlfmul = (ex->flags & GT_USECRLF) ? 2 : 1;
       LPWSTR buffer;
       DWORD buflen = ex->cb;
diff --git a/dlls/riched20/reader.c b/dlls/riched20/reader.c
index 1ecca08..5ee9fa2 100644
--- a/dlls/riched20/reader.c
+++ b/dlls/riched20/reader.c
@@ -2605,7 +2605,8 @@ static void SpecialChar (RTF_Info *info)
 	case rtfSect:
 	case rtfRow:
 	case rtfPar:
-		RTFPutUnicodeChar (info, '\n');
+		RTFPutUnicodeChar (info, '\r');
+		if (info->editor->bEmulateVersion10) RTFPutUnicodeChar (info, '\n');
 		break;
 	case rtfNoBrkSpace:
 		RTFPutUnicodeChar (info, 0x00A0);
diff --git a/dlls/riched32/tests/editor.c b/dlls/riched32/tests/editor.c
index 21972ab..70d1558 100644
--- a/dlls/riched32/tests/editor.c
+++ b/dlls/riched32/tests/editor.c
@@ -110,21 +110,21 @@ static void test_WM_SETTEXT()
   }
 
   TEST_SETTEXT(TestItem1, TestItem1, 1, 0, 0)
-  TEST_SETTEXT(TestItem2, TestItem2, 1, 1, 1)
-  TEST_SETTEXT(TestItem3, TestItem3, 2, 1, 1)
-  TEST_SETTEXT(TestItem4, TestItem4, 3, 1, 0)
-  TEST_SETTEXT(TestItem5, TestItem5, 2, 1, 0)
-  TEST_SETTEXT(TestItem6, TestItem6, 3, 1, 0)
-  TEST_SETTEXT(TestItem7, TestItem7, 4, 1, 0)
+  TEST_SETTEXT(TestItem2, TestItem2, 1, 0, 1)
+  TEST_SETTEXT(TestItem3, TestItem3, 2, 0, 1)
+  TEST_SETTEXT(TestItem4, TestItem4, 3, 0, 0)
+  TEST_SETTEXT(TestItem5, TestItem5, 2, 0, 0)
+  TEST_SETTEXT(TestItem6, TestItem6, 3, 0, 0)
+  TEST_SETTEXT(TestItem7, TestItem7, 4, 0, 0)
   TEST_SETTEXT(TestItem8, TestItem8, 2, 0, 0)
   TEST_SETTEXT(TestItem9, TestItem9, 3, 0, 0)
   TEST_SETTEXT(TestItem10, TestItem10, 3, 0, 0)
   TEST_SETTEXT(TestItem11, TestItem11, 1, 0, 0)
   TEST_SETTEXT(TestItem12, TestItem12, 2, 0, 0)
   TEST_SETTEXT(TestItem13, TestItem13, 3, 0, 0)
-  TEST_SETTEXT(TestItem14, TestItem14, 2, 1, 0)
-  TEST_SETTEXT(TestItem15, TestItem15, 3, 1, 1)
-  TEST_SETTEXT(TestItem16, TestItem16, 4, 1, 0)
+  TEST_SETTEXT(TestItem14, TestItem14, 2, 0, 0)
+  TEST_SETTEXT(TestItem15, TestItem15, 3, 0, 1)
+  TEST_SETTEXT(TestItem16, TestItem16, 4, 0, 0)
 
 #undef TEST_SETTEXT
   DestroyWindow(hwndRichEdit);
@@ -332,11 +332,11 @@ static void test_EM_STREAMOUT(void)
   SendMessage(hwndRichEdit, EM_STREAMOUT,
               (WPARAM)(SF_TEXT), (LPARAM)&es);
   r = strlen(buf);
-  todo_wine { /* Currently fails because of solitary \r mangling */
+
   ok(r == 13, "streamed text length is %d, expecting 13\n", r);
   ok(strcmp(buf, TestItem2) == 0,
         "streamed text different, got %s\n", buf);
-  }
+
   SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3);
   p = buf;
   es.dwCookie = (DWORD_PTR)&p;
@@ -360,8 +360,8 @@ static const struct getline_s {
   int wine_todo;
 } gl[] = {
   {0, 10, "foo bar\r\n", 0},
-  {1, 10, "\n", 1},
-  {2, 10, "bar\n", 1},
+  {1, 10, "\n", 0},
+  {2, 10, "bar\n", 0},
   {3, 10, "\r\n", 0},
 
   /* Buffer smaller than line length */
@@ -493,9 +493,9 @@ static void test_EM_GETTEXTRANGE(void)
     result = SendMessage(hwndRichEdit, EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
     ok(result == 7, "EM_GETTEXTRANGE returned %ld, expected %d\n",
         result, strlen(expect2));
-    todo_wine {
+
     ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
-    }
+
 
     DestroyWindow(hwndRichEdit);
 }
@@ -524,9 +524,9 @@ static void test_EM_GETSELTEXT(void)
     result = SendMessage(hwndRichEdit, EM_GETSELTEXT, 0, (LPARAM)buffer);
     ok(result == 7, "EM_GETTEXTRANGE returned %ld, expected %d\n",
         result, strlen(expect2));
-    todo_wine {
+
     ok(!strcmp(expect2, buffer), "EM_GETTEXTRANGE filled %s\n", buffer);
-    }
+
 
     DestroyWindow(hwndRichEdit);
 }




More information about the wine-cvs mailing list