Pass selected tiles into new util function, and from there into java

world, so confirming query can include them.
This commit is contained in:
Andy2 2011-10-19 18:34:26 -07:00
parent d63f6961d4
commit 4eee7f8aa7
21 changed files with 174 additions and 78 deletions

View file

@ -132,6 +132,18 @@ and_util_userQuery( XW_UtilCtxt* uc, UtilQueryID id, XWStreamCtxt* stream )
return result;
}
static XP_Bool
and_util_confirmTrade( XW_UtilCtxt* uc, const XP_UCHAR** tiles, XP_U16 nTiles )
{
XP_Bool result = XP_FALSE;
UTIL_CBK_HEADER("confirmTrade", "([Ljava/lang/String;)Z" );
jobjectArray jtiles = makeStringArray( env, nTiles, tiles );
result = (*env)->CallBooleanMethod( env, util->jutil, mid, jtiles );
(*env)->DeleteLocalRef( env, jtiles );
UTIL_CBK_TAIL();
return result;
}
static XP_S16
and_util_userPickTile( XW_UtilCtxt* uc, const PickInfo* pi,
XP_U16 playerNum, const XP_UCHAR** texts, XP_U16 nTiles )
@ -498,6 +510,7 @@ makeUtil( MPFORMAL JNIEnv** envp, jobject jutil, CurGameInfo* gi,
SET_PROC(getSquareBonus);
SET_PROC(userError);
SET_PROC(userQuery);
SET_PROC(confirmTrade);
SET_PROC(userPickTile);
SET_PROC(askPassword);
SET_PROC(trayHiddenChange);

View file

@ -1215,9 +1215,8 @@
<!-- Text of dialog asking user to confirm a move that exchanges
tiles (instead of forming a new word to earn points) -->
<string name="query_trade">Are you sure you want to exchange the
selected tiles?</string>
<string name="query_tradef">Are you sure you want to exchange the
selected tiles (%s)?</string>
<!-- ############################################################
# :Screens:
@ -1764,7 +1763,8 @@
dialog -->
<string name="changes_button">Recent changes</string>
<!-- New strings that need to be documented and found a home
above. -->
<string name="button_lookup">Look up words</string>
<string name="button_lookupf">Look up %s</string>
<string name="title_lookup">Tap to look up</string>

View file

@ -925,6 +925,7 @@ public class BoardActivity extends XWActivity
super( BoardActivity.this );
}
@Override
public void requestTime()
{
post( new Runnable() {
@ -936,12 +937,14 @@ public class BoardActivity extends XWActivity
} );
}
@Override
public void remSelected()
{
m_jniThread.handle( JNIThread.JNICmd.CMD_REMAINING,
R.string.tiles_left_title );
}
@Override
public void setIsServer( boolean isServer )
{
DeviceRole newRole = isServer? DeviceRole.SERVER_ISSERVER
@ -1016,6 +1019,7 @@ public class BoardActivity extends XWActivity
} );
}
@Override
public void setTimer( int why, int when, int handle )
{
if ( null != m_timers[why] ) {
@ -1038,6 +1042,7 @@ public class BoardActivity extends XWActivity
postDelayed( m_timers[why], inHowLong );
}
@Override
public void clearTimer( int why )
{
if ( null != m_timers[why] ) {
@ -1047,6 +1052,7 @@ public class BoardActivity extends XWActivity
}
// This is supposed to be called from the jni thread
@Override
public int userPickTile( int playerNum, String[] texts )
{
m_texts = texts;
@ -1054,6 +1060,7 @@ public class BoardActivity extends XWActivity
return m_resultCode;
}
@Override
public String askPassword( String name )
{
// call this each time dlg created or will get exception
@ -1070,6 +1077,7 @@ public class BoardActivity extends XWActivity
return result;
}
@Override
public void turnChanged()
{
post( new Runnable() {
@ -1081,11 +1089,13 @@ public class BoardActivity extends XWActivity
m_jniThread.handle( JNIThread.JNICmd. CMD_ZOOM, -8 );
}
@Override
public boolean engineProgressCallback()
{
return ! m_jniThread.busy();
}
@Override
public boolean userQuery( int id, String query )
{
boolean result;
@ -1103,13 +1113,8 @@ public class BoardActivity extends XWActivity
break;
// These *are* blocking dialogs
case UtilCtxt.QUERY_COMMIT_TRADE:
case UtilCtxt.QUERY_COMMIT_TURN:
if ( UtilCtxt.QUERY_COMMIT_TRADE == id ) {
m_dlgBytes = getString( R.string.query_trade );
} else {
m_dlgBytes = query;
}
m_dlgBytes = query;
m_dlgTitle = R.string.query_title;
result = 0 != waitBlockingDialog( QUERY_REQUEST_BLK, 0 );
break;
@ -1121,6 +1126,17 @@ public class BoardActivity extends XWActivity
return result;
}
@Override
public boolean confirmTrade( String[] tiles )
{
m_dlgTitle = R.string.info_title;
m_dlgBytes =
Utils.format( BoardActivity.this, R.string.query_tradef,
TextUtils.join( ", ", tiles ) );
return 0 != waitBlockingDialog( QUERY_REQUEST_BLK, 0 );
}
@Override
public void userError( int code )
{
int resid = 0;
@ -1176,6 +1192,7 @@ public class BoardActivity extends XWActivity
}
} // userError
@Override
public void informMove( String expl, String words )
{
m_dlgBytes = expl;
@ -1184,6 +1201,7 @@ public class BoardActivity extends XWActivity
waitBlockingDialog( DLG_SCORES_BLK, 0 );
}
@Override
public void notifyGameOver()
{
m_jniThread.handle( JNIThread.JNICmd.CMD_POST_OVER );
@ -1194,7 +1212,7 @@ public class BoardActivity extends XWActivity
// Utils.logf( "yOffsetChange(maxOffset=%d)", maxOffset );
// m_view.setVerticalScrollBarEnabled( maxOffset > 0 );
// }
@Override
public boolean warnIllegalWord( String[] words, int turn,
boolean turnLost )
{
@ -1230,6 +1248,7 @@ public class BoardActivity extends XWActivity
// we don't block the jni thread will continue processing messages
// and may stack dialogs on top of this one. Including later
// chat-messages.
@Override
public void showChat( final String msg )
{
post( new Runnable() {

View file

@ -76,10 +76,10 @@ public interface UtilCtxt {
String getUserString( int stringCode );
static final int QUERY_COMMIT_TURN = 0;
static final int QUERY_COMMIT_TRADE = 1;
static final int QUERY_ROBOT_TRADE = 2;
static final int QUERY_ROBOT_TRADE = 1;
boolean userQuery( int id, String query );
boolean confirmTrade( String[] tiles );
// These oughtto be an enum but then I'd have to cons one up in C.
static final int ERR_NONE = 0;

View file

@ -184,6 +184,12 @@ public class UtilCtxtImpl implements UtilCtxt {
return false;
}
public boolean confirmTrade( String[] tiles )
{
subclassOverride( "confirmTrade" );
return false;
}
public void userError( int id )
{
subclassOverride( "userError" );

View file

@ -742,6 +742,20 @@ warnBadWords( const XP_UCHAR* word, XP_Bool isLegal,
return ok;
} /* warnBadWords */
static XP_Bool
boardConfirmTrade( BoardCtxt* board, const TrayTileSet* tiles )
{
const XP_UCHAR* tfaces[MAX_TRAY_TILES];
XP_U16 ii;
DictionaryCtxt* dict = model_getDictionary( board->model );
for ( ii = 0; ii < tiles->nTiles; ++ii ) {
tfaces[ii] = dict_getTileString( dict, tiles->tiles[ii] );
}
return util_confirmTrade( board->util, tfaces, tiles->nTiles );
}
XP_Bool
board_commitTurn( BoardCtxt* board )
{
@ -764,12 +778,16 @@ board_commitTurn( BoardCtxt* board )
if ( NO_TILES == traySelBits ) {
util_userError( board->util, ERR_NO_EMPTY_TRADE );
} else if ( util_userQuery( board->util, QUERY_COMMIT_TRADE,
(XWStreamCtxt*)NULL ) ) {
/* server_commitTrade() changes selPlayer, so board_endTrade
must be called first() */
(void)board_endTrade( board );
(void)server_commitTrade( board->server, traySelBits );
} else {
TrayTileSet selTiles;
getSelTiles( board, traySelBits, &selTiles );
if ( boardConfirmTrade( board, &selTiles ) ) {
/* server_commitTrade() changes selPlayer, so board_endTrade
must be called first() */
(void)board_endTrade( board );
(void)server_commitTrade( board->server, &selTiles );
}
}
} else {
XP_Bool warn, legal;

View file

@ -303,6 +303,7 @@ void invalCurHintRect( BoardCtxt* board, XP_U16 player );
void moveTileInTray( BoardCtxt* board, XP_U16 moveTo, XP_U16 moveFrom );
XP_Bool handleTrayDuringTrade( BoardCtxt* board, XP_S16 index );
void getSelTiles( const BoardCtxt* board, TileBit selBits, TrayTileSet* selTiles );
const XP_UCHAR* getTileDrawInfo( const BoardCtxt* board, Tile tile,
XP_Bool isBlank, XP_Bitmaps* bitmaps,

View file

@ -1518,7 +1518,7 @@ makeTileTrade( ModelCtxt* model, XP_S16 player, const TrayTileSet* oldTiles,
void
model_makeTileTrade( ModelCtxt* model, XP_S16 player,
TrayTileSet* oldTiles, TrayTileSet* newTiles )
const TrayTileSet* oldTiles, const TrayTileSet* newTiles )
{
stack_addTrade( model->vol.stack, player, oldTiles, newTiles );
@ -1526,9 +1526,9 @@ model_makeTileTrade( ModelCtxt* model, XP_S16 player,
} /* model_makeTileTrade */
Tile
model_getPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index )
model_getPlayerTile( const ModelCtxt* model, XP_S16 turn, XP_S16 index )
{
PlayerCtxt* player;
const PlayerCtxt* player;
XP_ASSERT( turn >= 0 );
player = &model->players[turn];

View file

@ -137,7 +137,7 @@ XP_U16 model_getCellOwner( ModelCtxt* model, XP_U16 col, XP_U16 row );
void model_assignPlayerTiles( ModelCtxt* model, XP_S16 turn,
const TrayTileSet* tiles );
Tile model_getPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index );
Tile model_getPlayerTile( const ModelCtxt* model, XP_S16 turn, XP_S16 index );
Tile model_removePlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index );
void model_addPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index,
@ -182,7 +182,8 @@ void model_commitTurn( ModelCtxt* model, XP_S16 player,
TrayTileSet* newTiles );
void model_commitRejectedPhony( ModelCtxt* model, XP_S16 player );
void model_makeTileTrade( ModelCtxt* model, XP_S16 player,
TrayTileSet* oldTiles, TrayTileSet* newTiles );
const TrayTileSet* oldTiles,
const TrayTileSet* newTiles );
XP_Bool model_undoLatestMoves( ModelCtxt* model, PoolContext* pool,
XP_U16 nMovesSought, XP_U16* turn,

View file

@ -295,7 +295,7 @@ stack_addPhony( StackCtxt* stack, XP_U16 turn, MoveInfo* moveInfo )
void
stack_addTrade( StackCtxt* stack, XP_U16 turn,
TrayTileSet* oldTiles, TrayTileSet* newTiles )
const TrayTileSet* oldTiles, const TrayTileSet* newTiles )
{
StackEntry move;

View file

@ -79,7 +79,8 @@ void stack_addMove( StackCtxt* stack, XP_U16 turn, const MoveInfo* moveInfo,
const TrayTileSet* newTiles );
void stack_addPhony( StackCtxt* stack, XP_U16 turn, MoveInfo* moveInfo );
void stack_addTrade( StackCtxt* stack, XP_U16 turn,
TrayTileSet* oldTiles, TrayTileSet* newTiles );
const TrayTileSet* oldTiles,
const TrayTileSet* newTiles );
void stack_addAssign( StackCtxt* stack, XP_U16 turn,
const TrayTileSet* tiles );

View file

@ -171,10 +171,10 @@ pool_requestTiles( PoolContext* pool, Tile* tiles, XP_U8* maxNum )
} /* pool_requestTiles */
void
pool_replaceTiles( PoolContext* pool, TrayTileSet* tiles )
pool_replaceTiles( PoolContext* pool, const TrayTileSet* tiles )
{
XP_U16 nTiles = tiles->nTiles;
Tile* tilesP = tiles->tiles;
const Tile* tilesP = tiles->tiles;
while ( nTiles-- ) {
Tile tile = *tilesP++; /* do I need to filter off high bits? */
@ -188,10 +188,10 @@ pool_replaceTiles( PoolContext* pool, TrayTileSet* tiles )
} /* pool_replaceTiles */
void
pool_removeTiles( PoolContext* pool, TrayTileSet* tiles )
pool_removeTiles( PoolContext* pool, const TrayTileSet* tiles )
{
XP_U16 nTiles = tiles->nTiles;
Tile* tilesP = tiles->tiles;
const Tile* tilesP = tiles->tiles;
XP_ASSERT( nTiles <= MAX_TRAY_TILES );

View file

@ -26,8 +26,8 @@
void pool_requestTiles( PoolContext* pool, Tile* tiles,
/*in out*/ XP_U8* maxNum );
void pool_replaceTiles( PoolContext* pool, TrayTileSet* tiles );
void pool_removeTiles( PoolContext* pool, TrayTileSet* tiles );
void pool_replaceTiles( PoolContext* pool, const TrayTileSet* tiles );
void pool_removeTiles( PoolContext* pool, const TrayTileSet* tiles );
XP_U16 pool_getNTilesLeft( PoolContext* pool );
XP_U16 pool_getNTilesLeftFor( PoolContext* pool, Tile tile );

View file

@ -727,7 +727,8 @@ makeRobotMove( ServerCtxt* server )
/* trade if unable to find a move */
if ( trade ) {
result = server_commitTrade( server, ALLTILES );
result = server_commitTrade( server,
model_getPlayerTiles( model, turn ) );
/* Quick hack to fix gremlin bug where all-robot game seen none
able to trade for tiles to move and blowing the undo stack.
@ -1772,7 +1773,7 @@ checkMoveAllowed( ServerCtxt* server, XP_U16 playerNum )
static void
sendMoveTo( ServerCtxt* server, XP_U16 devIndex, XP_U16 turn,
XP_Bool legal, TrayTileSet* newTiles,
TrayTileSet* tradedTiles ) /* null if a move, set if a trade */
const TrayTileSet* tradedTiles ) /* null if a move, set if a trade */
{
XWStreamCtxt* stream;
XP_Bool isTrade = !!tradedTiles;
@ -1845,7 +1846,7 @@ readMoveInfo( ServerCtxt* server, XWStreamCtxt* stream,
static void
sendMoveToClientsExcept( ServerCtxt* server, XP_U16 whoMoved, XP_Bool legal,
TrayTileSet* newTiles, TrayTileSet* tradedTiles,
TrayTileSet* newTiles, const TrayTileSet* tradedTiles,
XP_U16 skip )
{
XP_U16 devIndex;
@ -2117,49 +2118,27 @@ server_commitMove( ServerCtxt* server )
return XP_TRUE;
} /* server_commitMove */
static void
removeTradedTiles( ServerCtxt* server, TileBit selBits, TrayTileSet* tiles )
{
XP_U8 nTiles = 0;
XP_S16 index;
XP_S16 turn = server->nv.currentTurn;
/* selBits: It's gross that server knows this much about tray's
implementation. PENDING(ehouse) */
for ( index = 0; selBits != 0; selBits >>= 1, ++index ) {
if ( (selBits & 0x01) != 0 ) {
Tile tile = model_getPlayerTile( server->vol.model, turn, index );
tiles->tiles[nTiles++] = tile;
}
}
tiles->nTiles = nTiles;
} /* saveTradedTiles */
XP_Bool
server_commitTrade( ServerCtxt* server, TileBit selBits )
server_commitTrade( ServerCtxt* server, const TrayTileSet* oldTiles )
{
TrayTileSet oldTiles;
TrayTileSet newTiles;
XP_U16 turn = server->nv.currentTurn;
removeTradedTiles( server, selBits, &oldTiles );
fetchTiles( server, turn, oldTiles.nTiles, &oldTiles, &newTiles );
fetchTiles( server, turn, oldTiles->nTiles, oldTiles, &newTiles );
#ifndef XWFEATURE_STANDALONE_ONLY
if ( server->vol.gi->serverRole == SERVER_ISCLIENT ) {
/* just send to server */
sendMoveTo(server, SERVER_DEVICE, turn, XP_TRUE, &newTiles, &oldTiles);
sendMoveTo(server, SERVER_DEVICE, turn, XP_TRUE, &newTiles, oldTiles);
} else {
sendMoveToClientsExcept( server, turn, XP_TRUE, &newTiles, &oldTiles,
sendMoveToClientsExcept( server, turn, XP_TRUE, &newTiles, oldTiles,
SERVER_DEVICE );
}
#endif
pool_replaceTiles( server->pool, &oldTiles );
pool_replaceTiles( server->pool, oldTiles );
model_makeTileTrade( server->vol.model, server->nv.currentTurn,
&oldTiles, &newTiles );
oldTiles, &newTiles );
sortTilesIf( server, turn );
nextTurn( server, PICK_NEXT );

View file

@ -101,7 +101,7 @@ XP_S16 server_countTilesInPool( ServerCtxt* server );
XP_Bool server_do( ServerCtxt* server );
XP_Bool server_commitMove( ServerCtxt* server );
XP_Bool server_commitTrade( ServerCtxt* server, TileBit bits );
XP_Bool server_commitTrade( ServerCtxt* server, const TrayTileSet* oldTiles );
/* call this when user wants to end the game */
void server_endGame( ServerCtxt* server );

View file

@ -379,6 +379,24 @@ handleTrayDuringTrade( BoardCtxt* board, XP_S16 index )
return XP_TRUE;
} /* handleTrayDuringTrade */
void
getSelTiles( const BoardCtxt* board, TileBit selBits, TrayTileSet* selTiles )
{
XP_U16 nTiles = 0;
XP_S16 index;
XP_S16 turn = board->selPlayer;
const ModelCtxt* model = board->model;
for ( index = 0; selBits != 0; selBits >>= 1, ++index ) {
if ( 0 != (selBits & 0x01) ) {
Tile tile = model_getPlayerTile( model, turn, index );
XP_ASSERT( nTiles < VSIZE(selTiles->tiles) );
selTiles->tiles[nTiles++] = tile;
}
}
selTiles->nTiles = nTiles;
}
static XP_Bool
handleActionInTray( BoardCtxt* board, XP_S16 index, XP_Bool onDivider )
{

View file

@ -65,7 +65,6 @@ typedef enum {
typedef enum {
QUERY_COMMIT_TURN, /* 0 means cancel; 1 means commit */
QUERY_COMMIT_TRADE,
QUERY_ROBOT_TRADE,
QUERY_LAST_COMMON
@ -113,7 +112,8 @@ typedef struct UtilVtable {
XP_Bool (*m_util_userQuery)( XW_UtilCtxt* uc, UtilQueryID id,
XWStreamCtxt* stream );
XP_Bool (*m_util_confirmTrade)( XW_UtilCtxt* uc, const XP_UCHAR** tiles,
XP_U16 nTiles );
/* return of < 0 means computer should pick */
XP_S16 (*m_util_userPickTile)( XW_UtilCtxt* uc, const PickInfo* pi,
XP_U16 playerNum,
@ -213,6 +213,9 @@ struct XW_UtilCtxt {
#define util_userQuery(uc,qcode,str) \
(uc)->vtable->m_util_userQuery((uc),(qcode),(str))
#define util_confirmTrade( uc, tx, nt ) \
(uc)->vtable->m_util_confirmTrade((uc),(tx),(nt))
#define util_userPickTile( uc, w, n, tx, nt ) \
(uc)->vtable->m_util_userPickTile( (uc), (w), (n), (tx), (nt) )
#define util_askPassword( uc, n, b, lp ) \

View file

@ -1,6 +1,6 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE"; -*- */
/* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
/*
* Copyright 2000-2009 by Eric House (xwords@eehouse.org). All rights
* Copyright 2000 - 2011 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
@ -277,11 +277,6 @@ curses_util_userQuery( XW_UtilCtxt* uc, UtilQueryID id, XWStreamCtxt* stream )
answers[numAnswers++] = "Cancel";
answers[numAnswers++] = "Ok";
break;
case QUERY_COMMIT_TRADE:
question = "Commit trade?";
answers[numAnswers++] = "Cancel";
answers[numAnswers++] = "Ok";
break;
case QUERY_ROBOT_TRADE:
question = strFromStream( stream );
freeMe = XP_TRUE;
@ -304,6 +299,16 @@ curses_util_userQuery( XW_UtilCtxt* uc, UtilQueryID id, XWStreamCtxt* stream )
return result;
} /* curses_util_userQuery */
static XP_Bool
curses_util_confirmTrade( XW_UtilCtxt* uc, const XP_UCHAR** tiles,
XP_U16 nTiles )
{
CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure;
char question[256];
formatConfirmTrade( tiles, nTiles, question, sizeof(question) );
return 1 == cursesask( globals, question, 2, "Cancel", "Ok" );
}
static void
curses_util_trayHiddenChange( XW_UtilCtxt* XP_UNUSED(uc),
XW_TrayVisState XP_UNUSED(state),
@ -1472,6 +1477,7 @@ setupCursesUtilCallbacks( CursesAppGlobals* globals, XW_UtilCtxt* util )
util->vtable->m_util_makeStreamFromAddr = curses_util_makeStreamFromAddr;
#endif
util->vtable->m_util_userQuery = curses_util_userQuery;
util->vtable->m_util_confirmTrade = curses_util_confirmTrade;
util->vtable->m_util_userPickTile = curses_util_userPickTile;
util->vtable->m_util_trayHiddenChange = curses_util_trayHiddenChange;
util->vtable->m_util_informMove = curses_util_informMove;

View file

@ -1761,9 +1761,6 @@ gtk_util_userQuery( XW_UtilCtxt* XP_UNUSED(uc), UtilQueryID id,
question = strFromStream( stream );
freeMe = XP_TRUE;
break;
case QUERY_COMMIT_TRADE:
question = "Are you sure you want to trade the selected tiles?";
break;
case QUERY_ROBOT_TRADE:
question = strFromStream( stream );
freeMe = XP_TRUE;
@ -1784,6 +1781,15 @@ gtk_util_userQuery( XW_UtilCtxt* XP_UNUSED(uc), UtilQueryID id,
return result;
} /* gtk_util_userQuery */
static XP_Bool
gtk_util_confirmTrade( XW_UtilCtxt* XP_UNUSED(uc),
const XP_UCHAR** tiles, XP_U16 nTiles )
{
char question[256];
formatConfirmTrade( tiles, nTiles, question, sizeof(question) );
return gtkask( question, GTK_BUTTONS_YES_NO );
}
static GtkWidget*
makeShowButtonFromBitmap( void* closure, const gchar* filename,
const gchar* alt, GCallback func )
@ -1922,6 +1928,7 @@ setupGtkUtilCallbacks( GtkAppGlobals* globals, XW_UtilCtxt* util )
{
util->vtable->m_util_userError = gtk_util_userError;
util->vtable->m_util_userQuery = gtk_util_userQuery;
util->vtable->m_util_confirmTrade = gtk_util_confirmTrade;
util->vtable->m_util_getVTManager = gtk_util_getVTManager;
util->vtable->m_util_userPickTile = gtk_util_userPickTile;
util->vtable->m_util_askPassword = gtk_util_askPassword;

View file

@ -1,6 +1,6 @@
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE"; -*- */
/* -*- compile-command: "make MEMDEBUG=TRUE -j3"; -*- */
/*
* Copyright 2000-2009 by Eric House (xwords@eehouse.org). All rights
* Copyright 2000-2011 by Eric House (xwords@eehouse.org). All rights
* reserved.
*
* This program is free software; you can redistribute it and/or
@ -407,6 +407,27 @@ linux_getErrString( UtilErrID id, XP_Bool* silent )
return (XP_UCHAR*)message;
} /* linux_getErrString */
void
formatConfirmTrade( const XP_UCHAR** tiles, XP_U16 nTiles,
char* buf, XP_U16 buflen )
{
char tileBuf[128];
int offset = 0;
int ii;
XP_ASSERT( nTiles > 0 );
for ( ii = 0; ii < nTiles; ++ii ) {
offset += snprintf( &tileBuf[offset], sizeof(tileBuf) - offset,
"%s, ", tiles[ii] );
XP_ASSERT( offset < sizeof(tileBuf) );
}
tileBuf[offset-2] = '\0';
snprintf( buf, buflen,
"Are you sure you want to trade the selected tiles (%s)?",
tileBuf );
}
#ifdef TEXT_MODEL
/* This is broken for UTF-8, even Spanish */
void

View file

@ -38,4 +38,7 @@ void linux_util_vt_destroy( XW_UtilCtxt* util );
const XP_UCHAR* linux_getErrString( UtilErrID id, XP_Bool* silent );
void formatConfirmTrade( const XP_UCHAR** tiles, XP_U16 nTiles, char* buf,
XP_U16 buflen );
#endif