Patch 9.0.0774
Problem:    The libvterm code is outdated.
Solution:   Include libvterm changes from revision 802 to 817.  Revert some
            changes made for C89.
Files:      src/libvterm/README, src/libvterm/CONTRIBUTING,
            src/libvterm/Makefile, src/libvterm/doc/seqs.txt,
            src/libvterm/include/vterm.h, src/libvterm/src/encoding.c,
            src/libvterm/src/keyboard.c, src/libvterm/src/parser.c,
            src/libvterm/src/pen.c, src/libvterm/src/screen.c,
            src/libvterm/src/state.c, src/libvterm/src/unicode.c,
            src/libvterm/src/vterm.c, src/libvterm/src/vterm_internal.h,
            src/libvterm/t/harness.c, src/libvterm/t/10state_putglyph.test,
            src/libvterm/t/13state_edit.test,
            src/libvterm/t/26state_query.test,
            src/libvterm/t/30state_pen.test, src/libvterm/t/64screen_pen.test,
            src/libvterm/t/69screen_reflow.test, src/libvterm/t/run-test.pl,
            src/terminal.c


*** ../vim-9.0.0773/src/libvterm/README 2022-10-16 14:35:41.840813752 +0100
--- src/libvterm/README 2022-10-16 18:20:18.898915023 +0100
***************
*** 7,14 ****
        https://github.com/neovim/libvterm
  
  Modifications:
! - Add a .gitignore file.
! - Convert some code from C99 to C90.
  - Other changes to support embedding in Vim.
  
  To get the latest version of libvterm you need the "bzr" command and do:
--- 7,17 ----
        https://github.com/neovim/libvterm
  
  Modifications:
! - revisions up to 817 have been included
! - Added a .gitignore file.
! - use TRUE and FALSE instead of true and false
! - use int or unsigned int instead of bool
! - Converted some code from C99 to C90.
  - Other changes to support embedding in Vim.
  
  To get the latest version of libvterm you need the "bzr" command and do:
*** ../vim-9.0.0773/src/libvterm/CONTRIBUTING   2020-05-17 21:20:28.000000000 
+0100
--- src/libvterm/CONTRIBUTING   2022-10-16 16:36:56.330870321 +0100
***************
*** 6,13 ****
    Launchpad
      https://launchpad.net/libvterm
  
!   Freenode:
!     ##tty or #tickit on irc.freenode.net
  
    Email:
      Paul "LeoNerd" Evans <[email protected]>
--- 6,13 ----
    Launchpad
      https://launchpad.net/libvterm
  
!   IRC:
!     ##tty or #tickit on irc.libera.chat
  
    Email:
      Paul "LeoNerd" Evans <[email protected]>
*** ../vim-9.0.0773/src/libvterm/Makefile       2021-11-24 17:06:17.000000000 
+0000
--- src/libvterm/Makefile       2022-10-16 17:55:10.159371324 +0100
***************
*** 37,43 ****
  HFILES_INT=$(sort $(wildcard src/*.h)) $(HFILES)
  
  VERSION_MAJOR=0
! VERSION_MINOR=2
  
  VERSION_CURRENT=0
  VERSION_REVISION=0
--- 37,43 ----
  HFILES_INT=$(sort $(wildcard src/*.h)) $(HFILES)
  
  VERSION_MAJOR=0
! VERSION_MINOR=3
  
  VERSION_CURRENT=0
  VERSION_REVISION=0
*** ../vim-9.0.0773/src/libvterm/doc/seqs.txt   2022-10-16 14:35:41.840813752 
+0100
--- src/libvterm/doc/seqs.txt   2022-10-16 17:56:53.415392912 +0100
***************
*** 122,127 ****
--- 122,128 ----
  123x   CSI l            = RM, Reset mode
  123x   CSI ? l          = DECRM, DEC reset mode
  123x   CSI m            = SGR, Set Graphic Rendition
+        CSI ? m          = DECSGR, private Set Graphic Rendition
  123x   CSI   n          = DSR, Device Status Report
   23x       5            =   operating status
   23x       6            =   CPR = cursor position
***************
*** 198,203 ****
--- 199,207 ----
     x   SGR 40-47        = Background ANSI
     x   SGR 48           = Background alternative palette
     x   SGR 49           = Background default
+        SGR 73           = Superscript on
+        SGR 74           = Subscript on
+        SGR 75           = Superscript/subscript off
     x   SGR 90-97        = Foreground ANSI high-intensity
     x   SGR 100-107      = Background ANSI high-intensity
  
*** ../vim-9.0.0773/src/libvterm/include/vterm.h        2022-10-16 
14:35:41.840813752 +0100
--- src/libvterm/include/vterm.h        2022-10-16 18:24:14.722785995 +0100
***************
*** 12,27 ****
  
  #include "vterm_keycodes.h"
  
  #define TRUE 1
  #define FALSE 0
  
! // from stdint.h
  typedef unsigned char         uint8_t;
  typedef unsigned short                uint16_t;
  typedef unsigned int          uint32_t;
  
  #define VTERM_VERSION_MAJOR 0
! #define VTERM_VERSION_MINOR 2
  
  #define VTERM_CHECK_VERSION \
          vterm_check_version(VTERM_VERSION_MAJOR, VTERM_VERSION_MINOR)
--- 12,28 ----
  
  #include "vterm_keycodes.h"
  
+ // VIM: use TRUE and FALSE instead of true and false
  #define TRUE 1
  #define FALSE 0
  
! // VIM: from stdint.h
  typedef unsigned char         uint8_t;
  typedef unsigned short                uint16_t;
  typedef unsigned int          uint32_t;
  
  #define VTERM_VERSION_MAJOR 0
! #define VTERM_VERSION_MINOR 3
  
  #define VTERM_CHECK_VERSION \
          vterm_check_version(VTERM_VERSION_MAJOR, VTERM_VERSION_MINOR)
***************
*** 131,137 ****
    VTERM_COLOR_DEFAULT_MASK = 0x06,
  
    /**
!    * If set, indicates that the color is invalid.
     */
    VTERM_COLOR_INVALID = 0x08
  } VTermColorType;
--- 132,138 ----
    VTERM_COLOR_DEFAULT_MASK = 0x06,
  
    /**
!    * VIM: If set, indicates that the color is invalid.
     */
    VTERM_COLOR_INVALID = 0x08
  } VTermColorType;
***************
*** 172,177 ****
--- 173,179 ----
   */
  #define VTERM_COLOR_IS_INVALID(col) (!!((col)->type & VTERM_COLOR_INVALID))
  
+ // VIM: this was a union, but that doesn't always work.
  typedef struct {
    /**
     * Tag indicating which member is actually valid.
***************
*** 237,242 ****
--- 239,246 ----
    VTERM_ATTR_FONT,       // number: 10-19
    VTERM_ATTR_FOREGROUND, // color:  30-39 90-97
    VTERM_ATTR_BACKGROUND, // color:  40-49 100-107
+   VTERM_ATTR_SMALL,      // bool:   73, 74, 75
+   VTERM_ATTR_BASELINE,   // number: 73, 74, 75
  
    VTERM_N_ATTRS
  } VTermAttr;
***************
*** 251,257 ****
    VTERM_PROP_REVERSE,           // bool
    VTERM_PROP_CURSORSHAPE,       // number
    VTERM_PROP_MOUSE,             // number
!   VTERM_PROP_CURSORCOLOR,       // string
  
    VTERM_N_PROPS
  } VTermProp;
--- 255,261 ----
    VTERM_PROP_REVERSE,           // bool
    VTERM_PROP_CURSORSHAPE,       // number
    VTERM_PROP_MOUSE,             // number
!   VTERM_PROP_CURSORCOLOR,       // VIM - string
  
    VTERM_N_PROPS
  } VTermProp;
***************
*** 312,318 ****
    void  (*free)(void *ptr, void *allocdata);
  } VTermAllocatorFunctions;
  
- /* A convenient shortcut for default cases */
  void vterm_check_version(int major, int minor);
  
  struct VTermBuilder {
--- 316,321 ----
***************
*** 333,339 ****
  /* A convenient shortcut for default cases */
  // Allocate and initialize a new terminal with default allocators.
  VTerm *vterm_new(int rows, int cols);
- 
  /* These shortcuts are generally discouraged in favour of just using 
vterm_build() */
  
  // Allocate and initialize a new terminal with specified allocators.
--- 336,341 ----
***************
*** 396,401 ****
--- 398,404 ----
  #define CSI_ARG(a)          ((a) & CSI_ARG_MASK)
  
  /* Can't use -1 to indicate a missing argument; use this instead */
+ // VIM: changed 31 to 30 to avoid an overflow warning
  #define CSI_ARG_MISSING ((1<<30)-1)
  
  #define CSI_ARG_IS_MISSING(a) (CSI_ARG(a) == CSI_ARG_MISSING)
***************
*** 436,443 ****
--- 439,448 ----
    int (*bell)(void *user);
    int (*resize)(int rows, int cols, VTermStateFields *fields, void *user);
    int (*setlineinfo)(int row, const VTermLineInfo *newinfo, const 
VTermLineInfo *oldinfo, void *user);
+   int (*sb_clear)(void *user);
  } VTermStateCallbacks;
  
+ // VIM: added
  typedef struct {
    VTermPos pos;
    int    buttons;
***************
*** 478,483 ****
--- 483,489 ----
  void vterm_state_reset(VTermState *state, int hard);
  
  void vterm_state_get_cursorpos(const VTermState *state, VTermPos *cursorpos);
+ // VIM: added
  void vterm_state_get_mousestate(const VTermState *state, VTermMouseState 
*mousestate);
  void vterm_state_get_default_colors(const VTermState *state, VTermColor 
*default_fg, VTermColor *default_bg);
  void vterm_state_get_palette_color(const VTermState *state, int index, 
VTermColor *col);
***************
*** 522,527 ****
--- 528,535 ----
      unsigned int font      : 4; /* 0 to 9 */
      unsigned int dwl       : 1; /* On a DECDWL or DECDHL line */
      unsigned int dhl       : 2; /* On a DECDHL line (1=top 2=bottom) */
+     unsigned int small     : 1;
+     unsigned int baseline  : 2;
  } VTermScreenCellAttrs;
  
  enum {
***************
*** 531,536 ****
--- 539,550 ----
    VTERM_UNDERLINE_CURLY,
  };
  
+ enum {
+   VTERM_BASELINE_NORMAL,
+   VTERM_BASELINE_RAISE,
+   VTERM_BASELINE_LOWER,
+ };
+ 
  typedef struct {
    uint32_t chars[VTERM_MAX_CHARS_PER_CELL];
    char     width;
***************
*** 551,556 ****
--- 565,571 ----
    // Return value is unused.
    int (*sb_pushline)(int cols, const VTermScreenCell *cells, void *user);
    int (*sb_popline)(int cols, VTermScreenCell *cells, void *user);
+   int (*sb_clear)(void* user);
  } VTermScreenCallbacks;
  
  // Return the screen of the vterm.
***************
*** 566,571 ****
--- 581,591 ----
  void  vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const 
VTermStateFallbacks *fallbacks, void *user);
  void *vterm_screen_get_unrecognised_fbdata(VTermScreen *screen);
  
+ void vterm_screen_enable_reflow(VTermScreen *screen, int reflow);
+ 
+ // Back-compat alias for the brief time it was in 0.3-RC1
+ #define vterm_screen_set_reflow  vterm_screen_enable_reflow
+ 
  // Enable support for using the alternate screen if "altscreen" is non-zero.
  // Before that switching to the alternate screen won't work.
  // Calling with "altscreen" zero has no effect.
