static void DrawDevice (COUNT device, COUNT pos, bool selected) { RECT r; TEXT t; t.align = ALIGN_CENTER; t.baseline.x = DEVICE_COL_1; r.extent.width = DEVICE_SEL_WIDTH; r.extent.height = TEXT_SPACING_Y * 2; r.corner.x = DEVICE_SEL_ORG_X; // draw line background r.corner.y = DEVICE_ORG_Y + pos * DEVICE_SPACING_Y + NAME_OFS_Y; SetContextForeGroundColor (selected ? DEVICES_SELECTED_BACK_COLOR : DEVICES_BACK_COLOR); DrawFilledRectangle (&r); SetContextFont (TinyFont); // print device name SetContextForeGroundColor (selected ? DEVICES_SELECTED_NAME_COLOR : DEVICES_NAME_COLOR); t.baseline.y = r.corner.y + TEXT_BASELINE; t.pStr = GAME_STRING (device + DEVICE_STRING_BASE + 1); t.CharCount = utf8StringPos (t.pStr, ' '); font_DrawText (&t); t.baseline.y += TEXT_SPACING_Y; t.pStr = skipUTF8Chars (t.pStr, t.CharCount + 1); t.CharCount = (COUNT)~0; font_DrawText (&t); }
static int ReadOneChar (joy_char_t *ch, const UNICODE *str) { UNICODE *next = skipUTF8Chars (str, 1); int len = next - str; ch->len = len; memcpy (ch->enc, str, len); ch->enc[len] = '\0'; // string term return len; }
static void DrawDevices (PMENU_STATE pMS, BYTE OldDevice, BYTE NewDevice) { #define MAX_VIS_DEVICES 5 COORD y, cy; TEXT t; RECT r; PBYTE pDeviceMap; LockMutex (GraphicsLock); SetContext (StatusContext); SetContextFont (TinyFont); y = 41; t.baseline.x = 40; t.align = ALIGN_CENTER; t.CharCount = 3; pDeviceMap = (PBYTE)pMS->CurFrame; if (OldDevice > NUM_DEVICES || (NewDevice < NUM_DEVICES && (NewDevice < (BYTE)pMS->first_item.y || NewDevice >= (BYTE)(pMS->first_item.y + MAX_VIS_DEVICES)))) { STAMP s; r.corner.x = 2; r.extent.width = FIELD_WIDTH + 1; if (!(pMS->Initialized & 1)) { ++r.corner.x; r.extent.width -= 2; r.corner.y = 33; r.extent.height = 89; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); DrawFilledRectangle (&r); } else { TEXT ct; r.corner.y = 20; r.extent.height = 109; DrawStarConBox (&r, 1, BUILD_COLOR (MAKE_RGB15 (0x10, 0x10, 0x10), 0x19), BUILD_COLOR (MAKE_RGB15 (0x08, 0x08, 0x08), 0x1F), TRUE, BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01)); SetContextFont (StarConFont); ct.baseline.x = (STATUS_WIDTH >> 1) - 1; ct.baseline.y = 27; ct.align = ALIGN_CENTER; ct.pStr = GAME_STRING (DEVICE_STRING_BASE); ct.CharCount = (COUNT)~0; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x0A, 0x1F, 0x1F), 0x0B)); font_DrawText (&ct); SetContextFont (TinyFont); } if (NewDevice < (BYTE)pMS->first_item.y) pMS->first_item.y = NewDevice; else if (NewDevice >= (BYTE)(pMS->first_item.y + MAX_VIS_DEVICES)) pMS->first_item.y = NewDevice - (MAX_VIS_DEVICES - 1); s.origin.x = 4; s.origin.y = 34; cy = y; SetContextForeGroundColor ( BUILD_COLOR (MAKE_RGB15 (0x00, 0x14, 0x14), 0x03)); for (OldDevice = (BYTE)pMS->first_item.y; OldDevice < (BYTE)(pMS->first_item.y + MAX_VIS_DEVICES) && OldDevice < (BYTE)pMS->first_item.x; ++OldDevice) { s.frame = SetAbsFrameIndex ( MiscDataFrame, 77 + pDeviceMap[OldDevice]); DrawStamp (&s); if (OldDevice != NewDevice) { t.baseline.y = cy; t.pStr = GAME_STRING (pDeviceMap[OldDevice] + DEVICE_STRING_BASE + 1); t.CharCount = utf8StringPos (t.pStr, ' '); font_DrawText (&t); t.baseline.y += 7; t.pStr = skipUTF8Chars (t.pStr, t.CharCount + 1); t.CharCount = (COUNT)~0; font_DrawText (&t); } cy += 18; s.origin.y += 18; } OldDevice = NewDevice; }
BOOLEAN DoTextEntry (PTEXTENTRY_STATE pTES) { wchar_t ch; UNICODE *pStr; UNICODE *CacheInsPt; int CacheCursorPos; int len; BOOLEAN changed = FALSE; if (GLOBAL (CurrentActivity) & CHECK_ABORT) return (FALSE); if (!pTES->Initialized) { // init basic vars int lwlen; pTES->InputFunc = DoTextEntry; pTES->Success = FALSE; pTES->Initialized = TRUE; pTES->JoystickMode = FALSE; pTES->UpperRegister = TRUE; // init insertion point if ((size_t)pTES->CursorPos > utf8StringCount (pTES->BaseStr)) pTES->CursorPos = utf8StringCount (pTES->BaseStr); pTES->InsPt = skipUTF8Chars (pTES->BaseStr, pTES->CursorPos); // load joystick alphabet pTES->JoyAlphaString = CaptureStringTable ( LoadStringTable (JOYSTICK_ALPHA_STRTAB)); pTES->JoyAlpha = LoadJoystickAlpha ( SetAbsStringTableIndex (pTES->JoyAlphaString, 0), &pTES->JoyAlphaLength); pTES->JoyUpper = LoadJoystickAlpha ( SetAbsStringTableIndex (pTES->JoyAlphaString, 1), &pTES->JoyRegLength); pTES->JoyLower = LoadJoystickAlpha ( SetAbsStringTableIndex (pTES->JoyAlphaString, 2), &lwlen); if (lwlen != pTES->JoyRegLength) { if (lwlen < pTES->JoyRegLength) pTES->JoyRegLength = lwlen; log_add (log_Warning, "Warning: Joystick upper-lower registers" " size mismatch; using the smallest subset (%d)", pTES->JoyRegLength); } pTES->CacheStr = HMalloc (pTES->MaxSize * sizeof (*pTES->CacheStr)); DoInput (pTES, TRUE); if (pTES->CacheStr) HFree (pTES->CacheStr); if (pTES->JoyLower) HFree (pTES->JoyLower); if (pTES->JoyUpper) HFree (pTES->JoyUpper); if (pTES->JoyAlpha) HFree (pTES->JoyAlpha); DestroyStringTable ( ReleaseStringTable (pTES->JoyAlphaString)); return pTES->Success; } pStr = pTES->InsPt; len = strlen (pStr); // save a copy of string CacheInsPt = pTES->InsPt; CacheCursorPos = pTES->CursorPos; memcpy (pTES->CacheStr, pTES->BaseStr, pTES->MaxSize); // process the pending character buffer ch = GetNextCharacter (); if (!ch && PulsedInputState.menu[KEY_MENU_ANY]) { // keyboard repeat, but only when buffer empty ch = GetLastCharacter (); } while (ch) { UNICODE chbuf[8]; int chsize; pTES->JoystickMode = FALSE; chsize = getStringFromChar (chbuf, sizeof (chbuf), ch); if (isWidePrintChar (ch) && chsize > 0) { if (pStr + len - pTES->BaseStr + chsize < pTES->MaxSize) { // insert character, when fits memmove (pStr + chsize, pStr, len + 1); memcpy (pStr, chbuf, chsize); pStr += chsize; ++pTES->CursorPos; changed = TRUE; } else { // does not fit PlayMenuSound (MENU_SOUND_FAILURE); } } ch = GetNextCharacter (); } if (PulsedInputState.menu[KEY_MENU_DELETE]) { if (len) { joy_char_t ch; ReadOneChar (&ch, pStr); memmove (pStr, pStr + ch.len, len - ch.len + 1); len -= ch.len; changed = TRUE; } } else if (PulsedInputState.menu[KEY_MENU_BACKSPACE]) { if (pStr > pTES->BaseStr) { UNICODE *prev = skipUTF8Chars (pTES->BaseStr, pTES->CursorPos - 1); memmove (prev, pStr, len + 1); pStr = prev; --pTES->CursorPos; changed = TRUE; } } else if (PulsedInputState.menu[KEY_MENU_LEFT]) { if (pStr > pTES->BaseStr) { UNICODE *prev = skipUTF8Chars (pTES->BaseStr, pTES->CursorPos - 1); pStr = prev; len += (prev - pStr); --pTES->CursorPos; changed = TRUE; } } else if (PulsedInputState.menu[KEY_MENU_RIGHT]) { if (len > 0) { joy_char_t ch; ReadOneChar (&ch, pStr); pStr += ch.len; len -= ch.len; ++pTES->CursorPos; changed = TRUE; } } else if (PulsedInputState.menu[KEY_MENU_HOME]) { if (pStr > pTES->BaseStr) { pStr = pTES->BaseStr; len = strlen (pStr); pTES->CursorPos = 0; changed = TRUE; } } else if (PulsedInputState.menu[KEY_MENU_END]) { if (len > 0) { pTES->CursorPos += utf8StringCount (pStr); pStr += len; len = 0; changed = TRUE; } } if (pTES->JoyAlpha && ( PulsedInputState.menu[KEY_MENU_UP] || PulsedInputState.menu[KEY_MENU_DOWN] || PulsedInputState.menu[KEY_MENU_PAGE_UP] || PulsedInputState.menu[KEY_MENU_PAGE_DOWN]) ) { // do joystick text joy_char_t ch; joy_char_t newch; joy_char_t cmpch; int i; pTES->JoystickMode = TRUE; if (len) ReadOneChar (&ch, pStr); else ch = pTES->JoyAlpha[0]; newch = ch; JoyCharToUpper (&cmpch, &ch, pTES); // find current char in the alphabet i = JoyCharFindIn (&cmpch, pTES->JoyAlpha, pTES->JoyAlphaLength); if (PulsedInputState.menu[KEY_MENU_UP]) { --i; if (i < 0) i = pTES->JoyAlphaLength - 1; newch = pTES->JoyAlpha[i]; } else if (PulsedInputState.menu[KEY_MENU_DOWN]) { ++i; if (i >= pTES->JoyAlphaLength) i = 0; newch = pTES->JoyAlpha[i]; } if (PulsedInputState.menu[KEY_MENU_PAGE_UP] || PulsedInputState.menu[KEY_MENU_PAGE_DOWN]) { if (len) { // single char change if (JoyCharIsLower (&newch, pTES)) JoyCharToUpper (&newch, &newch, pTES); else JoyCharToLower (&newch, &newch, pTES); } else { // register change pTES->UpperRegister = !pTES->UpperRegister; } } else { // check register if (pTES->UpperRegister) JoyCharToUpper (&newch, &newch, pTES); else JoyCharToLower (&newch, &newch, pTES); } if (strcmp (newch.enc, ch.enc) != 0) { // new char is different, put it in if (len) { // change current -- this is messy with utf8 int l = len - ch.len; if (pStr + l - pTES->BaseStr + newch.len < pTES->MaxSize) { // adjust other chars if necessary if (newch.len != ch.len) memmove (pStr + newch.len, pStr + ch.len, l + 1); memcpy (pStr, newch.enc, newch.len); len = l + newch.len; changed = TRUE; } } else { // append if (pStr + len - pTES->BaseStr + newch.len < pTES->MaxSize) { memcpy (pStr, newch.enc, newch.len); pStr[newch.len] = '\0'; len += newch.len; changed = TRUE; } else { // does not fit PlayMenuSound (MENU_SOUND_FAILURE); } } } } if (PulsedInputState.menu[KEY_MENU_SELECT]) { // done entering pTES->Success = TRUE; return FALSE; } else if (PulsedInputState.menu[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 memcpy (pTES->BaseStr, pTES->CacheStr, pTES->MaxSize); pTES->InsPt = CacheInsPt; pTES->CursorPos = CacheCursorPos; PlayMenuSound (MENU_SOUND_FAILURE); } } if (pTES->FrameCallback) return pTES->FrameCallback (pTES); return TRUE; }