#include "intrface.h"
 
#include "brender/brender.h"
 
#include "flicplay.h"
 
#include "globvars.h"
 
#include "grafdata.h"
 
#include "graphics.h"
 
#include "harness/trace.h"
 
#include "input.h"
 
#include "loading.h"
 
#include "main.h"
 
#include "pd/sys.h"
 
#include "sound.h"
 
#include <stdlib.h>
 
 
 
int gDisabled_choices[10];
 
int gCurrent_mode;
 
tU32 gStart_time;
 
int gCurrent_choice;
 
tInterface_spec* gSpec;
 
int gAlways_typing;
 
int gDisabled_count;
 
 
 
// IDA: void __cdecl SetAlwaysTyping()
 
void SetAlwaysTyping(void) {
 
    LOG_TRACE("()");
 
 
 
    gAlways_typing = 1;
 
}
 
 
 
// IDA: void __cdecl ClearAlwaysTyping()
 
void ClearAlwaysTyping(void) {
 
    LOG_TRACE("()");
 
 
 
    gAlways_typing = 0;
 
}
 
 
 
// IDA: int __usercall ChoiceDisabled@<EAX>(int pChoice@<EAX>)
 
int ChoiceDisabled(int pChoice) {
 
    int i;
 
    LOG_TRACE("(%d)", pChoice);
 
 
 
    for (i = 0; i < gDisabled_count; ++i) {
 
        if (gDisabled_choices[i] == pChoice) {
 
            return 1;
 
        }
 
    }
 
    return 0;
 
}
 
 
 
// IDA: void __cdecl ResetInterfaceTimeout()
 
void ResetInterfaceTimeout(void) {
 
    LOG_TRACE("()");
 
 
 
    gStart_time = PDGetTotalTime();
 
}
 
 
 
// IDA: void __usercall ChangeSelection(tInterface_spec *pSpec@<EAX>, int *pOld_selection@<EDX>, int *pNew_selection@<EBX>, int pMode@<ECX>, int pSkip_disabled)
 
void ChangeSelection(tInterface_spec* pSpec, int* pOld_selection, int* pNew_selection, int pMode, int pSkip_disabled) {
 
    //int i; // Pierre-Marie Baty -- unused variable
 
    LOG_TRACE("(%p, %p, %p, %d, %d)", pSpec, *pOld_selection, *pNew_selection, pMode, pSkip_disabled);
 
 
 
    if (ChoiceDisabled(*pNew_selection)) {
 
        if (!pSkip_disabled) {
 
            *pNew_selection = *pOld_selection;
 
        } else if (*pOld_selection < *pNew_selection) {
 
            do {
 
                *pNew_selection = *pNew_selection + 1;
 
                if (*pNew_selection < pSpec->move_up_min[pMode]) {
 
                    *pNew_selection = pSpec->move_up_max[pMode];
 
                }
 
                if (*pNew_selection > pSpec->move_up_max[pMode]) {
 
                    *pNew_selection = pSpec->move_up_min[pMode];
 
                }
 
            } while (*pNew_selection != *pOld_selection && ChoiceDisabled(*pNew_selection));
 
        } else {
 
            do {
 
                *pNew_selection = *pNew_selection - 1;
 
                if (*pNew_selection < pSpec->move_up_min[pMode]) {
 
                    *pNew_selection = pSpec->move_up_max[pMode];
 
                }
 
                if (*pNew_selection > pSpec->move_up_max[pMode]) {
 
                    *pNew_selection = pSpec->move_up_min[pMode];
 
                }
 
            } while (*pNew_selection != *pOld_selection && ChoiceDisabled(*pNew_selection));
 
        }
 
    }
 
 
 
    if (*pOld_selection != *pNew_selection) {
 
        if (*pOld_selection >= 0 && *pOld_selection < pSpec->number_of_button_flics) {
 
            if (pSpec->flicker_off_flics[*pOld_selection].flic_index >= 0) {
 
                AddToFlicQueue(pSpec->flicker_off_flics[*pOld_selection].flic_index,
 
                    pSpec->flicker_off_flics[*pOld_selection].x[gGraf_data_index],
 
                    pSpec->flicker_off_flics[*pOld_selection].y[gGraf_data_index], 0);
 
            }
 
        }
 
        if (*pNew_selection >= 0 && *pNew_selection < pSpec->number_of_button_flics) {
 
            if (pSpec->flicker_on_flics[*pNew_selection].flic_index >= 0) {
 
                AddToFlicQueue(pSpec->flicker_on_flics[*pNew_selection].flic_index,
 
                    pSpec->flicker_on_flics[*pNew_selection].x[gGraf_data_index],
 
                    pSpec->flicker_on_flics[*pNew_selection].y[gGraf_data_index], 0);
 
            }
 
        }
 
        *pOld_selection = *pNew_selection;
 
    }
 
}
 
 
 
