[PATCH] richedit: run.c: fixups to move over to reliance on CR and LF counters editor.c: add fixups for 1.0 emulation to initialize CR and LF counters properly writer.c: text streamout now honors CR and LF counters Tests to pin down required EM_STREAMOUT behavior.

Alex Villacís Lasso alex at karlalex.palosanto.com
Sat Apr 26 15:26:58 CDT 2008


---
 dlls/riched20/editor.c       |    3 ++
 dlls/riched20/para.c         |    2 +
 dlls/riched20/run.c          |   12 +++++--
 dlls/riched20/tests/editor.c |   55 +++++++++++++++++++++++++++++++++
 dlls/riched20/writer.c       |   45 ++++++++++++++++++++++-----
 dlls/riched32/tests/editor.c |   69 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 173 insertions(+), 13 deletions(-)

diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index dcb21d1..7a0dce7 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -3278,6 +3278,9 @@ LRESULT WINAPI RichEdit10ANSIWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
     
     editor->bEmulateVersion10 = TRUE;
     editor->pBuffer->pLast->member.para.nCharOfs = 2;
+    assert(editor->pBuffer->pLast->prev->type == diRun);
+    assert(editor->pBuffer->pLast->prev->member.run.nFlags & MERF_ENDPARA);
+    editor->pBuffer->pLast->prev->member.run.nLF = 1;
   }
   return result;
 }
diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c
index e25c2e6..6963b62 100644
--- a/dlls/riched20/para.c
+++ b/dlls/riched20/para.c
@@ -73,6 +73,8 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
   
   run = ME_MakeRun(style, ME_MakeString(wszParagraphSign), MERF_ENDPARA);
   run->member.run.nCharOfs = 0;
+  run->member.run.nCR = 1;
+  run->member.run.nLF = (editor->bEmulateVersion10) ? 1 : 0;
 
   ME_InsertBefore(text->pLast, para);
   ME_InsertBefore(text->pLast, run);
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c
index e193bd2..40ace55 100644
--- a/dlls/riched20/run.c
+++ b/dlls/riched20/run.c
@@ -127,8 +127,10 @@ void ME_CheckCharOffsets(ME_TextEditor *editor)
           p->member.run.nFlags,
           p->member.run.style->fmt.dwMask & p->member.run.style->fmt.dwEffects);
         assert(ofs == p->member.run.nCharOfs);
-        if (p->member.run.nFlags & MERF_ENDPARA)
-          ofs += (editor->bEmulateVersion10 ? 2 : 1);
+        if (p->member.run.nFlags & MERF_ENDPARA) {
+          assert(p->member.run.nCR + p->member.run.nLF > 0);
+          ofs += p->member.run.nCR + p->member.run.nLF;
+        }
         else
           ofs += ME_StrLen(p->member.run.strText);
         break;
@@ -209,10 +211,12 @@ void ME_RunOfsFromCharOfs(ME_TextEditor *editor, int nCharOfs, ME_DisplayItem **
         }
         *ppRun = pNext;
       }
-      /* the handling of bEmulateVersion10 may be a source of many bugs, I'm afraid */
-      eollen = (editor->bEmulateVersion10 ? 2 : 1);
+      /* Recover proper character length of this line break */
+      eollen = (*ppRun)->member.run.nCR + (*ppRun)->member.run.nLF;
       if (nCharOfs >= nParaOfs + (*ppRun)->member.run.nCharOfs &&
         nCharOfs < nParaOfs + (*ppRun)->member.run.nCharOfs + eollen) {
+        /* FIXME: Might cause problems when actually requiring an offset in the 
+           middle of a run that is considered a single line break */
         *pOfs = 0;
         return;
       }
diff --git a/dlls/riched20/tests/editor.c b/dlls/riched20/tests/editor.c
index 554d7ba..6cf02c3 100644
--- a/dlls/riched20/tests/editor.c
+++ b/dlls/riched20/tests/editor.c
@@ -1125,6 +1125,60 @@ static void test_WM_SETTEXT()
   DestroyWindow(hwndRichEdit);
 }
 
