#include "input.h"
 
 
 
#include "brender/brender.h"
 
#include "errors.h"
 
#include "globvars.h"
 
#include "grafdata.h"
 
#include "graphics.h"
 
#include "harness/hooks.h"
 
#include "harness/trace.h"
 
#include "pd/sys.h"
 
#include "utility.h"
 
#include <stdlib.h>
 
 
 
int gEdge_trigger_mode;
 
tU32 gLast_poll_keys;
 
int gInsert_mode;
 
int gGo_ahead_keys[3] = { 51, 52, 106 }; // enter, return, space
 
tJoy_array gJoy_array;
 
tKey_array gKey_array;
 
int gKey_poll_counter;
 
tRolling_letter* gRolling_letters;
 
int gCurrent_cursor;
 
int gCurrent_position;
 
int gLetter_x_coords[15];
 
int gVisible_length;
 
int gLetter_y_coords[15];
 
int gThe_key;
 
tU32 gLast_key_down_time;
 
int gThe_length;
 
tU32 gLast_roll;
 
int gLast_key_down;
 
int gKey_mapping[67];
 
char gCurrent_typing[110];
 
 
 
#define NBR_ROLLING_LETTERS 500
 
 
 
// IDA: void __usercall SetJoystickArrays(int *pKeys@<EAX>, int pMark@<EDX>)
 
void SetJoystickArrays(int* pKeys, int pMark) {
 
    //int i; // Pierre-Marie Baty -- unused variable
 
    //tS32 joyX; // Pierre-Marie Baty -- unused variable
 
    //tS32 joyY; // Pierre-Marie Baty -- unused variable
 
    //static tS32 old_joy1X; // Pierre-Marie Baty -- unused variable
 
    //static tS32 old_joy1Y; // Pierre-Marie Baty -- unused variable
 
    //static tS32 old_joy2X; // Pierre-Marie Baty -- unused variable
 
    //static tS32 old_joy2Y; // Pierre-Marie Baty -- unused variable
 
}
 
 
 
// IDA: void __cdecl PollKeys()
 
void PollKeys(void) {
 
 
 
    gKey_poll_counter++;
 
    PDSetKeyArray(gKey_array, gKey_poll_counter);
 
    SetJoystickArrays(gKey_array, gKey_poll_counter);
 
    gLast_poll_keys = PDGetTotalTime();
 
}
 
 
 
// IDA: void __cdecl CyclePollKeys()
 
void CyclePollKeys(void) {
 
    int i;
 
    for (i = 0; i < COUNT_OF(gKey_array); i++) {
 
        if (gKey_array[i] > gKey_poll_counter) {
 
            gKey_array[i] = 0;
 
            if (i > 115) {
 
                gJoy_array[i - 115] = -1; // yes this is a little weird I know...
 
            }
 
        }
 
    }
 
    gKey_poll_counter = 0;
 
}
 
 
 
// IDA: void __cdecl ResetPollKeys()
 
void ResetPollKeys(void) {
 
    int i;
 
    for (i = 0; i < COUNT_OF(gKey_array); i++) {
 
        gKey_array[i] = 0;
 
    }
 
    for (i = 0; i < COUNT_OF(gJoy_array); i++) {
 
        gJoy_array[i] = -1;
 
    }
 
}
 
 
 
// IDA: void __cdecl CheckKeysForMouldiness()
 
void CheckKeysForMouldiness(void) {
 
    LOG_TRACE9("()");
 
 
 
    if (PDGetTotalTime() - gLast_poll_keys > 500) {
 
        ResetPollKeys();
 
        CyclePollKeys();
 
        PollKeys();
 
    }
 
}
 
 
 
// IDA: int __cdecl EitherMouseButtonDown()
 
int EitherMouseButtonDown(void) {
 
    int but_1;
 
    int but_2;
 
 
 
    PDMouseButtons(&but_1, &but_2);
 
    return but_1 || but_2;
 
}
 
 
 
// IDA: tKey_down_result __usercall PDKeyDown2@<EAX>(int pKey_index@<EAX>)
 
tKey_down_result PDKeyDown2(int pKey_index) {
 
    tU32 the_time;
 
 
 
    CheckKeysForMouldiness();
 
    if (!gEdge_trigger_mode) {
 
        return gKey_array[pKey_index];
 
    }
 
    the_time = PDGetTotalTime();
 
    if (gKey_array[pKey_index]) {
 
        if (gLast_key_down == pKey_index) {
 
            if (the_time - gLast_key_down_time < 300) {
 
                return tKey_down_still;
 
            } else {
 
                gLast_key_down_time = the_time;
 
                return tKey_down_repeat;
 
            }
 
        } else {
 
            gLast_key_down_time = the_time;
 
            gLast_key_down = pKey_index;
 
            return tKey_down_yes;
 
        }
 
    }
 
    if (gLast_key_down == pKey_index) {
 
        gLast_key_down_time = 0;
 
        gLast_key_down = -1;
 
    }
 
    return tKey_down_no;
 
}
 
 
 
