// File: /workspace/github_c_makefile_star2_O3/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), %r14
movq 0x120(%rsi), %rcx
shrq $0x2, %rcx
movl $0x0, 0x4(%rsp)
movq $0x0, 0x18(%rsp)
movslq 0x130(%rdx), %rdx
testq %rdx, %rdx
je 0x7aa4
leaq (%rdx,%rdx,2), %rsi
jmp 0x7ac8
cmpb $0x0, (%r9)
js 0x7ab3
movslq 0x128(%rbx), %rsi
jmp 0x7ac4
testb $0x1, 0x18(%rsi)
jne 0x7bd3
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 %r14, %rdx
movq %r15, %rcx
pushq %rax
pushq %r10
callq *0x8(%rdi)
addq $0x10, %rsp
cmpl $0x0, (%r15)
je 0x7e72
cmpl $0x0, 0x130(%rbx)
je 0x7b1d
movl $0x0, 0x130(%rbx)
movl (%r14), %edi
callq 0xab95
xorl %r12d, %r12d
testl %eax, %eax
movq %rbx, 0x10(%rsp)
je 0x7c27
movl 0x38(%rbx), %eax
cmpl 0xa4(%rbx), %eax
jne 0x7c27
movl 0xa0(%rbx), %eax
addl 0xa8(%rbx), %eax
cmpl %eax, 0x3c(%rbx)
jne 0x7c27
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 0x7b65
cmpl $0x0, 0x4(%rsp)
jle 0x7bdf
xorl %r12d, %r12d
leaq (%r15,%r12), %rbp
decq %rbp
movl (%r14,%r12,4), %edi
callq 0xab95
testl %eax, %eax
je 0x7bce
cmpq %rbp, 0x98(%rbx)
ja 0x7ba7
movq %rbx, %rdi
callq 0xa0b2
movl (%r14,%r12,4), %eax
incq %r12
movq 0x90(%rbx), %rcx
movl %eax, (%rcx,%r13)
movslq 0x4(%rsp), %rax
addq $0x4, %r13
cmpq %rax, %r12
jl 0x7b82
leaq (%r15,%r12), %rbp
decq %rbp
movq %r14, %r15
jmp 0x7be5
leaq 0x110(%rbx), %rdi
jmp 0x7ad3
movq %r14, %r15
xorl %r12d, %r12d
movl %ebp, %ebx
movq 0x10(%rsp), %r14
cmpq %rbx, 0x98(%r14)
ja 0x7bfd
movq %r14, %rdi
callq 0xa0b2
movq 0x90(%r14), %rsi
movl $0x0, (%rsi,%rbx,4)
movl 0xa0(%r14), %edx
movq 0xa4(%r14), %rcx
movq %r14, %rdi
callq 0xa111
movq %r14, %rbx
movq %r15, %r14
cmpl 0x4(%rsp), %r12d
jge 0x7e63
leaq 0x4(%r14), %rax
movq %rax, 0x20(%rsp)
movq %r14, 0x8(%rsp)
movl %r12d, %r13d
movslq %r12d, %rbp
addl $0x5, %r12d
movslq %r12d, %r12
movq 0x20(%rsp), %rax
leaq (%rax,%rbp,4), %r14
xorl %ecx, %ecx
movq %rcx, %r15
leaq (%rcx,%rbp), %rax
incq %rax
movslq 0x4(%rsp), %rcx
cmpq %rcx, %rax
jge 0x7c86
leaq (%r15,%rbp), %rax
cmpq %r12, %rax
jge 0x7c86
movl (%r14,%r15,4), %edi
callq 0xab95
leaq 0x1(%r15), %rcx
testl %eax, %eax
jne 0x7c58
leal (%r15,%r13), %eax
cmpl %eax, %r13d
jle 0x7c96
xorl %ebp, %ebp
movl %r13d, %r12d
jmp 0x7ccb
leaq (%r15,%r13), %r12
incq %r12
movq 0x8(%rsp), %rax
leaq (%rax,%rbp,4), %r13
leaq 0x1(%r15), %r14
xorl %ebx, %ebx
xorl %ebp, %ebp
movl (%r13,%rbx,4), %edi
movl %edi, 0x30(%rsp,%rbx,4)
callq 0xaa2c
addl %eax, %ebp
incq %rbx
cmpl %ebx, %r14d
jne 0x7cae
movq 0x10(%rsp), %rbx
movq 0x8(%rsp), %r14
cmpl 0x4(%rsp), %r12d
jge 0x7cf4
movslq %r12d, %r12
movl (%r14,%r12,4), %edi
callq 0xab95
testl %eax, %eax
je 0x7cf4
incq %r12
movslq 0x4(%rsp), %rax
cmpq %rax, %r12
jl 0x7cda
incl %r15d
movslq %r15d, %rax
movl $0x0, 0x30(%rsp,%rax,4)
cmpl $0x0, 0x40(%rbx)
jne 0x7d2c
movl 0x3c(%rbx), %eax
addl %ebp, %eax
movq 0x70(%rbx), %rcx
movslq 0x38(%rbx), %rdx
movl 0x34(%rbx), %esi
movl %esi, %edi
shrl $0x1f, %edi
addl %esi, %edi
sarl %edi
testb $0x1, (%rcx,%rdx,4)
cmovel %esi, %edi
cmpl %edi, %eax
jle 0x7d48
movq %rbx, %rdi
callq 0xa15f
movq $0x0, 0x3c(%rbx)
movq 0x70(%rbx), %rax
movslq 0x38(%rbx), %rcx
orb $0x8, (%rax,%rcx,4)
testb $0x8, 0xac(%rbx)
je 0x7d93
movslq 0x38(%rbx), %rax
movl %eax, %ecx
leal 0x1(%rax), %esi
shlq $0x20, %rsi
orq %rcx, %rsi
movl 0x34(%rbx), %ecx
movl 0x3c(%rbx), %edi
movq 0x70(%rbx), %r8
movl %ecx, %edx
shrl $0x1f, %edx
addl %ecx, %edx
sarl %edx
testb $0x1, (%r8,%rax,4)
cmovel %ecx, %edx
shlq $0x20, %rdx
orq %rdi, %rdx
movq %rbx, %rdi
xorl %ecx, %ecx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
callq 0xa1c0
movq 0x38(%rbx), %rcx
movq %rbx, %rdi
leaq 0x30(%rsp), %rsi
movl %ebp, %edx
callq 0xa111
cmpl 0x4(%rsp), %r12d
jne 0x7de3
movl 0x30(%rsp), %eax
xorl %r15d, %r15d
testl %eax, %eax
je 0x7deb
cmpq %r15, 0x98(%rbx)
ja 0x7dce
movq %rbx, %rdi
callq 0xa0b2
movl 0x30(%rsp,%r15,4), %eax
movq 0x90(%rbx), %rcx
movl %eax, (%rcx,%r15,4)
movl 0x34(%rsp,%r15,4), %eax
incq %r15
jmp 0x7db4
movl 0x38(%rbx), %ecx
movl 0x3c(%rbx), %eax
jmp 0x7e23
cmpq %r15, 0x98(%rbx)
ja 0x7dfc
movq %rbx, %rdi
callq 0xa0b2
movq 0x90(%rbx), %rax
movl $0x0, (%rax,%r15,4)
movl %ebp, 0xa0(%rbx)
movq 0x38(%rbx), %rcx
movq %rcx, 0xa4(%rbx)
movq %rcx, %rax
shrq $0x20, %rax
addl %ebp, %eax
movq 0x70(%rbx), %rdx
movslq %ecx, %rcx
movl 0x34(%rbx), %esi
movl %esi, %edi
shrl $0x1f, %edi
addl %esi, %edi
sarl %edi
testb $0x1, (%rdx,%rcx,4)
cmovel %esi, %edi
cmpl %edi, %eax
jge 0x7e48
movl %eax, 0x3c(%rbx)
jmp 0x7e58
testb $0x4, 0xac(%rbx)
je 0x7e58
movl $0x1, 0x40(%rbx)
cmpl 0x4(%rsp), %r12d
jl 0x7c40
leaq 0x28(%rsp), %rsi
movq %rbx, %rdi
xorl %edx, %edx
callq 0xa42b
movl 0x18(%rsp), %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq