// File: /workspace/github_c_makefile_star2_O1/justy989[P]ce/ce.c
// Function: ce_buffer_remove_string
bool ce_buffer_remove_string(CeBuffer_t* buffer, CePoint_t point, int64_t length){
     if(buffer->status == CE_BUFFER_STATUS_READONLY) return false;
     if(!ce_buffer_point_is_valid(buffer, point)) return false;

     char* first_line_start = ce_utf8_iterate_to(buffer->lines[point.y], point.x);
     int64_t length_left_on_line = ce_utf8_strlen(first_line_start) + 1;

     if(length_left_on_line > length){
          // case: glue together left and right sides and cut out the middle
          char* end_of_start = ce_utf8_iterate_to(buffer->lines[point.y], point.x);
          assert(end_of_start);
          char* beginning_of_end = ce_utf8_iterate_to(buffer->lines[point.y], point.x + length);
          assert(beginning_of_end);

          // figure out how big of a line to allocate
          size_t start_line_len = end_of_start - buffer->lines[point.y];
          size_t end_line_len = strlen(beginning_of_end);
          size_t full_line_len = start_line_len + end_line_len;
          char* new_line = calloc(full_line_len + 1, sizeof(*new_line));
          if(!new_line) return false;

          // copy over the data to our new line
          memcpy(new_line, buffer->lines[point.y], start_line_len);
          memcpy(new_line + start_line_len, beginning_of_end, end_line_len);
          new_line[full_line_len] = 0;

          // free and overwrite our new line
          free(buffer->lines[point.y]);
          buffer->lines[point.y] = new_line;

          buffer->status = CE_BUFFER_STATUS_MODIFIED;
          return true;
     }else if(length_left_on_line == length){
          if(point.x == 0){
               buffer->status = CE_BUFFER_STATUS_MODIFIED;
               return ce_buffer_remove_lines(buffer, point.y, 1);
          }

          // remove characters left on current line
          int64_t keep_length = (first_line_start - buffer->lines[point.y]);
          buffer->lines[point.y] = realloc(buffer->lines[point.y], keep_length + 1);
          buffer->lines[point.y][keep_length] = 0;

          // perform a join with the next line
          int64_t next_line_index = point.y + 1;
          if(next_line_index > buffer->line_count) return false;
          if(next_line_index < buffer->line_count){
               int64_t cur_line_len = strlen(buffer->lines[point.y]);
               int64_t next_line_len = strlen(buffer->lines[next_line_index]);
               int64_t new_line_len = next_line_len + cur_line_len;
               buffer->lines[point.y] = realloc(buffer->lines[point.y], new_line_len + 1);
               strncpy(buffer->lines[point.y] + cur_line_len, buffer->lines[next_line_index], next_line_len);
               buffer->lines[point.y][new_line_len] = 0;
          }

          buffer->status = CE_BUFFER_STATUS_MODIFIED;
          return ce_buffer_remove_lines(buffer, next_line_index, 1);
     }

     // case: cut the end of the initial line, N lines in the middle and N leftover characters in the final
     //       line, and join the remaining characters in the last line to the initial line
     int64_t length_left = length - length_left_on_line;
     int64_t current_line = point.y + 1;
     int64_t save_current_line = current_line;
     int64_t line_len = 0;
     int64_t last_line_offset = 0;
     bool do_join = false;

     // how many lines do we have to delete?
     for(; current_line < buffer->line_count; current_line++){
          line_len = ce_utf8_strlen(buffer->lines[current_line]) + 1;

          if(length_left >= line_len){
               length_left -= line_len;
               if(length_left == 0){
                    if(point.x == 0 && point.y == 0){
                         // pass
                    }else if(current_line == (buffer->line_count - 1)){
                         current_line++;
                         break;
                    }else{
                         do_join = true;
                         current_line++;
                         break;
                    }
               }
          }else{
               last_line_offset = length_left;
               break;
          }
     }

     int64_t lines_to_delete = current_line - point.y;

     // join the rest of the last line in the deletion, to the first line
     if(last_line_offset || do_join){
          char* end_to_join = ce_utf8_iterate_to(buffer->lines[current_line], last_line_offset);
          int64_t join_len = strlen(end_to_join);
          int64_t new_len = point.x + join_len;
          buffer->lines[point.y] = realloc(buffer->lines[point.y], new_len + 1);
          memcpy(buffer->lines[point.y] + point.x, end_to_join, join_len);
          buffer->lines[point.y][new_len] = 0;
     }else{
          // if we aren't doing a join, then start with deleting the first line
          save_current_line--;
     }

     // remove the intermediate lines
     return ce_buffer_remove_lines(buffer, save_current_line, lines_to_delete);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rcx, %r12
cmpl $0x2, 0x18(%rdi)
sete %al
testq %rdx, %rdx
sets %cl
orb %al, %cl
jne 0xf3b8
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %rbx
cmpq %rdx, 0x8(%rdi)
setle %al
testq %rsi, %rsi
sets %cl
orb %al, %cl
jne 0xf3b8
movq (%rbx), %rax
movq (%rax,%r14,8), %rdi
callq 0xe485
cmpq %r15, %rax
jge 0xf3c9
xorl %eax, %eax
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%rbx), %rax
movq (%rax,%r14,8), %rdi
movq %r15, %rsi
callq 0xe5be
movq %rax, %r13
movq %rax, %rdi
callq 0xe485
cmpq %r12, %rax
jge 0xf4b7
incq %rax
subq %rax, %r12
jne 0xf583
testq %r15, %r15
je 0xf5e4
movq (%rbx), %rax
movq (%rax,%r14,8), %rdi
subq %rdi, %r13
leaq 0x1(%r13), %rsi
callq 0xd520
movq (%rbx), %rcx
movq %rax, (%rcx,%r14,8)
movq (%rbx), %rax
movq (%rax,%r14,8), %rax
movb $0x0, (%rax,%r13)
movq 0x8(%rbx), %rax
cmpq %r14, %rax
jle 0xf3b8
leaq 0x1(%r14), %r15
cmpq %rax, %r15
jge 0xf4a0
movq (%rbx), %rbp
movq (%rbp,%r14,8), %r12
movq %r12, %rdi
callq 0xd210
movq %rax, %r13
movq 0x8(%rbp,%r14,8), %rdi
callq 0xd210
movq %rax, %rbp
addq %r13, %rax
movq %rax, (%rsp)
leaq 0x1(,%r13), %rsi
addq %rbp, %rsi
movq %r12, %rdi
callq 0xd520
movq (%rbx), %rcx
movq %rax, (%rcx,%r14,8)
movq (%rbx), %rax
addq (%rax,%r14,8), %r13
movq 0x8(%rax,%r14,8), %rsi
movq %r13, %rdi
movq %rbp, %rdx
callq 0xd0b0
movq (%rbx), %rax
movq (%rax,%r14,8), %rax
movq (%rsp), %rcx
movb $0x0, (%rax,%rcx)
movl $0x1, 0x18(%rbx)
movl $0x1, %edx
movq %rbx, %rdi
movq %r15, %rsi
jmp 0xf682
movq (%rbx), %rax
movq (%rax,%r14,8), %rdi
movq %r15, %rsi
callq 0xe5be
testq %rax, %rax
je 0xf6a4
movq %rax, %r13
movq (%rbx), %rax
movq (%rax,%r14,8), %rdi
addq %r15, %r12
movq %r12, %rsi
callq 0xe5be
testq %rax, %rax
je 0xf6c3
movq %rax, %rbp
movq (%rbx), %rax
movq %rax, (%rsp)
movq (%rax,%r14,8), %rax
movq %rax, 0x8(%rsp)
subq %rax, %r13
movq %rbp, %rdi
callq 0xd210
movq %rax, %r15
leaq (%rax,%r13), %rdi
incq %rdi
movl $0x1, %esi
callq 0xd380
movq %rax, %r12
testq %rax, %rax
setne %al
je 0xf3ba
movq %rbp, 0x10(%rsp)
movq %r15, %rbp
addq %r13, %rbp
movq %r12, %rdi
movq 0x8(%rsp), %rsi
movq %r13, %rdx
callq 0xd420
movq %r12, %rdi
addq %r13, %rdi
movq 0x10(%rsp), %rsi
movq %r15, %rdx
callq 0xd420
movb $0x0, (%r12,%rbp)
movq (%rsp), %rax
movq (%rax,%r14,8), %rdi
callq 0xd090
movq (%rbx), %rax
movq %r12, (%rax,%r14,8)
movl $0x1, 0x18(%rbx)
movb $0x1, %al
jmp 0xf3ba
leaq 0x1(%r14), %r13
cmpq 0x8(%rbx), %r13
movq %r13, (%rsp)
jge 0xf5df
movq %r15, %rax
orq %r14, %rax
sete %bpl
leaq 0x2(%r14), %r13
movq (%rbx), %rax
movq -0x8(%rax,%r13,8), %rdi
callq 0xe485
cmpq %rax, %r12
jle 0xf5fb
notq %rax
addq %rax, %r12
setne %al
orb %bpl, %al
testb $0x1, %al
je 0xf695
leaq 0x1(%r13), %rcx
cmpq 0x8(%rbx), %r13
movq %rcx, %r13
jl 0xf59f
decq %rcx
xorl %r12d, %r12d
xorl %eax, %eax
movq %rcx, %r13
jmp 0xf600
xorl %r12d, %r12d
jmp 0xf5fe
movl $0x1, 0x18(%rbx)
movl $0x1, %edx
movq %rbx, %rdi
movq %r14, %rsi
jmp 0xf682
decq %r13
xorl %eax, %eax
movq %r13, %rbp
subq %r14, %rbp
testq %r12, %r12
jne 0xf614
testb %al, %al
jne 0xf614
movq %r14, %rsi
jmp 0xf67c
movq (%rbx), %rax
movq (%rax,%r13,8), %rdi
movq %r12, %rsi
callq 0xe5be
movq %rax, %r12
movq %rax, %rdi
callq 0xd210
movq %rax, %r13
addq %r15, %rax
movq %rax, 0x8(%rsp)
movq (%rbx), %rax
movq (%rax,%r14,8), %rdi
leaq (%r15,%r13), %rsi
incq %rsi
callq 0xd520
movq (%rbx), %rcx
movq %rax, (%rcx,%r14,8)
movq (%rbx), %rax
addq (%rax,%r14,8), %r15
movq %r15, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0xd420
movq (%rbx), %rax
movq (%rax,%r14,8), %rax
movq 0x8(%rsp), %rcx
movb $0x0, (%rax,%rcx)
movq (%rsp), %rsi
movq %rbx, %rdi
movq %rbp, %rdx
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xf6e2
cmpq %r13, 0x8(%rbx)
setne %al
xorl %r12d, %r12d
jmp 0xf600
leaq 0x1f017(%rip), %rdi     # 0x2e6c2
leaq 0x1efc6(%rip), %rsi     # 0x2e678
leaq 0x1f016(%rip), %rcx     # 0x2e6cf
movl $0x34b, %edx            # imm = 0x34B
callq 0xd280
leaq 0x1f045(%rip), %rdi     # 0x2e70f
leaq 0x1efa7(%rip), %rsi     # 0x2e678
leaq 0x1eff7(%rip), %rcx     # 0x2e6cf
movl $0x34d, %edx            # imm = 0x34D
callq 0xd280