Universal text input, stage 2: Resurrected joystick text entry with Up/Down (bug #495); PageUp/PageDown (on keyboard) change the letter case, Delete/BackSpace keys should also be mapped onto a joystick in keys.cfg

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2151 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2006-01-05 21:47:24 +00:00
parent 2232e16709
commit af48a0f83a
6 changed files with 186 additions and 125 deletions
+5
View File
@@ -20,6 +20,7 @@
#define _CONTROLS_H_
#include "libs/compiler.h"
#include "libs/strlib.h"
// Enumerated type for controls
@@ -115,6 +116,10 @@ typedef struct textentry_state
BOOLEAN Initialized;
BOOLEAN Success; // edit confirmed or canceled
UNICODE *CacheStr; // cached copy to revert immediate changes
STRING JoyAlphaString; // joystick alphabet definition
BOOLEAN JoystickMode; // TRUE when doing joystick input
BOOLEAN UpperRegister; // TRUE when entering Caps
UNICODE *JoyAlphaStr; // joystick alphabet
// 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
+37 -16
View File
@@ -205,8 +205,12 @@ FeedbackQuit (BYTE which_setting)
UnlockMutex (GraphicsLock);
}
#define DDSHS_NORMAL 0
#define DDSHS_EDIT 1
#define DDSHS_BLOCKCUR 2
static BOOLEAN
DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, SIZE state)
DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, COUNT state)
{
COUNT rel_index;
RECT r;
@@ -255,8 +259,10 @@ DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, SIZE state)
lf.pStr = ((GAME_DESC *)pMS->CurString)[rel_index];
lf.CharCount = (COUNT)~0;
if (state <= 0)
if (!(state & DDSHS_EDIT))
{ // normal state
SetFlashRect ((PRECT)~0L, (FRAME)0);
if (pMS->InputFunc == DoNaming)
{
if (pMS->CurState == CHANGE_CAPTAIN_SETTING)
@@ -269,7 +275,9 @@ DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, SIZE state)
}
}
else
{
{ // XXX: remnants of DOS? this function is never actually
// called outside DoNaming nowadays, which makes this
// code utterly dead
if (state == 0)
{
COLOR OldColor;
@@ -280,8 +288,6 @@ DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, SIZE state)
}
font_DrawText (&lf);
}
SetFlashRect (&r, (FRAME)0);
SetFlashRect ((PRECT)~0L, (FRAME)0);
}
else
{ // editing state
@@ -307,17 +313,27 @@ DrawDescriptionString (PMENU_STATE pMS, COUNT which_string, SIZE state)
text_r.corner.x += (SIZE)*pchar_deltas++;
if ((COUNT)pMS->first_item.x < lf.CharCount) /* end of line */
--text_r.corner.x;
text_r.extent.width = 1;
#if 0
/* This is code that's a remnant of non-keyboard systems */
else
{
if ((COUNT)pMS->first_item.x == lf.CharCount) /* end of line */
if (state & DDSHS_BLOCKCUR)
{ // Use block cursor for keyboardless systems
if ((COUNT)pMS->first_item.x == lf.CharCount)
{ // cursor at end-line -- use insertion point
text_r.extent.width = 1;
}
else if ((COUNT)pMS->first_item.x + 1 == lf.CharCount)
{ // extra pixel for last char margin
text_r.extent.width = (SIZE)*pchar_deltas + 2;
}
else
text_r.extent.width = (SIZE)*pchar_deltas;
{ // normal mid-line char
text_r.extent.width = (SIZE)*pchar_deltas + 1;
}
}
#endif
else
{ // Insertion point cursor
text_r.extent.width = 1;
}
text_r.corner.y = r.corner.y;
text_r.extent.height = r.extent.height;
SetContextForeGroundColor (BLACK_COLOR);
@@ -337,8 +353,13 @@ static BOOLEAN
OnNameChange (PTEXTENTRY_STATE pTES)
{
PMENU_STATE pMS = (PMENU_STATE) pTES->CbParam;
COUNT hl = DDSHS_EDIT;
pMS->first_item.x = pTES->InsPt - pTES->BaseStr;
return DrawDescriptionString (pMS, 0, 1);
if (pTES->JoystickMode)
hl |= DDSHS_BLOCKCUR;
return DrawDescriptionString (pMS, 0, hl);
}
static BOOLEAN
@@ -363,7 +384,7 @@ DoNaming (PMENU_STATE pMS)
// XXX: nasty hack; CurString may not be large enough to
// contain a pointer on some platforms
pMS->CurString = (STRING)buf;
DrawDescriptionString (pMS, 0, 1);
DrawDescriptionString (pMS, 0, DDSHS_EDIT);
LockMutex (GraphicsLock);
DrawStatusMessage (GAME_STRING (NAMING_STRING_BASE + 0));
@@ -391,7 +412,7 @@ DoNaming (PMENU_STATE pMS)
wstrcpy (Setting, buf);
else
wstrcpy (buf, Setting);
DrawDescriptionString (pMS, 0, 0);
DrawDescriptionString (pMS, 0, DDSHS_NORMAL);
SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
+98 -86
View File
@@ -23,72 +23,10 @@
#include "globdata.h"
#include "sounds.h"
#include "settings.h"
#include "resinst.h"
#include "nameref.h"
static UWORD cur_char = ' ';
void
SetJoystickChar (UWORD which_char)
{
if (!isalnum (cur_char = which_char))
cur_char = ' ';
}
UWORD
GetJoystickChar (void)
{
int dy;
UWORD old_char;
if (PulsedInputState.key[KEY_MENU_SELECT])
return ('\n');
else if (PulsedInputState.key[KEY_MENU_CANCEL])
return (0x1B);
else if (PulsedInputState.key[KEY_MENU_SPECIAL])
return (0x7F);
old_char = cur_char;
dy = 0;
if (PulsedInputState.key[KEY_MENU_UP]) dy = -1;
else if (PulsedInputState.key[KEY_MENU_DOWN]) dy = 1;
if (dy)
{
if (cur_char == ' ')
{
if (dy > 0)
cur_char = 'a';
else /* if (dy < 0) */
cur_char = '9';
}
else if (isdigit (cur_char))
{
cur_char += dy;
if (cur_char < '0')
cur_char = 'z';
else if (cur_char > '9')
cur_char = ' ';
}
else if (!isalpha (cur_char += dy))
{
cur_char -= dy;
if (cur_char == 'a' || cur_char == 'A')
cur_char = ' ';
else
cur_char = '0';
}
}
if ((PulsedInputState.key[KEY_MENU_PAGE_UP] || PulsedInputState.key[KEY_MENU_PAGE_DOWN]) && isalpha (cur_char))
{
if (islower (cur_char))
cur_char = toupper (cur_char);
else
cur_char = tolower (cur_char);
}
return (cur_char == old_char ? 0 : cur_char);
}
BOOLEAN
DoTextEntry (PTEXTENTRY_STATE pTES)
{
@@ -108,11 +46,18 @@ DoTextEntry (PTEXTENTRY_STATE pTES)
pTES->CacheStr = HMalloc (pTES->MaxSize);
pTES->Success = FALSE;
pTES->Initialized = TRUE;
pTES->JoystickMode = FALSE;
pTES->UpperRegister = TRUE;
pTES->JoyAlphaString = CaptureStringTable (
LoadStringTable (JOYSTICK_ALPHA_STRTAB));
pTES->JoyAlphaStr = GetStringAddress (
SetAbsStringTableIndex (pTES->JoyAlphaString, 0));
DoInput (pTES, TRUE);
if (pTES->CacheStr)
HFree (pTES->CacheStr);
DestroyStringTable ( ReleaseStringTable (pTES->JoyAlphaString));
return pTES->Success;
}
@@ -125,8 +70,15 @@ DoTextEntry (PTEXTENTRY_STATE pTES)
pTES->CacheStr[pTES->MaxSize - 1] = '\0';
// process the pending character buffer
while (ch = GetNextCharacter ())
ch = GetNextCharacter ();
if (!ch && PulsedInputState.key[KEY_CHARACTER])
{ // keyboard repeat, but only when buffer empty
ch = GetLastCharacter ();
}
while (ch)
{
pTES->JoystickMode = FALSE;
if (isprint (ch) && (pStr + len - pTES->BaseStr + 1 < pTES->MaxSize))
{
memmove (pStr + 1, pStr, (len + 1) * sizeof (*pStr));
@@ -135,22 +87,9 @@ DoTextEntry (PTEXTENTRY_STATE pTES)
++len;
changed = TRUE;
}
ch = GetNextCharacter ();
}
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)
@@ -202,13 +141,86 @@ DoTextEntry (PTEXTENTRY_STATE pTES)
changed = TRUE;
}
}
else if (PulsedInputState.key[KEY_MENU_UP])
{
// do joystick text
}
else if (PulsedInputState.key[KEY_MENU_DOWN])
{
// do joystick text
if (pTES->JoyAlphaStr && (
PulsedInputState.key[KEY_MENU_UP] ||
PulsedInputState.key[KEY_MENU_DOWN] ||
PulsedInputState.key[KEY_MENU_PAGE_UP] ||
PulsedInputState.key[KEY_MENU_PAGE_DOWN]) )
{ // do joystick text
UNICODE newch;
UNICODE cmpch;
int i;
pTES->JoystickMode = TRUE;
if (len)
ch = *pStr;
else
ch = pTES->JoyAlphaStr[0];
newch = ch;
cmpch = toupper (ch);
// find current char in the alphabet
for (i = 0; pTES->JoyAlphaStr[i] != cmpch
&& pTES->JoyAlphaStr[i] != '\0'; ++i)
;
if (PulsedInputState.key[KEY_MENU_UP])
{
--i;
if (i < 0)
i = wstrlen (pTES->JoyAlphaStr) - 1;
newch = pTES->JoyAlphaStr[i];
}
else if (PulsedInputState.key[KEY_MENU_DOWN])
{
++i;
if (i >= (int)wstrlen(pTES->JoyAlphaStr))
newch = pTES->JoyAlphaStr[0];
else
newch = pTES->JoyAlphaStr[i];
}
if (PulsedInputState.key[KEY_MENU_PAGE_UP] ||
PulsedInputState.key[KEY_MENU_PAGE_DOWN])
{
if (len)
{ // single char change
if (islower (newch))
newch = toupper (newch);
else
newch = tolower (newch);
}
else
{ // register change
pTES->UpperRegister = !pTES->UpperRegister;
}
}
else
{ // check register
if (pTES->UpperRegister)
newch = toupper (newch);
else
newch = tolower (newch);
}
if (newch != ch)
{
if (len)
{ // change current
pStr[0] = newch;
changed = TRUE;
}
else if (pStr + len - pTES->BaseStr + 1 < pTES->MaxSize)
{ // append
pStr[0] = newch;
pStr[1] = '\0';
++len;
changed = TRUE;
}
}
}
if (PulsedInputState.key[KEY_MENU_SELECT])
+1
View File
@@ -100,4 +100,5 @@
#define INTROPRES_STRTAB 0x23c06204L
#define FINALPRES_STRTAB 0x23e06304L
#define CREDITS_STRTAB 0x24206404L
#define JOYSTICK_ALPHA_STRTAB 0x24406504L
+44 -23
View File
@@ -138,10 +138,19 @@ PMELEE_STATE volatile pMeleeState;
static BOOLEAN DoMelee (PMELEE_STATE pMS);
static BOOLEAN DoEdit (PMELEE_STATE pMS);
static BOOLEAN DoPickShip (PMELEE_STATE pMS);
#define DTSHS_NORMAL 0
#define DTSHS_EDIT 1
#define DTSHS_SELECTED 2
#define DTSHS_REPAIR 4
#define DTSHS_BLOCKCUR 8
static BOOLEAN DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState);
static BOOLEAN DoLoadTeam (PMELEE_STATE pMS);
static void DrawFileStrings (PMELEE_STATE pMS, int HiLiteState);
static void
DrawMeleeIcon (COUNT which_icon)
{
@@ -310,7 +319,7 @@ RepairMeleeFrame (PRECT pRect)
DrawShipBox (pMeleeState, FALSE);
}
DrawTeamString (pMeleeState, 0);
DrawTeamString (pMeleeState, DTSHS_NORMAL);
}
pMeleeState->side = old_side;
pMeleeState->row = old_row;
@@ -337,15 +346,12 @@ DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState)
+ ((MELEE_BOX_HEIGHT + MELEE_BOX_SPACE) * NUM_MELEE_ROWS + 2));
r.extent.width = NUM_MELEE_COLUMNS * (MELEE_BOX_WIDTH + MELEE_BOX_SPACE);
r.extent.height = 13;
if (HiLiteState == 4)
if (HiLiteState == DTSHS_REPAIR)
{
RepairMeleeFrame (&r);
return (TRUE);
}
if (HiLiteState & 1)
r.extent.width -= 29;
SetContextFont (MicroFont);
lfText.pStr = pMS->TeamImage[pMS->side].TeamName;
@@ -356,7 +362,7 @@ DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState)
lfText.CharCount = wstrlen (lfText.pStr); // (COUNT)~0;
BatchGraphics ();
if (!(HiLiteState & 1))
if (!(HiLiteState & DTSHS_EDIT))
{ // normal or selected state
TEXT rtText;
UNICODE buf[10];
@@ -368,7 +374,7 @@ DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState)
rtText.baseline.y = lfText.baseline.y;
rtText.baseline.x = lfText.baseline.x + r.extent.width - 1;
SetContextForeGroundColor (HiLiteState == 0
SetContextForeGroundColor (!(HiLiteState & DTSHS_SELECTED)
? TEAM_NAME_TEXT_COLOR : TEAM_NAME_EDIT_TEXT_COLOR);
font_DrawText (&lfText);
font_DrawText (&rtText);
@@ -380,6 +386,9 @@ DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState)
BYTE char_deltas[MAX_TEAM_CHARS];
PBYTE pchar_deltas;
// not drawing team bucks
r.extent.width -= 29;
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
@@ -397,19 +406,28 @@ DrawTeamString (PMELEE_STATE pMS, COUNT HiLiteState)
pchar_deltas = char_deltas;
for (i = pMS->CurIndex; i > 0; --i)
text_r.corner.x += (SIZE)*pchar_deltas++;
if (pMS->CurIndex < lfText.CharCount) /* end of line */
if (pMS->CurIndex < lfText.CharCount) /* cursor mid-line */
--text_r.corner.x;
text_r.extent.width = 1;
#if 0
/* Code for keyboardless systems */
else
{
if (pMS->CurIndex == lfText.CharCount) /* end of line */
if (HiLiteState & DTSHS_BLOCKCUR)
{ // Use block cursor for keyboardless systems
if (pMS->CurIndex == lfText.CharCount)
{ // cursor at end-line -- use insertion point
text_r.extent.width = 1;
}
else if (pMS->CurIndex + 1 == lfText.CharCount)
{ // extra pixel for last char margin
text_r.extent.width = (SIZE)*pchar_deltas + 2;
}
else
text_r.extent.width = (SIZE)*pchar_deltas;
{ // normal mid-line char
text_r.extent.width = (SIZE)*pchar_deltas + 1;
}
}
#endif
else
{ // Insertion point cursor
text_r.extent.width = 1;
}
// position cursor within input field rect
++text_r.corner.x;
++text_r.corner.y;
text_r.extent.height -= 2;
@@ -490,7 +508,7 @@ Deselect (BYTE opt)
if (pMeleeState->row < NUM_MELEE_ROWS)
DrawShipBox (pMeleeState, FALSE);
else if (pMeleeState->CurIndex == (BYTE)~0)
DrawTeamString (pMeleeState, 0);
DrawTeamString (pMeleeState, DTSHS_NORMAL);
}
else if (pMeleeState->InputFunc == DoPickShip)
{
@@ -536,7 +554,7 @@ Select (BYTE opt)
if (pMeleeState->row < NUM_MELEE_ROWS)
DrawShipBox (pMeleeState, TRUE);
else if (pMeleeState->CurIndex == (BYTE)~0)
DrawTeamString (pMeleeState, 2);
DrawTeamString (pMeleeState, DTSHS_SELECTED);
}
else if (pMeleeState->InputFunc == DoPickShip)
{
@@ -1113,7 +1131,7 @@ DeleteCurrentShip (PMELEE_STATE pMS)
GetShipBox (&r, pMS->side, pMS->row, pMS->col);
RepairMeleeFrame (&r);
DrawTeamString (pMS, 4);
DrawTeamString (pMS, DTSHS_REPAIR);
UnlockMutex (GraphicsLock);
}
@@ -1138,11 +1156,14 @@ OnTeamNameChange (PTEXTENTRY_STATE pTES)
{
PMELEE_STATE pMS = (PMELEE_STATE) pTES->CbParam;
BOOLEAN ret;
COUNT hl = DTSHS_EDIT;
pMS->CurIndex = pTES->InsPt - pTES->BaseStr;
if (pTES->JoystickMode)
hl |= DTSHS_BLOCKCUR;
LockMutex (GraphicsLock);
ret = DrawTeamString (pMS, 1);
ret = DrawTeamString (pMS, hl);
UnlockMutex (GraphicsLock);
return ret;
@@ -1209,7 +1230,7 @@ DoEdit (PMELEE_STATE pMS)
// CurIndex to contain the current cursor position
pMS->CurIndex = 0;
LockMutex (GraphicsLock);
DrawTeamString (pMS, 1); /* draw input state */
DrawTeamString (pMS, DTSHS_EDIT);
UnlockMutex (GraphicsLock);
tes.Initialized = FALSE;
@@ -1223,7 +1244,7 @@ DoEdit (PMELEE_STATE pMS)
// done entering
pMS->CurIndex = (BYTE)~0;
LockMutex (GraphicsLock);
DrawTeamString (pMS, 4); /* draw normal state */
DrawTeamString (pMS, DTSHS_REPAIR);
UnlockMutex (GraphicsLock);
return (TRUE);
@@ -1346,7 +1367,7 @@ DoPickShip (PMELEE_STATE pMS)
pMS->TeamImage[pMS->side].ShipList[pMS->row][pMS->col] = pMS->CurIndex;
LockMutex (GraphicsLock);
DrawTeamString (pMS, 4);
DrawTeamString (pMS, DTSHS_REPAIR);
DrawShipBox (pMS, FALSE);
UnlockMutex (GraphicsLock);
AdvanceCursor (pMS);
+1
View File
@@ -307,5 +307,6 @@ enum
FINAL_PACKAGE,
CREDIT_FONTS_PACKAGE,
CREDITS_PACKAGE,
JOYSTICK_ALPHA_PACKAGE,
};