diff --git a/sc2/src/sc2code/controls.h b/sc2/src/sc2code/controls.h index 1745786bf..13350c18c 100644 --- a/sc2/src/sc2code/controls.h +++ b/sc2/src/sc2code/controls.h @@ -55,9 +55,14 @@ enum { KEY_MENU_SPECIAL, KEY_MENU_PAGE_UP, KEY_MENU_PAGE_DOWN, + KEY_MENU_HOME, + KEY_MENU_END, KEY_MENU_ZOOM_IN, KEY_MENU_ZOOM_OUT, KEY_MENU_DELETE, + KEY_MENU_BACKSPACE, + KEY_MENU_EDIT_CANCEL, + KEY_CHARACTER, /* abstract char key */ NUM_KEYS }; @@ -100,6 +105,30 @@ BATTLE_INPUT_STATE p2_combat_summary (void); extern volatile BOOLEAN GamePaused, ExitRequested; +typedef struct textentry_state +{ + // standard state required by DoInput + BOOLEAN (*InputFunc) (struct textentry_state *pTES); + COUNT MenuRepeatDelay; + + // these are semi-private read-only + BOOLEAN Initialized; + BOOLEAN Success; // edit confirmed or canceled + UNICODE *CacheStr; // cached copy to revert immediate changes + // these are public and must be set before calling DoTextEntry + UNICODE *BaseStr; // set to string to edit + UNICODE *InsPt; // set to curremt pos of insertion point + int MaxSize; // set to max size of edited string + + BOOLEAN (*ChangeCallback) (struct textentry_state *pTES); + // returns TRUE if last change is OK + void *CbParam; // callback parameter, use as you like + +} TEXTENTRY_STATE; +typedef TEXTENTRY_STATE *PTEXTENTRY_STATE; + +BOOLEAN DoTextEntry (PTEXTENTRY_STATE pTES); + #endif diff --git a/sc2/src/sc2code/gameinp.c b/sc2/src/sc2code/gameinp.c index 5cc011b02..8a6832314 100644 --- a/sc2/src/sc2code/gameinp.c +++ b/sc2/src/sc2code/gameinp.c @@ -192,7 +192,9 @@ UpdateInputState (void) int i; for (i = 0; i < NUM_KEYS; i++) { - _check_for_pulse(&PulsedInputState.key[i], &CachedInputState.key[i], &OldInputState.key[i], &RepeatDelays.key[i], &NewTime, &Times.key[i]); + _check_for_pulse (&PulsedInputState.key[i], + &CachedInputState.key[i], &OldInputState.key[i], + &RepeatDelays.key[i], &NewTime, &Times.key[i]); } } @@ -270,6 +272,7 @@ DoInput (PVOID pInputState, BOOLEAN resetInput) if (PulsedInputState.key[KEY_MENU_PAGE_UP]) input |= MENU_SOUND_PAGEUP; if (PulsedInputState.key[KEY_MENU_PAGE_DOWN]) input |= MENU_SOUND_PAGEDOWN; if (PulsedInputState.key[KEY_MENU_DELETE]) input |= MENU_SOUND_DELETE; + if (PulsedInputState.key[KEY_MENU_BACKSPACE]) input |= MENU_SOUND_DELETE; if (MenuSounds && (pSolarSysState == 0 diff --git a/sc2/src/sc2code/gameopt.c b/sc2/src/sc2code/gameopt.c index de9d126a8..1900db196 100644 --- a/sc2/src/sc2code/gameopt.c +++ b/sc2/src/sc2code/gameopt.c @@ -43,7 +43,6 @@ #define MAX_SAVED_GAMES 50 #define SUMMARY_X_OFFS 14 #define SUMMARY_SIDE_OFFS 7 -#define MAX_NAME_CHARS 15 #define SAVES_PER_PAGE 5 static BOOLEAN DoSettings (PMENU_STATE pMS); @@ -225,7 +224,7 @@ DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, SIZE state) r.extent.height = SHIP_NAME_HEIGHT; SetContext (StatusContext); - if (pMS->delta_item == CHANGE_CAPTAIN_SETTING) + if (pMS->CurState == CHANGE_CAPTAIN_SETTING) { Font = TinyFont; r.corner.y = 10; @@ -251,14 +250,16 @@ DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, SIZE state) } SetContextFont (Font); + // XXX: nasty hack; CurString may not be large enough to + // contain a pointer on some platforms lf.pStr = ((GAME_DESC *)pMS->CurString)[rel_index]; lf.CharCount = (COUNT)~0; if (state <= 0) - { + { // normal state if (pMS->InputFunc == DoNaming) { - if (pMS->delta_item == CHANGE_CAPTAIN_SETTING) + if (pMS->CurState == CHANGE_CAPTAIN_SETTING) DrawCaptainsName (); else { @@ -283,7 +284,7 @@ DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, SIZE state) SetFlashRect ((PRECT)~0L, (FRAME)0); } else - { + { // editing state COUNT i; RECT text_r; BYTE char_deltas[MAX_DESC_CHARS]; @@ -291,8 +292,10 @@ DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, SIZE state) TextRect (&lf, &text_r, char_deltas); if ((text_r.extent.width + 2) >= r.extent.width) - { + { // the text does not fit the input box size and so + // will not fit when displayed later UnlockMutex (GraphicsLock); + // disallow the change return (FALSE); } @@ -330,184 +333,72 @@ DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, SIZE state) return (TRUE); } -static UWORD -DoTextEntry (PMENU_STATE pMS) +static BOOLEAN +OnNameChange (PTEXTENTRY_STATE pTES) { - UWORD ch; - UNICODE *pStr, *pBaseStr; - COUNT len; - BOOLEAN left = FALSE, right = FALSE; - - pBaseStr = ((GAME_DESC *)pMS->CurString)[pMS->CurState - pMS->first_item.y]; - pStr = &pBaseStr[pMS->first_item.x]; - len = wstrlen (pStr); - - ch = GetCharacter (); - -#if 0 - /* This code goes away, but is listed here anyway just in case someone decides - to port this to a keyboardless platform later */ - - if (SerialInput) - { - ch = GetInputUNICODE (GetInputState (SerialInput)); - } - else - { - extern UWORD GetJoystickChar (INPUT_STATE InputState); - - ch = GetJoystickChar (); - } -#endif - - switch (ch) - { - case SK_DELETE: - if (len) - { - memmove (pStr, pStr + 1, len * sizeof (*pStr)); - len = (COUNT)~0; - } - break; - case '\b': - if (pMS->first_item.x) - { - memmove (pStr - 1, pStr, (len + 1) * sizeof (*pStr)); - --pMS->first_item.x; - - len = (COUNT)~0; - } - break; - case SK_LF_ARROW: - left = TRUE; - break; - case SK_RT_ARROW: - right = TRUE; - break; - default: - if (isprint (ch) && (len + (pStr - pBaseStr) < MAX_NAME_CHARS)) - { - memmove (pStr + 1, pStr, (len + 1) * sizeof (*pStr)); - if (len == 0) - *(pStr + 1) = '\0'; - *pStr++ = ch; - ++pMS->first_item.x; -#if 0 - /* Joystick letter-entry mode */ - *pStr = ch; - if (len == 0) - *(pStr + 1) = '\0'; -#endif - len = (COUNT)~0; - } - break; - } - - if (len == (COUNT)~0) - { - if (!DrawDescriptionString (pMS, pMS->CurState, 1)) - { - len = wstrlen (pStr); - memmove (pStr - 1, pStr, (len + 1) * sizeof (*pStr)); - --pMS->first_item.x; - } - } - else if (left) - { - if (pMS->first_item.x) - { - --pMS->first_item.x; - DrawDescriptionString (pMS, pMS->CurState, 1); - } - } - else if (right) - { - if (len) - { - ++pMS->first_item.x; - DrawDescriptionString (pMS, pMS->CurState, 1); - } - } - - return (ch); + PMENU_STATE pMS = (PMENU_STATE) pTES->CbParam; + pMS->first_item.x = pTES->InsPt - pTES->BaseStr; + return DrawDescriptionString (pMS, 0, 1); } static BOOLEAN DoNaming (PMENU_STATE pMS) { - if (GLOBAL (CurrentActivity) & CHECK_ABORT) - return (FALSE); - - if (!pMS->Initialized) + GAME_DESC buf; + TEXTENTRY_STATE tes; + UNICODE *Setting; + + pMS->Initialized = TRUE; + pMS->InputFunc = DoNaming; + + buf[0] = '\0'; + // XXX: this code abuses MENU_STATE struct members to store + // some values: + // first_item.x - current cursor position + // first_item.y - must be set to 0; DrawDescriptionString() + // treats it as base index into array of strings + // supplied in CurString + pMS->first_item.x = 0; + pMS->first_item.y = 0; + // XXX: nasty hack; CurString may not be large enough to + // contain a pointer on some platforms + pMS->CurString = (STRING)buf; + DrawDescriptionString (pMS, 0, 1); + + LockMutex (GraphicsLock); + DrawStatusMessage (GAME_STRING (NAMING_STRING_BASE + 0)); + UnlockMutex (GraphicsLock); + + if (pMS->CurState == CHANGE_CAPTAIN_SETTING) { - GAME_DESC GD[1]; - - pMS->Initialized = 1; - pMS->InputFunc = DoNaming; - - GD[0][0] = '\0'; - pMS->delta_item = pMS->CurState; - pMS->first_item.x = pMS->first_item.y = 0; - pMS->CurState = 0; - pMS->CurString = (STRING)&GD[0]; - DrawDescriptionString (pMS, pMS->CurState, 1); - - LockMutex (GraphicsLock); - DrawStatusMessage (GAME_STRING (NAMING_STRING_BASE + 0)); - UnlockMutex (GraphicsLock); - - EnableCharacterMode (); - DoInput (pMS, TRUE); - DisableCharacterMode (); - - SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); - - pMS->InputFunc = DoSettings; - pMS->CurState = (BYTE)pMS->delta_item; - pMS->delta_item = 0; - if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) - FeedbackSetting (pMS->CurState); + Setting = GLOBAL_SIS (CommanderName); + tes.MaxSize = sizeof (GLOBAL_SIS (CommanderName)); } else { - UWORD ch; - - if (pMS->Initialized == 1) - { - FlushInput (); - pMS->Initialized = 2; - return (TRUE); - } - - ch = DoTextEntry (pMS); - - if (ch == '\n' || ch == '\r' || ch == 0x1B) - { - if (ch == '\n' || ch == '\r') - { - if (pMS->delta_item == CHANGE_CAPTAIN_SETTING) - wstrcpy (GLOBAL_SIS (CommanderName), - (const UNICODE *)((GAME_DESC *)pMS->CurString)[0]); - else - wstrcpy (GLOBAL_SIS (ShipName), - (const UNICODE *)((GAME_DESC *)pMS->CurString)[0]); - } - else - { - if (pMS->delta_item == CHANGE_CAPTAIN_SETTING) - wstrcpy ((UNICODE *)((GAME_DESC *)pMS->CurString)[0], - GLOBAL_SIS (CommanderName)); - else - wstrcpy ((UNICODE *)((GAME_DESC *)pMS->CurString)[0], - GLOBAL_SIS (ShipName)); - } - - DrawDescriptionString (pMS, pMS->CurState, 0); - - return (FALSE); - } + Setting = GLOBAL_SIS (ShipName); + tes.MaxSize = sizeof (GLOBAL_SIS (ShipName)); } + // text entry setup + tes.Initialized = FALSE; + tes.MenuRepeatDelay = 0; + tes.BaseStr = buf; + tes.CbParam = pMS; + tes.ChangeCallback = OnNameChange; + + if (DoTextEntry (&tes)) + wstrcpy (Setting, buf); + else + wstrcpy (buf, Setting); + DrawDescriptionString (pMS, 0, 0); + + SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT); + + pMS->InputFunc = DoSettings; + if (!(GLOBAL (CurrentActivity) & CHECK_ABORT)) + FeedbackSetting (pMS->CurState); + return (TRUE); } diff --git a/sc2/src/sc2code/getchar.c b/sc2/src/sc2code/getchar.c index 68afefcbc..02c3cf494 100644 --- a/sc2/src/sc2code/getchar.c +++ b/sc2/src/sc2code/getchar.c @@ -18,6 +18,11 @@ #include #include "controls.h" +#include "libs/inplib.h" +#include "libs/misc.h" +#include "globdata.h" +#include "sounds.h" +#include "settings.h" static UWORD cur_char = ' '; @@ -83,3 +88,155 @@ GetJoystickChar (void) return (cur_char == old_char ? 0 : cur_char); } + +BOOLEAN +DoTextEntry (PTEXTENTRY_STATE pTES) +{ + UNICODE ch; + UNICODE *pStr; + UNICODE *CacheInsPt; + int len; + BOOLEAN changed = FALSE; + + if (GLOBAL (CurrentActivity) & CHECK_ABORT) + return (FALSE); + + if (!pTES->Initialized) + { // init basic vars + pTES->InputFunc = DoTextEntry; + pTES->InsPt = pTES->BaseStr; + pTES->CacheStr = HMalloc (pTES->MaxSize); + pTES->Success = FALSE; + pTES->Initialized = TRUE; + + DoInput (pTES, TRUE); + + if (pTES->CacheStr) + HFree (pTES->CacheStr); + + return pTES->Success; + } + + pStr = pTES->InsPt; + len = wstrlen (pStr); + // save a copy of string + CacheInsPt = pTES->InsPt; + wstrncpy (pTES->CacheStr, pTES->BaseStr, pTES->MaxSize - 1); + pTES->CacheStr[pTES->MaxSize - 1] = '\0'; + + // process the pending character buffer + while (ch = GetNextCharacter ()) + { + if (isprint (ch) && (pStr + len - pTES->BaseStr + 1 < pTES->MaxSize)) + { + memmove (pStr + 1, pStr, (len + 1) * sizeof (*pStr)); + *pStr = ch; + ++pStr; + ++len; + changed = TRUE; + } + } + + if (!changed && PulsedInputState.key[KEY_CHARACTER]) + { // keyboard repeat, but only when buffer empty + ch = GetLastCharacter (); + if (ch && isprint (ch) && + (pStr + len - pTES->BaseStr + 1 < pTES->MaxSize)) + { + memmove (pStr + 1, pStr, (len + 1) * sizeof (*pStr)); + *pStr = ch; + ++pStr; + ++len; + changed = TRUE; + } + } + + if (PulsedInputState.key[KEY_MENU_DELETE]) + { + if (len) + { + memmove (pStr, pStr + 1, len * sizeof (*pStr)); + --len; + changed = TRUE; + } + } + else if (PulsedInputState.key[KEY_MENU_BACKSPACE]) + { + if (pStr > pTES->BaseStr) + { + memmove (pStr - 1, pStr, (len + 1) * sizeof (*pStr)); + --pStr; + --len; + changed = TRUE; + } + } + else if (PulsedInputState.key[KEY_MENU_LEFT]) + { + if (pStr > pTES->BaseStr) + { + --pStr; + changed = TRUE; + } + } + else if (PulsedInputState.key[KEY_MENU_RIGHT]) + { + if (len > 0) + { + ++pStr; + changed = TRUE; + } + } + else if (PulsedInputState.key[KEY_MENU_HOME]) + { + if (pStr > pTES->BaseStr) + { + pStr = pTES->BaseStr; + changed = TRUE; + } + } + else if (PulsedInputState.key[KEY_MENU_END]) + { + if (len > 0) + { + pStr += len; + changed = TRUE; + } + } + else if (PulsedInputState.key[KEY_MENU_UP]) + { + // do joystick text + } + else if (PulsedInputState.key[KEY_MENU_DOWN]) + { + // do joystick text + } + + if (PulsedInputState.key[KEY_MENU_SELECT]) + { // done entering + pTES->Success = TRUE; + return FALSE; + } + else if (PulsedInputState.key[KEY_MENU_EDIT_CANCEL]) + { // canceled entering + pTES->Success = FALSE; + return FALSE; + } + + pTES->InsPt = pStr; + + if (changed && pTES->ChangeCallback) + { + if (!pTES->ChangeCallback (pTES)) + { // changes not accepted - revert + wstrncpy (pTES->BaseStr, pTES->CacheStr, pTES->MaxSize - 1); + pTES->BaseStr[pTES->MaxSize - 1] = '\0'; + pTES->InsPt = CacheInsPt; + + PlaySoundEffect (SetAbsSoundIndex (MenuSounds, 2), + 0, NotPositional (), NULL, 0); + } + } + + return TRUE; +} + diff --git a/sc2/src/sc2code/libs/inplib.h b/sc2/src/sc2code/libs/inplib.h index 813de3edb..7ac8f7d92 100644 --- a/sc2/src/sc2code/libs/inplib.h +++ b/sc2/src/sc2code/libs/inplib.h @@ -23,48 +23,11 @@ typedef DWORD INPUT_STATE; -/* Serial Keyboard Pseudo UNICODE Equivalents */ -#define SK_DELETE ((UNICODE)127) -#define SK_LF_ARROW ((UNICODE)128) -#define SK_RT_ARROW ((UNICODE)129) -#define SK_UP_ARROW ((UNICODE)130) -#define SK_DN_ARROW ((UNICODE)131) -#define SK_HOME ((UNICODE)132) -#define SK_PAGE_UP ((UNICODE)133) -#define SK_END ((UNICODE)134) -#define SK_PAGE_DOWN ((UNICODE)135) -#define SK_INSERT ((UNICODE)136) -#define SK_KEYPAD_PLUS ((UNICODE)137) -#define SK_KEYPAD_MINUS ((UNICODE)138) - -#define SK_LF_SHIFT ((UNICODE)139) -#define SK_RT_SHIFT ((UNICODE)140) -#define SK_LF_CTL ((UNICODE)141) -#define SK_RT_CTL ((UNICODE)142) -#define SK_LF_ALT ((UNICODE)143) -#define SK_RT_ALT ((UNICODE)144) - -#define SK_F1 ((UNICODE)145) -#define SK_F2 ((UNICODE)146) -#define SK_F3 ((UNICODE)147) -#define SK_F4 ((UNICODE)148) -#define SK_F5 ((UNICODE)149) -#define SK_F6 ((UNICODE)150) -#define SK_F7 ((UNICODE)151) -#define SK_F8 ((UNICODE)152) -#define SK_F9 ((UNICODE)153) -#define SK_F10 ((UNICODE)154) -#define SK_F11 ((UNICODE)155) -#define SK_F12 ((UNICODE)156) - extern BOOLEAN InitInput (void); extern BOOLEAN UninitInput (void); extern BOOLEAN AnyButtonPress (BOOLEAN DetectSpecial); extern void FlushInput (void); -extern BOOLEAN KeyDown (UNICODE which_scan); -extern UNICODE GetUnicodeKey (void); -extern UNICODE KBDToUNICODE (UWORD which_key); /* * Not used right now @@ -79,8 +42,9 @@ extern volatile int MouseButtonDown; void EnableCharacterMode (void); void DisableCharacterMode (void); -UNICODE GetCharacter (void); +UNICODE GetNextCharacter (void); +UNICODE GetLastCharacter (void); + #endif /* _INPLIB_H */ - diff --git a/sc2/src/sc2code/libs/input/sdl/input.c b/sc2/src/sc2code/libs/input/sdl/input.c index d5bf43259..675f1ff57 100644 --- a/sc2/src/sc2code/libs/input/sdl/input.c +++ b/sc2/src/sc2code/libs/input/sdl/input.c @@ -31,6 +31,8 @@ #define KBDBUFSIZE (1 << 8) static int kbdhead=0, kbdtail=0; static UNICODE kbdbuf[KBDBUFSIZE]; +static UNICODE lastchar; +static int kbdstate[SDLK_LAST]; static BOOLEAN InputInitialized = FALSE; UWORD UNICODEToKBD (UNICODE which_key); @@ -49,9 +51,13 @@ static VControl_NameBinding control_names[] = { { "Menu-Special", (int *)&ImmediateInputState.key[KEY_MENU_SPECIAL] }, { "Menu-Page-Up", (int *)&ImmediateInputState.key[KEY_MENU_PAGE_UP] }, { "Menu-Page-Down", (int *)&ImmediateInputState.key[KEY_MENU_PAGE_DOWN] }, + { "Menu-Home", (int *)&ImmediateInputState.key[KEY_MENU_HOME] }, + { "Menu-End", (int *)&ImmediateInputState.key[KEY_MENU_END] }, { "Menu-Zoom-In", (int *)&ImmediateInputState.key[KEY_MENU_ZOOM_IN] }, { "Menu-Zoom-Out", (int *)&ImmediateInputState.key[KEY_MENU_ZOOM_OUT] }, { "Menu-Delete", (int *)&ImmediateInputState.key[KEY_MENU_DELETE] }, + { "Menu-Backspace", (int *)&ImmediateInputState.key[KEY_MENU_BACKSPACE] }, + { "Menu-Edit-Cancel", (int *)&ImmediateInputState.key[KEY_MENU_EDIT_CANCEL] }, { "Player-1-Thrust", (int *)&ImmediateInputState.key[KEY_P1_THRUST] }, { "Player-1-Left", (int *)&ImmediateInputState.key[KEY_P1_LEFT] }, { "Player-1-Right", (int *)&ImmediateInputState.key[KEY_P1_RIGHT] }, @@ -152,6 +158,13 @@ initKeyConfig(void) { exit (EXIT_FAILURE); } +static void +resetKeyboardState (void) +{ + memset (kbdstate, 0, sizeof (kbdstate)); + ImmediateInputState.key[KEY_CHARACTER] = 0; +} + int TFB_InitInput (int driver, int flags) { @@ -184,6 +197,7 @@ TFB_InitInput (int driver, int flags) } _in_character_mode = FALSE; + resetKeyboardState (); /* Prepare the Virtual Controller system. */ VControl_Init (); @@ -204,34 +218,43 @@ TFB_UninitInput (void) VControl_Uninit (); } +// XXX: not currently used -- character mode is always on void EnableCharacterMode (void) { kbdhead = kbdtail = 0; + lastchar = 0; _in_character_mode = TRUE; VControl_ResetInput (); - } +// XXX: not currently used -- character mode is always on void DisableCharacterMode (void) { VControl_ResetInput (); _in_character_mode = FALSE; kbdhead = kbdtail = 0; + lastchar = 0; } UNICODE -GetCharacter (void) +GetNextCharacter (void) { UNICODE result; - while (kbdhead == kbdtail) - TaskSwitch (); + if (kbdhead == kbdtail) + return 0; result = kbdbuf[kbdhead]; kbdhead = (kbdhead + 1) & (KBDBUFSIZE - 1); return result; } +UNICODE +GetLastCharacter (void) +{ + return lastchar; +} + volatile int MouseButtonDown = 0; void @@ -252,34 +275,47 @@ ProcessMouseEvent (const SDL_Event *e) void -ProcessInputEvent(const SDL_Event *Event) +ProcessInputEvent (const SDL_Event *Event) { if (!InputInitialized) return; - ProcessMouseEvent (Event); - if (!_in_character_mode) - { - VControl_HandleEvent (Event); - } - else - { - SDLKey k = Event->key.keysym.sym; - UNICODE map_key; - if (Event->type != SDL_KEYDOWN) - return; - if (!Event->key.keysym.unicode && - (k == SDLK_CAPSLOCK || - k == SDLK_NUMLOCK)) - return; - if (Event->key.keysym.unicode != 0) - map_key = (UNICODE) Event->key.keysym.unicode; - else - map_key = KBDToUNICODE(k); - kbdbuf[kbdtail] = map_key; - kbdtail = (kbdtail + 1) & (KBDBUFSIZE - 1); - if (kbdtail == kbdhead) - kbdhead = (kbdhead + 1) & (KBDBUFSIZE - 1); + ProcessMouseEvent (Event); + VControl_HandleEvent (Event); + + { // process character input event, if any + SDLKey k = Event->key.keysym.sym; + UNICODE map_key = (UNICODE) Event->key.keysym.unicode; + + if (Event->type == SDL_KEYDOWN) + { + // dont care about the non-printable, non-char + if (!map_key) + return; + + kbdstate[k]++; + ImmediateInputState.key[KEY_CHARACTER]++; + + lastchar = map_key; + kbdbuf[kbdtail] = map_key; + kbdtail = (kbdtail + 1) & (KBDBUFSIZE - 1); + if (kbdtail == kbdhead) + kbdhead = (kbdhead + 1) & (KBDBUFSIZE - 1); + } + else if (Event->type == SDL_KEYUP) + { + if (kbdstate[k] == 0) + { // something is fishy -- better to reset the + // repeatable state to avoid big problems + ImmediateInputState.key[KEY_CHARACTER] = 0; + } + else + { + kbdstate[k]--; + if (ImmediateInputState.key[KEY_CHARACTER] > 0) + ImmediateInputState.key[KEY_CHARACTER]--; + } + } } } @@ -287,6 +323,10 @@ void TFB_ResetControls (void) { VControl_ResetInput (); + resetKeyboardState (); + // flush character buffer + kbdhead = kbdtail = 0; + lastchar = 0; } void @@ -296,140 +336,4 @@ FlushInput (void) FlushInputState (); } -// Translates from SDLKeys to values defined in inplib.h -UNICODE -KBDToUNICODE (UWORD SK_in) -{ - switch (SK_in) - { - case SDLK_KP_ENTER: - case SDLK_RETURN: - return '\n'; - case SDLK_KP4: - case SDLK_LEFT: - return (SK_LF_ARROW); - case SDLK_KP6: - case SDLK_RIGHT: - return (SK_RT_ARROW); - case SDLK_KP8: - case SDLK_UP: - return (SK_UP_ARROW); - case SDLK_KP2: - case SDLK_DOWN: - return (SK_DN_ARROW); - case SDLK_KP7: - case SDLK_HOME: - return (SK_HOME); - case SDLK_KP9: - case SDLK_PAGEUP: - return (SK_PAGE_UP); - case SDLK_KP1: - case SDLK_END: - return (SK_END); - case SDLK_KP3: - case SDLK_PAGEDOWN: - return (SK_PAGE_DOWN); - case SDLK_KP0: - case SDLK_INSERT: - return (SK_INSERT); - case SDLK_KP_PERIOD: - case SDLK_DELETE: - return (SK_DELETE); - case SDLK_KP_PLUS: - return (SK_KEYPAD_PLUS); - case SDLK_KP_MINUS: - return (SK_KEYPAD_MINUS); - case SDLK_LSHIFT: - return (SK_LF_SHIFT); - case SDLK_RSHIFT: - return (SK_RT_SHIFT); - case SDLK_LCTRL: - return (SK_LF_CTL); - case SDLK_RCTRL: - return (SK_RT_CTL); - case SDLK_LALT: - return (SK_LF_ALT); - case SDLK_RALT: - return (SK_RT_ALT); - case SDLK_F1: - case SDLK_F2: - case SDLK_F3: - case SDLK_F4: - case SDLK_F5: - case SDLK_F6: - case SDLK_F7: - case SDLK_F8: - case SDLK_F9: - case SDLK_F10: - case SDLK_F11: - case SDLK_F12: - return ((UNICODE) ((SK_in - SDLK_F1) + SK_F1)); - default: - return (UNICODE)SK_in; - } -} - -// Translates from values defined in inplib.h to SDLKey values -UWORD -UNICODEToKBD (UNICODE which_key) -{ - switch (which_key) - { - case '\r': - case '\n': - return SDLK_RETURN; - case SK_LF_ARROW: - return SDLK_LEFT; - case SK_RT_ARROW: - return SDLK_RIGHT; - case SK_UP_ARROW: - return SDLK_UP; - case SK_DN_ARROW: - return SDLK_DOWN; - case SK_HOME: - return SDLK_HOME; - case SK_PAGE_UP: - return SDLK_PAGEUP; - case SK_END: - return SDLK_END; - case SK_PAGE_DOWN: - return SDLK_PAGEDOWN; - case SK_INSERT: - return SDLK_INSERT; - case SK_DELETE: - return SDLK_DELETE; - case SK_KEYPAD_PLUS: - return SDLK_KP_PLUS; - case SK_KEYPAD_MINUS: - return SDLK_KP_MINUS; - case SK_LF_SHIFT: - return SDLK_LSHIFT; - case SK_RT_SHIFT: - return SDLK_RSHIFT; - case SK_LF_CTL: - return SDLK_LCTRL; - case SK_RT_CTL: - return SDLK_RCTRL; - case SK_LF_ALT: - return SDLK_LALT; - case SK_RT_ALT: - return SDLK_RALT; - case SK_F1: - case SK_F2: - case SK_F3: - case SK_F4: - case SK_F5: - case SK_F6: - case SK_F7: - case SK_F8: - case SK_F9: - case SK_F10: - case SK_F11: - case SK_F12: - return (which_key - SK_F1) + SDLK_F1; - default: - return which_key; - } -} - #endif diff --git a/sc2/src/sc2code/melee.c b/sc2/src/sc2code/melee.c index 8d1e53d8c..15c2bace7 100644 --- a/sc2/src/sc2code/melee.c +++ b/sc2/src/sc2code/melee.c @@ -138,7 +138,7 @@ PMELEE_STATE volatile pMeleeState; static BOOLEAN DoMelee (PMELEE_STATE pMS); static BOOLEAN DoEdit (PMELEE_STATE pMS); static BOOLEAN DoPickShip (PMELEE_STATE pMS); -static void DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState); +static BOOLEAN DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState); static BOOLEAN DoLoadTeam (PMELEE_STATE pMS); static void DrawFileStrings (PMELEE_STATE pMS, int HiLiteState); @@ -326,7 +326,7 @@ RepairMeleeFrame (PRECT pRect) SetContext (OldContext); } -static void +static BOOLEAN DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState) { RECT r; @@ -340,7 +340,7 @@ DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState) if (HiLiteState == 4) { RepairMeleeFrame (&r); - return; + return (TRUE); } if (HiLiteState & 1) @@ -357,7 +357,7 @@ DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState) BatchGraphics (); if (!(HiLiteState & 1)) - { + { // normal or selected state TEXT rtText; UNICODE buf[10]; @@ -374,18 +374,26 @@ DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState) font_DrawText (&rtText); } else - { + { // editing state COUNT i; RECT text_r; BYTE char_deltas[MAX_TEAM_CHARS]; PBYTE pchar_deltas; TextRect (&lfText, &text_r, char_deltas); + if ((text_r.extent.width + 2) >= r.extent.width) + { // the text does not fit the input box size and so + // will not fit when displayed later + UnbatchGraphics (); + // disallow the change + return (FALSE); + } text_r = r; SetContextForeGroundColor (TEAM_NAME_EDIT_RECT_COLOR); DrawFilledRectangle (&text_r); + // calculate the cursor position and draw it pchar_deltas = char_deltas; for (i = pMS->CurIndex; i > 0; --i) text_r.corner.x += (SIZE)*pchar_deltas++; @@ -412,6 +420,8 @@ DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState) font_DrawText (&lfText); } UnbatchGraphics (); + + return (TRUE); } static void @@ -988,88 +998,6 @@ DoLoadTeam (PMELEE_STATE pMS) return (TRUE); } -// XXX: TODO: to be merged with DoTextEntry in gameopt.c -static UWORD -DoTextEntry (PMELEE_STATE pMS) -{ - UWORD ch; - UNICODE *pStr, *pBaseStr; - COUNT len, max_chars; - BOOLEAN left = FALSE, right = FALSE; - - if (pMS->MeleeOption == EDIT_MELEE) - { - pBaseStr = pMS->TeamImage[pMS->side].TeamName; - max_chars = MAX_TEAM_CHARS; - } - else - { - // Should not happen. Satisfying compiler. - return 0; - } - - ch = GetCharacter (); - - pStr = &pBaseStr[pMS->CurIndex]; - len = wstrlen (pStr); - switch (ch) - { - case SK_DELETE: - if (len) - { - memmove (pStr, pStr + 1, len * sizeof (*pStr)); - len = (COUNT)~0; - } - break; - case '\b': - if (pMS->CurIndex) - { - memmove (pStr - 1, pStr, (len + 1) * sizeof (*pStr)); - --pMS->CurIndex; - - len = (COUNT)~0; - } - break; - case SK_LF_ARROW: - left = TRUE; - break; - case SK_RT_ARROW: - right = TRUE; - break; - default: - if (isprint (ch) && (len + pStr - pBaseStr < (int)(max_chars))) - { - memmove (pStr + 1, pStr, (len + 1) * sizeof (*pStr)); - *pStr++ = ch; - ++pMS->CurIndex; - - len = (COUNT)~0; - } - break; - } - - if (len == (COUNT)~0) - DrawTeamString (pMS, 1); - else if (left) - { - if (pMS->CurIndex) - { - --pMS->CurIndex; - DrawTeamString (pMS, 1); - } - } - else if (right) - { - if (len) - { - ++pMS->CurIndex; - DrawTeamString (pMS, 1); - } - } - - return (ch); -} - static int WriteTeamImage (TEAM_IMAGE *pTI, uio_Stream *save_fp) { @@ -1205,6 +1133,21 @@ AdvanceCursor (PMELEE_STATE pMS) } } +static BOOLEAN +OnTeamNameChange (PTEXTENTRY_STATE pTES) +{ + PMELEE_STATE pMS = (PMELEE_STATE) pTES->CbParam; + BOOLEAN ret; + + pMS->CurIndex = pTES->InsPt - pTES->BaseStr; + + LockMutex (GraphicsLock); + ret = DrawTeamString (pMS, 1); + UnlockMutex (GraphicsLock); + + return ret; +} + static BOOLEAN DoEdit (PMELEE_STATE pMS) { @@ -1257,32 +1200,32 @@ DoEdit (PMELEE_STATE pMS) if (row == NUM_MELEE_ROWS) { - if (pMS->CurIndex != (BYTE)~0) - { - UNICODE ch; - LockMutex (GraphicsLock); - if (pMS->Initialized == 1) - { - FlushInput (); - pMS->Initialized = 2; - } - else if (((ch = DoTextEntry (pMS)) == '\n') || (ch == '\r')) - { - pMS->CurIndex = (BYTE)~0; - DrawTeamString (pMS, 4); - pMS->Initialized = 1; - DisableCharacterMode (); - } - UnlockMutex (GraphicsLock); - return (TRUE); - } - else if (PulsedInputState.key[KEY_MENU_SELECT]) + if (PulsedInputState.key[KEY_MENU_SELECT]) { + TEXTENTRY_STATE tes; + + // going to enter text + // XXX: CurIndex is abused here; DrawTeamString expects + // CurIndex to contain the current cursor position pMS->CurIndex = 0; LockMutex (GraphicsLock); - DrawTeamString (pMS, 1); + DrawTeamString (pMS, 1); /* draw input state */ UnlockMutex (GraphicsLock); - EnableCharacterMode (); + + tes.Initialized = FALSE; + tes.MenuRepeatDelay = 0; + tes.BaseStr = pMS->TeamImage[pMS->side].TeamName; + tes.MaxSize = MAX_TEAM_CHARS + 1; + tes.CbParam = pMS; + tes.ChangeCallback = OnTeamNameChange; + DoTextEntry (&tes); + + // done entering + pMS->CurIndex = (BYTE)~0; + LockMutex (GraphicsLock); + DrawTeamString (pMS, 4); /* draw normal state */ + UnlockMutex (GraphicsLock); + return (TRUE); } } diff --git a/sc2/src/sc2code/planets/pstarmap.c b/sc2/src/sc2code/planets/pstarmap.c index dec428ed9..836a6401f 100644 --- a/sc2/src/sc2code/planets/pstarmap.c +++ b/sc2/src/sc2code/planets/pstarmap.c @@ -619,10 +619,7 @@ DoMoveCursor (PMENU_STATE pMS) pMS->MenuRepeatDelay = (COUNT)pMS->CurState; if (!pMS->Initialized) { - pMS->Initialized = MAKE_WORD ( - KBDToUNICODE (SK_INSERT), - KBDToUNICODE (SK_DELETE) - ); + pMS->Initialized = TRUE; pMS->InputFunc = DoMoveCursor; SetMenuRepeatDelay (MIN_ACCEL_DELAY, MAX_ACCEL_DELAY, STEP_ACCEL_DELAY, TRUE);