// IDA: void __usercall RecopyAreas(tInterface_spec *pSpec@<EAX>, br_pixelmap **pCopy_areas@<EDX>)
 
void RecopyAreas(tInterface_spec* pSpec, br_pixelmap** pCopy_areas) {
 
    int i;
 
    LOG_TRACE8("(%p, %p)", pSpec, pCopy_areas);
 
 
 
    for (i = 0; i < pSpec->number_of_recopy_areas; i++) {
 
        BrPixelmapRectangleCopy(
 
            gBack_screen,
 
            pSpec->recopy_areas[i].left[gGraf_data_index],
 
            pSpec->recopy_areas[i].top[gGraf_data_index],
 
            pCopy_areas[i],
 
            0,
 
            0,
 
            pSpec->recopy_areas[i].right[gGraf_data_index] - pSpec->recopy_areas[i].left[gGraf_data_index],
 
            pSpec->recopy_areas[i].bottom[gGraf_data_index] - pSpec->recopy_areas[i].top[gGraf_data_index]);
 
    }
 
}
 
 
 
// IDA: void __usercall DisableChoice(int pChoice@<EAX>)
 
void DisableChoice(int pChoice) {
 
    int i;
 
    LOG_TRACE("(%d)", pChoice);
 
 
 
    for (i = 0; i < gDisabled_count; i++) {
 
        if (gDisabled_choices[i] == pChoice) {
 
            return;
 
        }
 
    }
 
    gDisabled_choices[gDisabled_count] = pChoice;
 
    gDisabled_count++;
 
}
 
 
 
// IDA: void __usercall EnableChoice(int pChoice@<EAX>)
 
void EnableChoice(int pChoice) {
 
    int i;
 
    LOG_TRACE("(%d)", pChoice);
 
 
 
    for (i = 0; i < gDisabled_count; i++) {
 
        if (gDisabled_choices[i] == pChoice) {
 
            memmove(&gDisabled_choices
[i
], &gDisabled_choices
[i 
+ 1], (gDisabled_count 
- i 
- 1) * sizeof(gDisabled_choices
[0]));  
            gDisabled_count--;
 
            break;
 
        }
 
    }
 
}
 
 
 
// IDA: int __usercall DoInterfaceScreen@<EAX>(tInterface_spec *pSpec@<EAX>, int pOptions@<EDX>, int pCurrent_choice@<EBX>)
 
