Lots of progress on one-handed navigation: add gadgets to stand in for board

scoreboard and tray on palm; make center drill into the focussed object and
spacebar come back up then move the focus among them.  Integrate with other
focussable objects on main form.  Go from separate drawCursor routines to
same for all three, with cursor only visible when focus is drilled down.
On curses, add a hilite rect routine that can be called after text is laid
down, and use for cursors.
This commit is contained in:
ehouse 2006-11-03 06:23:54 +00:00
parent 02b45a156c
commit b0102f8baa
17 changed files with 657 additions and 281 deletions

View file

@ -60,6 +60,7 @@
#include "LocalizedStrIncludes.h"
#include "boardp.h"
#include "dbgutil.h"
#define bEND 0x62454e44
@ -76,11 +77,11 @@ static XP_Bool drawCell( BoardCtxt* board, XP_U16 col, XP_U16 row,
XP_Bool skipBlanks );
static void figureBoardRect( BoardCtxt* board );
static void drawBoard( BoardCtxt* board );
static void drawTimer( BoardCtxt* board );
static void drawScoreBoard( BoardCtxt* board );
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 );
@ -123,6 +124,7 @@ static XP_Bool moveKeyTileToBoard( BoardCtxt* board, XP_Key cursorKey );
#ifdef KEYBOARD_NAV
static XP_Bool moveScoreCursor( BoardCtxt* board, XP_Key key );
static XP_Bool board_moveCursor( BoardCtxt* board, XP_Key cursorKey );
static XP_Bool invalFocusOwner( BoardCtxt* board );
#endif
#ifdef XWFEATURE_SEARCHLIMIT
static HintAtts figureHintAtts( BoardCtxt* board, XP_U16 col, XP_U16 row );
@ -874,18 +876,25 @@ board_formatRemainingTiles( BoardCtxt* board, XWStreamCtxt* stream )
server_formatRemainingTiles( board->server, stream, curPlayer );
} /* board_formatRemainingTiles */
void
board_invalAll( BoardCtxt* board )
static void
board_invalAllTiles( BoardCtxt* board )
{
XP_U16 lastRow = model_numRows( board->model );
while ( lastRow-- ) {
board->redrawFlags[lastRow] = ~0;
}
board->tradingMiniWindowInvalid = XP_TRUE;
board->needsDrawing = XP_TRUE;
} /* board_invalAllTiles */
void
board_invalAll( BoardCtxt* board )
{
board_invalAllTiles( board );
board_invalTrayTiles( board, ALLTILES );
board->dividerInvalid = XP_TRUE;
board->tradingMiniWindowInvalid = XP_TRUE;
board->scoreBoardInvalid = XP_TRUE;
} /* board_invalAll */
@ -1037,97 +1046,101 @@ board_draw( BoardCtxt* board )
drawScoreBoard( board );
drawTray( board, board->focussed==OBJ_TRAY );
drawTray( board );
if ( board->needsDrawing
&& draw_boardBegin( board->draw,
model_getDictionary( board->model ),
&board->boardBounds,
board->focussed == OBJ_BOARD ) ) {
XP_Bool allDrawn = XP_TRUE;
XP_S16 lastCol, i;
XP_S16 row;
ModelCtxt* model = board->model;
BlankQueue bq;
scrollIfCan( board ); /* this must happen before we count blanks
since it invalidates squares */
model_listPlacedBlanks( model, board->selPlayer,
board->trayVisState == TRAY_REVEALED, &bq );
invalBlanksWithNeighbors( board, &bq );
/* Don't try to optimize this using lastVisibleRow etc. If the
board is flipped, "lastVisibleRow" here is really col.
redrawFlags is at the model level, pre-flip. */
for ( row = model_numRows(model) - 1; row >= 0; --row ) {
XP_U16 rowFlags = board->redrawFlags[row];
if ( rowFlags != 0 ) {
XP_U16 colMask;
XP_U16 failedBits = 0;
lastCol = model_numCols( model );
for ( colMask = 1<<(lastCol-1); lastCol--; colMask >>= 1 ) {
if ( (rowFlags & colMask) != 0 ) {
if ( !drawCell( board, lastCol, row, XP_TRUE )) {
failedBits |= colMask;
allDrawn = XP_FALSE;
}
}
}
board->redrawFlags[row] = failedBits;
}
}
/* draw the blanks we skipped before */
for ( i = 0; i < bq.nBlanks; ++i ) {
if ( !drawCell( board, bq.col[i], bq.row[i], XP_FALSE ) ) {
allDrawn = XP_FALSE;
}
}
if ( board->trayVisState == TRAY_REVEALED ) {
XP_Rect cursorRect;
BoardArrow* arrow = &board->boardArrow[board->selPlayer];
if ( arrow->visible ) {
XP_U16 col = arrow->col;
XP_U16 row = arrow->row;
XP_Bool drawVertical =
(arrow->vert == XP_CURSOR_KEY_DOWN) ^ board->isFlipped;
if ( getCellRect( board, col, row, &cursorRect ) ) {
XWBonusType bonus;
HintAtts hintAtts;
bonus = util_getSquareBonus( board->util, model,
col, row );
hintAtts = figureHintAtts( board, col, row );
draw_drawBoardArrow( board->draw, &cursorRect,
bonus, drawVertical, hintAtts );
}
}
#ifdef KEYBOARD_NAV
{
BdCursorLoc loc = board->bdCursor[board->selPlayer];
if ( getCellRect( board, loc.col, loc.row, &cursorRect ) ) {
draw_drawBoardCursor( board->draw, &cursorRect );
}
}
#endif
}
drawTradeWindowIf( board );
draw_boardFinished( board->draw );
board->needsDrawing = !allDrawn;
}
/* drawTray( board, board->focussed==OBJ_TRAY ); */
drawBoard( board );
}
return !board->needsDrawing;
} /* board_draw */
static void
drawBoard( BoardCtxt* board )
{
if ( board->needsDrawing
&& draw_boardBegin( board->draw,
model_getDictionary( board->model ),
&board->boardBounds,
dfsFor( board, OBJ_BOARD ) ) ) {
XP_Bool allDrawn = XP_TRUE;
XP_S16 lastCol, i;
XP_S16 row;
ModelCtxt* model = board->model;
BlankQueue bq;
XP_Rect cursorRect;
scrollIfCan( board ); /* this must happen before we count blanks
since it invalidates squares */
model_listPlacedBlanks( model, board->selPlayer,
board->trayVisState == TRAY_REVEALED, &bq );
invalBlanksWithNeighbors( board, &bq );
/* Don't try to optimize this using lastVisibleRow etc. If the
board is flipped, "lastVisibleRow" here is really col.
redrawFlags is at the model level, pre-flip. */
for ( row = model_numRows(model) - 1; row >= 0; --row ) {
XP_U16 rowFlags = board->redrawFlags[row];
if ( rowFlags != 0 ) {
XP_U16 colMask;
XP_U16 failedBits = 0;
lastCol = model_numCols( model );
for ( colMask = 1<<(lastCol-1); lastCol--; colMask >>= 1 ) {
if ( (rowFlags & colMask) != 0 ) {
if ( !drawCell( board, lastCol, row, XP_TRUE )) {
failedBits |= colMask;
allDrawn = XP_FALSE;
}
}
}
board->redrawFlags[row] = failedBits;
}
}
/* draw the blanks we skipped before */
for ( i = 0; i < bq.nBlanks; ++i ) {
if ( !drawCell( board, bq.col[i], bq.row[i], XP_FALSE ) ) {
allDrawn = XP_FALSE;
}
}
if ( board->trayVisState == TRAY_REVEALED ) {
BoardArrow* arrow = &board->boardArrow[board->selPlayer];
if ( arrow->visible ) {
XP_U16 col = arrow->col;
XP_U16 row = arrow->row;
XP_Bool drawVertical =
(arrow->vert == XP_CURSOR_KEY_DOWN) ^ board->isFlipped;
if ( getCellRect( board, col, row, &cursorRect ) ) {
XWBonusType bonus;
HintAtts hintAtts;
bonus = util_getSquareBonus( board->util, model,
col, row );
hintAtts = figureHintAtts( board, col, row );
draw_drawBoardArrow( board->draw, &cursorRect,
bonus, drawVertical, hintAtts );
}
}
}
#ifdef KEYBOARD_NAV
if ( board->focussed == OBJ_BOARD && board->focusHasDived ) {
BdCursorLoc loc = board->bdCursor[board->selPlayer];
if ( getCellRect( board, loc.col, loc.row, &cursorRect ) ){
draw_drawCursor( board->draw, OBJ_BOARD, &cursorRect );
}
}
#endif
drawTradeWindowIf( board );
draw_boardFinished( board->draw );
board->needsDrawing = !allDrawn;
}
} /* drawBoard */
static XP_S16
figureSecondsLeft( BoardCtxt* board )
{
@ -1185,9 +1198,12 @@ drawScoreBoard( BoardCtxt* board )
DrawScoreData datum[MAX_NUM_PLAYERS];
XP_S16 scores[MAX_NUM_PLAYERS];
XP_Bool isVertical = !board->scoreSplitHor;
draw_scoreBegin( board->draw, &board->scoreBdBounds, nPlayers,
board->focussed==OBJ_SCORE );
#ifdef KEYBOARD_NAV
XP_Rect cursorRect;
XP_Rect* cursorRectP = NULL;
#endif
draw_scoreBegin( board->draw, &board->scoreBdBounds, nPlayers,
dfsFor( board, OBJ_SCORE ) );
/* Let platform decide whether the rem: string should be given any
space once there are no tiles left. On Palm that space is
@ -1277,9 +1293,23 @@ drawScoreBoard( BoardCtxt* board )
draw_score_drawPlayer( board->draw, &innerRect, &scoreRect,
&dp->dsi );
#ifdef KEYBOARD_NAV
if ( i == board->scoreCursorLoc
&& board->focussed == OBJ_SCORE
&& board->focusHasDived ) {
cursorRect = scoreRect;
cursorRectP = &cursorRect;
}
#endif
*adjustPt += *adjustDim;
}
#ifdef KEYBOARD_NAV
if ( !!cursorRectP ) {
draw_drawCursor( board->draw, OBJ_SCORE, cursorRectP );
}
#endif
draw_scoreFinished( board->draw );
}
@ -1289,6 +1319,24 @@ drawScoreBoard( BoardCtxt* board )
drawTimer( board );
} /* drawScoreBoard */
#ifdef KEYBOARD_NAV
DrawFocusState
dfsFor( BoardCtxt* board, BoardObjectType obj )
{
DrawFocusState dfs;
if ( board->focussed == obj ) {
if ( board->focusHasDived ) {
dfs = DFS_DIVED;
} else {
dfs = DFS_TOP;
}
} else {
dfs = DFS_NONE;
}
return dfs;
} /* dfsFor */
#endif
void
board_setTrayLoc( BoardCtxt* board, XP_U16 trayLeft, XP_U16 trayTop,
XP_U16 trayWidth, XP_U16 trayHeight,
@ -1882,13 +1930,22 @@ invalCell( BoardCtxt* board, XP_U16 col, XP_U16 row )
static XP_Bool
focusNext( BoardCtxt* board )
{
short numHolders = 3; /* board */
short tmp = (short)board->focussed; /* avoid franklin casting crap */
BoardObjectType typ;
switch ( board->focussed ) {
case OBJ_SCORE:
typ = OBJ_BOARD;
break;
case OBJ_BOARD:
typ = OBJ_TRAY;
break;
case OBJ_TRAY:
case OBJ_NONE:
typ = OBJ_SCORE;
break;
}
tmp %= numHolders;
board->focussed = (BoardObjectType)(tmp + 1); /* skip OBJ_NONE */
return numHolders > 1;
board->focussed = typ;
return XP_TRUE;
} /* focusNext */
#endif
@ -2663,13 +2720,14 @@ board_handleKey( BoardCtxt* board, XP_Key key )
case XP_CURSOR_KEY_UP:
case XP_CURSOR_KEY_LEFT:
case XP_CURSOR_KEY_RIGHT:
if ( board->focussed == OBJ_BOARD ) {
result = trayVisible && board_moveCursor( board,
flipKey(board,key) );
} else if ( board->focussed == OBJ_SCORE ) {
result = moveScoreCursor( board, key );
} else if ( trayVisible && board->focussed == OBJ_TRAY ) {
result = tray_moveCursor( board, key );
if ( board->focusHasDived ) {
if ( board->focussed == OBJ_BOARD ) {
result = board_moveCursor( board, flipKey( board, key ) );
} else if ( board->focussed == OBJ_SCORE ) {
result = moveScoreCursor( board, key );
} else if ( board->focussed == OBJ_TRAY ) {
result = tray_moveCursor( board, key );
}
}
break;
#endif
@ -2683,27 +2741,40 @@ board_handleKey( BoardCtxt* board, XP_Key key )
#ifdef KEYBOARD_NAV
case XP_FOCUSCHANGE_KEY:
if ( focusNext( board ) ) {
board_invalAll( board ); /* really just want to inval borders! */
result = XP_TRUE;
invalFocusOwner( board );
if ( board->focusHasDived ) {
board->focusHasDived = XP_FALSE; /* come back up */
} else if ( focusNext( board ) ) {
invalFocusOwner( board );
}
result = XP_TRUE;
break;
case XP_RETURN_KEY:
if ( board->focussed == OBJ_TRAY ) {
if ( trayVisible ) {
result = tray_keyAction( board );
} else {
result = askRevealTray( board );
}
} else if ( board->focussed == OBJ_BOARD ) {
/* mimic pen-down/pen-up on cursor */
BdCursorLoc loc = board->bdCursor[board->selPlayer];
result = handleActionInCell( board, loc.col, loc.row );
} else if ( board->focussed == OBJ_SCORE ) {
/* tap on what's already selected: reveal tray, etc. */
board_selectPlayer( board, board->selPlayer );
result = XP_TRUE;
if ( board->focusHasDived ) {
result = XP_TRUE; /* even if don't draw, we handle it!! */
if ( board->focussed == OBJ_TRAY ) {
if ( trayVisible ) {
(void)tray_keyAction( board );
} else {
(void)askRevealTray( board );
}
} else if ( board->focussed == OBJ_BOARD ) {
/* mimic pen-down/pen-up on cursor */
if ( trayVisible ) {
BdCursorLoc loc = board->bdCursor[board->selPlayer];
(void)handleActionInCell( board, loc.col, loc.row );
} else {
askRevealTray( board );
}
} else if ( board->focussed == OBJ_SCORE ) {
/* tap on what's already selected: reveal tray, etc. */
board_selectPlayer( board, board->scoreCursorLoc );
}
} else if ( board->focussed != OBJ_NONE ) {
board->focusHasDived = XP_TRUE;
board_invalAll( board ); /* just want to inval borders! */
result = XP_TRUE;
}
break;
#endif
@ -2721,8 +2792,88 @@ board_handleKey( BoardCtxt* board, XP_Key key )
return result;
} /* board_handleKey */
/* used by curses version only! */
#ifdef KEYBOARD_NAV
static XP_Bool
invalFocusOwner( BoardCtxt* board )
{
XP_Bool draw = XP_TRUE;
XP_S16 selPlayer = board->selPlayer;
switch( board->focussed ) {
case OBJ_SCORE:
board->scoreBoardInvalid = XP_TRUE;
break;
case OBJ_BOARD:
if ( board->focusHasDived ) {
BdCursorLoc loc = board->bdCursor[selPlayer];
invalCell( board, loc.col, loc.row );
} else {
board_invalAllTiles( board );
}
break;
case OBJ_TRAY:
if ( board->focusHasDived ) {
XP_U16 loc = board->trayCursorLoc[selPlayer];
board_invalTrayTiles( board, 1 << loc );
} else {
board_invalTrayTiles( board, ALLTILES );
board->dividerInvalid = XP_TRUE;
}
break;
default: /* for compiler */
draw = XP_FALSE;
break;
}
board->needsDrawing = draw;
return draw;
} /* invalFocusOwner */
XP_Bool
board_focusChanged( BoardCtxt* board, BoardObjectType typ, XP_Bool gained )
{
XP_Bool draw = XP_FALSE;
LOG_FUNC();
/* Called when there's been a decision to advance the focus to a new
object, or when an object will lose it. Need to update internal data
structures, but also to communicate to client draw code in a way that
doesn't assume how it's representing focus.
Should pop focus to top on gaining it. Calling code should not be
seeing internal movement as focus events, but as key events we handle
One rule: each object must draw focus indicator entirely within its own
space. No interdependencies. So handling updating of focus indication
within the tray drawing process, for example, is ok.
Problem: on palm at least take and lost are inverted: you get a take on
the new object before a lose on the previous one. So we want to ignore
lost events *except* when it's a loss of something we have currently --
meaning the focus is moving to soemthing we don't control (a
platform-specific object)
*/
if ( gained ) {
/* Are we losing focus we currently have elsewhere? */
if ( typ != board->focussed ) {
draw = invalFocusOwner( board ) || draw;
}
board->focussed = typ;
XP_LOGF( "%s: set focussed to %d", __FUNCTION__, (int)typ );
draw = invalFocusOwner( board ) || draw;
board->focusHasDived = XP_FALSE;
} else {
/* we're losing it; inval and clear IFF we currently have same focus,
otherwise ignore */
if ( typ == board->focussed ) {
draw = invalFocusOwner( board ) || draw;
board->focussed = OBJ_NONE;
}
}
LOG_RETURNF( "%d", (int)draw );
return draw;
} /* board_focusChanged */
XP_Bool
board_toggle_arrowDir( BoardCtxt* board )
{
@ -2741,24 +2892,26 @@ moveScoreCursor( BoardCtxt* board, XP_Key key )
{
XP_Bool result = XP_TRUE;
XP_U16 nPlayers = board->gi->nPlayers;
XP_U16 selPlayer = board->selPlayer + nPlayers;
XP_U16 scoreCursorLoc = board->scoreCursorLoc + nPlayers;
switch ( key ) {
case XP_CURSOR_KEY_DOWN:
case XP_CURSOR_KEY_RIGHT:
++selPlayer;
++scoreCursorLoc;
break;
case XP_CURSOR_KEY_UP:
case XP_CURSOR_KEY_LEFT:
--selPlayer;
--scoreCursorLoc;
break;
default:
result = XP_FALSE;
}
board_selectPlayer( board, selPlayer % nPlayers );
board->scoreCursorLoc = scoreCursorLoc % nPlayers;
board->scoreBoardInvalid = XP_TRUE;
return result;
} /* moveScoreCursor */
#endif
#endif /* KEYBOARD_NAV */
static XP_Bool
advanceArrow( BoardCtxt* board )
@ -2785,61 +2938,58 @@ figureNextLoc( BoardCtxt* board, XP_Key cursorKey, XP_Bool canCycle,
/* XP_ASSERT( board->focussed == OBJ_BOARD ); */
/* don't allow cursor's jumps to reveal hidden tiles */
if ( board->trayVisState != TRAY_REVEALED || cursorKey == XP_KEY_NONE ) {
return XP_FALSE;
}
if ( cursorKey != XP_KEY_NONE ) {
numRows = model_numRows( board->model );
numCols = model_numCols( board->model );
numRows = model_numRows( board->model );
numCols = model_numCols( board->model );
switch ( cursorKey ) {
switch ( cursorKey ) {
case XP_CURSOR_KEY_DOWN:
incr = 1;
useWhat = (XP_S16*)rowP;
max = numRows;
end = max;
break;
case XP_CURSOR_KEY_UP:
incr = -1;
useWhat = (XP_S16*)rowP;
max = numRows;
end = -1;
break;
case XP_CURSOR_KEY_LEFT:
incr = -1;
useWhat = (XP_S16*)colP;
max = numCols;
end = -1;
break;
case XP_CURSOR_KEY_RIGHT:
incr = 1;
useWhat = (XP_S16*)colP;
max = numCols;
end = max;
break;
default:
XP_ASSERT( XP_FALSE );
return XP_FALSE;
}
XP_ASSERT( incr != 0 );
for ( counter = max; ; --counter ) {
*useWhat += incr;
if ( (counter == 0) || (!canCycle && (*useWhat == end)) ) {
result = XP_FALSE;
case XP_CURSOR_KEY_DOWN:
incr = 1;
useWhat = (XP_S16*)rowP;
max = numRows;
end = max;
break;
case XP_CURSOR_KEY_UP:
incr = -1;
useWhat = (XP_S16*)rowP;
max = numRows;
end = -1;
break;
case XP_CURSOR_KEY_LEFT:
incr = -1;
useWhat = (XP_S16*)colP;
max = numCols;
end = -1;
break;
case XP_CURSOR_KEY_RIGHT:
incr = 1;
useWhat = (XP_S16*)colP;
max = numCols;
end = max;
break;
default:
XP_ASSERT( XP_FALSE );
}
*useWhat = (*useWhat + max) % max;
XP_ASSERT( incr != 0 );
if ( !avoidOccupied
|| !cellOccupied( board, *colP, *rowP, XP_TRUE ) ) {
result = XP_TRUE;
break;
for ( counter = max; ; --counter ) {
*useWhat += incr;
if ( (counter == 0) || (!canCycle && (*useWhat == end)) ) {
break;
}
*useWhat = (*useWhat + max) % max;
if ( !avoidOccupied
|| !cellOccupied( board, *colP, *rowP, XP_TRUE ) ) {
result = XP_TRUE;
break;
}
}
}
@ -3115,7 +3265,7 @@ boardTileChanged( void* p_board, XP_U16 turn, TileBit bits )
{
BoardCtxt* board = (BoardCtxt*)p_board;
if ( turn == board->selPlayer ) {
board_invalTrayTiles( board, bits );
board_invalTrayTiles( board, bits );
}
} /* boardTileChanged */

View file

@ -33,19 +33,6 @@
extern "C" {
#endif
typedef enum {
TRAY_HIDDEN, /* doesn't happen unless tray overlaps board */
TRAY_REVERSED,
TRAY_REVEALED
} XW_TrayVisState;
typedef enum {
OBJ_NONE,
OBJ_BOARD,
OBJ_SCORE,
OBJ_TRAY
} BoardObjectType;
typedef enum {
/* keep these three together: for the cursor */
XP_KEY_NONE,
@ -67,7 +54,7 @@ typedef enum {
BoardCtxt* board_make( MPFORMAL ModelCtxt* model, ServerCtxt* server,
DrawCtx* draw, XW_UtilCtxt* util );
DrawCtx* draw, XW_UtilCtxt* util );
BoardCtxt* board_makeFromStream( MPFORMAL XWStreamCtxt* stream,
ModelCtxt* model, ServerCtxt* server,
DrawCtx* draw, XW_UtilCtxt* util,
@ -138,6 +125,8 @@ XP_Bool board_handleKey( BoardCtxt* board, XP_Key key );
#ifdef KEYBOARD_NAV
/* void board_focusChange( BoardCtxt* board ); */
XP_Bool board_focusChanged( BoardCtxt* board, BoardObjectType typ,
XP_Bool gained );
XP_Bool board_toggle_arrowDir( BoardCtxt* board );
#endif

View file

@ -125,6 +125,7 @@ struct BoardCtxt {
BoardArrow boardArrow[MAX_NUM_PLAYERS];
#ifdef KEYBOARD_NAV
BdCursorLoc bdCursor[MAX_NUM_PLAYERS];
XP_Bool focusHasDived;
#endif
XP_U8 dividerLoc[MAX_NUM_PLAYERS]; /* 0 means left of 0th tile, etc. */
@ -154,6 +155,7 @@ struct BoardCtxt {
TileBit traySelBits[MAX_NUM_PLAYERS];
#ifdef KEYBOARD_NAV
XP_U8 trayCursorLoc[MAX_NUM_PLAYERS];
XP_U8 scoreCursorLoc;
#endif
XW_TrayVisState trayVisState;
@ -181,7 +183,7 @@ struct BoardCtxt {
/* 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 );
void drawTray( BoardCtxt* board, XP_Bool focussed );
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 );
@ -196,6 +198,9 @@ XP_Bool rectsIntersect( XP_Rect* rect1, XP_Rect* rect2 );
#ifdef KEYBOARD_NAV
XP_Bool tray_moveCursor( BoardCtxt* board, XP_Key cursorKey );
XP_Bool tray_keyAction( BoardCtxt* board );
DrawFocusState dfsFor( BoardCtxt* board, BoardObjectType obj );
#else
# define dfsFor( board, obj ) DFS_NONE
#endif
#ifdef CPLUS

View file

@ -61,6 +61,25 @@ typedef enum {
,TRI_ENAB_ENABLED
} XP_TriEnable;
typedef enum {
DFS_NONE
,DFS_TOP /* focus is on the object */
,DFS_DIVED /* focus is inside the object */
} DrawFocusState;
typedef enum {
TRAY_HIDDEN, /* doesn't happen unless tray overlaps board */
TRAY_REVERSED,
TRAY_REVEALED
} XW_TrayVisState;
typedef enum {
OBJ_NONE,
OBJ_BOARD,
OBJ_SCORE,
OBJ_TRAY
} BoardObjectType;
/* I'm going to try putting all forward "class" decls in the same file */
typedef struct BoardCtxt BoardCtxt;
typedef struct CommMgrCtxt CommMgrCtxt;

View file

@ -40,6 +40,7 @@ COMMONSRC = \
$(COMMONDIR)/movestak.c \
$(COMMONDIR)/strutils.c \
$(COMMONDIR)/vtabmgr.c \
$(COMMONDIR)/dbgutil.c \
# PENDING: define this in terms of above!!!
@ -69,5 +70,6 @@ COMMON5 = \
$(COMMONOBJDIR)/movestak.o \
$(COMMONOBJDIR)/strutils.o \
$(COMMONOBJDIR)/vtabmgr.o \
$(COMMONOBJDIR)/dbgutil.o \
COMMONOBJ = $(COMMON1) $(COMMON2) $(COMMON3) $(COMMON4) $(COMMON5)

View file

@ -96,7 +96,7 @@ typedef struct DrawCtxVTable {
XP_Bool DRAW_VTABLE_NAME(boardBegin) ( DrawCtx* dctx,
const DictionaryCtxt* dict,
const XP_Rect* rect,
XP_Bool hasfocus );
DrawFocusState dfs );
void DRAW_VTABLE_NAME(boardFinished) ( DrawCtx* dctx );
/* rect is not const: set by callee */
@ -104,7 +104,8 @@ typedef struct DrawCtxVTable {
XP_S16 dist );
XP_Bool DRAW_VTABLE_NAME(trayBegin) ( DrawCtx* dctx, const XP_Rect* rect,
XP_U16 owner, XP_Bool hasfocus );
XP_U16 owner,
DrawFocusState dfs );
void DRAW_VTABLE_NAME(trayFinished) ( DrawCtx* dctx );
void DRAW_VTABLE_NAME(measureRemText) ( DrawCtx* dctx, const XP_Rect* r,
@ -115,8 +116,7 @@ typedef struct DrawCtxVTable {
XP_S16 nTilesLeft);
void DRAW_VTABLE_NAME(scoreBegin) ( DrawCtx* dctx, const XP_Rect* rect,
XP_U16 numPlayers,
XP_Bool hasfocus );
XP_U16 numPlayers, DrawFocusState dfs );
void DRAW_VTABLE_NAME(measureScoreText) ( DrawCtx* dctx,
const XP_Rect* r,
const DrawScoreInfo* dsi,
@ -161,8 +161,8 @@ typedef struct DrawCtxVTable {
XWBonusType bonus, XP_Bool vert,
HintAtts hintAtts );
#ifdef KEY_SUPPORT
void DRAW_VTABLE_NAME(drawTrayCursor) ( DrawCtx* dctx, const XP_Rect* rect );
void DRAW_VTABLE_NAME(drawBoardCursor) ( DrawCtx* dctx, const XP_Rect* rect );
void DRAW_VTABLE_NAME(drawCursor) ( DrawCtx* dctx, BoardObjectType typ,
const XP_Rect* rect );
#endif
XP_UCHAR* DRAW_VTABLE_NAME(getMiniWText) ( DrawCtx* dctx,
@ -250,11 +250,9 @@ struct DrawCtx {
#define draw_drawBoardArrow( dc, r, b, v, h ) \
CALL_DRAW_NAME4(drawBoardArrow,(dc),(r),(b), (v), (h))
#ifdef KEY_SUPPORT
# define draw_drawTrayCursor( dc, r ) CALL_DRAW_NAME1(drawTrayCursor,(dc),(r))
# define draw_drawBoardCursor( dc, r ) CALL_DRAW_NAME1(drawBoardCursor,(dc),(r))
# define draw_drawCursor( dc, t, r ) CALL_DRAW_NAME2(drawCursor,(dc),(t),(r))
#else
# define draw_drawTrayCursor( dc, r )
# define draw_drawBoardCursor( dc, r )
# define draw_drawCursor( dc, t, r )
#endif
#define draw_getMiniWText( dc, b ) CALL_DRAW_NAME1(getMiniWText, (dc),(b) )

View file

@ -19,6 +19,7 @@
#include "boardp.h"
#include "engine.h"
#include "draw.h"
#include "strutils.h"
#ifdef CPLUS
@ -99,7 +100,7 @@ figureTrayTileRect( BoardCtxt* board, XP_U16 index, XP_Rect* rect )
} /* figureTileRect */
void
drawTray( BoardCtxt* board, XP_Bool focussed )
drawTray( BoardCtxt* board )
{
XP_Rect tileRect;
short i;
@ -108,7 +109,7 @@ drawTray( BoardCtxt* board, XP_Bool focussed )
XP_S16 turn = board->selPlayer;
if ( draw_trayBegin( board->draw, &board->trayBounds, turn,
focussed ) ) {
dfsFor( board, OBJ_TRAY ) ) ) {
DictionaryCtxt* dictionary = model_getDictionary( board->model );
if ( board->eraseTray ) {
@ -175,13 +176,15 @@ drawTray( BoardCtxt* board, XP_Bool focussed )
board->dividerInvalid = XP_FALSE;
}
drawPendingScore( board );
#ifdef KEYBOARD_NAV
if ( showFaces ) {
if ( board->focusHasDived && board->focussed == OBJ_TRAY ) {
TileBit cursorLoc = 1 << board->trayCursorLoc[turn];
if ( !!cursorLoc ) {
XP_U16 index = indexForBits( cursorLoc );
figureTrayTileRect( board, index, &tileRect );
draw_drawTrayCursor( board->draw, &tileRect );
draw_drawCursor( board->draw, OBJ_TRAY, &tileRect );
}
}
#endif
@ -193,7 +196,6 @@ drawTray( BoardCtxt* board, XP_Bool focussed )
}
}
drawPendingScore( board );
} /* drawTray */
static void

View file

@ -27,6 +27,13 @@
#include "draw.h"
#include "board.h"
typedef struct CursesDrawCtx {
DrawCtxVTable* vtable;
WINDOW* boardWin;
} CursesDrawCtx;
static void curses_draw_clearRect( DrawCtx* p_dctx, const XP_Rect* rectP );
static void
@ -52,49 +59,69 @@ eraseRect( CursesDrawCtx* dctx, const XP_Rect* rect )
}
} /* eraseRect */
static void
cursesHiliteRect( WINDOW* window, const XP_Rect* rect )
{
int right, width, x, y;
LOG_FUNC();
width = rect->width;
right = width + rect->left;
wstandout( window );
for ( y = rect->top; y < rect->top + rect->height; ++y ) {
for ( x = rect->left; x < right; ++x ) {
chtype cht = mvwinch( window, y, x );
char ch = cht & A_CHARTEXT;
mvwaddch( window, y, x, ch );
}
}
wstandend( window );
}
static void
curses_draw_destroyCtxt( DrawCtx* XP_UNUSED(p_dctx) )
{
// CursesDrawCtx* dctx = (CursesDrawCtx*)p_dctx;
} /* draw_setup */
static void
drawFocusRect( CursesDrawCtx* dctx, DrawFocusState dfs, const XP_Rect* rect )
{
WINDOW* boardWin = dctx->boardWin;
if ( dfs == DFS_NONE ) {
drawRect( boardWin, rect, '|', '-' );
} else if ( dfs == DFS_TOP ) {
drawRect( boardWin, rect, '*', '*' );
} else if ( dfs == DFS_DIVED ) {
drawRect( boardWin, rect, '+', '+' );
} else {
XP_ASSERT(0);
}
}
static XP_Bool
curses_draw_boardBegin( DrawCtx* p_dctx, const DictionaryCtxt* XP_UNUSED(dict),
const XP_Rect* rect, XP_Bool hasfocus )
const XP_Rect* rect, DrawFocusState dfs )
{
CursesDrawCtx* dctx = (CursesDrawCtx*)p_dctx;
if ( hasfocus ) {
drawRect( dctx->boardWin, rect, '+', '+' );
} else {
drawRect( dctx->boardWin, rect, '|', '-' );
}
drawFocusRect( dctx, dfs, rect );
return XP_TRUE;
} /* draw_finish */
static XP_Bool
curses_draw_trayBegin( DrawCtx* p_dctx, const XP_Rect* rect,
XP_U16 XP_UNUSED(owner), XP_Bool hasfocus )
XP_U16 XP_UNUSED(owner), DrawFocusState dfs )
{
CursesDrawCtx* dctx = (CursesDrawCtx*)p_dctx;
if ( hasfocus ) {
drawRect( dctx->boardWin, rect, '+', '+' );
} else {
drawRect( dctx->boardWin, rect, '|', '-' );
}
drawFocusRect( dctx, dfs, rect );
return XP_TRUE;
} /* draw_finish */
static void
curses_draw_scoreBegin( DrawCtx* p_dctx, const XP_Rect* rect,
XP_U16 XP_UNUSED(numPlayers), XP_Bool hasfocus )
XP_U16 XP_UNUSED(numPlayers), DrawFocusState dfs )
{
CursesDrawCtx* dctx = (CursesDrawCtx*)p_dctx;
if ( hasfocus ) {
drawRect( dctx->boardWin, rect, '+', '+' );
} else {
drawRect( dctx->boardWin, rect, '|', '-' );
}
drawFocusRect( dctx, dfs, rect );
} /* curses_draw_scoreBegin */
static void
@ -154,7 +181,9 @@ formatScoreText( XP_UCHAR* buf, const DrawScoreInfo* dsi )
label = toupper(label);
}
len = sprintf( buf, "%s[%c] %s (%d)", (dsi->isTurn?"->":" "),
len = sprintf( buf, "%c:%c [%c] %s (%d)",
(dsi->isTurn? 'T' : ' '),
(dsi->selected? 'S' : ' '),
label, dsi->name, nTilesLeft );
while ( len < SCORE_COL ) {
++len;
@ -236,20 +265,12 @@ curses_draw_score_drawPlayer( DrawCtx* p_dctx, const XP_Rect* rInner,
curses_draw_clearRect( p_dctx, rOuter );
if ( dsi->selected ) {
wstandout( dctx->boardWin );
}
/* first blank out the whole thing! */
mvwhline( dctx->boardWin, y, rOuter->left, ' ', rOuter->width );
/* print the name and turn/remoteness indicator */
formatScoreText( buf, dsi );
mvwprintw( dctx->boardWin, y, rOuter->left, buf );
if ( dsi->selected ) {
wstandend( dctx->boardWin );
}
/* (void)wcolor_set( dctx->boardWin, prev, NULL ); */
} /* curses_draw_score_drawPlayer */
static XP_Bool
@ -373,23 +394,13 @@ curses_draw_drawBoardArrow( DrawCtx* p_dctx, const XP_Rect* rect,
} /* curses_draw_drawBoardArrow */
static void
curses_draw_drawBoardCursor( DrawCtx* p_dctx, const XP_Rect* rect )
curses_draw_drawCursor( DrawCtx* p_dctx, BoardObjectType XP_UNUSED(typ),
const XP_Rect* rect )
{
CursesDrawCtx* dctx = (CursesDrawCtx*)p_dctx;
chtype curChar = mvwinch(dctx->boardWin, rect->top, rect->left );
wstandout( dctx->boardWin );
mvwaddch( dctx->boardWin, rect->top, rect->left, curChar);
wstandend( dctx->boardWin );
cursesHiliteRect( dctx->boardWin, rect );
} /* curses_draw_drawBoardCursor */
static void
curses_draw_drawTrayCursor( DrawCtx* p_dctx, const XP_Rect* rect )
{
CursesDrawCtx* dctx = (CursesDrawCtx*)p_dctx;
wmove( dctx->boardWin, rect->top, rect->left );
whline( dctx->boardWin, 'v', rect->width );
} /* curses_draw_drawTrayCursor */
static void
curses_draw_clearRect( DrawCtx* p_dctx, const XP_Rect* rectP )
{
@ -490,8 +501,7 @@ cursesDrawCtxtMake( WINDOW* boardWin )
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTrayDivider, curses );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawBoardArrow, curses );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawBoardCursor, curses );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawTrayCursor, curses );
SET_VTABLE_ENTRY( dctx->vtable, draw_drawCursor, curses );
SET_VTABLE_ENTRY( dctx->vtable, draw_clearRect, curses );

View file

@ -991,7 +991,7 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
signal( SIGWINCH, SIGWINCH_handler );
initCurses( &globals );
globals.draw = (CursesDrawCtx*)cursesDrawCtxtMake( globals.boardWin );
globals.draw = (struct CursesDrawCtx*)cursesDrawCtxtMake( globals.boardWin );
gameID = (XP_U16)util_getCurSeconds( globals.cGlobals.params->util );
game_makeNewGame( MEMPOOL &globals.cGlobals.game, &params->gi,

View file

@ -41,14 +41,6 @@
#include "util.h"
/* #include "compipe.h" */
typedef struct CursesDrawCtx {
DrawCtxVTable* vtable;
WINDOW* boardWin;
/* WINDOW* trayWin; */
} CursesDrawCtx;
typedef struct CursesAppGlobals CursesAppGlobals;
typedef XP_Bool (*EventFunc)(CursesAppGlobals* globals, int ch);
@ -62,7 +54,7 @@ typedef XP_Bool (*EventFunc)(CursesAppGlobals* globals, int ch);
struct CursesAppGlobals {
CommonGlobals cGlobals;
CursesDrawCtx* draw;
struct CursesDrawCtx* draw;
DictionaryCtxt* dictionary;
EngineCtxt* engine;

View file

@ -240,7 +240,7 @@ gtk_draw_destroyCtxt( DrawCtx* p_dctx )
static XP_Bool
gtk_draw_boardBegin( DrawCtx* p_dctx, const DictionaryCtxt* XP_UNUSED(dict),
const XP_Rect* rect, XP_Bool XP_UNUSED(hasfocus) )
const XP_Rect* rect, DrawFocusState XP_UNUSED(dfs) )
{
GdkRectangle gdkrect;
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
@ -402,7 +402,7 @@ gtk_draw_invertCell( DrawCtx* XP_UNUSED(p_dctx),
static XP_Bool
gtk_draw_trayBegin( DrawCtx* p_dctx, const XP_Rect* rect, XP_U16 owner,
XP_Bool XP_UNUSED(hasfocus) )
DrawFocusState XP_UNUSED(dfs) )
{
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;
XP_Rect clip = *rect;
@ -574,7 +574,7 @@ gtk_draw_drawBoardArrow( DrawCtx* p_dctx, const XP_Rect* rectP,
static void
gtk_draw_scoreBegin( DrawCtx* p_dctx, const XP_Rect* rect,
XP_U16 XP_UNUSED(numPlayers),
XP_Bool XP_UNUSED(hasfocus) )
DrawFocusState XP_UNUSED(dfs) )
{
GtkDrawCtx* dctx = (GtkDrawCtx*)p_dctx;

View file

@ -164,7 +164,7 @@ BITMAP_RSRCS = \
# INCLUDES += -I/usr/local/share/palmdev/sdk-5r3/Extensions/ExpansionMgr
INCLUDES += -I/usr/local/share/palmdev/sdk-5r3/include/Extensions/Bluetooth
XWFEATURE_FIVEWAY = -DXWFEATURE_FIVEWAY
XWFEATURE_FIVEWAY = -DXWFEATURE_FIVEWAY -DKEYBOARD_NAV
ifneq (x$(XWFEATURE_FIVEWAY)x, xx)
INCLUDES += -I/usr/local/share/palmdev/Handspring5

View file

@ -94,6 +94,11 @@ USABLE
NOFRAME
MENUID XW_MAIN_MENU_ID
BEGIN
#ifdef XWFEATURE_FIVEWAY
GADGET ID XW_SCOREBOARD_GADGET_ID AT (0 0 1 1) USABLE
GADGET ID XW_BOARD_GADGET_ID AT (0 0 1 1) USABLE
GADGET ID XW_TRAY_GADGET_ID AT (0 0 1 1) USABLE
#endif
BUTTON "" XW_MAIN_FLIP_BUTTON_ID
AT (PALM_FLIP_LEFT PALM_BOARD_TOP FLIP_BUTTON_WIDTH
FLIP_BUTTON_HEIGHT) NOFRAME
@ -136,9 +141,15 @@ NAVIGATION ID XW_MAIN_FORM
INITIALSTATE kFrmNavHeaderFlagsObjectFocusStartState
INITIALOBJECTID XW_MAIN_FLIP_BUTTON_ID
BEGIN
ID XW_SCOREBOARD_GADGET_ID
ID XW_BOARD_GADGET_ID
ID XW_MAIN_FLIP_BUTTON_ID
ID XW_MAIN_VALUE_BUTTON_ID
ID XW_MAIN_HINT_BUTTON_ID
ID XW_TRAY_GADGET_ID
ID XW_MAIN_SHOWTRAY_BUTTON_ID
ID XW_MAIN_HIDE_BUTTON_ID
ID XW_MAIN_JUGGLE_BUTTON_ID

View file

@ -1,4 +1,4 @@
/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */
/* -*-mode: C; fill-column: 77; c-basic-offset: 4; compile-command: "make ARCH=68K_ONLY MEMDEBUG=TRUE";-*- */
/*
* Copyright 1999 - 2001 by Eric House (xwords@eehouse.org). All rights reserved.
*
@ -19,8 +19,12 @@
#include <UIResources.h>
#include <SystemMgr.h>
#ifdef XWFEATURE_FIVEWAY
# include <Hs.h>
#endif
#include "draw.h"
#include "dbgutil.h"
#include "palmmain.h"
#include "xwords4defines.h"
@ -48,7 +52,7 @@ static void palm_bnw_draw_score_drawPlayer( DrawCtx* p_dctx,
const XP_Rect* rOuter,
const DrawScoreInfo* dsi );
static XP_Bool palm_bnw_draw_trayBegin( DrawCtx* p_dctx, const XP_Rect* rect,
XP_U16 owner, XP_Bool hasfocus );
XP_U16 owner, DrawFocusState dfs );
static void palm_bnw_draw_trayFinished( DrawCtx* p_dctx );
static void palm_clr_draw_clearRect( DrawCtx* p_dctx, const XP_Rect* rectP );
static void palm_draw_drawMiniWindow( DrawCtx* p_dctx, const XP_UCHAR* text,
@ -124,6 +128,65 @@ bitmapInRect( PalmDrawCtx* dctx, Int16 resID, const XP_Rect* rectP )
drawBitmapAt( (DrawCtx*)dctx, resID, left, top );
} /* bitmapInRect */
#ifdef KEYBOARD_NAV
#ifdef XWFEATURE_FIVEWAY
static void
drawFocusRect( PalmDrawCtx* dctx, const XP_Rect* rect )
{
XP_Rect r;
Err err;
PalmAppGlobals* globals = dctx->globals;
XP_ASSERT( dctx->doHiRes );
r.left = rect->left >> 1;
r.top = rect->top >> 1;
r.width = rect->width >> 1;
r.height = rect->height >> 1;
++r.height;
++r.width;
insetRect( &r, 3 ); /* draw inside the thing */
rect = &r;
XP_LOGF( "%s: HsNavDrawFocusRing at {%d,%d,%d,%d}", __FUNCTION__,
rect->left, rect->top, rect->width, rect->height );
err = HsNavDrawFocusRing( globals->mainForm, XW_SCOREBOARD_GADGET_ID, 0,
(RectangleType*)rect,
hsNavFocusRingStyleObjectTypeDefault, false );
/* XP_LOGF( "%s: HsNavDrawFocusRing => %x", __FUNCTION__, err ); */
}
#else
# define drawFocusRect( a, b )
#endif
static void
dfsDrawIf( PalmDrawCtx* dctx, BoardObjectType obj )
{
if ( dctx->topFocusObj == obj ) {
drawFocusRect( dctx, &dctx->topFocusRect );
dctx->topFocusObj = OBJ_NONE;
}
}
static void
dfsCopyIf( PalmDrawCtx* dctx, DrawFocusState dfs,
const XP_Rect* rect, BoardObjectType obj )
{
XP_LOGF( "%s(%s, %s)", __FUNCTION__, DrawFocusState_2str(dfs),
BoardObjectType_2str(obj) );
if ( dfs == DFS_TOP ) {
dctx->topFocusObj = obj;
XP_MEMCPY( &dctx->topFocusRect, rect, sizeof(dctx->topFocusRect) );
} else /* if ( dfs == DFS_DIVED ) */ {
dctx->topFocusObj = OBJ_NONE;
}
}
#else
# define dfsCopyIf( dctx, dfs, rect, obj )
# define dfsDrawIf( dctx, obj )
#endif
# define BMP_WIDTH 16
# define BMP_HT 16
@ -224,7 +287,7 @@ checkFontOffsets( PalmDrawCtx* dctx, const DictionaryCtxt* dict )
static XP_Bool
palm_common_draw_boardBegin( DrawCtx* p_dctx, const DictionaryCtxt* dict,
const XP_Rect* rect, XP_Bool XP_UNUSED(hasfocus) )
const XP_Rect* rect, DrawFocusState dfs )
{
PalmDrawCtx* dctx = (PalmDrawCtx*)p_dctx;
PalmAppGlobals* globals = dctx->globals;
@ -234,13 +297,15 @@ palm_common_draw_boardBegin( DrawCtx* p_dctx, const DictionaryCtxt* dict,
checkFontOffsets( dctx, dict );
dfsCopyIf( dctx, dfs, rect, OBJ_BOARD );
return XP_TRUE;
} /* palm_common_draw_boardBegin */
#ifdef COLOR_SUPPORT
static XP_Bool
palm_clr_draw_boardBegin( DrawCtx* p_dctx, const DictionaryCtxt* dict,
const XP_Rect* rect, XP_Bool hasfocus )
const XP_Rect* rect, DrawFocusState dfs )
{
PalmDrawCtx* dctx = (PalmDrawCtx*)p_dctx;
@ -252,14 +317,16 @@ palm_clr_draw_boardBegin( DrawCtx* p_dctx, const DictionaryCtxt* dict,
HIGHRES_PUSH_NOPOP(dctx);
palm_common_draw_boardBegin( p_dctx, dict, rect, hasfocus );
palm_common_draw_boardBegin( p_dctx, dict, rect, dfs );
return XP_TRUE;
} /* palm_clr_draw_boardBegin */
static void
palm_clr_draw_boardFinished( DrawCtx* XP_UNUSED(p_dctx) )
palm_clr_draw_boardFinished( DrawCtx* p_dctx )
{
dfsDrawIf( (PalmDrawCtx*)p_dctx, OBJ_BOARD );
WinPopDrawState();
} /* palm_clr_draw_boardFinished */
@ -518,7 +585,7 @@ palm_draw_invertCell( DrawCtx* p_dctx, const XP_Rect* rect )
static XP_Bool
palm_clr_draw_trayBegin( DrawCtx* p_dctx, const XP_Rect* rect,
XP_U16 owner, XP_Bool hasfocus )
XP_U16 owner, DrawFocusState dfs )
{
PalmDrawCtx* dctx = (PalmDrawCtx*)p_dctx;
@ -531,21 +598,23 @@ palm_clr_draw_trayBegin( DrawCtx* p_dctx, const XP_Rect* rect,
HIGHRES_PUSH_NOPOP(dctx);
palm_bnw_draw_trayBegin( p_dctx, rect, owner, hasfocus );
palm_bnw_draw_trayBegin( p_dctx, rect, owner, dfs );
return XP_TRUE;
} /* palm_clr_draw_trayBegin */
static XP_Bool
palm_bnw_draw_trayBegin( DrawCtx* p_dctx, const XP_Rect* rect,
XP_U16 XP_UNUSED(owner),
XP_Bool XP_UNUSED(hasfocus) )
DrawFocusState dfs )
{
PalmDrawCtx* dctx = (PalmDrawCtx*)p_dctx;
dfsCopyIf( dctx, dfs, rect, OBJ_TRAY );
WinGetClip( &dctx->oldTrayClip );
WinSetClip( (RectangleType*)rect );
return XP_TRUE;
} /* palm_draw_trayBegin */
} /* palm_bnw_draw_trayBegin */
static void
palm_clr_draw_trayFinished( DrawCtx* p_dctx )
@ -558,6 +627,7 @@ static void
palm_bnw_draw_trayFinished( DrawCtx* p_dctx )
{
PalmDrawCtx* dctx = (PalmDrawCtx*)p_dctx;
dfsDrawIf( dctx, OBJ_TRAY );
WinSetClip( &dctx->oldTrayClip );
} /* palm_draw_trayFinished */
@ -579,6 +649,15 @@ smallBoldStringAt( const char* str, XP_U16 len, XP_S16 x, XP_U16 y )
WinSetScalingMode( oldMode );
} /* smallBoldStringAt */
static void
adjustTileRect( XP_Rect* r, XP_U16 doubler )
{
r->width -= 3 * doubler;
r->height -= 3 * doubler;
r->top += 2 * doubler;
r->left += 2 * doubler;
}
static void
palm_draw_drawTile( DrawCtx* p_dctx, const XP_Rect* rect,
const XP_UCHAR* letters, XP_Bitmap bitmap,
@ -596,10 +675,7 @@ palm_draw_drawTile( DrawCtx* p_dctx, const XP_Rect* rect,
draw_clearRect( p_dctx, &localR );
localR.width -= 3 * doubler;
localR.height -= 3 * doubler;
localR.top += 2 * doubler;
localR.left += 2 * doubler;
adjustTileRect( &localR, doubler );
/* this will fill it with the tile background color */
WinEraseRectangle( (const RectangleType*)&localR, 0 );
@ -747,10 +823,12 @@ palm_clr_draw_drawBoardArrow( DrawCtx* p_dctx, const XP_Rect* rectP,
static void
palm_draw_scoreBegin( DrawCtx* p_dctx, const XP_Rect* rect,
XP_U16 XP_UNUSED(numPlayers),
XP_Bool XP_UNUSED(hasfocus) )
DrawFocusState dfs )
{
PalmDrawCtx* dctx = (PalmDrawCtx*)p_dctx;
dfsCopyIf( dctx, dfs, rect, OBJ_SCORE );
HIGHRES_PUSH( dctx );
WinGetClip( &dctx->oldScoreClip );
@ -1082,6 +1160,7 @@ static void
palm_draw_scoreFinished( DrawCtx* p_dctx )
{
PalmDrawCtx* dctx = (PalmDrawCtx*)p_dctx;
dfsDrawIf( dctx, OBJ_SCORE );
WinSetClip( &dctx->oldScoreClip );
HIGHRES_POP(dctx);
@ -1328,6 +1407,32 @@ palm_draw_eraseMiniWindow( DrawCtx* p_dctx, const XP_Rect* XP_UNUSED(rect),
}
} /* palm_draw_eraseMiniWindow */
#ifdef KEYBOARD_NAV
static void
palm_draw_drawCursor( DrawCtx* p_dctx, BoardObjectType obj,
const XP_Rect* rect )
{
XP_Rect localR;
if ( OBJ_TRAY == obj ) {
PalmDrawCtx* dctx = (PalmDrawCtx*)p_dctx;
XP_U16 doubler = dctx->doHiRes? 2 : 1;
localR = *rect;
rect = &localR;
adjustTileRect( &localR, doubler );
localR.left += 2;
localR.top += 1;
localR.width -= 4;
localR.height -= 2;
insetRect( &localR, 1 );
}
drawFocusRect( (PalmDrawCtx*)p_dctx, rect );
}
#endif
static void
draw_doNothing( DrawCtx* XP_UNUSED(dctx), ... )
{
@ -1388,6 +1493,10 @@ palm_drawctxt_make( MPFORMAL GraphicsAbility able,
SET_VTABLE_ENTRY( dctx->vtable, draw_drawMiniWindow, palm );
SET_VTABLE_ENTRY( dctx->vtable, draw_eraseMiniWindow, palm );
#ifdef KEYBOARD_NAV
SET_VTABLE_ENTRY( dctx->vtable, draw_drawCursor, palm );
#endif
if ( able == COLOR ) {
#ifdef COLOR_SUPPORT
SET_VTABLE_ENTRY( dctx->vtable, draw_boardBegin, palm_clr );

View file

@ -2024,6 +2024,48 @@ hresRect( PalmAppGlobals* globals, RectangleType* r )
}
}
#ifdef XWFEATURE_FIVEWAY
static XP_Bool
handleChangeFocus( PalmAppGlobals* globals, const EventType* event,
XP_Bool* drawP )
{
XP_Bool handled = XP_FALSE;
XP_U16 objectID = event->data.frmObjectFocusTake.objectID;
XP_ASSERT( &event->data.frmObjectFocusTake.objectID
== &event->data.frmObjectFocusLost.objectID );
/* XP_LOGF( "%s(%d,%s)", __FUNCTION__, objectID, */
/* (event->eType == frmObjectFocusTakeEvent? "take":"lost") ); */
handled = ( objectID == XW_BOARD_GADGET_ID
|| objectID == XW_SCOREBOARD_GADGET_ID
|| objectID == XW_TRAY_GADGET_ID );
if ( handled ) {
XP_Bool take = event->eType == frmObjectFocusTakeEvent;
BoardObjectType typ = (objectID - XW_BOARD_GADGET_ID) + OBJ_BOARD;
*drawP = board_focusChanged( globals->game.board, typ, take );
if ( take ) {
FrmSetFocus( globals->mainForm,
FrmGetObjectIndex( globals->mainForm, objectID ) );
}
}
return handled;
} /* handleChangeFocus */
static void
checkSetFocus( PalmAppGlobals* globals )
{
BoardObjectType typ = board_getFocusOwner( globals->game.board );
XP_U16 objectID = XW_BOARD_GADGET_ID + (typ - OBJ_BOARD);
XP_LOGF( "%s: FrmSetFocus(%d)", __FUNCTION__, objectID );
FrmSetFocus( globals->mainForm,
FrmGetObjectIndex( globals->mainForm, objectID ) );
}
#endif
/*****************************************************************************
*
****************************************************************************/
@ -2439,6 +2481,13 @@ mainViewHandleEvent( EventPtr event )
}
break;
#ifdef XWFEATURE_FIVEWAY
case frmObjectFocusTakeEvent:
case frmObjectFocusLostEvent:
handled = handleChangeFocus( globals, event, &draw );
break;
#endif
case keyDownEvent: {
XP_Key xpkey = XP_KEY_NONE;
Int16 ch = event->data.keyDown.chr;
@ -2453,6 +2502,27 @@ mainViewHandleEvent( EventPtr event )
case backspaceChr:
xpkey = XP_CURSOR_KEY_DEL;
break;
#ifdef XWFEATURE_FIVEWAY
case vchrRockerCenter:
xpkey = XP_RETURN_KEY;
break;
case vchrRockerLeft:
xpkey = XP_CURSOR_KEY_LEFT;
break;
case vchrRockerRight:
xpkey = XP_CURSOR_KEY_RIGHT;
break;
case vchrRockerUp:
xpkey = XP_CURSOR_KEY_UP;
break;
case vchrRockerDown:
xpkey = XP_CURSOR_KEY_DOWN;
break;
case chrSpace:
xpkey = XP_FOCUSCHANGE_KEY;
break;
#endif
default:
/* I'm not interested in being dependent on a particular version
of the OS, (can't manage to link against the intl library
@ -2469,6 +2539,11 @@ mainViewHandleEvent( EventPtr event )
}
if ( xpkey != XP_KEY_NONE ) {
draw = board_handleKey( globals->game.board, xpkey );
#ifdef XWFEATURE_FIVEWAY
if ( xpkey == XP_FOCUSCHANGE_KEY ) {
checkSetFocus( globals );
}
#endif
}
handled = draw;
}

View file

@ -89,6 +89,11 @@ typedef struct PalmDrawCtx {
XP_LangCode fontLangCode;
PalmFontHtInfo* fontHtInfo;
#ifdef XWFEATURE_FIVEWAY
BoardObjectType topFocusObj;
XP_Rect topFocusRect;
#endif
union {
struct {
XP_U8 reserved; /* make CW compiler happy */

View file

@ -289,6 +289,15 @@
# endif
#endif
#ifdef XWFEATURE_FIVEWAY
/* These should be in same order as BoardObjectType */
# define XW_BOARD_GADGET_ID 3001
# define XW_SCOREBOARD_GADGET_ID 3002
# define XW_TRAY_GADGET_ID 3003
#endif
/* These aren't part of the hide/show thing as they're displayed only
* explicitly byother controls */
#define XW_PREFS_PHONIES_LIST_ID 2750