diff --git a/xwords4/common/board.c b/xwords4/common/board.c index 3dc6bbbd7..cb4d43421 100644 --- a/xwords4/common/board.c +++ b/xwords4/common/board.c @@ -439,6 +439,9 @@ board_figureLayout( BoardCtxt* board, const CurGameInfo* gi, // Scrolling's required if we use cell width sufficient to // fill the screen. But perhaps we don't need to. int cellWidth = 2 * (bHeight / ( 4 + 3 + (2*nCells))); + if ( cellWidth < fontWidth ) { + cellWidth = fontWidth; + } if ( firstPass && cellWidth >= fontHt ) { firstPass = XP_FALSE; ldims.boardWidth = nCells * cellWidth; diff --git a/xwords4/linux/cursesask.c b/xwords4/linux/cursesask.c index ffca1a9a7..31dd27c82 100644 --- a/xwords4/linux/cursesask.c +++ b/xwords4/linux/cursesask.c @@ -31,9 +31,9 @@ /* Figure out how many lines there are and how wide the widest is. */ -short +int cursesask( CursesAppGlobals* globals, const char* question, short numButtons, - const char* button1, ... ) + const char** buttons ) { WINDOW* confWin; int x, y, rows, row, nLines; @@ -79,7 +79,7 @@ cursesask( CursesAppGlobals* globals, const char* question, short numButtons, if ( newSelButton != curSelButton ) { drawButtons( confWin, rows+1, spacePerButton, numButtons, - curSelButton=newSelButton, &button1 ); + curSelButton=newSelButton, buttons ); } ch = wgetch( confWin ); diff --git a/xwords4/linux/cursesask.h b/xwords4/linux/cursesask.h index 36f20fb35..7e57db136 100644 --- a/xwords4/linux/cursesask.h +++ b/xwords4/linux/cursesask.h @@ -22,8 +22,8 @@ #include "cursesmain.h" -short cursesask( CursesAppGlobals* globals, const char* question, - short numButtons, const char* button1, ... ); +int cursesask( CursesAppGlobals* globals, const char* question, + short numButtons, const char** buttons ); #endif diff --git a/xwords4/linux/cursesdraw.c b/xwords4/linux/cursesdraw.c index e7aca9648..067ea87fa 100644 --- a/xwords4/linux/cursesdraw.c +++ b/xwords4/linux/cursesdraw.c @@ -122,12 +122,12 @@ curses_draw_drawRemText( DrawCtx* p_dctx, XP_S16 nTilesLeft, } #else static void -formatRemText( char* buf, int bufLen, XP_S16 nTilesLeft, int width ) +formatRemText( char* buf, int bufLen, XP_S16 nTilesLeft, int XP_UNUSED(width) ) { - snprintf( buf, bufLen, "Tiles left in pool: %.3d", nTilesLeft ); - if ( strlen(buf)+1 >= width ) { + /* int len = snprintf( buf, bufLen, "Tiles left in pool: %.3d", nTilesLeft ); */ + /* if ( len > bufLen || strlen(buf)+1 >= width ) { */ snprintf( buf, bufLen, "Rem: %.3d", nTilesLeft ); - } + /* } */ } /* formatRemText */ static XP_Bool @@ -136,11 +136,11 @@ curses_draw_measureRemText( DrawCtx* XP_UNUSED(dctx), XP_S16 nTilesLeft, XP_U16* width, XP_U16* height ) { - char buf[32]; + char buf[64]; formatRemText( buf, sizeof(buf), nTilesLeft, r->width ); *width = strlen(buf); - *height = 1; + *height = r->height; return XP_TRUE; } /* curses_draw_measureRemText */ @@ -162,6 +162,7 @@ curses_draw_drawRemText( DrawCtx* p_dctx, const XP_Rect* rInner, #ifdef XWFEATURE_SCOREONEPASS #else +#if 0 static int fitIn( char* buf, int len, int* rem, const char* str ) { @@ -177,41 +178,35 @@ fitIn( char* buf, int len, int* rem, const char* str ) memcpy( buf, str, slen ); return len; } /* fitIn */ +#endif static void -formatScoreText( XP_UCHAR* out, int outLen, const DrawScoreInfo* dsi, - int width ) +formatScoreText( XP_UCHAR* out, const DrawScoreInfo* dsi, const XP_Rect* rect, + char** lines ) { - /* Long and short formats. We'll try long first. If it fits, cool. - Otherwise we use short. Either way, we fill the whole rect so it can - overwrite anything that was there before.*/ - char tmp[width+1]; - char buf[width+1]; - int scoreWidth = 4; - - XP_ASSERT( width < outLen ); - - XP_MEMSET( buf, ' ', width ); - buf[width] = '\0'; - - /* Status/role chars at start */ - if ( dsi->isTurn ) { - buf[0] = 'T'; - } - if ( dsi->selected ) { - buf[1] = 'S'; - } - if ( dsi->isRobot) { - buf[2] = 'r'; + if ( 2 <= rect->height ) { + sprintf( out, "%s", dsi->name ); + *lines++ = out; + out += 1 + strlen(out); } - /* Score always goes at end. Will overwrite status if width is really small */ - snprintf( tmp, scoreWidth, "%.3d", dsi->totalScore ); - memcpy( &buf[width-scoreWidth+1], tmp, scoreWidth-1 ); + /* Status/role chars at start/top, if there's room */ + if ( 3 <= rect->height ) { + out[0] = dsi->isTurn ? 'T': ' '; + out[1] = dsi->selected ? 'S' : ' '; + out[2] = dsi->isRobot ? 'r' : ' '; + out[3] = '\0'; + *lines++ = out; + out += 4; + } + sprintf( out, "%.3d", dsi->totalScore ); + *lines++ = out; + out += 1 + strlen(out); + +#if 0 /* Now we want to fit name, rem tiles, last score, and last move, if there's space. Allocate to each so they're in columns. */ - width -= 8; /* status chars plus space; score plus space */ if ( width > 0 ) { int pos = 4; @@ -243,20 +238,28 @@ formatScoreText( XP_UCHAR* out, int outLen, const DrawScoreInfo* dsi, } snprintf( out, outLen, "%s", buf ); +#endif } /* formatScoreText */ static void curses_draw_measureScoreText( DrawCtx* XP_UNUSED(p_dctx), - const XP_Rect* r, + const XP_Rect* rect, const DrawScoreInfo* dsi, XP_U16* width, XP_U16* height ) { XP_UCHAR buf[100]; - formatScoreText( buf, sizeof(buf), dsi, r->width ); + char* lines[3] = {0}; + formatScoreText( buf, dsi, rect, lines ); - *width = strlen( buf ); - XP_ASSERT( *width <= r->width ); - *height = 1; /* one line per player */ + int ii; + int max = 0; + for ( ii = 0; ii < VSIZE(lines) && !!lines[ii]; ++ii ) { + max = XP_MAX( max, strlen( lines[ii] ) ); + } + XP_ASSERT( ii <= rect->height ); + *height = ii; + *width = max; + XP_ASSERT( *width <= rect->width ); } /* curses_draw_measureScoreText */ static void @@ -271,8 +274,12 @@ curses_draw_score_drawPlayer( DrawCtx* p_dctx, const XP_Rect* rInner, curses_draw_clearRect( p_dctx, rOuter ); /* print the name and turn/remoteness indicator */ - formatScoreText( buf, sizeof(buf), dsi, rInner->width ); - mvwprintw( dctx->boardWin, y, rOuter->left, buf ); + char* lines[3] = {0}; + formatScoreText( buf, dsi, rInner, lines ); + int ii; + for ( ii = 0; ii < VSIZE(lines) && !!lines[ii]; ++ii ) { + mvwprintw( dctx->boardWin, ii + y, rOuter->left, lines[ii] ); + } if ( (dsi->flags&CELL_ISCURSOR) != 0 ) { cursesHiliteRect( dctx->boardWin, rOuter ); @@ -329,6 +336,10 @@ curses_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect, XP_MEMCPY( loc, letter, strlen(letter) ); } + if ( highlight ) { + wstandout( dctx->boardWin ); + } + /* in case it's not 1x1 */ eraseRect( dctx, rect ); @@ -347,12 +358,7 @@ curses_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect, } /* switch */ } - if ( highlight ) { - wstandout( dctx->boardWin ); - } - - mvwaddnstr( dctx->boardWin, rect->top, rect->left, - loc, rect->width ); + mvwaddnstr( dctx->boardWin, rect->top, rect->left, loc, rect->width ); if ( highlight ) { wstandend( dctx->boardWin ); @@ -457,12 +463,16 @@ curses_draw_drawTileBack( DrawCtx* p_dctx, const XP_Rect* rect, static void curses_draw_drawTrayDivider( DrawCtx* p_dctx, const XP_Rect* rect, - CellFlags XP_UNUSED(flags) ) + CellFlags flags ) { CursesDrawCtx* dctx = (CursesDrawCtx*)p_dctx; - wmove( dctx->boardWin, rect->top, rect->left ); - wvline( dctx->boardWin, '#', rect->height ); + eraseRect( dctx, rect ); + wmove( dctx->boardWin, rect->top, rect->left + (rect->width/2)); + wvline( dctx->boardWin, '#', rect->height ); + if ( 0 != (flags & CELL_ISCURSOR) ) { + cursesHiliteRect( dctx->boardWin, rect ); + } } /* curses_draw_drawTrayDivider */ static void diff --git a/xwords4/linux/cursesmain.c b/xwords4/linux/cursesmain.c index d4b2613d0..3f59d30ac 100644 --- a/xwords4/linux/cursesmain.c +++ b/xwords4/linux/cursesmain.c @@ -228,7 +228,8 @@ cursesUserError( CursesAppGlobals* globals, const char* format, ... ) vsprintf( buf, format, ap ); - (void)cursesask( globals, buf, 1, "OK" ); + const char* buttons[] = {"OK"}; + (void)cursesask( globals, buf, VSIZE(buttons), buttons ); va_end(ap); } /* cursesUserError */ @@ -287,7 +288,7 @@ curses_util_userQuery( XW_UtilCtxt* uc, UtilQueryID id, XWStreamCtxt* stream ) { CursesAppGlobals* globals; char* question; - char* answers[3] = {NULL}; + const char* answers[3] = {NULL}; short numAnswers = 0; XP_Bool freeMe = XP_FALSE; XP_Bool result; @@ -312,8 +313,7 @@ curses_util_userQuery( XW_UtilCtxt* uc, UtilQueryID id, XWStreamCtxt* stream ) return 0; } globals = (CursesAppGlobals*)uc->closure; - result = cursesask( globals, question, numAnswers, - answers[0], answers[1], answers[2] ) == okIndex; + result = okIndex == cursesask( globals, question, numAnswers, answers ); if ( freeMe ) { free( question ); @@ -329,7 +329,8 @@ curses_util_confirmTrade( XW_UtilCtxt* uc, const XP_UCHAR** tiles, CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure; char question[256]; formatConfirmTrade( tiles, nTiles, question, sizeof(question) ); - return 1 == cursesask( globals, question, 2, "Cancel", "Ok" ); + const char* buttons[] = { "Cancel", "Ok" }; + return 1 == cursesask( globals, question, VSIZE(buttons), buttons ); } static void @@ -353,7 +354,8 @@ cursesShowFinalScores( CursesAppGlobals* globals ) text = strFromStream( stream ); - (void)cursesask( globals, text, 1, "Ok" ); + const char* buttons[] = { "Ok" }; + (void)cursesask( globals, text, VSIZE(buttons), buttons ); free( text ); stream_destroy( stream ); @@ -365,7 +367,8 @@ curses_util_informMove( XW_UtilCtxt* uc, XWStreamCtxt* expl, { CursesAppGlobals* globals = (CursesAppGlobals*)uc->closure; char* question = strFromStream( expl ); - (void)cursesask( globals, question, 1, "Ok" ); + const char* buttons[] = { "Ok" }; + (void)cursesask( globals, question, VSIZE(buttons), buttons ); free( question ); } @@ -1524,7 +1527,8 @@ curses_util_remSelected( XW_UtilCtxt* uc ) text = strFromStream( stream ); - (void)cursesask( globals, text, 1, "Ok" ); + const char* buttons[] = { "Ok" }; + (void)cursesask( globals, text, VSIZE(buttons), buttons ); free( text ); } @@ -1636,10 +1640,18 @@ passKeyToBoard( CursesAppGlobals* globals, char ch ) static void positionSizeStuff( CursesAppGlobals* globals, int width, int height ) { - BoardCtxt* board = globals->cGlobals.game.board; + CommonGlobals* cGlobals = &globals->cGlobals; + BoardCtxt* board = cGlobals->game.board; #ifdef COMMON_LAYOUT - XP_USE( width ); - XP_USE( height ); + + BoardDims dims; + board_figureLayout( board, cGlobals->gi, + 0, 0, width, height, + 150, 200, /* percents */ + width*100/75, 2, 1, + XP_FALSE, &dims ); + board_applyLayout( board, &dims ); + #else XP_U16 cellWidth, cellHt, scoreLeft, scoreWidth; int remWidth = width; @@ -1852,7 +1864,8 @@ cursesErrorMsgRcvd( void* closure, const XP_UCHAR* msg ) } else { g_free( globals->lastErr ); globals->lastErr = g_strdup( msg ); - (void)cursesask( globals, msg, 1, "Ok" ); + const char* buttons[] = { "Ok" }; + (void)cursesask( globals, msg, VSIZE(buttons), buttons ); } } diff --git a/xwords4/relay/cref.cpp b/xwords4/relay/cref.cpp index 892ddda73..f215e8f18 100644 --- a/xwords4/relay/cref.cpp +++ b/xwords4/relay/cref.cpp @@ -903,7 +903,7 @@ CookieRef::send_stored_messages( HostID dest, const AddrInfo* addr ) break; } if ( !UDPAckTrack::setOnAck( onMsgAcked, packetID, - (void*)msg.msgID() ) ) { + (void*)(uintptr_t)msg.msgID() ) ) { sentIDs.push_back( msg.msgID() ); } } diff --git a/xwords4/relay/ctrl.cpp b/xwords4/relay/ctrl.cpp index ee57b683a..dbb8397c0 100644 --- a/xwords4/relay/ctrl.cpp +++ b/xwords4/relay/ctrl.cpp @@ -547,7 +547,7 @@ cmd_print( int socket, const char* cmd, int argc, gchar** argv ) static void onAckProc( bool acked, DevIDRelay devid, uint32_t packetID, void* data ) { - int socket = (int)data; + int socket = (int)(uintptr_t)data; if ( acked ) { print_to_sock( socket, true, "got ack for packet %d from dev %d", packetID, devid ); @@ -660,7 +660,7 @@ cmd_devs( int socket, const char* cmd, int argc, gchar** argv ) DevIDRelay devid = *iter; if ( 0 != devid ) { if ( post_message( devid, unesc, onAckProc, - (void*)socket ) ) { + (void*)(uintptr_t)socket ) ) { result.catf( "posted message: %s\n", unesc ); } else { result.catf( "unable to post; does dev %d exist\n", @@ -744,7 +744,7 @@ static void* ctrl_thread_main( void* arg ) { blockSignals(); - int sock = (int)arg; + int sock = (int)(uintptr_t)arg; { MutexLock ml( &g_ctrlSocksMutex ); @@ -819,7 +819,7 @@ run_ctrl_thread( int ctrl_sock ) pthread_t thread; int result = pthread_create( &thread, NULL, - ctrl_thread_main, (void*)newSock ); + ctrl_thread_main, (void*)(uintptr_t)newSock ); pthread_detach( thread ); assert( result == 0 ); diff --git a/xwords4/relay/xwrelay.cpp b/xwords4/relay/xwrelay.cpp index dafb20eeb..1c402b821 100644 --- a/xwords4/relay/xwrelay.cpp +++ b/xwords4/relay/xwrelay.cpp @@ -1550,7 +1550,7 @@ onMsgAcked( bool acked, uint32_t packetID, void* data ) logf( XW_LOGINFO, "%s(packetID=%d, acked=%s)", __func__, packetID, acked?"true":"false" ); if ( acked ) { - int msgID = (int)data; + int msgID = (int)(uintptr_t)data; DBMgr::Get()->RemoveStoredMessage( msgID ); } } @@ -1587,7 +1587,8 @@ retrieveMessages( DevID& devID, const AddrInfo* addr ) __func__, devID.asRelayID() ); break; } - UDPAckTrack::setOnAck( onMsgAcked, packetID, (void*)msg.msgID() ); + UDPAckTrack::setOnAck( onMsgAcked, packetID, + (void*)(uintptr_t)msg.msgID() ); } }