Cygwin: console: Handle setting very long window title correctly.

- Previously, the console code could not handle escape sequence
  setting window title longer than 256 byte correctly. This patch
  fixes the issue.
  Addresses: https://cygwin.com/pipermail/cygwin/2022-June/251662.html
This commit is contained in:
Takashi Yano 2022-06-19 12:53:16 +09:00
parent fdbd153932
commit fe10e8f03a
2 changed files with 69 additions and 24 deletions

View File

@ -73,19 +73,59 @@ private:
static const size_t WPBUF_LEN = 256u; static const size_t WPBUF_LEN = 256u;
char buf[WPBUF_LEN]; char buf[WPBUF_LEN];
size_t ixput; size_t ixput;
HANDLE output_handle;
public: public:
void init (HANDLE &handle)
{
output_handle = handle;
empty ();
}
inline void put (char x) inline void put (char x)
{ {
if (ixput < WPBUF_LEN) if (ixput == WPBUF_LEN)
send ();
buf[ixput++] = x; buf[ixput++] = x;
} }
inline void empty () { ixput = 0u; } inline void empty () { ixput = 0u; }
inline void send (HANDLE &handle) inline void send ()
{ {
if (!output_handle)
{
empty ();
return;
}
mbtowc_p f_mbtowc =
(__MBTOWC == __ascii_mbtowc) ? __utf8_mbtowc : __MBTOWC;
wchar_t bufw[WPBUF_LEN]; wchar_t bufw[WPBUF_LEN];
DWORD len = sys_mbstowcs (bufw, WPBUF_LEN, buf, ixput); DWORD len = 0;
mbstate_t ps;
memset (&ps, 0, sizeof (ps));
char *p = buf;
while (ixput)
{
int bytes = f_mbtowc (_REENT, bufw + len, p, ixput, &ps);
if (bytes < 0)
{
if ((size_t) ps.__count < ixput)
{ /* Discard one byte and retry. */
p++;
ixput--;
memset (&ps, 0, sizeof (ps));
continue;
}
/* Halfway through the multibyte char. */
memmove (buf, p, ixput);
break;
}
else
{
len++;
p += bytes;
ixput -= bytes;
}
}
acquire_attach_mutex (mutex_timeout); acquire_attach_mutex (mutex_timeout);
WriteConsoleW (handle, bufw, len, NULL, 0); WriteConsoleW (output_handle, bufw, len, NULL, 0);
release_attach_mutex (); release_attach_mutex ();
} }
} wpbuf; } wpbuf;
@ -1485,6 +1525,7 @@ fhandler_console::open (int flags, mode_t)
} }
set_output_handle (h); set_output_handle (h);
handle_set.output_handle = h; handle_set.output_handle = h;
wpbuf.init (get_output_handle ());
setup_io_mutex (); setup_io_mutex ();
handle_set.input_mutex = input_mutex; handle_set.input_mutex = input_mutex;
@ -2353,7 +2394,7 @@ fhandler_console::char_command (char c)
wpbuf.put (c); wpbuf.put (c);
if (wincap.has_con_esc_rep ()) if (wincap.has_con_esc_rep ())
/* Just send the sequence */ /* Just send the sequence */
wpbuf.send (get_output_handle ()); wpbuf.send ();
else if (last_char && last_char != L'\n') else if (last_char && last_char != L'\n')
{ {
acquire_attach_mutex (mutex_timeout); acquire_attach_mutex (mutex_timeout);
@ -2367,7 +2408,7 @@ fhandler_console::char_command (char c)
con.scroll_region.Bottom = con.args[1] ? con.args[1] - 1 : -1; con.scroll_region.Bottom = con.args[1] ? con.args[1] - 1 : -1;
wpbuf.put (c); wpbuf.put (c);
/* Just send the sequence */ /* Just send the sequence */
wpbuf.send (get_output_handle ()); wpbuf.send ();
break; break;
case 'L': /* IL */ case 'L': /* IL */
if (wincap.has_con_broken_il_dl ()) if (wincap.has_con_broken_il_dl ())
@ -2400,7 +2441,7 @@ fhandler_console::char_command (char c)
srBottom + 1 - con.b.srWindow.Top); srBottom + 1 - con.b.srWindow.Top);
WriteConsoleW (get_output_handle (), bufw, wcslen (bufw), 0, 0); WriteConsoleW (get_output_handle (), bufw, wcslen (bufw), 0, 0);
wpbuf.put ('T'); wpbuf.put ('T');
wpbuf.send (get_output_handle ()); wpbuf.send ();
__small_swprintf (bufw, L"\033[%d;%dr", __small_swprintf (bufw, L"\033[%d;%dr",
srTop + 1 - con.b.srWindow.Top, srTop + 1 - con.b.srWindow.Top,
srBottom + 1 - con.b.srWindow.Top); srBottom + 1 - con.b.srWindow.Top);
@ -2414,7 +2455,7 @@ fhandler_console::char_command (char c)
{ {
wpbuf.put (c); wpbuf.put (c);
/* Just send the sequence */ /* Just send the sequence */
wpbuf.send (get_output_handle ()); wpbuf.send ();
} }
break; break;
case 'M': /* DL */ case 'M': /* DL */
@ -2437,7 +2478,7 @@ fhandler_console::char_command (char c)
acquire_attach_mutex (mutex_timeout); acquire_attach_mutex (mutex_timeout);
WriteConsoleW (get_output_handle (), bufw, wcslen (bufw), 0, 0); WriteConsoleW (get_output_handle (), bufw, wcslen (bufw), 0, 0);
wpbuf.put ('S'); wpbuf.put ('S');
wpbuf.send (get_output_handle ()); wpbuf.send ();
__small_swprintf (bufw, L"\033[%d;%dr", __small_swprintf (bufw, L"\033[%d;%dr",
srTop + 1 - con.b.srWindow.Top, srTop + 1 - con.b.srWindow.Top,
srBottom + 1 - con.b.srWindow.Top); srBottom + 1 - con.b.srWindow.Top);
@ -2451,7 +2492,7 @@ fhandler_console::char_command (char c)
{ {
wpbuf.put (c); wpbuf.put (c);
/* Just send the sequence */ /* Just send the sequence */
wpbuf.send (get_output_handle ()); wpbuf.send ();
} }
break; break;
case 'J': /* ED */ case 'J': /* ED */
@ -2480,13 +2521,13 @@ fhandler_console::char_command (char c)
} }
else else
/* Just send the sequence */ /* Just send the sequence */
wpbuf.send (get_output_handle ()); wpbuf.send ();
break; break;
case 'h': /* DECSET */ case 'h': /* DECSET */
case 'l': /* DECRST */ case 'l': /* DECRST */
wpbuf.put (c); wpbuf.put (c);
/* Just send the sequence */ /* Just send the sequence */
wpbuf.send (get_output_handle ()); wpbuf.send ();
if (con.saw_question_mark) if (con.saw_question_mark)
{ {
bool need_fix_tab_position = false; bool need_fix_tab_position = false;
@ -2515,7 +2556,7 @@ fhandler_console::char_command (char c)
} }
wpbuf.put (c); wpbuf.put (c);
/* Just send the sequence */ /* Just send the sequence */
wpbuf.send (get_output_handle ()); wpbuf.send ();
break; break;
case 'm': case 'm':
if (con.saw_greater_than_sign) if (con.saw_greater_than_sign)
@ -2523,13 +2564,13 @@ fhandler_console::char_command (char c)
/* Text attribute settings */ /* Text attribute settings */
wpbuf.put (c); wpbuf.put (c);
/* Just send the sequence */ /* Just send the sequence */
wpbuf.send (get_output_handle ()); wpbuf.send ();
break; break;
default: default:
/* Other escape sequences */ /* Other escape sequences */
wpbuf.put (c); wpbuf.put (c);
/* Just send the sequence */ /* Just send the sequence */
wpbuf.send (get_output_handle ()); wpbuf.send ();
break; break;
} }
return; return;
@ -3380,7 +3421,7 @@ fhandler_console::write (const void *vsrc, size_t len)
/* For xterm mode only */ /* For xterm mode only */
/* Just send the sequence */ /* Just send the sequence */
wpbuf.put (*src); wpbuf.put (*src);
wpbuf.send (get_output_handle ()); wpbuf.send ();
} }
else if (con.savex >= 0 && con.savey >= 0) else if (con.savex >= 0 && con.savey >= 0)
cursor_set (false, con.savex, con.savey); cursor_set (false, con.savex, con.savey);
@ -3394,7 +3435,7 @@ fhandler_console::write (const void *vsrc, size_t len)
/* For xterm mode only */ /* For xterm mode only */
/* Just send the sequence */ /* Just send the sequence */
wpbuf.put (*src); wpbuf.put (*src);
wpbuf.send (get_output_handle ()); wpbuf.send ();
} }
else else
cursor_get (&con.savex, &con.savey); cursor_get (&con.savex, &con.savey);
@ -3427,7 +3468,7 @@ fhandler_console::write (const void *vsrc, size_t len)
} }
else else
wpbuf.put (*src); wpbuf.put (*src);
wpbuf.send (get_output_handle ()); wpbuf.send ();
con.state = normal; con.state = normal;
wpbuf.empty(); wpbuf.empty();
} }
@ -3452,7 +3493,7 @@ fhandler_console::write (const void *vsrc, size_t len)
handled and just sent them. */ handled and just sent them. */
wpbuf.put (*src); wpbuf.put (*src);
/* Just send the sequence */ /* Just send the sequence */
wpbuf.send (get_output_handle ()); wpbuf.send ();
con.state = normal; con.state = normal;
wpbuf.empty(); wpbuf.empty();
} }
@ -3549,7 +3590,7 @@ fhandler_console::write (const void *vsrc, size_t len)
{ {
wpbuf.put (*src); wpbuf.put (*src);
if (wincap.has_con_24bit_colors () && !con_is_legacy) if (wincap.has_con_24bit_colors () && !con_is_legacy)
wpbuf.send (get_output_handle ()); wpbuf.send ();
wpbuf.empty (); wpbuf.empty ();
con.state = normal; con.state = normal;
src++; src++;
@ -3566,7 +3607,7 @@ fhandler_console::write (const void *vsrc, size_t len)
if (*src < ' ') if (*src < ' ')
{ {
if (wincap.has_con_24bit_colors () && !con_is_legacy) if (wincap.has_con_24bit_colors () && !con_is_legacy)
wpbuf.send (get_output_handle ()); wpbuf.send ();
else if (*src == '\007' && con.state == gettitle) else if (*src == '\007' && con.state == gettitle)
set_console_title (con.my_title_buf); set_console_title (con.my_title_buf);
con.state = normal; con.state = normal;
@ -3591,7 +3632,7 @@ fhandler_console::write (const void *vsrc, size_t len)
/* Send OSC Ps; Pt BEL other than OSC Ps; ? BEL */ /* Send OSC Ps; Pt BEL other than OSC Ps; ? BEL */
if (wincap.has_con_24bit_colors () && !con_is_legacy if (wincap.has_con_24bit_colors () && !con_is_legacy
&& !con.saw_question_mark) && !con.saw_question_mark)
wpbuf.send (get_output_handle ()); wpbuf.send ();
con.state = normal; con.state = normal;
wpbuf.empty(); wpbuf.empty();
} }
@ -3604,7 +3645,7 @@ fhandler_console::write (const void *vsrc, size_t len)
/* Send OSC Ps; Pt ST other than OSC Ps; ? ST */ /* Send OSC Ps; Pt ST other than OSC Ps; ? ST */
if (wincap.has_con_24bit_colors () && !con_is_legacy if (wincap.has_con_24bit_colors () && !con_is_legacy
&& !con.saw_question_mark) && !con.saw_question_mark)
wpbuf.send (get_output_handle ()); wpbuf.send ();
con.state = normal; con.state = normal;
} }
else else
@ -3868,6 +3909,7 @@ fhandler_console::fixup_after_fork_exec (bool execing)
{ {
set_unit (); set_unit ();
setup_io_mutex (); setup_io_mutex ();
wpbuf.init (get_output_handle ());
if (!execing) if (!execing)
return; return;

View File

@ -14,3 +14,6 @@ Bug Fixes
- Fix a regression that prevented Cygwin from starting if cygwin1.dll - Fix a regression that prevented Cygwin from starting if cygwin1.dll
is in the root directory. is in the root directory.
Addresses: https://cygwin.com/pipermail/cygwin/2022-May/251548.html Addresses: https://cygwin.com/pipermail/cygwin/2022-May/251548.html
- Handle setting very long window title correctly in console.
Addresses: https://cygwin.com/pipermail/cygwin/2022-June/251662.html