richedit: Actually store end of line string for end paragraph runs.

Dylan Smith dylan.ah.smith at gmail.com
Wed Jan 28 00:34:56 CST 2009


Previously a count of the carraige returns and line feeds were stored
for end of paragraph runs, and a paragraph sign was stored as the actual
string.  This was causing many special cases where the length of the
run needed to be determined differently if the run was or wasn't an
end of paragraph run.

There wasn't any use for storing the paragraph sign unless some drawing
code gets commented out to allow the end paragraphs to be shown,
therefore I changed the code to store the actual string that gets
retrieved by WM_GETTEXT.

This ended up fixing some riched32 tests for EM_FINDTEXT which didn't
handle this special case.
---
 dlls/riched20/caret.c        |   35 +++++++++++----------
 dlls/riched20/editor.c       |   69 +++++++++++++----------------------------
 dlls/riched20/editor.h       |    2 +-
 dlls/riched20/editstr.h      |    3 +-
 dlls/riched20/list.c         |    6 +--
 dlls/riched20/paint.c        |    1 -
 dlls/riched20/para.c         |   32 ++++++++-----------
 dlls/riched20/run.c          |    8 +----
 dlls/riched20/string.c       |    1 +
 dlls/riched20/table.c        |   21 ++++++++-----
 dlls/riched20/undo.c         |    6 +--
 dlls/riched20/writer.c       |   58 ++++++++--------------------------
 dlls/riched32/tests/editor.c |   13 ++++++--
 13 files changed, 101 insertions(+), 154 deletions(-)
-------------- next part --------------
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index 180688a..cdd8f79 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -303,14 +303,11 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
       /* We aren't deleting anything in this run, so we will go back to the
        * last run we are deleting text in. */
       c.pRun = ME_FindItemBack(c.pRun, diRun);
