1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Avoid undesirable NL to CRLF translation when doing binary output to the

Windows console.

FossilOrigin-Name: d25bdce36abed95524ad058a277aba7bb17270e7ff1476474713dbc29742c762
This commit is contained in:
drh
2024-10-11 14:02:48 +00:00
parent 64366ae114
commit 0b453b3b33
4 changed files with 92 additions and 26 deletions

View File

@ -67,6 +67,31 @@
# define IsConsole(fd) 1
#endif
/*
** Global variables determine if simulated O_BINARY mode is to be
** used for stdout or other, respectively. Simulated O_BINARY mode
** means the mode is usually O_BINARY, but switches to O_U8TEXT for
** unicode characters U+0080 or greater (any character that has a
** multi-byte representation in UTF-8). This is the only way we
** have found to render Unicode characters on a Windows console while
** at the same time avoiding undesirable \n to \r\n translation.
*/
static int simBinaryStdout = 0;
static int simBinaryOther = 0;
/*
** Determine if simulated binary mode should be used for output to fd
*/
static int UseBinaryWText(FILE *fd){
if( fd==stdout || fd==stderr ){
return simBinaryStdout;
}else{
return simBinaryOther;
}
}
/*
** Work-alike for the fopen() routine from the standard C library.
*/
@ -88,6 +113,7 @@ FILE *sqlite3_fopen(const char *zFilename, const char *zMode){
}
free(b1);
free(b2);
simBinaryOther = 0;
return fp;
}
@ -143,13 +169,53 @@ char *sqlite3_fgets(char *buf, int sz, FILE *in){
}
}
/*
** Send ASCII text as O_BINARY. But for Unicode characters U+0080 and
** greater, switch to O_U8TEXT.
*/
static void piecemealOutput(wchar_t *b1, int sz, FILE *out){
int i;
wchar_t c;
while( sz>0 ){
for(i=0; i<sz && b1[i]>=0x80; i++){}
if( i>0 ){
c = b1[i];
b1[i] = 0;
fflush(out);
_setmode(_fileno(out), _O_U8TEXT);
fputws(b1, out);
fflush(out);
b1 += i;
b1[0] = c;
sz -= i;
}else{
fflush(out);
_setmode(_fileno(out), _O_TEXT);
_setmode(_fileno(out), _O_BINARY);
fwrite(&b1[0], 1, 1, out);
for(i=1; i<sz && b1[i]<0x80; i++){
fwrite(&b1[i], 1, 1, out);
}
fflush(out);
_setmode(_fileno(out), _O_U8TEXT);
b1 += i;
sz -= i;
}
}
}
/*
** Work-alike for fputs() from the standard C library.
*/
int sqlite3_fputs(const char *z, FILE *out){
if( UseWtextForOutput(out) ){
if( !UseWtextForOutput(out) ){
/* Writing to a file or other destination, just write bytes without
** any translation. */
return fputs(z, out);
}else{
/* When writing to the command-prompt in Windows, it is necessary
** to use _O_WTEXT input mode and write UTF-16 characters.
** to use O_U8TEXT to render Unicode U+0080 and greater. Go ahead
** use O_U8TEXT for everything in text mode.
*/
int sz = (int)strlen(z);
wchar_t *b1 = malloc( (sz+1)*sizeof(wchar_t) );
@ -157,13 +223,13 @@ int sqlite3_fputs(const char *z, FILE *out){
sz = MultiByteToWideChar(CP_UTF8, 0, z, sz, b1, sz);
b1[sz] = 0;
_setmode(_fileno(out), _O_U8TEXT);
fputws(b1, out);
if( UseBinaryWText(out) ){
piecemealOutput(b1, sz, out);
}else{
fputws(b1, out);
}
sqlite3_free(b1);
return 0;
}else{
/* Writing to a file or other destination, just write bytes without
** any translation. */
return fputs(z, out);
}
}
@ -205,6 +271,10 @@ void sqlite3_fsetmode(FILE *fp, int mode){
if( !UseWtextForOutput(fp) ){
fflush(fp);
_setmode(_fileno(fp), mode);
}else if( fp==stdout || fp==stderr ){
simBinaryStdout = (mode==_O_BINARY);
}else{
simBinaryOther = (mode==_O_BINARY);
}
}