From: larrybr Date: Fri, 14 Apr 2023 19:56:32 +0000 (+0000) Subject: Cure CLI double-prompting (by ditching gcc fgetws()), general cleanup. Work remaining... X-Git-Tag: version-3.42.0~141^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=67f678138dc7e601db9e6e260195d4234d7d7734;p=thirdparty%2Fsqlite.git Cure CLI double-prompting (by ditching gcc fgetws()), general cleanup. Work remaining is to avoid effect of -utf8 when a line editor is linked/used as part of CLI. FossilOrigin-Name: 73a5f54231e9f6ad8f013df3987ea48c516080f9193ed873b56f982ee75658c2 --- diff --git a/manifest b/manifest index 260a215b52..6dfe5033f4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Get\sCLI\sutf8_fgets()\sto\snot\sconsume\smore\sinput\sthan\sit\sreturns.\sGet\sconsole\ssetup\srestoration\sto\shappen\sfor\sall\snon-crash\sexits. -D 2023-04-13T14:14:27.434 +C Cure\sCLI\sdouble-prompting\s(by\sditching\sgcc\sfgetws()),\sgeneral\scleanup.\sWork\sremaining\sis\sto\savoid\seffect\sof\s-utf8\swhen\sa\sline\seditor\sis\slinked/used\sas\spart\sof\sCLI. +D 2023-04-14T19:56:32.111 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -626,7 +626,7 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c 3e53e02ce87c9582bd7e7d22f13f4094a271678d9dc72820fa257a2abb5e4032 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 93bb02212256b49a90589a4664031896e2b2991198153dff1a33a72f437dad94 -F src/shell.c.in d3a5bef33e4ad55f3feeaeb0deaed32dcb80252a5b2ca184d1eefa816a9f92cf +F src/shell.c.in 23c6ed8477303108f53ec73c8333aaff8d11267276f3852597304d8915bc55d7 F src/sqlite.h.in 4fff9c6cc5d4cbba9532a668112efb6dc469c425e1a2196664d7c07d508363ef F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4 @@ -2052,8 +2052,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 824382393d92d9eb6df8701de7c263280150569a708759c4a539acc6d8d38821 -R 692e15a266cff0987f54e086d515e8e5 +P b4fa233d3dda54fa83771844cf5156bf1275c687925340af17a7713a9400dfef +R c50b2d60063b3025d3b72bba985f6bbb U larrybr -Z d0dd4db17efed3a7d98e05299e7fc21d +Z 16fa3e5dbb2e04c40e7812c85b6fd381 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 065235828d..d526131411 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b4fa233d3dda54fa83771844cf5156bf1275c687925340af17a7713a9400dfef \ No newline at end of file +73a5f54231e9f6ad8f013df3987ea48c516080f9193ed873b56f982ee75658c2 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 12748b29a3..2d954bb218 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -589,10 +589,12 @@ static char *dynamicContinuePrompt(void){ #endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */ #if (defined(_WIN32) || defined(WIN32)) && !defined(SQLITE_SHELL_FIDDLE) -static int infsMode; -static UINT codePage = 0; -static HANDLE hConsoleIn; -static DWORD consoleMode; +/* Following variables are used for -utf8 operation. */ +static int stdinEof = 0; /* EOF seen on console input */ +static int infsMode; /* Input file stream mode upon shell start */ +static UINT codePage = 0; /* Input code page upon shell start */ +static HANDLE hConsoleIn = INVALID_HANDLE_VALUE; /* Console input handle */ +static DWORD consoleMode; /* Console mode upon shell start */ /* ** Prepare input stream, (if known to be a WIN32 console), for UTF-8 @@ -601,7 +603,8 @@ static DWORD consoleMode; ** the preparation is not done and common "code page" issues occur. */ static void instream_prepare(void){ - if( isatty(0) ){ + hConsoleIn = GetStdHandle(STD_INPUT_HANDLE); + if( isatty(0) && GetFileType(hConsoleIn)==FILE_TYPE_CHAR ){ if( !IsValidCodePage(CP_UTF8) ){ fprintf(stderr, "Cannot use UTF-8 code page.\n"); console_utf8 = 0; @@ -609,7 +612,6 @@ static void instream_prepare(void){ } codePage = GetConsoleCP(); SetConsoleCP(CP_UTF8); - hConsoleIn = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode( hConsoleIn, &consoleMode); SetConsoleMode( hConsoleIn, consoleMode | ENABLE_LINE_INPUT ); infsMode = _setmode(_fileno(stdin), _O_U16TEXT); @@ -623,7 +625,7 @@ static void instream_prepare(void){ ** Undo the effects of instream_prepare(), if any. */ static void SQLITE_CDECL instream_restore(void){ - if( console_utf8 && codePage!=0 ){ + if( console_utf8 && codePage!=0 &&hConsoleIn != INVALID_HANDLE_VALUE ){ _setmode(_fileno(stdin), infsMode); SetConsoleCP(codePage); SetConsoleMode( hConsoleIn, consoleMode ); @@ -638,28 +640,55 @@ static void SQLITE_CDECL instream_restore(void){ ** startup option, -utf8, has not been provided or taken effect. */ static char* utf8_fgets(char *buf, int ncmax, FILE *fin){ - #define SQLITE_IA_LINE_LEN 150 + if( fin==0 ) fin = stdin; if( fin==stdin && stdin_is_interactive && console_utf8 ){ - wchar_t wbuf[SQLITE_IA_LINE_LEN]; +# define SQLITE_IALIM 150 + wchar_t wbuf[SQLITE_IALIM]; + int lend = 0; int noc = 0; - if( ncmax == 0 ) return 0; + if( ncmax == 0 || stdinEof ) return 0; buf[0] = 0; - while( noc < ncmax-7-1 ){ - /* There is room for at least 2 more characters and the 0-terminator. */ - int na = (ncmax-1 - noc)/4; - wchar_t * wz; - if( na > SQLITE_IA_LINE_LEN ) na = SQLITE_IA_LINE_LEN; - wz = fgetws(wbuf, na, stdin); - if( wz != 0 ){ - int nmb = WideCharToMultiByte(CP_UTF8, 0, wz, -1, 0, 0, 0, 0); + while( noc < ncmax-7-1 && !lend ){ + /* There is room for at least 2 more characters and a 0-terminator. */ + int na = (ncmax > SQLITE_IALIM*4+1 + noc) + ? SQLITE_IALIM : (ncmax-1 - noc)/4; +# undef SQLITE_IALIM + DWORD nbr = 0; + BOOL bRC = ReadConsoleW(hConsoleIn, wbuf, na, &nbr, 0); + if( !bRC || (noc==0 && nbr==0) ) return 0; + if( nbr > 0 ){ + int nmb = WideCharToMultiByte(CP_UTF8, WC_COMPOSITECHECK|WC_DEFAULTCHAR, + wbuf,nbr, 0,0, 0, 0); if( nmb !=0 && noc+nmb <= ncmax ){ - WideCharToMultiByte(CP_UTF8, 0, wz, -1, buf+noc, nmb, 0, 0); - noc += nmb-1; /* Strip 0-terminator added by above call. */ - if( buf[noc-1] == '\n' ) break; + int iseg = noc; + nmb = WideCharToMultiByte(CP_UTF8, WC_COMPOSITECHECK|WC_DEFAULTCHAR, + wbuf,nbr, buf+noc,nmb, 0,0); + noc += nmb; + /* Fixup line-ends as coded by Windows for CR (or "Enter".)*/ + if( noc > 0 ){ + if( buf[noc-1]=='\n' ){ + lend = 1; + if( noc > 1 && buf[noc-2]=='\r' ){ + buf[noc-2] = '\n'; + --noc; + } + } + } + /* Check for ^Z (anywhere in line) too. */ + while( iseg < noc ){ + if( buf[iseg]==0x1a ){ + 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; + buf[noc] = 0; return buf; }else{ return fgets(buf, ncmax, fin); @@ -889,14 +918,11 @@ static char *local_getline(char *zLine, FILE *in){ } } #if defined(_WIN32) || defined(WIN32) - /* For interactive input on Windows systems, translate the - ** multi-byte characterset characters into UTF-8. */ - if( stdin_is_interactive && in==stdin ){ - // FILE *cil = fopen("cin.log", "wa"); - // i64 nzl = strlen(zLine); + /* For interactive input on Windows systems, without -utf8, + ** translate the multi-byte characterset characters into UTF-8. + ** This is the translation that predates the -utf8 option. */ + if( stdin_is_interactive && in==stdin && !console_utf8 ){ char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0); - // fwrite(zLine, nzl, 1, cil); - // fwrite("\n", 1,1, cil); if( zTrans ){ i64 nTrans = strlen(zTrans)+1; if( nTrans>nLine ){ @@ -904,11 +930,8 @@ static char *local_getline(char *zLine, FILE *in){ shell_check_oom(zLine); } memcpy(zLine, zTrans, nTrans); - // fwrite(zLine, nTrans-1, 1, cil); - // fwrite("\n", 1,1, cil); sqlite3_free(zTrans); } - // fclose(cil); } #endif /* defined(_WIN32) || defined(WIN32) */ return zLine; @@ -11819,7 +11842,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ int argcToFree = 0; #endif - setBinaryMode(stdin, 0); setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ #ifdef SQLITE_SHELL_FIDDLE stdin_is_interactive = 0; @@ -12306,6 +12328,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ if( console_utf8 && stdin_is_interactive ){ instream_prepare(); }else{ + setBinaryMode(stdin, 0); console_utf8 = 0; } #endif