@@ -88,9 +88,7 @@ extern "C" {
88
88
#endif /* defined(HAVE_CURSES_H) && defined(HAVE_TERM_H) */
89
89
90
90
#undef bcmp // Fix problem with new readline
91
- #if defined(_WIN32)
92
- #include < conio.h>
93
- #else
91
+ #if !defined(_WIN32)
94
92
# ifdef __APPLE__
95
93
# include < editline/readline.h>
96
94
# else
@@ -104,6 +102,98 @@ extern "C" {
104
102
#define USE_POPEN
105
103
}
106
104
105
+ static CHARSET_INFO *charset_info= &my_charset_latin1;
106
+
107
+ #if defined(_WIN32)
108
+ /*
109
+ Set console mode for the whole duration of the client session.
110
+
111
+ We need for input
112
+ - line input (i.e read lines from console)
113
+ - echo typed characters
114
+ - "cooked" mode, i.e we do not want to handle all keystrokes,
115
+ like DEL etc ourselves, yet. We might want handle keystrokes
116
+ in the future, to implement tab completion, and better
117
+ (multiline) history.
118
+
119
+ Disable VT escapes for the output.We do not know what kind of escapes SELECT would return.
120
+ */
121
+ struct Console_mode
122
+ {
123
+ HANDLE in= GetStdHandle(STD_INPUT_HANDLE);
124
+ HANDLE out= GetStdHandle(STD_OUTPUT_HANDLE);
125
+ DWORD mode_in=0 ;
126
+ DWORD mode_out=0 ;
127
+
128
+ enum {STDIN_CHANGED = 1 , STDOUT_CHANGED = 2 };
129
+ int changes=0 ;
130
+
131
+ Console_mode ()
132
+ {
133
+ if (in && in != INVALID_HANDLE_VALUE && GetConsoleMode (in, &mode_in))
134
+ {
135
+ SetConsoleMode (in, ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT);
136
+ changes |= STDIN_CHANGED;
137
+ }
138
+
139
+ if (out && out != INVALID_HANDLE_VALUE && GetConsoleMode (out, &mode_out))
140
+ {
141
+ #ifdef ENABLE_VIRTUAL_TERMINAL_INPUT
142
+ SetConsoleMode (out, mode_out & ~ENABLE_VIRTUAL_TERMINAL_INPUT);
143
+ changes |= STDOUT_CHANGED;
144
+ #endif
145
+ }
146
+ }
147
+
148
+ ~Console_mode ()
149
+ {
150
+ if (changes & STDIN_CHANGED)
151
+ SetConsoleMode (in, mode_in);
152
+
153
+ if (changes & STDOUT_CHANGED)
154
+ SetConsoleMode (out, mode_out);
155
+ }
156
+ };
157
+
158
+ static Console_mode my_conmode;
159
+
160
+ #define MAX_CGETS_LINE_LEN 65535
161
+ /* * Read line from console, chomp EOL*/
162
+ static char *win_readline ()
163
+ {
164
+ static wchar_t wstrbuf[MAX_CGETS_LINE_LEN];
165
+ static char strbuf[MAX_CGETS_LINE_LEN * 4 ];
166
+
167
+ DWORD nchars= 0 ;
168
+ uint len= 0 ;
169
+ SetLastError (0 );
170
+ if (!ReadConsoleW (GetStdHandle (STD_INPUT_HANDLE), wstrbuf, MAX_CGETS_LINE_LEN-1 ,
171
+ &nchars, NULL ))
172
+ goto err;
173
+ if (nchars == 0 && GetLastError () == ERROR_OPERATION_ABORTED)
174
+ goto err;
175
+
176
+ for (;nchars > 0 ; nchars--)
177
+ {
178
+ if (wstrbuf[nchars - 1 ] != ' \n ' && wstrbuf[nchars - 1 ] != ' \r ' )
179
+ break ;
180
+ }
181
+
182
+ if (nchars > 0 )
183
+ {
184
+ uint errors;
185
+ len= my_convert (strbuf, sizeof (strbuf), charset_info,
186
+ (const char *) wstrbuf, nchars * sizeof (wchar_t ),
187
+ &my_charset_utf16le_bin, &errors);
188
+ }
189
+ strbuf[len]= 0 ;
190
+ return strbuf;
191
+ err:
192
+ return NULL ;
193
+ }
194
+ #endif
195
+
196
+
107
197
#ifdef HAVE_VIDATTR
108
198
static int have_curses= 0 ;
109
199
static void my_vidattr (chtype attrs)
@@ -208,7 +298,6 @@ unsigned short terminal_width= 80;
208
298
209
299
static uint opt_protocol=0 ;
210
300
static const char *opt_protocol_type= " " ;
211
- static CHARSET_INFO *charset_info= &my_charset_latin1;
212
301
213
302
static uint protocol_to_force= MYSQL_PROTOCOL_DEFAULT;
214
303
@@ -1353,6 +1442,46 @@ sig_handler mysql_end(int sig)
1353
1442
exit (status.exit_status );
1354
1443
}
1355
1444
1445
+ #ifdef _WIN32
1446
+ #define CNV_BUFSIZE 1024
1447
+
1448
+ /* *
1449
+ Convert user,database,and password to requested charset.
1450
+
1451
+ This is done in the single case when user connects with non-UTF8
1452
+ default-character-set, on UTF8 capable Windows.
1453
+
1454
+ User, password, and database are UTF8 encoded, prior to the function,
1455
+ this needs to be fixed, in case they contain non-ASCIIs.
1456
+
1457
+ Mostly a workaround, to allow existng users with non-ASCII password
1458
+ to survive upgrade without losing connectivity.
1459
+ */
1460
+ static void maybe_convert_charset (const char **user, const char **password,
1461
+ const char **database, const char *csname)
1462
+ {
1463
+ if (GetACP () != CP_UTF8 || !strncmp (csname, " utf8" , 4 ))
1464
+ return ;
1465
+ static char bufs[3 ][CNV_BUFSIZE];
1466
+ const char **from[]= {user, password, database};
1467
+ CHARSET_INFO *cs= get_charset_by_csname (csname, MY_CS_PRIMARY,
1468
+ MYF (MY_UTF8_IS_UTF8MB3 | MY_WME));
1469
+ if (!cs)
1470
+ return ;
1471
+ for (int i= 0 ; i < 3 ; i++)
1472
+ {
1473
+ const char *str= *from[i];
1474
+ if (!str)
1475
+ continue ;
1476
+ uint errors;
1477
+ uint len= my_convert (bufs[i], CNV_BUFSIZE, cs, str, (uint32) strlen (str),
1478
+ &my_charset_utf8mb4_bin, &errors);
1479
+ bufs[i][len]= 0 ;
1480
+ *from[i]= bufs[i];
1481
+ }
1482
+ }
1483
+ #endif
1484
+
1356
1485
/*
1357
1486
set connection-specific options and call mysql_real_connect
1358
1487
*/
@@ -1384,6 +1513,10 @@ static bool do_connect(MYSQL *mysql, const char *host, const char *user,
1384
1513
mysql_options (mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0 );
1385
1514
mysql_options4 (mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
1386
1515
" program_name" , " mysql" );
1516
+ #ifdef _WIN32
1517
+ maybe_convert_charset (&user, &password, &database,default_charset);
1518
+ #endif
1519
+
1387
1520
return mysql_real_connect (mysql, host, user, password, database,
1388
1521
opt_mysql_port, opt_mysql_unix_port, flags);
1389
1522
}
@@ -2033,11 +2166,6 @@ static int get_options(int argc, char **argv)
2033
2166
2034
2167
static int read_and_execute (bool interactive)
2035
2168
{
2036
- #if defined(_WIN32)
2037
- String tmpbuf;
2038
- String buffer;
2039
- #endif
2040
-
2041
2169
char *line= NULL ;
2042
2170
char in_string=0 ;
2043
2171
ulong line_number=0 ;
@@ -2115,26 +2243,7 @@ static int read_and_execute(bool interactive)
2115
2243
2116
2244
#if defined(_WIN32)
2117
2245
tee_fputs (prompt, stdout);
2118
- if (!tmpbuf.is_alloced ())
2119
- tmpbuf.alloc (65535 );
2120
- tmpbuf.length (0 );
2121
- buffer.length (0 );
2122
- size_t clen;
2123
- do
2124
- {
2125
- line= my_cgets ((char *)tmpbuf.ptr (), tmpbuf.alloced_length ()-1 , &clen);
2126
- buffer.append (line, clen);
2127
- /*
2128
- if we got buffer fully filled than there is a chance that
2129
- something else is still in console input buffer
2130
- */
2131
- } while (tmpbuf.alloced_length () <= clen);
2132
- /*
2133
- An empty line is returned from my_cgets when there's error reading :
2134
- Ctrl-c for example
2135
- */
2136
- if (line)
2137
- line= buffer.c_ptr ();
2246
+ line= win_readline ();
2138
2247
#else
2139
2248
if (opt_outfile)
2140
2249
fputs (prompt, OUTFILE);
@@ -2201,10 +2310,7 @@ static int read_and_execute(bool interactive)
2201
2310
}
2202
2311
}
2203
2312
2204
- #if defined(_WIN32)
2205
- buffer.free ();
2206
- tmpbuf.free ();
2207
- #else
2313
+ #if !defined(_WIN32)
2208
2314
if (interactive)
2209
2315
/*
2210
2316
free the last entered line.
@@ -3242,6 +3348,21 @@ com_clear(String *buffer,char *line __attribute__((unused)))
3242
3348
return 0 ;
3243
3349
}
3244
3350
3351
+ static void adjust_console_codepage (const char *name __attribute__ ((unused)))
3352
+ {
3353
+ #ifdef _WIN32
3354
+ if (my_set_console_cp (name) < 0 )
3355
+ {
3356
+ char buf[128 ];
3357
+ snprintf (buf, sizeof (buf),
3358
+ " WARNING: Could not determine Windows codepage for charset '%s',"
3359
+ " continue using codepage %u" , name, GetConsoleOutputCP ());
3360
+ put_info (buf, INFO_INFO);
3361
+ }
3362
+ #endif
3363
+ }
3364
+
3365
+
3245
3366
/* ARGSUSED */
3246
3367
static int
3247
3368
com_charset (String *buffer __attribute__ ((unused)), char *line)
@@ -3263,6 +3384,7 @@ com_charset(String *buffer __attribute__((unused)), char *line)
3263
3384
mysql_set_character_set (&mysql, charset_info->cs_name .str );
3264
3385
default_charset= (char *)charset_info->cs_name .str ;
3265
3386
put_info (" Charset changed" , INFO_INFO);
3387
+ adjust_console_codepage (charset_info->cs_name .str );
3266
3388
}
3267
3389
else put_info (" Charset is not found" , INFO_INFO);
3268
3390
return 0 ;
@@ -4806,6 +4928,7 @@ sql_real_connect(char *host,char *database,char *user,char *password,
4806
4928
put_info (buff, INFO_ERROR);
4807
4929
return 1 ;
4808
4930
}
4931
+ adjust_console_codepage (charset_info->cs_name .str );
4809
4932
connected=1 ;
4810
4933
#ifndef EMBEDDED_LIBRARY
4811
4934
mysql_options (&mysql, MYSQL_OPT_RECONNECT, &debug_info_flag);
0 commit comments