mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-28 05:43:11 +00:00
Use wcs2string when outputting the screen
The screen output code predates the ENCODE_DIRECT scheme, and directly-encoded bytes were not being properly output. This manifested as private-user characters being mangled when printed as part of fish_prompt. Just use str2wcstring instead. Fixes #7723
This commit is contained in:
parent
f1b6a5939d
commit
8648f52857
2 changed files with 9 additions and 61 deletions
|
@ -309,64 +309,9 @@ int outputter_t::term_puts(const char *str, int affcnt) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a wide character to the outputter. This should only be used when writing characters from
|
void outputter_t::writestr(const wchar_t *str, size_t len) {
|
||||||
/// user supplied strings. This is needed due to our use of the ENCODE_DIRECT_BASE mechanism to
|
wcs2string_appending(str, len, &contents_);
|
||||||
/// allow the user to specify arbitrary byte values to be output. Such as in a `printf` invocation
|
maybe_flush();
|
||||||
/// that includes literal byte values such as `\x1B`. This should not be used for writing non-user
|
|
||||||
/// supplied characters.
|
|
||||||
int outputter_t::writech(wint_t ch) {
|
|
||||||
char buff[MB_LEN_MAX + 1];
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (ch >= ENCODE_DIRECT_BASE && ch < ENCODE_DIRECT_BASE + 256) {
|
|
||||||
buff[0] = ch - ENCODE_DIRECT_BASE;
|
|
||||||
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.
|
|
||||||
buff[0] = ch & ~0xFF ? '?' : ch;
|
|
||||||
len = 1;
|
|
||||||
} else {
|
|
||||||
mbstate_t state = {};
|
|
||||||
len = std::wcrtomb(buff, ch, &state);
|
|
||||||
if (len == static_cast<size_t>(-1)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->writestr(buff, len);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write a wide character string to stdout. This should not be used to output things like warning
|
|
||||||
/// messages; just use debug() or std::fwprintf() for that. It should only be used to output user
|
|
||||||
/// supplied strings that might contain literal bytes; e.g., "\342\224\214" from issue #1894. This
|
|
||||||
/// is needed because those strings may contain chars specially encoded using ENCODE_DIRECT_BASE.
|
|
||||||
void outputter_t::writestr(const wchar_t *str) {
|
|
||||||
assert(str && "Empty input string");
|
|
||||||
|
|
||||||
if (MB_CUR_MAX == 1) {
|
|
||||||
// Single-byte locale (C/POSIX/ISO-8859).
|
|
||||||
while (*str) writech(*str++);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
size_t len = wcstombs(nullptr, str, 0); // figure amount of space needed
|
|
||||||
if (len == static_cast<size_t>(-1)) {
|
|
||||||
FLOGF(output_invalid, L"Tried to print invalid wide character string");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the string.
|
|
||||||
len++;
|
|
||||||
char *buffer, static_buffer[256];
|
|
||||||
if (len <= sizeof static_buffer) {
|
|
||||||
buffer = static_buffer;
|
|
||||||
} else {
|
|
||||||
buffer = new char[len];
|
|
||||||
}
|
|
||||||
|
|
||||||
int new_len = wcstombs(buffer, str, len);
|
|
||||||
this->writestr(buffer, new_len);
|
|
||||||
if (buffer != static_buffer) delete[] buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
outputter_t &outputter_t::stdoutput() {
|
outputter_t &outputter_t::stdoutput() {
|
||||||
|
|
|
@ -59,17 +59,20 @@ class outputter_t {
|
||||||
void set_color(rgb_color_t c, rgb_color_t c2);
|
void set_color(rgb_color_t c, rgb_color_t c2);
|
||||||
|
|
||||||
/// Write a wide character to the receiver.
|
/// Write a wide character to the receiver.
|
||||||
int writech(wint_t ch);
|
void writech(wchar_t ch) { writestr(&ch, 1); }
|
||||||
|
|
||||||
/// Write a NUL-terminated wide character string to the receiver.
|
/// Write a NUL-terminated wide character string to the receiver.
|
||||||
void writestr(const wchar_t *str);
|
void writestr(const wchar_t *str) { writestr(str, wcslen(str)); }
|
||||||
|
|
||||||
/// Write a wide character string to the receiver.
|
/// Write a wide character string to the receiver.
|
||||||
void writestr(const wcstring &str) { writestr(str.c_str()); }
|
void writestr(const wcstring &str) { writestr(str.data(), str.size()); }
|
||||||
|
|
||||||
/// Write the given terminfo string to the receiver, like tputs().
|
/// Write the given terminfo string to the receiver, like tputs().
|
||||||
int term_puts(const char *str, int affcnt);
|
int term_puts(const char *str, int affcnt);
|
||||||
|
|
||||||
|
/// Write a wide string of the given length.
|
||||||
|
void writestr(const wchar_t *str, size_t len);
|
||||||
|
|
||||||
/// Write a narrow string of the given length.
|
/// Write a narrow string of the given length.
|
||||||
void writestr(const char *str, size_t len) {
|
void writestr(const char *str, size_t len) {
|
||||||
contents_.append(str, len);
|
contents_.append(str, len);
|
||||||
|
|
Loading…
Reference in a new issue