xwords/xwords4/wince/ceutil.c
ehouse 885e7f0192 Put back "turn done" menu, and add call to change the left softkey.
Call it when turn changes, new game is begun, and hint feature has
been used.  Currently menuitem is duplicated.  Goal is to remove the
item being attached to the left button and to replace it when another
is chosen.
2008-02-26 13:49:41 +00:00

419 lines
12 KiB
C
Executable file

/* -*- fill-column: 77; c-basic-offset: 4; compile-command: "make TARGET_OS=wince DEBUG=TRUE" -*- */
/*
* Copyright 2002-2004 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 "stdafx.h"
#include <commctrl.h>
#include "ceutil.h"
#include "cedefines.h"
#define BUF_SIZE 128
#define VPADDING 4
#define HPADDING_L 2
#define HPADDING_R 3
void
ceSetDlgItemText( HWND hDlg, XP_U16 id, const XP_UCHAR* buf )
{
wchar_t widebuf[BUF_SIZE];
XP_U16 len;
XP_ASSERT( buf != NULL );
len = (XP_U16)XP_STRLEN( buf );
if ( len >= BUF_SIZE ) {
len = BUF_SIZE - 1;
}
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, buf, len, widebuf, len );
widebuf[len] = 0;
SendDlgItemMessage( hDlg, id, WM_SETTEXT, 0, (long)widebuf );
} /* ceSetDlgItemText */
void
ceSetDlgItemFileName( HWND hDlg, XP_U16 id, XP_UCHAR* str )
{
XP_UCHAR* stripstart;
XP_UCHAR buf[BUF_SIZE];
XP_U16 len = XP_STRLEN(str);
if ( len >= BUF_SIZE ) {
len = BUF_SIZE - 1;
}
XP_MEMCPY( buf, str, len );
buf[len] = '\0';
stripstart = strrchr( (const char*)buf, '.' );
if ( !!stripstart ) {
*stripstart = '\0';
}
ceSetDlgItemText( hDlg, id, buf );
} /* ceSetDlgItemFileName */
void
ceGetDlgItemText( HWND hDlg, XP_U16 id, XP_UCHAR* buf, XP_U16* bLen )
{
XP_U16 len = *bLen;
XP_U16 gotLen;
wchar_t wbuf[BUF_SIZE];
XP_ASSERT( len <= BUF_SIZE );
gotLen = (XP_U16)SendDlgItemMessage( hDlg, id, WM_GETTEXT, len,
(long)wbuf );
if ( gotLen > 0 ) {
XP_ASSERT( gotLen < len );
if ( gotLen >= len ) {
gotLen = len - 1;
}
gotLen = WideCharToMultiByte( CP_ACP, 0, wbuf, gotLen,
buf, len, NULL, NULL );
*bLen = gotLen;
buf[gotLen] = '\0';
} else {
buf[0] = '\0';
*bLen = 0;
}
} /* ceGetDlgItemText */
void
ceSetDlgItemNum( HWND hDlg, XP_U16 id, XP_S32 num )
{
XP_UCHAR buf[20];
XP_SNPRINTF( buf, sizeof(buf), "%ld", num );
ceSetDlgItemText( hDlg, id, buf );
} /* ceSetDlgItemNum */
XP_S32
ceGetDlgItemNum( HWND hDlg, XP_U16 id )
{
XP_S32 result = 0;
XP_UCHAR buf[24];
XP_U16 len = sizeof(buf);
ceGetDlgItemText( hDlg, id, buf, &len );
result = atoi( buf );
return result;
} /* ceGetDlgItemNum */
void
ce_selectAndShow( HWND hDlg, XP_U16 resID, XP_U16 index )
{
SendDlgItemMessage( hDlg, resID, LB_SETCURSEL, index, 0 );
SendDlgItemMessage( hDlg, resID, LB_SETANCHORINDEX, index, 0 );
} /* ce_selectAndShow */
void
ceShowOrHide( HWND hDlg, XP_U16 resID, XP_Bool visible )
{
HWND itemH = GetDlgItem( hDlg, resID );
if ( !!itemH ) {
ShowWindow( itemH, visible? SW_SHOW: SW_HIDE );
}
} /* ceShowOrHide */
void
ceEnOrDisable( HWND hDlg, XP_U16 resID, XP_Bool enable )
{
HWND itemH = GetDlgItem( hDlg, resID );
if ( !!itemH ) {
EnableWindow( itemH, enable );
}
} /* ceShowOrHide */
void
ceSetChecked( HWND hDlg, XP_U16 resID, XP_Bool check )
{
SendDlgItemMessage( hDlg, resID, BM_SETCHECK,
check? BST_CHECKED:BST_UNCHECKED, 0L );
} /* ceSetBoolCheck */
XP_Bool
ceGetChecked( HWND hDlg, XP_U16 resID )
{
XP_U16 checked;
checked = (XP_U16)SendDlgItemMessage( hDlg, resID, BM_GETCHECK, 0, 0L );
return checked == BST_CHECKED;
} /* ceGetChecked */
/* Return dlg-relative rect.
*/
static void
GetItemRect( HWND hDlg, XP_U16 resID, RECT* rect )
{
RECT dlgRect;
HWND itemH = GetDlgItem( hDlg, resID );
XP_U16 clientHt, winHt;
GetClientRect( hDlg, &dlgRect );
clientHt = dlgRect.bottom;
GetWindowRect( hDlg, &dlgRect );
winHt = dlgRect.bottom - dlgRect.top;
GetWindowRect( itemH, rect );
/* GetWindowRect includes the title bar, but functions like MoveWindow
set relative to the client area below it. So subtract out the
difference between window ht and client rect ht -- the title bar --
when returning the item's rect. */
(void)OffsetRect( rect, -dlgRect.left,
-(dlgRect.top + winHt - clientHt) );
} /* GetItemRect */
void
ceCenterCtl( HWND hDlg, XP_U16 resID )
{
RECT buttonR, dlgR;
HWND itemH = GetDlgItem( hDlg, resID );
XP_U16 newX, buttonWidth;
GetClientRect( hDlg, &dlgR );
XP_ASSERT( dlgR.left == 0 && dlgR.top == 0 );
GetItemRect( hDlg, resID, &buttonR );
buttonWidth = buttonR.right - buttonR.left;
newX = ( dlgR.right - buttonWidth ) / 2;
if ( !MoveWindow( itemH, newX, buttonR.top,
buttonWidth,
buttonR.bottom - buttonR.top, TRUE ) ) {
XP_LOGF( "MoveWindow=>%d", GetLastError() );
}
} /* ceCenterCtl */
XP_Bool
ceIsLandscape( CEAppGlobals* globals )
{
XP_U16 width, height;
XP_Bool landscape;
XP_ASSERT( !!globals );
XP_ASSERT( !!globals->hWnd );
if ( 0 ) {
#if defined DEBUG && !defined _WIN32_WCE
} else if ( globals->dbWidth != 0 ) {
width = globals->dbWidth;
height = globals->dbHeight;
#endif
} else {
RECT rect;
GetClientRect( globals->hWnd, &rect );
width = (XP_U16)(rect.right - rect.left);
height = (XP_U16)(rect.bottom - rect.top);
}
landscape = (height - CE_SCORE_HEIGHT)
< (width - CE_MIN_SCORE_WIDTH);
return landscape;
} /* ceIsLandscape */
/* Can't figure out how to do this on CE. IsWindowVisible doesn't work, and
GetWindowInfo isn't even there. */
static XP_Bool
ceIsVisible( HWND XP_UNUSED_CE(hwnd) )
{
#ifdef _WIN32_WCE /* GetWindowInfo isn't on CE */
return XP_TRUE;
#else
XP_Bool visible = XP_FALSE;
WINDOWINFO wi;
wi.cbSize = sizeof(wi);
if ( !!hwnd && GetWindowInfo( hwnd, &wi ) ) {
visible = (wi.dwStyle & WS_VISIBLE) != 0;
}
return visible;
#endif
} /* ceIsVisible */
#ifdef _WIN32_WCE
static XP_Bool
mkFullscreenWithSoftkeys( CEAppGlobals* globals, HWND hDlg )
{
/* XP_Bool fullScreen = XP_FALSE; /\* probably want this TRUE for */
/* small-screened smartphones only. *\/ */
/* if ( fullScreen ) { */
/* SHINITDLGINFO info; */
/* info.dwMask = SHIDIM_FLAGS; */
/* info.dwFlags = SHIDIF_SIZEDLG */
/* /\* | SHIDIF_DONEBUTTON *\/ */
/* | SHIDIF_WANTSCROLLBAR; */
/* info.hDlg = hDlg; */
/* BOOL b = SHInitDialog( &info ); */
/* XP_LOGF( "SHInitDialog=>%d", (int)b ); */
/* } */
XP_Bool success = XP_FALSE;
SHMENUBARINFO mbi;
XP_MEMSET( &mbi, 0, sizeof(mbi) );
mbi.cbSize = sizeof(mbi);
mbi.hwndParent = hDlg;
mbi.nToolBarId = IDM_OKCANCEL_MENUBAR;
mbi.hInstRes = globals->hInst;
success = SHCreateMenuBar( &mbi );
if ( !success ) {
XP_LOGF( "SHCreateMenuBar failed" );
}
return success;
} /* mkFullscreenWithSoftkeys */
#endif
void
ceStackButtonsRight( CEAppGlobals* globals, HWND hDlg )
{
XP_Bool justRemove = XP_FALSE;
XP_ASSERT( !!globals );
#ifdef _WIN32_WCE
if ( mkFullscreenWithSoftkeys( globals, hDlg ) ) {
justRemove = XP_TRUE;
}
#endif
if ( justRemove || ceIsLandscape( globals ) ) {
XP_U16 resIDs[] = { IDOK, IDCANCEL };
RECT wrect, crect;
XP_U16 left, top;
XP_U16 butWidth, butHeight;
XP_U16 barHt, i, nButtons, spacing;
XP_U16 newWidth, mainWidth;
/* First, figure height and width to use */
butHeight = 0;
butWidth = 0;
nButtons = 0;
for ( i = 0; i < VSIZE(resIDs); ++i ) {
HWND itemH = GetDlgItem( hDlg, resIDs[i] );
if ( ceIsVisible( itemH ) ) {
RECT buttonRect;
GetClientRect( itemH, &buttonRect );
if ( butWidth < buttonRect.right ) {
butWidth = buttonRect.right;
}
if ( butHeight < buttonRect.bottom ) {
butHeight = buttonRect.bottom;
}
++nButtons;
}
}
GetWindowRect( globals->hWnd, &wrect );
mainWidth = wrect.right - wrect.left;
/* Make sure we're not proposing to make the dialog wider than the
screen */
GetWindowRect( hDlg, &wrect );
newWidth = wrect.right - wrect.left +
butWidth + HPADDING_L + HPADDING_R;
if ( justRemove || (newWidth <= mainWidth) ) {
GetClientRect( hDlg, &crect );
barHt = wrect.bottom - wrect.top - crect.bottom;
spacing = crect.bottom - (nButtons * (butHeight + (VPADDING*2)));
spacing /= nButtons + 1;
top = spacing - (butHeight / 2) + VPADDING;
left = crect.right + HPADDING_L;
for ( i = 0; i < VSIZE(resIDs); ++i ) {
HWND itemH = GetDlgItem( hDlg, resIDs[i] );
if ( ceIsVisible( itemH ) ) {
(void)MoveWindow( itemH, left, top, butWidth, butHeight,
TRUE );
top += butHeight + spacing + (VPADDING * 2);
}
}
if ( justRemove ) {
MoveWindow( hDlg, wrect.left, wrect.top,
wrect.right - wrect.left, wrect.bottom - wrect.top - butHeight - 2,
FALSE );
} else {
butWidth += HPADDING_L + HPADDING_R;
MoveWindow( hDlg, wrect.left - (butWidth/2), wrect.top,
newWidth, wrect.bottom - wrect.top - butHeight - 2,
FALSE );
}
}
}
} /* ceStackButtonsRight */
#ifdef _WIN32_WCE
void
ceSetLeftSoftkey( CEAppGlobals* globals, XP_U16 id )
{
HMENU menu;
XP_U16 curItem = globals->softkey.curItem;
/* temporary!! */
if ( curItem == 0 ) {
curItem = ID_MOVE_TURNDONE;
}
TBBUTTONINFO info;
XP_MEMSET( &info, 0, sizeof(info) );
info.cbSize = sizeof(info);
/* Also temporary!! */
const wchar_t* txt = L"Mine";
switch( id ) {
case ID_MOVE_TURNDONE:
txt = L"Turn done";
break;
case ID_FILE_NEWGAME:
txt = L"New game";
break;
case ID_MOVE_NEXTHINT:
txt = L"Next hint";
break;
default:
XP_ASSERT(0);
}
info.dwMask = TBIF_LPARAM;
SendMessage( globals->hwndCB, TB_GETBUTTONINFO, IDM_MENU, (LPARAM)&info );
menu = (HMENU)info.lParam; /* Use to remove item being installed in
left button */
/* First put any existing menu item back in the main menu! */
/* Then find, remember and remove the new */
/* Make it the button */
info.dwMask = TBIF_TEXT | TBIF_COMMAND;
info.idCommand = id;
info.pszText = txt;
SendMessage( globals->hwndCB, TB_SETBUTTONINFO, curItem, (LPARAM)&info );
/* Save for next time */
globals->softkey.curItem = id;
} /* ceSetLeftSoftkey */
#endif