int DoInterfaceScreen(tInterface_spec* pSpec, int pOptions, int pCurrent_choice) {
 
    tProg_status entry_status; //
 
    int x_coord;               //
 
    int y_coord;               //
 
    int mouse_in_somewhere = 0;
 
    int i; //
 
    //int key2; // Pierre-Marie Baty -- unused variable
 
    //int mouse_was_started; // Pierre-Marie Baty -- unused variable
 
    int last_choice; //
 
    int escaped;     //
 
    int timed_out;   //
 
    int go_ahead;    //
 
    //int last_mode; // Pierre-Marie Baty -- unused variable
 
    int result;  //
 
    int the_key; //
 
    int the_max;
 
    int mouse_down;     //
 
    int new_mouse_down; //
 
    int last_mouse_down = 0;
 
    int defeat_mode_change; //
 
    int selection_changed;  //
 
    char the_str[256];
 
    tU32 last_press; //
 
    //tU32 last_left_press; // Pierre-Marie Baty -- unused variable
 
    //tU32 last_right_press; // Pierre-Marie Baty -- unused variable
 
    //tU32 last_up_press; // Pierre-Marie Baty -- unused variable
 
    //tU32 last_down_press; // Pierre-Marie Baty -- unused variable
 
    br_pixelmap** copy_areas;        //
 
    br_pixelmap* old_current_splash; //
 
    //void* pixels_copy; // Pierre-Marie Baty -- unused variable
 
    //void* palette_copy; // Pierre-Marie Baty -- unused variable
 
    LOG_TRACE("(%p, %d, %d)", pSpec, pOptions, pCurrent_choice);
 
 
 
#if defined(DETHRACE_FIX_BUGS)
 
    mouse_down = 0;
 
#endif
 
    entry_status = gProgram_state.prog_status;
 
    gTyping_slot = -1;
 
    EdgeTriggerModeOn();
 
    gSpec = pSpec;
 
    gDisabled_count = 0;
 
    LoadInterfaceStuff(gProgram_state.racing);
 
    gProgram_state.dont_save_or_load = pSpec->dont_save_or_load;
 
    for (i = 0; i < pSpec->number_of_button_flics; i++) {
 
        LoadFlic(pSpec->flicker_on_flics[i].flic_index);
 
        LoadFlic(pSpec->flicker_off_flics[i].flic_index);
 
        LoadFlic(pSpec->pushed_flics[i].flic_index);
 
    }
 
 
 
    InitFlicQueue();
 
    ResetInterfaceTimeout();
 
    gCurrent_choice = pCurrent_choice;
 
    gCurrent_mode = pSpec->initial_imode;
 
    StartMouseCursor();
 
    if (pSpec->font_needed) {
 
        InitRollingLetters();
 
        LoadFont(FONT_TYPEABLE);
 
    }
 
    old_current_splash = gCurrent_splash;
 
    KillSplashScreen();
 
    if (pSpec->start_proc1 != NULL) {
 
        pSpec->start_proc1();
 
    }
 
    if (!gFaded_palette && old_current_splash == NULL && !(pOptions & 2)) {
 
        DRS3StartSound(gEffects_outlet, 3006);
 
    }
 
    if (pOptions & 1) {
 
        if (pSpec->second_opening_flic > 0) {
 
            RunFlic(pSpec->second_opening_flic);
 
        }
 
    } else if (pSpec->first_opening_flic > 0) {
 
        RunFlic(pSpec->first_opening_flic);
 
    }
 
 
 
    if (pSpec->start_proc2 != NULL) {
 
        pSpec->start_proc2();
 
    }
 
 
 
    copy_areas = NULL;
 
    if (pSpec->number_of_recopy_areas != 0) {
 
        copy_areas = BrMemAllocate(sizeof(void*) * pSpec->number_of_recopy_areas, kMem_intf_copy_areas);
 
        for (i = 0; i < pSpec->number_of_recopy_areas; i++) {
 
            copy_areas[i] = BrPixelmapAllocate(BR_MEMORY_PIXELS,
 
                ((pSpec->recopy_areas[i].right[gGraf_data_index] - pSpec->recopy_areas[i].left[gGraf_data_index]) + 3) & ~3,
 
                pSpec->recopy_areas[i].bottom[gGraf_data_index] - pSpec->recopy_areas[i].top[gGraf_data_index],
 
                NULL, 0);
 
        }
 
    }
 
 
 
    last_choice = -1;
 
    ChangeSelection(pSpec, &last_choice, &gCurrent_choice, gCurrent_mode, 0);
 
    WaitForNoKeys();
 
    for (i = 0; i < pSpec->number_of_recopy_areas; i++) {
 
        BrPixelmapRectangleCopy(copy_areas[i], 0, 0, gBack_screen, pSpec->recopy_areas[i].left[gGraf_data_index], pSpec->recopy_areas[i].top[gGraf_data_index],
 
            pSpec->recopy_areas[i].right[gGraf_data_index] - pSpec->recopy_areas[i].left[gGraf_data_index],
 
            pSpec->recopy_areas[i].bottom[gGraf_data_index] - pSpec->recopy_areas[i].top[gGraf_data_index]);
 
    }
 
 
 
    timed_out = -1; /* Not sure this is right, timed_out looks like its used as a bool? */
 
    last_choice = gCurrent_choice;
 
    last_press = -1;
 
    do {
 
        if (last_choice != gCurrent_choice) {
 
            ChangeSelection(pSpec, &last_choice, &gCurrent_choice, gCurrent_mode, 1);
 
        }
 
        last_choice = gCurrent_choice;
 
        PollKeys();
 
        EdgeTriggerModeOff();
 
        the_key = PDAnyKeyDown();
 
        if (the_key != -1 && the_key != KEY_CAPSLOCK) {
 
            gMouse_in_use = 0;
 
            ResetInterfaceTimeout();
 
        }
 
        EdgeTriggerModeOn();
 
        if ((gTyping_slot < 0 || gAlways_typing) && (PDKeyDown(KEY_LEFT) || PDKeyDown(KEY_KP_4) || last_press == KEY_LEFT)) {
 
            last_press = -1;
 
            if (pSpec->move_left_delta[gCurrent_mode] != 0) {
 
                gCurrent_choice += pSpec->move_left_delta[gCurrent_mode];
 
                if (gCurrent_choice < pSpec->move_left_min[gCurrent_mode]) {
 
                    gCurrent_choice = pSpec->move_left_max[gCurrent_mode];
 
                }
 
                if (gCurrent_choice > pSpec->move_left_max[gCurrent_mode]) {
 
                    gCurrent_choice = pSpec->move_left_min[gCurrent_mode];
 
                }
 
                DRS3StartSound(gEffects_outlet, 3000);
 
            }
 
            if (pSpec->move_left_proc[gCurrent_mode] != NULL) {
 
                defeat_mode_change = (pSpec->move_left_proc[gCurrent_mode])(&gCurrent_choice, &gCurrent_mode);
 
            } else {
 
                defeat_mode_change = 0;
 
            }
 
            if (pSpec->move_left_new_mode[gCurrent_mode] >= 0 && !defeat_mode_change) {
 
                gCurrent_mode = pSpec->move_left_new_mode[gCurrent_mode];
 
            }
 
        }
 
        if ((gTyping_slot < 0 || gAlways_typing) && (PDKeyDown(KEY_RIGHT) || PDKeyDown(KEY_KP_6) || last_press == KEY_RIGHT)) {
 
            last_press = -1;
 
            if (pSpec->move_right_delta[gCurrent_mode] != 0) {
 
                gCurrent_choice += pSpec->move_right_delta[gCurrent_mode];
 
                if (gCurrent_choice < pSpec->move_right_min[gCurrent_mode]) {
 
                    gCurrent_choice = pSpec->move_right_max[gCurrent_mode];
 
                }
 
                if (gCurrent_choice > pSpec->move_right_max[gCurrent_mode]) {
 
                    gCurrent_choice = pSpec->move_right_min[gCurrent_mode];
 
                }
 
                DRS3StartSound(gEffects_outlet, 3000);
 
            }
 
            if (pSpec->move_right_proc[gCurrent_mode] != NULL) {
 
                defeat_mode_change = (pSpec->move_right_proc[gCurrent_mode])(&gCurrent_choice, &gCurrent_mode);
 
            } else {
 
                defeat_mode_change = 0;
 
            }
 
            if (pSpec->move_right_new_mode[gCurrent_mode] >= 0 && !defeat_mode_change) {
 
                gCurrent_mode = pSpec->move_right_new_mode[gCurrent_mode];
 
            }
 
        }
 
        if (PDKeyDown(KEY_UP) || PDKeyDown(KEY_KP_8) || last_press == KEY_UP) {
 
            last_press = -1;
 
            if (pSpec->move_up_delta[gCurrent_mode] != 0) {
 
                gCurrent_choice += pSpec->move_up_delta[gCurrent_mode];
 
                if (gCurrent_choice < pSpec->move_up_min[gCurrent_mode]) {
 
                    gCurrent_choice = pSpec->move_up_max[gCurrent_mode];
 
                }
 
                if (gCurrent_choice > pSpec->move_up_max[gCurrent_mode]) {
 
                    gCurrent_choice = pSpec->move_up_min[gCurrent_mode];
 
                }
 
                DRS3StartSound(gEffects_outlet, 3000);
 
            }
 
            if (pSpec->move_up_proc[gCurrent_mode] != NULL) {
 
                defeat_mode_change = (pSpec->move_up_proc[gCurrent_mode])(&gCurrent_choice, &gCurrent_mode);
 
            } else {
 
                defeat_mode_change = 0;
 
            }
 
            if (pSpec->move_up_new_mode[gCurrent_mode] >= 0 && !defeat_mode_change) {
 
                gCurrent_mode = pSpec->move_up_new_mode[gCurrent_mode];
 
            }
 
        }
 
        if (PDKeyDown(KEY_DOWN) || PDKeyDown(KEY_KP_2) || last_press == KEY_DOWN) {
 
            last_press = -1;
 
            if (pSpec->move_down_delta[gCurrent_mode] != 0) {
 
                gCurrent_choice += pSpec->move_down_delta[gCurrent_mode];
 
                if (gCurrent_choice < pSpec->move_down_min[gCurrent_mode]) {
 
                    gCurrent_choice = pSpec->move_down_max[gCurrent_mode];
 
                }
 
                if (gCurrent_choice > pSpec->move_down_max[gCurrent_mode]) {
 
                    gCurrent_choice = pSpec->move_down_min[gCurrent_mode];
 
                }
 
                DRS3StartSound(gEffects_outlet, 3000);
 
            }
 
            if (pSpec->move_down_proc[gCurrent_mode] != NULL) {
 
                defeat_mode_change = (pSpec->move_down_proc[gCurrent_mode])(&gCurrent_choice, &gCurrent_mode);
 
            } else {
 
                defeat_mode_change = 0;
 
            }
 
            if (pSpec->move_down_new_mode[gCurrent_mode] >= 0 && !defeat_mode_change) {
 
                gCurrent_mode = pSpec->move_down_new_mode[gCurrent_mode];
 
            }
 
        }
 
        if (gTyping_slot >= 0 && pSpec->typeable[gCurrent_mode] && gTyping_slot != gCurrent_choice && !gAlways_typing) {
 
            gCurrent_choice = gTyping_slot;
 
        }
 
        if (last_choice == gCurrent_choice) {
 
            selection_changed = 0;
 
        } else {
 
            ChangeSelection(pSpec, &last_choice, &gCurrent_choice, gCurrent_mode, 1);
 
            selection_changed = 1;
 
        }
 
        timed_out = pSpec->time_out && ((tU32) PDGetTotalTime() >= pSpec->time_out + gStart_time); // Pierre-Marie Baty -- added type cast
 
        RemoveTransientBitmaps(1);
 
        RecopyAreas(pSpec, copy_areas);
 
        if (pSpec->font_needed) {
 
            RollLettersIn();
 
        }
 
        ServicePanelFlics(1);
 
        if (pSpec->draw_proc != NULL) {
 
            pSpec->draw_proc(gCurrent_choice, gCurrent_mode);
 
        }
 
        ProcessFlicQueue(gFrame_period);
 
        if (DoMouseCursor() || EitherMouseButtonDown()) {
 
            ResetInterfaceTimeout();
 
        }
 
        PDScreenBufferSwap(0);
 
        if (gMouse_in_use && !selection_changed) {
 
            GetMousePosition(&x_coord, &y_coord);
 
            new_mouse_down = EitherMouseButtonDown();
 
            mouse_down = new_mouse_down && !last_mouse_down;
 
            last_mouse_down = new_mouse_down;
 
 
 
            mouse_in_somewhere = 0;
 
            for (i = 0; i < pSpec->number_of_mouse_areas; i++) {
 
                if (x_coord >= pSpec->mouse_areas[i].left[gGraf_data_index]
 
                    && y_coord >= pSpec->mouse_areas[i].top[gGraf_data_index]
 
                    && x_coord <= pSpec->mouse_areas[i].right[gGraf_data_index]
 
                    && y_coord <= pSpec->mouse_areas[i].bottom[gGraf_data_index]
 
                    && (gTyping_slot < 0 || gAlways_typing || pSpec->mouse_areas[i].available_when_typing || gTyping_slot == pSpec->mouse_areas[i].new_choice)) {
 
 
 
                    if (pSpec->mouse_areas[i].new_choice >= 0 && pSpec->mouse_areas[i].new_choice != gCurrent_choice) {
 
                        gCurrent_choice = pSpec->mouse_areas[i].new_choice;
 
                        ChangeSelection(pSpec, &last_choice, &gCurrent_choice, gCurrent_mode, 0);
 
                    }
 
                    if (pSpec->mouse_areas[i].new_mode >= 0) {
 
                        gCurrent_mode = pSpec->mouse_areas[i].new_mode;
 
                    }
 
 
 
                    if (pSpec->mouse_areas[i].new_mode >= 0 || pSpec->mouse_areas[i].new_choice >= 0) {
 
                        mouse_in_somewhere = 1;
 
                    }
 
                    if (mouse_down) {
 
                        if (pSpec->mouse_areas[i].mouse_click != NULL) {
 
                            mouse_down = pSpec->mouse_areas[i].mouse_click(&gCurrent_choice, &gCurrent_mode,
 
                                x_coord - pSpec->mouse_areas[i].left[gGraf_data_index],
 
                                y_coord - pSpec->mouse_areas[i].top[gGraf_data_index]);
 
                        }
 
                    }
 
                    break;
 
                }
 
            }
 
        }
 
 
 
        if (PDKeyDown(KEY_RETURN) || PDKeyDown(KEY_KP_ENTER) || (gTyping_slot < 0 && PDKeyDown(KEY_SPACE)) || (gMouse_in_use && mouse_in_somewhere && mouse_down)) {
 
            DRS3StartSound(gEffects_outlet, 3004);
 
            go_ahead = pSpec->go_ahead_allowed[gCurrent_mode];
 
            if (pSpec->go_ahead_proc[gCurrent_mode]) {
 
                go_ahead = (pSpec->go_ahead_proc[gCurrent_mode])(&gCurrent_choice, &gCurrent_mode);
 
            }
 
        } else {
 
            go_ahead = 0;
 
        }
 
        if (PDKeyDown(KEY_ESCAPE)) {
 
            DRS3StartSound(gEffects_outlet, 3005);
 
            escaped = pSpec->escape_allowed[gCurrent_mode];
 
            if (pSpec->escape_proc[gCurrent_mode] != NULL) {
 
                escaped = (pSpec->escape_proc[gCurrent_mode])(&gCurrent_choice, &gCurrent_mode);
 
            }
 
        } else {
 
            escaped = 0;
 
        }
 
        if (escaped && gTyping_slot >= 0 && !gAlways_typing) {
 
            pSpec->get_original_string(0, gTyping_slot, the_str, &the_max);
 
            escaped = 0;
 
            RevertTyping(gTyping_slot, the_str);
 
            gTyping = 0;
 
            gTyping_slot = -1;
 
        }
 
        if (go_ahead) {
 
            if (gCurrent_choice >= 0 && gCurrent_choice < pSpec->number_of_button_flics) {
 
                if (pSpec->pushed_flics[gCurrent_choice].flic_index >= 0) {
 
                    AddToFlicQueue(pSpec->pushed_flics[gCurrent_choice].flic_index, pSpec->pushed_flics[gCurrent_choice].x[gGraf_data_index], pSpec->pushed_flics[gCurrent_choice].y[gGraf_data_index], 1);
 
                }
 
            }
 
            if (pSpec->typeable[gCurrent_mode]) {
 
                if (gTyping_slot >= 0 || gAlways_typing) {
 
                    KillCursor(gCurrent_choice);
 
                    RecopyAreas(pSpec, copy_areas);
 
                    RollLettersIn();
 
                    PDScreenBufferSwap(0);
 
                } else {
 
                    gTyping_slot = gCurrent_choice;
 
                    pSpec->get_original_string(1, gCurrent_choice, the_str, &the_max);
 
                    StartTyping(gTyping_slot, the_str, the_max);
 
                    go_ahead = 0;
 
                    gTyping = 1;
 
                }
 
            }
 
        } else if (gTyping_slot >= 0 && !escaped) {
 
            last_press = PDAnyKeyDown();
 
            if (last_press != -1 && (!gAlways_typing || (last_press != KEY_LEFT && last_press != KEY_RIGHT && last_press != KEY_UP && last_press != KEY_DOWN))) {
 
                if (gCurrent_choice != gTyping_slot && !gAlways_typing) {
 
                    ChangeSelection(pSpec, &gCurrent_choice, &gTyping_slot, gCurrent_mode, gAlways_typing);
 
                    for (i = 0; i < 2; i++) {
 
                        if (pSpec->typeable[i]) {
 
                            gCurrent_mode = i;
 
                            break;
 
                        }
 
                    }
 
                }
 
                TypeKey(gAlways_typing ? 0 : gCurrent_choice, last_press);
 
            }
 
        }
 
        ServiceGame();
 
        if (last_choice != gCurrent_choice) {
 
            ChangeSelection(pSpec, &last_choice, &gCurrent_choice, gCurrent_mode, 1);
 
        }
 
        if (entry_status != eProg_idling && gProgram_state.prog_status == eProg_idling) {
 
            escaped = 1;
 
        }
 
    } while ((pSpec->exit_proc == NULL || !(pSpec->exit_proc)(&gCurrent_choice, &gCurrent_mode)) && !go_ahead && !timed_out && !escaped);
 
 
 
    gTyping = 0;
 
    if (pSpec->font_needed) {
 
        EndRollingLetters();
 
        DisposeFont(FONT_TYPEABLE);
 
    }
 
    if (pSpec->number_of_recopy_areas > 0) {
 
        for (i = 0; i < pSpec->number_of_recopy_areas; i++) {
 
            BrPixelmapFree(copy_areas[i]);
 
        }
 
        BrMemFree(copy_areas);
 
    }
 
 
 
    RemoveTransientBitmaps(1);
 
    FlushFlicQueue();
 
    for (i = 0; i < pSpec->number_of_button_flics; i++) {
 
        UnlockFlic(pSpec->flicker_on_flics[i].flic_index);
 
        UnlockFlic(pSpec->flicker_off_flics[i].flic_index);
 
        UnlockFlic(pSpec->pushed_flics[i].flic_index);
 
    }
 
 
 
    if (gCurrent_choice == pSpec->escape_code) {
 
        escaped = 1;
 
        go_ahead = 0;
 
    }
 
    if (escaped) {
 
        gCurrent_choice = pSpec->escape_code;
 
    }
 
    if (pSpec->done_proc != NULL) {
 
        result = (pSpec->done_proc)(gCurrent_choice, gCurrent_mode, go_ahead, escaped, timed_out);
 
    } else {
 
        result = gCurrent_choice;
 
    }
 
    if (go_ahead) {
 
        if (pSpec->end_flic_go_ahead > 0) {
 
            DRS3StartSound(gEffects_outlet, 3007);
 
            RunFlic(pSpec->end_flic_go_ahead);
 
        } else if (pSpec->end_flic_go_ahead < 0) {
 
            FadePaletteDown();
 
        }
 
    } else if (escaped) {
 
        if (pSpec->end_flic_escaped > 0) {
 
            DRS3StartSound(gEffects_outlet, 3007);
 
            RunFlic(pSpec->end_flic_escaped);
 
        } else if (pSpec->end_flic_escaped < 0) {
 
            FadePaletteDown();
 
        }
 
    } else {
 
        if (pSpec->end_flic_otherwise > 0) {
 
            DRS3StartSound(gEffects_outlet, 3007);
 
            RunFlic(pSpec->end_flic_otherwise);
 
        } else if (pSpec->end_flic_otherwise < 0) {
 
            FadePaletteDown();
 
        }
 
    }
 
 
 
    gProgram_state.dont_save_or_load = 0;
 
    EndMouseCursor();
 
    UnlockInterfaceStuff();
 
    EdgeTriggerModeOff();
 
    return result;
 
}
 
 
 
// IDA: void __usercall ChangeSelectionTo(int pNew_choice@<EAX>, int pNew_mode@<EDX>)
 
void ChangeSelectionTo(int pNew_choice, int pNew_mode) {
 
    int last_choice;
 
    LOG_TRACE("(%d, %d)", pNew_choice, pNew_mode);
 
 
 
    last_choice = gCurrent_choice;
 
    gCurrent_choice = pNew_choice;
 
    gCurrent_mode = pNew_mode;
 
    ChangeSelection(gSpec, &last_choice, &gCurrent_choice, pNew_mode, 1);
 
}