Dan Kegel : msvcrt: Improve CR CR LF handling.

Alexandre Julliard julliard at winehq.org
Fri Oct 5 04:55:59 CDT 2007


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

Author: Dan Kegel <dank at kegel.com>
Date:   Thu Oct  4 20:43:31 2007 -0700

msvcrt: Improve CR CR LF handling.

---

 dlls/msvcrt/file.c       |   17 ++++++++++++-----
 dlls/msvcrt/tests/file.c |   18 ++++++++++++++++++
 2 files changed, 30 insertions(+), 5 deletions(-)

diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index 4ceae0b..b878781 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -1639,15 +1639,21 @@ int CDECL _rmtmp(void)
 /*********************************************************************
  * (internal) remove_cr
  *
- *    Remove all \r inplace.
+ * Translate all \r\n to \n inplace.
  * return the number of \r removed
+ * Corner cases required by some apps:
+ *   \r\r\n -> \r\n
+ * BUG: should save state across calls somehow, so CR LF that
+ * straddles buffer boundary gets recognized properly?
  */
 static unsigned int remove_cr(char *buf, unsigned int count)
 {
     unsigned int i, j;
 
-    for (i = 0; i < count; i++) if (buf[i] == '\r') break;
-    for (j = i + 1; j < count; j++) if (buf[j] != '\r') buf[i++] = buf[j];
+    for (i=0, j=0; j < count; j++)
+        if ((buf[j] != '\r') || ((j+1) < count && buf[j+1] != '\n'))
+	    buf[i++] = buf[j];
+
     return count - i;
 }
 
@@ -2210,8 +2216,9 @@ int CDECL MSVCRT_fgetc(MSVCRT_FILE* file)
       j = *i;
     } else
       j = MSVCRT__filbuf(file);
-    if (!(MSVCRT_fdesc[file->_file].wxflag & WX_TEXT) || (j != '\r'))
-      return j;
+    if (!(MSVCRT_fdesc[file->_file].wxflag & WX_TEXT)
+    || ((j != '\r') || (file->_cnt && ((char *)file->_ptr)[0] != '\n')))
+        return j;
   } while(1);
 }
 
diff --git a/dlls/msvcrt/tests/file.c b/dlls/msvcrt/tests/file.c
index bdf0d0a..4a311e4 100644
--- a/dlls/msvcrt/tests/file.c
+++ b/dlls/msvcrt/tests/file.c
@@ -271,6 +271,23 @@ static void test_readmode( BOOL ascii_mode )
     unlink ("fdopen.tst");
 }
 
+static void test_asciimode(void)
+{
+    FILE *fp;
+    char buf[64];
+
+    /* Simple test of CR CR LF handling.  Test both fgets and fread code paths, they're different! */
+    fp = fopen("ascii.tst", "wb");
+    fputs("\r\r\n", fp);
+    fclose(fp);
+    fp = fopen("ascii.tst", "rt");
+    ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
+    ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
+    rewind(fp);
+    ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
+    fclose(fp);
+    unlink("ascii.tst");
+}
 
 static WCHAR* AtoW( const char* p )
 {
@@ -996,6 +1013,7 @@ START_TEST(file)
     test_fdopen();
     test_fopen_fclose_fcloseall();
     test_fileops();
+    test_asciimode();
     test_readmode(FALSE); /* binary mode */
     test_readmode(TRUE);  /* ascii mode */
     test_fgetc();




More information about the wine-cvs mailing list