ICU-3720 Make it possible to read from stdin.
Can't easily automate this test case

X-SVN-Rev: 16153
diff --git a/icu4c/source/io/ufile.c b/icu4c/source/io/ufile.c
index bcd9f09..19e95f6 100644
--- a/icu4c/source/io/ufile.c
+++ b/icu4c/source/io/ufile.c
@@ -27,6 +27,10 @@
 #include "cstring.h"
 #include "cmemory.h"
 
+#ifdef WIN32
+/* Windows likes to rename Unix-like functions */
+#define fileno _fileno
+#endif
 
 U_CAPI UFILE* U_EXPORT2 /* U_CAPI ... U_EXPORT2 added by Peter Kirk 17 Nov 2001 */
 u_finit(FILE        *f,
@@ -40,21 +44,18 @@
     }
 
     uprv_memset(result, 0, sizeof(UFILE));
+    result->fFileno = fileno(f);
 
 #ifdef WIN32
-    {
-        int filenum = _fileno(f);
-        if (0 <= filenum && filenum <= 2) {
-            /* stdin, stdout and stderr need to be special cased for Windows 98 */
-            result->fFile = &_iob[_fileno(f)];
-        }
-        else {
-            result->fFile = f;
-        }
+    if (0 <= result->fFileno && result->fFileno <= 2) {
+        /* stdin, stdout and stderr need to be special cased for Windows 98 */
+        result->fFile = &_iob[_fileno(f)];
     }
-#else
-    result->fFile = f;
+    else
 #endif
+    {
+        result->fFile = f;
+    }
 
     result->str.fBuffer = result->fUCBuffer;
     result->str.fPos    = result->fUCBuffer;
diff --git a/icu4c/source/io/ufile.h b/icu4c/source/io/ufile.h
index 0794144..8be6d73 100644
--- a/icu4c/source/io/ufile.h
+++ b/icu4c/source/io/ufile.h
@@ -68,6 +68,8 @@
     UChar       fUCBuffer[UFILE_UCHARBUFFER_SIZE];/* buffer used for toUnicode */
 
     UBool       fOwnFile;       /* TRUE if fFile should be closed */
+
+    int32_t     fFileno;        /* File number. Useful to determine if it's stdin. */
 };
 
 /**
diff --git a/icu4c/source/io/ustdio.c b/icu4c/source/io/ustdio.c
index dbb6560..28e1271 100644
--- a/icu4c/source/io/ustdio.c
+++ b/icu4c/source/io/ustdio.c
@@ -20,6 +20,7 @@
 #include "unicode/ustdio.h"
 #include "unicode/putil.h"
 #include "cmemory.h"
+#include "cstring.h"
 #include "ufile.h"
 #include "ufmt_cmn.h"
 #include "unicode/ucnv.h"
@@ -396,13 +397,16 @@
         return;
     }
 
-    /* shift the buffer if it isn't empty */
     str = &f->str;
     dataSize = (int32_t)(str->fLimit - str->fPos);
+    if (f->fFileno == 0 && dataSize > 0) {
+        /* Don't read from stdin too many times. There is still some data. */
+        return;
+    }
+
+    /* shift the buffer if it isn't empty */
     if(dataSize != 0) {
-        memmove(f->fUCBuffer,
-            str->fPos,
-            dataSize * sizeof(UChar));
+        uprv_memmove(f->fUCBuffer, str->fPos, dataSize * sizeof(UChar));
     }
 
 
@@ -414,10 +418,18 @@
     maxCPBytes = availLength / (f->fConverter!=NULL?(2*ucnv_getMinCharSize(f->fConverter)):1);
 
     /* Read in the data to convert */
-    bytesRead = (int32_t)fread(charBuffer,
-        sizeof(char),
-        ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE),
-        f->fFile);
+    if (f->fFileno == 0) {
+        /* Special case. Read from stdin one line at a time. */
+        char *retStr = fgets(charBuffer, ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE), f->fFile);
+        bytesRead = (retStr ? uprv_strlen(charBuffer) : 0);
+    }
+    else {
+        /* A normal file */
+        bytesRead = (int32_t)fread(charBuffer,
+            sizeof(char),
+            ufmt_min(maxCPBytes, UFILE_CHARBUFFER_SIZE),
+            f->fFile);
+    }
 
     /* Set up conversion parameters */
     status      = U_ZERO_ERROR;
@@ -555,7 +567,9 @@
     }
     else if (f) {
         /* otherwise, fill the buffer and return the next character */
-        ufile_fill_uchar_buffer(f);
+        if(f->str.fPos >= f->str.fLimit) {
+            ufile_fill_uchar_buffer(f);
+        }
         if(f->str.fPos < f->str.fLimit) {
             *ch = *(f->str.fPos)++;
             isValidChar = TRUE;
diff --git a/icu4c/source/test/iotest/filetst.c b/icu4c/source/test/iotest/filetst.c
index 9316d9e..1e7963f 100644
--- a/icu4c/source/test/iotest/filetst.c
+++ b/icu4c/source/test/iotest/filetst.c
@@ -23,8 +23,8 @@
 const char STANDARD_TEST_FILE[] = "iotest-c.txt";
 
 
-static void TestFileFromICU(UFILE *myFile) {
 #if !UCONFIG_NO_FORMATTING
+static void TestFileFromICU(UFILE *myFile) {
     int32_t n[1];
     float myFloat = -1234.0;
     int32_t newValuePtr[1];
@@ -317,6 +317,30 @@
     TestFileFromICU(u_finit(standardFile, NULL, NULL));
     fclose(standardFile);
 */
+}
+#endif
+
+static void StdinBuffering(void) {
+#if 0
+    UChar buff[255];
+    int32_t num = 0;
+    UFILE *uStdIn = NULL;
+    UFILE *uStdOut = NULL;
+    uStdIn = u_finit(stdin, NULL, NULL);
+    uStdOut = u_finit(stdout, NULL, NULL);
+    if (uStdIn == NULL)
+        return;
+
+    buff[0] = 0x40;
+    buff[1] = 0;
+    u_fgets(buff, sizeof(buff)/sizeof(buff[0]), uStdIn);
+    u_fprintf(uStdOut, "%S\n", buff);
+    u_fscanf(uStdIn, "%d", &num);
+    u_fprintf(uStdOut, "%d\n", num);
+    u_fscanf(uStdIn, "%d", &num);
+    u_fprintf(uStdOut, "%d\n", num);
+#else
+    log_verbose("Test disabled because it requires user interaction");
 #endif
 }
 
@@ -1415,6 +1439,7 @@
 #if !UCONFIG_NO_FORMATTING
     addTest(root, &TestFile, "file/TestFile");
 #endif
+    addTest(root, &StdinBuffering, "file/StdinBuffering");
     addTest(root, &TestfgetsBuffers, "file/TestfgetsBuffers");
     addTest(root, &TestfgetsLineCount, "file/TestfgetsLineCount");
     addTest(root, &TestfgetsNewLineHandling, "file/TestfgetsNewLineHandling");