+static void test_EM_STREAMOUT(void)
+{
+  HWND hwndRichEdit = new_richedit(NULL);
+  int r;
+  EDITSTREAM es;
+  char buf[1024] = {0};
+  char * p;
+
+  const char * TestItem1 = "TestSomeText";
+  const char * TestItem2 = "TestSomeText\r";
+  const char * TestItem3 = "TestSomeText\r\n";
+
+  SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem1);
+  p = buf;
+  es.dwCookie = (DWORD_PTR)&p;
+  es.dwError = 0;
+  es.pfnCallback = test_WM_SETTEXT_esCallback;
+  memset(buf, 0, sizeof(buf));
+  SendMessage(hwndRichEdit, EM_STREAMOUT,
+              (WPARAM)(SF_TEXT), (LPARAM)&es);
+  r = strlen(buf);
+  ok(r == 12, "streamed text length is %d, expecting 12\n", r);
+  ok(strcmp(buf, TestItem1) == 0,
+        "streamed text different, got %s\n", buf);
+  
+  SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem2);
+  p = buf;
+  es.dwCookie = (DWORD_PTR)&p;
+  es.dwError = 0;
+  es.pfnCallback = test_WM_SETTEXT_esCallback;
+  memset(buf, 0, sizeof(buf));
+  SendMessage(hwndRichEdit, EM_STREAMOUT,
+              (WPARAM)(SF_TEXT), (LPARAM)&es);
+  r = strlen(buf);
+  /* Here again, \r gets converted to \r\n, like WM_GETTEXT */
+  ok(r == 14, "streamed text length is %d, expecting 14\n", r);
+  ok(strcmp(buf, TestItem3) == 0, 
+        "streamed text different from, got %s\n", buf);
+  SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem3);
+  p = buf;
+  es.dwCookie = (DWORD_PTR)&p;
+  es.dwError = 0;
+  es.pfnCallback = test_WM_SETTEXT_esCallback;
+  memset(buf, 0, sizeof(buf));
+  SendMessage(hwndRichEdit, EM_STREAMOUT,
+              (WPARAM)(SF_TEXT), (LPARAM)&es);
+  r = strlen(buf);
+  ok(r == 14, "streamed text length is %d, expecting 14\n", r);
+  ok(strcmp(buf, TestItem3) == 0,
+        "streamed text different, got %s\n", buf);
+
+  DestroyWindow(hwndRichEdit);
+}
+
 static void test_EM_SETTEXTEX(void)
 {
   HWND hwndRichEdit = new_richedit(NULL);
@@ -2952,6 +3006,7 @@ START_TEST( editor )
   test_EM_EXSETSEL();
   test_WM_PASTE();
   test_EM_STREAMIN();
+  test_EM_STREAMOUT();
   test_EM_StreamIn_Undo();
   test_EM_FORMATRANGE();
   test_unicode_conversions();
diff --git a/dlls/riched20/writer.c b/dlls/riched20/writer.c
index 30e9c93..09d9566 100644
--- a/dlls/riched20/writer.c
+++ b/dlls/riched20/writer.c
@@ -711,9 +711,9 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
             if (!ME_StreamOutPrint(pStream, "\r\n\\par"))
               return FALSE;
           }
