// File: /workspace/github_c_makefile_star2_O2/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 $0x28, %rsp
cmpl $0x2, 0x18(%rdi)
je 0xf11c
movq %rcx, %r12
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %rbx
callq 0xe425
testq %rax, %rax
je 0xf11c
movq (%rbx), %rax
movq (%rax,%r14,8), %rdi
movq %r15, %rsi
callq 0xe4a6
movq %rax, %r13
movq %rax, %rdi
callq 0xe38c
cmpq %r12, %rax
jge 0xf05f
incq %rax
subq %rax, %r12
jne 0xf12d
testq %r15, %r15
je 0xf193
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 0xf11c
leaq 0x1(%r14), %r15
cmpq %rax, %r15
jge 0xf04a
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, 0x8(%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 0x8(%rsp), %rcx
movb $0x0, (%rax,%rcx)
movl $0x1, 0x18(%rbx)
pushq $0x1
popq %rdx
movq %rbx, %rdi
movq %r15, %rsi
jmp 0xf25c
movq (%rbx), %rax
movq (%rax,%r14,8), %rdi
movq %r15, %rsi
callq 0xe4a6
testq %rax, %rax
je 0xf26f
movq %rax, %r13
movq (%rbx), %rax
movq (%rax,%r14,8), %rdi
addq %r15, %r12
movq %r12, %rsi
callq 0xe4a6
testq %rax, %rax
je 0xf28e
movq %rax, %r15
movq (%rbx), %rax
movq (%rax,%r14,8), %rax
movq %rax, 0x10(%rsp)
subq %rax, %r13
movq %r15, %rdi
callq 0xd210
movq %rax, %r12
leaq (%rax,%r13), %rdi
incq %rdi
pushq $0x1
popq %rsi
callq 0xd380
testq %rax, %rax
je 0xf11c
movq %rax, %rbp
movq %r14, 0x8(%rsp)
movq %r12, %r14
addq %r13, %r14
movq %rax, %rdi
movq 0x10(%rsp), %rsi
movq %r13, %rdx
callq 0xd420
movq %rbp, %rdi
addq %r13, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0xd420
movb $0x0, (%rbp,%r14)
movq 0x10(%rsp), %rdi
callq 0xd090
movq (%rbx), %rax
movq 0x8(%rsp), %rcx
movq %rbp, (%rax,%rcx,8)
movl $0x1, 0x18(%rbx)
movb $0x1, %al
jmp 0xf11e
xorl %eax, %eax
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1(%r14), %rax
movq %rax, 0x18(%rsp)
movq %r15, 0x20(%rsp)
orq %r14, %r15
sete 0x10(%rsp)
movq %r14, 0x8(%rsp)
leaq (,%r14,8), %r14
pushq $0x1
popq %r15
pushq $-0x2
popq %rbp
movq 0x8(%rsp), %rax
leaq (%rax,%r15), %r13
cmpq 0x8(%rbx), %r13
jge 0xf1a8
movq (%rbx), %rax
addq %r14, %rax
movq (%rax,%r15,8), %rdi
callq 0xe38c
cmpq %rax, %r12
jle 0xf1ab
notq %rax
addq %rax, %r12
setne %al
orb 0x10(%rsp), %al
testb $0x1, %al
je 0xf1c3
incq %r15
decq %rbp
jmp 0xf157
movl $0x1, 0x18(%rbx)
pushq $0x1
popq %rdx
movq %rbx, %rdi
movq %r14, %rsi
jmp 0xf25c
xorl %r12d, %r12d
movq 0x8(%rsp), %r14
movq %r13, %rbp
subq %r14, %rbp
testq %r12, %r12
jne 0xf1e5
movq %r14, %rsi
jmp 0xf256
movq 0x8(%rsp), %r14
movq %r14, %rax
subq 0x8(%rbx), %rax
movq %r14, %r13
subq %rbp, %r13
cmpq %rbp, %rax
jne 0xf1df
xorl %r12d, %r12d
jmp 0xf1b0
negq %rbp
xorl %r12d, %r12d
movq (%rbx), %rax
movq (%rax,%r13,8), %rdi
movq %r12, %rsi
callq 0xe4a6
movq %rax, %r12
movq %rax, %rdi
callq 0xd210
movq %rax, %r13
movq %r14, %r15
movq 0x20(%rsp), %r14
addq %r14, %rax
movq %rax, 0x8(%rsp)
movq (%rbx), %rax
movq (%rax,%r15,8), %rdi
leaq (%r14,%r13), %rsi
incq %rsi
callq 0xd520
movq (%rbx), %rcx
movq %rax, (%rcx,%r15,8)
movq (%rbx), %rax
addq (%rax,%r15,8), %r14
movq %r14, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0xd420
movq (%rbx), %rax
movq (%rax,%r15,8), %rax
movq 0x8(%rsp), %rcx
movb $0x0, (%rax,%rcx)
movq 0x18(%rsp), %rsi
movq %rbx, %rdi
movq %rbp, %rdx
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xf2ad
leaq 0x1b44c(%rip), %rdi     # 0x2a6c2
leaq 0x1b3fb(%rip), %rsi     # 0x2a678
leaq 0x1b44b(%rip), %rcx     # 0x2a6cf
movl $0x34b, %edx            # imm = 0x34B
callq 0xd280
leaq 0x1b47a(%rip), %rdi     # 0x2a70f
leaq 0x1b3dc(%rip), %rsi     # 0x2a678
leaq 0x1b42c(%rip), %rcx     # 0x2a6cf
movl $0x34d, %edx            # imm = 0x34D
callq 0xd280