// File: /workspace/github_c_makefile_star2_O2/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, %r12
movq 0x38(%rdx), %rax
movq %rax, 0x28(%rsp)
movq (%rdx), %rdx
movq 0x118(%rdx), %rax
movq %rax, 0x8(%rsp)
movq 0x120(%rdx), %r8
andl $0x0, 0x4(%rsp)
movq %rsi, %rax
andq $0x0, 0x18(%rsp)
movq %rdi, %r9
shrq $0x2, %r8
movslq 0x130(%r12), %rcx
testq %rcx, %rcx
je 0x674d
imulq $0x18, %rcx, %rdx
jmp 0x6773
cmpb $0x0, (%r9)
js 0x675d
movslq 0x128(%r12), %rdx
jmp 0x676f
testb $0x1, 0x18(%rdx)
jne 0x6871
movslq 0x12c(%r12), %rdx
imulq $0x18, %rdx, %rdx
addq %r12, %rdx
addq $0xb0, %rdx
leaq 0x8(%rdx), %rsi
testl %ecx, %ecx
movq (%rdx), %rdi
pushq $0x1
popq %rcx
cmovnel %ecx, %r8d
leaq 0x18(%rsp), %r10
leaq 0x4(%rsp), %r15
movq 0x8(%rsp), %rdx
movq %r15, %rcx
pushq %rax
pushq %r10
callq *0x8(%rdi)
addq $0x10, %rsp
cmpl $0x0, (%r15)
je 0x6b1c
cmpl $0x0, 0x130(%r12)
je 0x67c7
andl $0x0, 0x130(%r12)
movq 0x8(%rsp), %rax
movl (%rax), %edi
callq 0x94de
xorl %ebp, %ebp
testl %eax, %eax
je 0x68ba
movl 0x38(%r12), %eax
cmpl 0xa4(%r12), %eax
jne 0x68ba
movl 0xa0(%r12), %eax
addl 0xa8(%r12), %eax
cmpl %eax, 0x3c(%r12)
jne 0x68ba
movq 0x90(%r12), %rax
pushq $-0x1
popq %r15
cmpl $0x0, 0x4(%rax,%r15,4)
leaq 0x1(%r15), %r15
jne 0x6817
xorl %ebp, %ebp
movslq 0x4(%rsp), %rax
cmpq %rax, %rbp
jge 0x687e
movq 0x8(%rsp), %rax
movl (%rax,%rbp,4), %edi
callq 0x94de
movq 0x98(%r12), %rcx
testl %eax, %eax
je 0x6886
cmpq %r15, %rcx
ja 0x6855
movq %r12, %rdi
callq 0x8b8e
movq 0x8(%rsp), %rax
movl (%rax,%rbp,4), %eax
incq %rbp
movq 0x90(%r12), %rcx
movl %eax, (%rcx,%r15,4)
incq %r15
jmp 0x6825
leaq 0x110(%r12), %rdx
jmp 0x677d
movq 0x98(%r12), %rcx
movl %r15d, %ebx
cmpq %rbx, %rcx
ja 0x6896
movq %r12, %rdi
callq 0x8b8e
movq 0x90(%r12), %rsi
andl $0x0, (%rsi,%rbx,4)
movl 0xa0(%r12), %edx
movq 0xa4(%r12), %rcx
movq %r12, %rdi
callq 0x8bed
movq %r12, 0x20(%rsp)
cmpl 0x4(%rsp), %ebp
jge 0x6b0d
movslq %ebp, %rcx
addl $0x5, %ebp
movslq %ebp, %r12
movq %rcx, %rdx
shlq $0x20, %rdx
pushq $0x1
popq %rsi
movq %rcx, 0x10(%rsp)
movabsq $0x100000000, %rbp      # imm = 0x100000000
movq %rdx, %r14
movl %esi, %r15d
leaq 0x1(%rcx), %rbx
movslq 0x4(%rsp), %rax
cmpq %rax, %rbx
jge 0x6921
cmpq %r12, %rcx
jge 0x6921
movq 0x8(%rsp), %rax
movl 0x4(%rax,%rcx,4), %edi
callq 0x94de
leaq (%r14,%rbp), %rdx
leal 0x1(%r15), %esi
movq %rbx, %rcx
testl %eax, %eax
jne 0x68eb
sarq $0x20, %r14
movq 0x8(%rsp), %rax
movq 0x10(%rsp), %rcx
leaq (%rax,%rcx,4), %r13
xorl %r12d, %r12d
xorl %ebx, %ebx
movq 0x10(%rsp), %rax
leaq (%rax,%r12), %rbp
cmpq %r14, %rbp
jg 0x695c
movl (%r13,%r12,4), %edi
movl %edi, 0x30(%rsp,%r12,4)
callq 0x9378
addl %eax, %ebx
incq %r12
jmp 0x6938
movq 0x20(%rsp), %r12
movslq 0x4(%rsp), %rax
cmpq %rax, %rbp
jge 0x6981
movq 0x8(%rsp), %rax
movl (%rax,%rbp,4), %edi
callq 0x94de
testl %eax, %eax
je 0x6981
incq %rbp
jmp 0x6961
movslq %r15d, %rax
andl $0x0, 0x30(%rsp,%rax,4)
cmpl $0x0, 0x40(%r12)
jne 0x69bd
movl 0x3c(%r12), %esi
addl %ebx, %esi
movq 0x70(%r12), %rdi
movslq 0x38(%r12), %r8
movl 0x34(%r12), %ecx
movl %ecx, %eax
cltd
pushq $0x2
popq %r9
idivl %r9d
testb $0x1, (%rdi,%r8,4)
cmovel %ecx, %eax
cmpl %eax, %esi
jle 0x69d9
movq %r12, %rdi
callq 0x8c3b
andq $0x0, 0x3c(%r12)
movq 0x70(%r12), %rax
movslq 0x38(%r12), %rcx
orb $0x8, (%rax,%rcx,4)
testb $0x8, 0xac(%r12)
je 0x6a2e
movslq 0x38(%r12), %rdi
movl %edi, %eax
leal 0x1(%rdi), %esi
shlq $0x20, %rsi
orq %rax, %rsi
movl 0x34(%r12), %ecx
movl 0x3c(%r12), %r8d
movq 0x70(%r12), %r9
movl %ecx, %eax
cltd
pushq $0x2
popq %r10
idivl %r10d
testb $0x1, (%r9,%rdi,4)
cmovnel %eax, %ecx
shlq $0x20, %rcx
orq %r8, %rcx
movq %r12, %rdi
movq %rcx, %rdx
xorl %ecx, %ecx
pushq $-0x1
popq %r8
callq 0x8c9a
movq 0x38(%r12), %rcx
movq %r12, %rdi
leaq 0x30(%rsp), %rsi
movl %ebx, %edx
callq 0x8bed
cmpl %ebp, 0x4(%rsp)
jne 0x6a7f
xorl %r14d, %r14d
movl 0x30(%rsp,%r14,4), %eax
movq 0x98(%r12), %rcx
testl %eax, %eax
je 0x6a8b
cmpq %r14, %rcx
ja 0x6a6e
movq %r12, %rdi
callq 0x8b8e
movl 0x30(%rsp,%r14,4), %eax
movq 0x90(%r12), %rcx
movl %eax, (%rcx,%r14,4)
incq %r14
jmp 0x6a4b
movl 0x38(%r12), %eax
movl 0x3c(%r12), %esi
jmp 0x6ac1
cmpq %r14, %rcx
ja 0x6a98
movq %r12, %rdi
callq 0x8b8e
movq 0x90(%r12), %rax
andl $0x0, (%rax,%r14,4)
movl %ebx, 0xa0(%r12)
movq 0x38(%r12), %rax
movq %rax, 0xa4(%r12)
movq %rax, %rsi
shrq $0x20, %rsi
addl %ebx, %esi
movq 0x70(%r12), %rdi
movslq %eax, %r8
movl 0x34(%r12), %ecx
movl %ecx, %eax
cltd
pushq $0x2
popq %r9
idivl %r9d
testb $0x1, (%rdi,%r8,4)
cmovel %ecx, %eax
cmpl %eax, %esi
jge 0x6af0
movl %esi, 0x3c(%r12)
jmp 0x68bf
testb $0x4, 0xac(%r12)
je 0x68bf
movl $0x1, 0x40(%r12)
jmp 0x68bf
leaq 0x28(%rsp), %rsi
movq %r12, %rdi
xorl %edx, %edx
callq 0x8f00
movl 0x18(%rsp), %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq