Searchengine changed: now find games, that hath the search string in it.

e.G. "SPOR" find "ea SPORts", "mario SPORts mix", "SPORe heros" and so on.
This commit is contained in:
ardi@ist-einmalig.de 2011-11-11 20:15:29 +00:00
parent baff754740
commit 164889c917
8 changed files with 94 additions and 70 deletions

View File

@ -2,8 +2,8 @@
<app version="1">
<name> USB Loader GX</name>
<coder>USB Loader GX Team</coder>
<version>2.3 r1126</version>
<release_date>201111081925</release_date>
<version>2.3 r1127</version>
<release_date>201111111858</release_date>
<!-- // remove this line to enable arguments
<arguments>
<arg>--ios=250</arg>

View File

@ -29,7 +29,7 @@ class cSearchButton
};
GuiSearchBar::GuiSearchBar(const wchar_t *SearchChars) :
GuiSearchBar::GuiSearchBar(const std::set<wchar_t> &SearchChars) :
inSide(0), text((char *) NULL, 22, ( GXColor )
{ 0, 0, 0, 255}), buttons(0),
keyImageData(Resources::GetFile("keyboard_key.png"), Resources::GetFileSize("keyboard_key.png")),
@ -39,24 +39,24 @@ GuiSearchBar::GuiSearchBar(const wchar_t *SearchChars) :
trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B);
SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE);
cnt = wcslen(SearchChars);
cnt = SearchChars.size();
buttons = new cSearchButton*[cnt];
wchar_t charstr[2] = { 0, 0 };
int lines = (cnt + 9) / 10;
int buttonsPerLine = (cnt + lines - 1) / lines;
width = 10 + buttonsPerLine * 42 + 10;
int x_start = 10, x = 0, y_start = 10 + 42, y = 0;
if (width < 200)
int i = 0, x_start = 10, x = 0, y_start = 10 + 42, y = 0;
if (width < 320)
{
x_start += (200 - width) >> 1;
width = 200;
x_start += (320 - width) >> 1;
width = 320;
}
for (int i = 0; i < cnt; i++, x++)
for (std::set<wchar_t>::iterator it=SearchChars.begin() ; it != SearchChars.end(); it++, i++, x++)
{
if (x >= buttonsPerLine) x = 0;
if (x == 0) y++;
charstr[0] = SearchChars[i];
charstr[0] = *it;
buttons[i] = new cSearchButton(charstr, &keyImageData, &keyOverImageData, x_start + x * 42, y_start - 42 + y
* 42, &trig, btnSoundOver, btnSoundClick);
this->Append(&(buttons[i]->button));

View File

@ -1,13 +1,14 @@
#ifndef GUI_SEARCHBAR_H_
#define GUI_SEARCHBAR_H_
#include "gui.h"
#include <set>
class cSearchButton;
class GuiSearchBar: public GuiWindow
{
public:
GuiSearchBar(const wchar_t *SearchChars);
GuiSearchBar(const std::set<wchar_t> &SearchChars);
virtual ~GuiSearchBar();
void Draw();
void Update(GuiTrigger * t);

View File

@ -908,13 +908,39 @@ int GameBrowseMenu::MainLoop()
{
if (searchChar > 27) //! Character clicked
{
int len = gameList.GetCurrentFilter() ? wcslen(gameList.GetCurrentFilter()) : 0;
wchar_t newFilter[len + 2];
if (gameList.GetCurrentFilter()) wcscpy(newFilter, gameList.GetCurrentFilter());
newFilter[len] = searchChar;
newFilter[len + 1] = 0;
for(;;)
{
int len = wcslen(gameList.GetCurrentFilter());
wchar_t newFilter[len + 2];
wcscpy(newFilter, gameList.GetCurrentFilter());
newFilter[len] = searchChar;
newFilter[len + 1] = 0;
gameList.FilterList(newFilter);
gameList.FilterList(newFilter);
if(gameList.GetAvailableSearchChars().size() != 1)
break;
searchChar = *gameList.GetAvailableSearchChars().begin();
}
bool autoClose = false;
switch(Settings.gameDisplay)
{
case LIST_MODE:
autoClose = gameList.size()<=9;
break;
case CAROUSEL_MODE:
autoClose = gameList.size()<=5;
break;
case GRID_MODE:
autoClose = gameList.size()<=3;
default:
break;
}
if(autoClose) // Close Searchwindow when less than 5 Games found
{
show_searchwindow = false;
searchBtn->StopEffect();
}
}
else if (searchChar == 27) //! Close
{
@ -930,11 +956,16 @@ int GameBrowseMenu::MainLoop()
{
int len = wcslen(gameList.GetCurrentFilter());
wchar_t newFilter[len + 1];
if (gameList.GetCurrentFilter()) wcscpy(newFilter, gameList.GetCurrentFilter());
newFilter[len > 0 ? len - 1 : 0] = 0;
gameList.FilterList(newFilter);
if(len == 1)
Settings.gridRows = GridRowsPreSearch; //! restore old rows amount so we don't stay on one row
wcscpy(newFilter, gameList.GetCurrentFilter());
int old_game_count = gameList.size();
for(; len > 0; len--)
{
newFilter[len - 1] = 0; // remove last char
if(len == 1)
Settings.gridRows = GridRowsPreSearch; //! restore old rows amount so we don't stay on one row
if(gameList.FilterList(newFilter) != old_game_count)
break;
}
}
ReloadBrowser();
return MENU_NONE;

View File

@ -181,14 +181,6 @@ int GameList::ReadGameList()
return LoadUnfiltered();
}
static bool WCharSortCallback(const wchar_t char1, const wchar_t char2)
{
if (char2 == 0) return true;
if (char1 == 0) return false;
return char2 > char1;
}
int GameList::FilterList(const wchar_t * gameFilter)
{
if (FullGameList.size() == 0) ReadGameList();
@ -251,22 +243,30 @@ int GameList::FilterList(const wchar_t * gameFilter)
if(n == Settings.EnabledCategories.size()) continue;
wchar_t *gameName = charToWideChar(GameTitles.GetTitle(header));
if (gameName && *GameFilter.c_str())
{
if (wcsnicmp(gameName, GameFilter.c_str(), GameFilter.size()) != 0)
{
delete [] gameName;
continue;
}
}
if (gameName)
{
if (wcslen(gameName) > GameFilter.size() &&
AvailableSearchChars.find(towupper(gameName[GameFilter.size()])) == std::string::npos &&
AvailableSearchChars.find(towlower(gameName[GameFilter.size()])) == std::string::npos)
if ( GameFilter.size() ) // has Filter
{
AvailableSearchChars.push_back(gameName[GameFilter.size()]);
bool found = false;
wchar_t *s1 = gameName, *s2;
while( (s2 = wcscasestr(s1, GameFilter.c_str())) ) // search filter in gameName
{
found = true;
wchar_t ch = towupper(s2[GameFilter.size()]);
if(ch) AvailableSearchChars.insert(ch);
s1++; // try search filter in gameName more times
}
if(!found)
{
delete [] gameName;
continue;
}
}
else // no Filter -> makes all chars as aviable
{
for(wchar_t *ch = gameName; *ch; ch++)
if(*ch >= '@') // limit chars by empty filter
AvailableSearchChars.insert(towupper(*ch));
}
delete [] gameName;
@ -277,7 +277,7 @@ int GameList::FilterList(const wchar_t * gameFilter)
NewTitles::Instance()->Save();
AvailableSearchChars.push_back(L'\0');
if (FilteredList.size() < 2)
if (FilteredList.size() < 2)
AvailableSearchChars.clear();
@ -305,12 +305,9 @@ int GameList::LoadUnfiltered()
wchar_t *gameName = charToWideChar(GameTitles.GetTitle(header));
if (gameName)
{
if (wcslen(gameName) > GameFilter.size() &&
AvailableSearchChars.find(towupper(gameName[GameFilter.size()])) == std::string::npos &&
AvailableSearchChars.find(towlower(gameName[GameFilter.size()])) == std::string::npos)
{
AvailableSearchChars.push_back(gameName[GameFilter.size()]);
}
for(wchar_t *ch = gameName; *ch; ch++)
if(*ch >= '@') // limit chars by unfiltered list
AvailableSearchChars.insert(towupper(*ch));
delete [] gameName;
}
@ -320,8 +317,6 @@ int GameList::LoadUnfiltered()
NewTitles::Instance()->Save();
AvailableSearchChars.push_back(L'\0');
if (FilteredList.size() < 2)
AvailableSearchChars.clear();
@ -350,10 +345,6 @@ void GameList::SortList()
{
std::sort(FilteredList.begin(), FilteredList.end(), NameSortCallback);
}
if (AvailableSearchChars.size() > 1)
std::sort(AvailableSearchChars.begin(), AvailableSearchChars.end(), WCharSortCallback);
}
bool GameList::NameSortCallback(const struct discHdr *a, const struct discHdr *b)

View File

@ -2,6 +2,7 @@
#define GAME_LIST_H_
#include <vector>
#include <set>
#include "Controls/DeviceHandler.hpp"
#include "wstring.hpp"
#include "usbloader/disc.h"
@ -19,7 +20,7 @@ class GameList
struct discHdr * operator[](int i) const { if (i < 0 || i >= (int) FilteredList.size()) return NULL; return FilteredList[i]; }
struct discHdr * GetDiscHeader(const char * gameID) const;
const wchar_t * GetCurrentFilter() const { return GameFilter.c_str(); }
const wchar_t * GetAvailableSearchChars() const { return AvailableSearchChars.c_str(); }
const std::set<wchar_t> &GetAvailableSearchChars() const { return AvailableSearchChars; }
void SortList();
void clear();
bool operator!() const { return (FullGameList.size() == 0); }
@ -41,7 +42,7 @@ class GameList
static bool RankingSortCallback(const struct discHdr *a, const struct discHdr *b);
static bool PlayersSortCallback(const struct discHdr *a, const struct discHdr *b);
wString AvailableSearchChars;
std::set<wchar_t> AvailableSearchChars;
wString GameFilter;
int selectedGame;
std::vector<struct discHdr *> FilteredList;

View File

@ -147,16 +147,15 @@ size_t utf8Len(const char *s)
return len;
}
int wcsnicmp(const wchar_t *s1, const wchar_t *s2, int len)
wchar_t *wcscasestr(const wchar_t *s1, const wchar_t *s2)
{
if (len <= 0) return (0);
do
{
int r = towupper(*s1) - towupper(*s2++);
if (r) return r;
if (*s1++ == 0) break;
} while (--len != 0);
return (0);
if(*s2==0) return (wchar_t *)s1;
int s1_len = wcslen(s1);
int s2_len = wcslen(s2);
if(s1_len < s2_len) return 0;
const wchar_t *end = &s1[s1_len-s2_len];
for(wchar_t *s=(wchar_t *)s1; s<=end; s++)
if(wcsncasecmp(s, s2, s2_len)==0)
return s;
return 0;
}

View File

@ -22,6 +22,7 @@ class wString: public std::basic_string<wchar_t, std::char_traits<wchar_t>, std:
};
size_t utf8Len(const char *s);
int wcsnicmp(const wchar_t *s1, const wchar_t *s2, int len);
wchar_t *wcscasestr(const wchar_t *s1, const wchar_t *s2);
#endif // !defined(__WSTRING_HPP)