// IDA: int __usercall PDKeyDown@<EAX>(int pKey_index@<EAX>)
 
int PDKeyDown(int pKey_index) {
 
    tKey_down_result result;
 
 
 
    result = PDKeyDown2(pKey_index);
 
    if (!gEdge_trigger_mode || pKey_index <= 10) {
 
        return result != tKey_down_no;
 
    }
 
    return result == tKey_down_yes || result == tKey_down_repeat;
 
}
 
 
 
// IDA: int __usercall PDKeyDown3@<EAX>(int pKey_index@<EAX>)
 
int PDKeyDown3(int pKey_index) {
 
    int last_key_down_time;
 
    int last_key_down;
 
    tKey_down_result result;
 
    LOG_TRACE("(%d)", pKey_index);
 
 
 
    last_key_down = gLast_key_down;
 
    last_key_down_time = gLast_key_down_time;
 
    result = PDKeyDown2(pKey_index);
 
    gLast_key_down_time = last_key_down_time;
 
    gLast_key_down = last_key_down;
 
    return result == tKey_down_yes || result == tKey_down_repeat;
 
}
 
 
 
// IDA: int __cdecl PDAnyKeyDown()
 
int PDAnyKeyDown(void) {
 
    int i;
 
    tKey_down_result result;
 
 
 
    CheckKeysForMouldiness();
 
    for (i = COUNT_OF(gKey_array) - 1; i >= 0; --i) {
 
        if (gKey_array[i]) {
 
            if (!gEdge_trigger_mode) {
 
                return i;
 
            }
 
            result = PDKeyDown2(i);
 
            switch (result) {
 
            case tKey_down_no:
 
            case tKey_down_still:
 
                return -1;
 
            case tKey_down_yes:
 
            case tKey_down_repeat:
 
                return i;
 
            }
 
        }
 
    }
 
    if (gEdge_trigger_mode) {
 
        gLast_key_down_time = 0;
 
        gLast_key_down = -1;
 
    }
 
    return -1;
 
}
 
 
 
// IDA: int __cdecl AnyKeyDown()
 
int AnyKeyDown(void) {
 
    int the_key;
 
 
 
    the_key = PDAnyKeyDown();
 
    if ((the_key != -1 && the_key != 4) || EitherMouseButtonDown() != 0) {
 
        return 1;
 
    }
 
    return 0;
 
}
 
 
 
// IDA: tU32* __cdecl KevKeyService()
 
tU32* KevKeyService(void) {
 
    static tU32 sum = 0;
 
    static tU32 code = 0;
 
    static tU32 code2 = 0;
 
    static int last_key = -1;
 
    static int last_single_key = -1;
 
    static tU32 last_time = 0;
 
    static tU32 return_val[2];
 
    tU32 keys;
 
 
 
    keys = gKeys_pressed;
 
    // printf("key: %d, %lx, %lx\n", sizeof(long), keys, code2);
 
    return_val[0] = 0;
 
    return_val[1] = 0;
 
 
 
    if (keys < 0x6B) {
 
        last_single_key = gKeys_pressed;
 
    } else {
 
        if (keys > 0x6b00) {
 
            sum = 0;
 
            code = 0;
 
            return return_val;
 
        }
 
        if ((keys & 0xff) != last_single_key && keys >> 8 != last_single_key) {
 
            sum = 0;
 
            code = 0;
 
            return return_val;
 
        }
 
        if (keys >> 8 != last_single_key) {
 
            sum = 0;
 
            code = 0;
 
            return return_val;
 
        }
 
        if ((keys & 0xff) == last_single_key) {
 
            keys = keys >> 8;
 
        }
 
        keys = keys & 0xff;
 
    }
 
 
 
    if (keys && keys != last_key) {
 
        sum += keys;
 
        code += keys << 11;
 
        code = (code >> 17) + (code << 4);
 
        code2 = (code2 >> 29) + keys * keys + (code2 << 3);
 
        // printf("accumulate: keys=%lx, sum=%lx, code=%lx, code2=%lx\n", keys, sum, code, code2);
 
        last_time = PDGetTotalTime();
 
    } else if ((tU32) PDGetTotalTime() > (last_time + 1000)) { // Pierre-Marie Baty -- added type cast
 
        return_val[0] = ((code >> 11) + (sum << 21));
 
        return_val[1] = code2;
 
        // printf("final value: code=%lx, code2=%lx\n", return_val[0], return_val[1]);
 
        code = 0;
 
        code2 = 0;
 
        sum = 0;
 
    }
 
    last_key = keys;
 
    return return_val;
 
}
 
 
 
