aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlarrybr <larrybr@noemail.net>2023-10-25 20:27:18 +0000
committerlarrybr <larrybr@noemail.net>2023-10-25 20:27:18 +0000
commit63aff62e697b46438004ac05fd6588e574e00f2f (patch)
tree603b356fa8fdeb8285baf424f41116fc6677e71f /src
parent47a484d8ed62b7455a915575c7311e878fb3bec6 (diff)
downloadsqlite-63aff62e697b46438004ac05fd6588e574e00f2f.tar.gz
sqlite-63aff62e697b46438004ac05fd6588e574e00f2f.zip
In CLI for Windows builds, do MBCS/UTF-8 translation independently for input and output. (WIP)
FossilOrigin-Name: 47b13e66e07be3a26cf7fa0b7b65ad8576c3b4be50fc422be8fe93be93d681ac
Diffstat (limited to 'src')
-rw-r--r--src/shell.c.in99
1 files changed, 58 insertions, 41 deletions
diff --git a/src/shell.c.in b/src/shell.c.in
index b78759c00..b970ce479 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -449,12 +449,20 @@ static int bail_on_error = 0;
*/
static int stdin_is_interactive = 1;
+/*
+** If build is for Windows, without 3rd-party line editing, Console
+** input and output may be done in a UTF-8 compatible way. This is
+** determined by invocation option and OS installed capability.
+*/
#if (defined(_WIN32) || defined(WIN32)) && SHELL_USE_LOCAL_GETLINE \
&& !defined(SHELL_OMIT_WIN_UTF8)
# define SHELL_WIN_UTF8_OPT 1
- static int console_utf8 = sizeof(char*)/4 - 1;
+ static int console_utf8_in = 0;
+ static int console_utf8_out = 0;
+ static int mbcs_opted = 0;
#else
-# define console_utf8 0
+# define console_utf8_in 0
+# define console_utf8_out 0
# define SHELL_WIN_UTF8_OPT 0
#endif
@@ -597,7 +605,7 @@ static struct ConsoleState {
int infsMode; /* Input file stream mode upon shell start */
UINT inCodePage; /* Input code page upon shell start */
UINT outCodePage; /* Output code page upon shell start */
- HANDLE hConsoleIn; /* Console input handle */
+ HANDLE hConsole; /* Console input or output handle */
DWORD consoleMode; /* Console mode upon shell start */
} conState = { 0, 0, 0, 0, INVALID_HANDLE_VALUE, 0 };
@@ -607,49 +615,59 @@ static struct ConsoleState {
/*
** Prepare console, (if known to be a WIN32 console), for UTF-8
-** input (from either typing or suitable paste operations) and for
+** input (from either typing or suitable paste operations) and/or for
** UTF-8 rendering. This may "fail" with a message to stderr, where
** the preparation is not done and common "code page" issues occur.
*/
-static void console_prepare(void){
+static void console_prepare_utf8(void){
HANDLE hCI = GetStdHandle(STD_INPUT_HANDLE);
+ HANDLE hCO = GetStdHandle(STD_OUTPUT_HANDLE);
+ HANDLE hCC = INVALID_HANDLE_VALUE;
DWORD consoleMode = 0;
- if( isatty(0) && GetFileType(hCI)==FILE_TYPE_CHAR
- && GetConsoleMode( hCI, &consoleMode) ){
- if( !IsValidCodePage(CP_UTF8) ){
- fprintf(stderr, "Cannot use UTF-8 code page.\n");
- console_utf8 = 0;
- return;
- }
- conState.hConsoleIn = hCI;
- conState.consoleMode = consoleMode;
- conState.inCodePage = GetConsoleCP();
- conState.outCodePage = GetConsoleOutputCP();
+ u8 conIO = 0;
+
+ console_utf8_in = console_utf8_out = 0;
+ if( isatty(0) && GetFileType(hCI)==FILE_TYPE_CHAR ) conIO = 1;
+ if( isatty(1) && GetFileType(hCO)==FILE_TYPE_CHAR ) conIO |= 2;
+ if( conIO==0 || mbcs_opted ) return;
+ if( conIO & 1 ) hCC = hCI;
+ else hCC = hCO;
+ if( !IsValidCodePage(CP_UTF8) || !GetConsoleMode( hCC, &consoleMode) ){
+ fprintf(stderr, "Cannot use UTF-8 code page.\n");
+ return;
+ }
+ conState.hConsole = hCC;
+ conState.consoleMode = consoleMode;
+ conState.inCodePage = GetConsoleCP();
+ conState.outCodePage = GetConsoleOutputCP();
+ if( conIO & 1 ){
+ console_utf8_in = 1;
SetConsoleCP(CP_UTF8);
- SetConsoleOutputCP(CP_UTF8);
consoleMode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
- SetConsoleMode(conState.hConsoleIn, consoleMode);
+ SetConsoleMode(conState.hConsole, consoleMode);
conState.infsMode = _setmode(_fileno(stdin), _O_U16TEXT);
- console_utf8 = 1;
- }else{
- console_utf8 = 0;
+ }
+ if( conIO & 2 ){
+ console_utf8_out = 1;
+ SetConsoleOutputCP(CP_UTF8);
}
}
/*
-** Undo the effects of console_prepare(), if any.
+** Undo the effects of console_prepare_utf8(), if any.
*/
static void SQLITE_CDECL console_restore(void){
- if( console_utf8 && conState.inCodePage!=0
- && conState.hConsoleIn!=INVALID_HANDLE_VALUE ){
+ if( (console_utf8_in||console_utf8_out) && conState.inCodePage!=0
+ && conState.hConsole!=INVALID_HANDLE_VALUE ){
_setmode(_fileno(stdin), conState.infsMode);
SetConsoleCP(conState.inCodePage);
SetConsoleOutputCP(conState.outCodePage);
- SetConsoleMode(conState.hConsoleIn, conState.consoleMode);
+ SetConsoleMode(conState.hConsole, conState.consoleMode);
/* Avoid multiple calls. */
- conState.hConsoleIn = INVALID_HANDLE_VALUE;
+ conState.hConsole = INVALID_HANDLE_VALUE;
conState.consoleMode = 0;
- console_utf8 = 0;
+ console_utf8_in = 0;
+ console_utf8_out = 0;
}
}
@@ -657,11 +675,11 @@ static void SQLITE_CDECL console_restore(void){
** Collect input like fgets(...) with special provisions for input
** from the Windows console to get around its strange coding issues.
** Defers to plain fgets() when input is not interactive or when the
-** startup option, -utf8, has not been provided or taken effect.
+** UTF-8 input is unavailable or opted out.
*/
static char* utf8_fgets(char *buf, int ncmax, FILE *fin){
if( fin==0 ) fin = stdin;
- if( fin==stdin && stdin_is_interactive && console_utf8 ){
+ if( fin==stdin && stdin_is_interactive && console_utf8_in ){
# define SQLITE_IALIM 150
wchar_t wbuf[SQLITE_IALIM];
int lend = 0;
@@ -674,7 +692,7 @@ static char* utf8_fgets(char *buf, int ncmax, FILE *fin){
? SQLITE_IALIM : (ncmax-1 - noc)/4;
# undef SQLITE_IALIM
DWORD nbr = 0;
- BOOL bRC = ReadConsoleW(conState.hConsoleIn, wbuf, na, &nbr, 0);
+ BOOL bRC = ReadConsoleW(conState.hConsole, wbuf, na, &nbr, 0);
if( !bRC || (noc==0 && nbr==0) ) return 0;
if( nbr > 0 ){
int nmb = WideCharToMultiByte(CP_UTF8,WC_COMPOSITECHECK|WC_DEFAULTCHAR,
@@ -720,8 +738,8 @@ static char* utf8_fgets(char *buf, int ncmax, FILE *fin){
/*
** Render output like fprintf(). Except, if the output is going to the
-** console and if this is running on a Windows machine, and if the -utf8
-** option is unavailable or (available and inactive), translate the
+** console and if this is running on a Windows machine, and if UTF-8
+** output unavailable (or available but opted out), translate the
** output from UTF-8 into MBCS for output through 8-bit stdout stream.
** (With -utf8 active, no translation is needed and must not be done.)
*/
@@ -729,7 +747,7 @@ static char* utf8_fgets(char *buf, int ncmax, FILE *fin){
void utf8_printf(FILE *out, const char *zFormat, ...){
va_list ap;
va_start(ap, zFormat);
- if( stdout_is_console && (out==stdout || out==stderr) && !console_utf8 ){
+ if( stdout_is_console && (out==stdout || out==stderr) && !console_utf8_out ){
char *z1 = sqlite3_vmprintf(zFormat, ap);
char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
sqlite3_free(z1);
@@ -942,8 +960,8 @@ static char *local_getline(char *zLine, FILE *in){
#if defined(_WIN32) || defined(WIN32)
/* 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 ){
+ ** This is the translation that predates console UTF-8 input. */
+ if( stdin_is_interactive && in==stdin && !console_utf8_in ){
char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
if( zTrans ){
i64 nTrans = strlen(zTrans)+1;
@@ -12503,11 +12521,11 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
stdin_is_interactive = 0;
}else if( cli_strcmp(z,"-utf8")==0 ){
#if SHELL_WIN_UTF8_OPT
- console_utf8 = 1;
+ mbcs_opted = 0;
#endif /* SHELL_WIN_UTF8_OPT */
}else if( cli_strcmp(z,"-no-utf8")==0 ){
#if SHELL_WIN_UTF8_OPT
- console_utf8 = 0;
+ mbcs_opted = 1;
#endif /* SHELL_WIN_UTF8_OPT */
}else if( cli_strcmp(z,"-heap")==0 ){
i++;
@@ -12591,11 +12609,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
data.cMode = data.mode;
}
#if SHELL_WIN_UTF8_OPT
- if( console_utf8 && stdin_is_interactive ){
- console_prepare();
+ if( stdin_is_interactive ){
+ console_prepare_utf8();
}else{
setBinaryMode(stdin, 0);
- console_utf8 = 0;
}
#endif
@@ -12636,7 +12653,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
const char *zCharset = "";
int nHistory;
#if SHELL_WIN_UTF8_OPT
- if( console_utf8 ) zCharset = " (utf8)";
+ if( console_utf8_in ) zCharset = " (utf8)";
#endif
printf(
"SQLite version %s %.19s%s\n" /*extra-version-info*/