Various star-search interface changes

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2193 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2006-01-19 00:07:48 +00:00
parent 4248dfa17c
commit 1de77b58d0
4 changed files with 163 additions and 127 deletions
+7 -13
View File
@@ -269,22 +269,12 @@ utf8StringCopy (unsigned char *dst, size_t size, const unsigned char *src)
return dst; return dst;
} }
// TODO: Better matching. It's now just based on the char number. // TODO: this is not implemented with respect to collating order
static inline int
utf8CompareChar (wchar_t ch1, wchar_t ch2)
{
if (ch1 < ch2)
return -1;
if (ch1 > ch2)
return 1;
return 0;
}
int int
utf8StringCompare (const unsigned char *str1, const unsigned char *str2) utf8StringCompare (const unsigned char *str1, const unsigned char *str2)
{ {
#if 0
// wchar_t comparing version
wchar_t ch1; wchar_t ch1;
wchar_t ch2; wchar_t ch2;
@@ -319,6 +309,10 @@ utf8StringCompare (const unsigned char *str1, const unsigned char *str2)
// ch1 == '\0' && ch2 == '\0'. // ch1 == '\0' && ch2 == '\0'.
// Strings match completely. // Strings match completely.
return 0; return 0;
#else
// this will do for now
return strcmp (str1, str2);
#endif
} }
unsigned char * unsigned char *
+1
View File
@@ -61,6 +61,7 @@ size_t utf8StringCountN(const unsigned char *start,
int utf8StringPos (const unsigned char *pStr, wchar_t ch); int utf8StringPos (const unsigned char *pStr, wchar_t ch);
unsigned char *utf8StringCopy (unsigned char *dst, size_t size, unsigned char *utf8StringCopy (unsigned char *dst, size_t size,
const unsigned char *src); const unsigned char *src);
int utf8StringCompare (const unsigned char *str1, const unsigned char *str2);
unsigned char *skipUTF8Chars(const unsigned char *ptr, size_t num); unsigned char *skipUTF8Chars(const unsigned char *ptr, size_t num);
size_t getWideFromString(wchar_t *wstr, size_t maxcount, size_t getWideFromString(wchar_t *wstr, size_t maxcount,
const unsigned char *start); const unsigned char *start);
+147 -106
View File
@@ -792,6 +792,7 @@ UpdateFuelRequirement (PMENU_STATE pMS)
typedef struct starsearch_state typedef struct starsearch_state
{ {
PMENU_STATE pMS; PMENU_STATE pMS;
UNICODE Text[STAR_SEARCH_BUFSIZE];
UNICODE LastText[STAR_SEARCH_BUFSIZE]; UNICODE LastText[STAR_SEARCH_BUFSIZE];
DWORD LastChangeTime; DWORD LastChangeTime;
int FirstIndex; int FirstIndex;
@@ -802,19 +803,22 @@ typedef struct starsearch_state
UNICODE Buffer[STAR_SEARCH_BUFSIZE]; UNICODE Buffer[STAR_SEARCH_BUFSIZE];
UNICODE *Prefix; UNICODE *Prefix;
UNICODE *Cluster; UNICODE *Cluster;
int SortedStars[NUM_SOLAR_SYSTEMS];
int PrefixLen; int PrefixLen;
int ClusterLen; int ClusterLen;
int ClusterPos;
int SortedStars[NUM_SOLAR_SYSTEMS];
} STAR_SEARCH_STATE; } STAR_SEARCH_STATE;
static int static int
compStarName (const void *ptr1, const void *ptr2) { compStarName (const void *ptr1, const void *ptr2)
{
int index1; int index1;
int index2; int index2;
index1 = *(const int *) ptr1; index1 = *(const int *) ptr1;
index2 = *(const int *) ptr2; index2 = *(const int *) ptr2;
if (star_array[index1].Postfix != star_array[index2].Postfix) { if (star_array[index1].Postfix != star_array[index2].Postfix)
{
return utf8StringCompare (GAME_STRING (star_array[index1].Postfix), return utf8StringCompare (GAME_STRING (star_array[index1].Postfix),
GAME_STRING (star_array[index2].Postfix)); GAME_STRING (star_array[index2].Postfix));
} }
@@ -829,7 +833,8 @@ compStarName (const void *ptr1, const void *ptr2) {
} }
static void static void
SortStarsOnName (STAR_SEARCH_STATE *pSS) { SortStarsOnName (STAR_SEARCH_STATE *pSS)
{
int i; int i;
int *sorted = pSS->SortedStars; int *sorted = pSS->SortedStars;
@@ -839,39 +844,18 @@ SortStarsOnName (STAR_SEARCH_STATE *pSS) {
qsort (sorted, NUM_SOLAR_SYSTEMS, sizeof (int), compStarName); qsort (sorted, NUM_SOLAR_SYSTEMS, sizeof (int), compStarName);
} }
static BOOLEAN
OnStarNameChange (PTEXTENTRY_STATE pTES)
{
STAR_SEARCH_STATE *pSS = (STAR_SEARCH_STATE *) pTES->CbParam;
COUNT flags = DSME_SETFR;
BOOLEAN ret;
if (strcmp (pTES->BaseStr, pSS->LastText) != 0)
{ // string changed
pSS->LastChangeTime = GetTimeCounter ();
strcpy (pSS->LastText, pTES->BaseStr);
}
if (pTES->JoystickMode)
flags |= DSME_BLOCKCUR;
LockMutex (GraphicsLock);
ret = DrawSISMessageEx (pTES->BaseStr, pTES->CursorPos, -1, flags);
UnlockMutex (GraphicsLock);
return ret;
}
static void static void
SplitStarName (STAR_SEARCH_STATE *pSS) SplitStarName (STAR_SEARCH_STATE *pSS)
{ {
UNICODE *buf = pSS->Buffer; UNICODE *buf = pSS->Buffer;
UNICODE *next; UNICODE *next;
UNICODE *sep;
pSS->Prefix = 0; pSS->Prefix = 0;
pSS->PrefixLen = 0; pSS->PrefixLen = 0;
pSS->Cluster = 0; pSS->Cluster = 0;
pSS->ClusterLen = 0; pSS->ClusterLen = 0;
pSS->ClusterPos = 0;
// skip leading space // skip leading space
for (next = buf; *next != '\0' && getCharFromString (&next) == ' '; for (next = buf; *next != '\0' && getCharFromString (&next) == ' ';
@@ -890,7 +874,7 @@ SplitStarName (STAR_SEARCH_STATE *pSS)
; ;
if (*buf != '\0') if (*buf != '\0')
{ // found possibly separating ' ' { // found possibly separating ' '
*buf = '\0'; // split sep = buf;
// skip separating space // skip separating space
for (buf = next; *next != '\0' && getCharFromString (&next) == ' '; for (buf = next; *next != '\0' && getCharFromString (&next) == ' ';
buf = next) buf = next)
@@ -901,6 +885,7 @@ SplitStarName (STAR_SEARCH_STATE *pSS)
{ // reached the end -- cluster only { // reached the end -- cluster only
pSS->Cluster = pSS->Prefix; pSS->Cluster = pSS->Prefix;
pSS->ClusterLen = utf8StringCount (pSS->Cluster); pSS->ClusterLen = utf8StringCount (pSS->Cluster);
pSS->ClusterPos = utf8StringCountN (pSS->Buffer, pSS->Cluster);
pSS->Prefix = 0; pSS->Prefix = 0;
return; return;
} }
@@ -908,21 +893,21 @@ SplitStarName (STAR_SEARCH_STATE *pSS)
// consider the rest cluster name (whatever there is) // consider the rest cluster name (whatever there is)
pSS->Cluster = buf; pSS->Cluster = buf;
pSS->ClusterLen = utf8StringCount (pSS->Cluster); pSS->ClusterLen = utf8StringCount (pSS->Cluster);
pSS->ClusterPos = utf8StringCountN (pSS->Buffer, pSS->Cluster);
*sep = '\0'; // split
pSS->PrefixLen = utf8StringCount (pSS->Prefix); pSS->PrefixLen = utf8StringCount (pSS->Prefix);
} }
// Returns the index in the sorted array with the specified Postfix. static inline int
static int SkipStarCluster (int *sortedStars, int istar)
GetFirstClusterStarIndex (int *sortedStars, BYTE Postfix)
{ {
// Linear search. A binary search would work, but why bother. int Postfix = star_array[sortedStars[istar]].Postfix;
int i;
for (i = 0; i < NUM_SOLAR_SYSTEMS; i++) { for (++istar; istar < NUM_SOLAR_SYSTEMS &&
if (star_array[sortedStars[i]].Postfix == Postfix) star_array[sortedStars[istar]].Postfix == Postfix;
return i; ++istar)
} ;
return -1; return istar;
} }
static int static int
@@ -945,7 +930,10 @@ FindNextStarIndex (STAR_SEARCH_STATE *pSS, int from, BOOLEAN WithinClust)
dlen = utf8StringCount (ClusterName); dlen = utf8StringCount (ClusterName);
if (pSS->ClusterLen > dlen) if (pSS->ClusterLen > dlen)
{ // no match, skip the rest of cluster
i = SkipStarCluster (pSS->SortedStars, i) - 1;
continue; continue;
}
for (c = 0, sptr = pSS->Cluster, dptr = ClusterName; for (c = 0, sptr = pSS->Cluster, dptr = ClusterName;
c < pSS->ClusterLen; ++c) c < pSS->ClusterLen; ++c)
@@ -958,7 +946,10 @@ FindNextStarIndex (STAR_SEARCH_STATE *pSS, int from, BOOLEAN WithinClust)
} }
if (c < pSS->ClusterLen) if (c < pSS->ClusterLen)
continue; // no match here { // no match here, skip the rest of cluster
i = SkipStarCluster (pSS->SortedStars, i) - 1;
continue;
}
if (!SDPtr->Prefix || WithinClust) if (!SDPtr->Prefix || WithinClust)
// singular star - prefix not checked // singular star - prefix not checked
@@ -968,11 +959,16 @@ FindNextStarIndex (STAR_SEARCH_STATE *pSS, int from, BOOLEAN WithinClust)
if (!pSS->Prefix) if (!pSS->Prefix)
{ // searching for cluster name only { // searching for cluster name only
// return only the first stars in a cluster // return only the first stars in a cluster
if (i == GetFirstClusterStarIndex ( if (i == 0 || SDPtr->Postfix !=
pSS->SortedStars, SDPtr->Postfix)) star_array[pSS->SortedStars[i - 1]].Postfix)
{ // found one
break; break;
}
else else
{ // another star in the same cluster, skip cluster
i = SkipStarCluster (pSS->SortedStars, i) - 1;
continue; continue;
}
} }
// check prefix // check prefix
@@ -1005,86 +1001,135 @@ DrawMatchedStarName (PTEXTENTRY_STATE pTES)
PMENU_STATE pMS = pSS->pMS; PMENU_STATE pMS = pSS->pMS;
UNICODE buf[STAR_SEARCH_BUFSIZE] = ""; UNICODE buf[STAR_SEARCH_BUFSIZE] = "";
SIZE ExPos = 0; SIZE ExPos = 0;
SIZE CurPos = -1;
STAR_DESCPTR SDPtr = &star_array[pSS->SortedStars[pSS->CurIndex]]; STAR_DESCPTR SDPtr = &star_array[pSS->SortedStars[pSS->CurIndex]];
COUNT flags;
if (pSS->SingleClust || pSS->SingleMatch) if (pSS->SingleClust || pSS->SingleMatch)
{ // draw full star name { // draw full star name
GetClusterName (SDPtr, buf); GetClusterName (SDPtr, buf);
ExPos = -1; ExPos = -1;
flags = DSME_SETFR;
} }
else else
{ // draw substring match { // draw substring match
if (pSS->Prefix) UNICODE *pstr = buf;
{
strcpy (buf, pSS->Prefix); strcpy (pstr, pSS->Text);
strcat (buf, " "); ExPos = pSS->ClusterPos;
ExPos = pSS->PrefixLen + 1; pstr = skipUTF8Chars (pstr, pSS->ClusterPos);
}
strcat (buf, GAME_STRING (SDPtr->Postfix)); strcpy (pstr, GAME_STRING (SDPtr->Postfix));
ExPos += pSS->ClusterLen; ExPos += pSS->ClusterLen;
CurPos = pTES->CursorPos;
flags = DSME_CLEARFR;
} }
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
DrawSISMessageEx (buf, -1, ExPos, DSME_SETFR); DrawSISMessageEx (buf, CurPos, ExPos, flags);
DrawHyperCoords (pMS->first_item); DrawHyperCoords (pMS->first_item);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
} }
static void
MatchNextStar (STAR_SEARCH_STATE *pSS, BOOLEAN Reset)
{
if (Reset)
pSS->FirstIndex = -1; // reset cache
if (pSS->FirstIndex < 0)
{ // first time after changes
pSS->CurIndex = -1;
pSS->LastIndex = -1;
pSS->SingleClust = FALSE;
pSS->SingleMatch = FALSE;
strcpy (pSS->Buffer, pSS->Text);
SplitStarName (pSS);
}
pSS->CurIndex = FindNextStarIndex (pSS, pSS->CurIndex + 1,
pSS->SingleClust);
if (pSS->FirstIndex < 0) // first search
pSS->FirstIndex = pSS->CurIndex;
if (pSS->CurIndex >= 0)
{ // remember as last (searching forward-only)
pSS->LastIndex = pSS->CurIndex;
}
else
{ // wrap around
pSS->CurIndex = pSS->FirstIndex;
if (pSS->FirstIndex == pSS->LastIndex && pSS->FirstIndex != -1)
{
if (!pSS->Prefix)
{ // only one cluster matching
pSS->SingleClust = TRUE;
}
else
{ // exact match
pSS->SingleMatch = TRUE;
}
}
}
}
static BOOLEAN
OnStarNameChange (PTEXTENTRY_STATE pTES)
{
STAR_SEARCH_STATE *pSS = (STAR_SEARCH_STATE *) pTES->CbParam;
PMENU_STATE pMS = pSS->pMS;
COUNT flags;
BOOLEAN ret;
if (strcmp (pSS->Text, pSS->LastText) != 0)
{ // string changed
pSS->LastChangeTime = GetTimeCounter ();
strcpy (pSS->LastText, pSS->Text);
// reset the search
MatchNextStar (pSS, TRUE);
}
if (pSS->CurIndex < 0)
{ // nothing found
if (pSS->Text[0] == '\0')
flags = DSME_SETFR;
else
flags = DSME_CLEARFR;
if (pTES->JoystickMode)
flags |= DSME_BLOCKCUR;
LockMutex (GraphicsLock);
ret = DrawSISMessageEx (pSS->Text, pTES->CursorPos, -1, flags);
UnlockMutex (GraphicsLock);
}
else
{
STAR_DESCPTR SDPtr;
// move the cursor to the found star
SDPtr = &star_array[pSS->SortedStars[pSS->CurIndex]];
UpdateCursorLocation (pMS, 0, 0, &SDPtr->star_pt);
DrawMatchedStarName (pTES);
UpdateFuelRequirement (pMS);
}
return ret;
}
static BOOLEAN static BOOLEAN
OnStarNameFrame (PTEXTENTRY_STATE pTES) OnStarNameFrame (PTEXTENTRY_STATE pTES)
{ {
#define FEEDBACK_DELAY (ONE_SECOND / 2)
STAR_SEARCH_STATE *pSS = (STAR_SEARCH_STATE *) pTES->CbParam; STAR_SEARCH_STATE *pSS = (STAR_SEARCH_STATE *) pTES->CbParam;
PMENU_STATE pMS = pSS->pMS; PMENU_STATE pMS = pSS->pMS;
if (PulsedInputState.key[KEY_MENU_NEXT] || if (PulsedInputState.key[KEY_MENU_NEXT])
(pSS->LastChangeTime != 0 && { // search for next match
GetTimeCounter () > pSS->LastChangeTime + FEEDBACK_DELAY))
{ // search for matches
STAR_DESCPTR SDPtr; STAR_DESCPTR SDPtr;
if (pSS->LastChangeTime != 0) MatchNextStar (pSS, FALSE);
pSS->FirstIndex = -1; // reset cache
pSS->LastChangeTime = 0; // reset delayed feedback
if (pSS->FirstIndex < 0)
{ // first time after changes
pSS->CurIndex = -1;
pSS->LastIndex = -1;
pSS->SingleClust = FALSE;
pSS->SingleMatch = FALSE;
strcpy (pSS->Buffer, pTES->BaseStr);
SplitStarName (pSS);
}
pSS->CurIndex = FindNextStarIndex (pSS, pSS->CurIndex + 1,
pSS->SingleClust);
if (pSS->FirstIndex < 0) // first search
pSS->FirstIndex = pSS->CurIndex;
if (pSS->CurIndex >= 0)
{ // remember as last (searching forward-only)
pSS->LastIndex = pSS->CurIndex;
}
else
{ // wrap around
pSS->CurIndex = pSS->FirstIndex;
if (pSS->FirstIndex == pSS->LastIndex && pSS->FirstIndex != -1)
{
if (!pSS->Prefix)
{ // only one cluster matching
pSS->SingleClust = TRUE;
// reset the first
pSS->FirstIndex = FindNextStarIndex (pSS, 0, TRUE);
}
else
{ //exact match
pSS->SingleMatch = TRUE;
}
}
}
if (pSS->CurIndex < 0) if (pSS->CurIndex < 0)
{ // nothing found { // nothing found
@@ -1110,20 +1155,19 @@ DoStarSearch (PMENU_STATE pMS)
{ {
TEXTENTRY_STATE tes; TEXTENTRY_STATE tes;
STAR_SEARCH_STATE *pss; STAR_SEARCH_STATE *pss;
UNICODE buf[STAR_SEARCH_BUFSIZE] = "";
BOOLEAN success; BOOLEAN success;
pss = HMalloc (sizeof (*pss)); pss = HMalloc (sizeof (*pss));
if (!pss) if (!pss)
return FALSE; return FALSE;
//searchPoint = pMS->first_item;
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
DrawSISMessageEx (buf, 0, 0, DSME_SETFR); DrawSISMessageEx ("", 0, 0, DSME_SETFR);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
pss->pMS = pMS; pss->pMS = pMS;
pss->LastChangeTime = 0; pss->LastChangeTime = 0;
pss->Text[0] = '\0';
pss->LastText[0] = '\0'; pss->LastText[0] = '\0';
pss->FirstIndex = -1; pss->FirstIndex = -1;
SortStarsOnName (pss); SortStarsOnName (pss);
@@ -1131,8 +1175,8 @@ DoStarSearch (PMENU_STATE pMS)
// text entry setup // text entry setup
tes.Initialized = FALSE; tes.Initialized = FALSE;
tes.MenuRepeatDelay = 0; tes.MenuRepeatDelay = 0;
tes.BaseStr = buf; tes.BaseStr = pss->Text;
tes.MaxSize = sizeof (buf); tes.MaxSize = sizeof (pss->Text);
tes.CursorPos = 0; tes.CursorPos = 0;
tes.CbParam = pss; tes.CbParam = pss;
tes.ChangeCallback = OnStarNameChange; tes.ChangeCallback = OnStarNameChange;
@@ -1142,7 +1186,7 @@ DoStarSearch (PMENU_STATE pMS)
success = DoTextEntry (&tes); success = DoTextEntry (&tes);
LockMutex (GraphicsLock); LockMutex (GraphicsLock);
DrawSISMessageEx (buf, -1, -1, DSME_CLEARFR); DrawSISMessageEx (pss->Text, -1, -1, DSME_CLEARFR);
UnlockMutex (GraphicsLock); UnlockMutex (GraphicsLock);
HFree (pss); HFree (pss);
@@ -1249,10 +1293,7 @@ DoMoveCursor (PMENU_STATE pMS)
if (PulsedInputState.key[KEY_MENU_UP]) sy = -1; if (PulsedInputState.key[KEY_MENU_UP]) sy = -1;
if (PulsedInputState.key[KEY_MENU_DOWN]) sy = 1; if (PulsedInputState.key[KEY_MENU_DOWN]) sy = 1;
if (sx == 0 && sy == 0) if (sx != 0 || sy != 0)
{
}
else
{ {
UpdateCursorLocation (pMS, sx, sy, NULL_PTR); UpdateCursorLocation (pMS, sx, sy, NULL_PTR);
UpdateCursorInfo (pMS, last_buf); UpdateCursorInfo (pMS, last_buf);
+8 -8
View File
@@ -216,9 +216,7 @@ DrawSISMessageEx (UNICODE *pStr, SIZE CurPos, SIZE ExPos, COUNT flags)
BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33)); BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33));
} }
t.baseline.x = SIS_MESSAGE_WIDTH >> 1;
t.baseline.y = SIS_MESSAGE_HEIGHT - 2; t.baseline.y = SIS_MESSAGE_HEIGHT - 2;
t.align = ALIGN_CENTER;
t.pStr = pStr; t.pStr = pStr;
t.CharCount = utf8StringCount(pStr); t.CharCount = utf8StringCount(pStr);
SetContextFont (TinyFont); SetContextFont (TinyFont);
@@ -231,6 +229,8 @@ DrawSISMessageEx (UNICODE *pStr, SIZE CurPos, SIZE ExPos, COUNT flags)
if (CurPos < 0 && ExPos < 0) if (CurPos < 0 && ExPos < 0)
{ // normal state { // normal state
ClearDrawable (); ClearDrawable ();
t.baseline.x = SIS_MESSAGE_WIDTH >> 1;
t.align = ALIGN_CENTER;
font_DrawText (&t); font_DrawText (&t);
} }
else else
@@ -240,8 +240,11 @@ DrawSISMessageEx (UNICODE *pStr, SIZE CurPos, SIZE ExPos, COUNT flags)
BYTE char_deltas[MAX_DESC_CHARS]; BYTE char_deltas[MAX_DESC_CHARS];
PBYTE pchar_deltas; PBYTE pchar_deltas;
t.baseline.x = 3;
t.align = ALIGN_LEFT;
TextRect (&t, &text_r, char_deltas); TextRect (&t, &text_r, char_deltas);
if (text_r.extent.width + 2 >= r.extent.width) if (text_r.extent.width + t.baseline.x + 2 >= r.extent.width)
{ // the text does not fit the input box size and so { // the text does not fit the input box size and so
// will not fit when displayed later // will not fit when displayed later
// disallow the change // disallow the change
@@ -253,10 +256,7 @@ DrawSISMessageEx (UNICODE *pStr, SIZE CurPos, SIZE ExPos, COUNT flags)
ClearDrawable (); ClearDrawable ();
t.baseline.x = text_r.corner.x; if (CurPos >= 0 && CurPos <= t.CharCount)
t.align = ALIGN_LEFT;
if (CurPos >= 0)
{ // calc and draw the cursor { // calc and draw the cursor
RECT cur_r = text_r; RECT cur_r = text_r;
@@ -294,7 +294,7 @@ DrawSISMessageEx (UNICODE *pStr, SIZE CurPos, SIZE ExPos, COUNT flags)
SetContextForeGroundColor ( SetContextForeGroundColor (
BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33)); BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33));
if (ExPos >= 0) if (ExPos >= 0 && ExPos < t.CharCount)
{ // handle extra characters { // handle extra characters
t.CharCount = ExPos; t.CharCount = ExPos;
font_DrawText (&t); font_DrawText (&t);