// File: Ciaxur[P]yagb-emu/include/imgui/imstb_textedit.h
// Function: ImStb::stb_text_undo(ImGuiInputTextState*, ImStb::STB_TexteditState*)
static void stb_text_undo(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
{
   StbUndoState *s = &state->undostate;
   StbUndoRecord u, *r;
   if (s->undo_point == 0)
      return;

   // we need to do two things: apply the undo record, and create a redo record
   u = s->undo_rec[s->undo_point-1];
   r = &s->undo_rec[s->redo_point-1];
   r->char_storage = -1;

   r->insert_length = u.delete_length;
   r->delete_length = u.insert_length;
   r->where = u.where;

   if (u.delete_length) {
      // if the undo record says to delete characters, then the redo record will
      // need to re-insert the characters that get deleted, so we need to store
      // them.

      // there are three cases:
      //    there's enough room to store the characters
      //    characters stored for *redoing* don't leave room for redo
      //    characters stored for *undoing* don't leave room for redo
      // if the last is true, we have to bail

      if (s->undo_char_point + u.delete_length >= STB_TEXTEDIT_UNDOCHARCOUNT) {
         // the undo records take up too much character space; there's no space to store the redo characters
         r->insert_length = 0;
      } else {
         int i;

         // there's definitely room to store the characters eventually
         while (s->undo_char_point + u.delete_length > s->redo_char_point) {
            // should never happen:
            if (s->redo_point == STB_TEXTEDIT_UNDOSTATECOUNT)
               return;
            // there's currently not enough room, so discard a redo record
            stb_textedit_discard_redo(s);
         }
         r = &s->undo_rec[s->redo_point-1];

         r->char_storage = s->redo_char_point - u.delete_length;
         s->redo_char_point = s->redo_char_point - u.delete_length;

         // now save the characters
         for (i=0; i < u.delete_length; ++i)
            s->undo_char[r->char_storage + i] = STB_TEXTEDIT_GETCHAR(str, u.where + i);
      }

      // now we can carry out the deletion
      STB_TEXTEDIT_DELETECHARS(str, u.where, u.delete_length);
   }

   // check type of recorded action:
   if (u.insert_length) {
      // easy case: was a deletion, so we need to insert n characters
      STB_TEXTEDIT_INSERTCHARS(str, u.where, &s->undo_char[u.char_storage], u.insert_length);
      s->undo_char_point -= u.insert_length;
   }

   state->cursor = u.where + u.insert_length;

   s->undo_point--;
   s->redo_point--;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x10(%rbp), %rax
addq $0x20, %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movswl 0xdfe(%rax), %eax
cmpl $0x0, %eax
jne 0x1591f1
jmp 0x1593e5
movq -0x18(%rbp), %rax
movq -0x18(%rbp), %rcx
movswl 0xdfe(%rcx), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rcx
movq %rcx, -0x28(%rbp)
movq 0x8(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rax
movq -0x18(%rbp), %rcx
movswl 0xe00(%rcx), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movl $0xffffffff, 0xc(%rax)  # imm = 0xFFFFFFFF
movl -0x20(%rbp), %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x4(%rax)
movl -0x24(%rbp), %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0x8(%rax)
movl -0x28(%rbp), %ecx
movq -0x30(%rbp), %rax
movl %ecx, (%rax)
cmpl $0x0, -0x20(%rbp)
je 0x15936e
movq -0x18(%rbp), %rax
movl 0xe04(%rax), %eax
addl -0x20(%rbp), %eax
cmpl $0x3e7, %eax            # imm = 0x3E7
jl 0x159292
movq -0x30(%rbp), %rax
movl $0x0, 0x4(%rax)
jmp 0x15935f
jmp 0x159294
movq -0x18(%rbp), %rax
movl 0xe04(%rax), %eax
addl -0x20(%rbp), %eax
movq -0x18(%rbp), %rcx
cmpl 0xe08(%rcx), %eax
jle 0x1592cd
movq -0x18(%rbp), %rax
movswl 0xe00(%rax), %eax
cmpl $0x63, %eax
jne 0x1592c2
jmp 0x1593e5
movq -0x18(%rbp), %rdi
callq 0x159ee0
jmp 0x159294
movq -0x18(%rbp), %rax
movq -0x18(%rbp), %rcx
movswl 0xe00(%rcx), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movl 0xe08(%rax), %ecx
subl -0x20(%rbp), %ecx
movq -0x30(%rbp), %rax
movl %ecx, 0xc(%rax)
movq -0x18(%rbp), %rax
movl 0xe08(%rax), %ecx
subl -0x20(%rbp), %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0xe08(%rax)
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x20(%rbp), %eax
jge 0x15935d
movq -0x8(%rbp), %rdi
movl -0x28(%rbp), %esi
addl -0x34(%rbp), %esi
callq 0x159a30
movw %ax, %dx
movq -0x18(%rbp), %rax
movq -0x30(%rbp), %rcx
movl 0xc(%rcx), %ecx
addl -0x34(%rbp), %ecx
movslq %ecx, %rcx
movw %dx, 0x630(%rax,%rcx,2)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x15931f
jmp 0x15935f
movq -0x8(%rbp), %rdi
movl -0x28(%rbp), %esi
movl -0x20(%rbp), %edx
callq 0x158e00
cmpl $0x0, -0x24(%rbp)
je 0x1593ad
movq -0x8(%rbp), %rdi
movl -0x28(%rbp), %esi
movq -0x18(%rbp), %rdx
addq $0x630, %rdx            # imm = 0x630
movslq -0x1c(%rbp), %rax
shlq %rax
addq %rax, %rdx
movl -0x24(%rbp), %ecx
callq 0x158ed0
movl -0x24(%rbp), %edx
movq -0x18(%rbp), %rax
movl 0xe04(%rax), %ecx
subl %edx, %ecx
movl %ecx, 0xe04(%rax)
movl -0x28(%rbp), %ecx
addl -0x24(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, (%rax)
movq -0x18(%rbp), %rax
movw 0xdfe(%rax), %cx
addw $-0x1, %cx
movw %cx, 0xdfe(%rax)
movq -0x18(%rbp), %rax
movw 0xe00(%rax), %cx
addw $-0x1, %cx
movw %cx, 0xe00(%rax)
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax,%rax)