mirror of
git://git.savannah.nongnu.org/eliot.git
synced 2025-01-17 06:11:49 +01:00
Each letter (tile) now has a display string, defaulting to its internal char. It is not yet possible to change it.
This display string is used in the ncurses and Qt interfaces. Display strings are types "wdstring" instead of plain "wstring" in a few places (not all of them) to help recognize them.
This commit is contained in:
parent
d8923c8231
commit
7569a58bb7
18 changed files with 224 additions and 271 deletions
46
dic/dic.h
46
dic/dic.h
|
@ -44,6 +44,17 @@ struct params_7plus1_t;
|
|||
struct params_regexp_t;
|
||||
class DicEdge;
|
||||
|
||||
/**
|
||||
* A wdstring is a display string, i.e. it can contains more chars thani
|
||||
* the represented string. The difference arises in languages such as Catalan,
|
||||
* where for example "QU" is made of 2 real characters, but corresponds to a
|
||||
* single tile.
|
||||
*
|
||||
* The wdstring type has no particular interest other than signaling
|
||||
* a bit more precisely the type of contents of the string.
|
||||
*/
|
||||
typedef wstring wdstring;
|
||||
|
||||
class Dictionary
|
||||
{
|
||||
public:
|
||||
|
@ -182,7 +193,7 @@ public:
|
|||
* @param oWordList: results
|
||||
* @param iMaxResults: maximum number of returned results (0 means no limit)
|
||||
*/
|
||||
void searchBenj(const wstring &iWord, vector<wstring> &oWordList,
|
||||
void searchBenj(const wstring &iWord, vector<wdstring> &oWordList,
|
||||
unsigned int iMaxResults = 0) const;
|
||||
|
||||
/**
|
||||
|
@ -191,27 +202,18 @@ public:
|
|||
* @param oWordList: results
|
||||
* @param iMaxResults: maximum number of returned results (0 means no limit)
|
||||
*/
|
||||
void searchRacc(const wstring &iWord, vector<wstring> &oWordList,
|
||||
void searchRacc(const wstring &iWord, vector<wdstring> &oWordList,
|
||||
unsigned int iMaxResults = 0) const;
|
||||
|
||||
/**
|
||||
* Search for crosswords
|
||||
* @param iMask: letters
|
||||
* @param oWordList: results
|
||||
* @param iMaxResults: maximum number of returned results (0 means no limit)
|
||||
*/
|
||||
void searchCross(const wstring &iMask, vector<wstring> &oWordList,
|
||||
unsigned int iMaxResults = 0) const;
|
||||
|
||||
/**
|
||||
* Search for all feasible word with "rack" plus one letter
|
||||
* @param iRack: letters
|
||||
* @param oWordlist: results
|
||||
* @param oWordlist: results (grouped by added character)
|
||||
* @param joker: true if the search must be performed when a joker is in the rack
|
||||
* @param iMaxResults: maximum number of returned results (0 means no limit)
|
||||
*/
|
||||
void search7pl1(const wstring &iRack,
|
||||
map<wchar_t, vector<wstring> > &oWordList,
|
||||
map<wstring, vector<wdstring> > &oWordList,
|
||||
bool joker) const;
|
||||
|
||||
/**
|
||||
|
@ -226,7 +228,7 @@ public:
|
|||
* @throw InvalidRegexpException When the regular expression cannot be parsed
|
||||
*/
|
||||
bool searchRegExp(const wstring &iRegexp,
|
||||
vector<wstring> &oWordList,
|
||||
vector<wdstring> &oWordList,
|
||||
unsigned int iMinLength,
|
||||
unsigned int iMaxLength,
|
||||
unsigned int iMaxResults = 0) const;
|
||||
|
@ -257,22 +259,18 @@ private:
|
|||
*/
|
||||
const DicEdge * seekEdgePtr(const wchar_t *s, const DicEdge *eptr) const;
|
||||
|
||||
/// Helper for searchCross()
|
||||
void searchCrossRec(struct params_cross_t *params,
|
||||
vector<wstring> &oWordList,
|
||||
const DicEdge *edgeptr,
|
||||
unsigned int iMaxResults) const;
|
||||
|
||||
/// Helper for search7pl1()
|
||||
void searchWordByLen(struct params_7plus1_t *params,
|
||||
void searchWordByLen(struct params_7plus1_t ¶ms,
|
||||
int i, const DicEdge *edgeptr) const;
|
||||
|
||||
/// Helper for searchRegExp()
|
||||
void searchRegexpRec(struct params_regexp_t *params,
|
||||
void searchRegexpRec(const struct params_regexp_t ¶ms,
|
||||
int state,
|
||||
const DicEdge *edgeptr,
|
||||
vector<wstring> &oWordList,
|
||||
unsigned int iMaxResults) const;
|
||||
vector<wdstring> &oWordList,
|
||||
unsigned int iMaxResults,
|
||||
const wdstring &iCurrWord = L"",
|
||||
unsigned int iNbChars = 0) const;
|
||||
};
|
||||
|
||||
#endif /* _DIC_H_ */
|
||||
|
|
|
@ -75,14 +75,28 @@ bool Dictionary::searchWord(const wstring &iWord) const
|
|||
|
||||
struct params_7plus1_t
|
||||
{
|
||||
wchar_t added_char;
|
||||
map<wchar_t, vector<wstring> > *results;
|
||||
wchar_t added_code;
|
||||
wdstring added_display;
|
||||
map<wdstring, vector<wdstring> > *results;
|
||||
int search_len;
|
||||
wchar_t search_wordtst[DIC_WORD_MAX];
|
||||
char search_letters[63];
|
||||
};
|
||||
|
||||
void Dictionary::searchWordByLen(struct params_7plus1_t *params,
|
||||
wdstring convertToDisplay(const Header &iHeader, const wstring &iWord)
|
||||
{
|
||||
wdstring dispStr;
|
||||
dispStr.reserve(iWord.size());
|
||||
for (unsigned int i = 0; i < iWord.size(); ++i)
|
||||
{
|
||||
const wdstring &chr =
|
||||
iHeader.getDisplayStr(iHeader.getCodeFromChar(iWord[i]));
|
||||
dispStr += chr;
|
||||
}
|
||||
return dispStr;
|
||||
}
|
||||
|
||||
void Dictionary::searchWordByLen(struct params_7plus1_t ¶ms,
|
||||
int i, const DicEdge *edgeptr) const
|
||||
{
|
||||
/* depth first search in the dictionary */
|
||||
|
@ -92,49 +106,49 @@ void Dictionary::searchWordByLen(struct params_7plus1_t *params,
|
|||
if (edgeptr->chr)
|
||||
{
|
||||
/* is the letter available in search_letters */
|
||||
if (params->search_letters[edgeptr->chr])
|
||||
if (params.search_letters[edgeptr->chr])
|
||||
{
|
||||
params->search_wordtst[i] = getHeader().getCharFromCode(edgeptr->chr);
|
||||
params->search_letters[edgeptr->chr] --;
|
||||
if (i == params->search_len)
|
||||
params.search_wordtst[i] = getHeader().getCharFromCode(edgeptr->chr);
|
||||
params.search_letters[edgeptr->chr] --;
|
||||
if (i == params.search_len)
|
||||
{
|
||||
if (edgeptr->term)
|
||||
{
|
||||
// Add the solution
|
||||
vector<wstring> &sols = (*params->results)[params->added_char];
|
||||
if (sols.empty() || sols.back() != params->search_wordtst)
|
||||
sols.push_back(params->search_wordtst);
|
||||
vector<wdstring> &sols = (*params.results)[params.added_display];
|
||||
if (sols.empty() || sols.back() != params.search_wordtst)
|
||||
sols.push_back(convertToDisplay(getHeader(), params.search_wordtst));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
searchWordByLen(params, i + 1, getEdgeAt(edgeptr->ptr));
|
||||
}
|
||||
params->search_letters[edgeptr->chr] ++;
|
||||
params->search_wordtst[i] = L'\0';
|
||||
params.search_letters[edgeptr->chr] ++;
|
||||
params.search_wordtst[i] = L'\0';
|
||||
}
|
||||
|
||||
/* the letter is of course available if we have a joker available */
|
||||
if (params->search_letters[0])
|
||||
if (params.search_letters[0])
|
||||
{
|
||||
params->search_wordtst[i] = getHeader().getCharFromCode(edgeptr->chr);
|
||||
params->search_letters[0] --;
|
||||
if (i == params->search_len)
|
||||
params.search_wordtst[i] = getHeader().getCharFromCode(edgeptr->chr);
|
||||
params.search_letters[0] --;
|
||||
if (i == params.search_len)
|
||||
{
|
||||
if (edgeptr->term)
|
||||
{
|
||||
// Add the solution
|
||||
vector<wstring> &sols = (*params->results)[params->added_char];
|
||||
if (sols.empty() || sols.back() != params->search_wordtst)
|
||||
sols.push_back(params->search_wordtst);
|
||||
vector<wdstring> &sols = (*params.results)[params.added_display];
|
||||
if (sols.empty() || sols.back() != params.search_wordtst)
|
||||
sols.push_back(convertToDisplay(getHeader(), params.search_wordtst));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
searchWordByLen(params, i + 1, getEdgeAt(edgeptr->ptr));
|
||||
}
|
||||
params->search_letters[0] ++;
|
||||
params->search_wordtst[i] = L'\0';
|
||||
params.search_letters[0] ++;
|
||||
params.search_wordtst[i] = L'\0';
|
||||
}
|
||||
}
|
||||
} while (! (*edgeptr++).last);
|
||||
|
@ -142,7 +156,7 @@ void Dictionary::searchWordByLen(struct params_7plus1_t *params,
|
|||
|
||||
|
||||
void Dictionary::search7pl1(const wstring &iRack,
|
||||
map<wchar_t, vector<wstring> > &oWordList,
|
||||
map<wdstring, vector<wdstring> > &oWordList,
|
||||
bool joker) const
|
||||
{
|
||||
if (iRack == L"" || iRack.size() > DIC_WORD_MAX)
|
||||
|
@ -189,10 +203,11 @@ void Dictionary::search7pl1(const wstring &iRack,
|
|||
params.results = &oWordList;
|
||||
|
||||
/* search for all the words that can be done with the letters */
|
||||
params.added_char = L'\0';
|
||||
params.added_code = 0;
|
||||
params.added_display = L"";
|
||||
params.search_len = wordlen - 1;
|
||||
params.search_wordtst[wordlen] = L'\0';
|
||||
searchWordByLen(¶ms, 0, root_edge);
|
||||
searchWordByLen(params, 0, root_edge);
|
||||
|
||||
/* search for all the words that can be done with the letters +1 */
|
||||
params.search_len = wordlen;
|
||||
|
@ -200,11 +215,12 @@ void Dictionary::search7pl1(const wstring &iRack,
|
|||
const wstring &letters = getHeader().getLetters();
|
||||
for (unsigned int i = 0; i < letters.size(); i++)
|
||||
{
|
||||
params.added_char = letters[i];
|
||||
unsigned int code = getHeader().getCodeFromChar(letters[i]);
|
||||
params.added_code = code;
|
||||
params.added_display = getHeader().getDisplayStr(code);
|
||||
params.search_letters[code]++;
|
||||
|
||||
searchWordByLen(¶ms, 0, root_edge);
|
||||
searchWordByLen(params, 0, root_edge);
|
||||
|
||||
params.search_letters[code]--;
|
||||
}
|
||||
|
@ -214,7 +230,7 @@ void Dictionary::search7pl1(const wstring &iRack,
|
|||
/****************************************/
|
||||
|
||||
void Dictionary::searchRacc(const wstring &iWord,
|
||||
vector<wstring> &oWordList,
|
||||
vector<wdstring> &oWordList,
|
||||
unsigned int iMaxResults) const
|
||||
{
|
||||
if (iWord == L"")
|
||||
|
@ -226,31 +242,28 @@ void Dictionary::searchRacc(const wstring &iWord,
|
|||
else
|
||||
oWordList.reserve(DEFAULT_VECT_ALLOC);
|
||||
|
||||
// Transform the given word to make it suitable for display
|
||||
const wdstring &displayWord = convertToDisplay(getHeader(), iWord);
|
||||
|
||||
// Try to add a letter at the front
|
||||
wchar_t wordtst[DIC_WORD_MAX];
|
||||
wcscpy(wordtst + 1, iWord.c_str());
|
||||
const wstring &letters = getHeader().getLetters();
|
||||
for (unsigned int i = 0; i <= letters.size(); i++)
|
||||
{
|
||||
wordtst[0] = letters[i];
|
||||
if (searchWord(wordtst))
|
||||
oWordList.push_back(wordtst);
|
||||
if (searchWord(letters[i] + iWord))
|
||||
{
|
||||
const wdstring &chr =
|
||||
getHeader().getDisplayStr(getHeader().getCodeFromChar(letters[i]));
|
||||
oWordList.push_back(chr + displayWord);
|
||||
}
|
||||
if (iMaxResults && oWordList.size() >= iMaxResults)
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to add a letter at the end
|
||||
int i;
|
||||
for (i = 0; iWord[i]; i++)
|
||||
wordtst[i] = iWord[i];
|
||||
|
||||
wordtst[i ] = '\0';
|
||||
wordtst[i+1] = '\0';
|
||||
|
||||
const DicEdge *edge_seek =
|
||||
seekEdgePtr(iWord.c_str(), getEdgeAt(getRoot()));
|
||||
|
||||
/* points to what the next letter can be */
|
||||
// Point to what the next letter can be
|
||||
const DicEdge *edge = getEdgeAt(edge_seek->ptr);
|
||||
|
||||
if (edge != getEdgeAt(0))
|
||||
|
@ -259,8 +272,7 @@ void Dictionary::searchRacc(const wstring &iWord,
|
|||
{
|
||||
if (edge->term)
|
||||
{
|
||||
wordtst[i] = getHeader().getCharFromCode(edge->chr);
|
||||
oWordList.push_back(wordtst);
|
||||
oWordList.push_back(displayWord + getHeader().getDisplayStr(edge->chr));
|
||||
if (iMaxResults && oWordList.size() >= iMaxResults)
|
||||
return;
|
||||
}
|
||||
|
@ -271,7 +283,7 @@ void Dictionary::searchRacc(const wstring &iWord,
|
|||
/****************************************/
|
||||
/****************************************/
|
||||
|
||||
void Dictionary::searchBenj(const wstring &iWord, vector<wstring> &oWordList,
|
||||
void Dictionary::searchBenj(const wstring &iWord, vector<wdstring> &oWordList,
|
||||
unsigned int iMaxResults) const
|
||||
{
|
||||
if (iWord == L"")
|
||||
|
@ -283,26 +295,27 @@ void Dictionary::searchBenj(const wstring &iWord, vector<wstring> &oWordList,
|
|||
else
|
||||
oWordList.reserve(DEFAULT_VECT_ALLOC);
|
||||
|
||||
wchar_t wordtst[DIC_WORD_MAX];
|
||||
wcscpy(wordtst + 3, iWord.c_str());
|
||||
// Transform the given word to make it suitable for display
|
||||
const wdstring &displayWord = convertToDisplay(getHeader(), iWord);
|
||||
|
||||
const DicEdge *edge0, *edge1, *edge2, *edgetst;
|
||||
edge0 = getEdgeAt(getRoot());
|
||||
edge0 = getEdgeAt(edge0->ptr);
|
||||
do
|
||||
{
|
||||
wordtst[0] = getHeader().getCharFromCode(edge0->chr);
|
||||
const wdstring &chr0 = getHeader().getDisplayStr(edge0->chr);
|
||||
edge1 = getEdgeAt(edge0->ptr);
|
||||
do
|
||||
{
|
||||
wordtst[1] = getHeader().getCharFromCode(edge1->chr);
|
||||
const wdstring &chr1 = getHeader().getDisplayStr(edge1->chr);
|
||||
edge2 = getEdgeAt(edge1->ptr);
|
||||
do
|
||||
{
|
||||
edgetst = seekEdgePtr(iWord.c_str(), edge2);
|
||||
if (edgetst->term)
|
||||
{
|
||||
wordtst[2] = getHeader().getCharFromCode(edge2->chr);
|
||||
oWordList.push_back(wordtst);
|
||||
const wdstring &chr2 = getHeader().getDisplayStr(edge2->chr);
|
||||
oWordList.push_back(chr0 + chr1 + chr2 + displayWord);
|
||||
if (iMaxResults && oWordList.size() >= iMaxResults)
|
||||
return;
|
||||
}
|
||||
|
@ -314,121 +327,33 @@ void Dictionary::searchBenj(const wstring &iWord, vector<wstring> &oWordList,
|
|||
/****************************************/
|
||||
/****************************************/
|
||||
|
||||
struct params_cross_t
|
||||
{
|
||||
int wordlen;
|
||||
wchar_t mask[DIC_WORD_MAX];
|
||||
};
|
||||
|
||||
|
||||
void Dictionary::searchCrossRec(struct params_cross_t *params,
|
||||
vector<wstring> &oWordList,
|
||||
const DicEdge *edgeptr,
|
||||
unsigned int iMaxResults) const
|
||||
{
|
||||
if (iMaxResults && oWordList.size() >= iMaxResults)
|
||||
return;
|
||||
|
||||
const DicEdge *current = getEdgeAt(edgeptr->ptr);
|
||||
|
||||
if (params->mask[params->wordlen] == '\0')
|
||||
{
|
||||
if (edgeptr->term)
|
||||
oWordList.push_back(params->mask);
|
||||
}
|
||||
else if (current->chr == 0)
|
||||
{
|
||||
// Do not go on recursion if we are on the sink
|
||||
return;
|
||||
}
|
||||
else if (params->mask[params->wordlen] == '.')
|
||||
{
|
||||
do
|
||||
{
|
||||
params->mask[params->wordlen] = getHeader().getCharFromCode(current->chr);
|
||||
params->wordlen ++;
|
||||
searchCrossRec(params, oWordList, current, iMaxResults);
|
||||
params->wordlen --;
|
||||
params->mask[params->wordlen] = '.';
|
||||
}
|
||||
while (!(*current++).last);
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
if (current->chr == getHeader().getCodeFromChar(params->mask[params->wordlen]))
|
||||
{
|
||||
params->wordlen ++;
|
||||
searchCrossRec(params, oWordList, current, iMaxResults);
|
||||
params->wordlen --;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!(*current++).last);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Dictionary::searchCross(const wstring &iMask, vector<wstring> &oWordList,
|
||||
unsigned int iMaxResults) const
|
||||
{
|
||||
if (iMask == L"")
|
||||
return;
|
||||
|
||||
// Allocate room for all the results
|
||||
if (iMaxResults)
|
||||
oWordList.reserve(iMaxResults);
|
||||
else
|
||||
oWordList.reserve(DEFAULT_VECT_ALLOC);
|
||||
|
||||
struct params_cross_t params;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < DIC_WORD_MAX && iMask[i]; i++)
|
||||
{
|
||||
if (iswalpha(iMask[i]))
|
||||
params.mask[i] = towupper(iMask[i]);
|
||||
else
|
||||
params.mask[i] = '.';
|
||||
}
|
||||
params.mask[i] = '\0';
|
||||
|
||||
params.wordlen = 0;
|
||||
searchCrossRec(¶ms, oWordList, getEdgeAt(getRoot()), iMaxResults);
|
||||
}
|
||||
|
||||
/****************************************/
|
||||
/****************************************/
|
||||
|
||||
struct params_regexp_t
|
||||
{
|
||||
int minlength;
|
||||
int maxlength;
|
||||
unsigned int minlength;
|
||||
unsigned int maxlength;
|
||||
Automaton *automaton_field;
|
||||
wchar_t word[DIC_WORD_MAX];
|
||||
int wordlen;
|
||||
};
|
||||
|
||||
|
||||
void Dictionary::searchRegexpRec(struct params_regexp_t *params,
|
||||
void Dictionary::searchRegexpRec(const struct params_regexp_t ¶ms,
|
||||
int state,
|
||||
const DicEdge *edgeptr,
|
||||
vector<wstring> &oWordList,
|
||||
unsigned int iMaxResults) const
|
||||
vector<wdstring> &oWordList,
|
||||
unsigned int iMaxResults,
|
||||
const wdstring &iCurrWord,
|
||||
unsigned int iNbChars) const
|
||||
{
|
||||
if (iMaxResults && oWordList.size() >= iMaxResults)
|
||||
return;
|
||||
|
||||
int next_state;
|
||||
/* if we have a valid word we store it */
|
||||
if (params->automaton_field->accept(state) && edgeptr->term)
|
||||
if (params.automaton_field->accept(state) && edgeptr->term)
|
||||
{
|
||||
int l = wcslen(params->word);
|
||||
if (params->minlength <= l &&
|
||||
params->maxlength >= l)
|
||||
if (params.minlength <= iNbChars &&
|
||||
params.maxlength >= iNbChars)
|
||||
{
|
||||
oWordList.push_back(params->word);
|
||||
oWordList.push_back(iCurrWord);
|
||||
}
|
||||
}
|
||||
/* we now drive the search by exploring the dictionary */
|
||||
|
@ -436,16 +361,12 @@ void Dictionary::searchRegexpRec(struct params_regexp_t *params,
|
|||
do
|
||||
{
|
||||
/* the current letter is current->chr */
|
||||
next_state = params->automaton_field->getNextState(state, current->chr);
|
||||
next_state = params.automaton_field->getNextState(state, current->chr);
|
||||
/* 1: the letter appears in the automaton as is */
|
||||
if (next_state)
|
||||
{
|
||||
params->word[params->wordlen] =
|
||||
getHeader().getCharFromCode(current->chr);
|
||||
params->wordlen ++;
|
||||
searchRegexpRec(params, next_state, current, oWordList, iMaxResults);
|
||||
params->wordlen --;
|
||||
params->word[params->wordlen] = L'\0';
|
||||
searchRegexpRec(params, next_state, current, oWordList, iMaxResults,
|
||||
iCurrWord + getHeader().getDisplayStr(current->chr), iNbChars + 1);
|
||||
}
|
||||
} while (!(*current++).last);
|
||||
}
|
||||
|
@ -453,7 +374,6 @@ void Dictionary::searchRegexpRec(struct params_regexp_t *params,
|
|||
|
||||
/**
|
||||
* Initialize the lists of letters with pre-defined lists
|
||||
|
||||
* 0: all tiles
|
||||
* 1: vowels
|
||||
* 2: consonants
|
||||
|
@ -489,7 +409,7 @@ static void initLetterLists(const Dictionary &iDic,
|
|||
|
||||
|
||||
bool Dictionary::searchRegExp(const wstring &iRegexp,
|
||||
vector<wstring> &oWordList,
|
||||
vector<wdstring> &oWordList,
|
||||
unsigned int iMinLength,
|
||||
unsigned int iMaxLength,
|
||||
unsigned int iMaxResults) const
|
||||
|
@ -542,9 +462,7 @@ bool Dictionary::searchRegExp(const wstring &iRegexp,
|
|||
params.minlength = iMinLength;
|
||||
params.maxlength = iMaxLength;
|
||||
params.automaton_field = a;
|
||||
memset(params.word, L'\0', sizeof(params.word));
|
||||
params.wordlen = 0;
|
||||
searchRegexpRec(¶ms, a->getInitId(),
|
||||
searchRegexpRec(params, a->getInitId(),
|
||||
getEdgeAt(getRoot()), oWordList,
|
||||
iMaxResults ? iMaxResults + 1 : 0);
|
||||
delete a;
|
||||
|
|
|
@ -236,9 +236,9 @@ wchar_t Header::getCharFromCode(unsigned int iCode) const
|
|||
// Safety check
|
||||
if (iCode == 0 || iCode > m_letters.size())
|
||||
{
|
||||
ostringstream ss;
|
||||
ss << iCode;
|
||||
throw DicException("Header::getCharFromCode: no letter for code " + ss.str());
|
||||
ostringstream oss;
|
||||
oss << iCode;
|
||||
throw DicException("Header::getCharFromCode: no letter for code " + oss.str());
|
||||
}
|
||||
return m_letters[iCode - 1];
|
||||
}
|
||||
|
@ -259,6 +259,20 @@ unsigned int Header::getCodeFromChar(wchar_t iChar) const
|
|||
}
|
||||
|
||||
|
||||
wstring Header::getDisplayStr(unsigned int iCode) const
|
||||
{
|
||||
// Safety check
|
||||
if (iCode == 0 || iCode > m_letters.size())
|
||||
{
|
||||
ostringstream oss;
|
||||
oss << iCode;
|
||||
throw DicException("Header::getDisplayStr: No code for letter '" + oss.str());
|
||||
}
|
||||
// TODO: return a const wstring & instead of a wstring
|
||||
return wstring(1, m_letters[iCode - 1]);
|
||||
}
|
||||
|
||||
|
||||
void Header::read(istream &iStream)
|
||||
{
|
||||
Dict_header_old aHeader;
|
||||
|
|
|
@ -121,6 +121,11 @@ public:
|
|||
*/
|
||||
unsigned int getCodeFromChar(wchar_t iChar) const;
|
||||
|
||||
/**
|
||||
* Return the display stirng corresponding to the given code
|
||||
*/
|
||||
wstring getDisplayStr(unsigned int iCode) const;
|
||||
|
||||
/**
|
||||
* Print a readable summary of the header on standard output
|
||||
*/
|
||||
|
|
15
dic/tile.cpp
15
dic/tile.cpp
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <wctype.h>
|
||||
#include "tile.h"
|
||||
#include "header.h"
|
||||
|
@ -95,6 +96,20 @@ unsigned int Tile::getPoints() const
|
|||
}
|
||||
|
||||
|
||||
wstring Tile::getDisplayStr() const
|
||||
{
|
||||
if (m_code == 0)
|
||||
throw DicException("Tile::getDisplayStr: Invalid tile");
|
||||
if (m_joker && iswalpha(m_char))
|
||||
{
|
||||
wstring str = m_header->getDisplayStr(m_code);
|
||||
std::transform(str.begin(), str.end(), str.begin(), towlower);
|
||||
return str;
|
||||
}
|
||||
return m_header->getDisplayStr(m_code);
|
||||
}
|
||||
|
||||
|
||||
wchar_t Tile::toChar() const
|
||||
{
|
||||
if (m_joker)
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -57,6 +58,7 @@ public:
|
|||
unsigned int getPoints() const;
|
||||
wchar_t toChar() const;
|
||||
unsigned int toCode() const;
|
||||
wstring getDisplayStr() const;
|
||||
|
||||
static const Tile &Joker() { return m_TheJoker; }
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ unsigned int Bag::getNbConsonants() const
|
|||
void Bag::takeTile(const Tile &iTile)
|
||||
{
|
||||
ASSERT(in(iTile),
|
||||
"The bag does not contain the letter " + convertToMb(iTile.toChar()));
|
||||
"The bag does not contain the letter " + convertToMb(iTile.getDisplayStr()));
|
||||
|
||||
m_tilesMap[iTile]--;
|
||||
m_ntiles--;
|
||||
|
@ -91,7 +91,7 @@ void Bag::takeTile(const Tile &iTile)
|
|||
void Bag::replaceTile(const Tile &iTile)
|
||||
{
|
||||
ASSERT(in(iTile) < iTile.maxNumber(),
|
||||
"Cannot replace tile: " + convertToMb(iTile.toChar()));
|
||||
"Cannot replace tile: " + convertToMb(iTile.getDisplayStr()));
|
||||
|
||||
m_tilesMap[iTile]++;
|
||||
m_ntiles++;
|
||||
|
|
|
@ -203,7 +203,7 @@ wstring PlayedRack::toString(display_mode mode) const
|
|||
|
||||
BOOST_FOREACH(const Tile &tile, m_oldTiles)
|
||||
{
|
||||
s += tile.toChar();
|
||||
s += tile.getDisplayStr();
|
||||
}
|
||||
|
||||
if (mode > RACK_SIMPLE && getNbOld() > 0 && getNbNew() > 0)
|
||||
|
@ -213,7 +213,7 @@ wstring PlayedRack::toString(display_mode mode) const
|
|||
|
||||
BOOST_FOREACH(const Tile &tile, m_newTiles)
|
||||
{
|
||||
s += tile.toChar();
|
||||
s += tile.getDisplayStr();
|
||||
}
|
||||
|
||||
return s;
|
||||
|
|
|
@ -34,7 +34,7 @@ Rack::Rack()
|
|||
void Rack::remove(const Tile &t)
|
||||
{
|
||||
ASSERT(in(t),
|
||||
"The rack does not contain the letter " + convertToMb(t.toChar()));
|
||||
"The rack does not contain the letter " + convertToMb(t.getDisplayStr()));
|
||||
m_tiles[t.toCode()]--;
|
||||
m_ntiles--;
|
||||
}
|
||||
|
@ -67,7 +67,11 @@ wstring Rack::toString() const
|
|||
for (unsigned int i = 1; i < m_tiles.size(); i++)
|
||||
{
|
||||
// Append m_tiles[i] copies of the char
|
||||
rs.append(m_tiles[i], Dictionary::GetDic().getTileFromCode(i).toChar());
|
||||
const wstring &chr = Dictionary::GetDic().getTileFromCode(i).getDisplayStr();
|
||||
for (unsigned int j = 0; j < m_tiles[i]; ++j)
|
||||
{
|
||||
rs += chr;
|
||||
}
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm> // For std::transform
|
||||
#include <wctype.h>
|
||||
#include "tile.h"
|
||||
#include "round.h"
|
||||
|
@ -137,15 +138,14 @@ void Round::removeRightToRack(Tile __UNUSED__ c, bool __UNUSED__ iJoker)
|
|||
|
||||
wstring Round::getWord() const
|
||||
{
|
||||
wchar_t c;
|
||||
wstring s;
|
||||
|
||||
for (unsigned int i = 0; i < getWordLen(); i++)
|
||||
{
|
||||
c = getTile(i).toChar();
|
||||
wstring chr = getTile(i).getDisplayStr();
|
||||
if (isJoker(i))
|
||||
c = towlower(c);
|
||||
s += c;
|
||||
std::transform(chr.begin(), chr.end(), chr.begin(), towlower);
|
||||
s += chr;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -79,10 +79,14 @@ void BagWidget::updateModel()
|
|||
unsigned int nb = bag.in(tile);
|
||||
if (nb != 0)
|
||||
{
|
||||
// Concatenate the display char nb times
|
||||
wdstring str;
|
||||
for (unsigned int i = 0; i < nb; ++i)
|
||||
str += tile.getDisplayStr();
|
||||
|
||||
int rowNum = m_model->rowCount();
|
||||
m_model->insertRow(rowNum);
|
||||
m_model->setData(m_model->index(rowNum, 0),
|
||||
qfw(wstring(nb, tile.toChar())));
|
||||
m_model->setData(m_model->index(rowNum, 0), qfw(str));
|
||||
m_model->setData(m_model->index(rowNum, 1), tile.getPoints());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*****************************************************************************/
|
||||
|
||||
#include <algorithm> // For std::transform
|
||||
#include <math.h>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QPaintEvent>
|
||||
|
@ -138,12 +139,14 @@ void BoardWidget::paintEvent(QPaintEvent *)
|
|||
// Draw the letter
|
||||
if (m_game != NULL && !m_game->getBoard().getTile(row, col).isEmpty())
|
||||
{
|
||||
wchar_t chr = towupper(m_game->getBoard().getTile(row, col).toChar());
|
||||
wstring chr = m_game->getBoard().getTile(row, col).getDisplayStr();
|
||||
// Make the display char in upper case
|
||||
std::transform(chr.begin(), chr.end(), chr.begin(), towupper);
|
||||
if (m_game->getBoard().getCharAttr(row, col) & ATTR_JOKER)
|
||||
painter.setPen(JokerColour);
|
||||
painter.setFont(letterFont);
|
||||
painter.drawText(xPos, yPos + 1, squareSize, squareSize,
|
||||
Qt::AlignCenter, qfw(wstring(1, chr)));
|
||||
Qt::AlignCenter, qfw(chr));
|
||||
painter.setPen(NormalColour);
|
||||
|
||||
// Draw the points of the tile
|
||||
|
|
|
@ -185,18 +185,18 @@ void DicToolsWidget::refreshPlus1()
|
|||
|
||||
if (rack->text() != "")
|
||||
{
|
||||
map<wchar_t, vector<wstring> > wordList;
|
||||
map<wstring, vector<wstring> > wordList;
|
||||
m_dic->search7pl1(qtw(rack->text()), wordList, true);
|
||||
|
||||
int rowNum = 0;
|
||||
map<wchar_t, vector<wstring> >::const_iterator it;
|
||||
map<wstring, vector<wstring> >::const_iterator it;
|
||||
for (it = wordList.begin(); it != wordList.end(); it++)
|
||||
{
|
||||
// Create the header line
|
||||
model->insertRow(rowNum);
|
||||
const QModelIndex &index = model->index(rowNum, 0);
|
||||
if (it->first)
|
||||
model->setData(index, qfw(wstring(1, it->first)));
|
||||
if (it->first != L"")
|
||||
model->setData(index, qfw(it->first));
|
||||
else
|
||||
model->setData(index, _q("Anagrams"));
|
||||
treeView->setExpanded(index, true);
|
||||
|
@ -300,7 +300,7 @@ void DicToolsWidget::refreshDicInfo()
|
|||
{
|
||||
model->insertRow(rowNum);
|
||||
model->setData(model->index(rowNum, 0),
|
||||
qfw(wstring(1, it->toChar())));
|
||||
qfw(it->getDisplayStr()));
|
||||
model->setData(model->index(rowNum, 1), it->getPoints());
|
||||
model->setData(model->index(rowNum, 2), it->maxNumber());
|
||||
model->setData(model->index(rowNum, 3),
|
||||
|
|
|
@ -4,12 +4,12 @@ commande> e
|
|||
mode entraînement
|
||||
[?] pour l'aide
|
||||
commande> b b maison
|
||||
PLUmaison
|
||||
PLUMAISON
|
||||
commande> b b animal
|
||||
commande> b b jures
|
||||
CONjures
|
||||
GOUjures
|
||||
PARjures
|
||||
CONJURES
|
||||
GOUJURES
|
||||
PARJURES
|
||||
commande> q
|
||||
fin du mode entraînement
|
||||
commande> q
|
||||
|
|
|
@ -4,24 +4,24 @@ commande> e
|
|||
mode entraînement
|
||||
[?] pour l'aide
|
||||
commande> b r ave
|
||||
Bave
|
||||
Cave
|
||||
Gave
|
||||
Have
|
||||
Lave
|
||||
Nave
|
||||
Pave
|
||||
Rave
|
||||
aveC
|
||||
aveN
|
||||
aveU
|
||||
aveZ
|
||||
BAVE
|
||||
CAVE
|
||||
GAVE
|
||||
HAVE
|
||||
LAVE
|
||||
NAVE
|
||||
PAVE
|
||||
RAVE
|
||||
AVEC
|
||||
AVEN
|
||||
AVEU
|
||||
AVEZ
|
||||
commande> b r yeux
|
||||
commande> b r ka
|
||||
Oka
|
||||
Ska
|
||||
kaN
|
||||
kaS
|
||||
OKA
|
||||
SKA
|
||||
KAN
|
||||
KAS
|
||||
commande> q
|
||||
fin du mode entraînement
|
||||
commande> q
|
||||
|
|
|
@ -485,7 +485,7 @@ void handleRegexp(const Dictionary& iDic, const vector<wstring> &tokens)
|
|||
printf("search for %s (%d,%d,%d)\n", convertToMb(regexp).c_str(),
|
||||
nres, lmin, lmax);
|
||||
|
||||
vector<wstring> wordList;
|
||||
vector<wdstring> wordList;
|
||||
try
|
||||
{
|
||||
iDic.searchRegExp(regexp, wordList, lmin, lmax, nres);
|
||||
|
@ -496,7 +496,7 @@ void handleRegexp(const Dictionary& iDic, const vector<wstring> &tokens)
|
|||
return;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const wstring &wstr, wordList)
|
||||
BOOST_FOREACH(const wdstring &wstr, wordList)
|
||||
{
|
||||
printf("%s\n", convertToMb(wstr).c_str());
|
||||
}
|
||||
|
@ -598,22 +598,22 @@ void loopTraining(PublicGame &iGame)
|
|||
{
|
||||
case L'b':
|
||||
{
|
||||
vector<wstring> wordList;
|
||||
vector<wdstring> wordList;
|
||||
iGame.getDic().searchBenj(word, wordList);
|
||||
BOOST_FOREACH(const wstring &wstr, wordList)
|
||||
BOOST_FOREACH(const wdstring &wstr, wordList)
|
||||
cout << convertToMb(wstr) << endl;
|
||||
}
|
||||
break;
|
||||
case L'p':
|
||||
{
|
||||
map<wchar_t, vector<wstring> > wordMap;
|
||||
map<wdstring, vector<wdstring> > wordMap;
|
||||
iGame.getDic().search7pl1(word, wordMap, false);
|
||||
map<wchar_t, vector<wstring> >::const_iterator it;
|
||||
map<wdstring, vector<wdstring> >::const_iterator it;
|
||||
for (it = wordMap.begin(); it != wordMap.end(); ++it)
|
||||
{
|
||||
if (it->first)
|
||||
if (it->first != L"")
|
||||
cout << "+" << convertToMb(it->first) << endl;
|
||||
BOOST_FOREACH(const wstring &wstr, it->second)
|
||||
BOOST_FOREACH(const wdstring &wstr, it->second)
|
||||
{
|
||||
cout << " " << convertToMb(wstr) << endl;
|
||||
}
|
||||
|
@ -622,9 +622,9 @@ void loopTraining(PublicGame &iGame)
|
|||
break;
|
||||
case L'r':
|
||||
{
|
||||
vector<wstring> wordList;
|
||||
vector<wdstring> wordList;
|
||||
iGame.getDic().searchRacc(word, wordList);
|
||||
BOOST_FOREACH(const wstring &wstr, wordList)
|
||||
BOOST_FOREACH(const wdstring &wstr, wordList)
|
||||
cout << convertToMb(wstr) << endl;
|
||||
}
|
||||
break;
|
||||
|
@ -659,22 +659,6 @@ void loopTraining(PublicGame &iGame)
|
|||
iGame.trainingSetRackManual(false, letters);
|
||||
}
|
||||
break;
|
||||
case L'x':
|
||||
{
|
||||
const wstring &cross = checkCrossToken(tokens, 1);
|
||||
if (cross == L"")
|
||||
helpTraining();
|
||||
else
|
||||
{
|
||||
vector<wstring> wordList;
|
||||
iGame.getDic().searchCross(cross, wordList);
|
||||
BOOST_FOREACH(const wstring &wstr, wordList)
|
||||
{
|
||||
printf(" %s\n", convertToMb(wstr).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case L'*':
|
||||
iGame.trainingSetRackRandom(false, PublicGame::kRACK_ALL);
|
||||
break;
|
||||
|
|
|
@ -187,7 +187,7 @@ void GameIO::printNonPlayed(ostream &out, const PublicGame &iGame)
|
|||
{
|
||||
if (bag.in(tile) > 9)
|
||||
out << " ";
|
||||
out << setw(2) << convertToMb(tile.toChar());
|
||||
out << setw(2) << convertToMb(tile.getDisplayStr());
|
||||
}
|
||||
out << endl;
|
||||
|
||||
|
|
|
@ -244,19 +244,22 @@ void CursesIntf::drawBoard(WINDOW *win, int y, int x) const
|
|||
mvwprintw(win, y + row + 1, x + 3 * col + 1, " ");
|
||||
|
||||
// Now add the letter
|
||||
wchar_t c = m_game->getBoard().getChar(row, col);
|
||||
if (c)
|
||||
const Tile &t = m_game->getBoard().getTile(row, col);
|
||||
if (!t.isEmpty())
|
||||
{
|
||||
cchar_t cc;
|
||||
if (iswlower(c))
|
||||
const wstring &chr = t.getDisplayStr();
|
||||
int offset = 0;
|
||||
if (chr.size() > 1)
|
||||
offset = -1;
|
||||
if (m_game->getBoard().isJoker(row, col))
|
||||
{
|
||||
setcchar(&cc, &c, A_BOLD, COLOR_GREEN, NULL);
|
||||
mvwadd_wch(win, y + row + 1, x + 3 * col + 2, &cc);
|
||||
wattron(win, A_BOLD | COLOR_PAIR(COLOR_GREEN));
|
||||
mvwprintw(win, y + row + 1, x + 3 * col + 2 + offset, convertToMb(chr).c_str());
|
||||
wattroff(win, A_BOLD);
|
||||
}
|
||||
else
|
||||
{
|
||||
setcchar(&cc, &c, 0, 0, NULL);
|
||||
mvwadd_wch(win, y + row + 1, x + 3 * col + 2, &cc);
|
||||
mvwprintw(win, y + row + 1, x + 3 * col + 2 + offset, convertToMb(chr).c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -374,7 +377,7 @@ void CursesIntf::drawHistory(Box &ioBox) const
|
|||
int y = ioBox.getTop();
|
||||
|
||||
// Heading
|
||||
string heading = truncString(_(" N | RACK | SOLUTION | REF | PTS | P | BONUS"),
|
||||
string heading = truncString(_(" N | RACK | SOLUTION | REF | PTS | P | BONUS"),
|
||||
ioBox.getWidth() - 1);
|
||||
mvwprintw(m_win, y, x + 1, "%s", heading.c_str());
|
||||
mvwhline(m_win, y + 1, x + 1, ACS_HLINE, heading.size());
|
||||
|
@ -392,7 +395,7 @@ void CursesIntf::drawHistory(Box &ioBox) const
|
|||
wstring coord = r.getCoord().toString();
|
||||
ioBox.printDataLine(i, x,
|
||||
" %2d %s %s %s %3d %1d %c",
|
||||
i + 1, padAndConvert(t.getPlayedRack().toString(), 8).c_str(),
|
||||
i + 1, padAndConvert(t.getPlayedRack().toString(), 14, false).c_str(),
|
||||
padAndConvert(r.getWord(), 15, false).c_str(),
|
||||
padAndConvert(coord, 3).c_str(), r.getPoints(),
|
||||
t.getPlayer(), r.getBonus() ? '*' : ' ');
|
||||
|
@ -403,7 +406,7 @@ void CursesIntf::drawHistory(Box &ioBox) const
|
|||
wstring invWord = L"<" + m.getBadWord() + L">";
|
||||
ioBox.printDataLine(i, x,
|
||||
" %2d %s %s %s %3d %1d",
|
||||
i + 1, padAndConvert(t.getPlayedRack().toString(), 8).c_str(),
|
||||
i + 1, padAndConvert(t.getPlayedRack().toString(), 14, false).c_str(),
|
||||
padAndConvert(invWord, 15, false).c_str(),
|
||||
padAndConvert(m.getBadCoord(), 3).c_str(), m.getScore(),
|
||||
t.getPlayer());
|
||||
|
@ -419,7 +422,7 @@ void CursesIntf::drawHistory(Box &ioBox) const
|
|||
|
||||
ioBox.printDataLine(i, x,
|
||||
" %2d %s %s %s %3d %1d",
|
||||
i + 1, padAndConvert(t.getPlayedRack().toString(), 8).c_str(),
|
||||
i + 1, padAndConvert(t.getPlayedRack().toString(), 14, false).c_str(),
|
||||
padAndConvert(action, 15, false).c_str(),
|
||||
" - ", m.getScore(), t.getPlayer());
|
||||
}
|
||||
|
@ -427,11 +430,11 @@ void CursesIntf::drawHistory(Box &ioBox) const
|
|||
int nbLines = min(i + 2 - ioBox.getFirstLine(),
|
||||
ioBox.getLastLine() - ioBox.getFirstLine() + 2);
|
||||
mvwvline(m_win, y, x + 4, ACS_VLINE, nbLines);
|
||||
mvwvline(m_win, y, x + 15, ACS_VLINE, nbLines);
|
||||
mvwvline(m_win, y, x + 33, ACS_VLINE, nbLines);
|
||||
mvwvline(m_win, y, x + 21, ACS_VLINE, nbLines);
|
||||
mvwvline(m_win, y, x + 39, ACS_VLINE, nbLines);
|
||||
mvwvline(m_win, y, x + 45, ACS_VLINE, nbLines);
|
||||
mvwvline(m_win, y, x + 49, ACS_VLINE, nbLines);
|
||||
mvwvline(m_win, y, x + 51, ACS_VLINE, nbLines);
|
||||
mvwvline(m_win, y, x + 55, ACS_VLINE, nbLines);
|
||||
}
|
||||
|
||||
|
||||
|
@ -500,13 +503,16 @@ void CursesIntf::drawBag(Box &ioBox) const
|
|||
int i;
|
||||
for (i = ioBox.getFirstLine(); i < (int)allTiles.size() && i < ioBox.getLastLine(); i++)
|
||||
{
|
||||
const wstring &chr = allTiles[i].getDisplayStr();
|
||||
wstring str;
|
||||
for (unsigned int j = 0; j < m_game->getBag().in(allTiles[i]); ++j)
|
||||
str += chr;
|
||||
ioBox.printDataLine(i, ioBox.getLeft() + 1,
|
||||
" %s %2d %2d %s",
|
||||
padAndConvert(wstring(1, allTiles[i].toChar()), 2).c_str(),
|
||||
padAndConvert(allTiles[i].getDisplayStr(), 2).c_str(),
|
||||
allTiles[i].getPoints(),
|
||||
allTiles[i].maxNumber(),
|
||||
convertToMb(wstring(m_game->getBag().in(allTiles[i]),
|
||||
allTiles[i].toChar())).c_str());
|
||||
convertToMb(str).c_str());
|
||||
}
|
||||
|
||||
int nbLines = min(i + 2 - ioBox.getFirstLine(),
|
||||
|
|
Loading…
Reference in a new issue