Hi

On Sun, Feb 23, 2025 at 6:56 PM Roman Penyaev <r.peni...@gmail.com> wrote:
>
> This patch implements DCH (delete character) and ICH (insert
> character) commands.
>
> DCH - Delete Character:
>    "As characters are deleted, the remaining characters between the
>     cursor and right margin move to the left. Character attributes move
>     with the characters. The terminal adds blank spaces with no visual
>     character attributes at the right margin. DCH has no effect outside
>     the scrolling margins" [1].
>
> ICH - Insert Character:
>    "The ICH sequence inserts Pn blank characters with the normal
>     character attribute. The cursor remains at the beginning of the
>     blank characters. Text between the cursor and right margin moves to
>     the right. Characters scrolled past the right margin are lost. ICH
>     has no effect outside the scrolling margins" [2].
>
> Without these commands console is barely usable.
>
> [1] https://vt100.net/docs/vt510-rm/DCH.html
> [1] https://vt100.net/docs/vt510-rm/ICH.html
>
> Signed-off-by: Roman Penyaev <r.peni...@gmail.com>
> Cc: "Marc-André Lureau" <marcandre.lur...@redhat.com>
> Cc: qemu-devel@nongnu.org
> ---
>  ui/console-vc.c | 108 +++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 102 insertions(+), 6 deletions(-)
>
> diff --git a/ui/console-vc.c b/ui/console-vc.c
> index 522adc2806c8..bc667897d1bc 100644
> --- a/ui/console-vc.c
> +++ b/ui/console-vc.c
> @@ -598,21 +598,29 @@ static void vc_clear_xy(VCChardev *vc, int x, int y)
>      vc_update_xy(vc, x, y);
>  }
>
> -static void vc_put_one(VCChardev *vc, int ch)
> +static void vc_insert_xy(VCChardev *vc, int ch, int x, int y)
>  {
>      QemuTextConsole *s = vc->console;
>      TextCell *c;
>      int y1;
> +
> +    y1 = (s->y_base + y) % s->total_height;
> +    c = &s->cells[y1 * s->width + x];
> +    c->ch = ch;
> +    c->t_attrib = vc->t_attrib;
> +    vc_update_xy(vc, x, y);
> +}
> +
> +static void vc_put_one(VCChardev *vc, int ch)
> +{
> +    QemuTextConsole *s = vc->console;
> +
>      if (s->x >= s->width) {
>          /* line wrap */
>          s->x = 0;
>          vc_put_lf(vc);
>      }
> -    y1 = (s->y_base + s->y) % s->total_height;
> -    c = &s->cells[y1 * s->width + s->x];
> -    c->ch = ch;
> -    c->t_attrib = vc->t_attrib;
> -    vc_update_xy(vc, s->x, s->y);
> +    vc_insert_xy(vc, ch, s->x, s->y);
>      s->x++;
>  }
>
> @@ -645,6 +653,88 @@ static void vc_set_cursor(VCChardev *vc, int x, int y)
>      s->y = y;
>  }
>
> +/**
> + * vc_csi_P() - (DCH) deletes one or more characters from the cursor
> + * position to the right. As characters are deleted, the remaining
> + * characters between the cursor and right margin move to the
> + * left. Character attributes move with the characters.
> + */
> +static void vc_csi_P(struct VCChardev *vc, unsigned int nr)
> +{
> +    QemuTextConsole *s = vc->console;
> +    TextCell *c1, *c2;
> +    unsigned int x1, x2, y;
> +    unsigned int end, len;
> +
> +    if (!nr) {
> +        nr = 1;
> +    }
> +    if (nr > s->width - s->x) {
> +        nr = s->width - s->x;
> +        if (!nr) {
> +            return;
> +        }
> +    }
> +
> +    x1 = s->x;
> +    x2 = s->x + nr;
> +    len = s->width - x2;
> +    if (len) {
> +        y = (s->y_base + s->y) % s->total_height;
> +        c1 = &s->cells[y * s->width + x1];
> +        c2 = &s->cells[y * s->width + x2];
> +        memmove(c1, c2, len * sizeof(*c1));
> +        for (end = x1 + len; x1 < end; x1++) {
> +            vc_update_xy(vc, x1, s->y);
> +        }
> +    }
> +    /* Clear the rest */
> +    for (; x1 < s->width; x1++) {
> +        vc_clear_xy(vc, x1, s->y);
> +    }
> +}
> +
> +/**
> + * vc_csi_at() - (ICH) inserts `nr` blank characters with the normal
> + * character attribute. The cursor remains at the beginning of the

What is "normal character attribute"?

Should you set it to  TEXT_ATTRIBUTES_DEFAULT while inserting blank chars?

> + * blank characters. Text between the cursor and right margin moves to
> + * the right. Characters scrolled past the right margin are lost.
> + */
> +static void vc_csi_at(struct VCChardev *vc, unsigned int nr)
> +{
> +    QemuTextConsole *s = vc->console;
> +    TextCell *c1, *c2;
> +    unsigned int x1, x2, y;
> +    unsigned int end, len;
> +
> +    if (!nr) {
> +        nr = 1;
> +    }
> +    if (nr > s->width - s->x) {
> +        nr = s->width - s->x;
> +        if (!nr) {
> +            return;
> +        }
> +    }
> +
> +    x1 = s->x + nr;
> +    x2 = s->x;
> +    len = s->width - x1;
> +    if (len) {
> +        y = (s->y_base + s->y) % s->total_height;
> +        c1 = &s->cells[y * s->width + x1];
> +        c2 = &s->cells[y * s->width + x2];
> +        memmove(c1, c2, len * sizeof(*c1));
> +        for (end = x1 + len; x1 < end; x1++) {
> +            vc_update_xy(vc, x1, s->y);
> +        }
> +    }
> +    /* Insert spaces */
> +    for (x1 = s->x; x1 < s->x + nr; x1++) {
> +        vc_insert_xy(vc, ' ', x1, s->y);
> +    }
> +}
> +
>  /**
>   * vc_save_cursor() - saves cursor position and character attributes.
>   */
> @@ -847,6 +937,9 @@ static void vc_putchar(VCChardev *vc, int ch)
>                      break;
>                  }
>                  break;
> +            case 'P':
> +                vc_csi_P(vc, vc->esc_params[0]);
> +                break;
>              case 'm':
>                  vc_handle_escape(vc);
>                  break;
> @@ -870,6 +963,9 @@ static void vc_putchar(VCChardev *vc, int ch)
>              case 'u':
>                  vc_restore_cursor(vc);
>                  break;
> +            case '@':
> +                vc_csi_at(vc, vc->esc_params[0]);
> +                break;
>              default:
>                  trace_console_putchar_unhandled(ch);
>                  break;
> --
> 2.43.0
>
>


-- 
Marc-André Lureau

Reply via email to