-      if (c.pRun->member.run.nFlags & MERF_ENDPARA)
-        c.nOffset = c.pRun->member.run.nCR + c.pRun->member.run.nLF;
-      else
-        c.nOffset = c.pRun->member.run.strText->nLen;
+      c.nOffset = c.pRun->member.run.strText->nLen;
     }
     run = &c.pRun->member.run;
     if (run->nFlags & MERF_ENDPARA) {
-      int eollen = run->nCR + run->nLF;
+      int eollen = c.pRun->member.run.strText->nLen;
       BOOL keepFirstParaFormat;
 
       if (!ME_FindItemFwd(c.pRun, diParagraph))
@@ -539,31 +536,37 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
     } else { /* handle EOLs */
       ME_DisplayItem *tp, *end_run;
       ME_Style *tmp_style;
-      int numCR, numLF;
+      int eol_len = 0;
 
       /* Find number of CR and LF in end of paragraph run */
-      numCR = 0; numLF = 0;
       if (*pos =='\r')
       {
-        numCR++;
         if (len > 1 && pos[1] == '\n')
-          numLF++;
+          eol_len = 2;
         else if (len > 2 && pos[1] == '\r' && pos[2] == '\n')
-          numCR++, numLF++;
+          eol_len = 3;
+        else
+          eol_len = 1;
       } else {
         assert(*pos == '\n');
-        numLF++;
+        eol_len = 1;
       }
-      pos += numCR + numLF;
+      pos += eol_len;
 
-      if (!editor->bEmulateVersion10 && numCR == 2 && numLF == 1)
+      if (!editor->bEmulateVersion10 && eol_len == 3)
       {
         /* handle special \r\r\n sequence (richedit 2.x and higher only) */
         WCHAR space = ' ';
         ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, style, 0);
       } else {
-        if (!editor->bEmulateVersion10)
-          numCR = 1, numLF = 0;
+        ME_String *eol_str;
+
+        if (!editor->bEmulateVersion10) {
+          WCHAR cr = '\r';
+          eol_str = ME_MakeStringN(&cr, 1);
+        } else {
+          eol_str = ME_MakeStringN(str, eol_len);
+        }
 
         p = &editor->pCursors[nCursor];
         if (p->nOffset) {
@@ -572,7 +575,7 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
         }
         tmp_style = ME_GetInsertStyle(editor, nCursor);
         /* ME_SplitParagraph increases style refcount */
-        tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, numCR, numLF, 0);
+        tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, eol_str, 0);
         p->pRun = ME_FindItemFwd(tp, diRun);
         end_run = ME_FindItemBack(tp, diRun);
         ME_ReleaseStyle(end_run->member.run.style);
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index b3f92bf..cd130a5 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -3621,12 +3621,11 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
       return 0;
 
     while (nCharsLeft && (run = ME_FindItemFwd(run, diRunOrStartRow))
-           && !(run->member.run.nFlags & MERF_ENDPARA))
+           && run->type == diRun)
     {
       unsigned int nCopy;
       ME_String *strText;
-      if (run->type != diRun)
-        break;
+
       strText = run->member.run.strText;
       nCopy = min(nCharsLeft, strText->nLen);
 
@@ -3642,31 +3641,12 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
     /* append line termination, space allowing */
     if (nCharsLeft > 0)
     {
-      if (run && (run->member.run.nFlags & MERF_ENDPARA))
-      {
-        int i;
-        /* Write as many \r as encoded in end-of-paragraph, space allowing */
-        for (i = 0; i < run->member.run.nCR && nCharsLeft > 0; i++, nCharsLeft--)
-        {
-          *((WCHAR *)dest) = '\r';
-          dest += unicode ? sizeof(WCHAR) : 1;
-        }
-        /* Write as many \n as encoded in end-of-paragraph, space allowing */
-        for (i = 0; i < run->member.run.nLF && nCharsLeft > 0; i++, nCharsLeft--)
-        {
-          *((WCHAR *)dest) = '\n';
-          dest += unicode ? sizeof(WCHAR) : 1;
-        }
-      }
-      if (nCharsLeft > 0)
-      {
-        if (unicode)
-          *((WCHAR *)dest) = '\0';
-        else
-          *dest = '\0';
-        nCharsLeft--;
-        wroteNull = TRUE;
-      }
+      if (unicode)
+        *((WCHAR *)dest) = '\0';
+      else
+        *dest = '\0';
+      nCharsLeft--;
+      wroteNull = TRUE;
     }
 
     TRACE("EM_GETLINE: got %u characters\n", nMaxChars - nCharsLeft);
@@ -3692,8 +3672,10 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
     last_para = ME_FindItemBack(item, diRun);
     assert(last_para);
     assert(last_para->member.run.nFlags & MERF_ENDPARA);
-    if (editor->bEmulateVersion10 && prev_para && last_para->member.run.nCharOfs == 0
-        && prev_para->member.run.nCR == 1 && prev_para->member.run.nLF == 0)
+    if (editor->bEmulateVersion10 && prev_para &&
+        last_para->member.run.nCharOfs == 0 &&
+        prev_para->member.run.strText->nLen == 1 &&
+        prev_para->member.run.strText->szData[0] == '\r')
     {
       /* In 1.0 emulation, the last solitary \r at the very end of the text
          (if one exists) is NOT a line break.
@@ -3764,7 +3746,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
       assert(endPara);
       assert(endPara->type == diRun);
       assert(endPara->member.run.nFlags & MERF_ENDPARA);
-      nNextLineOfs -= endPara->member.run.nCR + endPara->member.run.nLF;
+      nNextLineOfs -= endPara->member.run.strText->nLen;
     }
     nChars = nNextLineOfs - nThisLineOfs;
     TRACE("EM_LINELENGTH(%ld)==%d\n",wParam, nChars);
@@ -4550,29 +4532,22 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart,
         nLen = 0;
         nChars = 0;
       } else {
-        int numCR, numLF;
-        int i, j;
+        WCHAR cr_lf[] = {'\r', '\n', 0};
+        WCHAR *szData;
 
         if (bCRLF)
         {
-          numCR = 1;
-          numLF = 1;
+          nLen = 2;
+          szData = cr_lf;
         } else {
-          numCR = pRun->member.run.nCR;
-          numLF = pRun->member.run.nLF;
+          nLen = pRun->member.run.strText->nLen;
+          szData = pRun->member.run.strText->szData;
         }
-        numCR -= nOffset;
-
-        nLen = min(nChars, numCR + numLF);
-
-        for (i = 0; i < nLen && i < numCR; i++)
-          buffer[i] = '\r';
-
-        for (j = 0; i + j < nLen && j < numLF; j++)
-          buffer[i+j] = '\n';
+        nLen = min(nChars, nLen - nOffset);
+        CopyMemory(buffer, szData + nOffset, sizeof(WCHAR) * nLen);
       }
     } else {
-      nLen = min(nChars, ME_StrLen(pRun->member.run.strText) - nOffset);
+      nLen = min(nChars, pRun->member.run.strText->nLen - nOffset);
       CopyMemory(buffer, pRun->member.run.strText->szData + nOffset,
                  sizeof(WCHAR) * nLen);
     }
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index a5826b1..a412389 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -214,7 +214,7 @@ void ME_SendRequestResize(ME_TextEditor *editor, BOOL force);
 ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *run); 
 void ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end);
 void ME_MakeFirstParagraph(ME_TextEditor *editor);
-ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style, int numCR, int numLF, int paraFlags);
+ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *rp, ME_Style *style, ME_String *eol_str, int paraFlags);
 ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
                                   BOOL keepFirstParaFormat);
 void ME_DumpParaStyle(ME_Paragraph *s);
diff --git a/dlls/riched20/editstr.h b/dlls/riched20/editstr.h
index ccdf51d..a645075 100644
--- a/dlls/riched20/editstr.h
+++ b/dlls/riched20/editstr.h
@@ -162,7 +162,6 @@ typedef struct tagME_Run
   int nAscent, nDescent; /* pixels above/below baseline */
   POINT pt; /* relative to para's position */
   REOBJECT *ole_obj; /* FIXME: should be a union with strText (at least) */
-  int nCR; int nLF;  /* for MERF_ENDPARA: number of \r and \n characters encoded by run */
 } ME_Run;
 
 typedef struct tagME_Document {
@@ -252,7 +251,7 @@ typedef struct tagME_UndoItem
 {
   ME_DisplayItem di;
   int nStart, nLen;
-  int nCR, nLF;      /* used by diUndoSplitParagraph */
+  ME_String *eol_str; /* used by diUndoSplitParagraph */
 } ME_UndoItem;
 
 typedef struct tagME_TextBuffer
diff --git a/dlls/riched20/list.c b/dlls/riched20/list.c
index 804fd60..f9a9032 100644
--- a/dlls/riched20/list.c
+++ b/dlls/riched20/list.c
@@ -191,10 +191,8 @@ void ME_DumpDocument(ME_TextBuffer *buffer)
         TRACE(" - StartRow\n");
         break;
       case diRun:
-        TRACE(" - Run(\"%s\", %d)\n", debugstr_w(pItem->member.run.strText->szData), 
-          pItem->member.run.nCharOfs);
-        if (pItem->member.run.nFlags & MERF_ENDPARA)
-          TRACE(" - Paragraph end: %d CR, %d LF\n", pItem->member.run.nCR, pItem->member.run.nLF);
+        TRACE(" - Run(\"%s\", %d, flags=%x)\n", debugstr_w(pItem->member.run.strText->szData),
+          pItem->member.run.nCharOfs, pItem->member.run.nFlags);
         break;
       case diTextEnd:
         TRACE("End(ofs=%d)\n", pItem->member.para.nCharOfs);
diff --git a/dlls/riched20/paint.c b/dlls/riched20/paint.c
index 3de26e1..7d7ea76 100644
--- a/dlls/riched20/paint.c
+++ b/dlls/riched20/paint.c
@@ -421,7 +421,6 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa
   ME_GetSelection(c->editor, &nSelFrom, &nSelTo);
 
   /* Draw selected end-of-paragraph mark */
-  /* you can always comment it out if you need visible paragraph marks */
   if (run->nFlags & MERF_ENDPARA)
   {
     if (runofs >= nSelFrom && runofs < nSelTo)
diff --git a/dlls/riched20/para.c b/dlls/riched20/para.c
index 00d997a..a4a9adb 100644
--- a/dlls/riched20/para.c
+++ b/dlls/riched20/para.c
@@ -23,8 +23,6 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
 
-static const WCHAR wszParagraphSign[] = {0xB6, 0};
-
 void ME_MakeFirstParagraph(ME_TextEditor *editor)
 {
   ME_Context c;
@@ -35,6 +33,8 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
   ME_DisplayItem *para = ME_MakeDI(diParagraph);
   ME_DisplayItem *run;
   ME_Style *style;
+  ME_String *eol_str;
+  WCHAR cr_lf[] = {'\r','\n',0};
 
   ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost));
 
@@ -63,11 +63,10 @@ void ME_MakeFirstParagraph(ME_TextEditor *editor)
 
   style = ME_MakeStyle(&cf);
   text->pDefaultStyle = style;
-  
-  run = ME_MakeRun(style, ME_MakeString(wszParagraphSign), MERF_ENDPARA);
+
+  eol_str = ME_MakeStringN(cr_lf, editor->bEmulateVersion10 ? 2 : 1);
+  run = ME_MakeRun(style, eol_str, 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);
@@ -201,7 +200,7 @@ static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const
 
 /* split paragraph at the beginning of the run */
 ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
-                                  ME_Style *style, int numCR, int numLF,
+                                  ME_Style *style, ME_String *eol_str,
                                   int paraFlags)
 {
   ME_DisplayItem *next_para = NULL;
@@ -211,8 +210,8 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
   ME_UndoItem *undo = NULL;
   int ofs;
   ME_DisplayItem *pp;
-  int end_len = numCR + numLF;
   int run_flags = MERF_ENDPARA;
+
   if (!editor->bEmulateVersion10) { /* v4.1 */
     /* At most 1 of MEPF_CELL, MEPF_ROWSTART, or MEPF_ROWEND should be set. */
     assert(!(paraFlags & ~(MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND)));
@@ -224,12 +223,9 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
   } else { /* v1.0 - v3.0 */
     assert(!(paraFlags & (MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND)));
   }
-  end_run = ME_MakeRun(style,ME_MakeString(wszParagraphSign), run_flags);
-  
-  assert(run->type == diRun);  
+  end_run = ME_MakeRun(style, eol_str, run_flags);
 
-  end_run->member.run.nCR = numCR;
-  end_run->member.run.nLF = numLF;
+  assert(run->type == diRun);
   run_para = ME_GetParagraph(run);
   assert(run_para->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
 
@@ -248,7 +244,7 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
     pp = ME_FindItemFwd(pp, diRunOrParagraphOrEnd);
   }
   new_para->member.para.nCharOfs = ME_GetParagraph(run)->member.para.nCharOfs+ofs;
-  new_para->member.para.nCharOfs += end_len;
+  new_para->member.para.nCharOfs += eol_str->nLen;
   new_para->member.para.nFlags = MEPF_REWRAP;
 
   /* FIXME initialize format style and call ME_SetParaFormat blah blah */
@@ -315,7 +311,7 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run,
   new_para->member.para.prev_para->member.para.nFlags |= MEPF_REWRAP;
   
   /* we've added the end run, so we need to modify nCharOfs in the next paragraphs */
-  ME_PropagateCharOffset(next_para, end_len);
+  ME_PropagateCharOffset(next_para, eol_str->nLen);
   editor->nParagraphs++;
   
   return new_para;
@@ -344,7 +340,7 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
   assert(pRun->type == diRun);
   assert(pRun->member.run.nFlags & MERF_ENDPARA);
 
-  end_len = pRun->member.run.nCR + pRun->member.run.nLF;
+  end_len = pRun->member.run.strText->nLen;
 
   {
     /* null char format operation to store the original char format for the ENDPARA run */
@@ -356,8 +352,8 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
   if (undo)
   {
     undo->nStart = pNext->member.para.nCharOfs - end_len;
-    undo->nCR = pRun->member.run.nCR;
-    undo->nLF = pRun->member.run.nLF;
+    undo->eol_str = pRun->member.run.strText;
+    pRun->member.run.strText = NULL; /* Avoid freeing the string */
   }
   if (!keepFirstParaFormat)
   {
diff --git a/dlls/riched20/run.c b/dlls/riched20/run.c
index d7fdfa6..1f8cc18 100644
--- a/dlls/riched20/run.c
+++ b/dlls/riched20/run.c
@@ -127,12 +127,8 @@ 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) {
-          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);
+        assert(p->member.run.strText->nLen);
+        ofs += p->member.run.strText->nLen;
         break;
       case diCell:
         TRACE_(richedit_check)("cell\n");
diff --git a/dlls/riched20/string.c b/dlls/riched20/string.c
index c4abc6f..ee33214 100644
--- a/dlls/riched20/string.c
+++ b/dlls/riched20/string.c
@@ -83,6 +83,7 @@ ME_String *ME_StrDup(const ME_String *s)
 
 void ME_DestroyString(ME_String *s)
 {
+  if (!s) return;
   FREE_OBJ(s->szData);
   FREE_OBJ(s);
 }
diff --git a/dlls/riched20/table.c b/dlls/riched20/table.c
index 0b6eaf4..e7eca24 100644
--- a/dlls/riched20/table.c
+++ b/dlls/riched20/table.c
@@ -58,8 +58,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit_lists);
 
 static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor,
                                                   int nCursor,
-                                                  int numCR,
-                                                  int numLF,
+                                                  ME_String *eol_str,
                                                   int paraFlags)
 {
   ME_Style *pStyle = ME_GetInsertStyle(editor, nCursor);
@@ -70,7 +69,7 @@ static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor,
     cursor = &editor->pCursors[nCursor];
   }
 
-  tp = ME_SplitParagraph(editor, cursor->pRun, pStyle, numCR, numLF, paraFlags);
+  tp = ME_SplitParagraph(editor, cursor->pRun, pStyle, eol_str, paraFlags);
   cursor->pRun = ME_FindItemFwd(tp, diRun);
   return tp;
 }
