// File: /workspace/github_c_makefile_star2_O1/neovim[P]libvterm/src/state.c
// Function: on_text
static int on_text(const char bytes[], size_t len, void *user)
{
  VTermState *state = user;

  VTermPos oldpos = state->pos;

  uint32_t *codepoints = (uint32_t *)(state->vt->tmpbuffer);
  size_t maxpoints = (state->vt->tmpbuffer_len) / sizeof(uint32_t);

  int npoints = 0;
  size_t eaten = 0;

  VTermEncodingInstance *encoding =
    state->gsingle_set     ? &state->encoding[state->gsingle_set] :
    !(bytes[eaten] & 0x80) ? &state->encoding[state->gl_set] :
    state->vt->mode.utf8   ? &state->encoding_utf8 :
                             &state->encoding[state->gr_set];

  (*encoding->enc->decode)(encoding->enc, encoding->data,
      codepoints, &npoints, state->gsingle_set ? 1 : maxpoints,
      bytes, &eaten, len);

  /* There's a chance an encoding (e.g. UTF-8) hasn't found enough bytes yet
   * for even a single codepoint
   */
  if(!npoints)
    return eaten;

  if(state->gsingle_set && npoints)
    state->gsingle_set = 0;

  int i = 0;

  /* This is a combining char. that needs to be merged with the previous
   * glyph output */
  if(vterm_unicode_is_combining(codepoints[i])) {
    /* See if the cursor has moved since */
    if(state->pos.row == state->combine_pos.row && state->pos.col == state->combine_pos.col + state->combine_width) {
#ifdef DEBUG_GLYPH_COMBINE
      int printpos;
      printf("DEBUG: COMBINING SPLIT GLYPH of chars {");
      for(printpos = 0; state->combine_chars[printpos]; printpos++)
        printf("U+%04x ", state->combine_chars[printpos]);
      printf("} + {");
#endif

      /* Find where we need to append these combining chars */
      int saved_i = 0;
      while(state->combine_chars[saved_i])
        saved_i++;

      /* Add extra ones */
      while(i < npoints && vterm_unicode_is_combining(codepoints[i])) {
        if(saved_i >= state->combine_chars_size)
          grow_combine_buffer(state);
        state->combine_chars[saved_i++] = codepoints[i++];
      }
      if(saved_i >= state->combine_chars_size)
        grow_combine_buffer(state);
      state->combine_chars[saved_i] = 0;

#ifdef DEBUG_GLYPH_COMBINE
      for(; state->combine_chars[printpos]; printpos++)
        printf("U+%04x ", state->combine_chars[printpos]);
      printf("}\n");
#endif

      /* Now render it */
      putglyph(state, state->combine_chars, state->combine_width, state->combine_pos);
    }
    else {
      DEBUG_LOG("libvterm: TODO: Skip over split char+combining\n");
    }
  }

  for(; i < npoints; i++) {
    // Try to find combining characters following this
    int glyph_starts = i;
    int glyph_ends;
    for(glyph_ends = i + 1;
        (glyph_ends < npoints) && (glyph_ends < glyph_starts + VTERM_MAX_CHARS_PER_CELL);
        glyph_ends++)
      if(!vterm_unicode_is_combining(codepoints[glyph_ends]))
        break;

    int width = 0;

    uint32_t chars[VTERM_MAX_CHARS_PER_CELL + 1];

    for( ; i < glyph_ends; i++) {
      chars[i - glyph_starts] = codepoints[i];
      int this_width = vterm_unicode_width(codepoints[i]);
#ifdef DEBUG
      if(this_width < 0) {
        fprintf(stderr, "Text with negative-width codepoint U+%04x\n", codepoints[i]);
        abort();
      }
#endif
      width += this_width;
    }

    while(i < npoints && vterm_unicode_is_combining(codepoints[i]))
      i++;

    chars[glyph_ends - glyph_starts] = 0;
    i--;

#ifdef DEBUG_GLYPH_COMBINE
    int printpos;
    printf("DEBUG: COMBINED GLYPH of %d chars {", glyph_ends - glyph_starts);
    for(printpos = 0; printpos < glyph_ends - glyph_starts; printpos++)
      printf("U+%04x ", chars[printpos]);
    printf("}, onscreen width %d\n", width);
#endif

    if(state->at_phantom || state->pos.col + width > THISROWWIDTH(state)) {
      linefeed(state);
      state->pos.col = 0;
      state->at_phantom = 0;
      state->lineinfo[state->pos.row].continuation = 1;
    }

    if(state->mode.insert) {
      /* TODO: This will be a little inefficient for large bodies of text, as
       * it'll have to 'ICH' effectively before every glyph. We should scan
       * ahead and ICH as many times as required
       */
      VTermRect rect = {
        .start_row = state->pos.row,
        .end_row   = state->pos.row + 1,
        .start_col = state->pos.col,
        .end_col   = THISROWWIDTH(state),
      };
      scroll(state, rect, 0, -1);
    }

    putglyph(state, chars, width, state->pos);

    if(i == npoints - 1) {
      /* End of the buffer. Save the chars in case we have to combine with
       * more on the next call */
      int save_i;
      for(save_i = 0; chars[save_i]; save_i++) {
        if(save_i >= state->combine_chars_size)
          grow_combine_buffer(state);
        state->combine_chars[save_i] = chars[save_i];
      }
      if(save_i >= state->combine_chars_size)
        grow_combine_buffer(state);
      state->combine_chars[save_i] = 0;
      state->combine_width = width;
      state->combine_pos = state->pos;
    }

    if(state->pos.col + width >= THISROWWIDTH(state)) {
      if(state->mode.autowrap)
        state->at_phantom = 1;
    }
    else {
      state->pos.col += width;
    }
  }

  updatecursor(state, &oldpos, 0);

#ifdef DEBUG
  if(state->pos.row < 0 || state->pos.row >= state->rows ||
     state->pos.col < 0 || state->pos.col >= state->cols) {
    fprintf(stderr, "Position out of bounds after text: (%d,%d)\n",
        state->pos.row, state->pos.col);
    abort();
  }
#endif

  return eaten;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rdx, %rbx
movq %rsi, %rax
movq %rdi, %r9
movq 0x38(%rdx), %rcx
movq %rcx, 0x28(%rsp)
movq (%rdx), %rsi
movq 0x118(%rsi), %r13
movq 0x120(%rsi), %rcx
shrq $0x2, %rcx
movl $0x0, 0x4(%rsp)
movq $0x0, 0x18(%rsp)
movslq 0x130(%rdx), %rdx
testq %rdx, %rdx
je 0x7178
leaq (%rdx,%rdx,2), %rsi
jmp 0x719c
cmpb $0x0, (%r9)
js 0x7187
movslq 0x128(%rbx), %rsi
jmp 0x7198
testb $0x1, 0x18(%rsi)
jne 0x72af
movslq 0x12c(%rbx), %rsi
leaq (%rsi,%rsi,2), %rsi
leaq (%rbx,%rsi,8), %rdi
addq $0xb0, %rdi
leaq 0x8(%rdi), %rsi
testl %edx, %edx
movq (%rdi), %rdi
movl $0x1, %r8d
cmovel %ecx, %r8d
leaq 0x18(%rsp), %r10
leaq 0x4(%rsp), %r15
movq %r13, %rdx
movq %r15, %rcx
pushq %rax
pushq %r10
callq *0x8(%rdi)
addq $0x10, %rsp
cmpl $0x0, (%r15)
je 0x7555
cmpl $0x0, 0x130(%rbx)
je 0x71f1
movl $0x0, 0x130(%rbx)
movl (%r13), %edi
callq 0xa274
xorl %r12d, %r12d
testl %eax, %eax
movq %r13, 0x8(%rsp)
je 0x72fb
movl 0x38(%rbx), %eax
cmpl 0xa4(%rbx), %eax
jne 0x72fb
movl 0xa0(%rbx), %eax
addl 0xa8(%rbx), %eax
cmpl %eax, 0x3c(%rbx)
jne 0x72fb
movq 0x90(%rbx), %rax
xorl %ecx, %ecx
xorl %r15d, %r15d
movq %r15, %rbp
movq %rcx, %r13
incq %r15
addq $0x4, %rcx
cmpl $0x0, (%rax,%rbp,4)
jne 0x723a
cmpl $0x0, 0x4(%rsp)
jle 0x72bb
xorl %r12d, %r12d
movq 0x8(%rsp), %rdx
leaq (%r15,%r12), %rbp
decq %rbp
movl (%rdx,%r12,4), %edi
callq 0xa274
testl %eax, %eax
je 0x72be
cmpq %rbp, 0x98(%rbx)
ja 0x7281
movq %rbx, %rdi
callq 0x9751
movq 0x8(%rsp), %rdx
movl (%rdx,%r12,4), %eax
incq %r12
movq 0x90(%rbx), %rcx
movl %eax, (%rcx,%r13)
movslq 0x4(%rsp), %rax
addq $0x4, %r13
cmpq %rax, %r12
jl 0x725c
leaq (%r15,%r12), %rbp
decq %rbp
jmp 0x72be
leaq 0x110(%rbx), %rdi
jmp 0x71a7
xorl %r12d, %r12d
movq 0x8(%rsp), %r13
movl %ebp, %r14d
cmpq %r14, 0x98(%rbx)
ja 0x72d7
movq %rbx, %rdi
callq 0x9751
movq 0x90(%rbx), %rsi
movl $0x0, (%rsi,%r14,4)
movl 0xa0(%rbx), %edx
movq 0xa4(%rbx), %rcx
movq %rbx, %rdi
callq 0x97b0
cmpl 0x4(%rsp), %r12d
jge 0x7546
leaq 0x4(%r13), %rax
movq %rax, 0x20(%rsp)
movl %r12d, %eax
movq %rax, 0x10(%rsp)
movslq %r12d, %rbp
addl $0x5, %r12d
movslq %r12d, %r14
movq 0x20(%rsp), %rax
leaq (%rax,%rbp,4), %r12
xorl %ecx, %ecx
movq %rcx, %r15
leaq (%rcx,%rbp), %rax
incq %rax
movslq 0x4(%rsp), %rcx
cmpq %rcx, %rax
jge 0x735a
leaq (%r15,%rbp), %rax
cmpq %r14, %rax
jge 0x735a
movl (%r12,%r15,4), %edi
callq 0xa274
leaq 0x1(%r15), %rcx
testl %eax, %eax
jne 0x732c
movq 0x10(%rsp), %r12
leal (%r15,%r12), %eax
cmpl %eax, %r12d
jle 0x736c
xorl %ebp, %ebp
jmp 0x73ac
leaq (,%rbp,4), %r14
addq %r13, %r14
leaq 0x1(%r15), %r13
xorl %r12d, %r12d
xorl %ebp, %ebp
movl (%r14,%r12,4), %eax
movl %eax, 0x30(%rsp,%r12,4)
movl (%r14,%r12,4), %edi
callq 0xa0f8
addl %eax, %ebp
incq %r12
cmpl %r12d, %r13d
jne 0x7380
movq 0x10(%rsp), %rax
addl %r12d, %eax
movl %eax, %r12d
movq 0x8(%rsp), %r13
cmpl 0x4(%rsp), %r12d
jge 0x73d1
movslq %r12d, %r12
movl (%r13,%r12,4), %edi
callq 0xa274
testl %eax, %eax
je 0x73d1
incq %r12
movslq 0x4(%rsp), %rax
cmpq %rax, %r12
jl 0x73b6
incl %r15d
movslq %r15d, %rax
movl $0x0, 0x30(%rsp,%rax,4)
cmpl $0x0, 0x40(%rbx)
jne 0x740d
movq 0x70(%rbx), %rax
movslq 0x38(%rbx), %rcx
testb $0x1, (%rax,%rcx,4)
jne 0x73f8
movl 0x34(%rbx), %eax
jmp 0x7404
movl 0x34(%rbx), %ecx
movl %ecx, %eax
shrl $0x1f, %eax
addl %ecx, %eax
sarl %eax
movl 0x3c(%rbx), %ecx
addl %ebp, %ecx
cmpl %eax, %ecx
jle 0x7429
movq %rbx, %rdi
callq 0x9822
movq $0x0, 0x3c(%rbx)
movq 0x70(%rbx), %rax
movslq 0x38(%rbx), %rcx
orb $0x8, (%rax,%rcx,4)
testb $0x8, 0xac(%rbx)
je 0x7476
movslq 0x38(%rbx), %rsi
movq 0x70(%rbx), %rax
testb $0x1, (%rax,%rsi,4)
jne 0x7445
movl 0x34(%rbx), %edx
jmp 0x7451
movl 0x34(%rbx), %eax
movl %eax, %edx
shrl $0x1f, %edx
addl %eax, %edx
sarl %edx
movl %esi, %eax
incl %esi
shlq $0x20, %rsi
orq %rax, %rsi
movl 0x3c(%rbx), %eax
shlq $0x20, %rdx
orq %rax, %rdx
movq %rbx, %rdi
xorl %ecx, %ecx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
callq 0x988b
movq 0x38(%rbx), %rcx
movq %rbx, %rdi
leaq 0x30(%rsp), %rsi
movl %ebp, %edx
callq 0x97b0
cmpl 0x4(%rsp), %r12d
jne 0x7500
cmpl $0x0, 0x30(%rsp)
je 0x74cc
xorl %r14d, %r14d
cmpq %r14, 0x98(%rbx)
ja 0x74ab
movq %rbx, %rdi
callq 0x9751
movl 0x30(%rsp,%r14,4), %eax
movq 0x90(%rbx), %rcx
movl %eax, (%rcx,%r14,4)
leaq 0x1(%r14), %r15
cmpl $0x0, 0x34(%rsp,%r14,4)
movq %r15, %r14
jne 0x749a
jmp 0x74cf
xorl %r15d, %r15d
cmpq %r15, 0x98(%rbx)
ja 0x74e0
movq %rbx, %rdi
callq 0x9751
movq 0x90(%rbx), %rax
movl $0x0, (%rax,%r15,4)
movl %ebp, 0xa0(%rbx)
movq 0x38(%rbx), %rax
movq %rax, 0xa4(%rbx)
movq 0x70(%rbx), %rax
movslq 0x38(%rbx), %rcx
addl 0x3c(%rbx), %ebp
testb $0x1, (%rax,%rcx,4)
jne 0x7516
movl 0x34(%rbx), %eax
jmp 0x7522
movl 0x34(%rbx), %ecx
movl %ecx, %eax
shrl $0x1f, %eax
addl %ecx, %eax
sarl %eax
cmpl %eax, %ebp
jge 0x752b
movl %ebp, 0x3c(%rbx)
jmp 0x753b
testb $0x4, 0xac(%rbx)
je 0x753b
movl $0x1, 0x40(%rbx)
cmpl 0x4(%rsp), %r12d
jl 0x730f
leaq 0x28(%rsp), %rsi
movq %rbx, %rdi
xorl %edx, %edx
callq 0x9af5
movl 0x18(%rsp), %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq