mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-17 09:34:08 +01:00
merge with drag_n_drop branch: apply patch generated with this command on that branch: svn diff -r 2080:2087
This commit is contained in:
parent
4c730be669
commit
0b1f4b8f0a
9 changed files with 605 additions and 485 deletions
|
@ -62,6 +62,7 @@
|
||||||
#include "LocalizedStrIncludes.h"
|
#include "LocalizedStrIncludes.h"
|
||||||
|
|
||||||
#include "boardp.h"
|
#include "boardp.h"
|
||||||
|
#include "dragdrpp.h"
|
||||||
#include "dbgutil.h"
|
#include "dbgutil.h"
|
||||||
|
|
||||||
#define bEND 0x62454e44
|
#define bEND 0x62454e44
|
||||||
|
@ -73,8 +74,6 @@ extern "C" {
|
||||||
/****************************** prototypes ******************************/
|
/****************************** prototypes ******************************/
|
||||||
static XP_Bool getCellRect( BoardCtxt* board, XP_U16 col, XP_U16 row,
|
static XP_Bool getCellRect( BoardCtxt* board, XP_U16 col, XP_U16 row,
|
||||||
XP_Rect* rect);
|
XP_Rect* rect);
|
||||||
static XP_Bool coordToCell( BoardCtxt* board, XP_U16 x, XP_U16 y,
|
|
||||||
XP_U16* colP, XP_U16* rowP );
|
|
||||||
static XP_Bool drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row,
|
static XP_Bool drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row,
|
||||||
XP_Bool skipBlanks );
|
XP_Bool skipBlanks );
|
||||||
static void figureBoardRect( BoardCtxt* board );
|
static void figureBoardRect( BoardCtxt* board );
|
||||||
|
@ -82,13 +81,11 @@ static void figureBoardRect( BoardCtxt* board );
|
||||||
static void drawBoard( BoardCtxt* board );
|
static void drawBoard( BoardCtxt* board );
|
||||||
static void invalCell( BoardCtxt* board, XP_U16 col, XP_U16 row );
|
static void invalCell( BoardCtxt* board, XP_U16 col, XP_U16 row );
|
||||||
static void invalCellsUnderRect( BoardCtxt* board, XP_Rect* rect );
|
static void invalCellsUnderRect( BoardCtxt* board, XP_Rect* rect );
|
||||||
|
|
||||||
static XP_Bool moveTileToBoard( BoardCtxt* board, XP_U16 col, XP_U16 row,
|
|
||||||
XP_U16 tileIndex, Tile blankFace );
|
|
||||||
static XP_Bool rectContainsRect( XP_Rect* rect1, XP_Rect* rect2 );
|
static XP_Bool rectContainsRect( XP_Rect* rect1, XP_Rect* rect2 );
|
||||||
static void boardCellChanged( void* board, XP_U16 turn, XP_U16 col,
|
static void boardCellChanged( void* board, XP_U16 turn, XP_U16 col,
|
||||||
XP_U16 row, XP_Bool added );
|
XP_U16 row, XP_Bool added );
|
||||||
static void boardTileChanged( void* board, XP_U16 turn, TileBit bits );
|
static void boardTilesChanged( void* board, XP_U16 turn, XP_S16 index1,
|
||||||
|
XP_S16 index2 );
|
||||||
static void boardTurnChanged( void* board );
|
static void boardTurnChanged( void* board );
|
||||||
static void boardGameOver( void* board );
|
static void boardGameOver( void* board );
|
||||||
static void setArrow( BoardCtxt* board, XP_U16 row, XP_U16 col );
|
static void setArrow( BoardCtxt* board, XP_U16 row, XP_U16 col );
|
||||||
|
@ -96,8 +93,6 @@ static void setArrowFor( BoardCtxt* board, XP_U16 player, XP_U16 col,
|
||||||
XP_U16 row );
|
XP_U16 row );
|
||||||
static XP_Bool setArrowVisible( BoardCtxt* board, XP_Bool visible );
|
static XP_Bool setArrowVisible( BoardCtxt* board, XP_Bool visible );
|
||||||
|
|
||||||
static XP_Bool cellOccupied( BoardCtxt* board, XP_U16 col, XP_U16 row,
|
|
||||||
XP_Bool inclPending );
|
|
||||||
static void makeMiniWindowForTrade( BoardCtxt* board );
|
static void makeMiniWindowForTrade( BoardCtxt* board );
|
||||||
static void makeMiniWindowForText( BoardCtxt* board, const XP_UCHAR* text,
|
static void makeMiniWindowForText( BoardCtxt* board, const XP_UCHAR* text,
|
||||||
MiniWindowType winType );
|
MiniWindowType winType );
|
||||||
|
@ -115,8 +110,11 @@ static XP_Bool getArrow( BoardCtxt* board, XP_U16* col, XP_U16* row );
|
||||||
static XP_Bool setArrowVisibleFor( BoardCtxt* board, XP_U16 player,
|
static XP_Bool setArrowVisibleFor( BoardCtxt* board, XP_U16 player,
|
||||||
XP_Bool visible );
|
XP_Bool visible );
|
||||||
static XP_Bool board_moveArrow( BoardCtxt* board, XP_Key cursorKey );
|
static XP_Bool board_moveArrow( BoardCtxt* board, XP_Key cursorKey );
|
||||||
static void flipIf( const BoardCtxt* board, XP_U16 col, XP_U16 row,
|
#ifdef POINTER_SUPPORT
|
||||||
XP_U16* fCol, XP_U16* fRow );
|
static void drawDragTileIf( BoardCtxt* board );
|
||||||
|
#endif
|
||||||
|
static XP_Bool holdsPendingTile( BoardCtxt* board,
|
||||||
|
XP_U16 pencol, XP_U16 penrow );
|
||||||
|
|
||||||
#ifdef KEY_SUPPORT
|
#ifdef KEY_SUPPORT
|
||||||
static XP_Bool moveKeyTileToBoard( BoardCtxt* board, XP_Key cursorKey,
|
static XP_Bool moveKeyTileToBoard( BoardCtxt* board, XP_Key cursorKey,
|
||||||
|
@ -170,7 +168,7 @@ board_make( MPFORMAL ModelCtxt* model, ServerCtxt* server, DrawCtx* draw,
|
||||||
|
|
||||||
/* could just pass in invalCell.... PENDING(eeh) */
|
/* could just pass in invalCell.... PENDING(eeh) */
|
||||||
model_setBoardListener( model, boardCellChanged, result );
|
model_setBoardListener( model, boardCellChanged, result );
|
||||||
model_setTrayListener( model, boardTileChanged, result );
|
model_setTrayListener( model, boardTilesChanged, result );
|
||||||
server_setTurnChangeListener( server, boardTurnChanged, result );
|
server_setTurnChangeListener( server, boardTurnChanged, result );
|
||||||
server_setGameOverListener( server, boardGameOver, result );
|
server_setGameOverListener( server, boardGameOver, result );
|
||||||
|
|
||||||
|
@ -739,7 +737,7 @@ timerFiredForPen( BoardCtxt* board )
|
||||||
const XP_UCHAR* text = (XP_UCHAR*)NULL;
|
const XP_UCHAR* text = (XP_UCHAR*)NULL;
|
||||||
XP_UCHAR buf[80];
|
XP_UCHAR buf[80];
|
||||||
|
|
||||||
if ( board->penDownObject == OBJ_BOARD
|
if ( (board->penDownObject == OBJ_BOARD) && !dragDropInProgress(board)
|
||||||
#ifdef XWFEATURE_SEARCHLIMIT
|
#ifdef XWFEATURE_SEARCHLIMIT
|
||||||
&& !board->hintDragInProgress
|
&& !board->hintDragInProgress
|
||||||
#endif
|
#endif
|
||||||
|
@ -958,7 +956,7 @@ board_invalAll( BoardCtxt* board )
|
||||||
board->scoreBoardInvalid = XP_TRUE;
|
board->scoreBoardInvalid = XP_TRUE;
|
||||||
} /* board_invalAll */
|
} /* board_invalAll */
|
||||||
|
|
||||||
static void
|
void
|
||||||
flipIf( const BoardCtxt* board, XP_U16 col, XP_U16 row,
|
flipIf( const BoardCtxt* board, XP_U16 col, XP_U16 row,
|
||||||
XP_U16* fCol, XP_U16* fRow )
|
XP_U16* fCol, XP_U16* fRow )
|
||||||
{
|
{
|
||||||
|
@ -1261,8 +1259,11 @@ drawBoard( BoardCtxt* board )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* I doubt the two of these can happen at the same time */
|
||||||
drawTradeWindowIf( board );
|
drawTradeWindowIf( board );
|
||||||
|
#ifdef POINTER_SUPPORT
|
||||||
|
drawDragTileIf( board );
|
||||||
|
#endif
|
||||||
draw_objFinished( board->draw, OBJ_BOARD, &board->boardBounds,
|
draw_objFinished( board->draw, OBJ_BOARD, &board->boardBounds,
|
||||||
dfsFor( board, OBJ_BOARD ) );
|
dfsFor( board, OBJ_BOARD ) );
|
||||||
|
|
||||||
|
@ -1747,10 +1748,20 @@ drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool skipBlanks )
|
||||||
XP_UCHAR* textP = (XP_UCHAR*)ch;
|
XP_UCHAR* textP = (XP_UCHAR*)ch;
|
||||||
HintAtts hintAtts;
|
HintAtts hintAtts;
|
||||||
CellFlags flags = CELL_NONE;
|
CellFlags flags = CELL_NONE;
|
||||||
|
XP_Bool isOrigin;
|
||||||
|
|
||||||
isEmpty = !model_getTile( model, modelCol, modelRow, showPending,
|
isEmpty = !model_getTile( model, modelCol, modelRow, showPending,
|
||||||
selPlayer, &tile, &isBlank,
|
selPlayer, &tile, &isBlank,
|
||||||
&pending, &recent );
|
&pending, &recent );
|
||||||
|
if ( dragDropIsBeingDragged( board, col, row, &isOrigin ) ) {
|
||||||
|
flags |= isOrigin? CELL_DRAGSRC : CELL_DRAGCUR;
|
||||||
|
if ( isEmpty && !isOrigin ) {
|
||||||
|
dragDropTileInfo( board, &tile, &isBlank );
|
||||||
|
pending = XP_TRUE;
|
||||||
|
recent = XP_FALSE;
|
||||||
|
isEmpty = XP_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( isEmpty ) {
|
if ( isEmpty ) {
|
||||||
isBlank = XP_FALSE;
|
isBlank = XP_FALSE;
|
||||||
|
@ -1779,8 +1790,7 @@ drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool skipBlanks )
|
||||||
bonus = util_getSquareBonus( board->util, model, col, row );
|
bonus = util_getSquareBonus( board->util, model, col, row );
|
||||||
hintAtts = figureHintAtts( board, col, row );
|
hintAtts = figureHintAtts( board, col, row );
|
||||||
|
|
||||||
if ( isEmpty && (col==board->star_row)
|
if ( (col==board->star_row) && (row==board->star_row) ) {
|
||||||
&& (row==board->star_row ) ) {
|
|
||||||
flags |= CELL_ISSTAR;
|
flags |= CELL_ISSTAR;
|
||||||
}
|
}
|
||||||
if ( invert ) {
|
if ( invert ) {
|
||||||
|
@ -1835,7 +1845,7 @@ figureBoardRect( BoardCtxt* board )
|
||||||
}
|
}
|
||||||
} /* figureBoardRect */
|
} /* figureBoardRect */
|
||||||
|
|
||||||
static XP_Bool
|
XP_Bool
|
||||||
coordToCell( BoardCtxt* board, XP_U16 x, XP_U16 y, XP_U16* colP, XP_U16* rowP )
|
coordToCell( BoardCtxt* board, XP_U16 x, XP_U16 y, XP_U16* colP, XP_U16* rowP )
|
||||||
{
|
{
|
||||||
XP_U16 col, row, max;
|
XP_U16 col, row, max;
|
||||||
|
@ -1913,7 +1923,7 @@ invalCell( BoardCtxt* board, XP_U16 col, XP_U16 row )
|
||||||
} /* invalCell */
|
} /* invalCell */
|
||||||
|
|
||||||
#if defined POINTER_SUPPORT || defined KEYBOARD_NAV
|
#if defined POINTER_SUPPORT || defined KEYBOARD_NAV
|
||||||
static XP_Bool
|
XP_Bool
|
||||||
pointOnSomething( BoardCtxt* board, XP_U16 x, XP_U16 y, BoardObjectType* wp )
|
pointOnSomething( BoardCtxt* board, XP_U16 x, XP_U16 y, BoardObjectType* wp )
|
||||||
{
|
{
|
||||||
XP_Bool result = XP_TRUE;
|
XP_Bool result = XP_TRUE;
|
||||||
|
@ -2231,14 +2241,25 @@ static XP_Bool
|
||||||
handlePenDownOnBoard( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
handlePenDownOnBoard( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
||||||
{
|
{
|
||||||
XP_Bool result = XP_FALSE;
|
XP_Bool result = XP_FALSE;
|
||||||
|
XP_U16 col, row;
|
||||||
/* Start a timer no matter what. After it fires we'll decide whether it's
|
/* Start a timer no matter what. After it fires we'll decide whether it's
|
||||||
appropriate to handle it. No. That's too expensive */
|
appropriate to handle it. No. That's too expensive */
|
||||||
if ( TRADE_IN_PROGRESS(board) && ptOnTradeWindow( board, x, y ) ) {
|
if ( TRADE_IN_PROGRESS(board) && ptOnTradeWindow( board, x, y ) ) {
|
||||||
return XP_FALSE;
|
return XP_FALSE;
|
||||||
}
|
}
|
||||||
util_setTimer( board->util, TIMER_PENDOWN, 0, p_board_timerFired, board );
|
util_setTimer( board->util, TIMER_PENDOWN, 0, p_board_timerFired, board );
|
||||||
|
|
||||||
|
/* As a first cut, you start a hint-region drag unless the cell is
|
||||||
|
occupied by a non-committed cell. */
|
||||||
|
|
||||||
|
coordToCell( board, x, y, &col, &row );
|
||||||
|
if ( (board->trayVisState == TRAY_REVEALED)
|
||||||
|
&& !board->tradeInProgress[board->selPlayer]
|
||||||
|
&& holdsPendingTile( board, col, row ) ) {
|
||||||
|
result = dragDropStart( board, OBJ_BOARD, col, row );
|
||||||
#ifdef XWFEATURE_SEARCHLIMIT
|
#ifdef XWFEATURE_SEARCHLIMIT
|
||||||
if ( board->gi->allowHintRect && board->trayVisState == TRAY_REVEALED ) {
|
} else if ( board->gi->allowHintRect
|
||||||
|
&& (board->trayVisState == TRAY_REVEALED) ) {
|
||||||
result = startHintRegionDrag( board, x, y );
|
result = startHintRegionDrag( board, x, y );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2329,8 +2350,9 @@ handleLikeDown( BoardCtxt* board, BoardObjectType onWhich, XP_U16 x, XP_U16 y )
|
||||||
case OBJ_TRAY:
|
case OBJ_TRAY:
|
||||||
XP_ASSERT( board->trayVisState != TRAY_HIDDEN );
|
XP_ASSERT( board->trayVisState != TRAY_HIDDEN );
|
||||||
|
|
||||||
if ( board->trayVisState != TRAY_REVERSED ) {
|
if ( board->trayVisState != TRAY_REVERSED
|
||||||
result = handlePenDownInTray( board, x, y ) || result;
|
&& !board->tradeInProgress[board->selPlayer] ) {
|
||||||
|
result = dragDropStart( board, OBJ_TRAY, x, y ) || result;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2385,10 +2407,8 @@ board_handlePenMove( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
||||||
{
|
{
|
||||||
XP_Bool result = XP_FALSE;
|
XP_Bool result = XP_FALSE;
|
||||||
|
|
||||||
if ( board->tileDragState.dragInProgress ) {
|
if ( dragDropInProgress(board) ) {
|
||||||
result = continueTileDrag( board, x, y ) != 0;
|
result = dragDropContinue( board, x, y ) != 0;
|
||||||
} else if ( board->divDragState.dragInProgress ) {
|
|
||||||
result = continueDividerDrag( board, x, y ) != 0;
|
|
||||||
#ifdef XWFEATURE_SEARCHLIMIT
|
#ifdef XWFEATURE_SEARCHLIMIT
|
||||||
} else if ( board->gi->allowHintRect
|
} else if ( board->gi->allowHintRect
|
||||||
&& board->trayVisState == TRAY_REVEALED ) {
|
&& board->trayVisState == TRAY_REVEALED ) {
|
||||||
|
@ -2434,7 +2454,7 @@ moveSelTileToBoardXY( BoardCtxt* board, XP_U16 col, XP_U16 row )
|
||||||
return result;
|
return result;
|
||||||
} /* moveSelTileToBoardXY */
|
} /* moveSelTileToBoardXY */
|
||||||
|
|
||||||
static XP_Bool
|
XP_Bool
|
||||||
cellOccupied( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool inclPending )
|
cellOccupied( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Bool inclPending )
|
||||||
{
|
{
|
||||||
Tile tile;
|
Tile tile;
|
||||||
|
@ -2486,41 +2506,37 @@ tryMoveArrow( BoardCtxt* board, XP_U16 col, XP_U16 row )
|
||||||
return result;
|
return result;
|
||||||
} /* tryMoveArrow */
|
} /* tryMoveArrow */
|
||||||
|
|
||||||
/* Did I tap on a tile on the board that I have not yet committed? If so,
|
|
||||||
* return it to the tray.
|
|
||||||
*/
|
|
||||||
static XP_Bool
|
static XP_Bool
|
||||||
tryReplaceTile( BoardCtxt* board, XP_U16 pencol, XP_U16 penrow )
|
holdsPendingTile( BoardCtxt* board, XP_U16 pencol, XP_U16 penrow )
|
||||||
{
|
{
|
||||||
XP_Bool result = XP_FALSE;
|
|
||||||
XP_S16 index;
|
|
||||||
XP_U16 col, row;
|
|
||||||
Tile tile;
|
Tile tile;
|
||||||
XP_Bool ignore, isPending;
|
XP_Bool ignore, isPending;
|
||||||
XP_U16 modcol, modrow;
|
XP_U16 modcol, modrow;
|
||||||
|
|
||||||
flipIf( board, pencol, penrow, &modcol, &modrow );
|
flipIf( board, pencol, penrow, &modcol, &modrow );
|
||||||
if ( model_getTile( board->model, modcol, modrow, XP_TRUE,
|
|
||||||
board->selPlayer, &tile, &ignore, &isPending,
|
|
||||||
(XP_Bool*)NULL )
|
|
||||||
&& isPending ) {
|
|
||||||
|
|
||||||
XP_S16 count = model_getCurrentMoveCount( board->model,
|
return model_getTile( board->model, modcol, modrow, XP_TRUE,
|
||||||
board->selPlayer );
|
board->selPlayer, &tile, &ignore, &isPending,
|
||||||
while ( count-- ) {
|
(XP_Bool*)NULL )
|
||||||
index = count;
|
&& isPending;
|
||||||
model_getCurrentMoveTile( board->model, board->selPlayer,
|
} /* holdsPendingTile */
|
||||||
&index, &tile, &col, &row, &ignore );
|
|
||||||
if ( col == modcol && row == modrow ) {
|
/* Did I tap on a tile on the board that I have not yet committed? If so,
|
||||||
model_moveBoardToTray( board->model, board->selPlayer,
|
* return it to the tray.
|
||||||
index );
|
*/
|
||||||
/* the cursor should show up where the tile used to be so it's
|
XP_Bool
|
||||||
easy to replace it. */
|
tryReplaceTile( BoardCtxt* board, XP_U16 pencol, XP_U16 penrow )
|
||||||
setArrow( board, pencol, penrow );
|
{
|
||||||
result = XP_TRUE;
|
XP_Bool result = XP_FALSE;
|
||||||
break;
|
|
||||||
}
|
if ( holdsPendingTile( board, pencol, penrow ) ) {
|
||||||
}
|
XP_U16 modcol, modrow;
|
||||||
|
flipIf( board, pencol, penrow, &modcol, &modrow );
|
||||||
|
|
||||||
|
model_moveBoardToTray( board->model, board->selPlayer,
|
||||||
|
modcol, modrow, -1 );
|
||||||
|
setArrow( board, pencol, penrow );
|
||||||
|
result = XP_TRUE;
|
||||||
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} /* tryReplaceTile */
|
} /* tryReplaceTile */
|
||||||
|
@ -2549,7 +2565,8 @@ exitTradeMode( BoardCtxt* board )
|
||||||
XP_Bool
|
XP_Bool
|
||||||
board_handlePenUp( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
board_handlePenUp( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
||||||
{
|
{
|
||||||
XP_Bool result = XP_FALSE;
|
XP_Bool draw = XP_FALSE;
|
||||||
|
XP_Bool dragged = XP_FALSE;
|
||||||
BoardObjectType prevObj = board->penDownObject;
|
BoardObjectType prevObj = board->penDownObject;
|
||||||
|
|
||||||
/* prevent timer from firing after pen lifted. Set now rather than later
|
/* prevent timer from firing after pen lifted. Set now rather than later
|
||||||
|
@ -2557,19 +2574,19 @@ board_handlePenUp( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
||||||
exiting this function (which might give timer time to fire. */
|
exiting this function (which might give timer time to fire. */
|
||||||
board->penDownObject = OBJ_NONE;
|
board->penDownObject = OBJ_NONE;
|
||||||
|
|
||||||
if ( board->tileDragState.dragInProgress ) {
|
if ( dragDropInProgress(board) ) {
|
||||||
result = endTileDrag( board, x, y );
|
draw = dragDropEnd( board, x, y, &dragged );
|
||||||
} else if ( board->divDragState.dragInProgress ) {
|
}
|
||||||
result = endDividerDrag( board, x, y );
|
if ( dragged ) {
|
||||||
#ifdef XWFEATURE_SEARCHLIMIT
|
#ifdef XWFEATURE_SEARCHLIMIT
|
||||||
} else if ( board->hintDragInProgress ) {
|
} else if ( board->hintDragInProgress ) {
|
||||||
XP_ASSERT( board->gi->allowHintRect );
|
XP_ASSERT( board->gi->allowHintRect );
|
||||||
result = finishHintRegionDrag( board, x, y );
|
draw = finishHintRegionDrag( board, x, y ) || draw;
|
||||||
#endif
|
#endif
|
||||||
} else if ( board->penTimerFired ) {
|
} else if ( board->penTimerFired ) {
|
||||||
if ( valHintMiniWindowActive( board ) ) {
|
if ( valHintMiniWindowActive( board ) ) {
|
||||||
hideMiniWindow( board, XP_TRUE, MINIWINDOW_VALHINT );
|
hideMiniWindow( board, XP_TRUE, MINIWINDOW_VALHINT );
|
||||||
result = XP_TRUE;
|
draw = XP_TRUE;
|
||||||
}
|
}
|
||||||
/* Need to clean up if there's been any dragging happening */
|
/* Need to clean up if there's been any dragging happening */
|
||||||
board->penTimerFired = XP_FALSE;
|
board->penTimerFired = XP_FALSE;
|
||||||
|
@ -2580,7 +2597,7 @@ board_handlePenUp( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
||||||
switch( onWhich ) {
|
switch( onWhich ) {
|
||||||
case OBJ_SCORE:
|
case OBJ_SCORE:
|
||||||
if ( prevObj == OBJ_SCORE ) {
|
if ( prevObj == OBJ_SCORE ) {
|
||||||
result = handlePenUpScore( board, x, y );
|
draw = handlePenUpScore( board, x, y ) || draw;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJ_BOARD:
|
case OBJ_BOARD:
|
||||||
|
@ -2589,21 +2606,21 @@ board_handlePenUp( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
||||||
|
|
||||||
if ( TRADE_IN_PROGRESS(board) ) {
|
if ( TRADE_IN_PROGRESS(board) ) {
|
||||||
if ( ptOnTradeWindow( board, x, y )) {
|
if ( ptOnTradeWindow( board, x, y )) {
|
||||||
result = exitTradeMode( board );
|
draw = exitTradeMode( board ) || draw;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
XP_U16 col, row;
|
XP_U16 col, row;
|
||||||
coordToCell( board, board->penDownX, board->penDownY,
|
coordToCell( board, board->penDownX, board->penDownY,
|
||||||
&col, &row );
|
&col, &row );
|
||||||
result = handleActionInCell( board, col, row );
|
draw = handleActionInCell( board, col, row ) || draw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJ_TRAY:
|
case OBJ_TRAY:
|
||||||
if ( board->trayVisState == TRAY_REVERSED ) {
|
if ( board->trayVisState == TRAY_REVERSED ) {
|
||||||
result = askRevealTray( board );
|
draw = askRevealTray( board ) || draw;
|
||||||
} else {
|
} else {
|
||||||
result = handlePenUpTray( board, x, y );
|
draw = handlePenUpTray( board, x, y ) || draw;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -2615,7 +2632,7 @@ board_handlePenUp( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
||||||
#ifdef XWFEATURE_SEARCHLIMIT
|
#ifdef XWFEATURE_SEARCHLIMIT
|
||||||
board->hintDragInProgress = XP_FALSE;
|
board->hintDragInProgress = XP_FALSE;
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return draw;
|
||||||
} /* board_handlePenUp */
|
} /* board_handlePenUp */
|
||||||
#endif /* #ifdef POINTER_SUPPORT */
|
#endif /* #ifdef POINTER_SUPPORT */
|
||||||
|
|
||||||
|
@ -2914,8 +2931,6 @@ board_focusChanged( BoardCtxt* board, BoardObjectType typ, XP_Bool gained )
|
||||||
draw = invalFocusOwner( board ) || draw;
|
draw = invalFocusOwner( board ) || draw;
|
||||||
}
|
}
|
||||||
board->focussed = typ;
|
board->focussed = typ;
|
||||||
XP_LOGF( "%s: set focussed to %s", __func__,
|
|
||||||
BoardObjectType_2str(typ) );
|
|
||||||
board->focusHasDived = XP_FALSE;
|
board->focusHasDived = XP_FALSE;
|
||||||
draw = invalFocusOwner( board ) || draw;
|
draw = invalFocusOwner( board ) || draw;
|
||||||
} else {
|
} else {
|
||||||
|
@ -3148,8 +3163,7 @@ replaceLastTile( BoardCtxt* board )
|
||||||
index = -1;
|
index = -1;
|
||||||
model_getCurrentMoveTile( board->model, board->selPlayer, &index,
|
model_getCurrentMoveTile( board->model, board->selPlayer, &index,
|
||||||
&tile, &col, &row, &isBlank );
|
&tile, &col, &row, &isBlank );
|
||||||
|
model_moveBoardToTray( board->model, board->selPlayer, col, row, -1 );
|
||||||
model_moveBoardToTray( board->model, board->selPlayer, index );
|
|
||||||
|
|
||||||
flipIf( board, col, row, &col, &row );
|
flipIf( board, col, row, &col, &row );
|
||||||
setArrow( board, col, row );
|
setArrow( board, col, row );
|
||||||
|
@ -3160,9 +3174,9 @@ replaceLastTile( BoardCtxt* board )
|
||||||
return result;
|
return result;
|
||||||
} /* replaceLastTile */
|
} /* replaceLastTile */
|
||||||
|
|
||||||
static XP_Bool
|
XP_Bool
|
||||||
moveTileToBoard( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_U16 tileIndex,
|
moveTileToBoard( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_U16 tileIndex,
|
||||||
Tile blankFace )
|
Tile blankFace )
|
||||||
{
|
{
|
||||||
if ( cellOccupied( board, col, row, XP_TRUE ) ) {
|
if ( cellOccupied( board, col, row, XP_TRUE ) ) {
|
||||||
return XP_FALSE;
|
return XP_FALSE;
|
||||||
|
@ -3340,13 +3354,13 @@ boardCellChanged( void* p_board, XP_U16 turn, XP_U16 modelCol, XP_U16 modelRow,
|
||||||
} /* boardCellChanged */
|
} /* boardCellChanged */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
boardTileChanged( void* p_board, XP_U16 turn, TileBit bits )
|
boardTilesChanged( void* p_board, XP_U16 turn, XP_S16 index1, XP_S16 index2 )
|
||||||
{
|
{
|
||||||
BoardCtxt* board = (BoardCtxt*)p_board;
|
BoardCtxt* board = (BoardCtxt*)p_board;
|
||||||
if ( turn == board->selPlayer ) {
|
if ( turn == board->selPlayer ) {
|
||||||
board_invalTrayTiles( board, bits );
|
invalTrayTilesBetween( board, index1, index2 );
|
||||||
}
|
}
|
||||||
} /* boardTileChanged */
|
} /* boardTilesChanged */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
boardTurnChanged( void* p_board )
|
boardTurnChanged( void* p_board )
|
||||||
|
@ -3380,6 +3394,109 @@ boardGameOver( void* closure )
|
||||||
util_notifyGameOver( board->util );
|
util_notifyGameOver( board->util );
|
||||||
} /* boardGameOver */
|
} /* boardGameOver */
|
||||||
|
|
||||||
|
static void
|
||||||
|
forceRectToBoard( const BoardCtxt* board, XP_Rect* rect )
|
||||||
|
{
|
||||||
|
XP_Rect bounds = board->boardBounds;
|
||||||
|
if ( rect->left < bounds.left ) {
|
||||||
|
rect->left = bounds.left;
|
||||||
|
}
|
||||||
|
if ( rect->top < bounds.top ) {
|
||||||
|
rect->top = bounds.top;
|
||||||
|
}
|
||||||
|
if ( (rect->left + rect->width) > (bounds.left + bounds.width) ) {
|
||||||
|
rect->left -= (rect->left+rect->width) - (bounds.left+bounds.width);
|
||||||
|
}
|
||||||
|
if ( rect->top + rect->height > bounds.top + bounds.height ) {
|
||||||
|
rect->top -= (rect->top+rect->height) - (bounds.top+bounds.height);
|
||||||
|
}
|
||||||
|
} /* forceRectToBoard */
|
||||||
|
|
||||||
|
static void
|
||||||
|
getDragCellRect( BoardCtxt* board, XP_U16 col, XP_U16 row, XP_Rect* rectP )
|
||||||
|
{
|
||||||
|
XP_Rect rect;
|
||||||
|
XP_U16 tmp;
|
||||||
|
|
||||||
|
getCellRect( board, col, row, &rect );
|
||||||
|
|
||||||
|
tmp = rect.width;
|
||||||
|
rect.width = board->trayScaleH;
|
||||||
|
rect.left -= (rect.width - tmp) / 2;
|
||||||
|
|
||||||
|
tmp = rect.height;
|
||||||
|
rect.height = board->trayScaleV;
|
||||||
|
rect.top -= (rect.height - tmp) / 2;
|
||||||
|
|
||||||
|
*rectP = rect;
|
||||||
|
forceRectToBoard( board, rectP );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef POINTER_SUPPORT
|
||||||
|
static void
|
||||||
|
drawDragTileIf( BoardCtxt* board )
|
||||||
|
{
|
||||||
|
if ( dragDropInProgress( board ) ) {
|
||||||
|
XP_U16 col, row;
|
||||||
|
if ( dragDropGetBoardTile( board, &col, &row ) ) {
|
||||||
|
XP_Rect rect;
|
||||||
|
Tile tile;
|
||||||
|
XP_Bool isBlank;
|
||||||
|
XP_UCHAR buf[4];
|
||||||
|
XP_UCHAR* face;
|
||||||
|
XP_Bitmap bitmap = NULL;
|
||||||
|
XP_S16 value;
|
||||||
|
CellFlags flags;
|
||||||
|
|
||||||
|
getDragCellRect( board, col, row, &rect );
|
||||||
|
|
||||||
|
dragDropTileInfo( board, &tile, &isBlank );
|
||||||
|
|
||||||
|
face = getTileDrawInfo( board, tile, isBlank, &bitmap,
|
||||||
|
&value, buf, sizeof(buf) );
|
||||||
|
|
||||||
|
flags = CELL_DRAGCUR;
|
||||||
|
if ( isBlank ) {
|
||||||
|
flags |= CELL_ISBLANK;
|
||||||
|
}
|
||||||
|
draw_drawTileMidDrag( board->draw, &rect, face, bitmap, value,
|
||||||
|
flags );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* drawDragTileIf */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
invalDragObj( BoardCtxt* board, const DragObjInfo* di )
|
||||||
|
{
|
||||||
|
if ( OBJ_BOARD == di->obj ) {
|
||||||
|
XP_Rect rect;
|
||||||
|
getDragCellRect( board, di->u.board.col, di->u.board.row, &rect );
|
||||||
|
invalCellsUnderRect( board, &rect );
|
||||||
|
} else if ( OBJ_TRAY == di->obj ) {
|
||||||
|
board_invalTrayTiles( board, 1 << di->u.tray.index );
|
||||||
|
}
|
||||||
|
} /* invalCurObj */
|
||||||
|
|
||||||
|
void
|
||||||
|
invalDragObjRange( BoardCtxt* board, const DragObjInfo* from,
|
||||||
|
const DragObjInfo* to )
|
||||||
|
{
|
||||||
|
invalDragObj( board, from );
|
||||||
|
if ( NULL != to ) {
|
||||||
|
invalDragObj( board, to );
|
||||||
|
|
||||||
|
if ( (OBJ_TRAY == from->obj) && (OBJ_TRAY == to->obj) ) {
|
||||||
|
invalTrayTilesBetween( board, from->u.tray.index,
|
||||||
|
to->u.tray.index );
|
||||||
|
} else if ( OBJ_TRAY == from->obj ) {
|
||||||
|
invalTrayTilesAbove( board, from->u.tray.index );
|
||||||
|
} else if ( OBJ_TRAY == to->obj ) {
|
||||||
|
invalTrayTilesAbove( board, to->u.tray.index );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CPLUS
|
#ifdef CPLUS
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,18 +30,29 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct TileDragState {
|
typedef struct _DragObjInfo {
|
||||||
XP_Bool dragInProgress;
|
BoardObjectType obj;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
XP_U16 col;
|
||||||
|
XP_U16 row;
|
||||||
|
} board;
|
||||||
|
struct {
|
||||||
|
XP_U16 index;
|
||||||
|
} tray;
|
||||||
|
} u;
|
||||||
|
} DragObjInfo;
|
||||||
|
|
||||||
XP_Bool wasHilited;
|
typedef struct DragState {
|
||||||
TileBit selectionAtStart;
|
|
||||||
XP_Bool movePending;
|
|
||||||
TileBit prevIndex;
|
|
||||||
} TileDragState;
|
|
||||||
|
|
||||||
typedef struct DividerDragState {
|
|
||||||
XP_Bool dragInProgress;
|
XP_Bool dragInProgress;
|
||||||
} DividerDragState;
|
XP_Bool dividerOnly; /* special case; most other stuff ignored */
|
||||||
|
XP_Bool didMove; /* there was change during the drag; not a
|
||||||
|
tap */
|
||||||
|
XP_Bool isBlank; /* cache rather than lookup in model */
|
||||||
|
Tile tile; /* cache rather than lookup in model */
|
||||||
|
DragObjInfo start;
|
||||||
|
DragObjInfo cur;
|
||||||
|
} DragState;
|
||||||
|
|
||||||
typedef struct BoardArrow { /* gets flipped along with board */
|
typedef struct BoardArrow { /* gets flipped along with board */
|
||||||
XP_U8 col;
|
XP_U8 col;
|
||||||
|
@ -146,8 +157,7 @@ struct BoardCtxt {
|
||||||
XP_Bool dividerInvalid;
|
XP_Bool dividerInvalid;
|
||||||
|
|
||||||
XP_Bool scoreBoardInvalid;
|
XP_Bool scoreBoardInvalid;
|
||||||
TileDragState tileDragState;
|
DragState dragState;
|
||||||
DividerDragState divDragState;
|
|
||||||
|
|
||||||
MiniWindowStuff miniWindowStuff[2];
|
MiniWindowStuff miniWindowStuff[2];
|
||||||
XP_Bool tradingMiniWindowInvalid;
|
XP_Bool tradingMiniWindowInvalid;
|
||||||
|
@ -182,22 +192,41 @@ struct BoardCtxt {
|
||||||
#define TRADE_IN_PROGRESS(b) ((b)->tradeInProgress[(b)->selPlayer]==XP_TRUE)
|
#define TRADE_IN_PROGRESS(b) ((b)->tradeInProgress[(b)->selPlayer]==XP_TRUE)
|
||||||
|
|
||||||
/* tray-related functions */
|
/* tray-related functions */
|
||||||
XP_Bool handlePenDownInTray( BoardCtxt* board, XP_U16 x, XP_U16 y );
|
|
||||||
XP_Bool handlePenUpTray( BoardCtxt* board, XP_U16 x, XP_U16 y );
|
XP_Bool handlePenUpTray( BoardCtxt* board, XP_U16 x, XP_U16 y );
|
||||||
void drawTray( BoardCtxt* board );
|
void drawTray( BoardCtxt* board );
|
||||||
TileBit continueTileDrag( BoardCtxt* board, XP_U16 x, XP_U16 y );
|
|
||||||
XP_Bool endTileDrag( BoardCtxt* board, XP_U16 x, XP_U16 y );
|
|
||||||
XP_Bool continueDividerDrag( BoardCtxt* board, XP_U16 x, XP_U16 y );
|
|
||||||
XP_Bool endDividerDrag( BoardCtxt* board, XP_U16 x, XP_U16 y );
|
|
||||||
XP_Bool moveTileToArrowLoc( BoardCtxt* board, XP_U8 index );
|
XP_Bool moveTileToArrowLoc( BoardCtxt* board, XP_U8 index );
|
||||||
XP_U16 indexForBits( XP_U8 bits );
|
XP_U16 indexForBits( XP_U8 bits );
|
||||||
XP_Bool rectContainsPt( XP_Rect* rect1, XP_S16 x, XP_S16 y );
|
XP_Bool rectContainsPt( XP_Rect* rect1, XP_S16 x, XP_S16 y );
|
||||||
XP_Bool checkRevealTray( BoardCtxt* board );
|
XP_Bool checkRevealTray( BoardCtxt* board );
|
||||||
void invalTilesUnderRect( BoardCtxt* board, XP_Rect* rect );
|
|
||||||
void figureTrayTileRect( BoardCtxt* board, XP_U16 index, XP_Rect* rect );
|
void figureTrayTileRect( BoardCtxt* board, XP_U16 index, XP_Rect* rect );
|
||||||
XP_Bool rectsIntersect( const XP_Rect* rect1, const XP_Rect* rect2 );
|
XP_Bool rectsIntersect( const XP_Rect* rect1, const XP_Rect* rect2 );
|
||||||
|
XP_S16 pointToTileIndex( BoardCtxt* board, XP_U16 x, XP_U16 y,
|
||||||
|
XP_Bool* onDividerP );
|
||||||
void board_selectPlayer( BoardCtxt* board, XP_U16 newPlayer );
|
void board_selectPlayer( BoardCtxt* board, XP_U16 newPlayer );
|
||||||
|
void flipIf( const BoardCtxt* board, XP_U16 col, XP_U16 row,
|
||||||
|
XP_U16* fCol, XP_U16* fRow );
|
||||||
|
XP_Bool pointOnSomething( BoardCtxt* board, XP_U16 x, XP_U16 y,
|
||||||
|
BoardObjectType* wp );
|
||||||
|
XP_Bool coordToCell( BoardCtxt* board, XP_U16 x, XP_U16 y, XP_U16* colP,
|
||||||
|
XP_U16* rowP );
|
||||||
|
XP_Bool cellOccupied( BoardCtxt* board, XP_U16 col, XP_U16 row,
|
||||||
|
XP_Bool inclPending );
|
||||||
|
XP_Bool moveTileToBoard( BoardCtxt* board, XP_U16 col, XP_U16 row,
|
||||||
|
XP_U16 tileIndex, Tile blankFace );
|
||||||
|
|
||||||
|
void invalTilesUnderRect( BoardCtxt* board, XP_Rect* rect );
|
||||||
|
void invalDragObj( BoardCtxt* board, const DragObjInfo* di );
|
||||||
|
void invalDragObjRange( BoardCtxt* board, const DragObjInfo* from,
|
||||||
|
const DragObjInfo* to );
|
||||||
|
void invalTrayTilesAbove( BoardCtxt* board, XP_U16 tileIndex );
|
||||||
|
void invalTrayTilesBetween( BoardCtxt* board, XP_U16 tileIndex1,
|
||||||
|
XP_U16 tileIndex2 );
|
||||||
|
XP_Bool tryReplaceTile( BoardCtxt* board, XP_U16 pencol, XP_U16 penrow );
|
||||||
|
void moveTileInTray( BoardCtxt* board, XP_U16 moveTo, XP_U16 moveFrom );
|
||||||
|
XP_UCHAR* getTileDrawInfo( const BoardCtxt* board, Tile tile, XP_Bool isBlank,
|
||||||
|
XP_Bitmap* bitmap, XP_S16* value,
|
||||||
|
XP_UCHAR* buf, XP_U16 len );
|
||||||
|
XP_Bool dividerMoved( BoardCtxt* board, XP_U8 newLoc );
|
||||||
|
|
||||||
#ifdef KEYBOARD_NAV
|
#ifdef KEYBOARD_NAV
|
||||||
XP_Bool tray_moveCursor( BoardCtxt* board, XP_Key cursorKey,
|
XP_Bool tray_moveCursor( BoardCtxt* board, XP_Key cursorKey,
|
||||||
|
|
|
@ -24,6 +24,7 @@ COMMONOBJDIR = ../common/$(PLATFORM)
|
||||||
|
|
||||||
COMMONSRC = \
|
COMMONSRC = \
|
||||||
$(COMMONDIR)/board.c \
|
$(COMMONDIR)/board.c \
|
||||||
|
$(COMMONDIR)/dragdrpp.c \
|
||||||
$(COMMONDIR)/scorebdp.c \
|
$(COMMONDIR)/scorebdp.c \
|
||||||
$(COMMONDIR)/tray.c \
|
$(COMMONDIR)/tray.c \
|
||||||
$(COMMONDIR)/draw.c \
|
$(COMMONDIR)/draw.c \
|
||||||
|
@ -47,6 +48,7 @@ COMMONSRC = \
|
||||||
|
|
||||||
COMMON1 = \
|
COMMON1 = \
|
||||||
$(COMMONOBJDIR)/board.o \
|
$(COMMONOBJDIR)/board.o \
|
||||||
|
$(COMMONOBJDIR)/dragdrpp.o \
|
||||||
$(COMMONOBJDIR)/tray.o \
|
$(COMMONOBJDIR)/tray.o \
|
||||||
$(COMMONOBJDIR)/scorebdp.o \
|
$(COMMONOBJDIR)/scorebdp.o \
|
||||||
$(COMMONOBJDIR)/draw.o \
|
$(COMMONOBJDIR)/draw.o \
|
||||||
|
|
|
@ -37,6 +37,8 @@ typedef enum {
|
||||||
, CELL_ISSTAR = 0x04
|
, CELL_ISSTAR = 0x04
|
||||||
, CELL_ISCURSOR = 0x08
|
, CELL_ISCURSOR = 0x08
|
||||||
, CELL_ISEMPTY = 0x10 /* of a tray tile slot */
|
, CELL_ISEMPTY = 0x10 /* of a tray tile slot */
|
||||||
|
, CELL_DRAGSRC = 0x20 /* where drag originated */
|
||||||
|
, CELL_DRAGCUR = 0x40 /* where drag is now */
|
||||||
, CELL_ALL = 0xFF
|
, CELL_ALL = 0xFF
|
||||||
} CellFlags;
|
} CellFlags;
|
||||||
|
|
||||||
|
@ -166,6 +168,12 @@ typedef struct DrawCtxVTable {
|
||||||
/* at least 1 of these two will be null*/
|
/* at least 1 of these two will be null*/
|
||||||
const XP_UCHAR* text, const XP_Bitmap bitmap,
|
const XP_UCHAR* text, const XP_Bitmap bitmap,
|
||||||
XP_S16 val, CellFlags flags );
|
XP_S16 val, CellFlags flags );
|
||||||
|
#ifdef POINTER_SUPPORT
|
||||||
|
void DRAW_VTABLE_NAME(drawTileMidDrag) ( DrawCtx* dctx, const XP_Rect* rect,
|
||||||
|
/* at least 1 of these two will be null*/
|
||||||
|
const XP_UCHAR* text, const XP_Bitmap bitmap,
|
||||||
|
XP_S16 val, CellFlags flags );
|
||||||
|
#endif
|
||||||
void DRAW_VTABLE_NAME(drawTileBack) ( DrawCtx* dctx, const XP_Rect* rect,
|
void DRAW_VTABLE_NAME(drawTileBack) ( DrawCtx* dctx, const XP_Rect* rect,
|
||||||
CellFlags flags );
|
CellFlags flags );
|
||||||
void DRAW_VTABLE_NAME(drawTrayDivider) ( DrawCtx* dctx, const XP_Rect* rect,
|
void DRAW_VTABLE_NAME(drawTrayDivider) ( DrawCtx* dctx, const XP_Rect* rect,
|
||||||
|
@ -254,6 +262,10 @@ struct DrawCtx {
|
||||||
#define draw_invertCell( dc, rect ) CALL_DRAW_NAME1(invertCell,(dc),(rect))
|
#define draw_invertCell( dc, rect ) CALL_DRAW_NAME1(invertCell,(dc),(rect))
|
||||||
#define draw_drawTile( dc, rect, text, bmp, val, hil ) \
|
#define draw_drawTile( dc, rect, text, bmp, val, hil ) \
|
||||||
CALL_DRAW_NAME5(drawTile,(dc),(rect),(text),(bmp),(val),(hil))
|
CALL_DRAW_NAME5(drawTile,(dc),(rect),(text),(bmp),(val),(hil))
|
||||||
|
#ifdef POINTER_SUPPORT
|
||||||
|
#define draw_drawTileMidDrag( dc, rect, text, bmp, val, hil ) \
|
||||||
|
CALL_DRAW_NAME5(drawTileMidDrag,(dc),(rect),(text),(bmp),(val),(hil))
|
||||||
|
#endif /* POINTER_SUPPORT */
|
||||||
#define draw_drawTileBack( dc, rect, f ) \
|
#define draw_drawTileBack( dc, rect, f ) \
|
||||||
CALL_DRAW_NAME2(drawTileBack, (dc), (rect), (f) )
|
CALL_DRAW_NAME2(drawTileBack, (dc), (rect), (f) )
|
||||||
#define draw_drawTrayDivider( dc, rect, s ) \
|
#define draw_drawTrayDivider( dc, rect, s ) \
|
||||||
|
|
|
@ -48,7 +48,8 @@ static void decrPendingTileCountAt( ModelCtxt* model, XP_U16 col,
|
||||||
XP_U16 row );
|
XP_U16 row );
|
||||||
static void notifyBoardListeners( ModelCtxt* model, XP_U16 turn,
|
static void notifyBoardListeners( ModelCtxt* model, XP_U16 turn,
|
||||||
XP_U16 col, XP_U16 row, XP_Bool added );
|
XP_U16 col, XP_U16 row, XP_Bool added );
|
||||||
static void notifyTrayListeners( ModelCtxt* model, XP_U16 turn, TileBit bits);
|
static void notifyTrayListeners( ModelCtxt* model, XP_U16 turn,
|
||||||
|
XP_S16 index1, XP_S16 index2 );
|
||||||
static CellTile getModelTileRaw( ModelCtxt* model, XP_U16 col, XP_U16 row );
|
static CellTile getModelTileRaw( ModelCtxt* model, XP_U16 col, XP_U16 row );
|
||||||
static void setModelTileRaw( ModelCtxt* model, XP_U16 col, XP_U16 row,
|
static void setModelTileRaw( ModelCtxt* model, XP_U16 col, XP_U16 row,
|
||||||
CellTile tile );
|
CellTile tile );
|
||||||
|
@ -874,30 +875,35 @@ model_getCurrentMoveTile( ModelCtxt* model, XP_S16 turn, XP_S16* index,
|
||||||
*tile = pt->tile & TILE_VALUE_MASK;
|
*tile = pt->tile & TILE_VALUE_MASK;
|
||||||
} /* model_getCurrentMoveTile */
|
} /* model_getCurrentMoveTile */
|
||||||
|
|
||||||
Tile
|
static Tile
|
||||||
model_removePlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index )
|
removePlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index )
|
||||||
{
|
{
|
||||||
PlayerCtxt* player = &model->players[turn];
|
PlayerCtxt* player = &model->players[turn];
|
||||||
Tile tile;
|
Tile tile;
|
||||||
short i;
|
short i;
|
||||||
TileBit bits = 0;
|
|
||||||
|
|
||||||
if ( index < 0 ) {
|
XP_ASSERT( index < player->trayTiles.nTiles );
|
||||||
index = player->trayTiles.nTiles - 1;
|
|
||||||
} else {
|
|
||||||
XP_ASSERT( index < player->trayTiles.nTiles );
|
|
||||||
}
|
|
||||||
|
|
||||||
tile = player->trayTiles.tiles[index];
|
tile = player->trayTiles.tiles[index];
|
||||||
bits = 1 << index;
|
|
||||||
|
|
||||||
--player->trayTiles.nTiles;
|
--player->trayTiles.nTiles;
|
||||||
for ( i = index; i < player->trayTiles.nTiles; ++i ) {
|
for ( i = index; i < player->trayTiles.nTiles; ++i ) {
|
||||||
player->trayTiles.tiles[i] = player->trayTiles.tiles[i+1];
|
player->trayTiles.tiles[i] = player->trayTiles.tiles[i+1];
|
||||||
bits |= 3 << i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyTrayListeners( model, turn, bits );
|
return tile;
|
||||||
|
} /* removePlayerTile */
|
||||||
|
|
||||||
|
Tile
|
||||||
|
model_removePlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index )
|
||||||
|
{
|
||||||
|
Tile tile;
|
||||||
|
PlayerCtxt* player = &model->players[turn];
|
||||||
|
if ( index < 0 ) {
|
||||||
|
index = player->trayTiles.nTiles - 1;
|
||||||
|
}
|
||||||
|
tile = removePlayerTile( model, turn, index );
|
||||||
|
notifyTrayListeners( model, turn, index, player->trayTiles.nTiles );
|
||||||
return tile;
|
return tile;
|
||||||
} /* model_removePlayerTile */
|
} /* model_removePlayerTile */
|
||||||
|
|
||||||
|
@ -1003,28 +1009,36 @@ model_moveTrayToBoard( ModelCtxt* model, XP_S16 turn, XP_U16 col, XP_U16 row,
|
||||||
} /* model_moveTrayToBoard */
|
} /* model_moveTrayToBoard */
|
||||||
|
|
||||||
void
|
void
|
||||||
model_moveBoardToTray( ModelCtxt* model, XP_S16 turn, XP_S16 index )
|
model_moveBoardToTray( ModelCtxt* model, XP_S16 turn,
|
||||||
|
XP_U16 col, XP_U16 row, XP_U16 trayOffset )
|
||||||
{
|
{
|
||||||
|
XP_S16 index;
|
||||||
PlayerCtxt* player;
|
PlayerCtxt* player;
|
||||||
short i;
|
short i;
|
||||||
PendingTile* pt;
|
PendingTile* pt;
|
||||||
Tile tile;
|
Tile tile;
|
||||||
|
|
||||||
player = &model->players[turn];
|
player = &model->players[turn];
|
||||||
if ( index < 0 ) {
|
for ( pt = player->pendingTiles, index = 0;
|
||||||
index = player->nPending - 1;
|
index < player->nPending;
|
||||||
}
|
++index, ++pt ) {
|
||||||
|
if ( pt->col == col && pt->row == row ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* may be legal to fail to find, but we'd better return now! */
|
||||||
|
XP_ASSERT( index < player->nPending );
|
||||||
|
|
||||||
|
decrPendingTileCountAt( model, col, row );
|
||||||
|
notifyBoardListeners( model, turn, col, row, XP_FALSE );
|
||||||
|
|
||||||
pt = &player->pendingTiles[index];
|
|
||||||
decrPendingTileCountAt( model, pt->col, pt->row );
|
|
||||||
notifyBoardListeners( model, turn, pt->col, pt->row, XP_FALSE );
|
|
||||||
tile = pt->tile;
|
tile = pt->tile;
|
||||||
|
|
||||||
if ( (tile & TILE_BLANK_BIT) != 0 ) {
|
if ( (tile & TILE_BLANK_BIT) != 0 ) {
|
||||||
tile = dict_getBlankTile( model->vol.dict );
|
tile = dict_getBlankTile( model->vol.dict );
|
||||||
}
|
}
|
||||||
|
|
||||||
model_addPlayerTile( model, turn, -1, tile );
|
model_addPlayerTile( model, turn, trayOffset, tile );
|
||||||
|
|
||||||
--player->nPending;
|
--player->nPending;
|
||||||
for ( i = index; i < player->nPending; ++i ) {
|
for ( i = index; i < player->nPending; ++i ) {
|
||||||
|
@ -1038,6 +1052,36 @@ model_moveBoardToTray( ModelCtxt* model, XP_S16 turn, XP_S16 index )
|
||||||
invalidateScore( model, turn );
|
invalidateScore( model, turn );
|
||||||
} /* model_moveBoardToTray */
|
} /* model_moveBoardToTray */
|
||||||
|
|
||||||
|
void
|
||||||
|
model_moveTileOnBoard( ModelCtxt* model, XP_S16 turn, XP_U16 colCur,
|
||||||
|
XP_U16 rowCur, XP_U16 colNew, XP_U16 rowNew )
|
||||||
|
{
|
||||||
|
PlayerCtxt* player = &model->players[turn];
|
||||||
|
XP_S16 index = player->nPending;
|
||||||
|
|
||||||
|
while ( index-- ) {
|
||||||
|
Tile tile;
|
||||||
|
XP_U16 tcol, trow;
|
||||||
|
XP_Bool isBlank;
|
||||||
|
model_getCurrentMoveTile( model, turn, &index, &tile, &tcol, &trow,
|
||||||
|
&isBlank );
|
||||||
|
if ( colCur == tcol && rowCur == trow ) {
|
||||||
|
PendingTile* pt = &player->pendingTiles[index];
|
||||||
|
pt->col = colNew;
|
||||||
|
pt->row = rowNew;
|
||||||
|
if ( isBlank ) {
|
||||||
|
pt->tile = TILE_BLANK_BIT | askBlankTile( model, turn );
|
||||||
|
}
|
||||||
|
|
||||||
|
decrPendingTileCountAt( model, colCur, rowCur );
|
||||||
|
incrPendingTileCountAt( model, colNew, rowNew );
|
||||||
|
|
||||||
|
invalidateScore( model, turn );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
model_resetCurrentTurn( ModelCtxt* model, XP_S16 whose )
|
model_resetCurrentTurn( ModelCtxt* model, XP_S16 whose )
|
||||||
{
|
{
|
||||||
|
@ -1047,7 +1091,10 @@ model_resetCurrentTurn( ModelCtxt* model, XP_S16 whose )
|
||||||
player = &model->players[whose];
|
player = &model->players[whose];
|
||||||
|
|
||||||
while ( player->nPending > 0 ) {
|
while ( player->nPending > 0 ) {
|
||||||
model_moveBoardToTray( model, whose, -1 );
|
model_moveBoardToTray( model, whose,
|
||||||
|
player->pendingTiles[0].col,
|
||||||
|
player->pendingTiles[0].row,
|
||||||
|
-1 );
|
||||||
}
|
}
|
||||||
} /* model_resetCurrentTurn */
|
} /* model_resetCurrentTurn */
|
||||||
|
|
||||||
|
@ -1104,27 +1151,13 @@ static void
|
||||||
putBackOtherPlayersTiles( ModelCtxt* model, XP_U16 notMyTurn,
|
putBackOtherPlayersTiles( ModelCtxt* model, XP_U16 notMyTurn,
|
||||||
XP_U16 col, XP_U16 row )
|
XP_U16 col, XP_U16 row )
|
||||||
{
|
{
|
||||||
XP_S16 turn, j;
|
XP_S16 turn;
|
||||||
|
|
||||||
for ( turn = 0; turn < model->nPlayers; ++turn ) {
|
for ( turn = 0; turn < model->nPlayers; ++turn ) {
|
||||||
PlayerCtxt* player;
|
|
||||||
|
|
||||||
if ( turn == notMyTurn ) {
|
if ( turn == notMyTurn ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
model_moveBoardToTray( model, turn, col, row, -1 );
|
||||||
player = &model->players[turn];
|
|
||||||
for ( j = player->nPending-1; j >= 0; --j ) { /* backwards in case
|
|
||||||
removed */
|
|
||||||
PendingTile* pt = &player->pendingTiles[j];
|
|
||||||
if ( pt->col == col && pt->row == row ) {
|
|
||||||
/* this one needs to be put back */
|
|
||||||
|
|
||||||
model_moveBoardToTray( model, turn, j );
|
|
||||||
|
|
||||||
break; /* a player can have only one tile on a square */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} /* putBackOtherPlayersTiles */
|
} /* putBackOtherPlayersTiles */
|
||||||
|
|
||||||
|
@ -1271,31 +1304,44 @@ model_getPlayerTiles( ModelCtxt* model, XP_S16 turn )
|
||||||
return (const TrayTileSet*)&player->trayTiles;
|
return (const TrayTileSet*)&player->trayTiles;
|
||||||
} /* model_getPlayerTile */
|
} /* model_getPlayerTile */
|
||||||
|
|
||||||
void
|
static void
|
||||||
model_addPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index, Tile tile )
|
addPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index, Tile tile )
|
||||||
{
|
{
|
||||||
PlayerCtxt* player = &model->players[turn];
|
PlayerCtxt* player = &model->players[turn];
|
||||||
short i;
|
short i;
|
||||||
TileBit bits = 0;
|
|
||||||
|
|
||||||
XP_ASSERT( player->trayTiles.nTiles < MAX_TRAY_TILES );
|
XP_ASSERT( player->trayTiles.nTiles < MAX_TRAY_TILES );
|
||||||
|
XP_ASSERT( index >= 0 );
|
||||||
if ( index < 0 ) {
|
|
||||||
index = player->trayTiles.nTiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* move tiles up to make room */
|
/* move tiles up to make room */
|
||||||
for ( i = player->trayTiles.nTiles; i > index; --i ) {
|
for ( i = player->trayTiles.nTiles; i > index; --i ) {
|
||||||
player->trayTiles.tiles[i] = player->trayTiles.tiles[i-1];
|
player->trayTiles.tiles[i] = player->trayTiles.tiles[i-1];
|
||||||
bits |= (3 << (i-2));
|
|
||||||
}
|
}
|
||||||
++player->trayTiles.nTiles;
|
++player->trayTiles.nTiles;
|
||||||
player->trayTiles.tiles[index] = tile;
|
player->trayTiles.tiles[index] = tile;
|
||||||
|
} /* addPlayerTile */
|
||||||
|
|
||||||
bits |= (1 << index);
|
void
|
||||||
notifyTrayListeners( model, turn, bits );
|
model_addPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index, Tile tile )
|
||||||
|
{
|
||||||
|
PlayerCtxt* player = &model->players[turn];
|
||||||
|
if ( index < 0 ) {
|
||||||
|
index = player->trayTiles.nTiles;
|
||||||
|
}
|
||||||
|
addPlayerTile( model, turn, index, tile );
|
||||||
|
|
||||||
|
notifyTrayListeners( model, turn, index, player->trayTiles.nTiles );
|
||||||
} /* model_addPlayerTile */
|
} /* model_addPlayerTile */
|
||||||
|
|
||||||
|
void
|
||||||
|
model_moveTileOnTray( ModelCtxt* model, XP_S16 turn, XP_S16 indexCur,
|
||||||
|
XP_S16 indexNew )
|
||||||
|
{
|
||||||
|
Tile tile = removePlayerTile( model, turn, indexCur );
|
||||||
|
addPlayerTile( model, turn, indexNew, tile );
|
||||||
|
notifyTrayListeners( model, turn, indexCur, indexNew );
|
||||||
|
} /* model_moveTileOnTray */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
assignPlayerTiles( ModelCtxt* model, XP_S16 turn, TrayTileSet* tiles )
|
assignPlayerTiles( ModelCtxt* model, XP_S16 turn, TrayTileSet* tiles )
|
||||||
{
|
{
|
||||||
|
@ -1367,11 +1413,12 @@ notifyBoardListeners( ModelCtxt* model, XP_U16 turn, XP_U16 col, XP_U16 row,
|
||||||
} /* notifyBoardListeners */
|
} /* notifyBoardListeners */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
notifyTrayListeners( ModelCtxt* model, XP_U16 turn, TileBit bits )
|
notifyTrayListeners( ModelCtxt* model, XP_U16 turn, XP_S16 index1,
|
||||||
|
XP_S16 index2 )
|
||||||
{
|
{
|
||||||
if ( model->vol.trayListenerFunc != NULL ) {
|
if ( model->vol.trayListenerFunc != NULL ) {
|
||||||
(*model->vol.trayListenerFunc)( model->vol.trayListenerData, turn,
|
(*model->vol.trayListenerFunc)( model->vol.trayListenerData, turn,
|
||||||
bits );
|
index1, index2 );
|
||||||
}
|
}
|
||||||
} /* notifyTrayListeners */
|
} /* notifyTrayListeners */
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,8 @@ Tile model_getPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index );
|
||||||
Tile model_removePlayerTile( 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,
|
void model_addPlayerTile( ModelCtxt* model, XP_S16 turn, XP_S16 index,
|
||||||
Tile tile );
|
Tile tile );
|
||||||
|
void model_moveTileOnTray( ModelCtxt* model, XP_S16 turn, XP_S16 indexCur,
|
||||||
|
XP_S16 indexNew );
|
||||||
|
|
||||||
/* As an optimization, return a pointer to the model's array of tiles for a
|
/* As an optimization, return a pointer to the model's array of tiles for a
|
||||||
player. Don't even think about modifying the array!!!! */
|
player. Don't even think about modifying the array!!!! */
|
||||||
|
@ -134,9 +136,13 @@ const TrayTileSet* model_getPlayerTiles( ModelCtxt* model, XP_S16 turn );
|
||||||
|
|
||||||
XP_U16 model_getNumTilesInTray( ModelCtxt* model, XP_S16 turn );
|
XP_U16 model_getNumTilesInTray( ModelCtxt* model, XP_S16 turn );
|
||||||
XP_U16 model_getNumTilesTotal( ModelCtxt* model, XP_S16 turn );
|
XP_U16 model_getNumTilesTotal( ModelCtxt* model, XP_S16 turn );
|
||||||
void model_moveBoardToTray( ModelCtxt* model, XP_S16 turn, XP_S16 index );
|
void model_moveBoardToTray( ModelCtxt* model, XP_S16 turn,
|
||||||
|
XP_U16 col, XP_U16 row, XP_U16 trayOffset );
|
||||||
void model_moveTrayToBoard( ModelCtxt* model, XP_S16 turn, XP_U16 col,
|
void model_moveTrayToBoard( ModelCtxt* model, XP_S16 turn, XP_U16 col,
|
||||||
XP_U16 row, XP_S16 tileIndex, Tile blankFace );
|
XP_U16 row, XP_S16 tileIndex, Tile blankFace );
|
||||||
|
void model_moveTileOnBoard( ModelCtxt* model, XP_S16 turn, XP_U16 colCur,
|
||||||
|
XP_U16 rowCur, XP_U16 colNew, XP_U16 rowNew );
|
||||||
|
|
||||||
XP_S16 model_trayContains( ModelCtxt* model, XP_S16 turn, Tile tile );
|
XP_S16 model_trayContains( ModelCtxt* model, XP_S16 turn, Tile tile );
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,7 +190,8 @@ typedef void (*BoardListener)(void* data, XP_U16 turn, XP_U16 col,
|
||||||
XP_U16 row, XP_Bool added );
|
XP_U16 row, XP_Bool added );
|
||||||
void model_setBoardListener( ModelCtxt* model, BoardListener bl,
|
void model_setBoardListener( ModelCtxt* model, BoardListener bl,
|
||||||
void* data );
|
void* data );
|
||||||
typedef void (*TrayListener)(void* data, XP_U16 turn, TileBit bits );
|
typedef void (*TrayListener)( void* data, XP_U16 turn,
|
||||||
|
XP_S16 index1, XP_S16 index2 );
|
||||||
void model_setTrayListener( ModelCtxt* model, TrayListener bl,
|
void model_setTrayListener( ModelCtxt* model, TrayListener bl,
|
||||||
void* data );
|
void* data );
|
||||||
void model_foreachPendingCell( ModelCtxt* model, XP_S16 turn,
|
void model_foreachPendingCell( ModelCtxt* model, XP_S16 turn,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||||
/*
|
/*
|
||||||
* Copyright 1997 - 2007 by Eric House (xwords@eehouse.org). All rights reserved.
|
* Copyright 1997 - 2008 by Eric House (xwords@eehouse.org). All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "boardp.h"
|
#include "boardp.h"
|
||||||
|
#include "dragdrpp.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "strutils.h"
|
#include "strutils.h"
|
||||||
|
@ -27,13 +28,9 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/****************************** prototypes ******************************/
|
/****************************** prototypes ******************************/
|
||||||
static XP_Bool startDividerDrag( BoardCtxt* board );
|
|
||||||
static XP_Bool startTileDrag( BoardCtxt* board, XP_U8 startIndex );
|
|
||||||
static void figureDividerRect( BoardCtxt* board, XP_Rect* rect );
|
static void figureDividerRect( BoardCtxt* board, XP_Rect* rect );
|
||||||
static void drawPendingScore( BoardCtxt* board, XP_Bool hasCursor );
|
static void drawPendingScore( BoardCtxt* board, XP_Bool hasCursor );
|
||||||
static void invalTrayTilesBetween( BoardCtxt* board, XP_U16 tileIndex1,
|
static XP_U16 countTilesToShow( BoardCtxt* board );
|
||||||
XP_U16 tileIndex2 );
|
|
||||||
static XP_Bool endTileDragIndex( BoardCtxt* board, TileBit last );
|
|
||||||
|
|
||||||
static XP_S16
|
static XP_S16
|
||||||
trayLocToIndex( BoardCtxt* board, XP_U16 loc )
|
trayLocToIndex( BoardCtxt* board, XP_U16 loc )
|
||||||
|
@ -48,7 +45,7 @@ trayLocToIndex( BoardCtxt* board, XP_U16 loc )
|
||||||
return loc;
|
return loc;
|
||||||
} /* trayLocToIndex */
|
} /* trayLocToIndex */
|
||||||
|
|
||||||
static XP_S16
|
XP_S16
|
||||||
pointToTileIndex( BoardCtxt* board, XP_U16 x, XP_U16 y, XP_Bool* onDividerP )
|
pointToTileIndex( BoardCtxt* board, XP_U16 x, XP_U16 y, XP_Bool* onDividerP )
|
||||||
{
|
{
|
||||||
XP_S16 result = -1; /* not on a tile */
|
XP_S16 result = -1; /* not on a tile */
|
||||||
|
@ -99,11 +96,32 @@ figureTrayTileRect( BoardCtxt* board, XP_U16 index, XP_Rect* rect )
|
||||||
}
|
}
|
||||||
} /* figureTileRect */
|
} /* figureTileRect */
|
||||||
|
|
||||||
|
/* When drawing tray mid-drag:
|
||||||
|
*
|
||||||
|
* Rule is not to touch the model.
|
||||||
|
*
|
||||||
|
* Cases: Tile's been dragged into tray (but not yet dropped.); tile's been
|
||||||
|
* dragged out of tray (but not yet dropped); and tile's been dragged within
|
||||||
|
* tray. More's the point, there's an added tile and a removed one. We draw
|
||||||
|
* the added tile extra, and skip the removed one.
|
||||||
|
*
|
||||||
|
* We're walking two arrays at once, backwards. The first is the tile rects
|
||||||
|
* themselves. If the dirty bit is set, something must get drawn. The second
|
||||||
|
* is the model's view of tiles augmented by drag-and-drop. D-n-d may have
|
||||||
|
* removed a tile from the tray (for drawing purposes only), have added one,
|
||||||
|
* or both (drag-within-tray case). Since a drag lasts only until pen-up,
|
||||||
|
* there's never more than one tile involved. Adjustment is never by more
|
||||||
|
* than one.
|
||||||
|
*
|
||||||
|
* So while one counter (i) walks the array of rects, we can't use it
|
||||||
|
* unmodified to fetch from the model. Instead we increment or decrement it
|
||||||
|
* based on the drag state.
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
drawTray( BoardCtxt* board )
|
drawTray( BoardCtxt* board )
|
||||||
{
|
{
|
||||||
XP_Rect tileRect;
|
XP_Rect tileRect;
|
||||||
short i;
|
|
||||||
|
|
||||||
if ( (board->trayInvalBits != 0) || board->dividerInvalid ) {
|
if ( (board->trayInvalBits != 0) || board->dividerInvalid ) {
|
||||||
XP_S16 turn = board->selPlayer;
|
XP_S16 turn = board->selPlayer;
|
||||||
|
@ -122,23 +140,23 @@ drawTray( BoardCtxt* board )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* if ( board->eraseTray ) { */
|
|
||||||
/* draw_clearRect( board->draw, &board->trayBounds ); */
|
|
||||||
/* board->eraseTray = XP_FALSE; */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
if ( (board->trayVisState != TRAY_HIDDEN) && dictionary != NULL ) {
|
if ( (board->trayVisState != TRAY_HIDDEN) && dictionary != NULL ) {
|
||||||
XP_Bool showFaces = board->trayVisState == TRAY_REVEALED;
|
XP_Bool showFaces = board->trayVisState == TRAY_REVEALED;
|
||||||
Tile blank = dict_getBlankTile( dictionary );
|
Tile blank = dict_getBlankTile( dictionary );
|
||||||
|
|
||||||
if ( turn >= 0 ) {
|
if ( turn >= 0 ) {
|
||||||
XP_U16 numInTray = showFaces?
|
XP_S16 i; /* which tile slot are we drawing in */
|
||||||
model_getNumTilesInTray( board->model, turn ):
|
XP_U16 ddAddedIndx, ddRmvdIndx;
|
||||||
model_getNumTilesTotal( board->model, turn );
|
XP_U16 numInTray = countTilesToShow( board );
|
||||||
|
XP_Bool isBlank;
|
||||||
|
XP_Bool isADrag = dragDropInProgress( board );
|
||||||
|
|
||||||
|
dragDropGetTrayChanges( board, &ddRmvdIndx, &ddAddedIndx );
|
||||||
|
|
||||||
/* draw in reverse order so drawing happens after
|
/* draw in reverse order so drawing happens after
|
||||||
erasing */
|
erasing */
|
||||||
for ( i = MAX_TRAY_TILES - 1; i >= 0; --i ) {
|
for ( i = MAX_TRAY_TILES - 1;
|
||||||
|
i >= 0; --i ) {
|
||||||
CellFlags flags = CELL_NONE;
|
CellFlags flags = CELL_NONE;
|
||||||
XP_U16 mask = 1 << i;
|
XP_U16 mask = 1 << i;
|
||||||
|
|
||||||
|
@ -161,28 +179,41 @@ drawTray( BoardCtxt* board )
|
||||||
XP_UCHAR* textP = (XP_UCHAR*)NULL;
|
XP_UCHAR* textP = (XP_UCHAR*)NULL;
|
||||||
XP_U8 traySelBits = board->traySelBits[turn];
|
XP_U8 traySelBits = board->traySelBits[turn];
|
||||||
XP_S16 value;
|
XP_S16 value;
|
||||||
Tile tile = model_getPlayerTile( board->model,
|
Tile tile;
|
||||||
turn, i );
|
|
||||||
|
|
||||||
if ( dict_faceIsBitmap( dictionary, tile ) ) {
|
if ( ddAddedIndx == i ) {
|
||||||
bitmap = dict_getFaceBitmap( dictionary, tile,
|
dragDropTileInfo( board, &tile, &isBlank );
|
||||||
XP_TRUE );
|
|
||||||
} else {
|
} else {
|
||||||
textP = buf;
|
XP_U16 modIndex = i;
|
||||||
dict_tilesToString( dictionary, &tile, 1,
|
if ( ddAddedIndx < i ) {
|
||||||
textP, sizeof(buf) );
|
--modIndex;
|
||||||
|
}
|
||||||
|
/* while we're right of the removal area,
|
||||||
|
draw the one from the right to cover. */
|
||||||
|
if ( ddRmvdIndx <= modIndex /*slotIndx*/ ) {
|
||||||
|
++modIndex;
|
||||||
|
}
|
||||||
|
tile = model_getPlayerTile( board->model,
|
||||||
|
turn, modIndex );
|
||||||
|
isBlank = tile == blank;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textP = getTileDrawInfo( board, tile, isBlank,
|
||||||
|
&bitmap, &value,
|
||||||
|
buf, sizeof(buf) );
|
||||||
if ( board->hideValsInTray
|
if ( board->hideValsInTray
|
||||||
&& !board->showCellValues ) {
|
&& !board->showCellValues ) {
|
||||||
value = -1;
|
value = -1;
|
||||||
} else {
|
|
||||||
value = dict_getTileValue( dictionary, tile );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (traySelBits & (1<<i)) != 0 ) {
|
if ( isADrag ) {
|
||||||
|
if ( ddAddedIndx == i ) {
|
||||||
|
flags |= CELL_HIGHLIGHT;
|
||||||
|
}
|
||||||
|
} else if ( (traySelBits & (1<<i)) != 0 ) {
|
||||||
flags |= CELL_HIGHLIGHT;
|
flags |= CELL_HIGHLIGHT;
|
||||||
}
|
}
|
||||||
if ( tile == blank ) {
|
if ( isBlank ) {
|
||||||
flags |= CELL_ISBLANK;
|
flags |= CELL_ISBLANK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +230,7 @@ drawTray( BoardCtxt* board )
|
||||||
XP_Rect divider;
|
XP_Rect divider;
|
||||||
figureDividerRect( board, ÷r );
|
figureDividerRect( board, ÷r );
|
||||||
draw_drawTrayDivider( board->draw, ÷r,
|
draw_drawTrayDivider( board->draw, ÷r,
|
||||||
board->divDragState.dragInProgress );
|
dragDropIsDividerDrag(board) );
|
||||||
board->dividerInvalid = XP_FALSE;
|
board->dividerInvalid = XP_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,42 +247,69 @@ drawTray( BoardCtxt* board )
|
||||||
|
|
||||||
} /* drawTray */
|
} /* drawTray */
|
||||||
|
|
||||||
|
XP_UCHAR*
|
||||||
|
getTileDrawInfo( const BoardCtxt* board, Tile tile, XP_Bool isBlank,
|
||||||
|
XP_Bitmap* bitmap, XP_S16* value, XP_UCHAR* buf, XP_U16 len )
|
||||||
|
{
|
||||||
|
XP_UCHAR* face = NULL;
|
||||||
|
DictionaryCtxt* dict = model_getDictionary( board->model );
|
||||||
|
if ( isBlank ) {
|
||||||
|
tile = dict_getBlankTile( dict );
|
||||||
|
}
|
||||||
|
*value = dict_getTileValue( dict, tile );
|
||||||
|
if ( dict_faceIsBitmap( dict, tile ) ) {
|
||||||
|
*bitmap = dict_getFaceBitmap( dict, tile, XP_TRUE );
|
||||||
|
} else {
|
||||||
|
dict_tilesToString( dict, &tile, 1, buf, len );
|
||||||
|
face = buf;
|
||||||
|
}
|
||||||
|
return face;
|
||||||
|
}
|
||||||
|
|
||||||
|
static XP_U16
|
||||||
|
countTilesToShow( BoardCtxt* board )
|
||||||
|
{
|
||||||
|
XP_U16 numToShow;
|
||||||
|
XP_S16 selPlayer = board->selPlayer;
|
||||||
|
XP_U16 ddAddedIndx, ddRemovedIndx;
|
||||||
|
|
||||||
|
XP_ASSERT( selPlayer >= 0 );
|
||||||
|
if ( board->trayVisState == TRAY_REVEALED ) {
|
||||||
|
numToShow = model_getNumTilesInTray( board->model, selPlayer );
|
||||||
|
} else {
|
||||||
|
numToShow = model_getNumTilesTotal( board->model, selPlayer );
|
||||||
|
}
|
||||||
|
|
||||||
|
dragDropGetTrayChanges( board, &ddRemovedIndx, &ddAddedIndx );
|
||||||
|
if ( ddAddedIndx < MAX_TRAY_TILES ) {
|
||||||
|
++numToShow;
|
||||||
|
}
|
||||||
|
if ( ddRemovedIndx < MAX_TRAY_TILES ) {
|
||||||
|
--numToShow;
|
||||||
|
}
|
||||||
|
|
||||||
|
XP_ASSERT( numToShow <= MAX_TRAY_TILES );
|
||||||
|
return numToShow;
|
||||||
|
} /* countTilesToShow */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drawPendingScore( BoardCtxt* board, XP_Bool hasCursor )
|
drawPendingScore( BoardCtxt* board, XP_Bool hasCursor )
|
||||||
{
|
{
|
||||||
/* Draw the pending score down in the last tray's rect */
|
/* Draw the pending score down in the last tray's rect */
|
||||||
if ( board->trayVisState == TRAY_REVEALED ) {
|
if ( countTilesToShow( board ) < MAX_TRAY_TILES ) {
|
||||||
XP_U16 selPlayer = board->selPlayer;
|
XP_U16 selPlayer = board->selPlayer;
|
||||||
XP_U16 tilesInTray = model_getNumTilesInTray( board->model, selPlayer);
|
XP_S16 turnScore = 0;
|
||||||
if ( tilesInTray < MAX_TRAY_TILES ) {
|
XP_Rect lastTileR;
|
||||||
|
|
||||||
XP_S16 turnScore = 0;
|
(void)getCurrentMoveScoreIfLegal( board->model, selPlayer,
|
||||||
XP_Rect lastTileR;
|
(XWStreamCtxt*)NULL, &turnScore );
|
||||||
|
figureTrayTileRect( board, MAX_TRAY_TILES-1, &lastTileR );
|
||||||
(void)getCurrentMoveScoreIfLegal( board->model, selPlayer,
|
draw_score_pendingScore( board->draw, &lastTileR, turnScore,
|
||||||
(XWStreamCtxt*)NULL, &turnScore );
|
selPlayer,
|
||||||
figureTrayTileRect( board, MAX_TRAY_TILES-1, &lastTileR );
|
hasCursor?CELL_ISCURSOR:CELL_NONE );
|
||||||
draw_score_pendingScore( board->draw, &lastTileR, turnScore,
|
|
||||||
selPlayer,
|
|
||||||
hasCursor?CELL_ISCURSOR:CELL_NONE );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} /* drawPendingScore */
|
} /* drawPendingScore */
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static XP_U16
|
|
||||||
countSelectedTiles( XP_U8 ti )
|
|
||||||
{
|
|
||||||
XP_U16 result = 0;
|
|
||||||
|
|
||||||
while ( ti != 0 ) {
|
|
||||||
++result;
|
|
||||||
ti &= ti-1;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} /* countSelectedTiles */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
figureDividerRect( BoardCtxt* board, XP_Rect* rect )
|
figureDividerRect( BoardCtxt* board, XP_Rect* rect )
|
||||||
{
|
{
|
||||||
|
@ -293,66 +351,38 @@ handleTrayDuringTrade( BoardCtxt* board, XP_S16 index )
|
||||||
} /* handleTrayDuringTrade */
|
} /* handleTrayDuringTrade */
|
||||||
|
|
||||||
static XP_Bool
|
static XP_Bool
|
||||||
handleActionInTray( BoardCtxt* board, XP_S16 index, XP_Bool onDivider,
|
handleActionInTray( BoardCtxt* board, XP_S16 index, XP_Bool onDivider )
|
||||||
XP_Bool waitPenUp )
|
|
||||||
{
|
{
|
||||||
XP_Bool result = XP_FALSE;
|
XP_Bool result = XP_FALSE;
|
||||||
XP_U16 selPlayer = board->selPlayer;
|
XP_U16 selPlayer = board->selPlayer;
|
||||||
|
|
||||||
if ( onDivider ) {
|
if ( onDivider ) {
|
||||||
result = startDividerDrag( board );
|
/* do nothing */
|
||||||
} else if ( board->tradeInProgress[selPlayer]
|
} else if ( board->tradeInProgress[selPlayer] ) {
|
||||||
/* && MY_TURN(board) */ ) {
|
|
||||||
if ( index >= 0 ) {
|
if ( index >= 0 ) {
|
||||||
result = handleTrayDuringTrade( board, index );
|
result = handleTrayDuringTrade( board, index );
|
||||||
}
|
}
|
||||||
} else if ( index >= 0 ) {
|
} else if ( index >= 0 ) {
|
||||||
TileBit newIndex = 1 << index;
|
result = moveTileToArrowLoc( board, (XP_U8)index );
|
||||||
BoardArrow* arrow = &board->boardArrow[selPlayer];
|
if ( !result ) {
|
||||||
|
TileBit newBits = 1 << index;
|
||||||
if ( !arrow->visible ) {
|
XP_U8 selBits = board->traySelBits[selPlayer];
|
||||||
XP_U8 selFlags = board->traySelBits[selPlayer];
|
|
||||||
/* Tap on selected tile unselects. If we don't do this,
|
/* Tap on selected tile unselects. If we don't do this,
|
||||||
then there's no way to unselect and so no way to turn
|
then there's no way to unselect and so no way to turn
|
||||||
off the placement arrow */
|
off the placement arrow */
|
||||||
if ( !waitPenUp && newIndex == selFlags ) {
|
if ( newBits == selBits ) {
|
||||||
board_invalTrayTiles( board, selFlags );
|
board_invalTrayTiles( board, selBits );
|
||||||
selFlags = NO_TILES;
|
board->traySelBits[selPlayer] = NO_TILES;
|
||||||
board->traySelBits[selPlayer] = selFlags;
|
} else if ( selBits != 0 ) {
|
||||||
result = XP_TRUE;
|
XP_U16 selIndex = indexForBits( selBits );
|
||||||
|
model_moveTileOnTray( board->model, board->selPlayer,
|
||||||
|
selIndex, index );
|
||||||
|
board->traySelBits[selPlayer] = NO_TILES;
|
||||||
} else {
|
} else {
|
||||||
result = startTileDrag( board, newIndex );
|
board_invalTrayTiles( board, newBits );
|
||||||
if ( !waitPenUp ) {
|
board->traySelBits[selPlayer] = newBits;
|
||||||
/* key interface means pen up and down happen in the same
|
|
||||||
event. No dragging. */
|
|
||||||
result = endTileDragIndex( board, newIndex ) || result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
result = XP_TRUE;
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} /* handleActionInTray */
|
|
||||||
|
|
||||||
XP_Bool
|
|
||||||
handlePenDownInTray( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
|
||||||
{
|
|
||||||
XP_Bool onDivider = XP_FALSE;
|
|
||||||
XP_S16 index = pointToTileIndex( board, x, y, &onDivider );
|
|
||||||
|
|
||||||
return handleActionInTray( board, index, onDivider, XP_TRUE );
|
|
||||||
} /* handlePenDownInTray */
|
|
||||||
|
|
||||||
static XP_Bool
|
|
||||||
handlePenUpTrayInt( BoardCtxt* board, XP_S16 index )
|
|
||||||
{
|
|
||||||
XP_Bool result = XP_FALSE;
|
|
||||||
|
|
||||||
if ( index >= 0 ) {
|
|
||||||
XP_U16 selPlayer = board->selPlayer;
|
|
||||||
BoardArrow* arrow = &board->boardArrow[selPlayer];
|
|
||||||
|
|
||||||
if ( arrow->visible ) {
|
|
||||||
result = moveTileToArrowLoc( board, (XP_U8)index );
|
|
||||||
}
|
}
|
||||||
} else if ( index == -(MAX_TRAY_TILES) ) { /* pending score tile */
|
} else if ( index == -(MAX_TRAY_TILES) ) { /* pending score tile */
|
||||||
result = board_commitTurn( board );
|
result = board_commitTurn( board );
|
||||||
|
@ -361,85 +391,17 @@ handlePenUpTrayInt( BoardCtxt* board, XP_S16 index )
|
||||||
(void)board_replaceTiles( board );
|
(void)board_replaceTiles( board );
|
||||||
result = XP_TRUE;
|
result = XP_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} /* handlePenUpTray */
|
} /* handleActionInTray */
|
||||||
|
|
||||||
XP_Bool
|
XP_Bool
|
||||||
handlePenUpTray( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
handlePenUpTray( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
||||||
{
|
{
|
||||||
XP_Bool ignore;
|
XP_Bool onDivider;
|
||||||
XP_S16 index = pointToTileIndex( board, x, y, &ignore );
|
XP_S16 index = pointToTileIndex( board, x, y, &onDivider );
|
||||||
return handlePenUpTrayInt( board, index );
|
return handleActionInTray( board, index, onDivider );
|
||||||
} /* handlePenUpTray */
|
} /* handlePenUpTray */
|
||||||
|
|
||||||
static XP_Bool
|
|
||||||
startTileDrag( BoardCtxt* board, TileBit startBit/* , XP_U16 x, XP_U16 y */ )
|
|
||||||
{
|
|
||||||
XP_Bool result = XP_FALSE;
|
|
||||||
XP_U16 turn = board->selPlayer;
|
|
||||||
XP_U8 startSel = board->traySelBits[turn];
|
|
||||||
TileDragState* state = &board->tileDragState;
|
|
||||||
|
|
||||||
XP_ASSERT( countSelectedTiles( startBit ) == 1 );
|
|
||||||
XP_ASSERT( !state->dragInProgress );
|
|
||||||
|
|
||||||
state->wasHilited = startSel == startBit;
|
|
||||||
state->selectionAtStart = startSel;
|
|
||||||
state->movePending = XP_TRUE;
|
|
||||||
|
|
||||||
state->dragInProgress = XP_TRUE;
|
|
||||||
state->prevIndex = board->traySelBits[turn] = startBit;
|
|
||||||
|
|
||||||
if ( !state->wasHilited ) {
|
|
||||||
board_invalTrayTiles( board, (TileBit)(startBit | startSel) );
|
|
||||||
result = XP_TRUE;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} /* startTileDrag */
|
|
||||||
|
|
||||||
static void
|
|
||||||
moveTileInTray( BoardCtxt* board, TileBit prevTile, TileBit newTile )
|
|
||||||
{
|
|
||||||
XP_S16 selPlayer = board->selPlayer;
|
|
||||||
ModelCtxt* model = board->model;
|
|
||||||
XP_U16 moveTo = indexForBits( prevTile );
|
|
||||||
XP_U16 moveFrom = indexForBits( newTile );
|
|
||||||
Tile tile;
|
|
||||||
XP_U16 dividerLoc;
|
|
||||||
|
|
||||||
tile = model_removePlayerTile( model, selPlayer, moveFrom );
|
|
||||||
model_addPlayerTile( model, selPlayer, moveTo, tile );
|
|
||||||
|
|
||||||
dividerLoc = board->dividerLoc[selPlayer];
|
|
||||||
if ( moveTo < dividerLoc || moveFrom < dividerLoc ) {
|
|
||||||
server_resetEngine( board->server, selPlayer );
|
|
||||||
}
|
|
||||||
} /* moveTileInTray */
|
|
||||||
|
|
||||||
TileBit
|
|
||||||
continueTileDrag( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
|
||||||
{
|
|
||||||
TileDragState* state = &board->tileDragState;
|
|
||||||
TileBit overTile = 0;
|
|
||||||
XP_S16 index = pointToTileIndex( board, x, y, (XP_Bool*)NULL );
|
|
||||||
|
|
||||||
if ( index >= 0 ) {
|
|
||||||
|
|
||||||
overTile = 1 << index;
|
|
||||||
|
|
||||||
if ( overTile != state->prevIndex ) {
|
|
||||||
|
|
||||||
moveTileInTray( board, overTile, state->prevIndex );
|
|
||||||
|
|
||||||
state->movePending = XP_FALSE;
|
|
||||||
state->wasHilited = XP_FALSE; // so we won't deselect
|
|
||||||
state->prevIndex = board->traySelBits[board->selPlayer] = overTile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return overTile;
|
|
||||||
} /* continueTileDrag */
|
|
||||||
|
|
||||||
XP_U16
|
XP_U16
|
||||||
indexForBits( XP_U8 bits )
|
indexForBits( XP_U8 bits )
|
||||||
{
|
{
|
||||||
|
@ -455,123 +417,48 @@ indexForBits( XP_U8 bits )
|
||||||
return result;
|
return result;
|
||||||
} /* indexForBits */
|
} /* indexForBits */
|
||||||
|
|
||||||
static XP_Bool
|
|
||||||
endTileDragIndex( BoardCtxt* board, TileBit last )
|
|
||||||
{
|
|
||||||
XP_Bool result = XP_FALSE;
|
|
||||||
XP_U16 selPlayer = board->selPlayer;
|
|
||||||
|
|
||||||
TileDragState* state = &board->tileDragState;
|
|
||||||
|
|
||||||
if ( state->movePending ) { /* no drag took place */
|
|
||||||
|
|
||||||
if ( state->wasHilited ) { /* if the user just clicked; deselect */
|
|
||||||
board_invalTrayTiles( board, state->selectionAtStart );
|
|
||||||
board->traySelBits[selPlayer] = NO_TILES;
|
|
||||||
result = XP_TRUE;
|
|
||||||
} else if ( (last > 0)
|
|
||||||
&& !board->boardArrow[selPlayer].visible
|
|
||||||
&& (state->selectionAtStart != NO_TILES ) ) {
|
|
||||||
|
|
||||||
if ( model_getCurrentMoveCount( board->model, selPlayer) == 0 ) {
|
|
||||||
moveTileInTray( board, last, state->selectionAtStart );
|
|
||||||
board->traySelBits[selPlayer] = NO_TILES;
|
|
||||||
} else {
|
|
||||||
board_invalTrayTiles(
|
|
||||||
board,
|
|
||||||
(TileBit)(state->selectionAtStart|last) );
|
|
||||||
board->traySelBits[selPlayer] = last;
|
|
||||||
}
|
|
||||||
result = XP_TRUE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
board_invalTrayTiles( board, state->prevIndex );
|
|
||||||
board->traySelBits[selPlayer] = NO_TILES;
|
|
||||||
result = XP_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->dragInProgress = XP_FALSE;
|
|
||||||
return result;
|
|
||||||
} /* endTileDragIndex */
|
|
||||||
|
|
||||||
XP_Bool
|
XP_Bool
|
||||||
endTileDrag( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
|
||||||
{
|
|
||||||
TileBit newTile = continueTileDrag( board, x, y );
|
|
||||||
return endTileDragIndex( board, newTile );
|
|
||||||
} /* endTileDrag */
|
|
||||||
|
|
||||||
static XP_Bool
|
|
||||||
startDividerDrag( BoardCtxt* board )
|
|
||||||
{
|
|
||||||
board->divDragState.dragInProgress = XP_TRUE;
|
|
||||||
board->dividerInvalid = XP_TRUE;
|
|
||||||
return XP_TRUE;
|
|
||||||
} /* startDividerDrag */
|
|
||||||
|
|
||||||
static void
|
|
||||||
dividerMoved( BoardCtxt* board, XP_U8 newLoc )
|
dividerMoved( BoardCtxt* board, XP_U8 newLoc )
|
||||||
{
|
{
|
||||||
XP_U8 oldLoc = board->dividerLoc[board->selPlayer];
|
XP_U8 oldLoc = board->dividerLoc[board->selPlayer];
|
||||||
board->dividerLoc[board->selPlayer] = newLoc;
|
XP_Bool moved = oldLoc != newLoc;
|
||||||
|
if ( moved ) {
|
||||||
|
board->dividerLoc[board->selPlayer] = newLoc;
|
||||||
|
|
||||||
/* This divider's index corresponds to the tile it's to the left of, and
|
/* This divider's index corresponds to the tile it's to the left of, and
|
||||||
there's no need to invalidate any tiles to the left of the uppermore
|
there's no need to invalidate any tiles to the left of the uppermore
|
||||||
divider position. */
|
divider position. */
|
||||||
if ( oldLoc > newLoc ) {
|
if ( oldLoc > newLoc ) {
|
||||||
--oldLoc;
|
--oldLoc;
|
||||||
} else {
|
} else {
|
||||||
--newLoc;
|
--newLoc;
|
||||||
|
}
|
||||||
|
invalTrayTilesBetween( board, newLoc, oldLoc );
|
||||||
|
|
||||||
|
board->dividerInvalid = XP_TRUE;
|
||||||
|
/* changed number of available tiles */
|
||||||
|
board_resetEngine( board );
|
||||||
}
|
}
|
||||||
invalTrayTilesBetween( board, newLoc, oldLoc );
|
return moved;
|
||||||
|
|
||||||
board->dividerInvalid = XP_TRUE;
|
|
||||||
/* changed number of available tiles */
|
|
||||||
board_resetEngine( board );
|
|
||||||
} /* dividerMoved */
|
} /* dividerMoved */
|
||||||
|
|
||||||
XP_Bool
|
|
||||||
continueDividerDrag( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
|
||||||
{
|
|
||||||
XP_U8 newOffset;
|
|
||||||
XP_U16 trayScale = board->trayScaleH;
|
|
||||||
XP_Bool result = XP_FALSE;
|
|
||||||
|
|
||||||
XP_ASSERT( board->divDragState.dragInProgress );
|
|
||||||
|
|
||||||
/* Pen might have been dragged out of the tray */
|
|
||||||
if ( rectContainsPt( &board->trayBounds, x, y ) ) {
|
|
||||||
x -= board->trayBounds.left;
|
|
||||||
newOffset = x / trayScale;
|
|
||||||
if ( (x % trayScale) > (trayScale/2) ) {
|
|
||||||
++newOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = newOffset != board->dividerLoc[board->selPlayer];
|
|
||||||
if ( result ) {
|
|
||||||
dividerMoved( board, newOffset );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} /* continueDividerDrag */
|
|
||||||
|
|
||||||
XP_Bool
|
|
||||||
endDividerDrag( BoardCtxt* board, XP_U16 x, XP_U16 y )
|
|
||||||
{
|
|
||||||
XP_Bool result = XP_TRUE; /* b/c hilited state looks different */
|
|
||||||
(void)continueDividerDrag( board, x, y );
|
|
||||||
board->dividerInvalid = XP_TRUE;
|
|
||||||
board->divDragState.dragInProgress = XP_FALSE;
|
|
||||||
return result;
|
|
||||||
} /* endDividerDrag */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
board_invalTrayTiles( BoardCtxt* board, TileBit what )
|
board_invalTrayTiles( BoardCtxt* board, TileBit what )
|
||||||
{
|
{
|
||||||
board->trayInvalBits |= what;
|
board->trayInvalBits |= what;
|
||||||
} /* invalTrayTiles */
|
} /* invalTrayTiles */
|
||||||
|
|
||||||
static void
|
void
|
||||||
|
invalTrayTilesAbove( BoardCtxt* board, XP_U16 tileIndex )
|
||||||
|
{
|
||||||
|
TileBit bits = 0;
|
||||||
|
while ( tileIndex < MAX_TRAY_TILES ) {
|
||||||
|
bits |= 1 << tileIndex++;
|
||||||
|
}
|
||||||
|
board_invalTrayTiles( board, bits );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
invalTrayTilesBetween( BoardCtxt* board, XP_U16 tileIndex1,
|
invalTrayTilesBetween( BoardCtxt* board, XP_U16 tileIndex1,
|
||||||
XP_U16 tileIndex2 )
|
XP_U16 tileIndex2 )
|
||||||
{
|
{
|
||||||
|
@ -710,7 +597,7 @@ board_moveDivider( BoardCtxt* board, XP_Bool right )
|
||||||
loc += right? 1:-1;
|
loc += right? 1:-1;
|
||||||
loc %= MAX_TRAY_TILES + 1;
|
loc %= MAX_TRAY_TILES + 1;
|
||||||
|
|
||||||
dividerMoved( board, loc );
|
(void)dividerMoved( board, loc );
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} /* board_moveDivider */
|
} /* board_moveDivider */
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* -*- mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE"; -*- */
|
/* -*- mode: C; fill-column: 78; c-basic-offset: 4; compile-command: "make MEMDEBUG=TRUE"; -*- */
|
||||||
/*
|
/*
|
||||||
* Copyright 1997-2007 by Eric House (xwords@eehouse.org). All rights reserved.
|
* Copyright 1997-2008 by Eric House (xwords@eehouse.org). All rights
|
||||||
|
* reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -71,7 +72,7 @@ eraseRect( GtkDrawCtx* dctx, const XP_Rect* rect )
|
||||||
} /* eraseRect */
|
} /* eraseRect */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
frameRect( GtkDrawCtx* dctx, XP_Rect* rect )
|
frameRect( GtkDrawCtx* dctx, const XP_Rect* rect )
|
||||||
{
|
{
|
||||||
gdk_draw_rectangle( DRAW_WHAT(dctx),
|
gdk_draw_rectangle( DRAW_WHAT(dctx),
|
||||||
dctx->drawGC, FALSE, rect->left, rect->top,
|
dctx->drawGC, FALSE, rect->left, rect->top,
|
||||||
|
@ -431,55 +432,46 @@ gtk_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* letter,
|
||||||
rect->height );
|
rect->height );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* draw the bonus colors only if we're not putting a "tile" there */
|
/* We draw just an empty, potentially colored, square IFF there's nothing
|
||||||
if ( !!letter ) {
|
in the cell or if CELL_DRAGSRC is set */
|
||||||
if ( *letter == LETTER_NONE && bonus != BONUS_NONE ) {
|
if ( (flags & CELL_DRAGSRC) != 0 || ( !!letter && *letter == LETTER_NONE ) ) {
|
||||||
XP_ASSERT( bonus <= 4 );
|
if ( bonus != BONUS_NONE ) {
|
||||||
|
|
||||||
gdk_gc_set_foreground( dctx->drawGC, &dctx->bonusColors[bonus-1] );
|
gdk_gc_set_foreground( dctx->drawGC, &dctx->bonusColors[bonus-1] );
|
||||||
gdk_draw_rectangle( DRAW_WHAT(dctx),
|
gdk_draw_rectangle( DRAW_WHAT(dctx), dctx->drawGC, TRUE,
|
||||||
dctx->drawGC,
|
|
||||||
TRUE,
|
|
||||||
rectInset.left, rectInset.top,
|
rectInset.left, rectInset.top,
|
||||||
rectInset.width+1, rectInset.height+1 );
|
rectInset.width+1, rectInset.height+1 );
|
||||||
|
}
|
||||||
|
if ( (flags & CELL_ISSTAR) != 0 ) {
|
||||||
|
draw_string_at( dctx, "*", rect->height, rect, XP_GTK_JUST_CENTER,
|
||||||
|
&dctx->black, NULL );
|
||||||
|
}
|
||||||
|
} else if ( !!letter ) {
|
||||||
|
GdkColor* foreground;
|
||||||
|
|
||||||
} else if ( *letter != LETTER_NONE ) {
|
if ( !highlight ) {
|
||||||
GdkColor* foreground;
|
gdk_gc_set_foreground( dctx->drawGC, &dctx->tileBack );
|
||||||
|
}
|
||||||
|
gdk_draw_rectangle( DRAW_WHAT(dctx), dctx->drawGC, TRUE,
|
||||||
|
rectInset.left, rectInset.top,
|
||||||
|
rectInset.width+1, rectInset.height+1 );
|
||||||
|
|
||||||
if ( !highlight ) {
|
foreground = highlight? &dctx->white : &dctx->playerColors[owner];
|
||||||
gdk_gc_set_foreground( dctx->drawGC, &dctx->tileBack );
|
draw_string_at( dctx, letter, rectInset.height-2, &rectInset,
|
||||||
}
|
XP_GTK_JUST_CENTER, foreground, NULL );
|
||||||
gdk_draw_rectangle( DRAW_WHAT(dctx),
|
|
||||||
dctx->drawGC,
|
|
||||||
TRUE,
|
|
||||||
rectInset.left, rectInset.top,
|
|
||||||
rectInset.width+1, rectInset.height+1 );
|
|
||||||
|
|
||||||
foreground = highlight? &dctx->white : &dctx->playerColors[owner];
|
if ( (flags & CELL_ISBLANK) != 0 ) {
|
||||||
draw_string_at( dctx, letter, rectInset.height-2,
|
gdk_draw_arc( DRAW_WHAT(dctx), dctx->drawGC,
|
||||||
&rectInset, XP_GTK_JUST_CENTER,
|
0, /* filled */
|
||||||
foreground, NULL );
|
rect->left, /* x */
|
||||||
|
rect->top, /* y */
|
||||||
if ( (flags & CELL_ISBLANK) != 0 ) {
|
rect->width,/*width, */
|
||||||
gdk_draw_arc( DRAW_WHAT(dctx), dctx->drawGC,
|
rect->height,/*width, */
|
||||||
0, /* filled */
|
0, 360*64 );
|
||||||
rect->left, /* x */
|
|
||||||
rect->top, /* y */
|
|
||||||
rect->width,/*width, */
|
|
||||||
rect->height,/*width, */
|
|
||||||
0, 360*64 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if ( !!bitmap ) {
|
} else if ( !!bitmap ) {
|
||||||
drawBitmapFromLBS( dctx, bitmap, rect );
|
drawBitmapFromLBS( dctx, bitmap, rect );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (flags & CELL_ISSTAR) != 0 ) {
|
|
||||||
draw_string_at( dctx, "*", rect->height,
|
|
||||||
rect, XP_GTK_JUST_CENTER,
|
|
||||||
&dctx->black, NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
drawHintBorders( dctx, rect, hintAtts );
|
drawHintBorders( dctx, rect, hintAtts );
|
||||||
|
|
||||||
if ( (flags & CELL_ISCURSOR) != 0 ) {
|
if ( (flags & CELL_ISCURSOR) != 0 ) {
|
||||||
|
@ -525,15 +517,18 @@ gtk_draw_trayBegin( DrawCtx* p_dctx, const XP_Rect* rect, XP_U16 owner,
|
||||||
} /* gtk_draw_trayBegin */
|
} /* gtk_draw_trayBegin */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_draw_drawTile( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* textP,
|
gtkDrawTileImpl( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* textP,
|
||||||
XP_Bitmap bitmap, XP_S16 val, CellFlags flags )
|
XP_Bitmap bitmap, XP_S16 val, CellFlags flags,
|
||||||
|
XP_Bool clearBack )
|
||||||
{
|
{
|
||||||
XP_UCHAR numbuf[3];
|
XP_UCHAR numbuf[3];
|
||||||
gint len;
|
gint len;
|
||||||
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
|
||||||
XP_Rect insetR = *rect;
|
XP_Rect insetR = *rect;
|
||||||
|
|
||||||
eraseRect( dctx, &insetR );
|
if ( clearBack ) {
|
||||||
|
eraseRect( dctx, &insetR );
|
||||||
|
}
|
||||||
|
|
||||||
if ( val >= 0 ) {
|
if ( val >= 0 ) {
|
||||||
GdkColor* foreground = &dctx->playerColors[dctx->trayOwner];
|
GdkColor* foreground = &dctx->playerColors[dctx->trayOwner];
|
||||||
|
@ -541,17 +536,18 @@ gtk_draw_drawTile( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* textP,
|
||||||
|
|
||||||
insetRect( &insetR, 1 );
|
insetRect( &insetR, 1 );
|
||||||
|
|
||||||
|
if ( clearBack ) {
|
||||||
|
gdk_gc_set_foreground( dctx->drawGC, &dctx->tileBack );
|
||||||
|
gdk_draw_rectangle( DRAW_WHAT(dctx),
|
||||||
|
dctx->drawGC,
|
||||||
|
XP_TRUE,
|
||||||
|
insetR.left, insetR.top, insetR.width,
|
||||||
|
insetR.height );
|
||||||
|
}
|
||||||
|
|
||||||
formatRect.left += 3;
|
formatRect.left += 3;
|
||||||
formatRect.width -= 6;
|
formatRect.width -= 6;
|
||||||
|
|
||||||
gdk_gc_set_foreground( dctx->drawGC, &dctx->tileBack );
|
|
||||||
gdk_draw_rectangle( DRAW_WHAT(dctx),
|
|
||||||
dctx->drawGC,
|
|
||||||
TRUE,
|
|
||||||
insetR.left, insetR.top, insetR.width,
|
|
||||||
insetR.height );
|
|
||||||
|
|
||||||
|
|
||||||
if ( !!textP ) {
|
if ( !!textP ) {
|
||||||
if ( *textP != LETTER_NONE ) { /* blank */
|
if ( *textP != LETTER_NONE ) { /* blank */
|
||||||
draw_string_at( dctx, textP, formatRect.height>>1,
|
draw_string_at( dctx, textP, formatRect.height>>1,
|
||||||
|
@ -593,6 +589,25 @@ gtk_draw_drawTile( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* textP,
|
||||||
|
|
||||||
} /* gtk_draw_drawTile */
|
} /* gtk_draw_drawTile */
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_draw_drawTile( DrawCtx* p_dctx, const XP_Rect* rect, const XP_UCHAR* textP,
|
||||||
|
XP_Bitmap bitmap, XP_S16 val, CellFlags flags )
|
||||||
|
{
|
||||||
|
gtkDrawTileImpl( p_dctx, rect, textP, bitmap, val, flags, XP_TRUE );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef POINTER_SUPPORT
|
||||||
|
static void
|
||||||
|
gtk_draw_drawTileMidDrag( DrawCtx* p_dctx, const XP_Rect* rect,
|
||||||
|
const XP_UCHAR* textP, XP_Bitmap bitmap,
|
||||||
|
XP_S16 val, CellFlags flags )
|
||||||
|
{
|
||||||
|
gtkDrawTileImpl( p_dctx, rect, textP, bitmap, val,
|
||||||
|
flags | CELL_HIGHLIGHT,
|
||||||
|
XP_FALSE );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_draw_drawTileBack( DrawCtx* p_dctx, const XP_Rect* rect,
|
gtk_draw_drawTileBack( DrawCtx* p_dctx, const XP_Rect* rect,
|
||||||
CellFlags flags )
|
CellFlags flags )
|
||||||
|
@ -635,7 +650,7 @@ gtk_draw_drawTrayDivider( DrawCtx* p_dctx, const XP_Rect* rect,
|
||||||
++r.left;
|
++r.left;
|
||||||
r.width -= selected? 2:1;
|
r.width -= selected? 2:1;
|
||||||
if ( selected ) {
|
if ( selected ) {
|
||||||
--r.height;
|
--r.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
gdk_gc_set_foreground( dctx->drawGC, &dctx->black );
|
gdk_gc_set_foreground( dctx->drawGC, &dctx->black );
|
||||||
|
@ -1030,6 +1045,9 @@ gtkDrawCtxtMake( GtkWidget* drawing_area, GtkAppGlobals* globals )
|
||||||
SET_VTABLE_ENTRY( dctx->vtable, draw_trayBegin, gtk );
|
SET_VTABLE_ENTRY( dctx->vtable, draw_trayBegin, gtk );
|
||||||
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTile, gtk );
|
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTile, gtk );
|
||||||
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTileBack, gtk );
|
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTileBack, gtk );
|
||||||
|
#ifdef POINTER_SUPPORT
|
||||||
|
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTileMidDrag, gtk );
|
||||||
|
#endif
|
||||||
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTrayDivider, gtk );
|
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTrayDivider, gtk );
|
||||||
|
|
||||||
SET_VTABLE_ENTRY( dctx->vtable, draw_drawBoardArrow, gtk );
|
SET_VTABLE_ENTRY( dctx->vtable, draw_drawBoardArrow, gtk );
|
||||||
|
|
|
@ -108,12 +108,13 @@ button_press_event( GtkWidget* XP_UNUSED(widget), GdkEventButton *event,
|
||||||
{
|
{
|
||||||
XP_Bool redraw, handled;
|
XP_Bool redraw, handled;
|
||||||
|
|
||||||
globals->mouseDown = XP_TRUE;
|
if ( !globals->mouseDown ) {
|
||||||
|
globals->mouseDown = XP_TRUE;
|
||||||
redraw = board_handlePenDown( globals->cGlobals.game.board,
|
redraw = board_handlePenDown( globals->cGlobals.game.board,
|
||||||
event->x, event->y, &handled );
|
event->x, event->y, &handled );
|
||||||
if ( redraw ) {
|
if ( redraw ) {
|
||||||
board_draw( globals->cGlobals.game.board );
|
board_draw( globals->cGlobals.game.board );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
} /* button_press_event */
|
} /* button_press_event */
|
||||||
|
|
Loading…
Add table
Reference in a new issue