@@ -78,7 +77,9 @@ static ME_DisplayItem* ME_InsertEndParaFromCursor(ME_TextEditor *editor,
 ME_DisplayItem* ME_InsertTableRowStartFromCursor(ME_TextEditor *editor)
 {
   ME_DisplayItem *para;
-  para = ME_InsertEndParaFromCursor(editor, 0, 1, 1, MEPF_ROWSTART);
+  WCHAR cr_lf[] = {'\r', '\n', 0};
+  ME_String *eol_str = ME_MakeStringN(cr_lf, 2);
+  para = ME_InsertEndParaFromCursor(editor, 0, eol_str, MEPF_ROWSTART);
   return para->member.para.prev_para;
 }
 
@@ -118,14 +119,18 @@ ME_DisplayItem* ME_InsertTableRowStartAtParagraph(ME_TextEditor *editor,
 ME_DisplayItem* ME_InsertTableCellFromCursor(ME_TextEditor *editor)
 {
   ME_DisplayItem *para;
-  para = ME_InsertEndParaFromCursor(editor, 0, 1, 0, MEPF_CELL);
+  WCHAR cr = '\r';
+  ME_String *eol_str = ME_MakeStringN(&cr, 1);
+  para = ME_InsertEndParaFromCursor(editor, 0, eol_str, MEPF_CELL);
   return para;
 }
 
 ME_DisplayItem* ME_InsertTableRowEndFromCursor(ME_TextEditor *editor)
 {
   ME_DisplayItem *para;
-  para = ME_InsertEndParaFromCursor(editor, 0, 1, 1, MEPF_ROWEND);
+  WCHAR cr_lf[] = {'\r', '\n', 0};
+  ME_String *eol_str = ME_MakeStringN(cr_lf, 2);
+  para = ME_InsertEndParaFromCursor(editor, 0, eol_str, MEPF_ROWEND);
   return para->member.para.prev_para;
 }
 
@@ -283,7 +288,7 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars)
                     - end_para->member.para.nCharOfs;
     if (remaining)
     {
-      assert(remaining < c2.pRun->member.run.nCR + c2.pRun->member.run.nLF);
+      assert(remaining < c2.pRun->member.run.strText->nLen);
       end_para = end_para->member.para.next_para;
     }
   }
