// File: /workspace/github_c_makefile_star2_O2/neovim[P]libvterm/src/state.c
// Function: scroll
static void scroll(VTermState *state, VTermRect rect, int downward, int rightward)
{
  if(!downward && !rightward)
    return;

  int rows = rect.end_row - rect.start_row;
  if(downward > rows)
    downward = rows;
  else if(downward < -rows)
    downward = -rows;

  int cols = rect.end_col - rect.start_col;
  if(rightward > cols)
    rightward = cols;
  else if(rightward < -cols)
    rightward = -cols;

  if(state->callbacks_has_premove && state->callbacks && state->callbacks->premove) {
    // TODO: technically this logic is wrong if both downward != 0 and rightward != 0

    /* Work out what subsection of the destination area is about to be destroyed */
    if(downward > 0)
      /* about to destroy the top */
      (*state->callbacks->premove)((VTermRect){
          .start_row = rect.start_row, .end_row = rect.start_row + downward,
          .start_col = rect.start_col, .end_col = rect.end_col}, state->cbdata);
    else if(downward < 0)
      /* about to destroy the bottom */
      (*state->callbacks->premove)((VTermRect){
          .start_row = rect.end_row + downward, .end_row = rect.end_row,
          .start_col = rect.start_col,          .end_col = rect.end_col}, state->cbdata);

    if(rightward > 0)
      /* about to destroy the left */
      (*state->callbacks->premove)((VTermRect){
          .start_row = rect.start_row, .end_row = rect.end_row,
          .start_col = rect.start_col, .end_col = rect.start_col + rightward}, state->cbdata);
    else if(rightward < 0)
      /* about to destroy the right */
      (*state->callbacks->premove)((VTermRect){
          .start_row = rect.start_row,           .end_row = rect.end_row,
          .start_col = rect.end_col + rightward, .end_col = rect.end_col}, state->cbdata);
  }

  // Update lineinfo if full line
  if(rect.start_col == 0 && rect.end_col == state->cols && rightward == 0) {
    int height = rect.end_row - rect.start_row - abs(downward);

    if(downward > 0) {
      memmove(state->lineinfo + rect.start_row,
              state->lineinfo + rect.start_row + downward,
              height * sizeof(state->lineinfo[0]));
      for(int row = rect.end_row - downward; row < rect.end_row; row++)
        state->lineinfo[row] = (VTermLineInfo){ 0 };
    }
    else {
      memmove(state->lineinfo + rect.start_row - downward,
              state->lineinfo + rect.start_row,
              height * sizeof(state->lineinfo[0]));
      for(int row = rect.start_row; row < rect.start_row - downward; row++)
        state->lineinfo[row] = (VTermLineInfo){ 0 };
    }
  }

  if(state->callbacks && state->callbacks->scrollrect)
    if((*state->callbacks->scrollrect)(rect, downward, rightward, state->cbdata))
      return;

  if(state->callbacks)
    vterm_scroll_rect(rect, downward, rightward,
        state->callbacks->moverect, state->callbacks->erase, state->cbdata);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %r8d, %eax
orl %ecx, %eax
je 0x8dee
movq %rdx, %r10
movq %rsi, %r11
movq %rdi, %r15
movq %rsi, %rbp
shrq $0x20, %rbp
movq %rdx, %rbx
shrq $0x20, %rbx
movl %ebp, %r14d
subl %r11d, %r14d
movl %r14d, %r12d
negl %r12d
cmpl %ecx, %r12d
cmovlel %ecx, %r12d
cmpl %ecx, %r14d
cmovll %r14d, %r12d
movl %ebx, %eax
subl %r10d, %eax
movl %eax, %r13d
negl %r13d
cmpl %r8d, %r13d
cmovlel %r8d, %r13d
cmpl %r8d, %eax
cmovll %eax, %r13d
cmpb $0x1, 0x18(%rdi)
jne 0x8d8a
movq 0x8(%r15), %rax
testq %rax, %rax
je 0x8d8a
movq 0x60(%rax), %rax
testq %rax, %rax
je 0x8d8a
testl %r12d, %r12d
movq %r10, 0x8(%rsp)
movq %r11, 0x10(%rsp)
jle 0x8d41
leal (%r12,%r11), %ecx
movq 0x10(%r15), %rdx
shlq $0x20, %rcx
movl %r11d, %edi
orq %rcx, %rdi
movq %r10, %rsi
callq *%rax
jmp 0x8d47
js 0x8eb2
testl %r13d, %r13d
jle 0x8d7a
movq 0x8(%rsp), %rsi
leal (%rsi,%r13), %eax
movq 0x8(%r15), %rcx
movq 0x10(%r15), %rdx
shlq $0x20, %rax
movl %esi, %esi
orq %rax, %rsi
movq 0x10(%rsp), %rdi
callq *0x60(%rcx)
movq 0x10(%rsp), %r11
movq 0x8(%rsp), %r10
jmp 0x8d8a
movq 0x8(%rsp), %r10
movq 0x10(%rsp), %r11
js 0x8ed9
testl %r10d, %r10d
je 0x8dfd
movq 0x8(%r15), %rax
testq %rax, %rax
je 0x8dee
movq 0x10(%rax), %r9
testq %r9, %r9
je 0x8dcd
movq 0x10(%r15), %r8
movq %r11, %rdi
movq %r10, %rsi
movl %r12d, %edx
movl %r13d, %ecx
movq %r10, %rbx
movq %r11, %r14
callq *%r9
testl %eax, %eax
jne 0x8dee
movq %r14, %r11
movq %rbx, %r10
movq 0x8(%r15), %rax
testq %rax, %rax
je 0x8dee
movq 0x18(%rax), %r8
movq 0x20(%rax), %r9
movq 0x10(%r15), %rax
movq %rax, (%rsp)
movq %r11, %rdi
movq %r10, %rsi
movl %r12d, %edx
movl %r13d, %ecx
callq 0x2160
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testl %r13d, %r13d
jne 0x8d8f
cmpl %ebx, 0x34(%r15)
jne 0x8d8f
movq %r10, 0x8(%rsp)
movl %r12d, %eax
negl %eax
cmovnsl %r12d, %eax
addl %eax, %r14d
movslq %r11d, %rax
shlq $0x2, %rax
addq 0x70(%r15), %rax
testl %r12d, %r12d
movq %r11, %rbx
jle 0x8e6d
movl %r12d, %ecx
leaq (%rax,%rcx,4), %rsi
movslq %r14d, %rdx
shlq $0x2, %rdx
movq %rax, %rdi
callq 0x2190
subl %r12d, %ebp
movslq %ebp, %rax
movq %rbx, %rcx
sarq $0x20, %rcx
movq 0x8(%rsp), %r10
movq %rbx, %r11
cmpq %rcx, %rax
jge 0x8d8f
movq 0x70(%r15), %rdx
movb $0x0, (%rdx,%rax,4)
incq %rax
jmp 0x8e57
movslq %r12d, %rcx
shlq $0x2, %rcx
movq %rax, %rdi
subq %rcx, %rdi
movslq %r14d, %rdx
shlq $0x2, %rdx
movq %rax, %rsi
callq 0x2190
movl %ebx, %ecx
subl %r12d, %ecx
movslq %ebx, %rax
movslq %ecx, %rcx
movq 0x8(%rsp), %r10
movq %rbx, %r11
cmpq %rcx, %rax
jge 0x8d8f
movq 0x70(%r15), %rdx
movb $0x0, (%rdx,%rax,4)
incq %rax
jmp 0x8e9c
leal (%r12,%rbp), %edi
movq 0x10(%r15), %rdx
movq 0x10(%rsp), %rcx
movabsq $-0x100000000, %rsi     # imm = 0xFFFFFFFF00000000
andq %rsi, %rcx
orq %rcx, %rdi
movq 0x8(%rsp), %rsi
jmp 0x8d3d
leal (%rbx,%r13), %esi
movq 0x8(%r15), %rax
movq 0x10(%r15), %rdx
movabsq $-0x100000000, %rcx     # imm = 0xFFFFFFFF00000000
andq %r10, %rcx
orq %rcx, %rsi
movq %r11, %rdi
callq *0x60(%rax)
jmp 0x8d6e