// IDA: int __usercall OldKeyIsDown@<EAX>(int pKey_index@<EAX>)
 
int OldKeyIsDown(int pKey_index) {
 
    int i;
 
    LOG_TRACE("(%d)", pKey_index);
 
 
 
    switch (pKey_index) {
 
    case -2:
 
        return 1;
 
    case -1:
 
        for (i = 0; i < COUNT_OF(gGo_ahead_keys); i++) {
 
            if (PDKeyDown(gGo_ahead_keys[i]) != 0) {
 
                return 1;
 
            }
 
        }
 
        return 0;
 
    default:
 
        return PDKeyDown(gKey_mapping[pKey_index]);
 
    }
 
}
 
 
 
// IDA: int __usercall KeyIsDown@<EAX>(int pKey_index@<EAX>)
 
int KeyIsDown(int pKey_index) {
 
    int i;
 
 
 
    CheckKeysForMouldiness();
 
    switch (pKey_index) {
 
    case -2:
 
        return 1;
 
    case -1:
 
        for (i = 0; i < COUNT_OF(gGo_ahead_keys); i++) {
 
            if (gKey_array[gGo_ahead_keys[i]]) {
 
                return 1;
 
            }
 
        }
 
        return 0;
 
    default:
 
        return gKey_array[gKey_mapping[pKey_index]];
 
    }
 
}
 
 
 
// IDA: void __cdecl WaitForNoKeys()
 
void WaitForNoKeys(void) {
 
    LOG_TRACE("()");
 
 
 
    while (AnyKeyDown() || EitherMouseButtonDown()) {
 
        CheckQuit();
 
    }
 
    CheckQuit();
 
}
 
 
 
// IDA: void __cdecl WaitForAKey()
 
void WaitForAKey(void) {
 
    LOG_TRACE("()");
 
 
 
    while (1) {
 
        CheckQuit();
 
        if (AnyKeyDown()) {
 
            break;
 
        }
 
        if (EitherMouseButtonDown()) {
 
            break;
 
        }
 
    }
 
    CheckQuit();
 
    WaitForNoKeys();
 
}
 
 
 
// IDA: int __usercall CmdKeyDown@<EAX>(int pFKey_ID@<EAX>, int pCmd_key_ID@<EDX>)
 
int CmdKeyDown(int pFKey_ID, int pCmd_key_ID) {
 
    return KeyIsDown(pFKey_ID) || (KeyIsDown(KEYMAP_CONTROL_ANY) && KeyIsDown(pCmd_key_ID));
 
}
 
 
 
// IDA: void __usercall GetMousePosition(int *pX_coord@<EAX>, int *pY_coord@<EDX>)
 
void GetMousePosition(int* pX_coord, int* pY_coord) {
 
    //int x_left_margin; // Pierre-Marie Baty -- unused variable
 
    //int x_right_margin; // Pierre-Marie Baty -- unused variable
 
    //int y_top_margin; // Pierre-Marie Baty -- unused variable
 
    //int y_bottom_margin; // Pierre-Marie Baty -- unused variable
 
    LOG_TRACE("(%p, %p)", pX_coord, pY_coord);
 
 
 
    PDGetMousePosition(pX_coord, pY_coord);
 
    if (*pX_coord < 0) {
 
        *pX_coord = 0;
 
    } else if (gGraf_specs[gGraf_spec_index].total_width < *pX_coord) {
 
        *pX_coord = gGraf_specs[gGraf_spec_index].total_width;
 
    }
 
    if (*pY_coord < 0) {
 
        *pY_coord = 0;
 
    } else if (gGraf_specs[gGraf_spec_index].total_height < *pY_coord) {
 
        *pY_coord = gGraf_specs[gGraf_spec_index].total_height;
 
    }
 
}
 
 
 
// IDA: void __cdecl InitRollingLetters()
 
void InitRollingLetters(void) {
 
    int i;
 
    LOG_TRACE("()");
 
 
 
    gLast_roll = 0;
 
    gCurrent_cursor = -1;
 
    gRolling_letters = BrMemAllocate(NBR_ROLLING_LETTERS * sizeof(tRolling_letter), kMem_rolling_letters);
 
    for (i = 0; i < NBR_ROLLING_LETTERS; i++) {
 
        gRolling_letters[i].number_of_letters = -1;
 
    }
 
}
 
 
 