@@ -331,7 +336,7 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars)
         {
           ME_Run *end_run = &ME_FindItemBack(next_para, diRun)->member.run;
           int nCharsNew = (next_para->member.para.nCharOfs - nOfs
-                           - end_run->nCR - end_run->nLF);
+                           - end_run->strText->nLen);
           nCharsNew = max(nCharsNew, 0);
           assert(nCharsNew <= *nChars);
           *nChars = nCharsNew;
diff --git a/dlls/riched20/undo.c b/dlls/riched20/undo.c
index 49802a3..d845550 100644
--- a/dlls/riched20/undo.c
+++ b/dlls/riched20/undo.c
@@ -56,7 +56,6 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp
   else
   {
     ME_DisplayItem *pItem = (ME_DisplayItem *)ALLOC_OBJ(ME_UndoItem);
-    ((ME_UndoItem *)pItem)->nCR = ((ME_UndoItem *)pItem)->nLF = -1;
     switch(type)
     {
     case diUndoPotentialEndTransaction:
@@ -329,8 +328,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
     ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
     if (tmp.nOffset)
       tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset);
-    assert(pUItem->nCR >= 0);
-    assert(pUItem->nLF >= 0);
+    assert(pUItem->eol_str);
     this_para = ME_GetParagraph(tmp.pRun);
     bFixRowStart = this_para->member.para.nFlags & MEPF_ROWSTART;
     if (bFixRowStart)
@@ -340,7 +338,7 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
       this_para->member.para.nFlags &= ~MEPF_ROWSTART;
     }
     new_para = ME_SplitParagraph(editor, tmp.pRun, tmp.pRun->member.run.style,
-                                 pUItem->nCR, pUItem->nLF, paraFlags);
+                                 pUItem->eol_str, paraFlags);
     if (bFixRowStart)
       new_para->member.para.nFlags |= MEPF_ROWSTART;
     assert(pItem->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
diff --git a/dlls/riched20/writer.c b/dlls/riched20/writer.c
index 6ae3ccc..5a5135e 100644
--- a/dlls/riched20/writer.c
+++ b/dlls/riched20/writer.c
@@ -877,8 +877,7 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
               return FALSE;
           }
           /* 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;
+          nChars = max(0, nChars - p->member.run.strText->nLen);
         } else if (p->member.run.nFlags & MERF_ENDROW) {
           if (!ME_StreamOutPrint(pStream, "\\line \r\n"))
             return FALSE;
@@ -927,53 +926,24 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n
 
   if (!item)
     return FALSE;
-   
+
   if (dwFormat & SF_USECODEPAGE)
     nCodePage = HIWORD(dwFormat);
 
   /* TODO: Handle SF_TEXTIZED */
