From: larrybr Date: Sun, 5 Nov 2023 19:42:00 +0000 (+0000) Subject: Input working. No line-editor provisions yet. (WIP, but suitable for testing.) X-Git-Tag: version-3.45.0~134^2~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ff396346256f189f1ed336f630c191c57583f337;p=thirdparty%2Fsqlite.git Input working. No line-editor provisions yet. (WIP, but suitable for testing.) FossilOrigin-Name: e8568b1d925c2118eb08394dd8aa50cfb521240f87668f535ec4a03e67dc9a09 --- diff --git a/manifest b/manifest index 914526c556..da6d8f4914 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Setup,\stakedown,\smode\sset\sand\soutput\sworking.\sNo\sinput\syet.\s(WIP) -D 2023-11-05T01:21:14.743 +C Input\sworking.\sNo\sline-editor\sprovisions\syet.\s(WIP,\sbut\ssuitable\sfor\stesting.) +D 2023-11-05T19:42:00.134 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -669,8 +669,8 @@ F src/btreeInt.h ef12a72b708677e48d6bc8dcd66fed25434740568b89e2cfa368093cfc5b9d1 F src/build.c 189e4517d67f09f0a3e0d8e1faa6e2ef0c2e95f6ac82e33c912cb7efa2a359cc F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e -F src/console_io.c 484a4ad56c18ddc62b845494f8ac6e06df9f9b0bc2fa60ac2dcba74635bdf8da x -F src/console_io.h 6b7c86a5778445e507a089b9808803e4523e2989f33c04692e008eae3f0f4d8a +F src/console_io.c a04f62d1930d32f0bda26b546e9b3d6455e7caaee4ea7624be4b1ef7ea2329b7 x +F src/console_io.h 49680984d2a121697ccb2620f9e8465393d61c3edc3d5720c77dfa0a1f4a7389 F src/ctime.c 23331529e654be40ca97d171cbbffe9b3d4c71cc53b78fe5501230675952da8b F src/date.c eebc54a00e888d3c56147779e9f361b77d62fd69ff2008c5373946aa1ba1d574 F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782 @@ -2144,8 +2144,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 64abef8314b8544fdc7b71317d61a4641dc607a1ae42b8ff21543226fd338ba2 -R 9aec452b903f28bc0cbf638b7c11370e +P dfea85be1fb927ea446c9d98bae42ba1197bdab098aa6d95aa512a37d07a1e52 +R 4898fd3a7f002f1e4e422622974a0785 U larrybr -Z 37ecbe5d111f6f842b9b1e97c1e0e0d1 +Z c9314460b6b28a6cd16041af96151d83 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 5e27b835d6..c3c4b37173 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -dfea85be1fb927ea446c9d98bae42ba1197bdab098aa6d95aa512a37d07a1e52 \ No newline at end of file +e8568b1d925c2118eb08394dd8aa50cfb521240f87668f535ec4a03e67dc9a09 \ No newline at end of file diff --git a/src/console_io.c b/src/console_io.c index 8c4db84396..991479e0f8 100755 --- a/src/console_io.c +++ b/src/console_io.c @@ -8,7 +8,7 @@ ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** -************************************************************************* +******************************************************************************** ** This file implements various interfaces used for console I/O by the ** SQLite project command-line tools, as explained in console_io.h . */ @@ -28,7 +28,7 @@ # ifdef SHELL_LEGACY_CONSOLE_IO # define SHELL_CON_TRANSLATE 2 /* Use UTF-8/MBCS translation for console I/O */ # else -# define SHELL_CON_TRANSLATE 1 /* Use wchar APIs for console I/O */ +# define SHELL_CON_TRANSLATE 1 /* Use WCHAR Windows APIs for console I/O */ # endif #else # include @@ -45,91 +45,102 @@ static HANDLE handleOfFile(FILE *pf){ } #endif -static short fileOfConsole(FILE *pf){ +typedef struct PerStreamTags { #if SHELL_CON_TRANSLATE + DWORD consMode; + HANDLE hx; +#endif + FILE *pf; +} PerStreamTags; + +static short fileOfConsole(FILE *pf, PerStreamTags *ppst){ +#if SHELL_CON_TRANSLATE + short rv = 0; DWORD dwj; HANDLE fh = handleOfFile(pf); if( INVALID_HANDLE_VALUE != fh ){ - return (GetFileType(fh) == FILE_TYPE_CHAR && GetConsoleMode(fh,&dwj)); - }else return 0; + rv = (GetFileType(fh) == FILE_TYPE_CHAR && GetConsoleMode(fh,&dwj)); + if( rv ){ + ppst->hx = fh; + ppst->pf = pf; + GetConsoleMode(fh, &ppst->consMode); + } + } + return rv; #else return (short)isatty(fileno(pf)); #endif } #define SHELL_INVALID_FILE_PTR ((FILE *)sizeof(FILE*)) +#define SHELL_INVALID_CONS_MODE 0xFFFF0000 + +#if SHELL_CON_TRANSLATE +# define SHELL_CONI_MODE \ + (ENABLE_ECHO_INPUT | ENABLE_INSERT_MODE | ENABLE_LINE_INPUT | 0x80 \ + | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_PROCESSED_INPUT) +# define SHELL_CONO_MODE (ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT \ + | ENABLE_VIRTUAL_TERMINAL_PROCESSING) +#endif typedef struct ConsoleInfo { - /* int iDefaultFmode; */ - ConsoleStdConsStreams cscs; + /* int iInitialFmode[3]; + ** Above only needed for legacy console I/O for callable CLI. + ** Because that state cannot be obtained from each FILE *, + ** there will be no exact restoration of console state for + ** the CLI when built with SHELL_LEGACY_CONSOLE_IO defined. + */ + PerStreamTags pst[3]; #if SHELL_CON_TRANSLATE - HANDLE hIn; HANDLE hOut; HANDLE hErr; - HANDLE hLowest; + unsigned char haveInput; + unsigned char outputIx; + unsigned char stdinEof; #endif - FILE *pfIn; FILE *pfOut; FILE *pfErr; + ConsoleStdConsStreams cscs; } ConsoleInfo; -static ConsoleInfo consoleInfo = { - /* 0, iDefaultFmode */ - CSCS_NoConsole, #if SHELL_CON_TRANSLATE - INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, - INVALID_HANDLE_VALUE, +# define CI_INITIALIZER \ + {SHELL_INVALID_CONS_MODE, INVALID_HANDLE_VALUE, SHELL_INVALID_FILE_PTR } +#else +# define CI_INITIALIZER { SHELL_INVALID_FILE_PTR } #endif - SHELL_INVALID_FILE_PTR, SHELL_INVALID_FILE_PTR, SHELL_INVALID_FILE_PTR -}; -#undef SHELL_INVALID_FILE_PTR -#if SHELL_CON_TRANSLATE == 1 -# define SHELL_CON_MODE_CSZ _O_U16TEXT -#elif SHELL_CON_TRANSLATE == 2 -# define SHELL_CON_MODE_CSZ _O_U8TEXT +static ConsoleInfo consoleInfo = { + /* {0,0,0}, // iInitialFmode */ + { /* pst */ CI_INITIALIZER, CI_INITIALIZER, CI_INITIALIZER }, +#if SHELL_CON_TRANSLATE + 0, 0, 1, /* haveInput, outputIx, stdinEof */ #endif + CSCS_NoConsole +}; +#undef CI_INITIALIZER INT_LINKAGE ConsoleStdConsStreams consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ){ ConsoleStdConsStreams rv = CSCS_NoConsole; - if( fileOfConsole(pfErr) ){ - rv |= CSCS_ErrConsole; - consoleInfo.pfErr = pfErr; + FILE *apf[3] = { pfIn, pfOut, pfErr }; + int ix; + for( ix = 2; ix >= 0; --ix ){ + PerStreamTags *ppst = &consoleInfo.pst[ix]; + if( fileOfConsole(apf[ix], ppst) ){ #if SHELL_CON_TRANSLATE - fflush(pfErr); -# if SHELL_CON_TRANSLATE == 1 - _setmode(_fileno(pfErr), _O_U16TEXT); - _setmode(_fileno(pfErr), _O_BINARY); -# elif SHELL_CON_TRANSLATE == 2 - _setmode(_fileno(pfErr), _O_U8TEXT); - _setmode(_fileno(pfErr), _O_TEXT); -# endif - consoleInfo.hLowest = consoleInfo.hErr = handleOfFile(pfErr); -#endif - } - if( fileOfConsole(pfOut) ){ - rv |= CSCS_OutConsole; - consoleInfo.pfOut = pfOut; -#if SHELL_CON_TRANSLATE - fflush(pfOut); -# if SHELL_CON_TRANSLATE == 1 - _setmode(_fileno(pfOut), _O_U16TEXT); - _setmode(_fileno(pfOut), _O_BINARY); -# elif SHELL_CON_TRANSLATE == 2 - _setmode(_fileno(pfOut), _O_U8TEXT); - _setmode(_fileno(pfOut), _O_TEXT); -# endif - consoleInfo.hLowest = consoleInfo.hOut = handleOfFile(pfOut); + DWORD cm = (ix==0)? SHELL_CONI_MODE : SHELL_CONO_MODE; + if( ix==0 ){ + consoleInfo.haveInput = 1; + consoleInfo.stdinEof = 0; + }else{ + consoleInfo.outputIx |= ix; + } + SetConsoleMode(ppst->hx, cm); + fprintf(stderr, "consMode[%d]: %02x -> %02x\n", ix, ppst->consMode, cm); #endif - } - if( fileOfConsole(pfIn) ){ - rv |= CSCS_InConsole; - consoleInfo.pfIn = pfIn; -#if SHELL_CON_TRANSLATE == 1 - _setmode(_fileno(pfIn), _O_U16TEXT); - _setmode(_fileno(pfIn), _O_BINARY); - consoleInfo.hLowest = consoleInfo.hIn = handleOfFile(pfIn); -#elif SHELL_CON_TRANSLATE == 2 - _setmode(_fileno(pfIn), _O_U8TEXT); - _setmode(_fileno(pfIn), _O_TEXT); - consoleInfo.hLowest = consoleInfo.hIn = handleOfFile(pfIn); + rv |= (CSCS_InConsole< 0 ) fflush(apf[ix]); +#if SHELL_CON_TRANSLATE == 2 + _setmode(_fileno(apf[ix]), _O_U8TEXT); + _setmode(_fileno(apf[ix]), _O_TEXT); #endif } consoleInfo.cscs = rv; @@ -137,66 +148,69 @@ consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ){ } INT_LINKAGE void SQLITE_CDECL consoleRestore( void ){ -#if SHELL_CON_TRANSLATE if( consoleInfo.cscs ){ - /* ToDo: Read these modes in consoleClassifySetup somehow. - ** A _get_fmode() call almost works. But not with gcc, yet. - ** This has to be done to make the CLI a callable function. - */ - int tmode = _O_TEXT, xmode = _O_U8TEXT; - if( consoleInfo.cscs & CSCS_InConsole ){ - _setmode(_fileno(consoleInfo.pfIn), tmode); - _setmode(_fileno(consoleInfo.pfIn), xmode); - } - if( consoleInfo.cscs & CSCS_OutConsole ){ - _setmode(_fileno(consoleInfo.pfOut), tmode); - _setmode(_fileno(consoleInfo.pfOut), xmode); - } - if( consoleInfo.cscs & CSCS_ErrConsole ){ - _setmode(_fileno(consoleInfo.pfErr), tmode); - _setmode(_fileno(consoleInfo.pfErr), xmode); - } - } + int ix; + for( ix=0; ix<3; ++ix ){ + if( consoleInfo.cscs & (CSCS_InConsole<hx, ppst->consMode); + ppst->hx = INVALID_HANDLE_VALUE; #endif + ppst->pf = SHELL_INVALID_FILE_PTR; + } + consoleInfo.cscs = CSCS_NoConsole; +#if SHELL_CON_TRANSLATE + consoleInfo.stdinEof = consoleInfo.haveInput = consoleInfo.outputIx= 0; +#endif + } + } } +#undef SHELL_INVALID_FILE_PTR static short isConOut(FILE *pf){ - if( pf==consoleInfo.pfOut ) return 1; - else if( pf==consoleInfo.pfErr ) return 2; + if( pf==consoleInfo.pst[1].pf ) return 1; + else if( pf==consoleInfo.pst[2].pf ) return 2; else return 0; } -INT_LINKAGE void setBinaryMode(FILE *pf, short bFlush){ +#if SHELL_CON_TRANSLATE +static void setModeFlushQ(FILE *pf, short bFlush, int mode){ short ico = isConOut(pf); - if( ico || bFlush ) fflush(pf); -#if SHELL_CON_TRANSLATE == 2 - _setmode(_fileno(pf), _O_BINARY); -#elif SHELL_CON_TRANSLATE == 1 - /* Never change between text/binary on UTF-16 console streamss. */ - if( !ico && !(consoleInfo.pfIn==pf)) _setmode(_fileno(pf), _O_BINARY); + if( ico>1 || bFlush ) fflush(pf); + _setmode(_fileno(pf), mode); +} +#else +# define setModeFlushQ(f, b, m) if(isConOut(f)>0||b) fflush(f) #endif + +INT_LINKAGE void setBinaryMode(FILE *pf, short bFlush){ + setModeFlushQ(pf, bFlush, _O_BINARY); } INT_LINKAGE void setTextMode(FILE *pf, short bFlush){ - short ico = isConOut(pf); - if( ico || bFlush ) fflush(pf); -#if SHELL_CON_TRANSLATE == 2 - _setmode(_fileno(pf), _O_TEXT); -#elif SHELL_CON_TRANSLATE == 1 - /* Never change between text/binary on UTF-16 console streamss. */ - if( !ico && !(consoleInfo.pfIn==pf)) _setmode(_fileno(pf), _O_TEXT); -#endif + setModeFlushQ(pf, bFlush, _O_TEXT); } -/* Later: Factor common code out of above 2 procs. */ +#undef setModeFlushQ INT_LINKAGE int fprintfUtf8(FILE *pfO, const char *zFormat, ...){ va_list ap; int rv = 0; +#if SHELL_CON_TRANSLATE short on = isConOut(pfO); +#endif va_start(ap, zFormat); - if( on > 0 ){ #if SHELL_CON_TRANSLATE + if( on > 0 ){ char *z1 = sqlite3_vmprintf(zFormat, ap); # if SHELL_CON_TRANSLATE == 2 /* Legacy translation to active code page, then MBCS chars out. */ @@ -216,7 +230,7 @@ INT_LINKAGE int fprintfUtf8(FILE *pfO, const char *zFormat, ...){ if( nwc>0 ){ zw2 = sqlite3_malloc64((nwc+1)*sizeof(WCHAR)); if( zw2!=NULL ){ - HANDLE ho = (on==1)? consoleInfo.hOut : consoleInfo.hErr; + HANDLE ho = (on==1)? consoleInfo.pst[1].hx : consoleInfo.pst[2].hx; nwc = MultiByteToWideChar(CP_UTF8,0,z1,rv,zw2,nwc); zw2[nwc] = 0; WriteConsoleW(ho, zw2, nwc, 0, NULL); @@ -226,32 +240,112 @@ INT_LINKAGE int fprintfUtf8(FILE *pfO, const char *zFormat, ...){ } # endif sqlite3_free(z1); -#else -#endif }else{ +#endif rv = vfprintf(pfO, zFormat, ap); +#if SHELL_CON_TRANSLATE } +#endif va_end(ap); return rv; } -INT_LINKAGE int fgetsUtf8(char *buf, int ncMax, FILE *pfIn){ - return 0; +INT_LINKAGE char* fgetsUtf8(char *cBuf, int ncMax, FILE *pfIn){ + if( pfIn==0 ) pfIn = stdin; +#if SHELL_CON_TRANSLATE + if( pfIn == consoleInfo.pst[0].pf ){ + static const int nwcLen = 150; + WCHAR wcBuf[nwcLen+1]; + int lend = 0, noc = 0; + if( consoleInfo.stdinEof ) return 0; + if( ncMax > 0 ) cBuf[0] = 0; + while( noc < ncMax-8-1 && !lend ){ + /* There is room for at least 2 more characters and a 0-terminator. */ + int na = (ncMax > nwcLen*4+1 + noc)? nwcLen : (ncMax-1 - noc)/4; + DWORD nbr = 0; + BOOL bRC = ReadConsoleW(consoleInfo.pst[0].hx, wcBuf, na, &nbr, 0); + if( bRC && nbr>0 && (wcBuf[nbr-1]&0xF800)==0xD800 ){ + /* Last WHAR read is first of a UTF-16 surrogate pair. Grab its mate. */ + DWORD nbrx; + bRC &= ReadConsoleW(consoleInfo.pst[0].hx, wcBuf+nbr, 1, &nbrx, 0); + if( bRC ) nbr += nbrx; + } + hd(wcBuf,nbr); + if( !bRC || (noc==0 && nbr==0) ) return 0; + if( nbr > 0 ){ + int nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,0,0,0,0); + if( nmb != 0 && noc+nmb <= ncMax ){ + int iseg = noc; + nmb = WideCharToMultiByte(CP_UTF8, 0, wcBuf,nbr,cBuf+noc,nmb,0,0); + noc += nmb; + /* Fixup line-ends as coded by Windows for CR (or "Enter".) + ** Note that this is done without regard for any setModeText() + ** call that might have been done on the interactive input. + */ + if( noc > 0 ){ + if( cBuf[noc-1]=='\n' ){ + lend = 1; + if( noc > 1 && cBuf[noc-2]=='\r' ){ + cBuf[noc-2] = '\n'; + --noc; + } + } + } + /* Check for ^Z (anywhere in line) too. */ + while( iseg < noc ){ + if( cBuf[iseg]==0x1a ){ + consoleInfo.stdinEof = 1; + noc = iseg; /* Chop ^Z and anything following. */ + break; + } + ++iseg; + } + }else break; /* Drop apparent garbage in. (Could assert.) */ + }else break; + } + /* If got nothing, (after ^Z chop), must be at end-of-file. */ + if( noc == 0 ) return 0; + cBuf[noc] = 0; + return cBuf; + }else{ +#endif + return fgets(cBuf, ncMax, pfIn); +#if SHELL_CON_TRANSLATE + } +#endif } #ifdef TEST_CIO // cl -Zi -I. -DWIN32 -DTEST_CIO sqlite3.c src/console_io.c -Fecio.exe -// gcc -I. -DWIN32 -DTEST_CIO -o cio sqlite3.c src/console_io.c -o cio.exe +// gcc -I. -DWIN32 -DTEST_CIO sqlite3.c src/console_io.c -o cio.exe const char *prompts[] = { "main", "cont" }; Prompts goofy = { 2, prompts }; int main(int na, char *av[]){ ConsoleStdConsStreams cc = consoleClassifySetup(stdin, stdout, stderr); + const char *zt = "Math: ±×÷∂∆∙√∞∩∫≈≠≡≤≥\n" + "Hiragana: 亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦鯵梓圧斡扱" + "宛姐虻飴絢綾鮎或粟袷安庵按暗案闇鞍杏\n" + "Simplified Chinese: 餐参蚕残惭惨灿掺孱骖璨粲黪\n" + "Geometric Shapes: ■□▪▫▲△▼▽◆◇◊○◌◎●◢◣◤◥◦\n" + "Boxes single: ─━│┃┄┅┆┇┈┉┊┋ ┌┍┎┏┐┑┒┓└┕┖┗┘┙┚┛├┝┞┟┠┡┢┣┤┥┦┧┨┩┪┫┬┭┮┯┰┱┲┳" + "┴┵┶┷┸┹┺┻┼┽┾┿╀╁╂╃╄╅╆╇╈╉╊╋\n" + "Boxes double: ═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡╢╣╤╥╦╧╨╩╪╫╬\n" + "Rounded corners and diagonals: ╭╮╯╰╱╲╳\n" + ; + char inBuf[150]; setTextMode(stdout, 1); setTextMode(stderr, 1); - fprintfUtf8(stderr, "%d\n", cc); + fprintfUtf8(stderr, "Console streams: %d, CP_UTF8 valid: %d\n", cc, + IsValidCodePage(CP_UTF8)); fprintfUtf8(stdout, "%s=%d\n", "∑(1st 7 primes)", 42); fprintfUtf8(stderr, "%s\n", "∫ (1/x) dx ≡ ln(x)"); + fprintfUtf8(stdout, "%s", zt); + fprintfUtf8(stderr, "Entering input/echo loop." + " Type or copy/paste, or EOF to exit.\n"); + while( fprintfUtf8(stdout,"? ") && fgetsUtf8(inBuf, sizeof(inBuf), stdin) ){ + fprintfUtf8(stdout, "! %s", inBuf); + } consoleRestore(); return 0; } diff --git a/src/console_io.h b/src/console_io.h index 444c3e0e65..6f838427de 100644 --- a/src/console_io.h +++ b/src/console_io.h @@ -60,6 +60,10 @@ typedef enum ConsoleStdConsStreams { ** ** On some platforms, stream or console mode alteration (aka ** "Setup") may be made which is undone by consoleRestore(). +** +** Applications which run an inferior (child) process which +** inherits the same I/O streams may call this function after +** such a process exits to guard against console mode changes. */ INT_LINKAGE ConsoleStdConsStreams consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ); @@ -70,7 +74,13 @@ consoleClassifySetup( FILE *pfIn, FILE *pfOut, FILE *pfErr ); ** This should be called after consoleClassifySetup() and ** before the process terminates normally. It is suitable ** for use with the atexit() C library procedure. After -** this call, no I/O should be done with the console. +** this call, no I/O should be done with the console +** until consoleClassifySetup(...) is called again. +** +** Applications which run an inferior (child) process that +** inherits the same I/O streams might call this procedure +** before so that said process will have a console setup +** however users have configured it or come to expect. */ INT_LINKAGE void SQLITE_CDECL consoleRestore( void ); @@ -87,9 +97,10 @@ INT_LINKAGE int fprintfUtf8(FILE *pfO, const char *zFormat, ...); ** Collect input like fgets(...) with special provisions for input ** from the console on platforms that require same. Defers to the ** C library fgets() when input is not from the console. Newline -** translation may be done as set by set{Binary,Text}Mode(). +** translation may be done as set by set{Binary,Text}Mode(). As a +** convenience, pfIn==NULL is treated as stdin. */ -INT_LINKAGE int fgetsUtf8(char *buf, int ncMax, FILE *pfIn); +INT_LINKAGE char* fgetsUtf8(char *cBuf, int ncMax, FILE *pfIn); /* ** Set given stream for binary mode, where newline translation is @@ -100,8 +111,9 @@ INT_LINKAGE int fgetsUtf8(char *buf, int ncMax, FILE *pfIn); ** An additional side-effect is that if the stream is one passed ** to consoleClassifySetup() as an output, it is flushed first. ** -** Note that binary/text mode has no effect on console output -** translation. Newline chars start a new line on all platforms. +** Note that binary/text mode has no effect on console I/O +** translation. On all platforms, newline to the console starts +** a new line and CR,LF chars from the console become a newline. */ INT_LINKAGE void setBinaryMode(FILE *, short bFlush); INT_LINKAGE void setTextMode(FILE *, short bFlush);