***************
*** 606,613 ****
    VTERM_ATTR_FOREGROUND_MASK = 1 << 7,
    VTERM_ATTR_BACKGROUND_MASK = 1 << 8,
    VTERM_ATTR_CONCEAL_MASK    = 1 << 9,
  
!   VTERM_ALL_ATTRS_MASK = (1 << 10) - 1
  } VTermAttrMask;
  
  int vterm_screen_get_attrs_extent(const VTermScreen *screen, VTermRect 
*extent, VTermPos pos, VTermAttrMask attrs);
--- 626,635 ----
    VTERM_ATTR_FOREGROUND_MASK = 1 << 7,
    VTERM_ATTR_BACKGROUND_MASK = 1 << 8,
    VTERM_ATTR_CONCEAL_MASK    = 1 << 9,
+   VTERM_ATTR_SMALL_MASK      = 1 << 10,
+   VTERM_ATTR_BASELINE_MASK   = 1 << 11,
  
!   VTERM_ALL_ATTRS_MASK = (1 << 12) - 1
  } VTermAttrMask;
  
  int vterm_screen_get_attrs_extent(const VTermScreen *screen, VTermRect 
*extent, VTermPos pos, VTermAttrMask attrs);
*** ../vim-9.0.0773/src/libvterm/src/encoding.c 2020-05-22 20:14:56.000000000 
+0100
--- src/libvterm/src/encoding.c 2022-10-16 18:28:08.364109247 +0100
***************
*** 49,54 ****
--- 49,55 ----
        if(data->bytes_remaining) {
          data->bytes_remaining = 0;
          cp[(*cpi)++] = UNICODE_INVALID;
+       // VIM: avoid going over the end
        if (*cpi >= cplen)
          break;
        }