// IDA: void __cdecl EndRollingLetters()
 
void EndRollingLetters(void) {
 
    LOG_TRACE("()");
 
 
 
    BrMemFree(gRolling_letters);
 
}
 
 
 
// IDA: int __usercall AddRollingLetter@<EAX>(char pChar@<EAX>, int pX@<EDX>, int pY@<EBX>, tRolling_type rolling_type@<ECX>)
 
int AddRollingLetter(char pChar, int pX, int pY, tRolling_type rolling_type) {
 
    tRolling_letter* let;
 
    int i;
 
    //int number_of_letters; // Pierre-Marie Baty -- unused variable
 
    LOG_TRACE("(%d, %d, %d, %d)", pChar, pX, pY, rolling_type);
 
 
 
    let = &gRolling_letters[0];
 
    for (i = 0; i < NBR_ROLLING_LETTERS; i++) {
 
        let = &gRolling_letters[i];
 
        if (let->number_of_letters < 0) {
 
            break;
 
        }
 
    }
 
    if (i == NBR_ROLLING_LETTERS) {
 
        LOG_WARN("no rolling slot available");
 
        return -1;
 
    }
 
    let->x_coord = pX;
 
    let->y_coord = pY;
 
    let->rolling_type = rolling_type;
 
    switch (rolling_type) {
 
    case eRT_looping_random:
 
        let->number_of_letters = 9;
 
        break;
 
    case eRT_looping_single:
 
        let->number_of_letters = 2;
 
        break;
 
    default:
 
        let->number_of_letters = IRandomBetween(3, 9);
 
        break;
 
    }
 
 
 
    let->current_offset = (gCurrent_graf_data->save_slot_letter_height * let->number_of_letters);
 
    for (i = 0; i < let->number_of_letters; i++) {
 
        if (rolling_type == eRT_numeric) {
 
            /* The (tU8) cast makes sure extended ASCII is positive. */
 
            let->letters[i] = (tU8)pChar;
 
        } else {
 
            let->letters[i] = IRandomBetween('A', 'Z' + 1);
 
        }
 
    }
 
    if (rolling_type != eRT_looping_random) {
 
        /* The (tU8) cast makes sure extended ASCII is positive. */
 
        let->letters[0] = (tU8)pChar;
 
    }
 
 
 
    return 0;
 
}
 
 
 
// IDA: void __usercall AddRollingString(char *pStr@<EAX>, int pX@<EDX>, int pY@<EBX>, tRolling_type rolling_type@<ECX>)
 
void AddRollingString(char* pStr, int pX, int pY, tRolling_type rolling_type) {
 
    size_t i; // Pierre-Marie Baty -- fixed type
 
    LOG_TRACE("(\"%s\", %d, %d, %d)", pStr, pX, pY, rolling_type);
 
 
 
    for (i 
= 0; i 
< strlen(pStr
); i
++) {  
        AddRollingLetter(pStr[i], pX, pY, rolling_type);
 
        pX += gCurrent_graf_data->rolling_letter_x_pitch;
 
    }
 
}
 
 
 
// IDA: void __usercall AddRollingNumber(tU32 pNumber@<EAX>, int pWidth@<EDX>, int pX@<EBX>, int pY@<ECX>)
 
void AddRollingNumber(tU32 pNumber, int pWidth, int pX, int pY) {
 
    char the_string[32];
 
    LOG_TRACE("(%d, %d, %d, %d)", pNumber, pWidth, pX, pY);
 
 
 
    sprintf(the_string
, VARLZEROINT
, pWidth
, pNumber
);  
    AddRollingString(the_string, pX, pY, eRT_numeric);
 
}
 
 
 
// IDA: void __cdecl RollLettersIn()
 
