// File: donfreiday[P]gb/./imgui/imgui_demo.cpp
// Function: ExampleAppConsole::TextEditCallback(ImGuiTextEditCallbackData*)
int     TextEditCallback(ImGuiTextEditCallbackData* data)
    {
        //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
        switch (data->EventFlag)
        {
        case ImGuiInputTextFlags_CallbackCompletion:
            {
                // Example of TEXT COMPLETION

                // Locate beginning of current word
                const char* word_end = data->Buf + data->CursorPos;
                const char* word_start = word_end;
                while (word_start > data->Buf)
                {
                    const char c = word_start[-1];
                    if (c == ' ' || c == '\t' || c == ',' || c == ';')
                        break;
                    word_start--;
                }

                // Build a list of candidates
                ImVector<const char*> candidates;
                for (int i = 0; i < Commands.Size; i++)
                    if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)
                        candidates.push_back(Commands[i]);

                if (candidates.Size == 0)
                {
                    // No match
                    AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start);
                }
                else if (candidates.Size == 1)
                {
                    // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
                    data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));
                    data->InsertChars(data->CursorPos, candidates[0]);
                    data->InsertChars(data->CursorPos, " ");
                }
                else
                {
                    // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
                    int match_len = (int)(word_end - word_start);
                    for (;;)
                    {
                        int c = 0;
                        bool all_candidates_matches = true;
                        for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
                            if (i == 0)
                                c = toupper(candidates[i][match_len]);
                            else if (c != toupper(candidates[i][match_len]))
                                all_candidates_matches = false;
                        if (!all_candidates_matches)
                            break;
                        match_len++;
                    }

                    if (match_len > 0)
                    {
                        data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
                        data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
                    }

                    // List matches
                    AddLog("Possible matches:\n");
                    for (int i = 0; i < candidates.Size; i++)
                        AddLog("- %s\n", candidates[i]);
                }

                break;
            }
        case ImGuiInputTextFlags_CallbackHistory:
            {
                // Example of HISTORY
                const int prev_history_pos = HistoryPos;
                if (data->EventKey == ImGuiKey_UpArrow)
                {
                    if (HistoryPos == -1)
                        HistoryPos = History.Size - 1;
                    else if (HistoryPos > 0)
                        HistoryPos--;
                }
                else if (data->EventKey == ImGuiKey_DownArrow)
                {
                    if (HistoryPos != -1)
                        if (++HistoryPos >= History.Size)
                            HistoryPos = -1;
                }

                // A better implementation would preserve the data on the current input line along with cursor position.
                if (prev_history_pos != HistoryPos)
                {
                    snprintf(data->Buf, data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : "");
                    data->BufDirty = true;
                    data->CursorPos = data->SelectionStart = data->SelectionEnd = (int)strlen(data->Buf);
                }
            }
        }
        return 0;
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x10(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x68(%rbp)
subl $0x40, %eax
je 0x3bbee
jmp 0x3bbdb
movl -0x68(%rbp), %eax
subl $0x80, %eax
je 0x3bfc9
jmp 0x3c130
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq -0x10(%rbp), %rcx
movslq 0x28(%rcx), %rcx
addq %rcx, %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movq -0x10(%rbp), %rcx
cmpq 0x18(%rcx), %rax
jbe 0x3bc59
movq -0x20(%rbp), %rax
movb -0x1(%rax), %al
movb %al, -0x21(%rbp)
movsbl -0x21(%rbp), %eax
cmpl $0x20, %eax
je 0x3bc49
movsbl -0x21(%rbp), %eax
cmpl $0x9, %eax
je 0x3bc49
movsbl -0x21(%rbp), %eax
cmpl $0x2c, %eax
je 0x3bc49
movsbl -0x21(%rbp), %eax
cmpl $0x3b, %eax
jne 0x3bc4b
jmp 0x3bc59
movq -0x20(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x3bc0d
leaq -0x38(%rbp), %rdi
callq 0x3b390
movl $0x0, -0x3c(%rbp)
movq -0x70(%rbp), %rcx
movl -0x3c(%rbp), %eax
cmpl 0x130(%rcx), %eax
jge 0x3bd13
movq -0x70(%rbp), %rdi
addq $0x130, %rdi            # imm = 0x130
movl -0x3c(%rbp), %esi
callq 0x3c1f0
movq %rax, -0x78(%rbp)
jmp 0x3bc95
movq -0x78(%rbp), %rax
movq (%rax), %rdi
movq -0x20(%rbp), %rsi
movl -0x18(%rbp), %edx
movl %esi, %eax
subl %eax, %edx
callq 0x3c150
movl %eax, -0x7c(%rbp)
jmp 0x3bcb1
movl -0x7c(%rbp), %eax
cmpl $0x0, %eax
jne 0x3bd03
movq -0x70(%rbp), %rdi
addq $0x130, %rdi            # imm = 0x130
movl -0x3c(%rbp), %esi
callq 0x3c1f0
movq %rax, -0x88(%rbp)
jmp 0x3bcd5
movq -0x88(%rbp), %rsi
leaq -0x38(%rbp), %rdi
callq 0x3b440
jmp 0x3bce7
jmp 0x3bd03
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x3b4a0
jmp 0x3c13b
jmp 0x3bd05
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x3bc69
cmpl $0x0, -0x38(%rbp)
jne 0x3bd3d
movq -0x70(%rbp), %rdi
movl -0x18(%rbp), %edx
movq -0x20(%rbp), %rcx
movl %ecx, %eax
subl %eax, %edx
leaq 0x2448e(%rip), %rsi     # 0x601bd
xorl %eax, %eax
callq 0x3b6c0
jmp 0x3bd38
jmp 0x3bfbb
cmpl $0x1, -0x38(%rbp)
jne 0x3bdc9
movq -0x10(%rbp), %rdi
movl -0x20(%rbp), %eax
movl 0x18(%rdi), %ecx
movl %eax, %esi
subl %ecx, %esi
movl -0x18(%rbp), %edx
subl %eax, %edx
callq 0x253d0
jmp 0x3bd61
movq -0x10(%rbp), %rax
movq %rax, -0xa0(%rbp)
movl 0x28(%rax), %eax
movl %eax, -0x94(%rbp)
leaq -0x38(%rbp), %rdi
xorl %esi, %esi
callq 0x3c1f0
movq %rax, -0x90(%rbp)
jmp 0x3bd89
movl -0x94(%rbp), %esi
movq -0xa0(%rbp), %rdi
movq -0x90(%rbp), %rax
movq (%rax), %rdx
xorl %eax, %eax
movl %eax, %ecx
callq 0x25490
jmp 0x3bdab
movq -0x10(%rbp), %rdi
movl 0x28(%rdi), %esi
leaq 0x2be9a(%rip), %rdx     # 0x67c53
xorl %eax, %eax
movl %eax, %ecx
callq 0x25490
jmp 0x3bdc4
jmp 0x3bfb9
movq -0x18(%rbp), %rax
movq -0x20(%rbp), %rcx
subq %rcx, %rax
movl %eax, -0x50(%rbp)
movl $0x0, -0x54(%rbp)
movb $0x1, -0x55(%rbp)
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %ecx
xorl %eax, %eax
cmpl -0x38(%rbp), %ecx
movb %al, -0xa1(%rbp)
jge 0x3be02
movb -0x55(%rbp), %al
movb %al, -0xa1(%rbp)
movb -0xa1(%rbp), %al
testb $0x1, %al
jne 0x3be11
jmp 0x3be9f
cmpl $0x0, -0x5c(%rbp)
jne 0x3be48
movl -0x5c(%rbp), %esi
leaq -0x38(%rbp), %rdi
callq 0x3c1f0
movq %rax, -0xb0(%rbp)
jmp 0x3be2c
movq -0xb0(%rbp), %rax
movq (%rax), %rax
movslq -0x50(%rbp), %rcx
movsbl (%rax,%rcx), %edi
callq 0x7170
movl %eax, -0x54(%rbp)
jmp 0x3be8f
movl -0x54(%rbp), %eax
movl %eax, -0xbc(%rbp)
movl -0x5c(%rbp), %esi
leaq -0x38(%rbp), %rdi
callq 0x3c1f0
movq %rax, -0xb8(%rbp)
jmp 0x3be66
movq -0xb8(%rbp), %rax
movq (%rax), %rax
movslq -0x50(%rbp), %rcx
movsbl (%rax,%rcx), %edi
callq 0x7170
movl %eax, %ecx
movl -0xbc(%rbp), %eax
cmpl %ecx, %eax
je 0x3be8d
movb $0x0, -0x55(%rbp)
jmp 0x3be8f
jmp 0x3be91
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x3bde9
testb $0x1, -0x55(%rbp)
jne 0x3bea7
jmp 0x3beb5
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x3bdd7
cmpl $0x0, -0x50(%rbp)
jle 0x3bf54
movq -0x10(%rbp), %rdi
movl -0x20(%rbp), %eax
movl 0x18(%rdi), %ecx
movl %eax, %esi
subl %ecx, %esi
movl -0x18(%rbp), %edx
subl %eax, %edx
callq 0x253d0
jmp 0x3bed9
movq -0x10(%rbp), %rax
movq %rax, -0xd8(%rbp)
movl 0x28(%rax), %eax
movl %eax, -0xcc(%rbp)
leaq -0x38(%rbp), %rdi
xorl %esi, %esi
callq 0x3c1f0
movq %rax, -0xc8(%rbp)
jmp 0x3bf01
movq -0xc8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xe8(%rbp)
leaq -0x38(%rbp), %rdi
xorl %esi, %esi
callq 0x3c1f0
movq %rax, -0xe0(%rbp)
jmp 0x3bf26
movq -0xe8(%rbp), %rdx
movl -0xcc(%rbp), %esi
movq -0xd8(%rbp), %rdi
movq -0xe0(%rbp), %rax
movq (%rax), %rcx
movslq -0x50(%rbp), %rax
addq %rax, %rcx
callq 0x25490
jmp 0x3bf52
jmp 0x3bf54
movq -0x70(%rbp), %rdi
leaq 0x24274(%rip), %rsi     # 0x601d3
xorl %eax, %eax
callq 0x3b6c0
jmp 0x3bf68
movl $0x0, -0x60(%rbp)
movl -0x60(%rbp), %eax
cmpl -0x38(%rbp), %eax
jge 0x3bfb7
movl -0x60(%rbp), %esi
leaq -0x38(%rbp), %rdi
callq 0x3c1f0
movq %rax, -0xf0(%rbp)
jmp 0x3bf8c
movq -0x70(%rbp), %rdi
movq -0xf0(%rbp), %rax
movq (%rax), %rdx
leaq 0x24245(%rip), %rsi     # 0x601e6
xorl %eax, %eax
callq 0x3b6c0
jmp 0x3bfaa
jmp 0x3bfac
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x3bf6f
jmp 0x3bfb9
jmp 0x3bfbb
leaq -0x38(%rbp), %rdi
callq 0x3b4a0
jmp 0x3c130
movq -0x70(%rbp), %rax
movl 0x128(%rax), %eax
movl %eax, -0x64(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x3, 0x14(%rax)
jne 0x3c026
movq -0x70(%rbp), %rax
cmpl $-0x1, 0x128(%rax)
jne 0x3c002
movq -0x70(%rbp), %rax
movl 0x118(%rax), %ecx
subl $0x1, %ecx
movl %ecx, 0x128(%rax)
jmp 0x3c024
movq -0x70(%rbp), %rax
cmpl $0x0, 0x128(%rax)
jle 0x3c022
movq -0x70(%rbp), %rax
movl 0x128(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x128(%rax)
jmp 0x3c024
jmp 0x3c06c
movq -0x10(%rbp), %rax
cmpl $0x4, 0x14(%rax)
jne 0x3c06a
movq -0x70(%rbp), %rax
cmpl $-0x1, 0x128(%rax)
je 0x3c068
movq -0x70(%rbp), %rcx
movl 0x128(%rcx), %eax
addl $0x1, %eax
movl %eax, 0x128(%rcx)
cmpl 0x118(%rcx), %eax
jl 0x3c066
movq -0x70(%rbp), %rax
movl $0xffffffff, 0x128(%rax) # imm = 0xFFFFFFFF
jmp 0x3c068
jmp 0x3c06a
jmp 0x3c06c
movq -0x70(%rbp), %rcx
movl -0x64(%rbp), %eax
cmpl 0x128(%rcx), %eax
je 0x3c12e
movq -0x70(%rbp), %rax
movq -0x10(%rbp), %rcx
movq 0x18(%rcx), %rcx
movq %rcx, -0x100(%rbp)
movq -0x10(%rbp), %rcx
movslq 0x20(%rcx), %rcx
movq %rcx, -0xf8(%rbp)
cmpl $0x0, 0x128(%rax)
jl 0x3c0cf
movq -0x70(%rbp), %rax
movq %rax, %rdi
addq $0x118, %rdi            # imm = 0x118
movl 0x128(%rax), %esi
callq 0x3b520
movq (%rax), %rax
movq %rax, -0x108(%rbp)
jmp 0x3c0df
leaq 0x23178(%rip), %rax     # 0x5f24e
movq %rax, -0x108(%rbp)
jmp 0x3c0df
movq -0xf8(%rbp), %rsi
movq -0x100(%rbp), %rdi
movq -0x108(%rbp), %rcx
leaq 0x2414a(%rip), %rdx     # 0x60245
movb $0x0, %al
callq 0x7400
movq -0x10(%rbp), %rax
movb $0x1, 0x24(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x7330
movl %eax, %ecx
movq -0x10(%rbp), %rax
movl %ecx, 0x30(%rax)
movq -0x10(%rbp), %rax
movl %ecx, 0x2c(%rax)
movq -0x10(%rbp), %rax
movl %ecx, 0x28(%rax)
jmp 0x3c130
xorl %eax, %eax
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
movq -0x48(%rbp), %rdi
callq 0x74f0
nopw %cs:(%rax,%rax)
nop