-  
+
   while (success && nChars && item) {
-    nLen = ME_StrLen(item->member.run.strText) - nStart;
-    if (nLen > nChars)
-      nLen = nChars;
+    nLen = min(nChars, ME_StrLen(item->member.run.strText) - nStart);
 
-    if (item->member.run.nFlags & MERF_ENDPARA) {
+    if (!editor->bEmulateVersion10 && item->member.run.nFlags & MERF_ENDPARA)
+    {
       static const WCHAR szEOL[2] = { '\r', '\n' };
-      
-      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++;
-        }
-      }
+
+      /* 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);
     } else {
       if (dwFormat & SF_UNICODE)
         success = ME_StreamOutMove(pStream, (const char *)(item->member.run.strText->szData + nStart),
@@ -993,12 +963,12 @@ ME_StreamOutText(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int n
         success = ME_StreamOutMove(pStream, buffer, nSize);
       }
     }
-    
+
     nChars -= nLen;
     nStart = 0;
     item = ME_FindItemFwd(item, diRun);
   }
-  
+
   FREE_OBJ(buffer);
   return success;
 }
diff --git a/dlls/riched32/tests/editor.c b/dlls/riched32/tests/editor.c
index b8bd6eb..fe2d1d5 100644
--- a/dlls/riched32/tests/editor.c
+++ b/dlls/riched32/tests/editor.c
@@ -672,8 +672,15 @@ static void run_tests_EM_FINDTEXT(HWND hwnd, const char *name, struct find_s *fi
   int i;
 
   for (i = 0; i < num_tests; i++) {
-    check_EM_FINDTEXT(hwnd, name, &find[i], i);
-    check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
+    if (*name == '3' && i == 0) {
+        todo_wine {
+            check_EM_FINDTEXT(hwnd, name, &find[i], i);
+            check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
+        }
+    } else {
+        check_EM_FINDTEXT(hwnd, name, &find[i], i);
+        check_EM_FINDTEXTEX(hwnd, name, &find[i], i);
+    }
   }
 }
 
@@ -694,7 +701,7 @@ static void test_EM_FINDTEXT(void)
   SendMessage(hwndRichEdit, WM_SETTEXT, 0, (LPARAM) haystack2);
 
   /* Haystack text 2 (with EOL characters) */
-  todo_wine run_tests_EM_FINDTEXT(hwndRichEdit, "3", find_tests3,
+  run_tests_EM_FINDTEXT(hwndRichEdit, "3", find_tests3,
       sizeof(find_tests3)/sizeof(struct find_s));
 
   DestroyWindow(hwndRichEdit);


More information about the wine-patches mailing list