void RollLettersIn(void) {
 
    tU32 new_time;
 
    tU32 period;
 
    tRolling_letter* let;
 
    int i;
 
    int j;
 
    int k;
 
    int offset;
 
    int which_letter;
 
    int font_width;
 
    int letter_offset;
 
    int font_height;
 
    int the_row_bytes;
 
    tU8* char_ptr;
 
    tU8* saved_char_ptr;
 
    tU8* source_ptr;
 
    tU8 the_byte;
 
    LOG_TRACE9("()");
 
 
 
    new_time = PDGetTotalTime();
 
    if (gLast_roll) {
 
        period = new_time - gLast_roll;
 
    } else {
 
        period = 0;
 
    }
 
    font_height = gFonts[FONT_TYPEABLE].height;
 
    font_width = gFonts[FONT_TYPEABLE].width;
 
    the_row_bytes = gFonts[FONT_TYPEABLE].images->row_bytes;
 
 
 
    for (i = 0; i < NBR_ROLLING_LETTERS; i++) {
 
        let = &gRolling_letters[i];
 
        if (let->number_of_letters >= 0) {
 
            char_ptr = gBack_screen->pixels;
 
            char_ptr += let->y_coord * gBack_screen->row_bytes + let->x_coord;
 
            if (let->current_offset > 0.0f) {
 
                let->current_offset -= period * 0.18f;
 
                if (let->current_offset <= 0.0f) {
 
                    if (let->rolling_type == eRT_looping_random || let->rolling_type == eRT_looping_single) {
 
                        let->current_offset = (gCurrent_graf_data->save_slot_letter_height * let->number_of_letters) + let->current_offset;
 
                    } else {
 
                        let->current_offset = 0.0f;
 
                    }
 
                }
 
            }
 
            for (j = 0; j < gCurrent_graf_data->save_slot_height; j++) {
 
                offset = gCurrent_graf_data->save_slot_table[j] + let->current_offset;
 
                which_letter = offset / gCurrent_graf_data->save_slot_letter_height;
 
                letter_offset = offset % gCurrent_graf_data->save_slot_letter_height - (gCurrent_graf_data->save_slot_letter_height - font_height) / 2;
 
                saved_char_ptr = char_ptr;
 
                if (which_letter < let->number_of_letters && which_letter >= 0 && letter_offset >= 0 && letter_offset < font_height) {
 
 
 
                    // LOG_DEBUG("chars %d, %d, %d, %d", let->letters[0], let->letters[1], let->letters[2], let->letters[3]);
 
                    source_ptr = (tU8*)gFonts[FONT_TYPEABLE].images->pixels + (font_height * (let->letters[which_letter] - ' ') + letter_offset) * the_row_bytes;
 
                    for (k = 0; k < font_width; k++) {
 
                        the_byte = *source_ptr;
 
                        if (the_byte) {
 
                            *char_ptr = the_byte;
 
                        }
 
                        char_ptr++;
 
                        source_ptr++;
 
                    }
 
                }
 
                char_ptr = saved_char_ptr + gBack_screen->row_bytes;
 
            }
 
        }
 
    }
 
    gLast_roll = new_time;
 
}
 
 
 
// IDA: int __usercall ChangeCharTo@<EAX>(int pSlot_index@<EAX>, int pChar_index@<EDX>, char pNew_char@<EBX>)
 
int ChangeCharTo(int pSlot_index, int pChar_index, char pNew_char) {
 
    int x_coord;
 
    int y_coord;
 
    int i;
 
    //int j; // Pierre-Marie Baty -- unused variable
 
    tRolling_letter* let;
 
    tRolling_type new_type;
 
    LOG_TRACE("(%d, %d, %d)", pSlot_index, pChar_index, pNew_char);
 
 
 
    if (pChar_index >= gVisible_length || pChar_index < 0) {
 
        return -1;
 
    }
 
    y_coord = gLetter_y_coords[pSlot_index];
 
    x_coord = gCurrent_graf_data->rolling_letter_x_pitch * pChar_index + gLetter_x_coords[pSlot_index];
 
 
 
    if (pNew_char == ROLLING_LETTER_LOOP_RANDOM) {
 
        new_type = eRT_looping_random;
 
    } else if (pNew_char >= '0' && pNew_char <= '9') {
 
        new_type = eRT_numeric;
 
    } else {
 
        new_type = eRT_alpha;
 
    }
 
 
 
    for (i = 0; i < NBR_ROLLING_LETTERS; i++) {
 
        let = &gRolling_letters[i];
 
        if (let->number_of_letters >= 0 && x_coord == let->x_coord && y_coord == let->y_coord) {
 
            break;
 
        }
 
    }
 
    if (i >= NBR_ROLLING_LETTERS) {
 
        return AddRollingLetter(pNew_char, x_coord, y_coord, new_type);
 
    }
 
    if (pNew_char != ROLLING_LETTER_LOOP_RANDOM) {
 
        /* The (tU8) cast makes sure extended ASCII is positive. */
 
        let->letters[0] = (tU8)pNew_char;
 
    }
 
    if (pNew_char == ' ') {
 
        let->letters[0] = ' ';
 
    }
 
    let->rolling_type = new_type;
 
    let->current_offset = gCurrent_graf_data->save_slot_letter_height * let->number_of_letters;
 
    return i;
 
}
 
 
 
// IDA: void __usercall ChangeTextTo(int pXcoord@<EAX>, int pYcoord@<EDX>, char *pNew_str@<EBX>, char *pOld_str@<ECX>)
 
