xwords/wince/ceprefs.c
ehouse 2744bcef97 Work around what appears to be smartphone bug where grouped radio
buttons are not kept in sync by manually unchecking one when the
other's selected. Also add terminating WS_GROUP bits; they're supposed
to be there, but did not help.
2008-05-11 13:58:04 +00:00

350 lines
12 KiB
C
Executable file

/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */
/*
* Copyright 2002 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include "ceprefs.h"
#include "cemain.h"
#include "ceclrsel.h"
#include "ceutil.h"
#include "debhacks.h"
#include "cedebug.h"
/* Stuff the strings for phonies. Why can't I put this in the resource?
*/
static void
stuffPhoniesList( HWND hDlg )
{
XP_U16 i;
wchar_t* strings[] = {
L"Ignore",
L"Warn",
L"Disallow"
};
for ( i = 0; i < 3; ++i ) {
SendDlgItemMessage( hDlg, PHONIES_COMBO, ADDSTRING,
0, (long)strings[i] );
}
} /* stuffPhoniesList */
static void
turnOnOff( HWND hDlg, XP_U16* idList, XP_U16 idCount,
XP_Bool turnOn )
{
XP_U16 i;
for ( i = 0; i < idCount; ++i ) {
ceShowOrHide( hDlg, *idList++, turnOn );
}
} /* turnOff */
static void
setTimerCtls( HWND hDlg, XP_Bool checked )
{
ceShowOrHide( hDlg, TIMER_EDIT, checked );
SendDlgItemMessage( hDlg, TIMER_CHECK, BM_SETCHECK,
checked? BST_CHECKED:BST_UNCHECKED, 0 );
} /* setTimerCtls */
static void
adjustForChoice( HWND hDlg, CePrefsDlgState* state )
{
XP_U16 goesWithGlobal[] = {IDC_CHECKCOLORPLAYED, IDC_LEFTYCHECK,
IDC_CHECKSHOWCURSOR, IDC_CHECKROBOTSCORES,
IDC_PREFCOLORS };
XP_U16 goesWithLocal[] = {IDC_CHECKSMARTROBOT, IDC_CHECKNOHINTS,
TIMER_CHECK, TIMER_EDIT, PHONIES_LABEL,
PHONIES_COMBO, IDC_PHONIESUPDOWN, IDC_PICKTILES
#ifdef XWFEATURE_SEARCHLIMIT
,IDC_CHECKHINTSLIMITS
#endif
};
XP_U16 resID;
XP_Bool doGlobalPrefs = state->globals->doGlobalPrefs;
resID = doGlobalPrefs? IDC_RADIOGLOBAL:IDC_RADIOLOCAL;
SendDlgItemMessage( hDlg, resID, BM_SETCHECK, BST_CHECKED, 0L );
resID = doGlobalPrefs? IDC_RADIOLOCAL:IDC_RADIOGLOBAL;
SendDlgItemMessage( hDlg, resID, BM_SETCHECK, BST_UNCHECKED, 0L );
if ( doGlobalPrefs ) {
turnOnOff( hDlg, goesWithLocal, VSIZE(goesWithLocal), XP_FALSE );
turnOnOff( hDlg, goesWithGlobal, VSIZE(goesWithGlobal), XP_TRUE);
} else {
turnOnOff( hDlg, goesWithGlobal, VSIZE(goesWithGlobal), XP_FALSE );
turnOnOff( hDlg, goesWithLocal, VSIZE(goesWithLocal), XP_TRUE);
}
if ( !doGlobalPrefs ) {
setTimerCtls( hDlg, ceGetChecked( hDlg, TIMER_CHECK ) );
#ifdef XWFEATURE_SEARCHLIMIT
ceShowOrHide( hDlg, IDC_CHECKHINTSLIMITS,
!ceGetChecked( hDlg, IDC_CHECKNOHINTS) );
#endif
}
} /* adjustForChoice */
/* Copy global state into a local copy that can be changed without
* committing should user cancel.
*/
void
loadStateFromCurPrefs( CEAppGlobals* XP_UNUSED_STANDALONE(globals),
const CEAppPrefs* appPrefs,
const CurGameInfo* gi, CePrefsPrefs* prefsPrefs )
{
prefsPrefs->gp.hintsNotAllowed = gi->hintsNotAllowed;
prefsPrefs->gp.robotSmartness = gi->robotSmartness;
prefsPrefs->gp.timerEnabled = gi->timerEnabled;
prefsPrefs->gp.gameSeconds = gi->gameSeconds;
prefsPrefs->gp.phoniesAction = gi->phoniesAction;
#ifdef FEATURE_TRAY_EDIT
prefsPrefs->gp.allowPickTiles = gi->allowPickTiles;
#endif
#ifdef XWFEATURE_SEARCHLIMIT
prefsPrefs->gp.allowHintRect = gi->allowHintRect;
#endif
prefsPrefs->showColors = appPrefs->showColors;
XP_MEMCPY( &prefsPrefs->cp, &appPrefs->cp, sizeof(prefsPrefs->cp) );
XP_MEMCPY( &prefsPrefs->colors, &appPrefs->colors,
sizeof(prefsPrefs->colors) );
#if defined XWFEATURE_RELAY || defined XWFEATURE_BLUETOOTH
if ( globals->game.comms != NULL ) {
comms_getAddr( globals->game.comms, &prefsPrefs->addrRec );
} else {
comms_getInitialAddr( &prefsPrefs->addrRec );
}
#endif
} /* loadStateFromCurPrefs */
void
loadCurPrefsFromState( CEAppGlobals* XP_UNUSED_STANDALONE(globals),
CEAppPrefs* appPrefs,
CurGameInfo* gi, const CePrefsPrefs* prefsPrefs )
{
gi->hintsNotAllowed = prefsPrefs->gp.hintsNotAllowed;
gi->robotSmartness = prefsPrefs->gp.robotSmartness;
gi->timerEnabled = prefsPrefs->gp.timerEnabled;
gi->gameSeconds = prefsPrefs->gp.gameSeconds;
gi->phoniesAction = prefsPrefs->gp.phoniesAction;
#ifdef FEATURE_TRAY_EDIT
gi->allowPickTiles = prefsPrefs->gp.allowPickTiles;
#endif
#ifdef XWFEATURE_SEARCHLIMIT
gi->allowHintRect = prefsPrefs->gp.allowHintRect;
#endif
appPrefs->showColors = prefsPrefs->showColors;
XP_MEMCPY( &appPrefs->cp, &prefsPrefs->cp, sizeof(appPrefs->cp) );
XP_MEMCPY( &appPrefs->colors, &prefsPrefs->colors,
sizeof(prefsPrefs->colors) );
#ifndef XWFEATURE_STANDALONE_ONLY
/* I don't think this'll work... */
if ( globals->game.comms != NULL ) {
comms_setAddr( globals->game.comms, &prefsPrefs->addrRec );
} else {
XP_LOGF( "no comms to set addr on!!!" );
}
#endif
} /* loadCurPrefsFromState */
/* Reflect local state into the controls user will see.
*/
static void
loadControlsFromState( HWND hDlg, CePrefsDlgState* pState )
{
CePrefsPrefs* prefsPrefs = &pState->prefsPrefs;
ceSetChecked( hDlg, IDC_CHECKCOLORPLAYED, prefsPrefs->showColors );
ceSetChecked( hDlg, IDC_CHECKSMARTROBOT,
prefsPrefs->gp.robotSmartness > 0 );
ceSetChecked( hDlg, IDC_CHECKNOHINTS, prefsPrefs->gp.hintsNotAllowed );
ceSetChecked( hDlg, IDC_CHECKSHOWCURSOR, prefsPrefs->cp.showBoardArrow );
ceSetChecked( hDlg, IDC_CHECKROBOTSCORES, prefsPrefs->cp.showRobotScores );
#ifdef FEATURE_TRAY_EDIT
ceSetChecked( hDlg, IDC_PICKTILES, prefsPrefs->gp.allowPickTiles );
#endif
#ifdef XWFEATURE_SEARCHLIMIT
ceSetChecked( hDlg, IDC_CHECKHINTSLIMITS, prefsPrefs->gp.allowHintRect );
#endif
/* timer */
ceSetDlgItemNum( hDlg, TIMER_EDIT, prefsPrefs->gp.gameSeconds / 60 );
SendDlgItemMessage( hDlg, PHONIES_COMBO, SETCURSEL,
prefsPrefs->gp.phoniesAction, 0L );
if ( !pState->isNewGame ) {
XP_U16 unavail[] = { TIMER_CHECK, TIMER_EDIT, IDC_CHECKNOHINTS
#ifdef FEATURE_TRAY_EDIT
,IDC_PICKTILES
#endif
};
XP_U16 i;
for ( i = 0; i < VSIZE(unavail); ++i ) {
ceEnOrDisable( hDlg, unavail[i], XP_FALSE );
}
}
} /* loadControlsFromState */
/* Save the new choices into state so caller can do what it wants with
* the values.
*/
static void
ceControlsToPrefs( HWND hDlg, CePrefsPrefs* prefsPrefs )
{
XP_S16 selIndex;
prefsPrefs->showColors = ceGetChecked( hDlg, IDC_CHECKCOLORPLAYED );
prefsPrefs->gp.robotSmartness
= ceGetChecked( hDlg, IDC_CHECKSMARTROBOT ) ? 1 : 0;
prefsPrefs->gp.hintsNotAllowed = ceGetChecked( hDlg, IDC_CHECKNOHINTS );
selIndex = (XP_U16)SendDlgItemMessage( hDlg, PHONIES_COMBO, GETCURSEL,
0, 0 );
if ( selIndex != LB_ERR ) {
prefsPrefs->gp.phoniesAction = (XWPhoniesChoice)selIndex;
}
prefsPrefs->cp.showBoardArrow = ceGetChecked( hDlg, IDC_CHECKSHOWCURSOR );
prefsPrefs->cp.showRobotScores = ceGetChecked( hDlg, IDC_CHECKROBOTSCORES );
prefsPrefs->gp.timerEnabled = ceGetChecked( hDlg, TIMER_CHECK );
if ( prefsPrefs->gp.timerEnabled ) {
XP_U16 minutes;
minutes = ceGetDlgItemNum( hDlg, TIMER_EDIT );
prefsPrefs->gp.gameSeconds = minutes * 60;
}
#ifdef FEATURE_TRAY_EDIT
prefsPrefs->gp.allowPickTiles = ceGetChecked( hDlg, IDC_PICKTILES );
#endif
#ifdef XWFEATURE_SEARCHLIMIT
prefsPrefs->gp.allowHintRect = ceGetChecked( hDlg, IDC_CHECKHINTSLIMITS );
#endif
} /* ceControlsToPrefs */
LRESULT CALLBACK
PrefsDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
CEAppGlobals* globals;
XP_U16 id;
CePrefsDlgState* pState;
if ( message == WM_INITDIALOG ) {
SetWindowLong( hDlg, GWL_USERDATA, lParam );
pState = (CePrefsDlgState*)lParam;
globals = pState->globals;
stuffPhoniesList( hDlg );
loadControlsFromState( hDlg, pState );
adjustForChoice( hDlg, pState );
ceDlgSetup( globals, hDlg );
return TRUE;
} else {
XP_Bool timerOn;
pState = (CePrefsDlgState*)GetWindowLong( hDlg, GWL_USERDATA );
if ( !!pState ) {
globals = pState->globals;
switch (message) {
case WM_VSCROLL:
ceDoDlgScroll( globals, hDlg, wParam );
break;
case WM_NEXTDLGCTL:
ceDoDlgFocusScroll( globals, hDlg, wParam, lParam );
break;
case WM_COMMAND:
id = LOWORD(wParam);
switch( id ) {
case IDC_RADIOGLOBAL:
case IDC_RADIOLOCAL:
pState->globals->doGlobalPrefs = id == IDC_RADIOGLOBAL;
adjustForChoice( hDlg, pState );
break;
case TIMER_CHECK:
timerOn = SendDlgItemMessage( hDlg, TIMER_CHECK, BM_GETCHECK,
0, 0 );
setTimerCtls( hDlg, timerOn );
break;
case IDC_PREFCOLORS:
pState->colorsChanged =
ceDoColorsEdit( hDlg, pState->globals,
pState->prefsPrefs.colors );
break;
#ifdef XWFEATURE_SEARCHLIMIT
case IDC_CHECKNOHINTS:
timerOn = SendDlgItemMessage( hDlg, IDC_CHECKNOHINTS,
BM_GETCHECK, 0, 0 );
ceShowOrHide( hDlg, IDC_CHECKHINTSLIMITS, !timerOn );
break;
#endif
case IDOK:
ceControlsToPrefs( hDlg, &pState->prefsPrefs );
case IDCANCEL:
EndDialog(hDlg, id);
pState->userCancelled = id == IDCANCEL;
return TRUE;
}
}
}
}
return FALSE;
} /* PrefsDlg */
/* Using state in prefsPrefs, and initing and then storing dialog state in
state, put up the dialog and return whether it was cancelled.
*/
XP_Bool
WrapPrefsDialog( HWND hDlg, CEAppGlobals* globals, CePrefsDlgState* state,
CePrefsPrefs* prefsPrefs, XP_Bool isNewGame )
{
XP_Bool result;
XP_MEMSET( state, 0, sizeof(*state) );
state->globals = globals;
state->isNewGame = isNewGame;
XP_MEMCPY( &state->prefsPrefs, prefsPrefs, sizeof( state->prefsPrefs ) );
DialogBoxParam( globals->hInst, (LPCTSTR)IDD_OPTIONSDLG, hDlg,
(DLGPROC)PrefsDlg, (long)state );
result = !state->userCancelled;
if ( result ) {
XP_MEMCPY( prefsPrefs, &state->prefsPrefs, sizeof( *prefsPrefs ) );
}
return result;
} /* WrapPrefsDialog */