Hi Takashi,
A few typos and the strlen bugs me...
On Dec 19 16:48, Takashi Yano wrote:
> Currently, there are four separate workarounds for pseudo console
> output in pty_master_fwd_thread. Each workaround has its own 'for'
> loop that iterates over the entire output buffer, which is not
> efficient. This patch consolidates these loops and introduces a
> single state machine to handle all worarounds at once. In addition,
workarounds
> the workarouds are moved into a dedicated function,
workarounds
> 'workarounds_for_pseudo_console_output()' to improve readability.
>
> Suggested-by: Johannes Schindelin <[email protected]>
> Reviewed-by:
> Signed-off-by: Takashi Yano <[email protected]>
> ---
> winsup/cygwin/fhandler/pty.cc | 283 ++++++++++++++++------------------
> 1 file changed, 129 insertions(+), 154 deletions(-)
>
> diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc
> index 32e50540e..7fa747e0a 100644
> --- a/winsup/cygwin/fhandler/pty.cc
> +++ b/winsup/cygwin/fhandler/pty.cc
> @@ -2642,6 +2642,134 @@ pty_master_thread (VOID *arg)
> return fhandler_pty_master::pty_master_thread (&p);
> }
>
> +static DWORD
> +workarounds_for_pseudo_console_output (char *outbuf, DWORD rlen)
> +{
> + int state = 0;
> + int start_at = 0;
> + bool is_csi = false;
> + bool is_osc = false;
> + int arg = 0;
> + bool saw_greater_than_sign = false;
> + for (DWORD i=0; i<rlen; i++)
> + if (state == 0 && outbuf[i] == '\033')
> + {
> + start_at = i;
> + state = 1;
> + is_csi = false;
> + is_osc = false;
> + arg = 0;
> + continue;
> + }
> + else if (state == 1)
> + {
> + switch (outbuf[i])
> + {
> + case '[':
> + is_csi = true;
> + state = 2;
> + break;
> + case ']':
> + is_osc = true;
> + state = 2;
> + break;
> + case '\033':
> + start_at = i;
> + state = 1;
> + break;
> + default:
> + state = 0;
> + }
> + continue;
> + }
> + else if (is_csi)
> + {
> + if (state == 2 && outbuf[i] == '>')
> + saw_greater_than_sign = true;
> + else if (state == 2 && (isdigit (outbuf[i]) || outbuf[i] == ';'))
> + continue;
> + else if (state == 2)
> + {
> + if (saw_greater_than_sign && outbuf[i] == 'm')
> + {
> + /* Remove CSI > Pm m */
> + memmove (&outbuf[start_at], &outbuf[i+1], rlen-i-1);
> + rlen = start_at + rlen - i - 1;
> + i = start_at - 1;
> + state = 0;
> + }
> + else if (wincap.has_pcon_omit_nl_before_cursor_move ()
> + && !saw_greater_than_sign && outbuf[i] == 'H')
> + /* Workaround for rlwrap in Win11. rlwrap treats text between
> + NLs as a line, however, pseudo console in Win11 somtimes
sometimes
> + omits NL before "CSIm;nH". This does not happen in Win10. */
> + {
> + /* Add omitted CR NL before "CSIm;nH". However, when the
> + cusor is on the bottom-most line, adding NL might cause
cursor
> + unexpected scrolling. To avoid this, add "CSI H" before
> + CR NL. */
> + const char *ins = "\033[H\r\n";
> + const int ins_len = strlen (ins);
The strlen bugs me a bit. The expression is static and the length is
static, maybe the entire thing should express it's static, kind of like
this?
#define CSIH_INSERT "\033[H\r\n"
#define CSIH_INSLEN (sizeof(CSIH_INSERT)-1)
> + if (rlen + ins_len <= NT_MAX_PATH)
> + {
> + memmove (&outbuf[start_at + ins_len], &outbuf[start_at],
> + rlen - start_at);
> + memcpy (&outbuf[start_at], ins, ins_len);
> + rlen += ins_len;
> + i += ins_len;
> + }
> + }
> + state = 0;
> + }
> + else if (outbuf[i] == '\033')
> + {
> + start_at = i;
> + is_csi = false;
> + state = 1;
> + }
> + else
> + state = 0;
> + }
> + else if (is_osc)
> + {
> + if (state == 2 && isdigit (outbuf[i]))
> + arg = arg * 10 + (outbuf[i] - '0');
> + else if (state == 2 && outbuf[i] == ';')
> + state = 3;
> + else if (state == 3 && outbuf[i] == '\033')
> + state = 4;
> + else if ((state == 3 && outbuf[i] == '\a')
> + || (state == 4 && outbuf[i] == '\\'))
> + {
> + const char *helper_str = "\\bin\\cygwin-console-helper.exe";
Same here...
#define CONSOLE_HELPER ...
#define CONSOLE_HELPER_LEN
?
> + if (outbuf[start_at + 4] == '?' /* OSC Ps; ? BEL/ST */
> + /* Stray set title at the start up of pcon */
> + || (arg == 0 && memmem (&outbuf[start_at], i + 1 - start_at,
> + helper_str, strlen (helper_str))))
> + {
> + /* Remove this ESC sequence */
> + memmove (&outbuf[start_at], &outbuf[i+1], rlen-i-1);
> + rlen = start_at + rlen - i - 1;
> + i = start_at - 1;
> + }
> + state = 0;
> + }
> + else if (state == 3)
> + continue;
> + else if (outbuf[i] == '\033')
> + {
> + start_at = i;
> + is_osc = false;
> + state = 1;
> + }
> + else
> + state = 0;
> + }
> + else
> + state = 0; /* Do not reach */
> + return rlen;
> +}
> +
> /* The function pty_master_fwd_thread() should be static because the
> instance is deleted if the master is dup()'ed and the original is
> closed. In this case, dup()'ed instance still exists, therefore,
> @@ -2676,160 +2804,7 @@ fhandler_pty_master::pty_master_fwd_thread (const
> master_fwd_thread_param_t *p)
> char *ptr = outbuf;
> if (p->ttyp->pcon_activated)
> {
> - /* Avoid setting window title to "cygwin-console-helper.exe" */
> - int state = 0;
> - int start_at = 0;
> - for (DWORD i=0; i<rlen; i++)
> - if (state == 0 && outbuf[i] == '\033')
> - {
> - start_at = i;
> - state = 1;
> - continue;
> - }
> - else if ((state == 1 && outbuf[i] == ']') ||
> - (state == 2 && outbuf[i] == '0') ||
> - (state == 3 && outbuf[i] == ';') ||
> - (state == 4 && outbuf[i] == '\033'))
> - {
> - state ++;
> - continue;
> - }
> - else if ((state == 4 && outbuf[i] == '\a')
> - || (state == 5 && outbuf[i] == '\\'))
> - {
> - const char *helper_str = "\\bin\\cygwin-console-helper.exe";
> - if (memmem (&outbuf[start_at], i + 1 - start_at,
> - helper_str, strlen (helper_str)))
> - {
> - memmove (&outbuf[start_at], &outbuf[i+1], rlen-i-1);
> - rlen = wlen = start_at + rlen - i - 1;
> - i = start_at - 1;
> - }
> - state = 0;
> - continue;
> - }
> - else if (state == 4)
> - continue;
> - else if (outbuf[i] == '\033')
> - {
> - start_at = i;
> - state = 1;
> - continue;
> - }
> - else
> - {
> - state = 0;
> - continue;
> - }
> -
> - /* Remove CSI > Pm m */
> - state = 0;
> - for (DWORD i = 0; i < rlen; i++)
> - if (outbuf[i] == '\033')
> - {
> - start_at = i;
> - state = 1;
> - continue;
> - }
> - else if ((state == 1 && outbuf[i] == '[')
> - || (state == 2 && outbuf[i] == '>'))
> - {
> - state ++;
> - continue;
> - }
> - else if (state == 3 && (isdigit (outbuf[i]) || outbuf[i] == ';'))
> - continue;
> - else if (state == 3 && outbuf[i] == 'm')
> - {
> - memmove (&outbuf[start_at], &outbuf[i+1], rlen-i-1);
> - rlen = wlen = start_at + rlen - i - 1;
> - state = 0;
> - i = start_at - 1;
> - continue;
> - }
> - else
> - state = 0;
> -
> - /* Remove OSC Ps ; ? BEL/ST */
> - state = 0;
> - for (DWORD i = 0; i < rlen; i++)
> - if (state == 0 && outbuf[i] == '\033')
> - {
> - start_at = i;
> - state = 1;
> - continue;
> - }
> - else if ((state == 1 && outbuf[i] == ']')
> - || (state == 2 && outbuf[i] == ';')
> - || (state == 3 && outbuf[i] == '?')
> - || (state == 4 && outbuf[i] == '\033'))
> - {
> - state ++;
> - continue;
> - }
> - else if (state == 2 && isdigit (outbuf[i]))
> - continue;
> - else if ((state == 4 && outbuf[i] == '\a')
> - || (state == 5 && outbuf[i] == '\\'))
> - {
> - memmove (&outbuf[start_at], &outbuf[i+1], rlen-i-1);
> - rlen = wlen = start_at + rlen - i - 1;
> - state = 0;
> - i = start_at - 1;
> - continue;
> - }
> - else if (outbuf[i] == '\033')
> - {
> - start_at = i;
> - state = 1;
> - continue;
> - }
> - else
> - state = 0;
> -
> - /* Workaround for rlwrap in Win11. rlwrap treats text between
> - NLs as a line, however, pseudo console in Win11 somtimes
> - omits NL before "CSIm;nH". This does not happen in Win10. */
> - if (wincap.has_pcon_omit_nl_before_cursor_move ())
> - {
> - state = 0;
> - for (DWORD i = 0; i < rlen; i++)
> - if (state == 0 && outbuf[i] == '\033')
> - {
> - start_at = i;
> - state++;
> - continue;
> - }
> - else if (state == 1 && outbuf[i] == '[')
> - {
> - state++;
> - continue;
> - }
> - else if (state == 2
> - && (isdigit (outbuf[i]) || outbuf[i] == ';'))
> - continue;
> - else if (state == 2 && outbuf[i] == 'H')
> - {
> - /* Add omitted CR NL before "CSIm;nH". However, when the
> - cusor is on the bottom-most line, adding NL might cause
> - unexpected scrolling. To avoid this, add "CSI H" before
> - CR NL. */
> - const char *ins = "\033[H\r\n";
> - const int ins_len = strlen (ins);
> - if (rlen + ins_len <= NT_MAX_PATH)
> - {
> - memmove (&outbuf[start_at + ins_len],
> - &outbuf[start_at], rlen - start_at);
> - memcpy (&outbuf[start_at], ins, ins_len);
> - rlen += ins_len;
> - i += ins_len;
> - }
> - state = 0;
> - continue;
> - }
> - else
> - state = 0;
> - }
> + wlen = rlen = workarounds_for_pseudo_console_output (outbuf, rlen);
>
> if (p->ttyp->term_code_page != CP_UTF8)
> {
> --
> 2.51.0