-          nChars--;
-          if (editor->bEmulateVersion10 && nChars)
-            nChars--;
+          /* Skip as many characters as required by current line break */
+          nChars -= (p->member.run.nCR <= nChars) ? p->member.run.nCR : nChars;
+          nChars -= (p->member.run.nLF <= nChars) ? p->member.run.nLF : nChars;
         } else if (p->member.run.nFlags & MERF_ENDROW) {
           if (!ME_StreamOutPrint(pStream, "\\line \r\n"))
             return FALSE;
@@ -775,10 +775,39 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n
     if (item->member.run.nFlags & MERF_ENDPARA) {
       static const WCHAR szEOL[2] = { '\r', '\n' };
       
-      if (dwFormat & SF_UNICODE)
-        success = ME_StreamOutMove(pStream, (const char *)szEOL, sizeof(szEOL));
-      else
-        success = ME_StreamOutMove(pStream, "\r\n", 2);
+      if (!editor->bEmulateVersion10) {
+        /* richedit 2.0 - all line breaks are \r\n */
+        if (dwFormat & SF_UNICODE)
+          success = ME_StreamOutMove(pStream, (const char *)szEOL, sizeof(szEOL));
+        else
+          success = ME_StreamOutMove(pStream, "\r\n", 2);
+        assert(nLen == 1);
+      } else {
+        int i; int tnLen;
+        
+        /* richedit 1.0 - need to honor actual \r and \n amounts */
+        nLen = item->member.run.nCR + item->member.run.nLF;
+        if (nLen > nChars)
+          nLen = nChars;
+        tnLen = nLen;
+        
+        i = 0;
+        while (tnLen > 0 && i < item->member.run.nCR) {
+          if (dwFormat & SF_UNICODE)
+            success = ME_StreamOutMove(pStream, (const char *)(&szEOL[0]), sizeof(WCHAR));
+          else
+            success = ME_StreamOutMove(pStream, "\r", 1);
+          tnLen--; i++;
+        }
+        i = 0;
+        while (tnLen > 0 && i < item->member.run.nLF) {
+          if (dwFormat & SF_UNICODE)
+            success = ME_StreamOutMove(pStream, (const char *)(&szEOL[1]), sizeof(WCHAR));
+          else
+            success = ME_StreamOutMove(pStream, "\n", 1);
+          tnLen--; i++;
+        }
+      }
     } else {
       if (dwFormat & SF_UNICODE)
         success = ME_StreamOutMove(pStream, (const char *)(item->member.run.strText->szData + nStart),
@@ -800,8 +829,6 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n
     }
     
     nChars -= nLen;
-    if (editor->bEmulateVersion10 && nChars && item->member.run.nFlags & MERF_ENDPARA)
-      nChars--;
     nStart = 0;
     item = ME_FindItemFwd(item, diRun);
   }
diff --git a/dlls/riched32/tests/editor.c b/dlls/riched32/tests/editor.c
index c8b7181..bb8ce4b 100644
--- a/dlls/riched32/tests/editor.c
+++ b/dlls/riched32/tests/editor.c
@@ -284,6 +284,74 @@ static void test_EM_STREAMIN(void)
   DestroyWindow(hwndRichEdit);
 }
 
+static DWORD CALLBACK test_WM_SETTEXT_esCallback(DWORD_PTR dwCookie,
+                                         LPBYTE pbBuff,
+                                         LONG cb,
+                                         LONG *pcb)
+{
+  char** str = (char**)dwCookie;
+  *pcb = cb;
+  if (*pcb > 0) {
+    memcpy(*str, pbBuff, *pcb);
+    *str += *pcb;
+  }
+  return 0;
+}
+
+static void test_EM_STREAMOUT(void)
+{
+  HWND hwndRichEdit = new_richedit(NULL);
+  int r;
+  EDITSTREAM es;
+  char buf[1024] = {0};
+  char * p;
+
+  const char * TestItem1 = "TestSomeText";
+  const char * TestItem2 = "TestSomeText\r";
+  const char * TestItem3 = "TestSomeText\r\n";
+
+  SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem1);
+  p = buf;
+  es.dwCookie = (DWORD_PTR)&p;
+  es.dwError = 0;
+  es.pfnCallback = test_WM_SETTEXT_esCallback;
+  memset(buf, 0, sizeof(buf));
+  SendMessage(hwndRichEdit, EM_STREAMOUT,
+              (WPARAM)(SF_TEXT), (LPARAM)&es);
+  r = strlen(buf);
+  ok(r == 12, "streamed text length is %d, expecting 12\n", r);
+  ok(strcmp(buf, TestItem1) == 0,
+        "streamed text different, got %s\n", buf);
+  
+  SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) TestItem2);
+  p = buf;
+  es.dwCookie = (DWORD_PTR)&p;
+  es.dwError = 0;
+  es.pfnCallback = test_WM_SETTEXT_esCallback;
+  memset(buf, 0, sizeof(buf));
+  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;
+  es.dwError = 0;
+  es.pfnCallback = test_WM_SETTEXT_esCallback;
+  memset(buf, 0, sizeof(buf));
+  SendMessage(hwndRichEdit, EM_STREAMOUT,
+              (WPARAM)(SF_TEXT), (LPARAM)&es);
+  r = strlen(buf);
+  ok(r == 14, "streamed text length is %d, expecting 14\n", r);
+  ok(strcmp(buf, TestItem3) == 0,
+        "streamed text different, got %s\n", buf);
+
+  DestroyWindow(hwndRichEdit);
+}
 
 START_TEST( editor )
 {
@@ -298,6 +366,7 @@ START_TEST( editor )
   test_WM_SETTEXT();
   test_WM_GETTEXTLENGTH();
   test_EM_STREAMIN();
+  test_EM_STREAMOUT();
 
   /* Set the environment variable WINETEST_RICHED32 to keep windows
    * responsive and open for 30 seconds. This is useful for debugging.
-- 
1.5.4.1


--------------050905070501090706040705--



More information about the wine-patches mailing list