mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2024-12-27 09:58:45 +01:00
8f08667f5d
work now including saving/opening games. Network play probably doesn't as writing/reading a dict from stream has to change. It's doubtful patches from this branch will be merged. Rather, I'll take the concepts and crib some code when re-implementing. Concepts: XP_UCHAR becomes UTF-8 on both platforms, and on wince we translate to wchar_t just as now but from the utf-8 codepage. That keeps the work and risk to a minimum.
383 lines
13 KiB
C
Executable file
383 lines
13 KiB
C
Executable file
/* -*-mode: C; fill-column: 77; c-basic-offset: 4; -*- */
|
|
/*
|
|
* Copyright 2002-2009 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"
|
|
#include "cefonts.h"
|
|
|
|
/* Stuff the strings for phonies. Why can't I put this in the resource?
|
|
*/
|
|
static void
|
|
stuffPhoniesList( CePrefsDlgState* state )
|
|
{
|
|
HWND hDlg = state->dlgHdr.hDlg;
|
|
CEAppGlobals* globals = state->dlgHdr.globals;
|
|
XP_U16 ii;
|
|
wchar_t* strings[] = {
|
|
L"Ignore",
|
|
L"Warn",
|
|
L"Disallow"
|
|
};
|
|
|
|
for ( ii = 0; ii < 3; ++ii ) {
|
|
SendDlgItemMessage( hDlg, state->phonComboId,
|
|
ADDSTRING(globals), ii, (long)strings[ii] );
|
|
}
|
|
} /* 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( CePrefsDlgState* state )
|
|
{
|
|
HWND hDlg = state->dlgHdr.hDlg;
|
|
XP_U16 goesWithGlobal[] = {IDC_CHECKCOLORPLAYED, IDC_LEFTYCHECK,
|
|
IDC_CHECKSHOWCURSOR, IDC_CHECKROBOTSCORES,
|
|
IDC_HIDETILEVALUES, IDC_PREFCOLORS
|
|
#ifdef ALLOW_CHOOSE_FONTS
|
|
,IDC_PREFFONTS
|
|
#endif
|
|
|
|
};
|
|
XP_U16 goesWithLocal[] = {IDC_CHECKSMARTROBOT, IDC_CHECKHINTSOK,
|
|
TIMER_CHECK, TIMER_EDIT, PHONIES_LABEL,
|
|
PHONIES_COMBO, IDC_PHONIESUPDOWN,
|
|
PHONIES_COMBO_PPC,
|
|
IDC_PICKTILES
|
|
#ifdef XWFEATURE_SEARCHLIMIT
|
|
,IDC_CHECKHINTSLIMITS
|
|
#endif
|
|
};
|
|
XP_U16 resID;
|
|
XP_Bool doGlobalPrefs = state->dlgHdr.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_CHECKHINTSOK) );
|
|
#endif
|
|
ceDlgComboShowHide( &state->dlgHdr, PHONIES_COMBO );
|
|
}
|
|
} /* 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) );
|
|
|
|
#ifndef XWFEATURE_STANDALONE_ONLY
|
|
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( CePrefsDlgState* pState )
|
|
{
|
|
HWND hDlg = pState->dlgHdr.hDlg;
|
|
CEAppGlobals* globals = pState->dlgHdr.globals;
|
|
CePrefsPrefs* prefsPrefs = &pState->prefsPrefs;
|
|
|
|
ceSetChecked( hDlg, IDC_CHECKCOLORPLAYED, prefsPrefs->showColors );
|
|
ceSetChecked( hDlg, IDC_CHECKSMARTROBOT,
|
|
prefsPrefs->gp.robotSmartness > 0 );
|
|
ceSetChecked( hDlg, IDC_CHECKHINTSOK, !prefsPrefs->gp.hintsNotAllowed );
|
|
|
|
ceSetChecked( hDlg, IDC_CHECKSHOWCURSOR, prefsPrefs->cp.showBoardArrow );
|
|
ceSetChecked( hDlg, IDC_CHECKROBOTSCORES, prefsPrefs->cp.showRobotScores );
|
|
ceSetChecked( hDlg, IDC_HIDETILEVALUES, prefsPrefs->cp.hideTileValues );
|
|
|
|
#ifdef FEATURE_TRAY_EDIT
|
|
ceSetChecked( hDlg, IDC_PICKTILES, prefsPrefs->gp.allowPickTiles );
|
|
#endif
|
|
#ifdef XWFEATURE_SEARCHLIMIT
|
|
if ( !IS_SMARTPHONE(globals) ) {
|
|
ceSetChecked( hDlg, IDC_CHECKHINTSLIMITS, prefsPrefs->gp.allowHintRect );
|
|
}
|
|
#endif
|
|
/* timer */
|
|
ceSetDlgItemNum( hDlg, TIMER_EDIT, prefsPrefs->gp.gameSeconds / 60 );
|
|
|
|
SendDlgItemMessage( hDlg, pState->phonComboId, SETCURSEL(globals),
|
|
prefsPrefs->gp.phoniesAction, 0L );
|
|
|
|
if ( !pState->isNewGame ) {
|
|
XP_U16 unavail[] = { TIMER_CHECK, TIMER_EDIT, IDC_CHECKHINTSOK
|
|
#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( CePrefsDlgState* state )
|
|
{
|
|
XP_S16 selIndex;
|
|
CePrefsPrefs* prefsPrefs = &state->prefsPrefs;
|
|
HWND hDlg = state->dlgHdr.hDlg;
|
|
CEAppGlobals* globals = state->dlgHdr.globals;
|
|
|
|
prefsPrefs->showColors = ceGetChecked( hDlg, IDC_CHECKCOLORPLAYED );
|
|
prefsPrefs->gp.robotSmartness
|
|
= ceGetChecked( hDlg, IDC_CHECKSMARTROBOT ) ? 1 : 0;
|
|
prefsPrefs->gp.hintsNotAllowed = !ceGetChecked( hDlg, IDC_CHECKHINTSOK );
|
|
|
|
selIndex = (XP_U16)SendDlgItemMessage( hDlg, state->phonComboId,
|
|
GETCURSEL(globals),
|
|
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->cp.hideTileValues = ceGetChecked( hDlg, IDC_HIDETILEVALUES );
|
|
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
|
|
if ( !IS_SMARTPHONE(globals) ) {
|
|
prefsPrefs->gp.allowHintRect = ceGetChecked( hDlg, IDC_CHECKHINTSLIMITS );
|
|
}
|
|
#endif
|
|
} /* ceControlsToPrefs */
|
|
|
|
LRESULT CALLBACK
|
|
PrefsDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
XP_U16 id;
|
|
CePrefsDlgState* pState;
|
|
|
|
if ( message == WM_INITDIALOG ) {
|
|
SetWindowLongPtr( hDlg, GWL_USERDATA, lParam );
|
|
pState = (CePrefsDlgState*)lParam;
|
|
|
|
pState->phonComboId = LB_IF_PPC(pState->dlgHdr.globals,PHONIES_COMBO);
|
|
|
|
ceDlgSetup( &pState->dlgHdr, hDlg, DLG_STATE_TRAPBACK );
|
|
ceDlgComboShowHide( &pState->dlgHdr, PHONIES_COMBO );
|
|
|
|
stuffPhoniesList( pState );
|
|
|
|
loadControlsFromState( pState );
|
|
|
|
adjustForChoice( pState );
|
|
return TRUE;
|
|
|
|
} else {
|
|
pState = (CePrefsDlgState*)GetWindowLongPtr( hDlg, GWL_USERDATA );
|
|
if ( !!pState ) {
|
|
if ( !ceDoDlgHandle( &pState->dlgHdr, message, wParam, lParam ) ) {
|
|
CEAppGlobals* globals = pState->dlgHdr.globals;
|
|
XP_Bool timerOn;
|
|
|
|
switch (message) {
|
|
case WM_COMMAND:
|
|
id = LOWORD(wParam);
|
|
switch( id ) {
|
|
|
|
case IDC_RADIOGLOBAL:
|
|
case IDC_RADIOLOCAL:
|
|
globals->doGlobalPrefs = id == IDC_RADIOGLOBAL;
|
|
adjustForChoice( 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, globals,
|
|
pState->prefsPrefs.colors );
|
|
break;
|
|
#ifdef ALLOW_CHOOSE_FONTS
|
|
case IDC_PREFFONTS:
|
|
ceShowFonts( hDlg, globals );
|
|
break;
|
|
#endif
|
|
|
|
#ifdef XWFEATURE_SEARCHLIMIT
|
|
case IDC_CHECKHINTSOK:
|
|
timerOn = SendDlgItemMessage( hDlg, IDC_CHECKHINTSOK,
|
|
BM_GETCHECK, 0, 0 );
|
|
ceShowOrHide( hDlg, IDC_CHECKHINTSLIMITS, timerOn );
|
|
break;
|
|
case IDC_CHECKHINTSLIMITS:
|
|
if ( IS_SMARTPHONE(globals) ) {
|
|
ceMessageBoxChar( globals, XP_L("This feature ")
|
|
"requires a touch screen.",
|
|
L"Sorry", MB_OK | MB_ICONHAND );
|
|
ceSetChecked( hDlg, IDC_CHECKHINTSLIMITS, XP_FALSE );
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case IDOK:
|
|
ceControlsToPrefs( pState );
|
|
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->dlgHdr.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 */
|