void ChangeTextTo(int pXcoord, int pYcoord, char* pNew_str, char* pOld_str) {
 
    int x_coord;
 
    int i;
 
    int len;
 
    int len2;
 
    int j;
 
    tRolling_letter* let;
 
    tRolling_type new_type;
 
    char new_char;
 
    LOG_TRACE("(%d, %d, \"%s\", \"%s\")", pXcoord, pYcoord, pNew_str, pOld_str);
 
 
 
#if defined(DETHRACE_FIX_BUGS)
 
    new_type = eRT_looping_random;
 
#endif
 
 
 
    for (i = 0; i < len; i++) {
 
        if (i < len2) {
 
            new_char = pNew_str[i];
 
        } else {
 
            new_char = ' ';
 
        }
 
        if (new_char == ROLLING_LETTER_LOOP_RANDOM) {
 
            new_type = eRT_looping_random;
 
        } else if (new_char >= '0' && new_char <= '9') {
 
            new_type = eRT_numeric;
 
        } else {
 
            new_type = eRT_alpha;
 
        }
 
        x_coord = gCurrent_graf_data->rolling_letter_x_pitch * i + pXcoord;
 
        for (j = 0, let = gRolling_letters; j < NBR_ROLLING_LETTERS; j++, let++) {
 
            if (let->number_of_letters >= 0 && let->x_coord == x_coord && let->y_coord == pYcoord) {
 
                if (new_char != ROLLING_LETTER_LOOP_RANDOM) {
 
                    let->letters[0] = new_char;
 
                }
 
                if (new_char == ' ') {
 
                    let->letters[0] = ' ';
 
                }
 
                let->current_offset = let->number_of_letters * gCurrent_graf_data->save_slot_letter_height;
 
                let->rolling_type = new_type;
 
            }
 
        }
 
    }
 
    for (i = len; i < len2; i++) {
 
        AddRollingLetter(pNew_str[i], gCurrent_graf_data->rolling_letter_x_pitch * i + pXcoord, pYcoord, new_type);
 
    }
 
}
 
 
 
// IDA: void __usercall SetRollingCursor(int pSlot_index@<EAX>)
 
void SetRollingCursor(int pSlot_index) {
 
    LOG_TRACE("(%d)", pSlot_index);
 
 
 
    gCurrent_cursor = ChangeCharTo(pSlot_index, gCurrent_position, ROLLING_LETTER_LOOP_RANDOM);
 
}
 
 
 
// IDA: void __usercall BlankSlot(int pIndex@<EAX>, int pName_length@<EDX>, int pVisible_length@<EBX>)
 
void BlankSlot(int pIndex, int pName_length, int pVisible_length) {
 
    int i;
 
    LOG_TRACE("(%d, %d, %d)", pIndex, pName_length, pVisible_length);
 
 
 
    gVisible_length = pVisible_length;
 
    for (i = 0; i < pName_length; i++) {
 
        ChangeCharTo(pIndex, i, ' ');
 
    }
 
}
 
 
 
// IDA: void __usercall DoRLBackspace(int pSlot_index@<EAX>)
 
void DoRLBackspace(int pSlot_index) {
 
    int i;
 
    int new_len;
 
    LOG_TRACE("(%d)", pSlot_index);
 
 
 
    if (gCurrent_position != 0) {
 
        if (strlen(gCurrent_typing
) == gCurrent_position
) {  
            new_len 
= strlen(gCurrent_typing
); 
        } else {
 
            new_len 
= strlen(gCurrent_typing
) - 1; 
        }
 
        ChangeCharTo(pSlot_index, new_len, ' ');
 
        new_len 
= strlen(gCurrent_typing
) - 1; 
        for (i = gCurrent_position - 1; i < new_len; i++) {
 
            ChangeCharTo(pSlot_index, i, gCurrent_typing[i]);
 
            gCurrent_typing[i] = gCurrent_typing[i + 1];
 
        }
 
        gCurrent_typing[new_len] = 0;
 
        gCurrent_position = gCurrent_position - 1;
 
        SetRollingCursor(pSlot_index);
 
    }
 
}
 
 
 
// IDA: void __usercall DoRLDelete(int pSlot_index@<EAX>)
 
void DoRLDelete(int pSlot_index) {
 
    int i;
 
    int new_len;
 
    LOG_TRACE("(%d)", pSlot_index);
 
 
 
    if (gCurrent_position 
<= ((int)strlen(gCurrent_typing
) - 1)) {  
        new_len 
= strlen(gCurrent_typing
) - 1; 
        ChangeCharTo(pSlot_index, new_len, ' ');
 
        for (i = gCurrent_position; i < new_len; i++) {
 
            gCurrent_typing[i] = gCurrent_typing[i + 1];
 
            ChangeCharTo(pSlot_index, i, gCurrent_typing[i]);
 
        }
 
        gCurrent_typing[new_len] = '\0';
 
        SetRollingCursor(pSlot_index);
 
    }
 
}
 
 
 
