mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-24 01:11:15 -03:00
fix handling of non-ASCII chars in C locale
The relevant standards allow the mbtowc/mbrtowc functions to reject non-ASCII characters (i.e., chars with the high bit set) when the locale is C or POSIX. The BSD libraries (e.g., on OS X) don't do this but the GNU libraries (e.g., on Linux) do. Like most programs we need the C/POSIX locales to allow arbitrary bytes. So explicitly check if we're in a single-byte locale (which would also include ISO-8859 variants) and simply pass-thru the chars without encoding or decoding. Fixes #2802.
This commit is contained in:
@@ -386,32 +386,35 @@ int writeb(tputs_arg_t b)
|
||||
|
||||
int writech(wint_t ch)
|
||||
{
|
||||
mbstate_t state;
|
||||
size_t i;
|
||||
char buff[MB_LEN_MAX+1];
|
||||
size_t bytes;
|
||||
size_t len;
|
||||
|
||||
if ((ch >= ENCODE_DIRECT_BASE) &&
|
||||
(ch < ENCODE_DIRECT_BASE+256))
|
||||
if (ch >= ENCODE_DIRECT_BASE && ch < ENCODE_DIRECT_BASE + 256)
|
||||
{
|
||||
buff[0] = ch - ENCODE_DIRECT_BASE;
|
||||
bytes=1;
|
||||
len = 1;
|
||||
}
|
||||
else if (MB_CUR_MAX == 1) // single-byte locale (C/POSIX/ISO-8859)
|
||||
{
|
||||
// If `wc` contains a wide character we emit a question-mark.
|
||||
if (ch & ~0xFF)
|
||||
{
|
||||
ch = '?';
|
||||
}
|
||||
buff[0] = ch;
|
||||
len = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(&state, 0, sizeof(state));
|
||||
bytes= wcrtomb(buff, ch, &state);
|
||||
|
||||
switch (bytes)
|
||||
mbstate_t state = {};
|
||||
len = wcrtomb(buff, ch, &state);
|
||||
if (len == (size_t)-1)
|
||||
{
|
||||
case (size_t)(-1):
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<bytes; i++)
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
out(buff[i]);
|
||||
}
|
||||
@@ -420,29 +423,26 @@ int writech(wint_t ch)
|
||||
|
||||
void writestr(const wchar_t *str)
|
||||
{
|
||||
char *pos;
|
||||
|
||||
CHECK(str,);
|
||||
|
||||
// while( *str )
|
||||
// writech( *str++ );
|
||||
|
||||
/*
|
||||
Check amount of needed space
|
||||
*/
|
||||
size_t len = wcstombs(0, str, 0);
|
||||
if (MB_CUR_MAX == 1) // single-byte locale (C/POSIX/ISO-8859)
|
||||
{
|
||||
while( *str )
|
||||
{
|
||||
writech( *str++ );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
size_t len = wcstombs(0, str, 0); // figure amount of space needed
|
||||
if (len == (size_t)-1)
|
||||
{
|
||||
debug(1, L"Tried to print invalid wide character string");
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert the string.
|
||||
len++;
|
||||
|
||||
/*
|
||||
Convert
|
||||
*/
|
||||
char *buffer, static_buffer[256];
|
||||
if (len <= sizeof static_buffer)
|
||||
buffer = static_buffer;
|
||||
@@ -456,7 +456,7 @@ void writestr(const wchar_t *str)
|
||||
/*
|
||||
Write
|
||||
*/
|
||||
for (pos = buffer; *pos; pos++)
|
||||
for (char *pos = buffer; *pos; pos++)
|
||||
{
|
||||
out(*pos);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user