diff --git a/xwords4/common/boarddrw.c b/xwords4/common/boarddrw.c index 54aeed94c..c4391a7af 100644 --- a/xwords4/common/boarddrw.c +++ b/xwords4/common/boarddrw.c @@ -358,7 +358,7 @@ drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool skipBlanks ) XP_Bool invert = XP_FALSE; XP_Bitmaps bitmaps; XP_Bitmaps* bptr = NULL; - XP_UCHAR* textP = NULL; + const XP_UCHAR* textP = NULL; HintAtts hintAtts; CellFlags flags = CELL_NONE; XP_Bool isOrigin; @@ -392,15 +392,14 @@ drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool skipBlanks ) if ( board->showCellValues ) { Tile valTile = isBlank? dict_getBlankTile( dict ) : tile; XP_U16 val = dict_getTileValue( dict, valTile ); - XP_SNPRINTF( ch, sizeof(ch), (XP_UCHAR*)"%d", val ); + XP_SNPRINTF( ch, VSIZE(ch), "%d", val ); textP = ch; } else { if ( dict_faceIsBitmap( dict, tile ) ) { dict_getFaceBitmaps( dict, tile, &bitmaps ); bptr = &bitmaps; } - (void)dict_tilesToString( dict, &tile, 1, ch, sizeof(ch) ); - textP = ch; + textP = dict_getTileString( dict, tile ); } } bonus = util_getSquareBonus( board->util, model, col, row ); @@ -482,8 +481,7 @@ drawDragTileIf( BoardCtxt* board ) XP_Rect rect; Tile tile; XP_Bool isBlank; - XP_UCHAR buf[4]; - XP_UCHAR* face; + const XP_UCHAR* face; XP_Bitmaps bitmaps; XP_S16 value; CellFlags flags; @@ -493,7 +491,7 @@ drawDragTileIf( BoardCtxt* board ) dragDropTileInfo( board, &tile, &isBlank ); face = getTileDrawInfo( board, tile, isBlank, &bitmaps, - &value, buf, sizeof(buf) ); + &value ); flags = CELL_DRAGCUR; if ( isBlank ) { diff --git a/xwords4/common/boardp.h b/xwords4/common/boardp.h index b0071d98b..08ee48f8b 100644 --- a/xwords4/common/boardp.h +++ b/xwords4/common/boardp.h @@ -269,9 +269,9 @@ void hideMiniWindow( BoardCtxt* board, XP_Bool destroy, void moveTileInTray( BoardCtxt* board, XP_U16 moveTo, XP_U16 moveFrom ); XP_Bool handleTrayDuringTrade( BoardCtxt* board, XP_S16 index ); -XP_UCHAR* getTileDrawInfo( const BoardCtxt* board, Tile tile, XP_Bool isBlank, - XP_Bitmaps* bitmaps, XP_S16* value, - XP_UCHAR* buf, XP_U16 len ); +const XP_UCHAR* getTileDrawInfo( const BoardCtxt* board, Tile tile, + XP_Bool isBlank, XP_Bitmaps* bitmaps, + XP_S16* value ); XP_Bool dividerMoved( BoardCtxt* board, XP_U8 newLoc ); XP_Bool checkScrollCell( BoardCtxt* board, XP_U16 col, XP_U16 row ); diff --git a/xwords4/common/engine.c b/xwords4/common/engine.c index aa337e53c..5b0c64413 100644 --- a/xwords4/common/engine.c +++ b/xwords4/common/engine.c @@ -1046,7 +1046,7 @@ considerScoreWordHasBlanks( EngineCtxt* engine, XP_U16 blanksLeft, score = figureMoveScore( engine->model, &posmove->moveInfo, engine, (XWStreamCtxt*)NULL, - (WordNotifierInfo*)NULL, NULL ); + (WordNotifierInfo*)NULL, NULL, 0 ); /* First, check that the score is even what we're interested in. If it is, then go to the expense of filling in a PossibleMove to be diff --git a/xwords4/common/model.c b/xwords4/common/model.c index df0bb4343..8bbe35f4d 100644 --- a/xwords4/common/model.c +++ b/xwords4/common/model.c @@ -272,7 +272,7 @@ model_setDictionary( ModelCtxt* model, DictionaryCtxt* dict ) } /* model_setDictionary */ DictionaryCtxt* -model_getDictionary( ModelCtxt* model ) +model_getDictionary( const ModelCtxt* model ) { /* XP_ASSERT( !!model->vol.dict ); */ return model->vol.dict; @@ -1513,7 +1513,7 @@ printMovePre( ModelCtxt* model, XP_U16 XP_UNUSED(moveN), StackEntry* entry, if ( isPass ) { format = util_getUserString( model->vol.util, STR_PASS ); - XP_SNPRINTF( buf, sizeof(buf), "%s", format ); + XP_SNPRINTF( buf, VSIZE(buf), "%s", format ); } else { if ( isHorizontal ) { format = util_getUserString( model->vol.util, STRS_MOVE_ACROSS ); @@ -1676,7 +1676,7 @@ scoreLastMove( ModelCtxt* model, MoveInfo* moveInfo, XP_U16 howMany, const XP_UCHAR* str = util_getUserString( model->vol.util, STR_PASSED ); XP_U16 len = XP_STRLEN( str ); *bufLen = len; - XP_MEMCPY( buf, str, len+1 ); /* no XP_STRCPY yet */ + XP_STRNCPY( buf, str, len + 1 ); } else { XP_U16 score; XP_UCHAR wordBuf[MAX_ROWS+1]; @@ -1695,7 +1695,7 @@ scoreLastMove( ModelCtxt* model, MoveInfo* moveInfo, XP_U16 howMany, score = figureMoveScore( tmpModel, moveInfo, (EngineCtxt*)NULL, (XWStreamCtxt*)NULL, (WordNotifierInfo*)NULL, - wordBuf ); + wordBuf, VSIZE(wordBuf) ); model_destroy( tmpModel ); diff --git a/xwords4/common/model.h b/xwords4/common/model.h index 506ca89d0..a449c2681 100644 --- a/xwords4/common/model.h +++ b/xwords4/common/model.h @@ -112,7 +112,7 @@ void model_destroy( ModelCtxt* model ); void model_setNPlayers( ModelCtxt* model, XP_U16 numPlayers ); void model_setDictionary( ModelCtxt* model, DictionaryCtxt* dict ); -DictionaryCtxt* model_getDictionary( ModelCtxt* model ); +DictionaryCtxt* model_getDictionary( const ModelCtxt* model ); XP_Bool model_getTile( const ModelCtxt* model, XP_U16 col, XP_U16 row, XP_Bool getPending, XP_S16 turn, @@ -242,7 +242,8 @@ void model_figureFinalScores( ModelCtxt* model, ScoresArray* scores, /* figureMoveScore is meant only for the engine's use */ XP_U16 figureMoveScore( const ModelCtxt* model, MoveInfo* moveInfo, EngineCtxt* engine, XWStreamCtxt* stream, - WordNotifierInfo* notifyInfo, XP_UCHAR* mainWord ); + WordNotifierInfo* notifyInfo, XP_UCHAR* mainWord, + XP_U16 mainWordLen ); /********************* persistence ********************/ #ifdef INCLUDE_IO_SUPPORT diff --git a/xwords4/common/mscore.c b/xwords4/common/mscore.c index 1e4361322..917ff2631 100644 --- a/xwords4/common/mscore.c +++ b/xwords4/common/mscore.c @@ -42,7 +42,8 @@ static XP_S16 checkScoreMove( ModelCtxt* model, XP_S16 turn, XP_Bool silent, WordNotifierInfo* notifyInfo ); static XP_U16 scoreWord( const ModelCtxt* model, MoveInfo* movei, EngineCtxt* engine, XWStreamCtxt* stream, - WordNotifierInfo* notifyInfo, XP_UCHAR* mainWord ); + WordNotifierInfo* notifyInfo, XP_UCHAR* mainWord, + XP_U16 mainWordLen ); /* for formatting when caller wants an explanation of the score. These live in separate function called only when stream != NULL so that they'll have @@ -63,7 +64,8 @@ static void wordScoreFormatterAddTile( WordScoreFormatter* fmtr, Tile tile, XP_U16 tileMultiplier, XP_Bool isBlank ); static void wordScoreFormatterFinish( WordScoreFormatter* fmtr, Tile* word, - XWStreamCtxt* stream, XP_UCHAR* mainWord ); + XWStreamCtxt* stream, XP_UCHAR* mainWord, + XP_U16 mainWordLen ); static void formatWordScore( XWStreamCtxt* stream, XP_U16 wordScore, XP_U16 moveMultiplier ); static void formatSummary( XWStreamCtxt* stream, const ModelCtxt* model, @@ -102,7 +104,7 @@ adjustScoreForUndone( ModelCtxt* model, MoveInfo* mi, XP_U16 turn ) } else { moveScore = figureMoveScore( model, mi, (EngineCtxt*)NULL, (XWStreamCtxt*)NULL, - (WordNotifierInfo*)NULL, NULL ); + (WordNotifierInfo*)NULL, NULL, 0 ); } player->score -= moveScore; player->curMoveScore = 0; @@ -239,7 +241,7 @@ checkScoreMove( ModelCtxt* model, XP_S16 turn, EngineCtxt* engine, if ( isLegalMove( model, &moveInfo, silent ) ) { score = figureMoveScore( model, &moveInfo, engine, stream, - notifyInfo, NULL ); + notifyInfo, NULL, 0 ); } } else if ( !silent ) { /* tiles out of line */ util_userError( model->vol.util, ERR_TILES_NOT_IN_LINE ); @@ -444,7 +446,8 @@ isLegalMove( ModelCtxt* model, MoveInfo* mInfo, XP_Bool silent ) XP_U16 figureMoveScore( const ModelCtxt* model, MoveInfo* moveInfo, EngineCtxt* engine, XWStreamCtxt* stream, - WordNotifierInfo* notifyInfo, XP_UCHAR* mainWord ) + WordNotifierInfo* notifyInfo, XP_UCHAR* mainWord, + XP_U16 mainWordLen ) { XP_U16 col, row; XP_U16* incr; @@ -473,7 +476,7 @@ figureMoveScore( const ModelCtxt* model, MoveInfo* moveInfo, } oneScore = scoreWord( model, moveInfo, (EngineCtxt*)NULL, stream, - notifyInfo, mainWord ); + notifyInfo, mainWord, mainWordLen ); if ( !!stream ) { formatWordScore( stream, oneScore, moveMultiplier ); } @@ -499,7 +502,7 @@ figureMoveScore( const ModelCtxt* model, MoveInfo* moveInfo, tmpMI.tiles[0].tile = tiles->tile; oneScore = scoreWord( model, &tmpMI, engine, stream, - notifyInfo, mainWord ); + notifyInfo, mainWord, mainWordLen ); if ( !!stream ) { formatWordScore( stream, oneScore, multipliers[i] ); } @@ -559,7 +562,7 @@ scoreWord( const ModelCtxt* model, MoveInfo* movei, /* new tiles */ EngineCtxt* engine,/* for crosswise caching */ XWStreamCtxt* stream, WordNotifierInfo* notifyInfo, - XP_UCHAR* mainWord ) + XP_UCHAR* mainWord, XP_U16 mainWordLen ) { XP_U16 tileMultiplier; XP_U16 restScore = 0; @@ -682,7 +685,7 @@ scoreWord( const ModelCtxt* model, MoveInfo* movei, /* new tiles */ if ( !!stream || !!mainWord ) { wordScoreFormatterFinish( &fmtr, checkWordBuf, stream, - mainWord ); + mainWord, mainWordLen ); } #ifdef DEBUG @@ -760,16 +763,17 @@ static void wordScoreFormatterAddTile( WordScoreFormatter* fmtr, Tile tile, XP_U16 tileMultiplier, XP_Bool isBlank ) { - XP_UCHAR buf[4]; + const XP_UCHAR* face; XP_UCHAR* fullBufPtr; XP_UCHAR* prefix; XP_U16 tileScore; ++fmtr->nTiles; - dict_tilesToString( fmtr->dict, &tile, 1, buf, sizeof(buf) ); - XP_ASSERT( XP_STRLEN(fmtr->wordBuf) + XP_STRLEN(buf) < sizeof(fmtr->wordBuf) ); - XP_STRCAT( fmtr->wordBuf, buf ); + face = dict_getTileString( fmtr->dict, tile ); + XP_ASSERT( XP_STRLEN(fmtr->wordBuf) + XP_STRLEN(face) + < sizeof(fmtr->wordBuf) ); + XP_STRCAT( fmtr->wordBuf, face ); if ( isBlank ) { tile = dict_getBlankTile( fmtr->dict ); } @@ -795,8 +799,9 @@ wordScoreFormatterAddTile( WordScoreFormatter* fmtr, Tile tile, } /* wordScoreFormatterAddTile */ static void -wordScoreFormatterFinish( WordScoreFormatter* fmtr, Tile* word, XWStreamCtxt* stream, - XP_UCHAR* mainWord ) +wordScoreFormatterFinish( WordScoreFormatter* fmtr, Tile* word, + XWStreamCtxt* stream, XP_UCHAR* mainWord, + XP_U16 mainWordLen ) { XP_UCHAR buf[(MAX_ROWS*2)+1]; XP_U16 len = dict_tilesToString( fmtr->dict, word, fmtr->nTiles, @@ -810,7 +815,7 @@ wordScoreFormatterFinish( WordScoreFormatter* fmtr, Tile* word, XWStreamCtxt* st } if ( !!mainWord ) { - XP_MEMCPY( mainWord, fmtr->wordBuf, XP_STRLEN(fmtr->wordBuf) + 1 ); + XP_STRNCPY( mainWord, fmtr->wordBuf, mainWordLen ); } } /* wordScoreFormatterFinish */ diff --git a/xwords4/common/server.c b/xwords4/common/server.c index 00ee929da..022560850 100644 --- a/xwords4/common/server.c +++ b/xwords4/common/server.c @@ -972,8 +972,10 @@ client_readInitialMessage( ServerCtxt* server, XWStreamCtxt* stream ) /* version */ XP_U8 streamVersion = stream_getU8( stream ); - XP_ASSERT( streamVersion == STREAM_VERS_41B4 ); - if ( streamVersion != STREAM_VERS_41B4 ) { + XP_ASSERT( streamVersion == STREAM_VERS_41B4 + || streamVersion == STREAM_VERS_UTF8); + if ( (streamVersion != STREAM_VERS_41B4) + && (streamVersion != STREAM_VERS_UTF8) ) { return XP_FALSE; } stream_setVersion( stream, streamVersion ); @@ -1106,13 +1108,15 @@ server_sendInitialMessage( ServerCtxt* server ) RemoteAddress* addr = &server->nv.addresses[deviceIndex]; XWStreamCtxt* stream = util_makeStreamFromAddr( server->vol.util, addr->channelNo ); + DictionaryCtxt* dict = model_getDictionary(model); XP_ASSERT( !!stream ); stream_open( stream ); stream_putBits( stream, XWPROTO_NBITS, XWPROTO_CLIENT_SETUP ); /* write version for server's benefit; use old version until format changes */ - stream_putU8( stream, STREAM_VERS_41B4 ); + stream_putU8( stream, dict_isUTF8(dict)? + STREAM_VERS_UTF8:STREAM_VERS_41B4 ); XP_STATUSF( "putting gameID %lx into msg", gameID ); stream_putU32( stream, gameID ); @@ -1120,7 +1124,7 @@ server_sendInitialMessage( ServerCtxt* server ) makeSendableGICopy( server, &localGI, deviceIndex ); gi_writeToStream( stream, &localGI ); - dict_writeToStream( model_getDictionary(model), stream ); + dict_writeToStream( dict, stream ); /* send tiles currently in tray */ for ( i = 0; i < nPlayers; ++i ) { @@ -2404,13 +2408,12 @@ server_formatDictCounts( ServerCtxt* server, XWStreamCtxt* stream, for ( tile = 0, nPrinted = 0; ; ) { XP_UCHAR buf[24]; - XP_UCHAR face[4]; XP_U16 count, value; count = dict_numTiles( dict, tile ); if ( count > 0 ) { - dict_tilesToString( dict, &tile, 1, face, sizeof(face) ); + const XP_UCHAR* face = dict_getTileString( dict, tile ); value = dict_getTileValue( dict, tile ); XP_SNPRINTF( buf, sizeof(buf), (XP_UCHAR*)"%s: %d/%d", @@ -2461,8 +2464,7 @@ server_formatRemainingTiles( ServerCtxt* server, XWStreamCtxt* stream, XP_Bool hasCount = count > 0; if ( hasCount ) { - XP_UCHAR face[4]; - dict_tilesToString( dict, &tile, 1, face, sizeof(face) ); + const XP_UCHAR* face = dict_getTileString( dict, tile ); for ( ; ; ) { stream_catString( stream, face ); diff --git a/xwords4/common/tray.c b/xwords4/common/tray.c index 53a16f8dc..1307e8308 100644 --- a/xwords4/common/tray.c +++ b/xwords4/common/tray.c @@ -186,9 +186,8 @@ drawTray( BoardCtxt* board ) draw_drawTile( board->draw, &tileRect, NULL, NULL, -1, flags | CELL_ISEMPTY ); } else if ( showFaces ) { - XP_UCHAR buf[4]; XP_Bitmaps bitmaps; - XP_UCHAR* textP = (XP_UCHAR*)NULL; + const XP_UCHAR* textP = (XP_UCHAR*)NULL; XP_U8 traySelBits = pti->traySelBits; XP_S16 value; Tile tile; @@ -211,8 +210,7 @@ drawTray( BoardCtxt* board ) } textP = getTileDrawInfo( board, tile, isBlank, - &bitmaps, &value, - buf, sizeof(buf) ); + &bitmaps, &value ); if ( isADrag ) { if ( ddAddedIndx == ii ) { flags |= CELL_HIGHLIGHT; @@ -258,18 +256,16 @@ drawTray( BoardCtxt* board ) } /* drawTray */ -XP_UCHAR* +const XP_UCHAR* getTileDrawInfo( const BoardCtxt* board, Tile tile, XP_Bool isBlank, - XP_Bitmaps* bitmaps, XP_S16* value, XP_UCHAR* buf, - XP_U16 len ) + XP_Bitmaps* bitmaps, XP_S16* value ) { - XP_UCHAR* face = NULL; + const XP_UCHAR* face = NULL; DictionaryCtxt* dict = model_getDictionary( board->model ); if ( isBlank ) { tile = dict_getBlankTile( dict ); } else { - dict_tilesToString( dict, &tile, 1, buf, len ); - face = buf; + face = dict_getTileString( dict, tile ); } *value = dict_getTileValue( dict, tile );