// IDA: void __usercall DoRLInsert(int pSlot_index@<EAX>)
 
void DoRLInsert(int pSlot_index) {
 
    LOG_TRACE("(%d)", pSlot_index);
 
 
 
    gInsert_mode = !gInsert_mode;
 
}
 
 
 
// IDA: void __usercall DoRLCursorLeft(int pSlot_index@<EAX>)
 
void DoRLCursorLeft(int pSlot_index) {
 
    LOG_TRACE("(%d)", pSlot_index);
 
    if (gCurrent_position != 0) {
 
        if (strlen(gCurrent_typing
) == gCurrent_position
) {  
            ChangeCharTo
(pSlot_index
, strlen(gCurrent_typing
), ' '); 
        } else {
 
            ChangeCharTo(pSlot_index, gCurrent_position, gCurrent_typing[gCurrent_position]);
 
        }
 
 
 
        gCurrent_position--;
 
        SetRollingCursor(pSlot_index);
 
    }
 
}
 
 
 
// IDA: void __usercall DoRLCursorRight(int pSlot_index@<EAX>)
 
void DoRLCursorRight(int pSlot_index) {
 
    LOG_TRACE("(%d)", pSlot_index);
 
 
 
    if (gCurrent_position 
< (int) strlen(gCurrent_typing
)) { // Pierre-Marie Baty -- added type cast  
        ChangeCharTo(pSlot_index, gCurrent_position, gCurrent_typing[gCurrent_position]);
 
        gCurrent_position++;
 
        SetRollingCursor(pSlot_index);
 
    }
 
}
 
 
 
// IDA: void __usercall DoRLTypeLetter(int pChar@<EAX>, int pSlot_index@<EDX>)
 
void DoRLTypeLetter(int pChar, int pSlot_index) {
 
    int i;
 
    int new_len;
 
    LOG_TRACE("(%d, %d)", pChar, pSlot_index);
 
 
 
    // v2 = pSlot_index;
 
    if (pChar >= 32) {
 
        if (gInsert_mode) {
 
            new_len 
= strlen(gCurrent_typing
) + 1; 
            if (new_len > 100) {
 
                new_len = 100;
 
                DoErrorInterface(kMiscString_FIXED_THAT_YOU_TWISTED_BASTARD);
 
            }
 
            for (i = new_len - 1; i > gCurrent_position; i--) {
 
                gCurrent_typing[i] = gCurrent_typing[i - 1];
 
                ChangeCharTo(pSlot_index, i, gCurrent_typing[i]);
 
            }
 
        } else if (strlen(gCurrent_typing
) == gCurrent_position
) {  
            new_len 
= strlen(gCurrent_typing
) + 1; 
        } else {
 
            new_len 
= strlen(gCurrent_typing
); 
        }
 
        if (new_len > 100) {
 
            new_len = 100;
 
            DoErrorInterface(kMiscString_FIXED_THAT_YOU_TWISTED_BASTARD);
 
        }
 
 
 
        gCurrent_typing[new_len] = 0;
 
        if (new_len - 1 < gCurrent_position) {
 
            gCurrent_position = new_len - 1;
 
        }
 
        gCurrent_typing[gCurrent_position] = pChar;
 
        ChangeCharTo(pSlot_index, gCurrent_position, pChar);
 
        gCurrent_position++;
 
        SetRollingCursor(pSlot_index);
 
    }
 
}
 
 
 
// IDA: void __usercall StopTyping(int pSlot_index@<EAX>)
 
void StopTyping(int pSlot_index) {
 
    int i;
 
    LOG_TRACE("(%d)", pSlot_index);
 
 
 
    for (i = 0; i < gThe_length; i++) {
 
        if (i 
< ((int) strlen(gCurrent_typing
) - 1)) { // Pierre-Marie Baty -- added type cast  
            ChangeCharTo(pSlot_index, i, gCurrent_typing[i]);
 
        } else {
 
            ChangeCharTo(pSlot_index, i, ' ');
 
        }
 
    }
 
}
 
 
 
// IDA: void __usercall RevertTyping(int pSlot_index@<EAX>, char *pRevert_str@<EDX>)
 
