mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-28 09:58:30 +01:00
Move toward running curses on a small screen: replace omnipresent menu
with one drawn on demand; change size and location of scoreboard and tray if needed; use wgetch rather than reading stdin to support keypad keys for navigation. Also stick g_ in front of some frequently used global names.
This commit is contained in:
parent
bae6890c35
commit
b98b7fd993
3 changed files with 586 additions and 254 deletions
|
@ -28,10 +28,13 @@ CFLAGS += -Os
|
|||
endif
|
||||
|
||||
DO_CURSES = -DPLATFORM_NCURSES
|
||||
ifdef CURSES_SMALL_SCREEN
|
||||
DO_CURSES += -DCURSES_SMALL_SCREEN
|
||||
endif
|
||||
DO_GTK = -DPLATFORM_GTK
|
||||
|
||||
SVNDEF = -D'SVN_REV="$(shell svnversion -n .)"'
|
||||
CFLAGS += $(SVNDEF)
|
||||
SVN_REV ?= "$(shell svnversion -n .)"
|
||||
SVNDEF = -D'SVN_REV=$(SVN_REV)'
|
||||
|
||||
ifdef CURSES_ONLY
|
||||
DO_GTK =
|
||||
|
@ -43,28 +46,31 @@ DO_CURSES =
|
|||
PLATFORM := $(PLATFORM)_gtk
|
||||
endif
|
||||
|
||||
DEFINES += $(DO_CURSES) $(DO_GTK)
|
||||
DEFINES += $(DO_CURSES) $(DO_GTK) $(SVNDEF)
|
||||
|
||||
TARGET=$(PLATFORM)/xwords
|
||||
|
||||
ifdef BUILD_COMMAND
|
||||
CC = ${BUILD_COMMAND}
|
||||
else
|
||||
CC = gcc
|
||||
endif
|
||||
|
||||
include ../common/config.mk
|
||||
|
||||
DEFINES += -DPLATFORM_LINUX -DKEY_SUPPORT -DKEYBOARD_NAV -DNODE_CAN_4
|
||||
DEFINES += -DSTUBBED_DICT
|
||||
# DEFINES += -DSTUBBED_DICT
|
||||
ifdef DO_GTK
|
||||
DEFINES += -DXWFEATURE_SEARCHLIMIT
|
||||
endif
|
||||
DEFINES += -DFEATURE_TRAY_EDIT
|
||||
#DEFINES += -DDRAW_WITH_PRIMITIVES
|
||||
|
||||
ifdef CURSES_CELL_HT
|
||||
DEFINES += -DCURSES_CELL_HT=$(CURSES_CELL_HT)
|
||||
endif
|
||||
ifdef CURSES_CELL_WIDTH
|
||||
DEFINES += -DCURSES_CELL_WIDTH=$(CURSES_CELL_WIDTH)
|
||||
endif
|
||||
|
||||
# Bluetooth support
|
||||
ifndef NO_BLUETOOTH
|
||||
BLUETOOTH = -DXWFEATURE_BLUETOOTH -DBT_USE_L2CAP
|
||||
endif
|
||||
#BLUETOOTH = -DXWFEATURE_BLUETOOTH -DBT_USE_RFCOMM
|
||||
# DEFINES += -DXWFEATURE_IR
|
||||
DEFINES += ${BLUETOOTH}
|
||||
|
@ -114,7 +120,7 @@ OBJ = $(PLATFORM)/linuxmain.o \
|
|||
|
||||
# $(PLATFORM)/linuxcommpipe.o \
|
||||
|
||||
LIBS = -lm -lmcheck -L $(HOME)/usr/local/pilot/lib $(GPROFFLAG)
|
||||
LIBS = -lm -lmcheck $(GPROFFLAG)
|
||||
ifdef BLUETOOTH
|
||||
LIBS += -lbluetooth
|
||||
endif
|
||||
|
@ -126,7 +132,7 @@ ifneq (,$(findstring DPLATFORM_GTK,$(DEFINES)))
|
|||
endif
|
||||
|
||||
ifneq (,$(findstring DPLATFORM_NCURSES,$(DEFINES)))
|
||||
LIBS += -lncurses
|
||||
LIBS += $(OE_LIBDIR) -lncurses
|
||||
endif
|
||||
|
||||
# provides an all: target
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* -*-mode: C; fill-column: 78; c-basic-offset: 4; -*- */
|
||||
/* -*-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
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -36,6 +37,7 @@ typedef struct CursesDrawCtx {
|
|||
} CursesDrawCtx;
|
||||
|
||||
static void curses_draw_clearRect( DrawCtx* p_dctx, const XP_Rect* rectP );
|
||||
static void getTops( const XP_Rect* rect, int* toptop, int* topbot );
|
||||
|
||||
static void
|
||||
drawRect( WINDOW* win, const XP_Rect* rect, char vert, char hor )
|
||||
|
@ -64,7 +66,6 @@ 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 );
|
||||
|
@ -112,26 +113,22 @@ curses_draw_scoreBegin( DrawCtx* p_dctx, const XP_Rect* rect,
|
|||
} /* curses_draw_scoreBegin */
|
||||
|
||||
static void
|
||||
formatRemText( char* buf, XP_S16 nTilesLeft )
|
||||
formatRemText( char* buf, int bufLen, XP_S16 nTilesLeft, int width )
|
||||
{
|
||||
strcpy( buf, "Tiles left in pool: " );
|
||||
buf += strlen( buf );
|
||||
if ( nTilesLeft < 0 ) {
|
||||
strcpy( buf, "***" );
|
||||
} else {
|
||||
sprintf( buf, "%.3d", nTilesLeft );
|
||||
snprintf( buf, bufLen, "Tiles left in pool: %.3d", nTilesLeft );
|
||||
if ( strlen(buf)+1 >= width ) {
|
||||
snprintf( buf, bufLen, "Rem: %.3d", nTilesLeft );
|
||||
}
|
||||
} /* formatRemText */
|
||||
|
||||
static void
|
||||
curses_draw_measureRemText( DrawCtx* XP_UNUSED(dctx),
|
||||
const XP_Rect* XP_UNUSED(r),
|
||||
const XP_Rect* r,
|
||||
XP_S16 nTilesLeft,
|
||||
XP_U16* width, XP_U16* height )
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
formatRemText( buf, nTilesLeft );
|
||||
formatRemText( buf, sizeof(buf), nTilesLeft, r->width );
|
||||
|
||||
*width = strlen(buf);
|
||||
*height = 1;
|
||||
|
@ -144,60 +141,104 @@ curses_draw_drawRemText( DrawCtx* p_dctx, const XP_Rect* rInner,
|
|||
CursesDrawCtx* dctx = (CursesDrawCtx*)p_dctx;
|
||||
char buf[32];
|
||||
|
||||
formatRemText( buf, nTilesLeft );
|
||||
formatRemText( buf, sizeof(buf), nTilesLeft, rInner->width );
|
||||
mvwprintw( dctx->boardWin, rInner->top, rInner->left, buf );
|
||||
} /* curses_draw_drawRemText */
|
||||
|
||||
#define SCORE_COL 25
|
||||
#define RECENT_COL 31
|
||||
static int
|
||||
fitIn( char* buf, int len, int* rem, char* str )
|
||||
{
|
||||
int slen = strlen(str);
|
||||
if ( !!rem && (*rem != 0) ) {
|
||||
++len;
|
||||
--*rem;
|
||||
}
|
||||
if ( slen > len ) {
|
||||
slen = len;
|
||||
}
|
||||
|
||||
memcpy( buf, str, slen );
|
||||
return len;
|
||||
} /* fitIn */
|
||||
|
||||
static void
|
||||
formatScoreText( XP_UCHAR* buf, const DrawScoreInfo* dsi )
|
||||
formatScoreText( XP_UCHAR* out, int outLen, const DrawScoreInfo* dsi,
|
||||
int width )
|
||||
{
|
||||
XP_S16 nTilesLeft = dsi->nTilesLeft;
|
||||
XP_Bool isRobot = dsi->isRobot;
|
||||
char label = isRobot? 'r':'n';
|
||||
int len;
|
||||
char recbuf[32];
|
||||
XP_U16 recBufLen = sizeof(recbuf);
|
||||
/* Long and short formats. We'll try long first. If it fits, cool.
|
||||
Otherwise we use short. Either way, we fill the whole rect so it can
|
||||
overwrite anything that was there before.*/
|
||||
char tmp[width+1];
|
||||
char buf[width+1];
|
||||
int scoreWidth = 4;
|
||||
|
||||
if ( nTilesLeft < 0 ) {
|
||||
nTilesLeft = MAX_TRAY_TILES;
|
||||
XP_ASSERT( width < outLen );
|
||||
|
||||
XP_MEMSET( buf, ' ', width );
|
||||
buf[width] = '\0';
|
||||
|
||||
/* Status/role chars at start */
|
||||
if ( dsi->isTurn ) {
|
||||
buf[0] = 'T';
|
||||
}
|
||||
if ( dsi->isRemote ) {
|
||||
label = toupper(label);
|
||||
if ( dsi->selected ) {
|
||||
buf[1] = 'S';
|
||||
}
|
||||
if ( dsi->isRobot) {
|
||||
buf[2] = 'r';
|
||||
}
|
||||
|
||||
len = sprintf( buf, "%c:%c [%c] %s (%d)",
|
||||
(dsi->isTurn? 'T' : ' '),
|
||||
(dsi->selected? 'S' : ' '),
|
||||
label, dsi->name, nTilesLeft );
|
||||
while ( len < SCORE_COL ) {
|
||||
++len;
|
||||
strcat( buf, " " );
|
||||
}
|
||||
len += sprintf( buf + len, "%.3d", dsi->totalScore );
|
||||
/* Score always goes at end. Will overwrite status if width is really small */
|
||||
snprintf( tmp, scoreWidth, "%.3d", dsi->totalScore );
|
||||
memcpy( &buf[width-scoreWidth+1], tmp, scoreWidth-1 );
|
||||
|
||||
if ( (*dsi->lsc)( dsi->lscClosure, dsi->playerNum, recbuf, &recBufLen ) ) {
|
||||
while ( len < RECENT_COL ) {
|
||||
++len;
|
||||
strcat( buf, " " );
|
||||
/* Now we want to fit name, rem tiles, last score, and last move, if
|
||||
there's space. Allocate to each so they're in columns. */
|
||||
|
||||
width -= 8; /* status chars plus space; score plus space */
|
||||
if ( width > 0 ) {
|
||||
int pos = 4;
|
||||
int nCols = 2;
|
||||
int perCol = (width - ( nCols - 1)) / nCols; /* not counting spaces */
|
||||
if ( perCol > 0 ) {
|
||||
int rem = (width - ( nCols - 1)) % nCols;
|
||||
|
||||
pos += 1 + fitIn( &buf[pos], perCol, &rem, dsi->name );
|
||||
|
||||
XP_U16 len = sizeof(tmp);
|
||||
if ( (*dsi->lsc)( dsi->lscClosure, dsi->playerNum, tmp, &len ) ) {
|
||||
char* s = tmp;
|
||||
if ( len > perCol ) {
|
||||
/* We want to preserve the score first, then the first part of
|
||||
word. That is, WORD:20 prints as W0:20, not WORD: or
|
||||
RD:20 */
|
||||
char* colon = strstr( tmp, ":" );
|
||||
if ( colon ) {
|
||||
s += len - perCol;
|
||||
memmove( s, tmp, colon - tmp - (len - perCol) );
|
||||
}
|
||||
}
|
||||
pos += 1 + fitIn( &buf[pos], perCol, NULL, s );
|
||||
}
|
||||
} else {
|
||||
fitIn( &buf[pos], width, NULL, dsi->name );
|
||||
}
|
||||
strcat( buf, recbuf );
|
||||
}
|
||||
}
|
||||
|
||||
snprintf( out, outLen, "%s", buf );
|
||||
} /* formatScoreText */
|
||||
|
||||
static void
|
||||
curses_draw_measureScoreText( DrawCtx* XP_UNUSED(p_dctx),
|
||||
const XP_Rect* XP_UNUSED(r),
|
||||
const XP_Rect* r,
|
||||
const DrawScoreInfo* dsi,
|
||||
XP_U16* width, XP_U16* height )
|
||||
{
|
||||
XP_UCHAR buf[100];
|
||||
formatScoreText( buf, dsi );
|
||||
formatScoreText( buf, sizeof(buf), dsi, r->width );
|
||||
|
||||
*width = strlen( buf );
|
||||
XP_ASSERT( *width <= r->width );
|
||||
*height = 1; /* one line per player */
|
||||
} /* curses_draw_measureScoreText */
|
||||
|
||||
|
@ -215,8 +256,11 @@ curses_draw_score_pendingScore( DrawCtx* p_dctx, const XP_Rect* rect,
|
|||
strcpy( buf, "???" );
|
||||
}
|
||||
|
||||
mvwprintw( dctx->boardWin, rect->top+1, rect->left, "pt:" );
|
||||
mvwprintw( dctx->boardWin, rect->top+2, rect->left, "%s", buf );
|
||||
int toptop, topbot;
|
||||
getTops( rect, &toptop, &topbot );
|
||||
|
||||
mvwprintw( dctx->boardWin, toptop, rect->left, "pt:" );
|
||||
mvwprintw( dctx->boardWin, topbot, rect->left, "%s", buf );
|
||||
} /* curses_draw_score_pendingScore */
|
||||
|
||||
static void
|
||||
|
@ -241,7 +285,7 @@ curses_draw_score_drawPlayer( DrawCtx* p_dctx, const XP_Rect* rInner,
|
|||
curses_draw_clearRect( p_dctx, rOuter );
|
||||
|
||||
/* print the name and turn/remoteness indicator */
|
||||
formatScoreText( buf, dsi );
|
||||
formatScoreText( buf, sizeof(buf), dsi, rInner->width );
|
||||
mvwprintw( dctx->boardWin, y, rOuter->left, buf );
|
||||
|
||||
if ( (dsi->flags&CELL_ISCURSOR) != 0 ) {
|
||||
|
@ -260,7 +304,6 @@ curses_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect,
|
|||
XP_UCHAR loc[4] = { ' ', ' ', ' ', '\0' };
|
||||
XP_ASSERT( XP_STRLEN(letter) < sizeof(loc) );
|
||||
XP_ASSERT( rect->width < sizeof(loc) );
|
||||
XP_ASSERT( rect->height == 1 );
|
||||
XP_MEMCPY( loc, letter, strlen(letter) );
|
||||
|
||||
if ( letter[0] == LETTER_NONE ) {
|
||||
|
@ -296,21 +339,40 @@ curses_draw_drawCell( DrawCtx* p_dctx, const XP_Rect* rect,
|
|||
return XP_TRUE;
|
||||
} /* curses_draw_drawCell */
|
||||
|
||||
static void
|
||||
getTops( const XP_Rect* rect, int* toptop, int* topbot )
|
||||
{
|
||||
int top = rect->top;
|
||||
if ( rect->height >= 4 ) {
|
||||
++top;
|
||||
}
|
||||
*toptop = top;
|
||||
|
||||
top = rect->top + rect->height - 1;
|
||||
if ( rect->height >= 3 ) {
|
||||
--top;
|
||||
}
|
||||
*topbot = top;
|
||||
} /* getTops */
|
||||
|
||||
static void
|
||||
curses_stringInTile( CursesDrawCtx* dctx, const XP_Rect* rect,
|
||||
XP_UCHAR* letter, XP_UCHAR* val )
|
||||
{
|
||||
eraseRect( dctx, rect );
|
||||
|
||||
int toptop, topbot;
|
||||
getTops( rect, &toptop, &topbot );
|
||||
|
||||
if ( !!letter ) {
|
||||
mvwaddnstr( dctx->boardWin, rect->top+1, rect->left+(rect->width/2),
|
||||
mvwaddnstr( dctx->boardWin, toptop, rect->left+(rect->width/2),
|
||||
letter, strlen(letter) );
|
||||
}
|
||||
|
||||
if ( !!val ) {
|
||||
int len = strlen( val );
|
||||
mvwaddnstr( dctx->boardWin, rect->top+rect->height-2,
|
||||
rect->left + rect->width - len, val, len );
|
||||
mvwaddnstr( dctx->boardWin, topbot, rect->left + rect->width - len,
|
||||
val, len );
|
||||
}
|
||||
} /* curses_stringInTile */
|
||||
|
||||
|
|
|
@ -56,10 +56,128 @@
|
|||
#include "util.h"
|
||||
#include "dbgutil.h"
|
||||
|
||||
#define MENU_WINDOW_HEIGHT 5 /* three lines plus borders */
|
||||
#define INFINITE_TIMEOUT -1
|
||||
#ifdef CURSES_SMALL_SCREEN
|
||||
# define MENU_WINDOW_HEIGHT 1
|
||||
# define BOARD_OFFSET 0
|
||||
#else
|
||||
# define MENU_WINDOW_HEIGHT 5 /* three lines plus borders */
|
||||
# define BOARD_OFFSET 1
|
||||
#endif
|
||||
|
||||
CursesAppGlobals globals; /* must be global b/c of SIGWINCH_handler */
|
||||
#ifndef CURSES_CELL_HT
|
||||
# define CURSES_CELL_HT 1
|
||||
#endif
|
||||
#ifndef CURSES_CELL_WIDTH
|
||||
# define CURSES_CELL_WIDTH 2
|
||||
#endif
|
||||
|
||||
#ifndef CURSES_MAX_HEIGHT
|
||||
# define CURSES_MAX_HEIGHT 40
|
||||
#endif
|
||||
#ifndef CURSES_MAX_WIDTH
|
||||
//# define CURSES_MAX_WIDTH 50
|
||||
# define CURSES_MAX_WIDTH 70
|
||||
#endif
|
||||
|
||||
#define INFINITE_TIMEOUT -1
|
||||
#define BOARD_SCORE_PADDING 3
|
||||
|
||||
|
||||
typedef XP_Bool (*CursesMenuHandler)(CursesAppGlobals* globals);
|
||||
typedef struct MenuList {
|
||||
CursesMenuHandler handler;
|
||||
char* desc;
|
||||
char* keyDesc;
|
||||
char key;
|
||||
} MenuList;
|
||||
|
||||
static XP_Bool handleQuit( CursesAppGlobals* globals );
|
||||
static XP_Bool handleRight( CursesAppGlobals* globals );
|
||||
static XP_Bool handleSpace( CursesAppGlobals* globals );
|
||||
static XP_Bool handleRet( CursesAppGlobals* globals );
|
||||
static XP_Bool handleHint( CursesAppGlobals* globals );
|
||||
static XP_Bool handleLeft( CursesAppGlobals* globals );
|
||||
static XP_Bool handleRight( CursesAppGlobals* globals );
|
||||
static XP_Bool handleUp( CursesAppGlobals* globals );
|
||||
static XP_Bool handleDown( CursesAppGlobals* globals );
|
||||
static XP_Bool handleCommit( CursesAppGlobals* globals );
|
||||
static XP_Bool handleFlip( CursesAppGlobals* globals );
|
||||
static XP_Bool handleToggleValues( CursesAppGlobals* globals );
|
||||
static XP_Bool handleBackspace( CursesAppGlobals* globals );
|
||||
static XP_Bool handleUndo( CursesAppGlobals* globals );
|
||||
static XP_Bool handleReplace( CursesAppGlobals* globals );
|
||||
static XP_Bool handleRootKeyShow( CursesAppGlobals* globals );
|
||||
static XP_Bool handleRootKeyHide( CursesAppGlobals* globals );
|
||||
static XP_Bool handleJuggle( CursesAppGlobals* globals );
|
||||
static XP_Bool handleHide( CursesAppGlobals* globals );
|
||||
static XP_Bool handleAltLeft( CursesAppGlobals* globals );
|
||||
static XP_Bool handleAltRight( CursesAppGlobals* globals );
|
||||
static XP_Bool handleAltUp( CursesAppGlobals* globals );
|
||||
static XP_Bool handleAltDown( CursesAppGlobals* globals );
|
||||
|
||||
|
||||
MenuList g_sharedMenuList[] = {
|
||||
{ handleQuit, "Quit", "Q", 'Q' },
|
||||
{ handleRight, "Tab right", "<tab>", '\t' },
|
||||
{ handleSpace, "Raise focus", "<spc>", ' ' },
|
||||
{ handleRet, "Click/tap", "<ret>", '\r' },
|
||||
{ handleHint, "Hint", "?", '?' },
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
{ handleLeft, "Left", "H", 'H' },
|
||||
{ handleRight, "Right", "L", 'L' },
|
||||
{ handleUp, "Up", "J", 'J' },
|
||||
{ handleDown, "Down", "K", 'K' },
|
||||
#endif
|
||||
|
||||
{ handleCommit, "Commit move", "C", 'C' },
|
||||
{ handleFlip, "Flip", "F", 'F' },
|
||||
{ handleToggleValues, "Show values", "V", 'V' },
|
||||
|
||||
{ handleBackspace, "Remove from board", "<del>", 8 },
|
||||
{ handleUndo, "Undo prev", "U", 'U' },
|
||||
{ handleReplace, "uNdo cur", "N", 'N' },
|
||||
|
||||
{ NULL, NULL, NULL, '\0'}
|
||||
};
|
||||
|
||||
MenuList g_boardMenuList[] = {
|
||||
{ handleAltLeft, "Force left", "{", '{' },
|
||||
{ handleAltRight, "Force right", "}", '}' },
|
||||
{ handleAltUp, "Force up", "_", '_' },
|
||||
{ handleAltDown, "Force down", "+", '+' },
|
||||
{ NULL, NULL, NULL, '\0'}
|
||||
};
|
||||
|
||||
MenuList g_scoreMenuList[] = {
|
||||
#ifdef KEYBOARD_NAV
|
||||
#endif
|
||||
{ NULL, NULL, NULL, '\0'}
|
||||
};
|
||||
|
||||
MenuList g_trayMenuList[] = {
|
||||
{ handleJuggle, "Juggle", "G", 'G' },
|
||||
{ handleHide, "[un]hIde", "I", 'I' },
|
||||
{ handleAltLeft, "Divider left", "{", '{' },
|
||||
{ handleAltRight, "Divider right", "}", '}' },
|
||||
|
||||
{ NULL, NULL, NULL, '\0'}
|
||||
};
|
||||
|
||||
#ifdef CURSES_SMALL_SCREEN
|
||||
MenuList g_rootMenuListShow[] = {
|
||||
{ handleRootKeyShow, "Press . for menu", "", '.' },
|
||||
{ NULL, NULL, NULL, '\0'}
|
||||
};
|
||||
|
||||
MenuList g_rootMenuListHide[] = {
|
||||
{ handleRootKeyHide, "Clear menu", ".", '.' },
|
||||
{ NULL, NULL, NULL, '\0'}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
static CursesAppGlobals g_globals; /* must be global b/c of SIGWINCH_handler */
|
||||
|
||||
static void changeMenuForFocus( CursesAppGlobals* globals,
|
||||
BoardObjectType obj );
|
||||
|
@ -68,6 +186,11 @@ static XP_Bool handleRight( CursesAppGlobals* globals );
|
|||
static XP_Bool handleUp( CursesAppGlobals* globals );
|
||||
static XP_Bool handleDown( CursesAppGlobals* globals );
|
||||
static XP_Bool handleFocusKey( CursesAppGlobals* globals, XP_Key key );
|
||||
static void countMenuLines( MenuList** menuLists, int maxX, int padding,
|
||||
int* nLinesP, int* nColsP );
|
||||
static void drawMenuFromList( WINDOW* win, MenuList** menuLists,
|
||||
int nLines, int padding );
|
||||
static CursesMenuHandler getHandlerForKey( MenuList* list, char ch );
|
||||
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
|
@ -257,7 +380,7 @@ initCurses( CursesAppGlobals* globals )
|
|||
WINDOW* menuWin;
|
||||
WINDOW* boardWin;
|
||||
|
||||
int x, y;
|
||||
int width, height;
|
||||
|
||||
/* ncurses man page says most apps want this sequence */
|
||||
mainWin = initscr();
|
||||
|
@ -265,16 +388,22 @@ initCurses( CursesAppGlobals* globals )
|
|||
noecho();
|
||||
nonl();
|
||||
intrflush(stdscr, FALSE);
|
||||
keypad(stdscr, TRUE);
|
||||
keypad(stdscr, TRUE); /* effects wgetch only? */
|
||||
|
||||
getmaxyx(mainWin, y, x);
|
||||
globals->statusLine = y - MENU_WINDOW_HEIGHT - 1;
|
||||
menuWin = newwin( MENU_WINDOW_HEIGHT, x, y-MENU_WINDOW_HEIGHT, 0 );
|
||||
getmaxyx(mainWin, height, width );
|
||||
XP_LOGF( "getmaxyx->w:%d; h:%d", width, height );
|
||||
if ( height > CURSES_MAX_HEIGHT ) {
|
||||
height = CURSES_MAX_HEIGHT;
|
||||
}
|
||||
if ( width > CURSES_MAX_WIDTH ) {
|
||||
width = CURSES_MAX_WIDTH;
|
||||
}
|
||||
|
||||
globals->statusLine = height - MENU_WINDOW_HEIGHT - 1;
|
||||
menuWin = newwin( MENU_WINDOW_HEIGHT, width,
|
||||
height-MENU_WINDOW_HEIGHT, 0 );
|
||||
nodelay(menuWin, 1); /* don't block on getch */
|
||||
boardWin = newwin( MAX_ROWS+1, x, 0, 0 );
|
||||
|
||||
/* leaveok( boardWin, 1 ); */
|
||||
/* leaveok( menuWin, 1 ); */
|
||||
boardWin = newwin( height-MENU_WINDOW_HEIGHT, width, 0, 0 );
|
||||
|
||||
globals->menuWin = menuWin;
|
||||
globals->boardWin = boardWin;
|
||||
|
@ -308,13 +437,6 @@ showStatus( CursesAppGlobals* globals )
|
|||
} /* showStatus */
|
||||
#endif
|
||||
|
||||
typedef XP_Bool (*CursesMenuHandler)(CursesAppGlobals* globals);
|
||||
typedef struct MenuList {
|
||||
CursesMenuHandler handler;
|
||||
char* desc;
|
||||
char* keyDesc;
|
||||
char key;
|
||||
} MenuList;
|
||||
static XP_Bool
|
||||
handleQuit( CursesAppGlobals* globals )
|
||||
{
|
||||
|
@ -391,6 +513,70 @@ handleHide( CursesAppGlobals* globals )
|
|||
return XP_TRUE;
|
||||
} /* handleJuggle */
|
||||
|
||||
#ifdef CURSES_SMALL_SCREEN
|
||||
static XP_Bool
|
||||
handleRootKeyShow( CursesAppGlobals* globals )
|
||||
{
|
||||
WINDOW* win;
|
||||
MenuList* lists[] = { g_sharedMenuList, globals->menuList,
|
||||
g_rootMenuListHide, NULL };
|
||||
int winMaxY, winMaxX;
|
||||
|
||||
wclear( globals->menuWin );
|
||||
wrefresh( globals->menuWin );
|
||||
|
||||
getmaxyx( globals->boardWin, winMaxY, winMaxX );
|
||||
|
||||
int border = 2;
|
||||
int width = winMaxX - (border * 2);
|
||||
int padding = 1; /* for the box */
|
||||
int nLines, nCols;
|
||||
countMenuLines( lists, width, padding, &nLines, &nCols );
|
||||
|
||||
if ( width > nCols ) {
|
||||
width = nCols;
|
||||
}
|
||||
|
||||
win = newwin( nLines+(padding*2), width+(padding*2),
|
||||
((winMaxY-nLines-padding-padding)/2), (winMaxX-width)/2 );
|
||||
wclear( win );
|
||||
box( win, '|', '-');
|
||||
|
||||
drawMenuFromList( win, lists, nLines, padding );
|
||||
wrefresh( win );
|
||||
|
||||
CursesMenuHandler handler = NULL;
|
||||
while ( !handler ) {
|
||||
int ch = fgetc( stdin );
|
||||
|
||||
int i;
|
||||
for ( i = 0; !!lists[i]; ++i ) {
|
||||
handler = getHandlerForKey( lists[i], ch );
|
||||
if ( !!handler ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delwin( win );
|
||||
|
||||
touchwin( globals->boardWin );
|
||||
wrefresh( globals->boardWin );
|
||||
MenuList* ml[] = { g_rootMenuListShow, NULL };
|
||||
drawMenuFromList( globals->menuWin, ml, 1, 0 );
|
||||
wrefresh( globals->menuWin );
|
||||
|
||||
return handler != NULL && (*handler)(globals);
|
||||
} /* handleRootKeyShow */
|
||||
|
||||
static XP_Bool
|
||||
handleRootKeyHide( CursesAppGlobals* globals )
|
||||
{
|
||||
globals->doDraw = XP_TRUE;
|
||||
return XP_TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static XP_Bool
|
||||
handleAltLeft( CursesAppGlobals* globals )
|
||||
{
|
||||
|
@ -452,31 +638,6 @@ handleReplace( CursesAppGlobals* globals )
|
|||
return XP_TRUE;
|
||||
} /* handleReplace */
|
||||
|
||||
MenuList sharedMenuList[] = {
|
||||
{ handleQuit, "Quit", "Q", 'Q' },
|
||||
{ handleRight, "Tab right", "<tab>", '\t' },
|
||||
{ handleSpace, "Raise focus", "<spc>", ' ' },
|
||||
{ handleRet, "Click/tap", "<ret>", '\r' },
|
||||
{ handleHint, "Hint", "?", '?' },
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
{ handleLeft, "Left", "H", 'H' },
|
||||
{ handleRight, "Right", "L", 'L' },
|
||||
{ handleUp, "Up", "J", 'J' },
|
||||
{ handleDown, "Down", "K", 'K' },
|
||||
#endif
|
||||
|
||||
{ handleCommit, "Commit move", "C", 'C' },
|
||||
{ handleFlip, "Flip", "F", 'F' },
|
||||
{ handleToggleValues, "Show values", "V", 'V' },
|
||||
|
||||
{ handleBackspace, "Remove from board", "<del>", 8 },
|
||||
{ handleUndo, "Undo prev", "U", 'U' },
|
||||
{ handleReplace, "uNdo cur", "N", 'N' },
|
||||
|
||||
{ NULL, NULL, NULL, '\0'}
|
||||
};
|
||||
|
||||
#ifdef KEYBOARD_NAV
|
||||
static XP_Bool
|
||||
handleFocusKey( CursesAppGlobals* globals, XP_Key key )
|
||||
|
@ -525,109 +686,112 @@ handleDown( CursesAppGlobals* globals )
|
|||
} /* handleDown */
|
||||
#endif
|
||||
|
||||
MenuList boardMenuList[] = {
|
||||
{ handleAltLeft, "Force left", "{", '{' },
|
||||
{ handleAltRight, "Force right", "}", '}' },
|
||||
{ handleAltUp, "Force up", "_", '_' },
|
||||
{ handleAltDown, "Force down", "+", '+' },
|
||||
{ NULL, NULL, NULL, '\0'}
|
||||
};
|
||||
static void
|
||||
fmtMenuItem( const MenuList* item, char* buf, int maxLen )
|
||||
{
|
||||
snprintf( buf, maxLen, "%s %s", item->keyDesc, item->desc );
|
||||
}
|
||||
|
||||
MenuList scoreMenuList[] = {
|
||||
#ifdef KEYBOARD_NAV
|
||||
#endif
|
||||
{ NULL, NULL, NULL, '\0'}
|
||||
};
|
||||
|
||||
MenuList trayMenuList[] = {
|
||||
{ handleJuggle, "Juggle", "G", 'G' },
|
||||
{ handleHide, "[un]hIde", "I", 'I' },
|
||||
{ handleAltLeft, "Divider left", "{", '{' },
|
||||
{ handleAltRight, "Divider right", "}", '}' },
|
||||
|
||||
{ NULL, NULL, NULL, '\0'}
|
||||
};
|
||||
|
||||
static void
|
||||
figureMaxes( MenuList* mList, short maxLines, short* maxKeyP, short* maxCmdP )
|
||||
countMenuLines( MenuList** menuLists, int maxX, int padding,
|
||||
int* nLinesP, int* nColsP )
|
||||
{
|
||||
short i;
|
||||
int nCols = 0;
|
||||
/* The menu space should be wider rather than taller, but line up by
|
||||
column. So we want to use as many columns as possible to minimize the
|
||||
number of lines. So start with one line and lay out. If that doesn't
|
||||
fit, try two. Given the number of lines, get the max width of each
|
||||
column.
|
||||
*/
|
||||
|
||||
*maxKeyP = *maxCmdP = 0;
|
||||
maxX -= padding * 2; /* on left and right side */
|
||||
|
||||
for ( i = 0; i < maxLines && mList->handler != NULL; ++i ) {
|
||||
short keyLen = strlen(mList->keyDesc);
|
||||
short cmdLen = strlen(mList->desc);
|
||||
*maxKeyP = XP_MAX( *maxKeyP, keyLen );
|
||||
*maxCmdP= XP_MAX( *maxCmdP, cmdLen );
|
||||
++mList;
|
||||
int nLines;
|
||||
for ( nLines = 1; ; ++nLines ) {
|
||||
short line = 0;
|
||||
XP_Bool tooFewLines = XP_FALSE;
|
||||
int maxThisCol = 0;
|
||||
int i;
|
||||
nCols = 0;
|
||||
|
||||
for ( i = 0; !tooFewLines && (NULL != menuLists[i]); ++i ) {
|
||||
MenuList* entry;
|
||||
for ( entry = menuLists[i]; !tooFewLines && !!entry->handler;
|
||||
++entry ) {
|
||||
int width;
|
||||
char buf[32];
|
||||
|
||||
/* time to switch to new column? */
|
||||
if ( line == nLines ) {
|
||||
nCols += maxThisCol;
|
||||
if ( nCols > maxX ) {
|
||||
tooFewLines = XP_TRUE;
|
||||
break;
|
||||
}
|
||||
maxThisCol = 0;
|
||||
line = 0;
|
||||
}
|
||||
|
||||
fmtMenuItem( entry, buf, sizeof(buf) );
|
||||
width = strlen(buf) + 2; /* padding */
|
||||
|
||||
if ( maxThisCol < width ) {
|
||||
maxThisCol = width;
|
||||
}
|
||||
|
||||
++line;
|
||||
}
|
||||
}
|
||||
/* If we get here without running out of space, we're done */
|
||||
nCols += maxThisCol;
|
||||
if ( !tooFewLines && (nCols < maxX) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* figureMaxes */
|
||||
|
||||
*nColsP = nCols;
|
||||
*nLinesP = nLines;
|
||||
} /* countMenuLines */
|
||||
|
||||
static void
|
||||
drawMenuFromList( CursesAppGlobals* globals, MenuList* menuList )
|
||||
drawMenuFromList( WINDOW* win, MenuList** menuLists,
|
||||
int nLines, int padding )
|
||||
{
|
||||
short i;
|
||||
short maxKey = 0, maxCmd = 0;
|
||||
short line = 0, col;
|
||||
short nLines;
|
||||
short line = 0, col, i;
|
||||
int winMaxY, winMaxX;
|
||||
WINDOW* win = globals->menuWin;
|
||||
XP_Bool done = XP_FALSE;
|
||||
|
||||
getmaxyx( win, winMaxY, winMaxX );
|
||||
|
||||
nLines = globals->nLinesMenu;
|
||||
if ( nLines == 0 ) {
|
||||
nLines = 1;
|
||||
int maxColWidth = 0;
|
||||
if ( 0 == nLines ) {
|
||||
int ignore;
|
||||
countMenuLines( menuLists, winMaxX, padding, &nLines, &ignore );
|
||||
}
|
||||
col = 0;
|
||||
|
||||
for ( ; !done; ++nLines ) {
|
||||
MenuList* entry = sharedMenuList;
|
||||
XP_Bool isShared = XP_TRUE;
|
||||
for ( i = 0; NULL != menuLists[i]; ++i ) {
|
||||
MenuList* entry;
|
||||
for ( entry = menuLists[i]; !!entry->handler; ++entry ) {
|
||||
char buf[32];
|
||||
|
||||
wclear( win );
|
||||
fmtMenuItem( entry, buf, sizeof(buf) );
|
||||
|
||||
maxKey = maxCmd = 0;
|
||||
for ( line = 0, col = -2, i = 0; ; ++entry, ++line ) {
|
||||
char* key;
|
||||
mvwaddstr( win, line+padding, col+padding, buf );
|
||||
|
||||
if ( entry->handler == NULL ) {
|
||||
if ( !isShared ) {
|
||||
done = XP_TRUE;
|
||||
break;
|
||||
} else if ( menuList->handler == NULL ) {
|
||||
done = XP_TRUE;
|
||||
break;
|
||||
} else {
|
||||
isShared = XP_FALSE;
|
||||
entry = menuList;
|
||||
XP_ASSERT( !!entry->handler );
|
||||
}
|
||||
int width = strlen(buf) + 2;
|
||||
if ( width > maxColWidth ) {
|
||||
maxColWidth = width;
|
||||
}
|
||||
|
||||
XP_ASSERT( nLines > 0 );
|
||||
if ( line % nLines == 0 ) {
|
||||
if ( ++line == nLines ) {
|
||||
line = 0;
|
||||
col += maxKey + maxCmd + 2;
|
||||
figureMaxes( entry, nLines, &maxKey, &maxCmd );
|
||||
if ( (col + maxCmd + strlen(entry->keyDesc)) >= winMaxX ) {
|
||||
break;
|
||||
}
|
||||
col += maxColWidth;
|
||||
maxColWidth = 0;
|
||||
}
|
||||
|
||||
key = entry->keyDesc;
|
||||
|
||||
wstandout( win );
|
||||
mvwaddstr( win, line, col+maxKey-strlen(key), key );
|
||||
wstandend( win );
|
||||
mvwaddstr( win, line, col+maxKey+1, entry->desc );
|
||||
}
|
||||
}
|
||||
|
||||
globals->nLinesMenu = nLines - 1;
|
||||
|
||||
wrefresh( win );
|
||||
} /* drawMenuFromList */
|
||||
|
||||
static void
|
||||
|
@ -642,9 +806,9 @@ SIGWINCH_handler( int signal )
|
|||
/* (*globals.drawMenu)( &globals ); */
|
||||
|
||||
getmaxyx( stdscr, y, x );
|
||||
wresize( globals.mainWin, y-MENU_WINDOW_HEIGHT, x );
|
||||
wresize( g_globals.mainWin, y-MENU_WINDOW_HEIGHT, x );
|
||||
|
||||
board_draw( globals.cGlobals.game.board );
|
||||
board_draw( g_globals.cGlobals.game.board );
|
||||
} /* SIGWINCH_handler */
|
||||
|
||||
static void
|
||||
|
@ -748,7 +912,7 @@ blocking_gotEvent( CursesAppGlobals* globals, int* ch )
|
|||
|
||||
/* stdin first */
|
||||
if ( (globals->fdArray[FD_STDIN].revents & POLLIN) != 0 ) {
|
||||
int evtCh = fgetc(stdin);
|
||||
int evtCh = wgetch(globals->mainWin);
|
||||
XP_LOGF( "%s: got key: %x", __func__, evtCh );
|
||||
*ch = evtCh;
|
||||
result = XP_TRUE;
|
||||
|
@ -854,22 +1018,68 @@ blocking_gotEvent( CursesAppGlobals* globals, int* ch )
|
|||
return result;
|
||||
} /* blocking_gotEvent */
|
||||
|
||||
static void
|
||||
remapKey( int* kp )
|
||||
{
|
||||
/* There's what the manual says I should get, and what I actually do from
|
||||
* a funky M$ keyboard....
|
||||
*/
|
||||
int key = *kp;
|
||||
switch( key ) {
|
||||
case KEY_B2: /* "center of keypad" */
|
||||
key = '\r';
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
case 526:
|
||||
key = 'K';
|
||||
break;
|
||||
case KEY_UP:
|
||||
case 523:
|
||||
key = 'J';
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
case 524:
|
||||
key = 'H';
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
case 525:
|
||||
key = 'L';
|
||||
break;
|
||||
default:
|
||||
if ( key > 0xFF ) {
|
||||
XP_LOGF( "%s(%d): no mapping", __func__, key );
|
||||
}
|
||||
break;
|
||||
}
|
||||
*kp = key;
|
||||
}
|
||||
|
||||
static void
|
||||
drawMenuLargeOrSmall( CursesAppGlobals* globals, const MenuList* menuList )
|
||||
{
|
||||
#ifdef CURSES_SMALL_SCREEN
|
||||
MenuList* lists[] = { g_rootMenuListShow, NULL };
|
||||
#else
|
||||
MenuList* lists[] = { g_sharedMenuList, menuList, NULL };
|
||||
#endif
|
||||
drawMenuFromList( globals->menuWin, lists, 0, 0 );
|
||||
wrefresh( globals->menuWin );
|
||||
}
|
||||
|
||||
static void
|
||||
changeMenuForFocus( CursesAppGlobals* globals, BoardObjectType focussed )
|
||||
{
|
||||
#ifdef KEYBOARD_NAV
|
||||
if ( focussed == OBJ_TRAY ) {
|
||||
globals->menuList = trayMenuList;
|
||||
drawMenuFromList( globals, trayMenuList );
|
||||
globals->menuList = g_trayMenuList;
|
||||
} else if ( focussed == OBJ_BOARD ) {
|
||||
globals->menuList = boardMenuList;
|
||||
drawMenuFromList( globals, boardMenuList );
|
||||
globals->menuList = g_boardMenuList;
|
||||
} else if ( focussed == OBJ_SCORE ) {
|
||||
globals->menuList = scoreMenuList;
|
||||
drawMenuFromList( globals, scoreMenuList );
|
||||
globals->menuList = g_scoreMenuList;
|
||||
} else {
|
||||
XP_ASSERT(0);
|
||||
}
|
||||
drawMenuLargeOrSmall( globals, globals->menuList );
|
||||
#endif
|
||||
} /* changeMenuForFocus */
|
||||
|
||||
|
@ -989,18 +1199,29 @@ sendOnClose( XWStreamCtxt* stream, void* closure )
|
|||
} /* sendOnClose */
|
||||
#endif
|
||||
|
||||
static XP_Bool
|
||||
handleKeyEvent( CursesAppGlobals* globals, MenuList* list, char ch )
|
||||
static CursesMenuHandler
|
||||
getHandlerForKey( MenuList* list, char ch )
|
||||
{
|
||||
CursesMenuHandler handler = NULL;
|
||||
while ( list->handler != NULL ) {
|
||||
if ( list->key == ch ) {
|
||||
if ( (*list->handler)(globals) ) {
|
||||
return XP_TRUE;
|
||||
}
|
||||
handler = list->handler;
|
||||
break;
|
||||
}
|
||||
++list;
|
||||
}
|
||||
return XP_FALSE;
|
||||
return handler;
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
handleKeyEvent( CursesAppGlobals* globals, MenuList* list, char ch )
|
||||
{
|
||||
CursesMenuHandler handler = getHandlerForKey( list, ch );
|
||||
XP_Bool result = XP_FALSE;
|
||||
if ( !!handler ) {
|
||||
result = (*handler)(globals);
|
||||
}
|
||||
return result;
|
||||
} /* handleKeyEvent */
|
||||
|
||||
static XP_Bool
|
||||
|
@ -1015,59 +1236,110 @@ passKeyToBoard( CursesAppGlobals* globals, char ch )
|
|||
return handled;
|
||||
} /* passKeyToBoard */
|
||||
|
||||
static void
|
||||
positionSizeStuff( CursesAppGlobals* globals, int width, int height )
|
||||
{
|
||||
XP_U16 cellWidth, cellHt, scoreLeft, scoreWidth;
|
||||
BoardCtxt* board = globals->cGlobals.game.board;
|
||||
int remWidth = width;
|
||||
|
||||
board_setPos( board, BOARD_OFFSET, BOARD_OFFSET, XP_FALSE );
|
||||
cellWidth = CURSES_CELL_HT;
|
||||
cellHt = CURSES_CELL_WIDTH;
|
||||
board_setScale( board, cellWidth, cellHt );
|
||||
scoreLeft = (cellWidth * MAX_COLS);// + BOARD_SCORE_PADDING;
|
||||
remWidth -= cellWidth * MAX_COLS;
|
||||
|
||||
/* If the scoreboard will right of the board, put it there. Otherwise try
|
||||
to fit it below the boards. */
|
||||
int tileWidth = 3;
|
||||
int trayWidth = (tileWidth*MAX_TRAY_TILES);
|
||||
int trayLeft = scoreLeft;
|
||||
int trayTop;
|
||||
int trayHt = 4;
|
||||
if ( trayWidth < remWidth ) {
|
||||
trayLeft += XP_MIN(remWidth - trayWidth, BOARD_SCORE_PADDING );
|
||||
trayTop = 8;
|
||||
} else {
|
||||
trayLeft = BOARD_OFFSET;
|
||||
trayTop = BOARD_OFFSET + (cellHt * MAX_ROWS);
|
||||
if ( trayTop + trayHt > height ) {
|
||||
trayHt = height - trayTop;
|
||||
}
|
||||
}
|
||||
board_setTrayLoc( board, trayLeft, trayTop, (3*MAX_TRAY_TILES)+1,
|
||||
trayHt, 1 );
|
||||
|
||||
scoreWidth = remWidth;
|
||||
if ( scoreWidth > 45 ) {
|
||||
scoreWidth = 45;
|
||||
scoreLeft += (remWidth - scoreWidth) / 2;
|
||||
}
|
||||
board_setScoreboardLoc( board, scoreLeft, 1,
|
||||
scoreWidth, 5, /*4 players + rem*/ XP_FALSE );
|
||||
|
||||
/* no divider -- yet */
|
||||
/* board_setTrayVisible( globals.board, XP_TRUE, XP_FALSE ); */
|
||||
|
||||
board_invalAll( board );
|
||||
} /* positionSizeStuff */
|
||||
|
||||
void
|
||||
cursesmain( XP_Bool isServer, LaunchParams* params )
|
||||
{
|
||||
int piperesult;
|
||||
DictionaryCtxt* dict;
|
||||
XP_U16 gameID;
|
||||
XP_U16 colWidth, scoreLeft;
|
||||
int width, height;
|
||||
|
||||
memset( &globals, 0, sizeof(globals) );
|
||||
memset( &g_globals, 0, sizeof(g_globals) );
|
||||
|
||||
globals.amServer = isServer;
|
||||
globals.cGlobals.params = params;
|
||||
g_globals.amServer = isServer;
|
||||
g_globals.cGlobals.params = params;
|
||||
#ifdef XWFEATURE_RELAY
|
||||
globals.cGlobals.socket = -1;
|
||||
g_globals.cGlobals.socket = -1;
|
||||
#endif
|
||||
|
||||
globals.cGlobals.socketChanged = curses_socket_changed;
|
||||
globals.cGlobals.socketChangedClosure = &globals;
|
||||
globals.cGlobals.addAcceptor = curses_socket_acceptor;
|
||||
g_globals.cGlobals.socketChanged = curses_socket_changed;
|
||||
g_globals.cGlobals.socketChangedClosure = &g_globals;
|
||||
g_globals.cGlobals.addAcceptor = curses_socket_acceptor;
|
||||
|
||||
globals.cp.showBoardArrow = XP_TRUE;
|
||||
globals.cp.showRobotScores = params->showRobotScores;
|
||||
g_globals.cp.showBoardArrow = XP_TRUE;
|
||||
g_globals.cp.showRobotScores = params->showRobotScores;
|
||||
|
||||
dict = params->dict;
|
||||
|
||||
setupCursesUtilCallbacks( &globals, params->util );
|
||||
setupCursesUtilCallbacks( &g_globals, params->util );
|
||||
|
||||
#ifdef XWFEATURE_RELAY
|
||||
if ( params->conType == COMMS_CONN_RELAY ) {
|
||||
globals.cGlobals.defaultServerName
|
||||
g_globals.cGlobals.defaultServerName
|
||||
= params->connInfo.relay.relayName;
|
||||
}
|
||||
#endif
|
||||
cursesListenOnSocket( &globals, 0 ); /* stdin */
|
||||
cursesListenOnSocket( &g_globals, 0 ); /* stdin */
|
||||
|
||||
piperesult = pipe( globals.timepipe );
|
||||
piperesult = pipe( g_globals.timepipe );
|
||||
XP_ASSERT( piperesult == 0 );
|
||||
|
||||
/* reader pipe */
|
||||
cursesListenOnSocket( &globals, globals.timepipe[0] );
|
||||
cursesListenOnSocket( &g_globals, g_globals.timepipe[0] );
|
||||
signal( SIGWINCH, SIGWINCH_handler );
|
||||
initCurses( &globals );
|
||||
|
||||
globals.draw = (struct CursesDrawCtx*)cursesDrawCtxtMake( globals.boardWin );
|
||||
initCurses( &g_globals );
|
||||
getmaxyx( g_globals.boardWin, height, width );
|
||||
|
||||
g_globals.draw = (struct CursesDrawCtx*)
|
||||
cursesDrawCtxtMake( g_globals.boardWin );
|
||||
|
||||
gameID = (XP_U16)util_getCurSeconds( globals.cGlobals.params->util );
|
||||
game_makeNewGame( MEMPOOL &globals.cGlobals.game, ¶ms->gi,
|
||||
params->util, (DrawCtx*)globals.draw,
|
||||
gameID, &globals.cp, LINUX_SEND,
|
||||
IF_CH(linux_reset) &globals );
|
||||
gameID = (XP_U16)util_getCurSeconds( g_globals.cGlobals.params->util );
|
||||
game_makeNewGame( MEMPOOL &g_globals.cGlobals.game, ¶ms->gi,
|
||||
params->util, (DrawCtx*)g_globals.draw,
|
||||
gameID, &g_globals.cp, LINUX_SEND,
|
||||
IF_CH(linux_reset) &g_globals );
|
||||
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
if ( globals.cGlobals.game.comms ) {
|
||||
if ( g_globals.cGlobals.game.comms ) {
|
||||
CommsAddrRec addr;
|
||||
|
||||
if ( 0 ) {
|
||||
|
@ -1090,60 +1362,52 @@ cursesmain( XP_Bool isServer, LaunchParams* params )
|
|||
sizeof(params->connInfo.bt.hostAddr) );
|
||||
# endif
|
||||
}
|
||||
comms_setAddr( globals.cGlobals.game.comms, &addr );
|
||||
comms_setAddr( g_globals.cGlobals.game.comms, &addr );
|
||||
}
|
||||
#endif
|
||||
|
||||
model_setDictionary( globals.cGlobals.game.model, params->dict );
|
||||
model_setDictionary( g_globals.cGlobals.game.model, params->dict );
|
||||
|
||||
board_setPos( globals.cGlobals.game.board, 1, 1, XP_FALSE );
|
||||
colWidth = 2;
|
||||
board_setScale( globals.cGlobals.game.board, colWidth, 1 );
|
||||
scoreLeft = (colWidth * MAX_COLS) + 3;
|
||||
board_setScoreboardLoc( globals.cGlobals.game.board,
|
||||
scoreLeft, 1,
|
||||
45, 5, /*4 players + rem*/ XP_FALSE );
|
||||
|
||||
board_setTrayLoc( globals.cGlobals.game.board,
|
||||
scoreLeft, 8, (3*MAX_TRAY_TILES)+1,
|
||||
4, 1 );
|
||||
/* no divider -- yet */
|
||||
/* board_setTrayVisible( globals.board, XP_TRUE, XP_FALSE ); */
|
||||
|
||||
board_invalAll( globals.cGlobals.game.board );
|
||||
positionSizeStuff( &g_globals, width, height );
|
||||
|
||||
#ifndef XWFEATURE_STANDALONE_ONLY
|
||||
/* send any events that need to get off before the event loop begins */
|
||||
if ( !isServer ) {
|
||||
if ( 1 /* stream_open( params->info.clientInfo.stream ) */) {
|
||||
server_initClientConnection( globals.cGlobals.game.server,
|
||||
server_initClientConnection( g_globals.cGlobals.game.server,
|
||||
mem_stream_make( MEMPOOL
|
||||
params->vtMgr,
|
||||
&globals,
|
||||
&g_globals,
|
||||
(XP_PlayerAddr)0,
|
||||
sendOnClose ) );
|
||||
} else {
|
||||
cursesUserError( &globals, "Unable to open connection to server");
|
||||
cursesUserError( &g_globals, "Unable to open connection to server");
|
||||
exit( 0 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
server_do( globals.cGlobals.game.server );
|
||||
server_do( g_globals.cGlobals.game.server );
|
||||
|
||||
globals.menuList = boardMenuList;
|
||||
drawMenuFromList( &globals, boardMenuList );
|
||||
board_draw( globals.cGlobals.game.board );
|
||||
g_globals.menuList = g_boardMenuList;
|
||||
drawMenuLargeOrSmall( &g_globals, g_boardMenuList );
|
||||
board_draw( g_globals.cGlobals.game.board );
|
||||
|
||||
while ( !globals.timeToExit ) {
|
||||
while ( !g_globals.timeToExit ) {
|
||||
int ch;
|
||||
if ( blocking_gotEvent( &globals, &ch )
|
||||
&& (handleKeyEvent( &globals, globals.menuList, ch )
|
||||
|| handleKeyEvent( &globals, sharedMenuList, ch )
|
||||
|| passKeyToBoard( &globals, ch ) ) ) {
|
||||
if ( globals.doDraw ) {
|
||||
board_draw( globals.cGlobals.game.board );
|
||||
globals.doDraw = XP_FALSE;
|
||||
if ( blocking_gotEvent( &g_globals, &ch ) ) {
|
||||
remapKey( &ch );
|
||||
if (
|
||||
#ifdef CURSES_SMALL_SCREEN
|
||||
handleKeyEvent( &g_globals, g_rootMenuListShow, ch ) ||
|
||||
#endif
|
||||
handleKeyEvent( &g_globals, g_globals.menuList, ch )
|
||||
|| handleKeyEvent( &g_globals, g_sharedMenuList, ch )
|
||||
|| passKeyToBoard( &g_globals, ch ) ) {
|
||||
if ( g_globals.doDraw ) {
|
||||
board_draw( g_globals.cGlobals.game.board );
|
||||
g_globals.doDraw = XP_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue