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:
Olivier Teulière 2009-06-23 12:41:53 +00:00
parent d8923c8231
commit 7569a58bb7
18 changed files with 224 additions and 271 deletions

View file

@ -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 &params,
int i, const DicEdge *edgeptr) const;
/// Helper for searchRegExp()
void searchRegexpRec(struct params_regexp_t *params,
void searchRegexpRec(const struct params_regexp_t &params,
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_ */

View file

@ -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 &params,
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(&params, 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(&params, 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(&params, 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 &params,
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(&params, a->getInitId(),
searchRegexpRec(params, a->getInitId(),
getEdgeAt(getRoot()), oWordList,
iMaxResults ? iMaxResults + 1 : 0);
delete a;

View file

@ -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;

View file

@ -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
*/

View file

@ -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)

View file

@ -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; }

View file

@ -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++;

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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());
}
}

View file

@ -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

View file

@ -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),

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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(),