void RevertTyping(int pSlot_index, char* pRevert_str) {
 
    int i;
 
    LOG_TRACE("(%d, \"%s\")", pSlot_index, pRevert_str);
 
 
 
    for (i = 0; i < gThe_length; i++) {
 
        ChangeCharTo
(pSlot_index
, i
, i 
>= (int) strlen(pRevert_str
) ? ' ' : pRevert_str
[i
]); // Pierre-Marie Baty -- added type cast 
    }
 
}
 
 
 
// IDA: void __usercall StartTyping(int pSlot_index@<EAX>, char *pText@<EDX>, int pVisible_length@<EBX>)
 
void StartTyping(int pSlot_index, char* pText, int pVisible_length) {
 
    LOG_TRACE("(%d, \"%s\", %d)", pSlot_index, pText, pVisible_length);
 
 
 
    gThe_length = pVisible_length;
 
    strcpy(gCurrent_typing
, pText
);  
    gVisible_length = pVisible_length;
 
    gCurrent_position 
= strlen(gCurrent_typing
); 
    SetRollingCursor(pSlot_index);
 
}
 
 
 
// IDA: void __usercall TypeKey(int pSlot_index@<EAX>, char pKey@<EDX>)
 
void TypeKey(int pSlot_index, char pKey) {
 
    LOG_TRACE("(%d, %d)", pSlot_index, pKey);
 
 
 
    switch (pKey) {
 
    case KEY_GRAVE:
 
        break;
 
    case KEY_BACKSPACE:
 
        DoRLBackspace(pSlot_index);
 
        break;
 
    case KEY_INSERT:
 
        DoRLInsert(pSlot_index);
 
        break;
 
    case KEY_DELETE:
 
        DoRLDelete(pSlot_index);
 
        break;
 
    case KEY_LEFT:
 
        DoRLCursorLeft(pSlot_index);
 
        break;
 
    case KEY_RIGHT:
 
        DoRLCursorRight(pSlot_index);
 
        break;
 
    default:
 
        DoRLTypeLetter(PDGetASCIIFromKey(pKey), pSlot_index);
 
        break;
 
    }
 
}
 
 
 
// IDA: void __usercall SetSlotXY(int pSlot_index@<EAX>, int pX_coord@<EDX>, int pY_coord@<EBX>)
 
void SetSlotXY(int pSlot_index, int pX_coord, int pY_coord) {
 
    LOG_TRACE("(%d, %d, %d)", pSlot_index, pX_coord, pY_coord);
 
 
 
    gLetter_x_coords[pSlot_index] = pX_coord;
 
    gLetter_y_coords[pSlot_index] = pY_coord;
 
}
 
 
 
// IDA: void __usercall GetTypedName(char *pDestn@<EAX>, int pMax_length@<EDX>)
 
void GetTypedName(char* pDestn, int pMax_length) {
 
    LOG_TRACE("(\"%s\", %d)", pDestn, pMax_length);
 
 
 
    if ((int) strlen(gCurrent_typing
) <= pMax_length
) { // Pierre-Marie Baty -- added type cast  
        strcpy(pDestn
, gCurrent_typing
);  
    } else {
 
        memcpy(pDestn
, gCurrent_typing
, pMax_length
);  
        pDestn[pMax_length] = 0;
 
    }
 
}
 
 
 
// IDA: void __usercall KillCursor(int pSlot_index@<EAX>)
 
void KillCursor(int pSlot_index) {
 
    int x_coord;
 
    int y_coord;
 
    int i;
 
    //int j; // Pierre-Marie Baty -- unused variable
 
    tRolling_letter* let;
 
    //tRolling_type new_type; // Pierre-Marie Baty -- unused variable
 
    LOG_TRACE("(%d)", pSlot_index);
 
 
 
    if (gCurrent_position < gVisible_length && gCurrent_position >= 0) {
 
        y_coord = gLetter_y_coords[pSlot_index];
 
        x_coord = gCurrent_graf_data->rolling_letter_x_pitch * gCurrent_position + gLetter_x_coords[pSlot_index];
 
        for (i = 0; i < NBR_ROLLING_LETTERS; i++) {
 
            let = &gRolling_letters[i];
 
            if (let->number_of_letters >= 0 && x_coord == let->x_coord && y_coord == let->y_coord) {
 
                gRolling_letters[i].number_of_letters = -1;
 
                break;
 
            }
 
        }
 
    }
 
}
 
 
 
// IDA: void __cdecl EdgeTriggerModeOn()
 
void EdgeTriggerModeOn(void) {
 
    gEdge_trigger_mode = 1;
 
}
 
 
 
// IDA: void __cdecl EdgeTriggerModeOff()
 
void EdgeTriggerModeOff(void) {
 
    gEdge_trigger_mode = 0;
 
}