[2/7] richedit: End of line sequence limited to 2 carriage returns.

Dylan Smith dylan.ah.smith at gmail.com
Tue Jan 27 02:38:49 CST 2009


riched32.dll does preserve the carraige returns and line feeds unlike
later versions of the richedit control, however the tests previously
missed the fact that a sequence of carriage returns followed by a line
feed (e.g. \r\r\r\n) can actually cause multiple paragraph breaks.

It is the \r\r\n sequence that is handled specially.  For v1.0 this
becomes a line break, for v2.0+ this becomes a space.

The similarities between the version allow for a simpler version of the
ME_InsertTextFromCursor to be written.  I chose to also get rid of
unnecessary continue statements, and considions that were always true,
since they made the function hard to read.
---
 dlls/riched20/caret.c        |  131 ++++++++++++++---------------------------
 dlls/riched32/tests/editor.c |   27 ++------
 2 files changed, 52 insertions(+), 106 deletions(-)
-------------- next part --------------
diff --git a/dlls/riched20/caret.c b/dlls/riched20/caret.c
index bd0b149..460f9be 100644
--- a/dlls/riched20/caret.c
+++ b/dlls/riched20/caret.c
@@ -517,107 +517,66 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
   if(editor->nTextLimit < oldLen +len)
     editor->nTextLimit = oldLen + len;
 
+  pos = str;
+
   while (len)
   {
-    pos = str;
     /* FIXME this sucks - no respect for unicode (what else can be a line separator in unicode?) */
-    while(pos-str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
+    while(pos - str < len && *pos != '\r' && *pos != '\n' && *pos != '\t')
       pos++;
-    if (pos-str < len && *pos == '\t') { /* handle tabs */
-      WCHAR tab = '\t';
 
-      if (pos!=str)
-        ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
-    
+    if (pos != str) { /* handle text */
+      ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
+    } else if (*pos == '\t') { /* handle tabs */
+      WCHAR tab = '\t';
       ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB);
- 
       pos++;
-      if(pos-str <= len) {
-        len -= pos - str;
-        str = pos;
-        continue;
-      }
-    }
-    /* handle special \r\r\n sequence (richedit 2.x and higher only) */
-    if (!editor->bEmulateVersion10 && pos-str < len-2 && pos[0] == '\r' && pos[1] == '\r' && pos[2] == '\n') {
-      WCHAR space = ' ';
-
-      if (pos!=str)
-        ME_InternalInsertTextFromCursor(editor, nCursor, str, pos-str, style, 0);
-
-      ME_InternalInsertTextFromCursor(editor, nCursor, &space, 1, style, 0);
-
-      pos+=3;
-      if(pos-str <= len) {
-        len -= pos - str;
-        str = pos;
-        continue;
-      }
-    }
-    if (pos-str < len) {   /* handle EOLs */
+    } else { /* 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];
-      if (p->nOffset) {
-        ME_SplitRunSimple(editor, p->pRun, p->nOffset);
-        p = &editor->pCursors[nCursor];
-      }
-      tmp_style = ME_GetInsertStyle(editor, nCursor);
-      /* ME_SplitParagraph increases style refcount */
-
-      /* 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) {
-          /* 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;
-          numLF = 1;
-        } else {
-          /* Found some other content past the run of \r's */
-          pos++;
-          numCR = 1; numLF = 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++;
+        else if (len > 2 && pos[1] == '\r' && pos[2] == '\n')
+          numCR++, numLF++;
       } else {
-        if(pos-str < len && *pos =='\r')
-          pos++;
-        if(pos-str < len && *pos =='\n')
-          pos++;
-        numCR = 1; numLF = 0;
+        assert(*pos == '\n');
+        numLF++;
       }
-      tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, numCR, numLF, 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;
-
-      if(pos-str <= len) {
-        len -= pos - str;
-        str = pos;
-        continue;
+      pos += numCR + numLF;
+
+      if (!editor->bEmulateVersion10 && numCR == 2 && numLF == 1)
+      {
+        /* 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;
+
+        p = &editor->pCursors[nCursor];
+        if (p->nOffset) {
+          ME_SplitRunSimple(editor, p->pRun, p->nOffset);
+          p = &editor->pCursors[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);
+        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;
       }
     }
-    ME_InternalInsertTextFromCursor(editor, nCursor, str, len, style, 0);
-    len = 0;
+    len -= pos - str;
+    str = pos;
   }
 }
 
diff --git a/dlls/riched32/tests/editor.c b/dlls/riched32/tests/editor.c
index 1fab410..b01faee 100644
--- a/dlls/riched32/tests/editor.c
+++ b/dlls/riched32/tests/editor.c
@@ -392,12 +392,8 @@ static void test_EM_GETLINE(void)
     /* EM_GETLINE appends a "\r\0" to the end of the line
      * nCopied counts up to and including the '\r' */
     nCopied = SendMessage(hwndRichEdit, EM_GETLINE, gl[i].line, (LPARAM) dest);
-    if (i >= 1 && i <= 4)
-      todo_wine ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
-         expected_nCopied);
-    else
-      ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
-         expected_nCopied);
+    ok(nCopied == expected_nCopied, "%d: %d!=%d\n", i, nCopied,
+       expected_nCopied);
     /* two special cases since a parameter is passed via dest */
     if (gl[i].buffer_len == 0)
       ok(!dest[0] && !dest[1] && !strncmp(dest+2, origdest+2, nBuf-2),
@@ -407,20 +403,11 @@ static void test_EM_GETLINE(void)
          !strncmp(dest+2, origdest+2, nBuf-2), "buffer_len=1\n");
     else
     {
-      if (i >= 1 && i <= 4)
-        todo_wine ok(!strncmp(dest, gl[i].text, expected_bytes_written),
-           "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
-      else
-        ok(!strncmp(dest, gl[i].text, expected_bytes_written),
-           "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
-      if (i >= 1 && i <= 2)
-        todo_wine ok(!strncmp(dest + expected_bytes_written, origdest
-                    + expected_bytes_written, nBuf - expected_bytes_written),
-           "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
-      else
-        ok(!strncmp(dest + expected_bytes_written, origdest
-                    + expected_bytes_written, nBuf - expected_bytes_written),
-           "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
+      ok(!strncmp(dest, gl[i].text, expected_bytes_written),
+         "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
+      ok(!strncmp(dest + expected_bytes_written, origdest
+                  + expected_bytes_written, nBuf - expected_bytes_written),
+         "%d: expected_bytes_written=%d\n", i, expected_bytes_written);
     }
   }
 


More information about the wine-patches mailing list