***************
*** 226,233 ****
  /* This ought to be INTERNAL but isn't because it's used by unit testing */
  VTermEncoding *vterm_lookup_encoding(VTermEncodingType type, char designation)
  {
!   int i;
!   for(i = 0; encodings[i].designation; i++)
      if(encodings[i].type == type && encodings[i].designation == designation)
        return encodings[i].enc;
    return NULL;
--- 227,233 ----
  /* This ought to be INTERNAL but isn't because it's used by unit testing */
  VTermEncoding *vterm_lookup_encoding(VTermEncodingType type, char designation)
  {
!   for(int i = 0; encodings[i].designation; i++)
      if(encodings[i].type == type && encodings[i].designation == designation)
        return encodings[i].enc;
    return NULL;
*** ../vim-9.0.0773/src/libvterm/src/keyboard.c 2020-05-22 20:19:33.000000000 
+0100
--- src/libvterm/src/keyboard.c 2022-10-16 18:31:40.812946125 +0100
***************
*** 4,9 ****
--- 4,10 ----
  
  #include "utf8.h"
  
+ // VIM: added
  int vterm_is_modify_other_keys(VTerm *vt)
  {
    return vt->state->mode.modify_other_keys;
***************
*** 12,19 ****
  
  void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod)
  {
!   int needs_CSIu;
! 
    if (vt->state->mode.modify_other_keys && mod != 0) {
      vterm_push_output_sprintf_ctrl(vt, C1_CSI, "27;%d;%d~", mod+1, c);
      return;
--- 13,19 ----
  
  void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod)
  {
!   // VIM: added modifyOtherKeys support
    if (vt->state->mode.modify_other_keys && mod != 0) {
      vterm_push_output_sprintf_ctrl(vt, C1_CSI, "27;%d;%d~", mod+1, c);
      return;
***************
*** 33,38 ****
--- 33,39 ----
      return;
    }
  
+   int needs_CSIu;
    switch(c) {
      /* Special Ctrl- letters that can't be represented elsewise */
      case 'i': case 'j': case 'm': case '[':
***************
*** 93,104 ****
    { KEYCODE_CSI_CURSOR, 'D', 0 }, // LEFT
    { KEYCODE_CSI_CURSOR, 'C', 0 }, // RIGHT
  
!   { KEYCODE_CSINUM,     '~', 2 }, // INS
!   { KEYCODE_CSINUM,     '~', 3 }, // DEL
    { KEYCODE_CSI_CURSOR, 'H', 0 }, // HOME
    { KEYCODE_CSI_CURSOR, 'F', 0 }, // END
!   { KEYCODE_CSINUM,     '~', 5 }, // PAGEUP
!   { KEYCODE_CSINUM,     '~', 6 }, // PAGEDOWN
  };
  
  static keycodes_s keycodes_fn[] = {
--- 94,105 ----
    { KEYCODE_CSI_CURSOR, 'D', 0 }, // LEFT
    { KEYCODE_CSI_CURSOR, 'C', 0 }, // RIGHT
  
!   { KEYCODE_CSINUM, '~', 2 },  // INS
!   { KEYCODE_CSINUM, '~', 3 },  // DEL
    { KEYCODE_CSI_CURSOR, 'H', 0 }, // HOME
    { KEYCODE_CSI_CURSOR, 'F', 0 }, // END
!   { KEYCODE_CSINUM, '~', 5 },  // PAGEUP
!   { KEYCODE_CSINUM, '~', 6 },  // PAGEDOWN
  };
  
  static keycodes_s keycodes_fn[] = {
***************
*** 107,120 ****
    { KEYCODE_SS3,      'Q', 0 }, // F2
    { KEYCODE_SS3,      'R', 0 }, // F3
    { KEYCODE_SS3,      'S', 0 }, // F4
!   { KEYCODE_CSINUM,     '~', 15 }, // F5
!   { KEYCODE_CSINUM,     '~', 17 }, // F6
!   { KEYCODE_CSINUM,     '~', 18 }, // F7
!   { KEYCODE_CSINUM,     '~', 19 }, // F8
!   { KEYCODE_CSINUM,     '~', 20 }, // F9
!   { KEYCODE_CSINUM,     '~', 21 }, // F10
!   { KEYCODE_CSINUM,     '~', 23 }, // F11
!   { KEYCODE_CSINUM,     '~', 24 }, // F12
  };
  
  static keycodes_s keycodes_kp[] = {
--- 108,121 ----
    { KEYCODE_SS3,      'Q', 0 }, // F2
    { KEYCODE_SS3,      'R', 0 }, // F3
    { KEYCODE_SS3,      'S', 0 }, // F4
!   { KEYCODE_CSINUM, '~', 15 }, // F5
!   { KEYCODE_CSINUM, '~', 17 }, // F6
!   { KEYCODE_CSINUM, '~', 18 }, // F7
!   { KEYCODE_CSINUM, '~', 19 }, // F8
!   { KEYCODE_CSINUM, '~', 20 }, // F9
!   { KEYCODE_CSINUM, '~', 21 }, // F10
!   { KEYCODE_CSINUM, '~', 23 }, // F11
!   { KEYCODE_CSINUM, '~', 24 }, // F12
  };
  
  static keycodes_s keycodes_kp[] = {
***************
*** 140,150 ****
  
  void vterm_keyboard_key(VTerm *vt, VTermKey key, VTermModifier mod)
  {
-   keycodes_s k;
- 
    if(key == VTERM_KEY_NONE)
      return;
  
    if(key < VTERM_KEY_FUNCTION_0) {
      if(key >= sizeof(keycodes)/sizeof(keycodes[0]))
        return;
--- 141,150 ----
  
  void vterm_keyboard_key(VTerm *vt, VTermKey key, VTermModifier mod)
  {
    if(key == VTERM_KEY_NONE)
      return;
  
+   keycodes_s k;
    if(key < VTERM_KEY_FUNCTION_0) {
      if(key >= sizeof(keycodes)/sizeof(keycodes[0]))
        return;
*** ../vim-9.0.0773/src/libvterm/src/parser.c   2021-11-24 18:06:27.000000000 
+0000
--- src/libvterm/src/parser.c   2022-10-16 18:34:14.953397598 +0100
***************
*** 142,148 ****
    for( ; pos < len; pos++) {
      unsigned char c = bytes[pos];
      int c1_allowed = !vt->mode.utf8;
-     size_t string_len;
  
      if(c == 0x00 || c == 0x7f) { // NUL, DEL
        if(IS_STRING_STATE()) {
--- 142,147 ----
***************
*** 187,193 ****
      }
      // else fallthrough
  
!     string_len = bytes + pos - string_start;
  
      if(vt->parser.in_esc) {
        // Hoist an ESC letter into a C1 if we're not in a string mode
--- 186,192 ----
      }
      // else fallthrough
  
!     size_t string_len = bytes + pos - string_start;
  
      if(vt->parser.in_esc) {
        // Hoist an ESC letter into a C1 if we're not in a string mode
***************
*** 247,253 ****
        vt->parser.v.csi.argi++;
        vt->parser.intermedlen = 0;
        vt->parser.state = CSI_INTERMED;
!       // fallthrough
      case CSI_INTERMED:
        if(is_intermed(c)) {
          if(vt->parser.intermedlen < INTERMED_MAX-1)
--- 246,252 ----
        vt->parser.v.csi.argi++;
        vt->parser.intermedlen = 0;
        vt->parser.state = CSI_INTERMED;
!       // FALLTHROUGH
      case CSI_INTERMED:
        if(is_intermed(c)) {
          if(vt->parser.intermedlen < INTERMED_MAX-1)
*** ../vim-9.0.0773/src/libvterm/src/pen.c      2020-06-29 22:12:33.000000000 
+0100
--- src/libvterm/src/pen.c      2022-10-16 18:37:49.997877703 +0100
***************
*** 44,49 ****
--- 44,50 ----
  
  static void lookup_default_colour_ansi(long idx, VTermColor *col)
  {
+   // VIM: store both RGB color and index
    vterm_color_rgb(
        col,
        ansi_colors[idx].red, ansi_colors[idx].green, ansi_colors[idx].blue);
***************
*** 161,187 ****
  
  INTERNAL void vterm_state_newpen(VTermState *state)
  {
-   int col;
- 
    // 90% grey so that pure white is brighter
    vterm_color_rgb(&state->default_fg, 240, 240, 240);
    vterm_color_rgb(&state->default_bg, 0, 0, 0);
    vterm_state_set_default_colors(state, &state->default_fg, 
&state->default_bg);
  
!   for(col = 0; col < 16; col++)
      lookup_default_colour_ansi(col, &state->colors[col]);
  }
  
  INTERNAL void vterm_state_resetpen(VTermState *state)
  {
    state->pen.bold = 0;      setpenattr_bool(state, VTERM_ATTR_BOLD, 0);
!   state->pen.underline = 0; setpenattr_int( state, VTERM_ATTR_UNDERLINE, 0);
    state->pen.italic = 0;    setpenattr_bool(state, VTERM_ATTR_ITALIC, 0);
    state->pen.blink = 0;     setpenattr_bool(state, VTERM_ATTR_BLINK, 0);
    state->pen.reverse = 0;   setpenattr_bool(state, VTERM_ATTR_REVERSE, 0);
    state->pen.conceal = 0;   setpenattr_bool(state, VTERM_ATTR_CONCEAL, 0);
    state->pen.strike = 0;    setpenattr_bool(state, VTERM_ATTR_STRIKE, 0);
!   state->pen.font = 0;      setpenattr_int( state, VTERM_ATTR_FONT, 0);
  
    state->pen.fg = state->default_fg;  setpenattr_col(state, 
VTERM_ATTR_FOREGROUND, state->default_fg);
    state->pen.bg = state->default_bg;  setpenattr_col(state, 
VTERM_ATTR_BACKGROUND, state->default_bg);
--- 162,188 ----
  
  INTERNAL void vterm_state_newpen(VTermState *state)
  {
    // 90% grey so that pure white is brighter
    vterm_color_rgb(&state->default_fg, 240, 240, 240);
    vterm_color_rgb(&state->default_bg, 0, 0, 0);
    vterm_state_set_default_colors(state, &state->default_fg, 
&state->default_bg);
  
!   for(int col = 0; col < 16; col++)
      lookup_default_colour_ansi(col, &state->colors[col]);
  }
  
  INTERNAL void vterm_state_resetpen(VTermState *state)
  {
    state->pen.bold = 0;      setpenattr_bool(state, VTERM_ATTR_BOLD, 0);
!   state->pen.underline = 0; setpenattr_int (state, VTERM_ATTR_UNDERLINE, 0);
    state->pen.italic = 0;    setpenattr_bool(state, VTERM_ATTR_ITALIC, 0);
    state->pen.blink = 0;     setpenattr_bool(state, VTERM_ATTR_BLINK, 0);
    state->pen.reverse = 0;   setpenattr_bool(state, VTERM_ATTR_REVERSE, 0);
    state->pen.conceal = 0;   setpenattr_bool(state, VTERM_ATTR_CONCEAL, 0);
    state->pen.strike = 0;    setpenattr_bool(state, VTERM_ATTR_STRIKE, 0);
!   state->pen.font = 0;      setpenattr_int (state, VTERM_ATTR_FONT, 0);
!   state->pen.small = 0;     setpenattr_bool(state, VTERM_ATTR_SMALL, 0);
!   state->pen.baseline = 0;  setpenattr_int (state, VTERM_ATTR_BASELINE, 0);
  
    state->pen.fg = state->default_fg;  setpenattr_col(state, 
VTERM_ATTR_FOREGROUND, state->default_fg);
    state->pen.bg = state->default_bg;  setpenattr_col(state, 
VTERM_ATTR_BACKGROUND, state->default_bg);
***************
*** 195,208 ****
    else {
      state->pen = state->saved.pen;
  
!     setpenattr_bool(state, VTERM_ATTR_BOLD,       state->pen.bold);
!     setpenattr_int( state, VTERM_ATTR_UNDERLINE,  state->pen.underline);
!     setpenattr_bool(state, VTERM_ATTR_ITALIC,     state->pen.italic);
!     setpenattr_bool(state, VTERM_ATTR_BLINK,      state->pen.blink);
!     setpenattr_bool(state, VTERM_ATTR_REVERSE,    state->pen.reverse);
!     setpenattr_bool(state, VTERM_ATTR_CONCEAL,    state->pen.conceal);
!     setpenattr_bool(state, VTERM_ATTR_STRIKE,     state->pen.strike);
!     setpenattr_int( state, VTERM_ATTR_FONT,       state->pen.font);
      setpenattr_col( state, VTERM_ATTR_FOREGROUND, state->pen.fg);
      setpenattr_col( state, VTERM_ATTR_BACKGROUND, state->pen.bg);
    }
--- 196,212 ----
    else {
      state->pen = state->saved.pen;
  
!     setpenattr_bool(state, VTERM_ATTR_BOLD,      state->pen.bold);
!     setpenattr_int (state, VTERM_ATTR_UNDERLINE, state->pen.underline);
!     setpenattr_bool(state, VTERM_ATTR_ITALIC,    state->pen.italic);
!     setpenattr_bool(state, VTERM_ATTR_BLINK,     state->pen.blink);
!     setpenattr_bool(state, VTERM_ATTR_REVERSE,   state->pen.reverse);
!     setpenattr_bool(state, VTERM_ATTR_CONCEAL,   state->pen.conceal);
!     setpenattr_bool(state, VTERM_ATTR_STRIKE,    state->pen.strike);
!     setpenattr_int (state, VTERM_ATTR_FONT,      state->pen.font);
!     setpenattr_bool(state, VTERM_ATTR_SMALL,     state->pen.small);
!     setpenattr_int (state, VTERM_ATTR_BASELINE,  state->pen.baseline);
! 
      setpenattr_col( state, VTERM_ATTR_FOREGROUND, state->pen.fg);
      setpenattr_col( state, VTERM_ATTR_BACKGROUND, state->pen.bg);
    }
***************
*** 447,452 ****
--- 451,468 ----
        setpenattr_col(state, VTERM_ATTR_BACKGROUND, state->pen.bg);
        break;
  
+     case 73: // Superscript
+     case 74: // Subscript
+     case 75: // Superscript/subscript off
+       state->pen.small = (arg != 75);
+       state->pen.baseline =
+         (arg == 73) ? VTERM_BASELINE_RAISE :
+         (arg == 74) ? VTERM_BASELINE_LOWER :
+                       VTERM_BASELINE_NORMAL;
+       setpenattr_bool(state, VTERM_ATTR_SMALL,    state->pen.small);
+       setpenattr_int (state, VTERM_ATTR_BASELINE, state->pen.baseline);
+       break;
+ 
      case 90: case 91: case 92: case 93:
      case 94: case 95: case 96: case 97: // Foreground colour high-intensity 
palette
        value = CSI_ARG(args[argi]) - 90 + 8;
***************
*** 544,549 ****
--- 560,572 ----
  
    argi = vterm_state_getpen_color(&state->pen.bg, argi, args, FALSE);
  
+   if(state->pen.small) {
+     if(state->pen.baseline == VTERM_BASELINE_RAISE)
+       args[argi++] = 73;
+     else if(state->pen.baseline == VTERM_BASELINE_LOWER)
+       args[argi++] = 74;
+   }
+ 
    return argi;
  }
  
***************
*** 590,595 ****
--- 613,626 ----
      val->color = state->pen.bg;
      return 1;
  
+   case VTERM_ATTR_SMALL:
+     val->boolean = state->pen.small;
+     return 1;
+ 
+   case VTERM_ATTR_BASELINE:
+     val->number = state->pen.baseline;
+     return 1;
+ 
    case VTERM_N_ATTRS:
      return 0;
    }
*** ../vim-9.0.0773/src/libvterm/src/screen.c   2022-10-16 14:35:41.840813752 
+0100
--- src/libvterm/src/screen.c   2022-10-16 18:58:01.835223223 +0100
***************
*** 10,15 ****
--- 10,17 ----
  #define UNICODE_SPACE 0x20
  #define UNICODE_LINEFEED 0x0a
  
+ #undef DEBUG_REFLOW
+ 
  /* State of the pen at some moment in time, also used in a cell */
  typedef struct
  {
***************
*** 24,29 ****
--- 26,33 ----
    unsigned int conceal   : 1;
    unsigned int strike    : 1;
    unsigned int font      : 4; /* 0 to 9 */
+   unsigned int small     : 1;
+   unsigned int baseline  : 2;
  
    /* Extra state storage that isn't strictly pen-related */
    unsigned int protected_cell : 1;
***************
*** 54,60 ****
  
    int rows;
    int cols;
!   int global_reverse;
  
    /* Primary and Altscreen. buffers[1] is lazily allocated as needed */
    ScreenCell *buffers[2];
--- 58,66 ----
  
    int rows;
    int cols;
! 
!   unsigned int global_reverse : 1;
!   unsigned int reflow : 1;
  
    /* Primary and Altscreen. buffers[1] is lazily allocated as needed */
    ScreenCell *buffers[2];
***************
*** 88,98 ****
  static ScreenCell *alloc_buffer(VTermScreen *screen, int rows, int cols)
  {
    ScreenCell *new_buffer = vterm_allocator_malloc(screen->vt, 
sizeof(ScreenCell) * rows * cols);
-   int row;
-   int col;
  
!   for(row = 0; row < rows; row++) {
!     for(col = 0; col < cols; col++) {
        clearcell(screen, &new_buffer[row * cols + col]);
      }
    }
--- 94,102 ----
  static ScreenCell *alloc_buffer(VTermScreen *screen, int rows, int cols)
  {
    ScreenCell *new_buffer = vterm_allocator_malloc(screen->vt, 
sizeof(ScreenCell) * rows * cols);
  
!   for(int row = 0; row < rows; row++) {
!     for(int col = 0; col < cols; col++) {
        clearcell(screen, &new_buffer[row * cols + col]);
      }
    }
***************
*** 168,183 ****
  
  static int putglyph(VTermGlyphInfo *info, VTermPos pos, void *user)
  {
-   int i;
-   int col;
-   VTermRect rect;
- 
    VTermScreen *screen = user;
    ScreenCell *cell = getcell(screen, pos.row, pos.col);
  
    if(!cell)
      return 0;
  
    for(i = 0; i < VTERM_MAX_CHARS_PER_CELL && info->chars[i]; i++) {
      cell->chars[i] = info->chars[i];
      cell->pen = screen->pen;
--- 172,184 ----
  
  static int putglyph(VTermGlyphInfo *info, VTermPos pos, void *user)
  {
    VTermScreen *screen = user;
    ScreenCell *cell = getcell(screen, pos.row, pos.col);
  
    if(!cell)
      return 0;
  
+   int i;
    for(i = 0; i < VTERM_MAX_CHARS_PER_CELL && info->chars[i]; i++) {
      cell->chars[i] = info->chars[i];
      cell->pen = screen->pen;
***************
*** 185,191 ****
    if(i < VTERM_MAX_CHARS_PER_CELL)
      cell->chars[i] = 0;
  
!   for(col = 1; col < info->width; col++)
    {
      ScreenCell *onecell = getcell(screen, pos.row, pos.col + col);
      if (onecell == NULL)
--- 186,192 ----
    if(i < VTERM_MAX_CHARS_PER_CELL)
      cell->chars[i] = 0;
  
!   for(int col = 1; col < info->width; col++)
    {
      ScreenCell *onecell = getcell(screen, pos.row, pos.col + col);
      if (onecell == NULL)
***************
*** 193,198 ****
--- 194,200 ----
      onecell->chars[0] = (uint32_t)-1;
    }
  
+   VTermRect rect;
    rect.start_row = pos.row;
    rect.end_row   = pos.row+1;
    rect.start_col = pos.col;
***************
*** 225,257 ****
       dest.start_row == 0 && dest.start_col == 0 &&        // starts top-left 
corner
       dest.end_col == screen->cols &&                      // full width
       screen->buffer == screen->buffers[BUFIDX_PRIMARY]) { // not altscreen
!     int row;
!     for(row = 0; row < src.start_row; row++)
        sb_pushline_from_row(screen, row);
    }
  
!   {
!     int cols = src.end_col - src.start_col;
!     int downward = src.start_row - dest.start_row;
!     int init_row, test_row, inc_row;
!     int row;
! 
!     if(downward < 0) {
!       init_row = dest.end_row - 1;
!       test_row = dest.start_row - 1;
!       inc_row  = -1;
!     }
!     else {
!       init_row = dest.start_row;
!       test_row = dest.end_row;
!       inc_row  = +1;
!     }
  
!     for(row = init_row; row != test_row; row += inc_row)
!       memmove(getcell(screen, row, dest.start_col),
!             getcell(screen, row + downward, src.start_col),
!             cols * sizeof(ScreenCell));
    }
  
    return 1;
  }
--- 227,255 ----
       dest.start_row == 0 && dest.start_col == 0 &&        // starts top-left 
corner
       dest.end_col == screen->cols &&                      // full width
       screen->buffer == screen->buffers[BUFIDX_PRIMARY]) { // not altscreen
!     for(int row = 0; row < src.start_row; row++)
        sb_pushline_from_row(screen, row);
    }
  
!   int cols = src.end_col - src.start_col;
!   int downward = src.start_row - dest.start_row;
  
!   int init_row, test_row, inc_row;
!   if(downward < 0) {
!     init_row = dest.end_row - 1;
!     test_row = dest.start_row - 1;
!     inc_row  = -1;
    }
+   else {
+     init_row = dest.start_row;
+     test_row = dest.end_row;
+     inc_row  = +1;
+   }
+ 
+   for(int row = init_row; row != test_row; row += inc_row)
+     memmove(getcell(screen, row, dest.start_col),
+             getcell(screen, row + downward, src.start_col),
+             cols * sizeof(ScreenCell));
  
    return 1;
  }
***************
*** 277,288 ****
  static int erase_internal(VTermRect rect, int selective, void *user)
  {
    VTermScreen *screen = user;
-   int row, col;
  
!   for(row = rect.start_row; row < screen->state->rows && row < rect.end_row; 
row++) {
      const VTermLineInfo *info = vterm_state_get_lineinfo(screen->state, row);
  
!     for(col = rect.start_col; col < rect.end_col; col++) {
        ScreenCell *cell = getcell(screen, row, col);
  
        if (cell == NULL)
--- 275,285 ----
  static int erase_internal(VTermRect rect, int selective, void *user)
  {
    VTermScreen *screen = user;
  
!   for(int row = rect.start_row; row < screen->state->rows && row < 
rect.end_row; row++) {
      const VTermLineInfo *info = vterm_state_get_lineinfo(screen->state, row);
  
!     for(int col = rect.start_col; col < rect.end_col; col++) {
        ScreenCell *cell = getcell(screen, row, col);
  
        if (cell == NULL)
***************
*** 448,453 ****
--- 445,456 ----
    case VTERM_ATTR_BACKGROUND:
      screen->pen.bg = val->color;
      return 1;
+   case VTERM_ATTR_SMALL:
+     screen->pen.small = val->boolean;
+     return 1;
+   case VTERM_ATTR_BASELINE:
+     screen->pen.baseline = val->number;
+     return 1;
  
    case VTERM_N_ATTRS:
      return 0;
***************
*** 496,501 ****
--- 499,516 ----
    return 0;
  }
  
+ /* How many cells are non-blank
+  * Returns the position of the first blank cell in the trailing blank end */
+ static int line_popcount(ScreenCell *buffer, int row, int rows UNUSED, int 
cols)
+ {
+   int col = cols - 1;
+   while(col >= 0 && buffer[row * cols + col].chars[0] == 0)
+     col--;
+   return col + 1;
+ }
+ 
+ #define REFLOW (screen->reflow)
+ 
  static void resize_buffer(VTermScreen *screen, int bufidx, int new_rows, int 
new_cols, int active, VTermStateFields *statefields)
  {
    int old_rows = screen->rows;
***************
*** 510,542 ****
    // Find the final row of old buffer content
    int old_row = old_rows - 1;
    int new_row = new_rows - 1;
-   int col;
  
!   while(new_row >= 0 && old_row >= 0) {
!     for(col = 0; col < old_cols && col < new_cols; col++)
!       new_buffer[new_row * new_cols + col] = old_buffer[old_row * old_cols + 
col];
!     for( ; col < new_cols; col++)
!       clearcell(screen, &new_buffer[new_row * new_cols + col]);
! 
!     new_lineinfo[new_row] = old_lineinfo[old_row];
! 
!     old_row--;
!     new_row--;
! 
!     if(new_row < 0 && old_row >= 0 &&
!         new_buffer[(new_rows - 1) * new_cols].chars[0] == 0 &&
!         (!active || statefields->pos.row < (new_rows - 1))) {
!       int moverows = new_rows - 1;
!       memmove(&new_buffer[1 * new_cols], &new_buffer[0], moverows * new_cols 
* sizeof(ScreenCell));
  
!       new_row++;
      }
    }
  
    if(old_row >= 0 && bufidx == BUFIDX_PRIMARY) {
      /* Push spare lines to scrollback buffer */
!     int row;
!     for(row = 0; row <= old_row; row++)
        sb_pushline_from_row(screen, row);
      if(active)
        statefields->pos.row -= (old_row + 1);
--- 525,674 ----
    // Find the final row of old buffer content
    int old_row = old_rows - 1;
    int new_row = new_rows - 1;
  
!   VTermPos old_cursor = statefields->pos;
!   VTermPos new_cursor = { -1, -1 };
! 
! #ifdef DEBUG_REFLOW
!   fprintf(stderr, "Resizing from %dx%d to %dx%d; cursor was at (%d,%d)\n",
!       old_cols, old_rows, new_cols, new_rows, old_cursor.col, old_cursor.row);
! #endif
! 
!   /* Keep track of the final row that is knonw to be blank, so we know what
!    * spare space we have for scrolling into
!    */
!   int final_blank_row = new_rows;
! 
!   while(old_row >= 0) {
!     int old_row_end = old_row;
!     /* TODO: Stop if dwl or dhl */
!     while(REFLOW && old_lineinfo && old_row >= 0 && 
old_lineinfo[old_row].continuation)
!       old_row--;
!     int old_row_start = old_row;
! 
!     int width = 0;
!     for(int row = old_row_start; row <= old_row_end; row++) {
!       if(REFLOW && row < (old_rows - 1) && old_lineinfo[row + 1].continuation)
!         width += old_cols;
!       else
!         width += line_popcount(old_buffer, row, old_rows, old_cols);
!     }
! 
!     if(final_blank_row == (new_row + 1) && width == 0)
!       final_blank_row = new_row;
! 
!     int new_height = REFLOW
!       ? width ? (width + new_cols - 1) / new_cols : 1
!       : 1;
! 
!     int new_row_end = new_row;
!     int new_row_start = new_row - new_height + 1;
! 
!     old_row = old_row_start;
!     int old_col = 0;
! 
!     int spare_rows = new_rows - final_blank_row;
! 
!     if(new_row_start < 0 && /* we'd fall off the top */
!         spare_rows >= 0 && /* we actually have spare rows */
!         (!active || new_cursor.row == -1 || (new_cursor.row - new_row_start) 
< new_rows))
!     {
!       /* Attempt to scroll content down into the blank rows at the bottom to
!        * make it fit
!        */
!       int downwards = -new_row_start;
!       if(downwards > spare_rows)
!         downwards = spare_rows;
!       int rowcount = new_rows - downwards;
! 
! #ifdef DEBUG_REFLOW
!       fprintf(stderr, "  scroll %d rows +%d downwards\n", rowcount, 
downwards);
! #endif
! 
!       memmove(&new_buffer[downwards * new_cols], &new_buffer[0],   rowcount * 
new_cols * sizeof(ScreenCell));
!       memmove(&new_lineinfo[downwards],          &new_lineinfo[0], rowcount   
         * sizeof(new_lineinfo[0]));
! 
!       new_row += downwards;
!       new_row_start += downwards;
!       new_row_end += downwards;
! 
!       if(new_cursor.row >= 0)
!         new_cursor.row += downwards;
! 
!       final_blank_row += downwards;
!     }
! 
! #ifdef DEBUG_REFLOW
!     fprintf(stderr, "  rows [%d..%d] <- [%d..%d] width=%d\n",
!         new_row_start, new_row_end, old_row_start, old_row_end, width);
! #endif
! 
!     if(new_row_start < 0)
!       break;
! 
!     for(new_row = new_row_start, old_row = old_row_start; new_row <= 
new_row_end; new_row++) {
!       int count = width >= new_cols ? new_cols : width;
!       width -= count;
! 
!       int new_col = 0;
! 
!       while(count) {
!         /* TODO: This could surely be done a lot faster by memcpy()'ing the 
entire range */
!         new_buffer[new_row * new_cols + new_col] = old_buffer[old_row * 
old_cols + old_col];
! 
!         if(old_cursor.row == old_row && old_cursor.col == old_col)
!           new_cursor.row = new_row, new_cursor.col = new_col;
! 
!         old_col++;
!         if(old_col == old_cols) {
!           old_row++;
! 
!           if(!REFLOW) {
!             new_col++;
!             break;
!           }
!           old_col = 0;
!         }
! 
!         new_col++;
!         count--;
!       }
! 
!       if(old_cursor.row == old_row && old_cursor.col >= old_col) {
!         new_cursor.row = new_row, new_cursor.col = (old_cursor.col - old_col 
+ new_col);
!         if(new_cursor.col >= new_cols)
!           new_cursor.col = new_cols-1;
!       }
  
!       while(new_col < new_cols) {
!         clearcell(screen, &new_buffer[new_row * new_cols + new_col]);
!         new_col++;
!       }
! 
!       new_lineinfo[new_row].continuation = (new_row > new_row_start);
      }
+ 
+     old_row = old_row_start - 1;
+     new_row = new_row_start - 1;
+   }
+ 
+   if(old_cursor.row <= old_row) {
+     /* cursor would have moved entirely off the top of the screen; lets just
+      * bring it within range */
+     new_cursor.row = 0, new_cursor.col = old_cursor.col;
+     if(new_cursor.col >= new_cols)
+       new_cursor.col = new_cols-1;
+   }
+ 
+   /* We really expect the cursor position to be set by now */
+   if(active && (new_cursor.row == -1 || new_cursor.col == -1)) {
+     fprintf(stderr, "screen_resize failed to update cursor position\n");
+     abort();
    }
  
    if(old_row >= 0 && bufidx == BUFIDX_PRIMARY) {
      /* Push spare lines to scrollback buffer */
!     for(int row = 0; row <= old_row; row++)
        sb_pushline_from_row(screen, row);
      if(active)
        statefields->pos.row -= (old_row + 1);
***************
*** 553,561 ****
        for(pos.col = 0; pos.col < old_cols && pos.col < new_cols; pos.col += 
screen->sb_buffer[pos.col].width) {
          VTermScreenCell *src = &screen->sb_buffer[pos.col];
          ScreenCell *dst = &new_buffer[pos.row * new_cols + pos.col];
-       int i;
  
!         for(i = 0; i < VTERM_MAX_CHARS_PER_CELL; i++) {
            dst->chars[i] = src->chars[i];
            if(!src->chars[i])
              break;
--- 685,692 ----
        for(pos.col = 0; pos.col < old_cols && pos.col < new_cols; pos.col += 
screen->sb_buffer[pos.col].width) {
          VTermScreenCell *src = &screen->sb_buffer[pos.col];
          ScreenCell *dst = &new_buffer[pos.row * new_cols + pos.col];
  
!         for(int i = 0; i < VTERM_MAX_CHARS_PER_CELL; i++) {
            dst->chars[i] = src->chars[i];
            if(!src->chars[i])
              break;
***************
*** 569,574 ****
--- 700,707 ----
          dst->pen.conceal   = src->attrs.conceal;
          dst->pen.strike    = src->attrs.strike;
          dst->pen.font      = src->attrs.font;
+         dst->pen.small     = src->attrs.small;
+         dst->pen.baseline  = src->attrs.baseline;
  
          dst->pen.fg = src->fg;
          dst->pen.bg = src->bg;
***************
*** 584,598 ****
          statefields->pos.row++;
      }
    }
- 
    if(new_row >= 0) {
      /* Scroll new rows back up to the top and fill in blanks at the bottom */
      int moverows = new_rows - new_row - 1;
      memmove(&new_buffer[0], &new_buffer[(new_row + 1) * new_cols], moverows * 
new_cols * sizeof(ScreenCell));
      memmove(&new_lineinfo[0], &new_lineinfo[new_row + 1], moverows * 
sizeof(new_lineinfo[0]));
  
      for(new_row = moverows; new_row < new_rows; new_row++) {
!       for(col = 0; col < new_cols; col++)
          clearcell(screen, &new_buffer[new_row * new_cols + col]);
        new_lineinfo[new_row] = (VTermLineInfo){ 0 };
      }
--- 717,732 ----
          statefields->pos.row++;
      }
    }
    if(new_row >= 0) {
      /* Scroll new rows back up to the top and fill in blanks at the bottom */
      int moverows = new_rows - new_row - 1;
      memmove(&new_buffer[0], &new_buffer[(new_row + 1) * new_cols], moverows * 
new_cols * sizeof(ScreenCell));
      memmove(&new_lineinfo[0], &new_lineinfo[new_row + 1], moverows * 
sizeof(new_lineinfo[0]));
  
+     new_cursor.row -= (new_row + 1);
+ 
      for(new_row = moverows; new_row < new_rows; new_row++) {
!       for(int col = 0; col < new_cols; col++)
          clearcell(screen, &new_buffer[new_row * new_cols + col]);
        new_lineinfo[new_row] = (VTermLineInfo){ 0 };
      }
***************
*** 604,614 ****
    vterm_allocator_free(screen->vt, old_lineinfo);
    statefields->lineinfos[bufidx] = new_lineinfo;
  
!   return;
  
!   /* REFLOW TODO:
!    *   Handle delta. Probably needs to be a full cursorpos that we edit
!    */
  }
  
  static int resize(int new_rows, int new_cols, VTermStateFields *fields, void 
*user)
--- 738,747 ----
    vterm_allocator_free(screen->vt, old_lineinfo);
    statefields->lineinfos[bufidx] = new_lineinfo;
  
!   if(active)
!     statefields->pos = new_cursor;
  
!   return;
  }
  
  static int resize(int new_rows, int new_cols, VTermStateFields *fields, void 
*user)
***************
*** 667,678 ****
  static int setlineinfo(int row, const VTermLineInfo *newinfo, const 
VTermLineInfo *oldinfo, void *user)
  {
    VTermScreen *screen = user;
-   int col;
-   VTermRect rect;
  
    if(newinfo->doublewidth != oldinfo->doublewidth ||
       newinfo->doubleheight != oldinfo->doubleheight) {
!     for(col = 0; col < screen->cols; col++) {
        ScreenCell *cell = getcell(screen, row, col);
        if (cell == NULL)
        {
--- 800,809 ----
  static int setlineinfo(int row, const VTermLineInfo *newinfo, const 
VTermLineInfo *oldinfo, void *user)
  {
    VTermScreen *screen = user;
  
    if(newinfo->doublewidth != oldinfo->doublewidth ||
       newinfo->doubleheight != oldinfo->doubleheight) {
!     for(int col = 0; col < screen->cols; col++) {
        ScreenCell *cell = getcell(screen, row, col);
        if (cell == NULL)
        {
***************
*** 684,689 ****
--- 815,821 ----
        cell->pen.dhl = newinfo->doubleheight;
      }
  
+     VTermRect rect;
      rect.start_row = row;
      rect.end_row   = row + 1;
      rect.start_col = 0;
***************
*** 701,706 ****
--- 833,848 ----
    return 1;
  }
  
+ static int sb_clear(void *user) {
+   VTermScreen *screen = user;
+ 
+   if(screen->callbacks && screen->callbacks->sb_clear)
+     if((*screen->callbacks->sb_clear)(screen->cbdata))
+       return 1;
+ 
+   return 0;
+ }
+ 
  static VTermStateCallbacks state_cbs = {
    &putglyph, // putglyph
    &movecursor, // movecursor
***************
*** 712,718 ****
    &settermprop, // settermprop
    &bell, // bell
    &resize, // resize
!   &setlineinfo // setlineinfo
  };
  
  /*
--- 854,861 ----
    &settermprop, // settermprop
    &bell, // bell
    &resize, // resize
!   &setlineinfo, // setlineinfo
!   &sb_clear, //sb_clear
  };
  
  /*
***************
*** 722,735 ****
  static VTermScreen *screen_new(VTerm *vt)
  {
    VTermState *state = vterm_obtain_state(vt);
!   VTermScreen *screen;
!   int rows, cols;
! 
!   if (state == NULL)
      return NULL;
!   screen = vterm_allocator_malloc(vt, sizeof(VTermScreen));
    if (screen == NULL)
      return NULL;
  
    vterm_get_size(vt, &rows, &cols);
  
--- 865,877 ----
  static VTermScreen *screen_new(VTerm *vt)
  {
    VTermState *state = vterm_obtain_state(vt);
!   if(!state)
      return NULL;
! 
!   VTermScreen *screen = vterm_allocator_malloc(vt, sizeof(VTermScreen));
    if (screen == NULL)
      return NULL;
+   int rows, cols;
  
    vterm_get_size(vt, &rows, &cols);
  
***************
*** 743,748 ****
--- 885,893 ----
    screen->rows = rows;
    screen->cols = cols;
  
+   screen->global_reverse = FALSE;
+   screen->reflow = FALSE;
+ 
    screen->callbacks = NULL;
    screen->cbdata    = NULL;
  
***************
*** 785,791 ****
  {
    size_t outpos = 0;
    int padding = 0;
-   int row, col;
  
  #define PUT(c)                                             \
    if(utf8) {                                               \
--- 930,935 ----
***************
*** 802,811 ****
        outpos++;                                            \
    }
  
!   for(row = rect.start_row; row < rect.end_row; row++) {
!     for(col = rect.start_col; col < rect.end_col; col++) {
        ScreenCell *cell = getcell(screen, row, col);
-       int i;
  
        if (cell == NULL)
        {
--- 946,954 ----
        outpos++;                                            \
    }
  
!   for(int row = rect.start_row; row < rect.end_row; row++) {
!     for(int col = rect.start_col; col < rect.end_col; col++) {
        ScreenCell *cell = getcell(screen, row, col);
  
        if (cell == NULL)
        {
***************
*** 824,830 ****
            PUT(UNICODE_SPACE);
            padding--;
          }
!         for(i = 0; i < VTERM_MAX_CHARS_PER_CELL && cell->chars[i]; i++) {
            PUT(cell->chars[i]);
          }
        }
--- 967,973 ----
            PUT(UNICODE_SPACE);
            padding--;
          }
!         for(int i = 0; i < VTERM_MAX_CHARS_PER_CELL && cell->chars[i]; i++) {
            PUT(cell->chars[i]);
          }
        }
***************
*** 853,864 ****
  int vterm_screen_get_cell(const VTermScreen *screen, VTermPos pos, 
VTermScreenCell *cell)
  {
    ScreenCell *intcell = getcell(screen, pos.row, pos.col);
-   int i;
  
    if(!intcell)
      return 0;
  
!   for(i = 0; i < VTERM_MAX_CHARS_PER_CELL; i++) {
      cell->chars[i] = intcell->chars[i];
      if(!intcell->chars[i])
        break;
--- 996,1006 ----
  int vterm_screen_get_cell(const VTermScreen *screen, VTermPos pos, 
VTermScreenCell *cell)
  {
    ScreenCell *intcell = getcell(screen, pos.row, pos.col);
  
    if(!intcell)
      return 0;
  
!   for(int i = 0; i < VTERM_MAX_CHARS_PER_CELL; i++) {
      cell->chars[i] = intcell->chars[i];
      if(!intcell->chars[i])
        break;
***************
*** 872,877 ****
--- 1014,1021 ----
    cell->attrs.conceal   = intcell->pen.conceal;
    cell->attrs.strike    = intcell->pen.strike;
    cell->attrs.font      = intcell->pen.font;
+   cell->attrs.small     = intcell->pen.small;
+   cell->attrs.baseline  = intcell->pen.baseline;
  
    cell->attrs.dwl = intcell->pen.dwl;
    cell->attrs.dhl = intcell->pen.dhl;
***************
*** 919,929 ****
  
  VTermScreen *vterm_obtain_screen(VTerm *vt)
  {
!   if(!vt->screen)
!     vt->screen = screen_new(vt);
    return vt->screen;
  }
  
  void vterm_screen_enable_altscreen(VTermScreen *screen, int altscreen)
  {
    if(!screen->buffers[BUFIDX_ALTSCREEN] && altscreen) {
--- 1063,1087 ----
  
  VTermScreen *vterm_obtain_screen(VTerm *vt)
  {
!   if(vt->screen)
!     return vt->screen;
! 
!   vt->screen = screen_new(vt);
    return vt->screen;
  }
  
+ void vterm_screen_enable_reflow(VTermScreen *screen, int reflow)
+ {
+   screen->reflow = reflow;
+ }
+ 
+ // Removed, causes a compiler warning and isn't used
+ // #undef vterm_screen_set_reflow
+ // void vterm_screen_set_reflow(VTermScreen *screen, int reflow)
+ // {
+ //   vterm_screen_enable_reflow(screen, reflow);
+ // }
+ 
  void vterm_screen_enable_altscreen(VTermScreen *screen, int altscreen)
  {
    if(!screen->buffers[BUFIDX_ALTSCREEN] && altscreen) {
***************
*** 1000,1013 ****
      return 1;
    if((attrs & VTERM_ATTR_BACKGROUND_MASK) && 
!vterm_color_is_equal(&a->pen.bg, &b->pen.bg))
      return 1;
  
    return 0;
  }
  
  int vterm_screen_get_attrs_extent(const VTermScreen *screen, VTermRect 
*extent, VTermPos pos, VTermAttrMask attrs)
  {
-   int col;
- 
    ScreenCell *target = getcell(screen, pos.row, pos.col);
  
    // TODO: bounds check
--- 1158,1173 ----
      return 1;
    if((attrs & VTERM_ATTR_BACKGROUND_MASK) && 
!vterm_color_is_equal(&a->pen.bg, &b->pen.bg))
      return 1;
+   if((attrs & VTERM_ATTR_SMALL_MASK)    && (a->pen.small != b->pen.small))
+     return 1;
+   if((attrs & VTERM_ATTR_BASELINE_MASK)    && (a->pen.baseline != 
b->pen.baseline))
+     return 1;
  
    return 0;
  }
  
  int vterm_screen_get_attrs_extent(const VTermScreen *screen, VTermRect 
*extent, VTermPos pos, VTermAttrMask attrs)
  {
    ScreenCell *target = getcell(screen, pos.row, pos.col);
  
    // TODO: bounds check
***************
*** 1019,1024 ****
--- 1179,1186 ----
    if(extent->end_col < 0)
      extent->end_col = screen->cols;
  
+   int col;
+ 
    for(col = pos.col - 1; col >= extent->start_col; col--)
      if(attrs_differ(attrs, target, getcell(screen, pos.row, col)))
        break;
*** ../vim-9.0.0773/src/libvterm/src/state.c    2022-10-16 14:35:41.840813752 
+0100
--- src/libvterm/src/state.c    2022-10-16 19:07:43.515621165 +0100
***************
*** 387,395 ****
        }
  #endif
        if (i == glyph_starts || this_width > width)
!       width = this_width;
      }
  
      chars[glyph_ends - glyph_starts] = 0;
      i--;
  
--- 387,398 ----
        }
  #endif
        if (i == glyph_starts || this_width > width)
!       width = this_width;  // TODO: should be += ?
      }
  
+     while(i < npoints && vterm_unicode_is_combining(codepoints[i]))
+       i++;
+ 
      chars[glyph_ends - glyph_starts] = 0;
      i--;
  
***************
*** 1149,1154 ****
--- 1152,1163 ----
        set_lineinfo(state, row, FORCE, DWL_OFF, DHL_OFF);
        erase(state, rect, selective);
        break;
+ 
+     case 3:
+       if(state->callbacks && state->callbacks->sb_clear)
+         if((*state->callbacks->sb_clear)(state->cbdata))
+           return 1;
+       break;
      }
      break;
  
***************
*** 1391,1396 ****
--- 1400,1428 ----
      vterm_state_setpen(state, args, argcount);
      break;
  
+   case LEADER('?', 0x6d): // DECSGR
+     /* No actual DEC terminal recognised these, but some printers did. These
+      * are alternative ways to request subscript/superscript/off
+      */
+     for(int argi = 0; argi < argcount; argi++) {
+       long arg;
+       switch(arg = CSI_ARG(args[argi])) {
+         case 4: // Superscript on
+           arg = 73;
+           vterm_state_setpen(state, &arg, 1);
+           break;
+         case 5: // Subscript on
+           arg = 74;
+           vterm_state_setpen(state, &arg, 1);
+           break;
+         case 24: // Super+subscript off
+           arg = 75;
+           vterm_state_setpen(state, &arg, 1);
+           break;
+       }
+     }
+     break;
+ 
    case LEADER('>', 0x6d): // xterm resource modifyOtherKeys
      if (argcount == 2 && args[0] == 4)
        state->mode.modify_other_keys = args[1] == 2;
***************
*** 1857,1867 ****
    VTerm *vt = state->vt;
  
    char *tmp = state->tmp.decrqss;
-   size_t i = 0;
  
    if(frag.initial)
      tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
  
    while(i < sizeof(state->tmp.decrqss)-1 && tmp[i])
      i++;
    while(i < sizeof(state->tmp.decrqss)-1 && frag.len--)
--- 1889,1899 ----
    VTerm *vt = state->vt;
  
    char *tmp = state->tmp.decrqss;
  
    if(frag.initial)
      tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
  
+   size_t i = 0;
    while(i < sizeof(state->tmp.decrqss)-1 && tmp[i])
      i++;
    while(i < sizeof(state->tmp.decrqss)-1 && frag.len--)
***************
*** 1877,1890 ****
        long args[20];
        int argc = vterm_state_getpen(state, args, 
sizeof(args)/sizeof(args[0]));
        size_t cur = 0;
-       int argi;
  
        cur += SNPRINTF(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur,
            vt->mode.ctrl8bit ? "\x90" "1$r" : ESC_S "P" "1$r"); // DCS 1$r ...
        if(cur >= vt->tmpbuffer_len)
          return;
  
!       for(argi = 0; argi < argc; argi++) {
          cur += SNPRINTF(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur,
              argi == argc - 1             ? "%ld" :
              CSI_ARG_HAS_MORE(args[argi]) ? "%ld:" :
--- 1909,1921 ----
        long args[20];
        int argc = vterm_state_getpen(state, args, 
sizeof(args)/sizeof(args[0]));
        size_t cur = 0;
  
        cur += SNPRINTF(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur,
            vt->mode.ctrl8bit ? "\x90" "1$r" : ESC_S "P" "1$r"); // DCS 1$r ...
        if(cur >= vt->tmpbuffer_len)
          return;
  
!       for(int argi = 0; argi < argc; argi++) {
          cur += SNPRINTF(vt->tmpbuffer + cur, vt->tmpbuffer_len - cur,
              argi == argc - 1             ? "%ld" :
              CSI_ARG_HAS_MORE(args[argi]) ? "%ld:" :
***************
*** 1996,2010 ****
  {
    VTermState *state = user;
    VTermPos oldpos = state->pos;
-   VTermStateFields fields;
  
    if(cols != state->cols) {
-     int col;
      unsigned char *newtabstops = vterm_allocator_malloc(state->vt, (cols + 7) 
/ 8);
      if (newtabstops == NULL)
        return 0;
  
      /* TODO: This can all be done much more efficiently bytewise */
      for(col = 0; col < state->cols && col < cols; col++) {
        unsigned char mask = 1 << (col & 7);
        if(state->tabstops[col >> 3] & mask)
--- 2027,2040 ----
  {
    VTermState *state = user;
    VTermPos oldpos = state->pos;
  
    if(cols != state->cols) {
      unsigned char *newtabstops = vterm_allocator_malloc(state->vt, (cols + 7) 
/ 8);
      if (newtabstops == NULL)
        return 0;
  
      /* TODO: This can all be done much more efficiently bytewise */
+     int col;
      for(col = 0; col < state->cols && col < cols; col++) {
        unsigned char mask = 1 << (col & 7);
        if(state->tabstops[col >> 3] & mask)
***************
*** 2033,2045 ****
    if(state->scrollregion_right > -1)
      UBOUND(state->scrollregion_right, state->cols);
  
    fields.pos = state->pos;
    fields.lineinfos[0] = state->lineinfos[0];
    fields.lineinfos[1] = state->lineinfos[1];
  
    if(state->callbacks && state->callbacks->resize) {
      (*state->callbacks->resize)(rows, cols, &fields, state->cbdata);
- 
      state->pos = fields.pos;
  
      state->lineinfos[0] = fields.lineinfos[0];
--- 2063,2075 ----
    if(state->scrollregion_right > -1)
      UBOUND(state->scrollregion_right, state->cols);
  
+   VTermStateFields fields;
    fields.pos = state->pos;
    fields.lineinfos[0] = state->lineinfos[0];
    fields.lineinfos[1] = state->lineinfos[1];
  
    if(state->callbacks && state->callbacks->resize) {
      (*state->callbacks->resize)(rows, cols, &fields, state->cbdata);
      state->pos = fields.pos;
  
      state->lineinfos[0] = fields.lineinfos[0];
***************
*** 2111,2121 ****
   */
  VTermState *vterm_obtain_state(VTerm *vt)
  {
-   VTermState *state;
    if(vt->state)
      return vt->state;
  
!   state = vterm_state_new(vt);
    if (state == NULL)
      return NULL;
    vt->state = state;
--- 2141,2150 ----
   */
  VTermState *vterm_obtain_state(VTerm *vt)
  {
    if(vt->state)
      return vt->state;
  
!   VTermState *state = vterm_state_new(vt);
    if (state == NULL)
      return NULL;
    vt->state = state;
***************
*** 2127,2134 ****
  
  void vterm_state_reset(VTermState *state, int hard)
  {
-   VTermEncoding *default_enc;
- 
    state->scrollregion_top = 0;
    state->scrollregion_bottom = -1;
    state->scrollregion_left = 0;
--- 2156,2161 ----
***************
*** 2149,2185 ****
  
    state->vt->mode.ctrl8bit   = 0;
  
!   {
!     int col;
!     for(col = 0; col < state->cols; col++)
!       if(col % 8 == 0)
!       set_col_tabstop(state, col);
!       else
!       clear_col_tabstop(state, col);
!   }
  
!   {
!     int row;
!     for(row = 0; row < state->rows; row++)
!       set_lineinfo(state, row, FORCE, DWL_OFF, DHL_OFF);
!   }
  
    if(state->callbacks && state->callbacks->initpen)
      (*state->callbacks->initpen)(state->cbdata);
  
    vterm_state_resetpen(state);
  
!   default_enc = state->vt->mode.utf8 ?
        vterm_lookup_encoding(ENC_UTF8,      'u') :
        vterm_lookup_encoding(ENC_SINGLE_94, 'B');
  
!   {
!     int i;
!     for(i = 0; i < 4; i++) {
!       state->encoding[i].enc = default_enc;
!       if(default_enc->init)
!       (*default_enc->init)(default_enc, state->encoding[i].data);
!     }
    }
  
    state->gl_set = 0;
--- 2176,2203 ----
  
    state->vt->mode.ctrl8bit   = 0;
  
!   for(int col = 0; col < state->cols; col++)
!     if(col % 8 == 0)
!       set_col_tabstop(state, col);
!     else
!       clear_col_tabstop(state, col);
  
!   for(int row = 0; row < state->rows; row++)
!     set_lineinfo(state, row, FORCE, DWL_OFF, DHL_OFF);
  
    if(state->callbacks && state->callbacks->initpen)
      (*state->callbacks->initpen)(state->cbdata);
  
    vterm_state_resetpen(state);
  
!   VTermEncoding *default_enc = state->vt->mode.utf8 ?
        vterm_lookup_encoding(ENC_UTF8,      'u') :
        vterm_lookup_encoding(ENC_SINGLE_94, 'B');
  
!   for(int i = 0; i < 4; i++) {
!     state->encoding[i].enc = default_enc;
!     if(default_enc->init)
!       (*default_enc->init)(default_enc, state->encoding[i].data);
    }
  
    state->gl_set = 0;
***************
*** 2194,2205 ****
    settermprop_int (state, VTERM_PROP_CURSORSHAPE,   
VTERM_PROP_CURSORSHAPE_BLOCK);
  
    if(hard) {
-     VTermRect rect = { 0, 0, 0, 0 };
- 
      state->pos.row = 0;
      state->pos.col = 0;
      state->at_phantom = 0;
  
      rect.end_row = state->rows;
      rect.end_col =  state->cols;
      erase(state, rect, 0);
--- 2212,2222 ----
    settermprop_int (state, VTERM_PROP_CURSORSHAPE,   
VTERM_PROP_CURSORSHAPE_BLOCK);
  
    if(hard) {
      state->pos.row = 0;
      state->pos.col = 0;
      state->at_phantom = 0;
  
+     VTermRect rect = { 0, 0, 0, 0 };
      rect.end_row = state->rows;
      rect.end_col =  state->cols;
      erase(state, rect, 0);
*** ../vim-9.0.0773/src/libvterm/src/unicode.c  2020-05-22 20:50:28.000000000 
+0100
--- src/libvterm/src/unicode.c  2022-10-16 18:12:20.047158323 +0100
***************
*** 452,471 ****
  }
  #endif
  
! #if 0 // unused
! static int mk_wcswidth(const uint32_t *pwcs, size_t n)
! {
!   int w, width = 0;
! 
!   for (;*pwcs && n-- > 0; pwcs++)
!     if ((w = mk_wcwidth(*pwcs)) < 0)
!       return -1;
!     else
!       width += w;
! 
!   return width;
! }
  
  
  /*
   * The following functions are the same as mk_wcwidth() and
--- 452,515 ----
  }
  #endif
  
! /* sorted list of non-overlapping intervals of East Asian Ambiguous
! * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
! static const struct interval ambiguous[] = {
! { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
! { 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
! { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
! { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
! { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
! { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
! { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
! { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
! { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
! { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
! { 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
! { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
! { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
! { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
! { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
! { 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
! { 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
! { 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
! { 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
! { 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
! { 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
! { 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
! { 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
! { 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
! { 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
! { 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
! { 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
! { 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
! { 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
! { 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
! { 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
! { 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
! { 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
! { 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
! { 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
! { 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
! { 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
! { 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
! { 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
! { 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
! { 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
! { 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
! { 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
! { 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
! { 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
! { 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
! { 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
! { 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
! { 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
! { 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
! { 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
! { 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
! };
  
+ #ifdef USE_MK_WCWIDTH_CJK
  
  /*
   * The following functions are the same as mk_wcwidth() and
***************
*** 478,542 ****
   */
  static int mk_wcwidth_cjk(uint32_t ucs)
  {
- #endif
-   /* sorted list of non-overlapping intervals of East Asian Ambiguous
-    * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
-   static const struct interval ambiguous[] = {
-     { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
-     { 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
-     { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
-     { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
-     { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
-     { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
-     { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
-     { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
-     { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
-     { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
-     { 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
-     { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
-     { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
-     { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
-     { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
-     { 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
-     { 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
-     { 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
-     { 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
-     { 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
-     { 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
-     { 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
-     { 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
-     { 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
-     { 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
-     { 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
-     { 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
-     { 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
-     { 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
-     { 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
-     { 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
-     { 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
-     { 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
-     { 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
-     { 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
-     { 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
-     { 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
-     { 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
-     { 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
-     { 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
-     { 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
-     { 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
-     { 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
-     { 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
-     { 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
-     { 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
-     { 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
-     { 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
-     { 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
-     { 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
-     { 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
-     { 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
-   };
- #if 0
- 
    /* binary search in table of non-spacing characters */
    if (bisearch(ucs, ambiguous,
                 sizeof(ambiguous) / sizeof(struct interval) - 1))
--- 522,527 ----
***************
*** 545,563 ****
    return mk_wcwidth(ucs);
  }
  
- 
- static int mk_wcswidth_cjk(const uint32_t *pwcs, size_t n)
- {
-   int w, width = 0;
- 
-   for (;*pwcs && n-- > 0; pwcs++)
-     if ((w = mk_wcwidth_cjk(*pwcs)) < 0)
-       return -1;
-     else
-       width += w;
- 
-   return width;
- }
  #endif
  
  INTERNAL int vterm_unicode_is_ambiguous(uint32_t codepoint)
--- 530,535 ----
*** ../vim-9.0.0773/src/libvterm/src/vterm.c    2022-10-16 14:35:41.840813752 
+0100
--- src/libvterm/src/vterm.c    2022-10-16 19:14:38.139885762 +0100
***************
*** 134,139 ****
--- 134,142 ----
  
  void vterm_set_size(VTerm *vt, int rows, int cols)
  {
+   if(rows < 1 || cols < 1)
+     return;
+ 
    vt->rows = rows;
    vt->cols = cols;
  
***************
*** 201,207 ****
  INTERNAL void vterm_push_output_sprintf_ctrl(VTerm *vt, unsigned char ctrl, 
const char *fmt, ...)
  {
    size_t cur;
-   va_list args;
  
    if(ctrl >= 0x80 && !vt->mode.ctrl8bit)
      cur = SNPRINTF(vt->tmpbuffer, vt->tmpbuffer_len,
--- 204,209 ----
***************
*** 213,218 ****
--- 215,221 ----
      return;
    vterm_push_output_bytes(vt, vt->tmpbuffer, cur);
  
+   va_list args;
    va_start(args, fmt);
    vterm_push_output_vsprintf(vt, fmt, args);
    va_end(args);
***************
*** 221,227 ****
  INTERNAL void vterm_push_output_sprintf_str(VTerm *vt, unsigned char ctrl, 
int term, const char *fmt, ...)
  {
    size_t cur;
-   va_list args;
  
    if(ctrl) {
      if(ctrl >= 0x80 && !vt->mode.ctrl8bit)
--- 224,229 ----
***************
*** 236,241 ****
--- 238,244 ----
      vterm_push_output_bytes(vt, vt->tmpbuffer, cur);
    }
  
+   va_list args;
    va_start(args, fmt);
    vterm_push_output_vsprintf(vt, fmt, args);
    va_end(args);
***************
*** 292,297 ****
--- 295,302 ----
      case VTERM_ATTR_FONT:       return VTERM_VALUETYPE_INT;
      case VTERM_ATTR_FOREGROUND: return VTERM_VALUETYPE_COLOR;
      case VTERM_ATTR_BACKGROUND: return VTERM_VALUETYPE_COLOR;
+     case VTERM_ATTR_SMALL:      return VTERM_VALUETYPE_BOOL;
+     case VTERM_ATTR_BASELINE:   return VTERM_VALUETYPE_INT;
  
      case VTERM_N_ATTRS: return 0;
    }
***************
*** 396,403 ****
    int init_row, test_row, init_col, test_col;
    int inc_row, inc_col;
  
-   VTermPos pos;
- 
    if(downward < 0) {
      init_row = dest.end_row - 1;
      test_row = dest.start_row - 1;
--- 401,406 ----
***************
*** 420,425 ****
--- 423,429 ----
      inc_col = +1;
    }
  
+   VTermPos pos;
    for(pos.row = init_row; pos.row != test_row; pos.row += inc_row)
      for(pos.col = init_col; pos.col != test_col; pos.col += inc_col) {
        VTermPos srcpos;
*** ../vim-9.0.0773/src/libvterm/src/vterm_internal.h   2022-10-16 
14:35:41.840813752 +0100
--- src/libvterm/src/vterm_internal.h   2022-10-16 16:56:13.194822674 +0100
***************
*** 60,65 ****
--- 60,67 ----
    unsigned int conceal:1;
    unsigned int strike:1;
    unsigned int font:4; /* To store 0-9 */
+   unsigned int small:1;
+   unsigned int baseline:2;
  };
  
  struct VTermState
*** ../vim-9.0.0773/src/libvterm/t/harness.c    2022-10-16 14:35:41.840813752 
+0100
--- src/libvterm/t/harness.c    2022-10-16 18:00:30.459392805 +0100
***************
*** 1,6 ****
--- 1,7 ----
  #include "vterm.h"
  #include "../src/vterm_internal.h" // We pull in some internal bits too
  
+ #include <assert.h>
  #include <stdio.h>
  #include <string.h>
  
***************
*** 409,414 ****
--- 410,417 ----
    int conceal;
    int strike;
    int font;
+   int small;
+   int baseline;
    VTermColor foreground;
    VTermColor background;
  } state_pen;
***************
*** 439,444 ****
--- 442,453 ----
    case VTERM_ATTR_FONT:
      state_pen.font = val->number;
      break;
+   case VTERM_ATTR_SMALL:
+     state_pen.small = val->boolean;
+     break;
+   case VTERM_ATTR_BASELINE:
+     state_pen.baseline = val->number;
+     break;
    case VTERM_ATTR_FOREGROUND:
      state_pen.foreground = val->color;
      break;
***************
*** 458,463 ****
--- 467,481 ----
    return 1;
  }
  
+ static int want_state_scrollback = 0;
+ static int state_sb_clear(void *user UNUSED) {
+   if(!want_state_scrollback)
+     return 1;
+ 
+   printf("sb_clear\n");
+   return 0;
+ }
+ 
  VTermStateCallbacks state_cbs = {
    state_putglyph, // putglyph
    movecursor, // movecursor
***************
*** 470,475 ****
--- 488,494 ----
    NULL, // bell
    NULL, // resize
    state_setlineinfo, // setlineinfo
+   state_sb_clear, // sb_clear
  };
  
  static int selection_set(VTermSelectionMask mask, VTermStringFragment frag, 
void *user UNUSED)
***************
*** 592,597 ****
--- 611,625 ----
    return 1;
  }
  
+ static int screen_sb_clear(void *user UNUSED)
+ {
+   if(!want_screen_scrollback)
+     return 1;
+ 
+   printf("sb_clear\n");
+   return 0;
+ }
+ 
  VTermScreenCallbacks screen_cbs = {
    screen_damage, // damage
    moverect, // moverect
***************
*** 600,606 ****
    NULL, // bell
    NULL, // resize
    screen_sb_pushline, // sb_pushline
!   screen_sb_popline // sb_popline
  };
  
  int main(int argc UNUSED, char **argv UNUSED)
--- 628,635 ----
    NULL, // bell
    NULL, // resize
    screen_sb_pushline, // sb_pushline
!   screen_sb_popline, // sb_popline
!   screen_sb_clear, // sb_clear
  };
  
  int main(int argc UNUSED, char **argv UNUSED)
***************
*** 629,640 ****
--- 658,671 ----
      }
  
      else if(streq(line, "WANTPARSER")) {
+       assert(vt);
        vterm_parser_set_callbacks(vt, &parser_cbs, NULL);
      }
  
      else if(strstartswith(line, "WANTSTATE") && (line[9] == '\0' || line[9] 
== ' ')) {
        int i = 9;
        int sense = 1;
+       assert(vt);
        if(!state) {
          state = vterm_obtain_state(vt);
          vterm_state_set_callbacks(state, &state_cbs, NULL);
***************
*** 671,676 ****
--- 702,710 ----
          case 'f':
            vterm_state_set_unrecognised_fallbacks(state, sense ? &fallbacks : 
NULL, NULL);
            break;
+         case 'b':
+           want_state_scrollback = sense;
+           break;
          default:
            fprintf(stderr, "Unrecognised WANTSTATE flag '%c'\n", line[i]);
          }
***************
*** 679,684 ****
--- 713,719 ----
      else if(strstartswith(line, "WANTSCREEN") && (line[10] == '\0' || 
line[10] == ' ')) {
        int i = 10;
        int sense = 1;
+       assert(vt);
        if(!screen)
          screen = vterm_obtain_screen(vt);
        vterm_screen_set_callbacks(screen, &screen_cbs, NULL);
***************
*** 712,717 ****
--- 747,755 ----
          case 'b':
            want_screen_scrollback = sense;
            break;
+         case 'r':
+           vterm_screen_enable_reflow(screen, sense);
+           break;
          default:
            fprintf(stderr, "Unrecognised WANTSCREEN flag '%c'\n", line[i]);
          }
***************
*** 743,748 ****
--- 781,788 ----
      else if(strstartswith(line, "PUSH ")) {
        char *bytes = line + 5;
        size_t len = inplace_hex2bytes(bytes);
+       assert(len);
+ 
        size_t written = vterm_input_write(vt, bytes, len);
        if(written < len)
          fprintf(stderr, "! short write\n");
***************
*** 759,764 ****
--- 799,805 ----
      else if(strstartswith(line, "ENCIN ")) {
        char *bytes = line + 6;
        size_t len = inplace_hex2bytes(bytes);
+       assert(len);
  
        uint32_t cp[1024];
        int cpi = 0;
***************
*** 814,819 ****
--- 855,861 ----
      }
  
      else if(strstartswith(line, "FOCUS ")) {
+       assert(state);
        char *linep = line + 6;
        if(streq(linep, "IN"))
          vterm_state_focus_in(state);
***************
*** 869,874 ****
--- 911,918 ----
        }
        frag.len = inplace_hex2bytes(linep);
        frag.str = linep;
+       assert(frag.len);
+ 
        linep += frag.len * 2;
        while(linep[0] == ' ')
          linep++;
***************
*** 879,884 ****
--- 923,929 ----
      }
  
      else if(strstartswith(line, "DAMAGEMERGE ")) {
+       assert(screen);
        char *linep = line + 12;
        while(linep[0] == ' ')
          linep++;
***************
*** 893,903 ****
--- 938,950 ----
      }
  
      else if(strstartswith(line, "DAMAGEFLUSH")) {
+       assert(screen);
        vterm_screen_flush_damage(screen);
      }
  
      else if(line[0] == '?') {
        if(streq(line, "?cursor")) {
+         assert(state);
          VTermPos pos;
          vterm_state_get_cursorpos(state, &pos);
          if(pos.row != state_pos.row)
***************
*** 910,915 ****
--- 957,963 ----
            printf("%d,%d\n", state_pos.row, state_pos.col);
        }
        else if(strstartswith(line, "?pen ")) {
+         assert(state);
          VTermValue val;
          char *linep = line + 5;
          while(linep[0] == ' ')
***************
*** 965,970 ****
--- 1013,1036 ----
            else
              printf("%d\n", state_pen.font);
          }
+         else if(streq(linep, "small")) {
+           vterm_state_get_penattr(state, VTERM_ATTR_SMALL, &val);
+           if(val.boolean != state_pen.small)
+             printf("! pen small mismatch; state=%s, event=%s\n",
+                 BOOLSTR(val.boolean), BOOLSTR(state_pen.small));
+           else
+             printf("%s\n", BOOLSTR(state_pen.small));
+         }
+         else if(streq(linep, "baseline")) {
+           vterm_state_get_penattr(state, VTERM_ATTR_BASELINE, &val);
+           if(val.number != state_pen.baseline)
+             printf("! pen baseline mismatch: state=%d, event=%d\n",
+                 val.number, state_pen.baseline);
+           else
+             printf("%s\n", state_pen.baseline == VTERM_BASELINE_RAISE ? 
"raise"
+                          : state_pen.baseline == VTERM_BASELINE_LOWER ? 
"lower"
+                          : "normal");
+         }
          else if(streq(linep, "foreground")) {
            print_color(&state_pen.foreground);
            printf("\n");
***************
*** 977,982 ****
--- 1043,1049 ----
            printf("?\n");
        }
        else if(strstartswith(line, "?lineinfo ")) {
+         assert(state);
          char *linep = line + 10;
          int row;
          const VTermLineInfo *info;
***************
*** 996,1001 ****
--- 1063,1069 ----
          printf("\n");
        }
        else if(strstartswith(line, "?screen_chars ")) {
+         assert(screen);
          char *linep = line + 13;
          VTermRect rect;
          size_t len;
***************
*** 1028,1033 ****
--- 1096,1102 ----
          }
        }
        else if(strstartswith(line, "?screen_text ")) {
+         assert(screen);
          char *linep = line + 12;
          VTermRect rect;
          size_t len;
***************
*** 1067,1072 ****
--- 1136,1142 ----
          }
        }
        else if(strstartswith(line, "?screen_cell ")) {
+         assert(screen);
          char *linep = line + 12;
        int i;
          VTermPos pos;
***************
*** 1090,1095 ****
--- 1160,1169 ----
          if(cell.attrs.blink)     printf("K");
          if(cell.attrs.reverse)   printf("R");
          if(cell.attrs.font)      printf("F%d", cell.attrs.font);
+         if(cell.attrs.small)     printf("S");
+         if(cell.attrs.baseline)  printf(
+             cell.attrs.baseline == VTERM_BASELINE_RAISE ? "^" :
+                                                           "_");
          printf("} ");
          if(cell.attrs.dwl)       printf("dwl ");
          if(cell.attrs.dhl)       printf("dhl-%s ", cell.attrs.dhl == 2 ? 
"bottom" : "top");
***************
*** 1102,1107 ****
--- 1176,1182 ----
          printf("\n");
        }
        else if(strstartswith(line, "?screen_eol ")) {
+         assert(screen);
          VTermPos pos;
          char *linep = line + 12;
          while(linep[0] == ' ')
***************
*** 1113,1118 ****
--- 1188,1194 ----
          printf("%d\n", vterm_screen_is_eol(screen, pos));
        }
        else if(strstartswith(line, "?screen_attrs_extent ")) {
+         assert(screen);
          VTermPos pos;
          VTermRect rect;
          char *linep = line + 21;
*** ../vim-9.0.0773/src/libvterm/t/10state_putglyph.test        2020-05-17 
14:50:36.000000000 +0100
--- src/libvterm/t/10state_putglyph.test        2022-10-16 17:43:03.887560542 
+0100
***************
*** 52,57 ****
--- 52,63 ----
    putglyph 0x65,0x301 1 0,0
    putglyph 0x5a 1 0,1
  
+ !Spare combining chars get truncated
+ RESET
+ PUSH "e" . "\xCC\x81" x 10
+   putglyph 0x65,0x301,0x301,0x301,0x301,0x301 1 0,0
+   # and nothing more
+ 
  RESET
  PUSH "e"
    putglyph 0x65 1 0,0
*** ../vim-9.0.0773/src/libvterm/t/13state_edit.test    2017-06-24 
15:44:02.000000000 +0100
--- src/libvterm/t/13state_edit.test    2022-10-16 16:31:27.283019951 +0100
***************
*** 1,6 ****
  INIT
  UTF8 1
! WANTSTATE se
  
  !ICH
  RESET
--- 1,6 ----
  INIT
  UTF8 1
! WANTSTATE seb
  
  !ICH
  RESET
***************
*** 242,247 ****
--- 242,251 ----
    erase 0..25,0..80
    ?cursor = 1,1
  
+ !ED 3
+ PUSH "\e[3J"
+   sb_clear
+ 
  !SED
  RESET
    erase 0..25,0..80
*** ../vim-9.0.0773/src/libvterm/t/26state_query.test   2022-10-16 
14:35:41.844813763 +0100
--- src/libvterm/t/26state_query.test   2022-10-16 17:56:08.831385596 +0100
***************
*** 9,15 ****
  !XTVERSION
  RESET
  PUSH "\e[>q"
!   output "\eP>|libvterm(0.2)\e\\"
  
  !DSR
  RESET
--- 9,15 ----
  !XTVERSION
  RESET
  PUSH "\e[>q"
!   output "\eP>|libvterm(0.3)\e\\"
  
  !DSR
  RESET
*** ../vim-9.0.0773/src/libvterm/t/30state_pen.test     2020-05-20 
19:47:52.000000000 +0100
--- src/libvterm/t/30state_pen.test     2022-10-16 16:56:46.410816452 +0100
***************
*** 112,114 ****
--- 112,125 ----
  PUSH "\e[m\e[37;1m"
    ?pen bold = on
    ?pen foreground = idx(15)
+ 
+ !Super/Subscript
+ PUSH "\e[73m"
+   ?pen small = on
+   ?pen baseline = raise
+ PUSH "\e[74m"
+   ?pen small = on
+   ?pen baseline = lower
+ PUSH "\e[75m"
+   ?pen small = off
+   ?pen baseline = normal
*** ../vim-9.0.0773/src/libvterm/t/64screen_pen.test    2020-05-21 
18:36:24.000000000 +0100
--- src/libvterm/t/64screen_pen.test    2022-10-16 16:47:29.926848023 +0100
***************
*** 35,40 ****
--- 35,46 ----
  PUSH "\e[42mH\e[m"
    ?screen_cell 0,7 = {0x48} width=1 attrs={} fg=rgb(240,240,240) bg=idx(2)
  
+ !Super/subscript
+ PUSH "x\e[74m0\e[73m2\e[m"
+   ?screen_cell 0,8  = {0x78} width=1 attrs={} fg=rgb(240,240,240) 
bg=rgb(0,0,0)
+   ?screen_cell 0,9  = {0x30} width=1 attrs={S_} fg=rgb(240,240,240) 
bg=rgb(0,0,0)
+   ?screen_cell 0,10 = {0x32} width=1 attrs={S^} fg=rgb(240,240,240) 
bg=rgb(0,0,0)
+ 
  !EL sets reverse and colours to end of line
  PUSH "\e[H\e[7;33;44m\e[K"
    ?screen_cell 0,0  = {} width=1 attrs={R} fg=idx(3) bg=idx(4)
*** ../vim-9.0.0773/src/libvterm/t/69screen_reflow.test 2022-10-16 
19:25:58.364308066 +0100
--- src/libvterm/t/69screen_reflow.test 2022-10-16 17:49:57.943197373 +0100
***************
*** 0 ****
--- 1,79 ----
+ INIT
+ # Run these tests on a much smaller default screen, so debug output is
+ # nowhere near as noisy
+ RESIZE 5,10
+ WANTSTATE
+ WANTSCREEN r
+ RESET
+ 
+ !Resize wider reflows wide lines
+ RESET
+ PUSH "A"x12
+   ?screen_row 0 = "AAAAAAAAAA"
+   ?screen_row 1 = "AA"
+   ?lineinfo 1 = cont
+   ?cursor = 1,2
+ RESIZE 5,15
+   ?screen_row 0 = "AAAAAAAAAAAA"
+   ?screen_row 1 = 
+   ?lineinfo 1 =
+   ?cursor = 0,12
+ RESIZE 5,20
+   ?screen_row 0 = "AAAAAAAAAAAA"
+   ?screen_row 1 = 
+   ?lineinfo 1 =
+   ?cursor = 0,12
+ 
+ !Resize narrower can create continuation lines
+ RESET
+ RESIZE 5,10
+ PUSH "ABCDEFGHI"
+   ?screen_row 0 = "ABCDEFGHI"
+   ?screen_row 1 = ""
+   ?lineinfo 1 =
+   ?cursor = 0,9
+ RESIZE 5,8
+   ?screen_row 0 = "ABCDEFGH"
+   ?screen_row 1 = "I"
+   ?lineinfo 1 = cont
+   ?cursor = 1,1
+ RESIZE 5,6
+   ?screen_row 0 = "ABCDEF"
+   ?screen_row 1 = "GHI"
+   ?lineinfo 1 = cont
+   ?cursor = 1,3
+ 
+ !Shell wrapped prompt behaviour
+ RESET
+ RESIZE 5,10
+ PUSH "PROMPT GOES HERE\r\n> \r\n\r\nPROMPT GOES HERE\r\n> "
+   ?screen_row 0 = "> "
+   ?screen_row 1 = ""
+   ?screen_row 2 = "PROMPT GOE"
+   ?screen_row 3 = "S HERE"
+   ?lineinfo 3 = cont
+   ?screen_row 4 = "> "
+   ?cursor = 4,2
+ RESIZE 5,11
+   ?screen_row 0 = "> "
+   ?screen_row 1 = ""
+   ?screen_row 2 = "PROMPT GOES"
+   ?screen_row 3 = " HERE"
+   ?lineinfo 3 = cont
+   ?screen_row 4 = "> "
+   ?cursor = 4,2
+ RESIZE 5,12
+   ?screen_row 0 = "> "
+   ?screen_row 1 = ""
+   ?screen_row 2 = "PROMPT GOES "
+   ?screen_row 3 = "HERE"
+   ?lineinfo 3 = cont
+   ?screen_row 4 = "> "
+   ?cursor = 4,2
+ RESIZE 5,16
+   ?screen_row 0 = "> "
+   ?screen_row 1 = ""
+   ?screen_row 2 = "PROMPT GOES HERE"
+   ?lineinfo 3 =
+   ?screen_row 3 = "> "
+   ?cursor = 3,2
*** ../vim-9.0.0773/src/libvterm/t/run-test.pl  2022-10-16 14:35:41.840813752 
+0100
--- src/libvterm/t/run-test.pl  2022-10-16 16:37:48.162846316 +0100
***************
*** 124,130 ****
        elsif( $line =~ m/^putglyph (\S+) (.*)$/ ) {
           $line = "putglyph " . join( ",", map sprintf("%x", $_), eval($1) ) . 
" $2";
        }
!       elsif( $line =~ 
m/^(?:movecursor|scrollrect|moverect|erase|damage|sb_pushline|sb_popline|settermprop|setmousefunc|selection-query)
 / ) {
           # no conversion
        }
        elsif( $line =~ m/^(selection-set) (.*?) (\[?)(.*?)(\]?)$/ ) {
--- 124,130 ----
        elsif( $line =~ m/^putglyph (\S+) (.*)$/ ) {
           $line = "putglyph " . join( ",", map sprintf("%x", $_), eval($1) ) . 
" $2";
        }
!       elsif( $line =~ 
m/^(?:movecursor|scrollrect|moverect|erase|damage|sb_pushline|sb_popline|sb_clear|settermprop|setmousefunc|selection-query)
 ?/ ) {
           # no conversion
        }
        elsif( $line =~ m/^(selection-set) (.*?) (\[?)(.*?)(\]?)$/ ) {
*** ../vim-9.0.0773/src/terminal.c      2022-10-15 11:47:54.217416750 +0100
--- src/terminal.c      2022-10-16 16:34:44.094931092 +0100
***************
*** 3447,3453 ****
    handle_bell,                // bell
    handle_resize,      // resize
    handle_pushline,    // sb_pushline
!   NULL                        // sb_popline
  };
  
  /*
--- 3447,3454 ----
    handle_bell,                // bell
    handle_resize,      // resize
    handle_pushline,    // sb_pushline
!   NULL,                       // sb_popline
!   NULL                        // sb_clear
  };
  
  /*
*** ../vim-9.0.0773/src/version.c       2022-10-16 14:53:30.981598163 +0100
--- src/version.c       2022-10-16 19:23:36.680220701 +0100
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     774,
  /**/

-- 
If an elephant is left tied to a parking meter, the parking fee has to be paid
just as it would for a vehicle.
                [real standing law in Florida, United States of America]

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221016182726.6853B1C05ED%40moolenaar.net.

Raspunde prin e-mail lui