2006-02-25 20:50:29 +00:00
/*
AppleWin : An Apple //e emulator for Windows
Copyright ( C ) 1994 - 1996 , Michael O ' Brien
Copyright ( C ) 1999 - 2001 , Oliver Schmidt
Copyright ( C ) 2002 - 2005 , Tom Charlesworth
2014-07-26 20:23:57 +00:00
Copyright ( C ) 2006 - 2014 , Tom Charlesworth , Michael Pohoreski
2006-02-25 20:50:29 +00:00
AppleWin 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 .
AppleWin 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 AppleWin ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
/* Description: Frame
*
* Author : Various
*/
# include "StdAfx.h"
2014-08-13 20:30:35 +00:00
# include <sys/stat.h>
2018-02-24 15:12:40 +00:00
# include "Applewin.h"
2014-08-13 20:30:35 +00:00
# include "CPU.h"
# include "Disk.h"
2010-01-03 18:43:08 +00:00
# include "DiskImage.h"
# include "Harddisk.h"
2014-08-13 20:30:35 +00:00
# include "Frame.h"
# include "Keyboard.h"
# include "Log.h"
# include "Memory.h"
# include "Mockingboard.h"
2007-08-06 21:38:35 +00:00
# include "MouseInterface.h"
2018-09-09 12:56:55 +00:00
# include "NTSC.h"
2014-08-13 20:30:35 +00:00
# include "ParallelPrinter.h"
2016-03-21 23:48:02 +00:00
# include "Pravets.h"
2014-08-13 20:30:35 +00:00
# include "Registry.h"
# include "SaveState.h"
# include "SerialComms.h"
# include "SoundCore.h"
# include "Speaker.h"
2010-02-14 21:11:26 +00:00
# ifdef USE_SPEECH_API
# include "Speech.h"
# endif
2014-08-13 20:30:35 +00:00
# include "Video.h"
2018-02-24 15:12:40 +00:00
# include "../resource/resource.h"
# include "Configuration/PropertySheet.h"
# include "Debugger/Debug.h"
2006-02-25 20:50:29 +00:00
2008-08-31 04:31:35 +00:00
//#define ENABLE_MENU 0
2018-07-27 20:55:53 +00:00
# define DEBUG_KEY_MESSAGES 0
2006-02-25 20:50:29 +00:00
2017-10-11 16:38:36 +00:00
// 3D border around the 560x384 Apple II display
# define VIEWPORTX 5
# define VIEWPORTY 5
2013-03-07 23:23:26 +00:00
static const int kDEFAULT_VIEWPORT_SCALE = 2 ;
2017-10-11 16:38:36 +00:00
int g_nViewportCX = GetFrameBufferBorderlessWidth ( ) * kDEFAULT_VIEWPORT_SCALE ;
int g_nViewportCY = GetFrameBufferBorderlessHeight ( ) * kDEFAULT_VIEWPORT_SCALE ;
2014-07-26 21:51:23 +00:00
static int g_nViewportScale = kDEFAULT_VIEWPORT_SCALE ; // saved REGSAVE
2016-07-25 20:19:00 +00:00
static int g_nMaxViewportScale = kDEFAULT_VIEWPORT_SCALE ; // Max scale in Windowed mode with borders, buttons etc (full-screen may be +1)
2008-08-31 04:31:35 +00:00
2012-12-29 14:53:52 +00:00
# define BUTTONX (g_nViewportCX + VIEWPORTX*2)
2006-02-25 20:50:29 +00:00
# define BUTTONY 0
# define BUTTONCX 45
# define BUTTONCY 45
# define BUTTONS 8
2010-12-18 21:00:52 +00:00
static HBITMAP g_hCapsLockBitmap [ 2 ] ;
static HBITMAP g_hHardDiskBitmap [ 2 ] ;
//Pravets8 only
static HBITMAP g_hCapsBitmapP8 [ 2 ] ;
static HBITMAP g_hCapsBitmapLat [ 2 ] ;
//static HBITMAP charsetbitmap [4]; //The idea was to add a charset indicator on the front panel, but it was given up. All charsetbitmap occurences must be REMOVED!
//===========================
static HBITMAP g_hDiskWindowedLED [ NUM_DISK_STATUS ] ;
2009-02-18 23:53:24 +00:00
2014-07-25 04:58:19 +00:00
static int g_nTrackDrive1 = - 1 ;
static int g_nTrackDrive2 = - 1 ;
static int g_nSectorDrive1 = - 1 ;
static int g_nSectorDrive2 = - 1 ;
static TCHAR g_sTrackDrive1 [ 8 ] = TEXT ( " ?? " ) ;
static TCHAR g_sTrackDrive2 [ 8 ] = TEXT ( " ?? " ) ;
static TCHAR g_sSectorDrive1 [ 8 ] = TEXT ( " ?? " ) ;
static TCHAR g_sSectorDrive2 [ 8 ] = TEXT ( " ?? " ) ;
2014-07-24 01:08:52 +00:00
Disk_Status_e g_eStatusDrive1 = DISK_STATUS_OFF ;
Disk_Status_e g_eStatusDrive2 = DISK_STATUS_OFF ;
2009-02-18 23:53:24 +00:00
// Must keep in sync with Disk_Status_e g_aDiskFullScreenColors
static DWORD g_aDiskFullScreenColorsLED [ NUM_DISK_STATUS ] =
{
RGB ( 0 , 0 , 0 ) , // DISK_STATUS_OFF BLACK
RGB ( 0 , 255 , 0 ) , // DISK_STATUS_READ GREEN
RGB ( 255 , 0 , 0 ) , // DISK_STATUS_WRITE RED
RGB ( 255 , 128 , 0 ) // DISK_STATUS_PROT ORANGE
// RGB( 0, 0,255) // DISK_STATUS_PROT -blue-
} ;
2006-02-28 18:40:59 +00:00
2006-02-25 20:50:29 +00:00
static HBITMAP buttonbitmap [ BUTTONS ] ;
2006-06-26 16:59:48 +00:00
static bool g_bAppActive = false ;
2006-02-25 20:50:29 +00:00
static HBRUSH btnfacebrush = ( HBRUSH ) 0 ;
static HPEN btnfacepen = ( HPEN ) 0 ;
static HPEN btnhighlightpen = ( HPEN ) 0 ;
static HPEN btnshadowpen = ( HPEN ) 0 ;
static int buttonactive = - 1 ;
static int buttondown = - 1 ;
static int buttonover = - 1 ;
static int buttonx = BUTTONX ;
static int buttony = BUTTONY ;
2012-12-29 14:53:52 +00:00
static HDC g_hFrameDC = ( HDC ) 0 ;
2006-02-25 20:50:29 +00:00
static RECT framerect = { 0 , 0 , 0 , 0 } ;
2009-02-16 19:11:33 +00:00
2014-07-27 21:31:00 +00:00
HWND g_hFrameWindow = ( HWND ) 0 ;
2017-10-11 16:38:36 +00:00
static bool g_bIsFullScreen = false ;
2014-07-27 21:31:00 +00:00
BOOL g_bConfirmReboot = 1 ; // saved PageConfig REGSAVE
BOOL g_bMultiMon = 0 ; // OFF = load window position & clamp initial frame to screen, ON = use window position as is
2009-02-16 19:11:33 +00:00
2006-02-25 20:50:29 +00:00
static BOOL helpquit = 0 ;
2009-01-06 22:02:31 +00:00
static BOOL g_bPaintingWindow = 0 ;
2006-02-25 20:50:29 +00:00
static HFONT smallfont = ( HFONT ) 0 ;
static HWND tooltipwindow = ( HWND ) 0 ;
2017-10-28 20:59:48 +00:00
static BOOL g_bUsingCursor = FALSE ; // TRUE = AppleWin is using (hiding) the mouse-cursor && restricting cursor to window - see SetUsingCursor()
2008-05-17 23:20:33 +00:00
static int viewportx = VIEWPORTX ; // Default to Normal (non-FullScreen) mode
static int viewporty = VIEWPORTY ; // Default to Normal (non-FullScreen) mode
2006-02-25 20:50:29 +00:00
2017-10-28 20:59:48 +00:00
static UINT_PTR g_TimerIDEvent_100msec = 0 ;
static UINT g_uCount100msec = 0 ;
2007-12-02 14:55:32 +00:00
static bool g_bShowingCursor = true ;
2008-05-17 23:20:33 +00:00
static bool g_bLastCursorInAppleViewport = false ;
2007-12-02 14:55:32 +00:00
2006-02-25 20:50:29 +00:00
void DrawStatusArea ( HDC passdc , BOOL drawflags ) ;
2013-12-06 21:10:41 +00:00
static void ProcessButtonClick ( int button , bool bFromButtonUI = false ) ;
2006-02-28 18:40:59 +00:00
void ProcessDiskPopupMenu ( HWND hwnd , POINT pt , const int iDrive ) ;
2006-02-25 20:50:29 +00:00
void RelayEvent ( UINT message , WPARAM wparam , LPARAM lparam ) ;
void ResetMachineState ( ) ;
void SetFullScreenMode ( ) ;
void SetNormalMode ( ) ;
2017-10-28 20:59:48 +00:00
static void SetUsingCursor ( BOOL ) ;
2014-08-14 19:29:01 +00:00
static bool FileExists ( std : : string strFilename ) ;
2006-02-25 20:50:29 +00:00
2007-08-06 21:38:35 +00:00
bool g_bScrollLock_FullSpeed = false ;
2009-02-17 02:13:18 +00:00
bool g_bFreshReset = false ;
2014-06-26 21:44:02 +00:00
static bool g_bFullScreen32Bit = true ;
2007-08-06 21:38:35 +00:00
2016-07-26 21:33:45 +00:00
#if 0 // enable non-integral full-screen scaling
# define FULLSCREEN_SCALE_TYPE float
# else
# define FULLSCREEN_SCALE_TYPE int
# endif
static RECT g_main_window_saved_rect ;
static int g_main_window_saved_style ;
static int g_main_window_saved_exstyle ;
static FULLSCREEN_SCALE_TYPE g_win_fullscreen_scale = 1 ;
static int g_win_fullscreen_offsetx = 0 ;
static int g_win_fullscreen_offsety = 0 ;
2017-10-28 21:13:05 +00:00
static bool g_bFrameActive = false ;
2017-10-28 20:59:48 +00:00
2011-02-20 07:32:09 +00:00
// __ Prototypes __________________________________________________________________________________
2017-10-28 20:59:48 +00:00
void DrawCrosshairs ( int x , int y ) ;
void UpdateMouseInAppleViewport ( int iOutOfBoundsX , int iOutOfBoundsY , int x = 0 , int y = 0 ) ;
void ScreenWindowResize ( const bool bCtrlKey ) ;
void FrameResizeWindow ( int nNewScale ) ;
2012-12-29 14:53:52 +00:00
2011-02-20 07:32:09 +00:00
2018-06-10 17:14:34 +00:00
// ==========================================================================
static bool g_bAltEnter_ToggleFullScreen = true ; // Default for ALT+ENTER is to toggle between windowed and full-screen modes
void SetAltEnterToggleFullScreen ( bool mode )
{
g_bAltEnter_ToggleFullScreen = mode ;
}
2017-10-11 16:38:36 +00:00
// ==========================================================================
// Display construction:
// . Apple II video gets rendered to the framebuffer (maybe with some preliminary/final NTSC data in the border areas)
// . The *borderless* framebuffer is stretchblt() copied to the frame DC, in VideoRefreshScreen()
// . Draw cross-hairs (if using mouse as either a mouse or joystick) to frame DC
// . In Windowed mode:
// - Draw 3D border, 8x buttons, status area (disk LEDs, caps) to frame DC
// . In Fullscreen mode:
// - Optional: Draw status area to frame DC
//
UINT GetFrameBufferBorderlessWidth ( void )
{
2019-08-29 20:38:00 +00:00
static const UINT uFrameBufferBorderlessW = 560 ; // 560 = Double Hi-Res
2017-10-11 16:55:10 +00:00
return uFrameBufferBorderlessW ;
2017-10-11 16:38:36 +00:00
}
UINT GetFrameBufferBorderlessHeight ( void )
{
2017-10-11 18:18:53 +00:00
static const UINT uFrameBufferBorderlessH = 384 ; // 384 = Double Scan Line
2017-10-11 16:55:10 +00:00
return uFrameBufferBorderlessH ;
2017-10-11 16:38:36 +00:00
}
2017-10-11 16:55:10 +00:00
// NB. These border areas are not visible (... and these border areas are unrelated to the 3D border below)
2017-10-11 16:38:36 +00:00
UINT GetFrameBufferBorderWidth ( void )
{
2017-10-11 18:18:53 +00:00
static const UINT uBorderW = 20 ;
2017-10-11 16:55:10 +00:00
return uBorderW ;
2017-10-11 16:38:36 +00:00
}
UINT GetFrameBufferBorderHeight ( void )
{
2017-10-11 18:18:53 +00:00
static const UINT uBorderH = 18 ;
2017-10-11 16:55:10 +00:00
return uBorderH ;
2017-10-11 16:38:36 +00:00
}
2011-02-20 07:32:09 +00:00
2017-10-11 16:38:36 +00:00
UINT GetFrameBufferWidth ( void )
{
return GetFrameBufferBorderlessWidth ( ) + 2 * GetFrameBufferBorderWidth ( ) ;
}
UINT GetFrameBufferHeight ( void )
{
return GetFrameBufferBorderlessHeight ( ) + 2 * GetFrameBufferBorderHeight ( ) ;
}
//
UINT Get3DBorderWidth ( void )
{
return IsFullScreen ( ) ? 0 : VIEWPORTX ;
}
UINT Get3DBorderHeight ( void )
{
return IsFullScreen ( ) ? 0 : VIEWPORTY ;
}
// ==========================================================================
2019-08-31 14:02:32 +00:00
2016-03-21 23:48:02 +00:00
static void GetAppleWindowTitle ( )
2011-02-20 07:32:09 +00:00
{
switch ( g_Apple2Type )
{
default :
2019-09-15 20:24:50 +00:00
case A2TYPE_APPLE2 : g_pAppTitle = TITLE_APPLE_2 ; break ;
case A2TYPE_APPLE2PLUS : g_pAppTitle = TITLE_APPLE_2_PLUS ; break ;
case A2TYPE_APPLE2E : g_pAppTitle = TITLE_APPLE_2E ; break ;
case A2TYPE_APPLE2EENHANCED : g_pAppTitle = TITLE_APPLE_2E_ENHANCED ; break ;
case A2TYPE_PRAVETS82 : g_pAppTitle = TITLE_PRAVETS_82 ; break ;
case A2TYPE_PRAVETS8M : g_pAppTitle = TITLE_PRAVETS_8M ; break ;
case A2TYPE_PRAVETS8A : g_pAppTitle = TITLE_PRAVETS_8A ; break ;
case A2TYPE_TK30002E : g_pAppTitle = TITLE_TK3000_2E ; break ;
2011-02-20 07:32:09 +00:00
}
# if _DEBUG
2019-09-15 20:24:50 +00:00
g_pAppTitle + = " *DEBUG* " ;
2011-02-20 07:32:09 +00:00
# endif
if ( g_nAppMode = = MODE_LOGO )
return ;
2019-09-15 20:24:50 +00:00
g_pAppTitle + = " - " ;
2011-02-20 07:32:09 +00:00
2019-02-24 15:59:35 +00:00
if ( IsVideoStyle ( VS_HALF_SCANLINES ) )
2011-02-20 07:32:09 +00:00
{
2019-09-15 20:24:50 +00:00
g_pAppTitle + = " 50% " ;
2011-02-20 07:32:09 +00:00
}
2019-09-15 20:24:50 +00:00
g_pAppTitle + = g_apVideoModeDesc [ g_eVideoType ] ;
2011-02-20 07:32:09 +00:00
if ( g_hCustomRomF8 ! = INVALID_HANDLE_VALUE )
2019-09-15 20:24:50 +00:00
g_pAppTitle + = TEXT ( " (custom rom) " ) ;
2012-03-27 21:20:36 +00:00
else if ( sg_PropertySheet . GetTheFreezesF8Rom ( ) & & IS_APPLE2 )
2019-09-15 20:24:50 +00:00
g_pAppTitle + = TEXT ( " (The Freeze's non-autostart F8 rom) " ) ;
2011-02-20 07:32:09 +00:00
switch ( g_nAppMode )
{
2019-09-15 20:24:50 +00:00
case MODE_PAUSED : g_pAppTitle + = std : : string ( TEXT ( " [ " ) ) + TITLE_PAUSED + TEXT ( " ] " ) ; break ;
case MODE_STEPPING : g_pAppTitle + = std : : string ( TEXT ( " [ " ) ) + TITLE_STEPPING + TEXT ( " ] " ) ; break ;
2011-02-20 07:32:09 +00:00
}
}
2008-05-17 23:20:33 +00:00
2006-02-25 20:50:29 +00:00
//===========================================================================
2008-05-18 18:23:25 +00:00
2008-06-08 12:31:50 +00:00
static void FrameShowCursor ( BOOL bShow )
2008-05-18 18:23:25 +00:00
{
int nCount ;
if ( bShow )
{
do
{
nCount = ShowCursor ( bShow ) ;
}
while ( nCount < 0 ) ;
g_bShowingCursor = true ;
}
else
{
do
{
nCount = ShowCursor ( bShow ) ;
}
while ( nCount > = 0 ) ;
g_bShowingCursor = false ;
}
}
2008-06-08 12:31:50 +00:00
// Called when:
// . Ctrl-Left mouse button
// . PAUSE pressed (when MODE_RUNNING)
2017-10-28 21:13:05 +00:00
// . AppleWin's main window is activated/deactivated
2008-06-08 12:31:50 +00:00
static void RevealCursor ( )
{
if ( ! sg_Mouse . IsActiveAndEnabled ( ) )
return ;
sg_Mouse . SetEnabled ( false ) ;
FrameShowCursor ( TRUE ) ;
2012-03-27 21:20:36 +00:00
if ( sg_PropertySheet . GetMouseShowCrosshair ( ) ) // Erase crosshairs if they are being drawn
2008-06-08 12:31:50 +00:00
DrawCrosshairs ( 0 , 0 ) ;
2012-03-27 21:20:36 +00:00
if ( sg_PropertySheet . GetMouseRestrictToWindow ( ) )
2008-06-08 12:31:50 +00:00
SetUsingCursor ( FALSE ) ;
g_bLastCursorInAppleViewport = false ;
}
2017-10-28 20:59:48 +00:00
// Called when:
// . WM_MOUSEMOVE event
// . Switch from full-screen to normal (windowed) mode
2017-10-28 21:13:05 +00:00
// . AppleWin's main window is activated/deactivated
2017-10-28 20:59:48 +00:00
static void FullScreenRevealCursor ( void )
{
if ( ! g_bIsFullScreen )
return ;
if ( sg_Mouse . IsActive ( ) )
return ;
if ( ! g_bUsingCursor & & ! g_bShowingCursor )
{
FrameShowCursor ( TRUE ) ;
g_uCount100msec = 0 ;
}
}
2008-05-18 18:23:25 +00:00
//===========================================================================
2006-07-02 09:56:50 +00:00
# define LOADBUTTONBITMAP(bitmapname) LoadImage(g_hInstance,bitmapname, \
2006-02-25 20:50:29 +00:00
IMAGE_BITMAP , 0 , 0 , \
LR_CREATEDIBSECTION | \
LR_LOADMAP3DCOLORS | \
LR_LOADTRANSPARENT ) ;
2008-06-20 23:47:25 +00:00
2013-08-08 21:13:31 +00:00
static void CreateGdiObjects ( void )
{
ZeroMemory ( buttonbitmap , BUTTONS * sizeof ( HBITMAP ) ) ;
buttonbitmap [ BTN_HELP ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " HELP_BUTTON " ) ) ;
switch ( g_Apple2Type )
{
case A2TYPE_PRAVETS82 :
case A2TYPE_PRAVETS8M :
case A2TYPE_PRAVETS8A :
buttonbitmap [ BTN_RUN ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " RUNP_BUTTON " ) ) ;
break ;
2016-10-22 22:20:23 +00:00
case A2TYPE_TK30002E :
buttonbitmap [ BTN_RUN ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " RUN3000E_BUTTON " ) ) ;
break ;
2013-08-08 21:13:31 +00:00
default :
buttonbitmap [ BTN_RUN ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " RUN_BUTTON " ) ) ;
break ;
}
buttonbitmap [ BTN_DRIVE1 ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " DRIVE1_BUTTON " ) ) ;
buttonbitmap [ BTN_DRIVE2 ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " DRIVE2_BUTTON " ) ) ;
buttonbitmap [ BTN_DRIVESWAP ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " DRIVESWAP_BUTTON " ) ) ;
buttonbitmap [ BTN_FULLSCR ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " FULLSCR_BUTTON " ) ) ;
buttonbitmap [ BTN_DEBUG ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " DEBUG_BUTTON " ) ) ;
buttonbitmap [ BTN_SETUP ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " SETUP_BUTTON " ) ) ;
//
g_hCapsLockBitmap [ 0 ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " LED_CAPSOFF_BITMAP " ) ) ;
g_hCapsLockBitmap [ 1 ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " LED_CAPSON_BITMAP " ) ) ;
//Pravets8 only
g_hCapsBitmapP8 [ 0 ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " LED_CAPSOFF_P8_BITMAP " ) ) ;
g_hCapsBitmapP8 [ 1 ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " LED_CAPSON_P8_BITMAP " ) ) ;
g_hCapsBitmapLat [ 0 ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " LED_LATOFF_BITMAP " ) ) ;
g_hCapsBitmapLat [ 1 ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " LED_LATON_BITMAP " ) ) ;
/*charsetbitmap[0] = (HBITMAP)LOADBUTTONBITMAP(TEXT("CHARSET_APPLE_BITMAP"));
charsetbitmap [ 1 ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " CHARSET_82_BITMAP " ) ) ;
charsetbitmap [ 2 ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " CHARSET_8A_BITMAP " ) ) ;
charsetbitmap [ 3 ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " CHARSET_8M_BITMAP " ) ) ;
*/
//===========================
g_hDiskWindowedLED [ DISK_STATUS_OFF ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " DISKOFF_BITMAP " ) ) ;
g_hDiskWindowedLED [ DISK_STATUS_READ ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " DISKREAD_BITMAP " ) ) ;
g_hDiskWindowedLED [ DISK_STATUS_WRITE ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " DISKWRITE_BITMAP " ) ) ;
g_hDiskWindowedLED [ DISK_STATUS_PROT ] = ( HBITMAP ) LOADBUTTONBITMAP ( TEXT ( " DISKPROT_BITMAP " ) ) ;
btnfacebrush = CreateSolidBrush ( GetSysColor ( COLOR_BTNFACE ) ) ;
btnfacepen = CreatePen ( PS_SOLID , 1 , GetSysColor ( COLOR_BTNFACE ) ) ;
btnhighlightpen = CreatePen ( PS_SOLID , 1 , GetSysColor ( COLOR_BTNHIGHLIGHT ) ) ;
btnshadowpen = CreatePen ( PS_SOLID , 1 , GetSysColor ( COLOR_BTNSHADOW ) ) ;
smallfont = CreateFont ( 11 , 6 , 0 , 0 , FW_NORMAL , 0 , 0 , 0 , ANSI_CHARSET ,
OUT_DEFAULT_PRECIS , CLIP_DEFAULT_PRECIS ,
DEFAULT_QUALITY , VARIABLE_PITCH | FF_SWISS ,
TEXT ( " Small Fonts " ) ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2013-08-08 21:13:31 +00:00
static void DeleteGdiObjects ( void )
{
for ( int loop = 0 ; loop < BUTTONS ; loop + + )
_ASSERT ( DeleteObject ( buttonbitmap [ loop ] ) ) ;
for ( int loop = 0 ; loop < 2 ; loop + + )
{
_ASSERT ( DeleteObject ( g_hCapsLockBitmap [ loop ] ) ) ;
_ASSERT ( DeleteObject ( g_hCapsBitmapP8 [ loop ] ) ) ;
_ASSERT ( DeleteObject ( g_hCapsBitmapLat [ loop ] ) ) ;
}
for ( int loop = 0 ; loop < NUM_DISK_STATUS ; loop + + )
{
_ASSERT ( DeleteObject ( g_hDiskWindowedLED [ loop ] ) ) ;
}
_ASSERT ( DeleteObject ( btnfacebrush ) ) ;
_ASSERT ( DeleteObject ( btnfacepen ) ) ;
_ASSERT ( DeleteObject ( btnhighlightpen ) ) ;
_ASSERT ( DeleteObject ( btnshadowpen ) ) ;
_ASSERT ( DeleteObject ( smallfont ) ) ;
2006-02-25 20:50:29 +00:00
}
2006-07-05 21:23:13 +00:00
// Draws an 3D box around the main apple screen
2006-02-25 20:50:29 +00:00
//===========================================================================
2008-06-08 12:31:50 +00:00
static void Draw3dRect ( HDC dc , int x1 , int y1 , int x2 , int y2 , BOOL out )
2006-07-05 21:23:13 +00:00
{
SelectObject ( dc , GetStockObject ( NULL_BRUSH ) ) ;
SelectObject ( dc , out ? btnshadowpen : btnhighlightpen ) ;
POINT pt [ 3 ] ;
pt [ 0 ] . x = x1 ; pt [ 0 ] . y = y2 - 1 ;
pt [ 1 ] . x = x2 - 1 ; pt [ 1 ] . y = y2 - 1 ;
pt [ 2 ] . x = x2 - 1 ; pt [ 2 ] . y = y1 ;
Polyline ( dc , ( LPPOINT ) & pt , 3 ) ;
SelectObject ( dc , ( out = = 1 ) ? btnhighlightpen : btnshadowpen ) ;
pt [ 1 ] . x = x1 ; pt [ 1 ] . y = y1 ;
pt [ 2 ] . x = x2 ; pt [ 2 ] . y = y1 ;
Polyline ( dc , ( LPPOINT ) & pt , 3 ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2008-06-08 12:31:50 +00:00
static void DrawBitmapRect ( HDC dc , int x , int y , LPRECT rect , HBITMAP bitmap ) {
2006-02-25 20:50:29 +00:00
HDC memdc = CreateCompatibleDC ( dc ) ;
SelectObject ( memdc , bitmap ) ;
BitBlt ( dc , x , y ,
rect - > right + 1 - rect - > left ,
rect - > bottom + 1 - rect - > top ,
memdc ,
rect - > left ,
rect - > top ,
SRCCOPY ) ;
DeleteDC ( memdc ) ;
}
//===========================================================================
2008-06-08 12:31:50 +00:00
static void DrawButton ( HDC passdc , int number ) {
2006-02-25 20:50:29 +00:00
FrameReleaseDC ( ) ;
2006-05-14 00:44:38 +00:00
HDC dc = ( passdc ? passdc : GetDC ( g_hFrameWindow ) ) ;
2006-02-25 20:50:29 +00:00
int x = buttonx ;
int y = buttony + number * BUTTONCY ;
if ( number = = buttondown ) {
int loop = 0 ;
while ( loop + + < 3 )
Draw3dRect ( dc , x + loop , y + loop , x + BUTTONCX , y + BUTTONCY , 0 ) ;
RECT rect = { 0 , 0 , 39 , 39 } ;
DrawBitmapRect ( dc , x + 4 , y + 4 , & rect , buttonbitmap [ number ] ) ;
}
else {
Draw3dRect ( dc , x + 1 , y + 1 , x + BUTTONCX , y + BUTTONCY , 1 ) ;
Draw3dRect ( dc , x + 2 , y + 2 , x + BUTTONCX - 1 , y + BUTTONCY - 1 , 1 ) ;
RECT rect = { 1 , 1 , 40 , 40 } ;
DrawBitmapRect ( dc , x + 3 , y + 3 , & rect , buttonbitmap [ number ] ) ;
}
if ( ( number = = BTN_DRIVE1 ) | | ( number = = BTN_DRIVE2 ) ) {
int offset = ( number = = buttondown ) < < 1 ;
RECT rect = { x + offset + 3 ,
y + offset + 31 ,
x + offset + 42 ,
y + offset + 42 } ;
SelectObject ( dc , smallfont ) ;
SetTextColor ( dc , RGB ( 0 , 0 , 0 ) ) ;
SetTextAlign ( dc , TA_CENTER | TA_TOP ) ;
SetBkMode ( dc , TRANSPARENT ) ;
2019-09-07 08:02:39 +00:00
LPCTSTR pszBaseName = sg_Disk2Card . GetBaseName ( number - BTN_DRIVE1 ) . c_str ( ) ;
2006-02-25 20:50:29 +00:00
ExtTextOut ( dc , x + offset + 22 , rect . top , ETO_CLIPPED , & rect ,
2010-01-03 18:43:08 +00:00
pszBaseName ,
MIN ( 8 , _tcslen ( pszBaseName ) ) ,
2006-02-25 20:50:29 +00:00
NULL ) ;
}
if ( ! passdc )
2006-05-14 00:44:38 +00:00
ReleaseDC ( g_hFrameWindow , dc ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2016-07-12 21:43:31 +00:00
// NB. x=y=0 means erase only
2008-06-08 12:31:50 +00:00
static void DrawCrosshairs ( int x , int y ) {
2006-02-25 20:50:29 +00:00
static int lastx = 0 ;
static int lasty = 0 ;
FrameReleaseDC ( ) ;
2006-05-14 00:44:38 +00:00
HDC dc = GetDC ( g_hFrameWindow ) ;
2006-02-25 20:50:29 +00:00
# define LINE(x1,y1,x2,y2) MoveToEx(dc,x1,y1,NULL); LineTo(dc,x2,y2);
// ERASE THE OLD CROSSHAIRS
if ( lastx & & lasty )
2016-07-12 21:43:31 +00:00
if ( g_bIsFullScreen )
{
int loop = 4 ;
while ( loop - - ) {
RECT rect = { 0 , 0 , 5 , 5 } ;
switch ( loop ) {
2016-07-26 21:33:45 +00:00
case 0 : OffsetRect ( & rect , GetFullScreenOffsetX ( ) + lastx - 2 , GetFullScreenOffsetY ( ) + viewporty - 5 ) ; break ;
case 1 : OffsetRect ( & rect , GetFullScreenOffsetX ( ) + lastx - 2 , GetFullScreenOffsetY ( ) + viewporty + g_nViewportCY ) ; break ;
case 2 : OffsetRect ( & rect , GetFullScreenOffsetX ( ) + viewportx - 5 , GetFullScreenOffsetY ( ) + lasty - 2 ) ; break ;
case 3 : OffsetRect ( & rect , GetFullScreenOffsetX ( ) + viewportx + g_nViewportCX , GetFullScreenOffsetY ( ) + lasty - 2 ) ; break ;
2016-07-12 21:43:31 +00:00
}
FillRect ( dc , & rect , ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) ) ;
}
}
else
{
2006-02-25 20:50:29 +00:00
int loop = 5 ;
while ( loop - - ) {
switch ( loop ) {
case 0 : SelectObject ( dc , GetStockObject ( BLACK_PEN ) ) ; break ;
case 1 : // fall through
case 2 : SelectObject ( dc , btnshadowpen ) ; break ;
case 3 : // fall through
case 4 : SelectObject ( dc , btnfacepen ) ; break ;
}
LINE ( lastx - 2 , VIEWPORTY - loop - 1 ,
lastx + 3 , VIEWPORTY - loop - 1 ) ;
LINE ( VIEWPORTX - loop - 1 , lasty - 2 ,
VIEWPORTX - loop - 1 , lasty + 3 ) ;
if ( ( loop = = 1 ) | | ( loop = = 2 ) )
SelectObject ( dc , btnhighlightpen ) ;
2012-12-29 14:53:52 +00:00
LINE ( lastx - 2 , VIEWPORTY + g_nViewportCY + loop ,
lastx + 3 , VIEWPORTY + g_nViewportCY + loop ) ;
LINE ( VIEWPORTX + g_nViewportCX + loop , lasty - 2 ,
VIEWPORTX + g_nViewportCX + loop , lasty + 3 ) ;
2006-02-25 20:50:29 +00:00
}
}
// DRAW THE NEW CROSSHAIRS
if ( x & & y ) {
2016-07-12 21:43:31 +00:00
if ( g_bIsFullScreen )
{
int loop = 4 ;
while ( loop - - ) {
if ( ( loop = = 1 ) | | ( loop = = 2 ) )
SelectObject ( dc , GetStockObject ( WHITE_PEN ) ) ;
else
SelectObject ( dc , GetStockObject ( BLACK_PEN ) ) ;
2016-07-26 21:33:45 +00:00
LINE ( GetFullScreenOffsetX ( ) + x + loop - 2 , GetFullScreenOffsetY ( ) + viewporty - 5 ,
GetFullScreenOffsetX ( ) + x + loop - 2 , GetFullScreenOffsetY ( ) + viewporty ) ;
LINE ( GetFullScreenOffsetX ( ) + x + loop - 2 , GetFullScreenOffsetY ( ) + viewporty + g_nViewportCY + 4 ,
GetFullScreenOffsetX ( ) + x + loop - 2 , GetFullScreenOffsetY ( ) + viewporty + g_nViewportCY - 1 ) ;
LINE ( GetFullScreenOffsetX ( ) + viewportx - 5 , GetFullScreenOffsetY ( ) + y + loop - 2 ,
GetFullScreenOffsetX ( ) + viewportx , GetFullScreenOffsetY ( ) + y + loop - 2 ) ;
LINE ( GetFullScreenOffsetX ( ) + viewportx + g_nViewportCX + 4 , GetFullScreenOffsetY ( ) + y + loop - 2 ,
GetFullScreenOffsetX ( ) + viewportx + g_nViewportCX - 1 , GetFullScreenOffsetY ( ) + y + loop - 2 ) ;
2016-07-12 21:43:31 +00:00
}
}
else
{
int loop = 4 ;
while ( loop - - ) {
if ( ( loop = = 1 ) | | ( loop = = 2 ) )
SelectObject ( dc , GetStockObject ( WHITE_PEN ) ) ;
else
SelectObject ( dc , GetStockObject ( BLACK_PEN ) ) ;
LINE ( x + loop - 2 , viewporty - 5 ,
x + loop - 2 , viewporty ) ;
LINE ( x + loop - 2 , viewporty + g_nViewportCY + 4 ,
x + loop - 2 , viewporty + g_nViewportCY - 1 ) ;
LINE ( viewportx - 5 , y + loop - 2 ,
viewportx , y + loop - 2 ) ;
LINE ( viewportx + g_nViewportCX + 4 , y + loop - 2 ,
viewportx + g_nViewportCX - 1 , y + loop - 2 ) ;
}
}
2006-02-25 20:50:29 +00:00
}
# undef LINE
lastx = x ;
lasty = y ;
2006-05-14 00:44:38 +00:00
ReleaseDC ( g_hFrameWindow , dc ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2009-02-21 04:42:35 +00:00
static void DrawFrameWindow ( )
{
FrameReleaseDC ( ) ;
PAINTSTRUCT ps ;
HDC dc = ( g_bPaintingWindow
? BeginPaint ( g_hFrameWindow , & ps )
: GetDC ( g_hFrameWindow ) ) ;
2006-02-25 20:50:29 +00:00
2009-02-21 04:42:35 +00:00
if ( ! g_bIsFullScreen )
{
// DRAW THE 3D BORDER AROUND THE EMULATED SCREEN
Draw3dRect ( dc ,
VIEWPORTX - 2 , VIEWPORTY - 2 ,
2012-12-29 14:53:52 +00:00
VIEWPORTX + g_nViewportCX + 2 , VIEWPORTY + g_nViewportCY + 2 ,
2009-02-21 04:42:35 +00:00
0 ) ;
Draw3dRect ( dc ,
VIEWPORTX - 3 , VIEWPORTY - 3 ,
2012-12-29 14:53:52 +00:00
VIEWPORTX + g_nViewportCX + 3 , VIEWPORTY + g_nViewportCY + 3 ,
2009-02-21 04:42:35 +00:00
0 ) ;
SelectObject ( dc , btnfacepen ) ;
Rectangle ( dc ,
VIEWPORTX - 4 , VIEWPORTY - 4 ,
2012-12-29 14:53:52 +00:00
VIEWPORTX + g_nViewportCX + 4 , VIEWPORTY + g_nViewportCY + 4 ) ;
2009-02-21 04:42:35 +00:00
Rectangle ( dc ,
VIEWPORTX - 5 , VIEWPORTY - 5 ,
2012-12-29 14:53:52 +00:00
VIEWPORTX + g_nViewportCX + 5 , VIEWPORTY + g_nViewportCY + 5 ) ;
2009-02-21 04:42:35 +00:00
// DRAW THE TOOLBAR BUTTONS
int iButton = BUTTONS ;
while ( iButton - - )
{
DrawButton ( dc , iButton ) ;
}
2012-12-29 14:53:52 +00:00
if ( g_nViewportScale = = 2 )
{
int x = buttonx + 1 ;
int y = buttony + BUTTONS * BUTTONCY + 36 ; // 36 = height of StatusArea
RECT rect = { x , y , x + 45 , y + BUTTONS * BUTTONCY + 22 } ;
2017-10-05 21:06:53 +00:00
int res = FillRect ( dc , & rect , btnfacebrush ) ;
2012-12-29 14:53:52 +00:00
}
2009-02-21 04:42:35 +00:00
}
// DRAW THE STATUS AREA
2014-07-29 14:56:55 +00:00
DrawStatusArea ( dc , DRAW_BACKGROUND | DRAW_LEDS | DRAW_DISK_STATUS ) ;
2009-02-21 04:42:35 +00:00
// DRAW THE CONTENTS OF THE EMULATED SCREEN
if ( g_nAppMode = = MODE_LOGO )
VideoDisplayLogo ( ) ;
else if ( g_nAppMode = = MODE_DEBUG )
2017-04-22 19:52:21 +00:00
DebugDisplay ( ) ;
2009-02-21 04:42:35 +00:00
else
2016-09-25 09:42:14 +00:00
VideoRedrawScreen ( ) ;
2009-02-21 04:42:35 +00:00
if ( g_bPaintingWindow )
EndPaint ( g_hFrameWindow , & ps ) ;
else
ReleaseDC ( g_hFrameWindow , dc ) ;
2006-02-25 20:50:29 +00:00
}
2017-10-02 21:22:26 +00:00
//===========================================================================
static bool g_bFullScreen_ShowSubunitStatus = true ;
bool IsFullScreen ( void )
{
2017-10-11 16:38:36 +00:00
return g_bIsFullScreen ;
2017-10-02 21:22:26 +00:00
}
bool GetFullScreenShowSubunitStatus ( void )
{
return g_bFullScreen_ShowSubunitStatus ;
}
void SetFullScreenShowSubunitStatus ( bool bShow )
{
g_bFullScreen_ShowSubunitStatus = bShow ;
}
2014-07-24 01:08:52 +00:00
//===========================================================================
void FrameDrawDiskLEDS ( HDC passdc )
2006-06-26 16:59:48 +00:00
{
2017-10-02 21:22:26 +00:00
Disk_Status_e eDrive1Status ;
Disk_Status_e eDrive2Status ;
2019-04-14 16:01:49 +00:00
sg_Disk2Card . GetLightStatus ( & eDrive1Status , & eDrive2Status ) ;
2014-07-24 01:08:52 +00:00
g_eStatusDrive1 = eDrive1Status ;
g_eStatusDrive2 = eDrive2Status ;
// Draw Track/Sector
2006-06-26 16:59:48 +00:00
FrameReleaseDC ( ) ;
HDC dc = ( passdc ? passdc : GetDC ( g_hFrameWindow ) ) ;
2014-07-22 01:21:31 +00:00
2006-06-26 16:59:48 +00:00
int x = buttonx ;
int y = buttony + BUTTONS * BUTTONCY + 1 ;
2010-12-18 21:00:52 +00:00
2014-07-24 01:08:52 +00:00
if ( g_bIsFullScreen )
{
2017-10-02 21:22:26 +00:00
if ( ! g_bFullScreen_ShowSubunitStatus )
return ;
2014-07-24 01:08:52 +00:00
SelectObject ( dc , smallfont ) ;
SetBkMode ( dc , OPAQUE ) ;
SetBkColor ( dc , RGB ( 0 , 0 , 0 ) ) ;
SetTextAlign ( dc , TA_LEFT | TA_TOP ) ;
SetTextColor ( dc , g_aDiskFullScreenColorsLED [ eDrive1Status ] ) ;
TextOut ( dc , x + 3 , y + 2 , TEXT ( " 1 " ) , 1 ) ;
SetTextColor ( dc , g_aDiskFullScreenColorsLED [ eDrive2Status ] ) ;
TextOut ( dc , x + 13 , y + 2 , TEXT ( " 2 " ) , 1 ) ;
}
else
{
RECT rDiskLed = { 0 , 0 , 8 , 8 } ;
DrawBitmapRect ( dc , x + 12 , y + 6 , & rDiskLed , g_hDiskWindowedLED [ eDrive1Status ] ) ;
DrawBitmapRect ( dc , x + 31 , y + 6 , & rDiskLed , g_hDiskWindowedLED [ eDrive2Status ] ) ;
}
}
// Feature Request #201 Show track status
// https://github.com/AppleWin/AppleWin/issues/201
//===========================================================================
void FrameDrawDiskStatus ( HDC passdc )
{
2016-03-21 23:48:02 +00:00
if ( mem = = NULL )
return ;
2017-10-05 21:06:53 +00:00
if ( g_nAppMode = = MODE_LOGO )
return ;
2014-07-28 21:13:40 +00:00
// We use the actual drive since probing from memory doesn't tell us anything we don't already know.
// DOS3.3 ProDOS
// Drive $B7EA $BE3D
// Track $B7EC LC1 $D356
// Sector $B7ED LC1 $D357
2014-07-28 21:18:32 +00:00
// RWTS LC1 $D300
2019-04-14 16:01:49 +00:00
int nActiveFloppy = sg_Disk2Card . GetCurrentDrive ( ) ;
2019-04-08 09:41:47 +00:00
2019-04-14 16:01:49 +00:00
int nDisk1Track = sg_Disk2Card . GetTrack ( DRIVE_1 ) ;
int nDisk2Track = sg_Disk2Card . GetTrack ( DRIVE_2 ) ;
2014-07-24 01:08:52 +00:00
// Probe known OS's for Track/Sector
2014-07-25 04:58:19 +00:00
int isProDOS = mem [ 0xBF00 ] = = 0x4C ;
bool isValid = true ;
2014-07-24 01:08:52 +00:00
// Try DOS3.3 Sector
2014-07-28 21:18:32 +00:00
if ( ! isProDOS )
2014-07-24 01:08:52 +00:00
{
2014-07-28 21:13:40 +00:00
int nDOS33track = mem [ 0xB7EC ] ;
int nDOS33sector = mem [ 0xB7ED ] ;
2014-07-24 05:40:35 +00:00
2014-07-28 21:13:40 +00:00
if ( ( nDOS33track > = 0 & & nDOS33track < 40 )
& & ( nDOS33sector > = 0 & & nDOS33sector < 16 ) )
2014-07-24 01:08:52 +00:00
{
2014-07-28 21:13:40 +00:00
# if _DEBUG && 0
if ( nDOS33track ! = nDisk1Track )
{
char text [ 128 ] ;
sprintf ( text , " \n \n \n WARNING: DOS33Track: %d (%02X) != nDisk1Track: %d (%02X) \n \n \n " , nDOS33track , nDOS33track , nDisk1Track , nDisk1Track ) ;
OutputDebugString ( text ) ;
}
# endif // _DEBUG
/**/ if ( nActiveFloppy = = 0 ) g_nSectorDrive1 = nDOS33sector ;
else if ( nActiveFloppy = = 1 ) g_nSectorDrive2 = nDOS33sector ;
2014-07-24 01:08:52 +00:00
}
2014-07-25 04:58:19 +00:00
else
isValid = false ;
2014-07-24 01:08:52 +00:00
}
2014-07-28 21:18:32 +00:00
else // isProDOS
2014-07-24 01:08:52 +00:00
{
2014-07-26 16:36:29 +00:00
// we can't just read from mem[ 0xD357 ] since it might be bank-switched from ROM
// and we need the Language Card RAM
2014-07-28 21:18:32 +00:00
// memrom[ 0xD350 ] = " ERROR\x07\x00" Applesoft error message
// T S
2014-07-28 21:13:40 +00:00
int nProDOStrack = * MemGetMainPtr ( 0xC356 ) ; // LC1 $D356
int nProDOSsector = * MemGetMainPtr ( 0xC357 ) ; // LC1 $D357
2014-07-25 04:58:19 +00:00
2014-07-28 21:13:40 +00:00
if ( ( nProDOStrack > = 0 & & nProDOStrack < 40 )
& & ( nProDOSsector > = 0 & & nProDOSsector < 16 ) )
2014-07-24 05:40:35 +00:00
{
2014-07-28 21:13:40 +00:00
/**/ if ( nActiveFloppy = = 0 ) g_nSectorDrive1 = nProDOSsector ;
else if ( nActiveFloppy = = 1 ) g_nSectorDrive2 = nProDOSsector ;
2014-07-24 05:40:35 +00:00
}
else
2014-07-25 04:58:19 +00:00
isValid = false ;
2014-07-24 01:08:52 +00:00
}
2014-07-25 04:58:19 +00:00
g_nTrackDrive1 = nDisk1Track ;
g_nTrackDrive2 = nDisk2Track ;
if ( ! isValid )
2014-07-24 01:08:52 +00:00
{
2014-07-25 04:58:19 +00:00
if ( nActiveFloppy = = 0 ) g_nSectorDrive1 = - 1 ;
else g_nSectorDrive2 = - 1 ;
2014-07-24 01:08:52 +00:00
}
2014-07-25 04:58:19 +00:00
sprintf_s ( g_sTrackDrive1 , sizeof ( g_sTrackDrive1 ) , " %2d " , g_nTrackDrive1 ) ;
2016-09-10 00:35:07 +00:00
if ( g_nSectorDrive1 < 0 ) sprintf_s ( g_sSectorDrive1 , sizeof ( g_sSectorDrive1 ) , " ?? " ) ;
2014-07-25 04:58:19 +00:00
else sprintf_s ( g_sSectorDrive1 , sizeof ( g_sSectorDrive1 ) , " %2d " , g_nSectorDrive1 ) ;
sprintf_s ( g_sTrackDrive2 , sizeof ( g_sTrackDrive2 ) , " %2d " , g_nTrackDrive2 ) ;
2016-09-10 00:35:07 +00:00
if ( g_nSectorDrive2 < 0 ) sprintf_s ( g_sSectorDrive2 , sizeof ( g_sSectorDrive2 ) , " ?? " ) ;
2014-07-25 04:58:19 +00:00
else sprintf_s ( g_sSectorDrive2 , sizeof ( g_sSectorDrive2 ) , " %2d " , g_nSectorDrive2 ) ;
2014-07-24 01:08:52 +00:00
// Draw Track/Sector
FrameReleaseDC ( ) ;
HDC dc = ( passdc ? passdc : GetDC ( g_hFrameWindow ) ) ;
int x = buttonx ;
2017-10-21 20:59:21 +00:00
int y = buttony + BUTTONS * BUTTONCY + 4 ;
2014-07-22 01:21:31 +00:00
2014-07-22 05:56:57 +00:00
SelectObject ( dc , smallfont ) ;
SetBkMode ( dc , OPAQUE ) ;
SetBkColor ( dc , RGB ( 0 , 0 , 0 ) ) ;
SetTextAlign ( dc , TA_LEFT | TA_TOP ) ;
2014-07-24 01:08:52 +00:00
char text [ 16 ] ;
2014-07-22 05:56:57 +00:00
2014-07-22 01:21:31 +00:00
if ( g_bIsFullScreen )
{
2017-10-05 21:06:53 +00:00
// GH#57 - drive lights in full screen mode
2017-10-02 21:22:26 +00:00
if ( ! g_bFullScreen_ShowSubunitStatus )
return ;
2014-07-25 04:58:19 +00:00
SetTextColor ( dc , g_aDiskFullScreenColorsLED [ g_eStatusDrive1 ] ) ;
2014-07-24 01:08:52 +00:00
TextOut ( dc , x + 3 , y + 2 , TEXT ( " 1 " ) , 1 ) ;
2014-07-22 01:21:31 +00:00
2014-07-25 04:58:19 +00:00
SetTextColor ( dc , g_aDiskFullScreenColorsLED [ g_eStatusDrive2 ] ) ;
2014-07-24 01:08:52 +00:00
TextOut ( dc , x + 13 , y + 2 , TEXT ( " 2 " ) , 1 ) ;
int dx = 0 ;
if ( nActiveFloppy = = 0 )
sprintf ( text , " %s/%s " , g_sTrackDrive1 , g_sSectorDrive1 ) ;
else
sprintf ( text , " %s/%s " , g_sTrackDrive2 , g_sSectorDrive2 ) ;
SetTextColor ( dc , g_aDiskFullScreenColorsLED [ DISK_STATUS_READ ] ) ;
TextOut ( dc , x + dx , y - 12 , text , strlen ( text ) ) ; // original: y+2; y-12 puts status in the Configuration Button Icon
2014-07-22 01:21:31 +00:00
}
else
{
2014-07-28 21:18:32 +00:00
// NB. Only draw Track/Sector if 2x windowed
2014-08-25 20:42:23 +00:00
if ( g_nViewportScale = = 1 )
2014-07-28 21:18:32 +00:00
return ;
2014-07-22 01:21:31 +00:00
2014-07-28 21:18:32 +00:00
// Erase background
SelectObject ( dc , GetStockObject ( NULL_PEN ) ) ;
SelectObject ( dc , btnfacebrush ) ;
Rectangle ( dc , x + 4 , y + 32 , x + BUTTONCX + 1 , y + 56 ) ; // y+35 -> 44 -> 56
2014-07-22 05:56:57 +00:00
2014-07-28 21:18:32 +00:00
SetTextColor ( dc , RGB ( 0 , 0 , 0 ) ) ;
SetBkMode ( dc , TRANSPARENT ) ;
2014-07-22 01:21:31 +00:00
2014-07-28 21:18:32 +00:00
sprintf ( text , " T%s " , g_sTrackDrive1 ) ;
2017-10-21 20:59:21 +00:00
TextOut ( dc , x + 6 , y + 32 , text , strlen ( text ) ) ;
2014-07-28 21:18:32 +00:00
sprintf ( text , " S%s " , g_sSectorDrive1 ) ;
2017-10-21 20:59:21 +00:00
TextOut ( dc , x + 6 , y + 42 , text , strlen ( text ) ) ;
2014-07-28 21:18:32 +00:00
sprintf ( text , " T%s " , g_sTrackDrive2 ) ;
2017-10-21 20:59:21 +00:00
TextOut ( dc , x + 26 , y + 32 , text , strlen ( text ) ) ;
2014-07-28 21:18:32 +00:00
sprintf ( text , " S%s " , g_sSectorDrive2 ) ;
TextOut ( dc , x + 26 , y + 42 , text , strlen ( text ) ) ;
2014-07-22 01:21:31 +00:00
}
}
2006-02-25 20:50:29 +00:00
//===========================================================================
2008-06-08 12:31:50 +00:00
static void DrawStatusArea ( HDC passdc , int drawflags )
2006-06-26 16:59:48 +00:00
{
2016-03-21 23:48:02 +00:00
if ( g_hFrameWindow = = NULL )
{
// TC: Fix drawing of drive buttons before frame created:
// . Main init loop: LoadConfiguration() called before FrameCreateWindow(), eg:
// LoadConfiguration() -> Disk_LoadLastDiskImage() -> DiskInsert() -> FrameRefreshStatus()
return ;
}
2006-06-26 16:59:48 +00:00
FrameReleaseDC ( ) ;
HDC dc = ( passdc ? passdc : GetDC ( g_hFrameWindow ) ) ;
int x = buttonx ;
int y = buttony + BUTTONS * BUTTONCY + 1 ;
2010-12-20 23:46:11 +00:00
const bool bCaps = KeybGetCapsStatus ( ) ;
//const bool bP8Caps = KeybGetP8CapsStatus(); // TODO: FIXME: Not used ?! Should show the LED status ...
2010-12-18 21:00:52 +00:00
# if HD_LED
// 1.19.0.0 Hard Disk Status/Indicator Light
2010-12-20 23:46:11 +00:00
Disk_Status_e eHardDriveStatus = DISK_STATUS_OFF ;
HD_GetLightStatus ( & eHardDriveStatus ) ;
2010-12-18 21:00:52 +00:00
# endif
2009-02-16 19:11:33 +00:00
if ( g_bIsFullScreen )
2006-02-25 20:50:29 +00:00
{
2017-10-02 21:22:26 +00:00
if ( ! g_bFullScreen_ShowSubunitStatus )
{
// Erase Config button icon too, as trk/sec is written here - see FrameDrawDiskStatus()
2017-10-05 21:06:53 +00:00
RECT rect = { x - 2 , y - BUTTONCY , x + BUTTONCX + 2 , y + BUTTONCY } ; // Extend rect's width by +/-2 as the TITLE_PAUSED text is wider than an icon button
2017-10-02 21:22:26 +00:00
FillRect ( dc , & rect , ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) ) ;
}
else
{
SelectObject ( dc , smallfont ) ;
2009-02-18 23:53:24 +00:00
2017-10-02 21:22:26 +00:00
if ( drawflags & DRAW_DISK_STATUS )
FrameDrawDiskStatus ( dc ) ;
2009-02-18 23:53:24 +00:00
2010-12-18 21:30:50 +00:00
# if HD_LED
2017-10-05 21:06:53 +00:00
SetTextAlign ( dc , TA_RIGHT | TA_TOP ) ;
2017-10-02 21:22:26 +00:00
SetTextColor ( dc , g_aDiskFullScreenColorsLED [ eHardDriveStatus ] ) ;
TextOut ( dc , x + 23 , y + 2 , TEXT ( " H " ) , 1 ) ;
2010-12-18 21:30:50 +00:00
# endif
2017-10-02 21:22:26 +00:00
if ( ! IS_APPLE2 )
{
SetTextAlign ( dc , TA_RIGHT | TA_TOP ) ;
SetTextColor ( dc , ( bCaps
? RGB ( 128 , 128 , 128 )
: RGB ( 0 , 0 , 0 ) ) ) ;
2010-12-18 21:30:50 +00:00
2017-10-02 21:22:26 +00:00
TextOut ( dc , x + BUTTONCX , y + 2 , TEXT ( " A " ) , 1 ) ; // NB. Caps Lock indicator is already flush right!
}
2017-10-05 21:06:53 +00:00
//
static const char * pCurrentAppModeText = NULL ;
const char * const pNewAppModeText = ( g_nAppMode = = MODE_PAUSED )
2017-10-02 21:22:26 +00:00
? TITLE_PAUSED
2017-10-05 21:06:53 +00:00
: ( g_nAppMode = = MODE_STEPPING )
? TITLE_STEPPING
: NULL ;
SetTextAlign ( dc , TA_CENTER | TA_TOP ) ;
if ( pCurrentAppModeText & & pNewAppModeText ! = pCurrentAppModeText )
{
SetTextColor ( dc , RGB ( 0 , 0 , 0 ) ) ;
TextOut ( dc , x + BUTTONCX / 2 , y + 13 , pCurrentAppModeText , strlen ( pCurrentAppModeText ) ) ;
pCurrentAppModeText = NULL ;
}
if ( pNewAppModeText )
{
SetTextColor ( dc , RGB ( 255 , 255 , 255 ) ) ;
TextOut ( dc , x + BUTTONCX / 2 , y + 13 , pNewAppModeText , strlen ( pNewAppModeText ) ) ;
pCurrentAppModeText = pNewAppModeText ;
}
2006-06-26 16:59:48 +00:00
}
2006-02-25 20:50:29 +00:00
}
2017-10-02 21:22:26 +00:00
else // !g_bIsFullScreen
2006-06-26 16:59:48 +00:00
{
if ( drawflags & DRAW_BACKGROUND )
{
SelectObject ( dc , GetStockObject ( NULL_PEN ) ) ;
SelectObject ( dc , btnfacebrush ) ;
2017-10-05 21:06:53 +00:00
Rectangle ( dc , x , y , x + BUTTONCX + 2 , y + 34 ) ;
Draw3dRect ( dc , x + 1 , y + 3 , x + BUTTONCX , y + 30 , 0 ) ;
2014-07-22 05:56:57 +00:00
2006-06-26 16:59:48 +00:00
SelectObject ( dc , smallfont ) ;
SetTextAlign ( dc , TA_CENTER | TA_TOP ) ;
SetTextColor ( dc , RGB ( 0 , 0 , 0 ) ) ;
SetBkMode ( dc , TRANSPARENT ) ;
2010-12-18 21:00:52 +00:00
TextOut ( dc , x + 7 , y + 5 , TEXT ( " 1 " ) , 1 ) ;
TextOut ( dc , x + 27 , y + 5 , TEXT ( " 2 " ) , 1 ) ;
// 1.19.0.0 Hard Disk Status/Indicator Light
TextOut ( dc , x + 7 , y + 17 , TEXT ( " H " ) , 1 ) ;
2006-06-26 16:59:48 +00:00
}
2014-07-22 01:21:31 +00:00
2006-06-26 16:59:48 +00:00
if ( drawflags & DRAW_LEDS )
{
2014-07-24 01:08:52 +00:00
FrameDrawDiskLEDS ( dc ) ;
2010-12-18 21:00:52 +00:00
2014-07-29 14:56:55 +00:00
if ( drawflags & DRAW_DISK_STATUS )
FrameDrawDiskStatus ( dc ) ;
2006-11-28 16:34:21 +00:00
2007-05-28 11:16:42 +00:00
if ( ! IS_APPLE2 )
2006-11-28 16:34:21 +00:00
{
2010-12-18 21:00:52 +00:00
RECT rCapsLed = { 0 , 0 , 10 , 12 } ; // HACK: HARD-CODED bitmaps size
switch ( g_Apple2Type )
{
case A2TYPE_APPLE2 :
case A2TYPE_APPLE2PLUS :
case A2TYPE_APPLE2E :
2012-09-16 21:53:07 +00:00
case A2TYPE_APPLE2EENHANCED :
2010-12-18 21:00:52 +00:00
default : DrawBitmapRect ( dc , x + 31 , y + 17 , & rCapsLed , g_hCapsLockBitmap [ bCaps ! = 0 ] ) ; break ;
2011-01-06 17:59:19 +00:00
case A2TYPE_PRAVETS82 :
case A2TYPE_PRAVETS8M : DrawBitmapRect ( dc , x + 31 , y + 17 , & rCapsLed , g_hCapsBitmapP8 [ bCaps ! = 0 ] ) ; break ; // TODO: FIXME: Shouldn't one of these use g_hCapsBitmapLat ??
case A2TYPE_PRAVETS8A : DrawBitmapRect ( dc , x + 31 , y + 17 , & rCapsLed , g_hCapsBitmapP8 [ bCaps ! = 0 ] ) ; break ;
2010-12-18 21:00:52 +00:00
}
# if HD_LED
// 1.19.0.0 Hard Disk Status/Indicator Light
2014-07-22 01:21:31 +00:00
RECT rDiskLed = { 0 , 0 , 8 , 8 } ;
2010-12-20 23:46:11 +00:00
DrawBitmapRect ( dc , x + 12 , y + 18 , & rDiskLed , g_hDiskWindowedLED [ eHardDriveStatus ] ) ;
2010-12-18 21:00:52 +00:00
# endif
2006-11-28 16:34:21 +00:00
}
2006-06-26 16:59:48 +00:00
}
if ( drawflags & DRAW_TITLE )
{
2011-02-20 07:32:09 +00:00
GetAppleWindowTitle ( ) ; // SetWindowText() // WindowTitle
2019-09-07 09:16:51 +00:00
SendMessage ( g_hFrameWindow , WM_SETTEXT , 0 , ( LPARAM ) g_pAppTitle . c_str ( ) ) ;
2006-06-26 16:59:48 +00:00
}
2014-07-22 01:21:31 +00:00
2006-06-26 16:59:48 +00:00
if ( drawflags & DRAW_BUTTON_DRIVES )
{
DrawButton ( dc , BTN_DRIVE1 ) ;
DrawButton ( dc , BTN_DRIVE2 ) ;
}
}
if ( ! passdc )
ReleaseDC ( g_hFrameWindow , dc ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2008-06-08 12:31:50 +00:00
static void EraseButton ( int number ) {
2006-02-25 20:50:29 +00:00
RECT rect ;
rect . left = buttonx ;
rect . right = rect . left + BUTTONCX ;
rect . top = buttony + number * BUTTONCY ;
rect . bottom = rect . top + BUTTONCY ;
2009-02-21 04:42:35 +00:00
InvalidateRect ( g_hFrameWindow , & rect , 1 ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2008-06-08 12:31:50 +00:00
2006-06-26 16:59:48 +00:00
LRESULT CALLBACK FrameWndProc (
HWND window ,
UINT message ,
WPARAM wparam ,
LPARAM lparam )
{
switch ( message )
{
2008-06-08 12:31:50 +00:00
case WM_ACTIVATE : // Sent when window is activated/deactivated. wParam indicates WA_ACTIVE, WA_INACTIVE, etc
// Eg. Deactivate when Config dialog is active, AppleWin app loses focus, etc
2006-02-25 20:50:29 +00:00
JoyReset ( ) ;
2017-10-28 20:59:48 +00:00
SetUsingCursor ( FALSE ) ;
2008-06-08 12:31:50 +00:00
RevealCursor ( ) ;
2017-10-28 20:59:48 +00:00
FullScreenRevealCursor ( ) ;
2017-10-28 21:13:05 +00:00
g_bFrameActive = ( wparam ! = WA_INACTIVE ) ;
2006-02-25 20:50:29 +00:00
break ;
2008-06-08 12:31:50 +00:00
case WM_ACTIVATEAPP : // Sent when different app's window is activated/deactivated.
// Eg. Deactivate when AppleWin app loses focus
g_bAppActive = ( wparam ? TRUE : FALSE ) ;
2006-02-25 20:50:29 +00:00
break ;
case WM_CLOSE :
2013-03-23 13:34:01 +00:00
LogFileOutput ( " WM_CLOSE \n " ) ;
2016-09-10 21:58:26 +00:00
if ( g_bIsFullScreen & & g_bRestart )
2016-07-23 21:53:29 +00:00
g_bRestartFullScreen = true ;
2009-02-16 19:11:33 +00:00
if ( g_bIsFullScreen )
2006-02-25 20:50:29 +00:00
SetNormalMode ( ) ;
if ( ! IsIconic ( window ) )
GetWindowRect ( window , & framerect ) ;
2010-01-17 18:43:06 +00:00
RegSaveValue ( TEXT ( REG_PREFS ) , TEXT ( REGVALUE_PREF_WINDOW_X_POS ) , 1 , framerect . left ) ;
RegSaveValue ( TEXT ( REG_PREFS ) , TEXT ( REGVALUE_PREF_WINDOW_Y_POS ) , 1 , framerect . top ) ;
2006-02-25 20:50:29 +00:00
FrameReleaseDC ( ) ;
2017-10-28 20:59:48 +00:00
SetUsingCursor ( FALSE ) ;
2006-02-25 20:50:29 +00:00
if ( helpquit ) {
helpquit = 0 ;
HtmlHelp ( NULL , NULL , HH_CLOSE_ALL , 0 ) ;
}
2017-10-28 20:59:48 +00:00
if ( g_TimerIDEvent_100msec )
{
BOOL bRes = KillTimer ( g_hFrameWindow , g_TimerIDEvent_100msec ) ;
LogFileOutput ( " KillTimer(g_TimerIDEvent_100msec), res=%d \n " , bRes ? 1 : 0 ) ;
g_TimerIDEvent_100msec = 0 ;
}
2013-03-23 13:34:01 +00:00
LogFileOutput ( " WM_CLOSE (done) \n " ) ;
2018-07-31 17:06:53 +00:00
// Exit via DefWindowProc(), which does the default action for WM_CLOSE, which is to call DestroyWindow(), posting WM_DESTROY
2006-02-25 20:50:29 +00:00
break ;
2018-07-31 17:17:42 +00:00
case WM_DESTROY :
LogFileOutput ( " WM_DESTROY \n " ) ;
DragAcceptFiles ( window , 0 ) ;
if ( ! g_bRestart ) // GH#564: Only save-state on shutdown (not on a restart)
Snapshot_Shutdown ( ) ;
DebugDestroy ( ) ;
if ( ! g_bRestart ) {
2019-04-14 16:01:49 +00:00
sg_Disk2Card . Destroy ( ) ;
2018-07-31 17:17:42 +00:00
ImageDestroy ( ) ;
HD_Destroy ( ) ;
}
PrintDestroy ( ) ;
sg_SSC . CommDestroy ( ) ;
CpuDestroy ( ) ;
MemDestroy ( ) ;
SpkrDestroy ( ) ;
VideoDestroy ( ) ;
MB_Destroy ( ) ;
DeleteGdiObjects ( ) ;
DIMouse : : DirectInputUninit ( window ) ; // NB. do before window is destroyed
PostQuitMessage ( 0 ) ; // Post WM_QUIT message to the thread's message queue
LogFileOutput ( " WM_DESTROY (done) \n " ) ;
break ;
2006-02-25 20:50:29 +00:00
case WM_CREATE :
2013-03-23 13:34:01 +00:00
LogFileOutput ( " WM_CREATE \n " ) ;
2013-03-28 22:28:42 +00:00
g_hFrameWindow = window ; // NB. g_hFrameWindow by CreateWindow()
2013-03-23 13:34:01 +00:00
2006-02-25 20:50:29 +00:00
CreateGdiObjects ( ) ;
2013-03-23 13:34:01 +00:00
LogFileOutput ( " WM_CREATE: CreateGdiObjects() \n " ) ;
2006-02-25 20:50:29 +00:00
DSInit ( ) ;
2013-03-23 13:34:01 +00:00
LogFileOutput ( " WM_CREATE: DSInit() \n " ) ;
2013-04-21 21:31:12 +00:00
DIMouse : : DirectInputInit ( window ) ;
LogFileOutput ( " WM_CREATE: DIMouse::DirectInputInit() \n " ) ;
2013-03-23 13:34:01 +00:00
MB_Initialize ( ) ;
LogFileOutput ( " WM_CREATE: MB_Initialize() \n " ) ;
SpkrInitialize ( ) ;
LogFileOutput ( " WM_CREATE: SpkrInitialize() \n " ) ;
DragAcceptFiles ( window , 1 ) ;
LogFileOutput ( " WM_CREATE: DragAcceptFiles() \n " ) ;
LogFileOutput ( " WM_CREATE (done) \n " ) ;
break ;
2006-02-25 20:50:29 +00:00
case WM_DDE_INITIATE : {
2013-03-23 13:34:01 +00:00
LogFileOutput ( " WM_DDE_INITIATE \n " ) ;
2006-02-25 20:50:29 +00:00
ATOM application = GlobalAddAtom ( TEXT ( " applewin " ) ) ;
ATOM topic = GlobalAddAtom ( TEXT ( " system " ) ) ;
if ( LOWORD ( lparam ) = = application & & HIWORD ( lparam ) = = topic )
SendMessage ( ( HWND ) wparam , WM_DDE_ACK , ( WPARAM ) window , MAKELPARAM ( application , topic ) ) ;
GlobalDeleteAtom ( application ) ;
GlobalDeleteAtom ( topic ) ;
2013-03-23 13:34:01 +00:00
LogFileOutput ( " WM_DDE_INITIATE (done) \n " ) ;
2006-02-25 20:50:29 +00:00
break ;
}
case WM_DDE_EXECUTE : {
2013-03-23 13:34:01 +00:00
LogFileOutput ( " WM_DDE_EXECUTE \n " ) ;
2006-02-25 20:50:29 +00:00
LPTSTR filename = ( LPTSTR ) GlobalLock ( ( HGLOBAL ) lparam ) ;
2013-12-06 21:10:41 +00:00
//MessageBox( g_hFrameWindow, filename, "DDE Exec", MB_OK );
2019-04-14 16:01:49 +00:00
ImageError_e Error = sg_Disk2Card . InsertDisk ( DRIVE_1 , filename , IMAGE_USE_FILES_WRITE_PROTECT_STATUS , IMAGE_DONT_CREATE ) ;
2010-01-03 18:43:08 +00:00
if ( Error = = eIMAGE_ERROR_NONE )
{
2009-02-16 19:11:33 +00:00
if ( ! g_bIsFullScreen )
2006-02-25 20:50:29 +00:00
DrawButton ( ( HDC ) 0 , BTN_DRIVE1 ) ;
2010-01-17 18:43:06 +00:00
PostMessage ( window , WM_USER_BOOT , 0 , 0 ) ;
2006-02-25 20:50:29 +00:00
}
else
2009-01-06 22:02:31 +00:00
{
2019-04-14 16:01:49 +00:00
sg_Disk2Card . NotifyInvalidImage ( DRIVE_1 , filename , Error ) ;
2009-01-06 22:02:31 +00:00
}
2006-02-25 20:50:29 +00:00
GlobalUnlock ( ( HGLOBAL ) lparam ) ;
2013-03-23 13:34:01 +00:00
LogFileOutput ( " WM_DDE_EXECUTE (done) \n " ) ;
2006-02-25 20:50:29 +00:00
break ;
}
case WM_DISPLAYCHANGE :
VideoReinitialize ( ) ;
break ;
case WM_DROPFILES : {
TCHAR filename [ MAX_PATH ] ;
DragQueryFile ( ( HDROP ) wparam , 0 , filename , sizeof ( filename ) ) ;
POINT point ;
DragQueryPoint ( ( HDROP ) wparam , & point ) ;
RECT rect ;
rect . left = buttonx ;
rect . right = rect . left + BUTTONCX + 1 ;
rect . top = buttony + BTN_DRIVE2 * BUTTONCY + 1 ;
rect . bottom = rect . top + BUTTONCY ;
2010-01-03 18:43:08 +00:00
const int iDrive = PtInRect ( & rect , point ) ? DRIVE_2 : DRIVE_1 ;
2019-04-14 16:01:49 +00:00
ImageError_e Error = sg_Disk2Card . InsertDisk ( iDrive , filename , IMAGE_USE_FILES_WRITE_PROTECT_STATUS , IMAGE_DONT_CREATE ) ;
2010-01-03 18:43:08 +00:00
if ( Error = = eIMAGE_ERROR_NONE )
{
2009-02-16 19:11:33 +00:00
if ( ! g_bIsFullScreen )
2006-02-25 20:50:29 +00:00
DrawButton ( ( HDC ) 0 , PtInRect ( & rect , point ) ? BTN_DRIVE2 : BTN_DRIVE1 ) ;
rect . top = buttony + BTN_DRIVE1 * BUTTONCY + 1 ;
2010-01-03 18:43:08 +00:00
if ( ! PtInRect ( & rect , point ) )
{
2006-02-25 20:50:29 +00:00
SetForegroundWindow ( window ) ;
ProcessButtonClick ( BTN_RUN ) ;
}
}
else
2010-01-03 18:43:08 +00:00
{
2019-04-14 16:01:49 +00:00
sg_Disk2Card . NotifyInvalidImage ( iDrive , filename , Error ) ;
2010-01-03 18:43:08 +00:00
}
2006-02-25 20:50:29 +00:00
DragFinish ( ( HDROP ) wparam ) ;
break ;
}
2009-01-06 22:02:31 +00:00
// @see: http://answers.google.com/answers/threadview?id=133059
// Win32 doesn't pass the PrintScreen key via WM_CHAR
// else if (wparam == VK_SNAPSHOT)
// Solution: 2 choices:
// 1) register hotkey, or
// 2) Use low level Keyboard hooks
// We use the 1st one since it is compatible with Win95
case WM_HOTKEY :
// wparam = user id
// lparam = modifiers: shift, ctrl, alt, win
if ( wparam = = VK_SNAPSHOT_560 )
{
# if _DEBUG
2013-12-06 21:10:41 +00:00
// MessageBox( g_hFrameWindow, "Double 580x384 size!", "PrintScreen", MB_OK );
2009-01-06 22:02:31 +00:00
# endif
Video_TakeScreenShot ( SCREENSHOT_560x384 ) ;
}
else
2014-08-25 15:35:43 +00:00
if ( wparam = = VK_SNAPSHOT_280 ) // ( lparam & MOD_SHIFT )
2009-01-06 22:02:31 +00:00
{
# if _DEBUG
2014-08-25 15:35:43 +00:00
// MessageBox( g_hFrameWindow, "Normal 280x192 size!", "PrintScreen", MB_OK );
2009-01-06 22:02:31 +00:00
# endif
Video_TakeScreenShot ( SCREENSHOT_280x192 ) ;
}
2014-08-25 15:35:43 +00:00
else
if ( wparam = = VK_SNAPSHOT_TEXT ) // ( lparam & MOD_CONTROL )
{
char * pText ;
2014-12-02 06:01:08 +00:00
size_t nSize = 0 ;
// if viewing the debugger, get the last virtual debugger screen
2016-11-06 14:23:23 +00:00
if ( ( g_nAppMode = = MODE_DEBUG ) & & ! DebugGetVideoMode ( NULL ) )
2014-12-02 06:01:08 +00:00
nSize = Util_GetDebuggerText ( pText ) ;
else
nSize = Util_GetTextScreen ( pText ) ;
2014-08-25 15:35:43 +00:00
Util_CopyTextToClipboard ( nSize , pText ) ;
}
2009-01-06 22:02:31 +00:00
break ;
2006-06-26 16:59:48 +00:00
case WM_KEYDOWN :
KeybUpdateCtrlShiftStatus ( ) ;
2018-05-30 21:38:10 +00:00
2014-08-25 16:20:32 +00:00
// Process is done in WM_KEYUP: VK_F1 VK_F2 VK_F3 VK_F4 VK_F5 VK_F6 VK_F7 VK_F8
2006-06-26 16:59:48 +00:00
if ( ( wparam > = VK_F1 ) & & ( wparam < = VK_F8 ) & & ( buttondown = = - 1 ) )
2006-02-25 20:50:29 +00:00
{
2017-10-28 20:59:48 +00:00
SetUsingCursor ( FALSE ) ;
2006-06-26 16:59:48 +00:00
buttondown = wparam - VK_F1 ;
2009-02-16 19:11:33 +00:00
if ( g_bIsFullScreen & & ( buttonover ! = - 1 ) ) {
2006-06-26 16:59:48 +00:00
if ( buttonover ! = buttondown )
EraseButton ( buttonover ) ;
buttonover = - 1 ;
}
DrawButton ( ( HDC ) 0 , buttondown ) ;
2006-02-25 20:50:29 +00:00
}
2006-06-26 16:59:48 +00:00
else if ( wparam = = VK_F9 )
2017-04-30 17:50:27 +00:00
{
// F9 Next Video Mode
// SHIFT+F9 Prev Video Mode
// CTRL+SHIFT+F9 Toggle 50% Scan Lines
// ALT+F9 Can't use Alt-F9 as Alt is Open-Apple = Joystick Button #1
2009-02-17 01:36:34 +00:00
2018-07-27 20:55:53 +00:00
if ( ! KeybGetCtrlStatus ( ) & & ! KeybGetShiftStatus ( ) ) // F9
2009-02-14 03:36:15 +00:00
{
2009-02-16 19:11:33 +00:00
g_eVideoType + + ;
2009-02-18 16:05:01 +00:00
if ( g_eVideoType > = NUM_VIDEO_MODES )
2009-02-16 19:11:33 +00:00
g_eVideoType = 0 ;
2009-02-14 03:36:15 +00:00
}
2018-07-27 20:55:53 +00:00
else if ( ! KeybGetCtrlStatus ( ) & & KeybGetShiftStatus ( ) ) // SHIFT+F9
2009-02-14 03:36:15 +00:00
{
2009-02-16 19:11:33 +00:00
if ( g_eVideoType < = 0 )
2009-02-18 16:05:01 +00:00
g_eVideoType = NUM_VIDEO_MODES ;
2009-02-16 19:11:33 +00:00
g_eVideoType - - ;
2008-05-17 23:20:33 +00:00
}
2018-07-27 20:55:53 +00:00
else if ( KeybGetCtrlStatus ( ) & & KeybGetShiftStatus ( ) ) // CTRL+SHIFT+F9
2017-04-30 17:50:27 +00:00
{
2019-02-24 15:59:35 +00:00
SetVideoStyle ( ( VideoStyle_e ) ( GetVideoStyle ( ) ^ VS_HALF_SCANLINES ) ) ;
2017-04-30 17:50:27 +00:00
}
2008-05-17 23:20:33 +00:00
2009-02-18 16:05:01 +00:00
// TODO: Clean up code:FrameRefreshStatus(DRAW_TITLE) DrawStatusArea((HDC)0,DRAW_TITLE)
DrawStatusArea ( ( HDC ) 0 , DRAW_TITLE ) ;
2019-03-16 14:27:40 +00:00
VideoReinitialize ( false ) ;
2016-07-23 21:53:29 +00:00
if ( g_nAppMode ! = MODE_LOGO )
2006-06-26 16:59:48 +00:00
{
2016-11-06 14:23:23 +00:00
if ( g_nAppMode = = MODE_DEBUG )
{
UINT debugVideoMode ;
2016-11-06 14:33:14 +00:00
if ( DebugGetVideoMode ( & debugVideoMode ) )
VideoRefreshScreen ( debugVideoMode , true ) ;
else
VideoRefreshScreen ( ) ;
2016-11-06 14:23:23 +00:00
}
else
{
2016-11-06 14:33:14 +00:00
VideoRefreshScreen ( ) ;
2016-11-06 14:23:23 +00:00
}
2006-06-26 16:59:48 +00:00
}
2009-02-14 03:36:15 +00:00
Config_Save_Video ( ) ;
2006-02-25 20:50:29 +00:00
}
2018-05-30 21:38:10 +00:00
else if ( wparam = = VK_F10 )
{
2018-12-09 10:05:46 +00:00
if ( g_Apple2Type = = A2TYPE_APPLE2E | | g_Apple2Type = = A2TYPE_APPLE2EENHANCED )
2018-05-30 21:38:10 +00:00
{
2018-11-17 16:29:17 +00:00
SetVideoRomRockerSwitch ( ! GetVideoRomRockerSwitch ( ) ) ; // F10: toggle rocker switch
NTSC_VideoInitAppleType ( ) ;
}
else if ( g_Apple2Type = = A2TYPE_PRAVETS8A )
{
KeybToggleP8ACapsLock ( ) ; // F10: Toggles Pravets8A Capslock
2018-05-30 21:38:10 +00:00
}
}
2018-07-27 20:55:53 +00:00
else if ( wparam = = VK_F11 & & ! KeybGetCtrlStatus ( ) ) // Save state (F11)
2006-02-25 20:50:29 +00:00
{
2006-06-26 16:59:48 +00:00
SoundCore_SetFade ( FADE_OUT ) ;
2012-03-27 21:20:36 +00:00
if ( sg_PropertySheet . SaveStateSelectImage ( window , true ) )
2006-06-26 16:59:48 +00:00
{
Snapshot_SaveState ( ) ;
}
SoundCore_SetFade ( FADE_IN ) ;
2006-02-25 20:50:29 +00:00
}
2018-05-30 21:38:10 +00:00
else if ( wparam = = VK_F12 ) // Load state (F12 or Ctrl+F12)
2006-02-25 20:50:29 +00:00
{
2006-06-26 16:59:48 +00:00
SoundCore_SetFade ( FADE_OUT ) ;
2012-03-27 21:20:36 +00:00
if ( sg_PropertySheet . SaveStateSelectImage ( window , false ) )
2006-06-26 16:59:48 +00:00
{
Snapshot_LoadState ( ) ;
}
SoundCore_SetFade ( FADE_IN ) ;
}
else if ( wparam = = VK_CAPITAL )
2007-08-06 21:38:35 +00:00
{
2006-06-26 16:59:48 +00:00
KeybToggleCapsLock ( ) ;
2007-08-06 21:38:35 +00:00
}
2006-06-26 16:59:48 +00:00
else if ( wparam = = VK_PAUSE )
{
2017-10-28 20:59:48 +00:00
SetUsingCursor ( FALSE ) ;
2006-06-26 16:59:48 +00:00
switch ( g_nAppMode )
{
case MODE_RUNNING :
g_nAppMode = MODE_PAUSED ;
SoundCore_SetFade ( FADE_OUT ) ;
2008-06-08 12:31:50 +00:00
RevealCursor ( ) ;
2006-06-26 16:59:48 +00:00
break ;
case MODE_PAUSED :
g_nAppMode = MODE_RUNNING ;
SoundCore_SetFade ( FADE_IN ) ;
2008-05-18 18:23:25 +00:00
// Don't call FrameShowCursor(FALSE) else ClipCursor() won't be called
2006-06-26 16:59:48 +00:00
break ;
case MODE_STEPPING :
2017-03-12 21:45:55 +00:00
SoundCore_SetFade ( FADE_OUT ) ;
2017-04-22 16:13:41 +00:00
DebugStopStepping ( ) ;
2006-06-26 16:59:48 +00:00
break ;
}
DrawStatusArea ( ( HDC ) 0 , DRAW_TITLE ) ;
if ( ( g_nAppMode ! = MODE_LOGO ) & & ( g_nAppMode ! = MODE_DEBUG ) )
VideoRedrawScreen ( ) ;
}
2012-03-27 21:20:36 +00:00
else if ( ( wparam = = VK_SCROLL ) & & sg_PropertySheet . GetScrollLockToggle ( ) )
2007-08-06 21:38:35 +00:00
{
g_bScrollLock_FullSpeed = ! g_bScrollLock_FullSpeed ;
}
2006-06-26 16:59:48 +00:00
else if ( ( g_nAppMode = = MODE_RUNNING ) | | ( g_nAppMode = = MODE_LOGO ) | | ( g_nAppMode = = MODE_STEPPING ) )
{
2018-07-27 20:55:53 +00:00
// NB. Alt Gr (Right-Alt): this normally send 2 WM_KEYDOWN messages for: VK_LCONTROL, then VK_RMENU
2018-11-10 15:55:20 +00:00
// . NB. The keyboard hook filter will suppress VK_LCONTROL (if -hook-altgr-control is passed on the cmd-line)
2018-06-12 20:50:27 +00:00
bool extended = ( HIWORD ( lparam ) & KF_EXTENDED ) ! = 0 ;
2018-11-10 15:55:20 +00:00
bool down = true ;
bool autorep = ( HIWORD ( lparam ) & KF_REPEAT ) ! = 0 ;
2018-06-02 21:26:29 +00:00
BOOL IsJoyKey = JoyProcessKey ( ( int ) wparam , extended , down , autorep ) ;
2018-07-27 20:55:53 +00:00
# if DEBUG_KEY_MESSAGES
LogOutput ( " WM_KEYDOWN: %08X (scanCode=%04X) \n " , wparam , ( lparam > > 16 ) & 0xfff ) ;
# endif
2018-07-15 14:38:37 +00:00
if ( ! IsJoyKey & &
( g_nAppMode ! = MODE_LOGO ) ) // !MODE_LOGO - not emulating so don't pass to the VM's keyboard
2018-06-02 21:26:29 +00:00
{
2019-08-23 15:46:43 +00:00
// GH#678 Alternate key(s) to toggle max speed
2019-08-26 19:52:40 +00:00
// . Ctrl-0: Toggle speed: custom speed / Full-Speed
// . Ctrl-1: Speed = 1 MHz
// . Ctrl-3: Speed = Full-Speed
bool keyHandled = false ;
2019-08-23 15:46:43 +00:00
if ( KeybGetCtrlStatus ( ) & & wparam > = ' 0 ' & & wparam < = ' 9 ' )
{
switch ( wparam )
{
2019-08-26 19:52:40 +00:00
case ' 0 ' : // Toggle speed: custom speed / Full-Speed
if ( g_dwSpeed = = SPEED_MAX )
2019-08-29 18:19:47 +00:00
REGLOAD_DEFAULT ( TEXT ( REGVALUE_EMULATION_SPEED ) , & g_dwSpeed , SPEED_NORMAL ) ;
2019-08-26 19:52:40 +00:00
else
g_dwSpeed = SPEED_MAX ;
keyHandled = true ; break ;
case ' 1 ' : // Speed = 1 MHz
g_dwSpeed = SPEED_NORMAL ;
REGSAVE ( TEXT ( REGVALUE_EMULATION_SPEED ) , g_dwSpeed ) ;
keyHandled = true ; break ;
case ' 3 ' : // Speed = Full-Speed
g_dwSpeed = SPEED_MAX ;
keyHandled = true ; break ;
2019-08-23 15:46:43 +00:00
default :
break ;
}
2019-08-26 19:52:40 +00:00
if ( keyHandled )
SetCurrentCLK6502 ( ) ;
2019-08-23 15:46:43 +00:00
}
2019-08-26 19:52:40 +00:00
if ( ! keyHandled )
2019-08-23 15:46:43 +00:00
KeybQueueKeypress ( wparam , NOT_ASCII ) ;
2018-06-02 21:26:29 +00:00
2018-06-12 20:50:27 +00:00
if ( ! autorep )
KeybAnyKeyDown ( WM_KEYDOWN , wparam , extended ) ;
2018-06-02 21:26:29 +00:00
}
2006-06-26 16:59:48 +00:00
}
else if ( g_nAppMode = = MODE_DEBUG )
2009-02-21 04:42:35 +00:00
{
2011-02-21 23:54:09 +00:00
DebuggerProcessKey ( wparam ) ; // Debugger already active, re-direct key to debugger
2009-02-21 04:42:35 +00:00
}
2006-06-26 16:59:48 +00:00
break ;
2006-02-25 20:50:29 +00:00
2018-07-31 17:17:42 +00:00
case WM_CHAR :
if ( ( g_nAppMode = = MODE_RUNNING ) | | ( g_nAppMode = = MODE_STEPPING ) | | ( g_nAppMode = = MODE_LOGO ) )
{
if ( ! g_bDebuggerEatKey )
{
# if DEBUG_KEY_MESSAGES
LogOutput ( " WM_CHAR: %08X \n " , wparam ) ;
# endif
if ( g_nAppMode ! = MODE_LOGO ) // !MODE_LOGO - not emulating so don't pass to the VM's keyboard
KeybQueueKeypress ( wparam , ASCII ) ;
}
g_bDebuggerEatKey = false ;
}
else if ( g_nAppMode = = MODE_DEBUG )
{
DebuggerInputConsoleChar ( ( TCHAR ) wparam ) ;
}
break ;
2014-08-25 16:20:32 +00:00
case WM_KEYUP :
// Process is done in WM_KEYUP: VK_F1 VK_F2 VK_F3 VK_F4 VK_F5 VK_F6 VK_F7 VK_F8
2007-08-06 21:38:35 +00:00
if ( ( wparam > = VK_F1 ) & & ( wparam < = VK_F8 ) & & ( buttondown = = ( int ) wparam - VK_F1 ) )
{
buttondown = - 1 ;
2009-02-16 19:11:33 +00:00
if ( g_bIsFullScreen )
2007-08-06 21:38:35 +00:00
EraseButton ( wparam - VK_F1 ) ;
else
DrawButton ( ( HDC ) 0 , wparam - VK_F1 ) ;
2013-12-06 21:10:41 +00:00
ProcessButtonClick ( wparam - VK_F1 , true ) ;
2007-08-06 21:38:35 +00:00
}
else
{
2018-06-12 20:50:27 +00:00
bool extended = ( HIWORD ( lparam ) & KF_EXTENDED ) ! = 0 ;
2018-11-10 15:55:20 +00:00
bool down = false ;
bool autorep = false ;
2018-06-02 21:26:29 +00:00
BOOL bIsJoyKey = JoyProcessKey ( ( int ) wparam , extended , down , autorep ) ;
2018-07-27 20:55:53 +00:00
# if DEBUG_KEY_MESSAGES
LogOutput ( " WM_KEYUP: %08X \n " , wparam ) ;
# endif
2018-06-02 21:26:29 +00:00
if ( ! bIsJoyKey )
2018-06-12 20:50:27 +00:00
KeybAnyKeyDown ( WM_KEYUP , wparam , extended ) ;
2007-08-06 21:38:35 +00:00
}
break ;
2006-02-25 20:50:29 +00:00
case WM_LBUTTONDOWN :
2017-08-25 14:22:08 +00:00
KeybUpdateCtrlShiftStatus ( ) ;
2007-08-06 21:38:35 +00:00
if ( buttondown = = - 1 )
{
2006-02-25 20:50:29 +00:00
int x = LOWORD ( lparam ) ;
int y = HIWORD ( lparam ) ;
if ( ( x > = buttonx ) & &
( y > = buttony ) & &
2007-08-06 21:38:35 +00:00
( y < = buttony + BUTTONS * BUTTONCY ) )
{
2006-02-25 20:50:29 +00:00
buttonactive = buttondown = ( y - buttony - 1 ) / BUTTONCY ;
DrawButton ( ( HDC ) 0 , buttonactive ) ;
SetCapture ( window ) ;
}
2008-06-08 12:31:50 +00:00
else if ( g_bUsingCursor & & ! sg_Mouse . IsActive ( ) )
2007-08-06 21:38:35 +00:00
{
2006-02-25 20:50:29 +00:00
if ( wparam & ( MK_CONTROL | MK_SHIFT ) )
2007-08-06 21:38:35 +00:00
{
2017-10-28 20:59:48 +00:00
SetUsingCursor ( FALSE ) ;
2007-08-06 21:38:35 +00:00
}
2006-02-25 20:50:29 +00:00
else
2007-08-06 21:38:35 +00:00
{
2007-12-02 14:55:32 +00:00
JoySetButton ( BUTTON0 , BUTTON_DOWN ) ;
2007-08-06 21:38:35 +00:00
}
}
2007-12-02 14:55:32 +00:00
else if ( ( ( x < buttonx ) & & JoyUsingMouse ( ) & & ( ( g_nAppMode = = MODE_RUNNING ) | | ( g_nAppMode = = MODE_STEPPING ) ) ) )
2007-08-06 21:38:35 +00:00
{
2017-10-28 20:59:48 +00:00
SetUsingCursor ( TRUE ) ;
2007-08-06 21:38:35 +00:00
}
2008-05-17 23:20:33 +00:00
else if ( sg_Mouse . IsActive ( ) )
2007-12-02 14:55:32 +00:00
{
2008-05-17 23:20:33 +00:00
if ( wparam & ( MK_CONTROL | MK_SHIFT ) )
{
2008-06-08 12:31:50 +00:00
RevealCursor ( ) ;
2008-05-17 23:20:33 +00:00
}
2016-03-21 23:48:02 +00:00
else if ( g_nAppMode = = MODE_RUNNING | | g_nAppMode = = MODE_STEPPING )
2008-05-17 23:20:33 +00:00
{
if ( ! sg_Mouse . IsEnabled ( ) )
{
sg_Mouse . SetEnabled ( true ) ;
2008-06-08 12:31:50 +00:00
POINT Point ;
GetCursorPos ( & Point ) ;
ScreenToClient ( g_hFrameWindow , & Point ) ;
const int iOutOfBoundsX = 0 , iOutOfBoundsY = 0 ;
UpdateMouseInAppleViewport ( iOutOfBoundsX , iOutOfBoundsY , Point . x , Point . y ) ;
2008-05-18 18:23:25 +00:00
// Don't call SetButton() when 1st enabled (else get the confusing action of both enabling & an Apple mouse click)
2008-05-17 23:20:33 +00:00
}
else
{
sg_Mouse . SetButton ( BUTTON0 , BUTTON_DOWN ) ;
}
}
2007-12-02 14:55:32 +00:00
}
2017-08-25 14:22:08 +00:00
2006-07-05 21:23:13 +00:00
DebuggerMouseClick ( x , y ) ;
2006-02-25 20:50:29 +00:00
}
RelayEvent ( WM_LBUTTONDOWN , wparam , lparam ) ;
break ;
case WM_LBUTTONUP :
if ( buttonactive ! = - 1 ) {
ReleaseCapture ( ) ;
if ( buttondown = = buttonactive ) {
buttondown = - 1 ;
2009-02-16 19:11:33 +00:00
if ( g_bIsFullScreen )
2006-02-25 20:50:29 +00:00
EraseButton ( buttonactive ) ;
else
DrawButton ( ( HDC ) 0 , buttonactive ) ;
2013-12-06 21:10:41 +00:00
ProcessButtonClick ( buttonactive , true ) ;
2006-02-25 20:50:29 +00:00
}
buttonactive = - 1 ;
}
2008-06-08 12:31:50 +00:00
else if ( g_bUsingCursor & & ! sg_Mouse . IsActive ( ) )
2007-08-06 21:38:35 +00:00
{
2007-12-02 14:55:32 +00:00
JoySetButton ( BUTTON0 , BUTTON_UP ) ;
}
2008-05-17 23:20:33 +00:00
else if ( sg_Mouse . IsActive ( ) )
2007-12-02 14:55:32 +00:00
{
sg_Mouse . SetButton ( BUTTON0 , BUTTON_UP ) ;
2007-08-06 21:38:35 +00:00
}
2006-02-25 20:50:29 +00:00
RelayEvent ( WM_LBUTTONUP , wparam , lparam ) ;
break ;
case WM_MOUSEMOVE : {
2013-04-21 21:31:12 +00:00
// MSDN: "WM_MOUSEMOVE message" : Do not use the LOWORD or HIWORD macros to extract the x- and y- coordinates...
int x = GET_X_LPARAM ( lparam ) ;
int y = GET_Y_LPARAM ( lparam ) ;
2006-02-25 20:50:29 +00:00
int newover = ( ( ( x > = buttonx ) & &
( x < = buttonx + BUTTONCX ) & &
( y > = buttony ) & &
( y < = buttony + BUTTONS * BUTTONCY ) )
? ( y - buttony - 1 ) / BUTTONCY : - 1 ) ;
if ( buttonactive ! = - 1 ) {
int newdown = ( newover = = buttonactive ) ? buttonactive : - 1 ;
if ( newdown ! = buttondown ) {
buttondown = newdown ;
DrawButton ( ( HDC ) 0 , buttonactive ) ;
}
}
2009-02-16 19:11:33 +00:00
else if ( g_bIsFullScreen & & ( newover ! = buttonover ) & & ( buttondown = = - 1 ) ) {
2006-02-25 20:50:29 +00:00
if ( buttonover ! = - 1 )
EraseButton ( buttonover ) ;
buttonover = newover ;
if ( buttonover ! = - 1 )
DrawButton ( ( HDC ) 0 , buttonover ) ;
}
2008-06-08 12:31:50 +00:00
else if ( g_bUsingCursor & & ! sg_Mouse . IsActive ( ) )
2007-08-06 21:38:35 +00:00
{
2006-02-25 20:50:29 +00:00
DrawCrosshairs ( x , y ) ;
2012-12-29 14:53:52 +00:00
JoySetPosition ( x - viewportx - 2 , g_nViewportCX - 4 , y - viewporty - 2 , g_nViewportCY - 4 ) ;
2006-02-25 20:50:29 +00:00
}
2016-03-21 23:48:02 +00:00
else if ( sg_Mouse . IsActiveAndEnabled ( ) & & ( g_nAppMode = = MODE_RUNNING | | g_nAppMode = = MODE_STEPPING ) )
2007-12-02 14:55:32 +00:00
{
2008-05-17 23:20:33 +00:00
if ( g_bLastCursorInAppleViewport )
break ;
2008-05-18 18:23:25 +00:00
// Outside Apple viewport
2012-12-29 14:53:52 +00:00
const int iAppleScreenMaxX = g_nViewportCX - 1 ;
const int iAppleScreenMaxY = g_nViewportCY - 1 ;
2008-05-17 23:20:33 +00:00
const int iBoundMinX = viewportx ;
const int iBoundMaxX = iAppleScreenMaxX ;
const int iBoundMinY = viewporty ;
const int iBoundMaxY = iAppleScreenMaxY ;
int iOutOfBoundsX = 0 , iOutOfBoundsY = 0 ;
if ( x < iBoundMinX ) iOutOfBoundsX = - 1 ;
if ( x > iBoundMaxX ) iOutOfBoundsX = 1 ;
if ( y < iBoundMinY ) iOutOfBoundsY = - 1 ;
if ( y > iBoundMaxY ) iOutOfBoundsY = 1 ;
UpdateMouseInAppleViewport ( iOutOfBoundsX , iOutOfBoundsY , x , y ) ;
2007-12-02 14:55:32 +00:00
}
2008-05-17 23:20:33 +00:00
2017-10-28 20:59:48 +00:00
FullScreenRevealCursor ( ) ;
2006-02-25 20:50:29 +00:00
RelayEvent ( WM_MOUSEMOVE , wparam , lparam ) ;
break ;
}
2008-05-17 23:20:33 +00:00
case WM_TIMER :
if ( wparam = = IDEVENT_TIMER_MOUSE )
{
2008-06-08 12:31:50 +00:00
// NB. Need to check /g_bAppActive/ since WM_TIMER events still occur after AppleWin app has lost focus
2016-03-21 23:48:02 +00:00
if ( g_bAppActive & & sg_Mouse . IsActiveAndEnabled ( ) & & ( g_nAppMode = = MODE_RUNNING | | g_nAppMode = = MODE_STEPPING ) )
2008-05-17 23:20:33 +00:00
{
2008-06-08 12:31:50 +00:00
if ( ! g_bLastCursorInAppleViewport )
2008-05-17 23:20:33 +00:00
break ;
2008-05-18 18:23:25 +00:00
// Inside Apple viewport
2008-05-17 23:20:33 +00:00
int iOutOfBoundsX = 0 , iOutOfBoundsY = 0 ;
long dX , dY ;
if ( DIMouse : : ReadImmediateData ( & dX , & dY ) = = S_OK )
sg_Mouse . SetPositionRel ( dX , dY , & iOutOfBoundsX , & iOutOfBoundsY ) ;
UpdateMouseInAppleViewport ( iOutOfBoundsX , iOutOfBoundsY ) ;
}
}
2017-10-28 20:59:48 +00:00
else if ( wparam = = IDEVENT_TIMER_100MSEC ) // GH#504
{
if ( g_bIsFullScreen
& & ! sg_Mouse . IsActive ( ) // Don't interfere if there's a mousecard present!
& & ! g_bUsingCursor // Using mouse for joystick emulation (or mousecard restricted to window)
& & g_bShowingCursor
2017-10-28 21:13:05 +00:00
& & g_bFrameActive ) // Frame inactive when eg. Config or 'Select Disk Image' dialogs are opened
2017-10-28 20:59:48 +00:00
{
g_uCount100msec + + ;
if ( g_uCount100msec > 20 ) // Hide every 2sec of mouse inactivity
{
FrameShowCursor ( FALSE ) ;
}
}
}
2008-05-17 23:20:33 +00:00
break ;
2006-06-26 16:59:48 +00:00
// VSCROLL
// SB_LINEUP // Line Scrolling
// SB_PAGEUP // Page Scrolling
case WM_MOUSEWHEEL :
if ( g_nAppMode = = MODE_DEBUG )
{
KeybUpdateCtrlShiftStatus ( ) ;
int zDelta = ( short ) HIWORD ( wparam ) ;
if ( zDelta > 0 )
{
DebuggerProcessKey ( VK_UP ) ;
}
else
{
DebuggerProcessKey ( VK_DOWN ) ;
}
}
break ;
2010-01-03 18:43:08 +00:00
case WM_NOTIFY : // Tooltips for Drive buttons
2006-02-25 20:50:29 +00:00
if ( ( ( LPNMTTDISPINFO ) lparam ) - > hdr . hwndFrom = = tooltipwindow & &
( ( LPNMTTDISPINFO ) lparam ) - > hdr . code = = TTN_GETDISPINFO )
( ( LPNMTTDISPINFO ) lparam ) - > lpszText =
2019-09-07 08:02:39 +00:00
( LPTSTR ) sg_Disk2Card . GetFullDiskFilename ( ( ( LPNMTTDISPINFO ) lparam ) - > hdr . idFrom ) . c_str ( ) ;
2006-02-25 20:50:29 +00:00
break ;
case WM_PAINT :
if ( GetUpdateRect ( window , NULL , 0 ) ) {
2008-07-14 16:02:44 +00:00
g_bPaintingWindow = 1 ;
2006-02-25 20:50:29 +00:00
DrawFrameWindow ( ) ;
2008-07-14 16:02:44 +00:00
g_bPaintingWindow = 0 ;
2006-02-25 20:50:29 +00:00
}
break ;
case WM_PALETTECHANGED :
2009-02-21 04:42:35 +00:00
// To avoid creating an infinite loop, a window that receives this
// message must not realize its palette, unless it determines that
// wParam does not contain its own window handle.
if ( ( HWND ) wparam = = window )
2015-01-03 22:13:55 +00:00
break ;
2009-02-21 04:42:35 +00:00
// else fall through
2006-02-25 20:50:29 +00:00
case WM_QUERYNEWPALETTE :
DrawFrameWindow ( ) ;
break ;
case WM_RBUTTONDOWN :
case WM_RBUTTONUP :
2006-02-26 02:05:57 +00:00
// Right Click on Drive Icon -- eject Disk
if ( ( buttonover = = - 1 ) & & ( message = = WM_RBUTTONUP ) ) // HACK: BUTTON_NONE
{
int x = LOWORD ( lparam ) ;
int y = HIWORD ( lparam ) ;
if ( ( x > = buttonx ) & &
( y > = buttony ) & &
( y < = buttony + BUTTONS * BUTTONCY ) )
{
int iButton = ( y - buttony - 1 ) / BUTTONCY ;
int iDrive = iButton - BTN_DRIVE1 ;
if ( ( iButton = = BTN_DRIVE1 ) | | ( iButton = = BTN_DRIVE2 ) )
{
2006-02-28 18:40:59 +00:00
/*
2006-02-26 02:05:57 +00:00
if ( KeybGetShiftStatus ( ) )
DiskProtect ( iDrive , true ) ;
else
if ( KeybGetCtrlStatus ( ) )
DiskProtect ( iDrive , false ) ;
else
2006-02-28 18:40:59 +00:00
*/
{
2010-01-03 18:43:08 +00:00
RECT rect ; // client area
POINT pt ; // location of mouse click
// Get the bounding rectangle of the client area.
GetClientRect ( window , ( LPRECT ) & rect ) ;
// Get the client coordinates for the mouse click.
pt . x = GET_X_LPARAM ( lparam ) ;
pt . y = GET_Y_LPARAM ( lparam ) ;
// If the mouse click took place inside the client
// area, execute the application-defined function
// that displays the shortcut menu.
if ( PtInRect ( ( LPRECT ) & rect , pt ) )
ProcessDiskPopupMenu ( window , pt , iDrive ) ;
2006-02-28 18:40:59 +00:00
}
2006-02-26 02:05:57 +00:00
FrameRefreshStatus ( DRAW_LEDS | DRAW_BUTTON_DRIVES ) ;
DrawButton ( ( HDC ) 0 , iButton ) ;
}
}
}
2017-10-28 20:59:48 +00:00
if ( g_bUsingCursor & & ! sg_Mouse . IsActive ( ) )
JoySetButton ( BUTTON1 , ( message = = WM_RBUTTONDOWN ) ? BUTTON_DOWN : BUTTON_UP ) ;
else if ( sg_Mouse . IsActive ( ) )
sg_Mouse . SetButton ( BUTTON1 , ( message = = WM_RBUTTONDOWN ) ? BUTTON_DOWN : BUTTON_UP ) ;
2006-02-26 02:05:57 +00:00
RelayEvent ( message , wparam , lparam ) ;
break ;
2006-02-25 20:50:29 +00:00
case WM_SYSCOLORCHANGE :
2009-02-21 04:42:35 +00:00
# if DEBUG_DD_PALETTE
if ( g_bIsFullScreen )
OutputDebugString ( " WM_SYSCOLORCHANGE: Full Screen \n " ) ;
else
OutputDebugString ( " WM_SYSCOLORCHANGE: Windowed \n " ) ;
# endif
DeleteGdiObjects ( ) ;
CreateGdiObjects ( ) ;
break ;
2006-02-25 20:50:29 +00:00
case WM_SYSCOMMAND :
switch ( wparam & 0xFFF0 ) {
case SC_KEYMENU :
2009-02-16 19:11:33 +00:00
if ( g_bIsFullScreen & & g_bAppActive )
2006-02-25 20:50:29 +00:00
return 0 ;
break ;
case SC_MINIMIZE :
GetWindowRect ( window , & framerect ) ;
break ;
}
break ;
2018-06-10 17:14:34 +00:00
case WM_SYSKEYDOWN : // ALT + any key; or F10
2014-07-26 23:44:38 +00:00
KeybUpdateCtrlShiftStatus ( ) ;
2014-08-25 16:20:32 +00:00
// http://msdn.microsoft.com/en-us/library/windows/desktop/gg153546(v=vs.85).aspx
2018-07-27 20:55:53 +00:00
if ( g_bAltEnter_ToggleFullScreen & & KeybGetAltStatus ( ) & & ( wparam = = VK_RETURN ) ) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
2014-08-25 16:20:32 +00:00
return 0 ; // NOP -- eat key
2018-06-10 17:14:34 +00:00
PostMessage ( window , WM_KEYDOWN , wparam , lparam ) ;
2006-02-25 20:50:29 +00:00
2014-08-25 16:20:32 +00:00
if ( ( wparam = = VK_F10 ) | | ( wparam = = VK_MENU ) ) // VK_MENU == ALT Key
return 0 ;
2018-05-26 17:04:13 +00:00
2014-08-25 16:20:32 +00:00
break ;
case WM_SYSKEYUP :
KeybUpdateCtrlShiftStatus ( ) ;
2018-11-17 16:29:17 +00:00
// F10: no WM_KEYUP handler for VK_F10. Don't allow WM_KEYUP to pass to default handler which will show the app window's "menu" (and lose focus)
if ( wparam = = VK_F10 )
return 0 ;
2018-07-27 20:55:53 +00:00
if ( g_bAltEnter_ToggleFullScreen & & KeybGetAltStatus ( ) & & ( wparam = = VK_RETURN ) ) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
2014-08-25 16:20:32 +00:00
ScreenWindowResize ( false ) ;
else
PostMessage ( window , WM_KEYUP , wparam , lparam ) ;
2018-06-10 17:14:34 +00:00
2014-08-25 16:20:32 +00:00
break ;
2006-02-25 20:50:29 +00:00
2018-05-26 17:04:13 +00:00
case WM_MENUCHAR : // GH#556 - Suppress the Windows Default Beep (ie. Ding) whenever ALT+<key> is pressed
return ( MNC_CLOSE < < 16 ) | ( wparam & 0xffff ) ;
2006-02-25 20:50:29 +00:00
case WM_USER_BENCHMARK : {
UpdateWindow ( window ) ;
ResetMachineState ( ) ;
2006-06-12 22:06:50 +00:00
g_nAppMode = MODE_LOGO ;
2006-02-25 20:50:29 +00:00
DrawStatusArea ( ( HDC ) 0 , DRAW_TITLE ) ;
HCURSOR oldcursor = SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
VideoBenchmark ( ) ;
ResetMachineState ( ) ;
SetCursor ( oldcursor ) ;
break ;
}
case WM_USER_RESTART :
2018-07-31 17:17:42 +00:00
// Changed h/w config, eg. Apple computer type (][+ or //e), slot configuration, etc.
2016-09-10 21:58:26 +00:00
g_bRestart = true ;
2006-02-25 20:50:29 +00:00
PostMessage ( window , WM_CLOSE , 0 , 0 ) ;
break ;
case WM_USER_SAVESTATE : // Save state
Snapshot_SaveState ( ) ;
break ;
case WM_USER_LOADSTATE : // Load state
Snapshot_LoadState ( ) ;
break ;
2009-01-26 15:24:40 +00:00
case WM_USER_TCP_SERIAL : // TCP serial events
2010-01-17 18:43:06 +00:00
{
2009-01-26 15:24:40 +00:00
WORD error = WSAGETSELECTERROR ( lparam ) ;
if ( error ! = 0 )
{
LogOutput ( " TCP Serial Winsock error 0x%X (%d) \r " , error , error ) ;
switch ( error )
{
case WSAENETRESET :
case WSAECONNABORTED :
case WSAECONNRESET :
case WSAENOTCONN :
case WSAETIMEDOUT :
sg_SSC . CommTcpSerialClose ( ) ;
break ;
default :
sg_SSC . CommTcpSerialCleanup ( ) ;
break ;
}
}
else
{
WORD wSelectEvent = WSAGETSELECTEVENT ( lparam ) ;
switch ( wSelectEvent )
{
case FD_ACCEPT :
sg_SSC . CommTcpSerialAccept ( ) ;
break ;
case FD_CLOSE :
sg_SSC . CommTcpSerialClose ( ) ;
break ;
case FD_READ :
sg_SSC . CommTcpSerialReceive ( ) ;
break ;
}
}
break ;
2010-01-17 18:43:06 +00:00
}
// Message posted by: WM_DDE_EXECUTE & Cmd-line boot
case WM_USER_BOOT :
{
SetForegroundWindow ( window ) ;
Sleep ( 500 ) ; // Wait for SetForegroundWindow() to take affect (400ms seems OK, so use 500ms to be sure)
SoundCore_TweakVolumes ( ) ;
2014-08-25 16:20:32 +00:00
ProcessButtonClick ( BTN_RUN ) ;
2010-01-17 18:43:06 +00:00
break ;
}
2012-12-29 14:53:52 +00:00
// Message posted by: Cmd-line boot
case WM_USER_FULLSCREEN :
{
2014-08-25 16:40:52 +00:00
ScreenWindowResize ( false ) ;
2012-12-29 14:53:52 +00:00
break ;
}
2010-01-17 18:43:06 +00:00
} // switch(message)
2006-02-25 20:50:29 +00:00
return DefWindowProc ( window , message , wparam , lparam ) ;
}
2006-02-28 18:40:59 +00:00
2006-02-25 20:50:29 +00:00
//===========================================================================
2014-08-25 16:20:32 +00:00
// Process: VK_F6
2012-12-29 14:53:52 +00:00
static void ScreenWindowResize ( const bool bCtrlKey )
{
2014-08-25 20:49:58 +00:00
static int nOldViewportScale = kDEFAULT_VIEWPORT_SCALE ;
if ( g_bIsFullScreen ) // if full screen: then switch back to normal
2012-12-29 14:53:52 +00:00
{
SetNormalMode ( ) ;
2014-08-25 20:49:58 +00:00
FrameResizeWindow ( nOldViewportScale ) ;
2012-12-29 14:53:52 +00:00
}
2014-08-25 20:49:58 +00:00
else if ( bCtrlKey ) // if normal screen && CTRL: then toggle scaling
2014-08-25 16:20:32 +00:00
{
FrameResizeWindow ( ( g_nViewportScale = = 1 ) ? 2 : 1 ) ; // Toggle between 1x and 2x
REGSAVE ( TEXT ( REGVALUE_WINDOW_SCALE ) , g_nViewportScale ) ;
}
else
2012-12-29 14:53:52 +00:00
{
2014-08-25 20:49:58 +00:00
nOldViewportScale = g_nViewportScale ;
2013-01-06 13:47:52 +00:00
FrameResizeWindow ( 1 ) ; // reset to 1x
2012-12-29 14:53:52 +00:00
SetFullScreenMode ( ) ;
}
}
2013-12-06 21:10:41 +00:00
static bool ConfirmReboot ( bool bFromButtonUI )
{
2014-07-27 21:31:00 +00:00
if ( ! bFromButtonUI | | ! g_bConfirmReboot )
2013-12-06 21:10:41 +00:00
return true ;
2014-07-26 22:42:55 +00:00
int res = MessageBox ( g_hFrameWindow ,
" Are you sure you want to reboot? \n "
" (All data will be lost!) \n "
" \n "
2014-07-27 21:31:00 +00:00
" You can skip this dialog from displaying \n "
" in the future by unchecking: \n "
" \n "
" [ ] Confirm reboot \n "
" \n "
2014-07-26 22:42:55 +00:00
" in the Configuration dialog. \n "
, " Reboot " , MB_ICONWARNING | MB_YESNO ) ;
2013-12-06 21:10:41 +00:00
return res = = IDYES ;
}
static void ProcessButtonClick ( int button , bool bFromButtonUI /*=false*/ )
2009-02-21 04:42:35 +00:00
{
SoundCore_SetFade ( FADE_OUT ) ;
2017-03-12 21:45:55 +00:00
bool bAllowFadeIn = true ;
2006-02-25 20:50:29 +00:00
2009-02-21 04:42:35 +00:00
# if DEBUG_DD_PALETTE
char _text [ 80 ] ;
sprintf ( _text , " Button: F%d Full Screen: %d \n " , button + 1 , g_bIsFullScreen ) ;
OutputDebugString ( _text ) ;
# endif
2006-02-25 20:50:29 +00:00
switch ( button ) {
case BTN_HELP :
{
2019-09-06 16:34:25 +00:00
const std : : string filename = g_sProgramDir + TEXT ( " APPLEWIN.CHM " ) ;
2017-08-14 20:23:49 +00:00
// (GH#437) For any internet downloaded AppleWin.chm files (stored on an NTFS drive) there may be an Alt Data Stream containing a Zone Identifier
// - try to delete it, otherwise the content won't be displayed unless it's unblock (via File Properties)
{
2019-09-06 16:34:25 +00:00
const std : : string filename_with_zone_identifier = filename + TEXT ( " :Zone.Identifier " ) ;
DeleteFile ( filename_with_zone_identifier . c_str ( ) ) ;
2017-08-14 20:23:49 +00:00
}
2019-09-06 16:34:25 +00:00
HtmlHelp ( g_hFrameWindow , filename . c_str ( ) , HH_DISPLAY_TOC , 0 ) ;
2006-02-25 20:50:29 +00:00
helpquit = 1 ;
}
break ;
case BTN_RUN :
2009-04-16 21:29:28 +00:00
KeybUpdateCtrlShiftStatus ( ) ;
2018-07-27 20:55:53 +00:00
if ( KeybGetCtrlStatus ( ) )
2009-02-17 02:13:18 +00:00
{
CtrlReset ( ) ;
2017-04-22 19:42:42 +00:00
if ( g_nAppMode = = MODE_DEBUG )
2017-04-22 19:52:21 +00:00
DebugDisplay ( TRUE ) ;
2009-02-17 02:13:18 +00:00
return ;
}
2009-02-17 01:36:34 +00:00
if ( g_nAppMode = = MODE_LOGO )
{
2019-04-14 16:01:49 +00:00
sg_Disk2Card . Boot ( ) ;
2016-09-19 21:14:57 +00:00
LogFileTimeUntilFirstKeyReadReset ( ) ;
2009-02-17 01:36:34 +00:00
g_nAppMode = MODE_RUNNING ;
}
2017-04-22 19:42:42 +00:00
else if ( ( g_nAppMode = = MODE_RUNNING ) | | ( g_nAppMode = = MODE_DEBUG ) | | ( g_nAppMode = = MODE_STEPPING ) | | ( g_nAppMode = = MODE_PAUSED ) )
2009-02-17 01:36:34 +00:00
{
2013-12-06 21:10:41 +00:00
if ( ConfirmReboot ( bFromButtonUI ) )
{
ResetMachineState ( ) ;
2017-04-22 19:42:42 +00:00
// NB. Don't exit debugger or stepping
if ( g_nAppMode = = MODE_DEBUG )
2017-04-22 19:52:21 +00:00
DebugDisplay ( TRUE ) ;
2013-12-06 21:10:41 +00:00
}
2009-02-17 01:36:34 +00:00
}
2017-04-22 19:42:42 +00:00
2006-02-25 20:50:29 +00:00
DrawStatusArea ( ( HDC ) 0 , DRAW_TITLE ) ;
VideoRedrawScreen ( ) ;
break ;
case BTN_DRIVE1 :
case BTN_DRIVE2 :
2019-04-14 16:01:49 +00:00
sg_Disk2Card . UserSelectNewDiskImage ( button - BTN_DRIVE1 ) ;
2009-02-16 19:11:33 +00:00
if ( ! g_bIsFullScreen )
2006-02-25 20:50:29 +00:00
DrawButton ( ( HDC ) 0 , button ) ;
break ;
case BTN_DRIVESWAP :
2019-04-14 16:01:49 +00:00
sg_Disk2Card . DriveSwap ( ) ;
2006-02-25 20:50:29 +00:00
break ;
case BTN_FULLSCR :
2012-12-29 14:53:52 +00:00
KeybUpdateCtrlShiftStatus ( ) ;
2018-07-27 20:55:53 +00:00
ScreenWindowResize ( KeybGetCtrlStatus ( ) ) ;
2006-02-25 20:50:29 +00:00
break ;
case BTN_DEBUG :
2013-04-26 21:55:45 +00:00
if ( g_nAppMode = = MODE_LOGO & & ! GetLoadedSaveStateFlag ( ) )
2006-06-12 22:06:50 +00:00
{
2017-04-22 16:13:41 +00:00
// FIXME: Why is this needed? Surely when state is MODE_LOGO, then AppleII system will have been reset!
// - Transition to MODE_LOGO when: (a) AppleWin starts, (b) there's a Config change to the AppleII h/w
2006-06-12 22:06:50 +00:00
ResetMachineState ( ) ;
}
2013-04-26 21:55:45 +00:00
2006-06-12 22:06:50 +00:00
if ( g_nAppMode = = MODE_STEPPING )
{
2017-03-12 21:45:55 +00:00
// Allow F7 to enter debugger even when not MODE_RUNNING
2017-04-22 16:13:41 +00:00
DebugStopStepping ( ) ;
2017-03-12 21:45:55 +00:00
bAllowFadeIn = false ;
2006-06-12 22:06:50 +00:00
}
2017-04-22 16:13:41 +00:00
else if ( g_nAppMode = = MODE_DEBUG )
2006-06-12 22:06:50 +00:00
{
2017-04-22 19:42:42 +00:00
DebugExitDebugger ( ) ; // Exit debugger, switch to MODE_RUNNING or MODE_STEPPING
2017-05-29 20:28:45 +00:00
g_bDebuggerEatKey = false ; // Don't "eat" the next keypress when leaving the debugger via F7 (or clicking the Debugger button)
2006-06-12 22:06:50 +00:00
}
2017-04-22 19:42:42 +00:00
else // MODE_RUNNING, MODE_LOGO, MODE_PAUSED
2006-06-12 22:06:50 +00:00
{
DebugBegin ( ) ;
}
2006-02-25 20:50:29 +00:00
break ;
case BTN_SETUP :
{
2012-03-27 21:20:36 +00:00
sg_PropertySheet . Init ( ) ;
2006-02-25 20:50:29 +00:00
}
break ;
}
2017-03-12 21:45:55 +00:00
if ( ( g_nAppMode ! = MODE_DEBUG ) & & ( g_nAppMode ! = MODE_PAUSED ) & & bAllowFadeIn )
2006-02-25 20:50:29 +00:00
{
SoundCore_SetFade ( FADE_IN ) ;
}
}
2006-02-28 18:40:59 +00:00
//===========================================================================
2008-06-20 23:47:25 +00:00
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/menus/usingmenus.asp
// http://www.codeproject.com/menu/MenusForBeginners.asp?df=100&forumid=67645&exp=0&select=903061
2010-01-03 18:43:08 +00:00
void ProcessDiskPopupMenu ( HWND hwnd , POINT pt , const int iDrive )
2019-08-09 03:50:29 +00:00
{
// This is the default installation path of CiderPress.
// It shall not be left blank, otherwise an explorer window will be open.
TCHAR PathToCiderPress [ MAX_PATH ] ;
RegLoadString (
TEXT ( " Configuration " ) ,
REGVALUE_CIDERPRESSLOC ,
1 ,
PathToCiderPress ,
MAX_PATH ,
TEXT ( " C: \\ Program Files \\ faddenSoft \\ CiderPress \\ CiderPress.exe " ) ) ;
2008-06-20 23:47:25 +00:00
//TODO: A directory is open if an empty path to CiderPress is set. This has to be fixed.
2014-08-14 19:29:01 +00:00
std : : string filename1 = " \" " ;
2019-04-14 16:01:49 +00:00
filename1 . append ( sg_Disk2Card . GetFullName ( iDrive ) ) ;
2013-12-06 21:10:41 +00:00
filename1 . append ( " \" " ) ;
2014-08-14 19:29:01 +00:00
std : : string sFileNameEmpty = " \" " ;
2013-12-06 21:10:41 +00:00
sFileNameEmpty . append ( " \" " ) ;
2010-01-03 18:43:08 +00:00
// Load the menu template containing the shortcut menu from the
// application's resources.
HMENU hmenu = LoadMenu ( g_hInstance , MAKEINTRESOURCE ( IDR_MENU_DISK_POPUP ) ) ; // menu template
if ( hmenu = = NULL )
return ;
// Get the first shortcut menu in the menu template.
// This is the menu that TrackPopupMenu displays.
HMENU hmenuTrackPopup = GetSubMenu ( hmenu , 0 ) ; // shortcut menu
// TrackPopup uses screen coordinates, so convert the
// coordinates of the mouse click to screen coordinates.
ClientToScreen ( hwnd , ( LPPOINT ) & pt ) ;
// Check menu depending on current floppy protection
{
int iMenuItem = ID_DISKMENU_WRITEPROTECTION_OFF ;
2019-04-14 16:01:49 +00:00
if ( sg_Disk2Card . GetProtect ( iDrive ) )
2010-01-03 18:43:08 +00:00
iMenuItem = ID_DISKMENU_WRITEPROTECTION_ON ;
CheckMenuItem ( hmenu , iMenuItem , MF_CHECKED ) ;
}
2019-04-14 16:01:49 +00:00
if ( sg_Disk2Card . IsDriveEmpty ( iDrive ) )
2010-01-03 18:43:08 +00:00
EnableMenuItem ( hmenu , ID_DISKMENU_EJECT , MF_GRAYED ) ;
2019-04-14 16:01:49 +00:00
if ( sg_Disk2Card . IsDiskImageWriteProtected ( iDrive ) )
2010-01-03 18:43:08 +00:00
{
// If image-file is read-only (or a gzip) then disable these menu items
EnableMenuItem ( hmenu , ID_DISKMENU_WRITEPROTECTION_ON , MF_GRAYED ) ;
EnableMenuItem ( hmenu , ID_DISKMENU_WRITEPROTECTION_OFF , MF_GRAYED ) ;
}
// Draw and track the shortcut menu.
2006-02-28 18:40:59 +00:00
int iCommand = TrackPopupMenu (
hmenuTrackPopup
, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD
, pt . x , pt . y
, 0
2010-01-03 18:43:08 +00:00
, hwnd , NULL ) ;
2006-02-28 18:40:59 +00:00
if ( iCommand = = ID_DISKMENU_EJECT )
2019-04-14 16:01:49 +00:00
sg_Disk2Card . EjectDisk ( iDrive ) ;
2006-02-28 18:40:59 +00:00
else
if ( iCommand = = ID_DISKMENU_WRITEPROTECTION_ON )
2019-04-14 16:01:49 +00:00
sg_Disk2Card . SetProtect ( iDrive , true ) ;
2006-02-28 18:40:59 +00:00
else
if ( iCommand = = ID_DISKMENU_WRITEPROTECTION_OFF )
2019-04-14 16:01:49 +00:00
sg_Disk2Card . SetProtect ( iDrive , false ) ;
2008-06-20 23:47:25 +00:00
else
if ( iCommand = = ID_DISKMENU_SENDTO_CIDERPRESS )
{
2013-08-08 21:13:31 +00:00
static char szCiderpressNotFoundCaption [ ] = " CiderPress not found " ;
static char szCiderpressNotFoundText [ ] = " CiderPress not found! \n "
" Please install CiderPress. \n "
" Otherwise set the path to CiderPress from Configuration->Disk. " ;
2019-04-14 16:01:49 +00:00
sg_Disk2Card . FlushCurrentTrack ( iDrive ) ;
2017-10-20 05:49:10 +00:00
2008-06-20 23:47:25 +00:00
//if(!filename1.compare("\"\"") == false) //Do not use this, for some reason it does not work!!!
2010-01-03 18:43:08 +00:00
if ( ! filename1 . compare ( sFileNameEmpty ) )
2008-06-20 23:47:25 +00:00
{
2013-12-06 21:10:41 +00:00
int MB_Result = MessageBox ( g_hFrameWindow , " No disk image loaded. Do you want to run CiderPress anyway? " , " No disk image. " , MB_ICONINFORMATION | MB_YESNO ) ;
2010-01-03 18:43:08 +00:00
if ( MB_Result = = IDYES )
2008-06-20 23:47:25 +00:00
{
if ( FileExists ( PathToCiderPress ) )
{
HINSTANCE nResult = ShellExecute ( NULL , " open " , PathToCiderPress , " " , NULL , SW_SHOWNORMAL ) ;
}
2010-01-03 18:43:08 +00:00
else
{
2013-12-06 21:10:41 +00:00
MessageBox ( g_hFrameWindow , szCiderpressNotFoundText , szCiderpressNotFoundCaption , MB_ICONINFORMATION | MB_OK ) ;
2008-06-20 23:47:25 +00:00
}
}
2010-01-03 18:43:08 +00:00
}
2008-06-20 23:47:25 +00:00
else
{
if ( FileExists ( PathToCiderPress ) )
{
2010-01-03 18:43:08 +00:00
HINSTANCE nResult = ShellExecute ( NULL , " open " , PathToCiderPress , filename1 . c_str ( ) , NULL , SW_SHOWNORMAL ) ;
2008-06-20 23:47:25 +00:00
}
else
{
2013-12-06 21:10:41 +00:00
MessageBox ( g_hFrameWindow , szCiderpressNotFoundText , szCiderpressNotFoundCaption , MB_ICONINFORMATION | MB_OK ) ;
2008-06-20 23:47:25 +00:00
}
}
}
2010-01-03 18:43:08 +00:00
// Destroy the menu.
BOOL bRes = DestroyMenu ( hmenu ) ;
_ASSERT ( bRes ) ;
2008-06-20 23:47:25 +00:00
}
2006-02-28 18:40:59 +00:00
2006-02-25 20:50:29 +00:00
//===========================================================================
void RelayEvent ( UINT message , WPARAM wparam , LPARAM lparam ) {
2009-02-16 19:11:33 +00:00
if ( g_bIsFullScreen )
2006-02-25 20:50:29 +00:00
return ;
MSG msg ;
2006-05-14 00:44:38 +00:00
msg . hwnd = g_hFrameWindow ;
2006-02-25 20:50:29 +00:00
msg . message = message ;
msg . wParam = wparam ;
msg . lParam = lparam ;
SendMessage ( tooltipwindow , TTM_RELAYEVENT , 0 , ( LPARAM ) & msg ) ;
}
//===========================================================================
2016-03-21 23:48:02 +00:00
2017-08-12 10:50:31 +00:00
// CtrlReset() vs ResetMachineState():
// . CPU:
2017-12-03 21:05:05 +00:00
// Ctrl+Reset : 6502.sp=-3 / CpuReset()
// Power cycle: 6502.sp=0x1ff / CpuInitialize()
2017-08-12 10:50:31 +00:00
// . Disk][:
// Ctrl+Reset : if motor-on, then motor-off but continue to spin for 1s
// Power cycle: motor-off & immediately stop spinning
2016-03-21 23:48:02 +00:00
// todo: consolidate CtrlReset() and ResetMachineState()
2009-02-17 02:13:18 +00:00
void ResetMachineState ( )
{
2019-04-14 16:01:49 +00:00
sg_Disk2Card . Reset ( true ) ;
2017-12-03 21:05:05 +00:00
HD_Reset ( ) ;
2006-02-25 20:50:29 +00:00
g_bFullSpeed = 0 ; // Might've hit reset in middle of InternalCpuExecute() - so beep may get (partially) muted
2017-08-12 10:50:31 +00:00
MemReset ( ) ; // calls CpuInitialize()
2016-03-21 23:48:02 +00:00
PravetsReset ( ) ;
2019-04-14 16:01:49 +00:00
sg_Disk2Card . Boot ( ) ;
2006-02-25 20:50:29 +00:00
VideoResetState ( ) ;
2019-04-16 20:24:32 +00:00
KeybReset ( ) ;
2007-05-28 11:16:42 +00:00
sg_SSC . CommReset ( ) ;
2007-03-23 22:26:35 +00:00
PrintReset ( ) ;
2006-02-25 20:50:29 +00:00
JoyReset ( ) ;
MB_Reset ( ) ;
SpkrReset ( ) ;
2007-12-01 21:21:40 +00:00
sg_Mouse . Reset ( ) ;
2016-03-21 23:48:02 +00:00
SetActiveCpu ( GetMainCpu ( ) ) ;
2010-02-14 21:11:26 +00:00
# ifdef USE_SPEECH_API
g_Speech . Reset ( ) ;
# endif
2006-02-25 20:50:29 +00:00
SoundCore_SetFade ( FADE_NONE ) ;
2016-09-06 20:38:00 +00:00
LogFileTimeUntilFirstKeyReadReset ( ) ;
2006-02-25 20:50:29 +00:00
}
2009-02-17 02:13:18 +00:00
//===========================================================================
2016-03-21 23:48:02 +00:00
2018-03-20 01:49:08 +00:00
/*
* In comments , UTAII is an abbreviation for a reference to " Understanding the Apple II " by James Sather
*/
2016-03-21 23:48:02 +00:00
// todo: consolidate CtrlReset() and ResetMachineState()
2018-03-20 01:49:08 +00:00
// Ctrl+Reset - TODO: This is a terrible place for this code! Should be in AppleWin.cpp
2009-02-17 02:13:18 +00:00
void CtrlReset ( )
{
2018-03-20 01:49:08 +00:00
if ( ! IS_APPLE2 )
{
// For A][ & A][+, reset doesn't reset the LC switches (UTAII:5-29)
2009-02-17 02:13:18 +00:00
MemResetPaging ( ) ;
2018-03-20 01:49:08 +00:00
// For A][ & A][+, reset doesn't reset the video mode (UTAII:4-4)
VideoResetState ( ) ; // Switch Alternate char set off
}
2016-03-21 23:48:02 +00:00
PravetsReset ( ) ;
2019-04-14 16:01:49 +00:00
sg_Disk2Card . Reset ( ) ;
2017-12-03 21:05:05 +00:00
HD_Reset ( ) ;
2009-02-17 02:13:18 +00:00
KeybReset ( ) ;
2009-02-17 02:25:34 +00:00
sg_SSC . CommReset ( ) ;
2009-02-17 02:13:18 +00:00
MB_Reset ( ) ;
2017-12-03 21:05:05 +00:00
sg_Mouse . Reset ( ) ; // Deassert any pending IRQs - GH#514
2010-02-14 21:11:26 +00:00
# ifdef USE_SPEECH_API
g_Speech . Reset ( ) ;
# endif
2009-02-17 02:13:18 +00:00
CpuReset ( ) ;
g_bFreshReset = true ;
}
2006-02-25 20:50:29 +00:00
//===========================================================================
2014-06-26 21:44:02 +00:00
2016-07-26 21:33:45 +00:00
int GetFullScreenOffsetX ( void )
{
return g_win_fullscreen_offsetx ;
}
int GetFullScreenOffsetY ( void )
{
return g_win_fullscreen_offsety ;
}
2016-07-12 21:43:31 +00:00
2009-02-16 19:11:33 +00:00
void SetFullScreenMode ( )
{
2012-10-05 07:01:27 +00:00
# ifdef NO_DIRECT_X
return ;
# else // NO_DIRECT_X
2016-07-12 21:43:31 +00:00
MONITORINFO monitor_info ;
FULLSCREEN_SCALE_TYPE width , height , scalex , scaley ;
2016-07-25 20:19:00 +00:00
int top , left ;
2016-07-12 21:43:31 +00:00
2009-02-16 19:11:33 +00:00
buttonover = - 1 ;
2016-07-12 21:43:31 +00:00
g_main_window_saved_style = GetWindowLong ( g_hFrameWindow , GWL_STYLE ) ;
g_main_window_saved_exstyle = GetWindowLong ( g_hFrameWindow , GWL_EXSTYLE ) ;
GetWindowRect ( g_hFrameWindow , & g_main_window_saved_rect ) ;
2017-08-26 23:45:51 +00:00
SetWindowLong ( g_hFrameWindow , GWL_STYLE , g_main_window_saved_style & ~ ( WS_CAPTION | WS_THICKFRAME ) ) ;
2016-07-12 21:43:31 +00:00
SetWindowLong ( g_hFrameWindow , GWL_EXSTYLE , g_main_window_saved_exstyle & ~ ( WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE ) ) ;
monitor_info . cbSize = sizeof ( monitor_info ) ;
GetMonitorInfo ( MonitorFromWindow ( g_hFrameWindow , MONITOR_DEFAULTTONEAREST ) , & monitor_info ) ;
2017-08-26 23:45:51 +00:00
2016-07-12 21:43:31 +00:00
left = monitor_info . rcMonitor . left ;
2017-08-26 23:45:51 +00:00
top = monitor_info . rcMonitor . top ;
width = ( FULLSCREEN_SCALE_TYPE ) ( monitor_info . rcMonitor . right - monitor_info . rcMonitor . left ) ;
height = ( FULLSCREEN_SCALE_TYPE ) ( monitor_info . rcMonitor . bottom - monitor_info . rcMonitor . top ) ;
2017-10-11 16:55:10 +00:00
scalex = width / GetFrameBufferBorderlessWidth ( ) ;
scaley = height / GetFrameBufferBorderlessHeight ( ) ;
2017-08-26 23:45:51 +00:00
2016-07-12 21:43:31 +00:00
g_win_fullscreen_scale = ( scalex < = scaley ) ? scalex : scaley ;
2017-10-11 16:55:10 +00:00
g_win_fullscreen_offsetx = ( ( int ) width - ( int ) ( g_win_fullscreen_scale * GetFrameBufferBorderlessWidth ( ) ) ) / 2 ;
g_win_fullscreen_offsety = ( ( int ) height - ( int ) ( g_win_fullscreen_scale * GetFrameBufferBorderlessHeight ( ) ) ) / 2 ;
2016-07-12 21:43:31 +00:00
SetWindowPos ( g_hFrameWindow , NULL , left , top , ( int ) width , ( int ) height , SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED ) ;
g_bIsFullScreen = true ;
2016-07-25 20:19:00 +00:00
SetViewportScale ( g_win_fullscreen_scale , true ) ;
2016-07-12 21:43:31 +00:00
2016-07-26 21:33:45 +00:00
buttonx = GetFullScreenOffsetX ( ) + g_nViewportCX + VIEWPORTX * 2 ;
buttony = GetFullScreenOffsetY ( ) ;
2017-10-11 16:38:36 +00:00
viewportx = VIEWPORTX ; // TC-TODO: Should be zero too? (Since there's no 3D border in full-screen)
viewporty = 0 ; // GH#464
2009-02-21 04:42:35 +00:00
2009-02-16 19:11:33 +00:00
InvalidateRect ( g_hFrameWindow , NULL , 1 ) ;
2012-10-05 07:01:27 +00:00
# endif // NO_DIRECT_X
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2009-02-16 19:11:33 +00:00
void SetNormalMode ( )
{
2017-10-28 20:59:48 +00:00
FullScreenRevealCursor ( ) ; // Do before clearing g_bIsFullScreen flag
2009-02-16 19:11:33 +00:00
buttonover = - 1 ;
buttonx = BUTTONX ;
buttony = BUTTONY ;
viewportx = VIEWPORTX ;
viewporty = VIEWPORTY ;
2009-02-21 04:42:35 +00:00
2016-07-12 21:43:31 +00:00
g_win_fullscreen_offsetx = 0 ;
g_win_fullscreen_offsety = 0 ;
g_win_fullscreen_scale = 1 ;
SetWindowLong ( g_hFrameWindow , GWL_STYLE , g_main_window_saved_style ) ;
SetWindowLong ( g_hFrameWindow , GWL_EXSTYLE , g_main_window_saved_exstyle ) ;
SetWindowPos ( g_hFrameWindow , NULL ,
g_main_window_saved_rect . left ,
g_main_window_saved_rect . top ,
g_main_window_saved_rect . right - g_main_window_saved_rect . left ,
g_main_window_saved_rect . bottom - g_main_window_saved_rect . top ,
SWP_SHOWWINDOW ) ;
g_bIsFullScreen = false ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2008-06-08 12:31:50 +00:00
void SetUsingCursor ( BOOL bNewValue )
{
if ( bNewValue = = g_bUsingCursor )
return ;
g_bUsingCursor = bNewValue ;
2017-10-28 20:59:48 +00:00
2008-06-08 12:31:50 +00:00
if ( g_bUsingCursor )
{
2017-10-28 20:59:48 +00:00
// Set TRUE when:
// . Using mouse for joystick emulation
// . Using mousecard and mouse is restricted to window
2008-06-08 12:31:50 +00:00
SetCapture ( g_hFrameWindow ) ;
RECT rect = { viewportx + 2 , // left
viewporty + 2 , // top
2012-12-29 14:53:52 +00:00
viewportx + g_nViewportCX - 1 , // right
viewporty + g_nViewportCY - 1 } ; // bottom
2008-06-08 12:31:50 +00:00
ClientToScreen ( g_hFrameWindow , ( LPPOINT ) & rect . left ) ;
ClientToScreen ( g_hFrameWindow , ( LPPOINT ) & rect . right ) ;
ClipCursor ( & rect ) ;
FrameShowCursor ( FALSE ) ;
POINT pt ;
GetCursorPos ( & pt ) ;
ScreenToClient ( g_hFrameWindow , & pt ) ;
DrawCrosshairs ( pt . x , pt . y ) ;
}
else
{
DrawCrosshairs ( 0 , 0 ) ;
FrameShowCursor ( TRUE ) ;
ClipCursor ( NULL ) ;
ReleaseCapture ( ) ;
}
2006-02-25 20:50:29 +00:00
}
2012-12-29 14:53:52 +00:00
int GetViewportScale ( void )
{
return g_nViewportScale ;
}
2016-07-25 20:19:00 +00:00
int SetViewportScale ( int nNewScale , bool bForce /*=false*/ )
2012-12-29 14:53:52 +00:00
{
2016-07-25 20:19:00 +00:00
if ( ! bForce & & nNewScale > g_nMaxViewportScale )
2013-03-07 23:23:26 +00:00
nNewScale = g_nMaxViewportScale ;
2012-12-29 14:53:52 +00:00
g_nViewportScale = nNewScale ;
2017-10-11 16:55:10 +00:00
g_nViewportCX = g_nViewportScale * GetFrameBufferBorderlessWidth ( ) ;
g_nViewportCY = g_nViewportScale * GetFrameBufferBorderlessHeight ( ) ;
2013-03-07 23:23:26 +00:00
return nNewScale ;
2012-12-29 14:53:52 +00:00
}
static void SetupTooltipControls ( void )
{
TOOLINFO toolinfo ;
toolinfo . cbSize = sizeof ( toolinfo ) ;
toolinfo . uFlags = TTF_CENTERTIP ;
toolinfo . hwnd = g_hFrameWindow ;
toolinfo . hinst = g_hInstance ;
toolinfo . lpszText = LPSTR_TEXTCALLBACK ;
toolinfo . rect . left = BUTTONX ;
toolinfo . rect . right = toolinfo . rect . left + BUTTONCX + 1 ;
toolinfo . uId = 0 ;
toolinfo . rect . top = BUTTONY + BTN_DRIVE1 * BUTTONCY + 1 ;
toolinfo . rect . bottom = toolinfo . rect . top + BUTTONCY ;
SendMessage ( tooltipwindow , TTM_ADDTOOL , 0 , ( LPARAM ) & toolinfo ) ;
toolinfo . uId = 1 ;
toolinfo . rect . top = BUTTONY + BTN_DRIVE2 * BUTTONCY + 1 ;
toolinfo . rect . bottom = toolinfo . rect . top + BUTTONCY ;
SendMessage ( tooltipwindow , TTM_ADDTOOL , 0 , ( LPARAM ) & toolinfo ) ;
}
2014-08-20 21:40:48 +00:00
// SM_CXPADDEDBORDER is not supported on 2000 & XP, but GetSystemMetrics() returns 0 for unknown values, so this use of SM_CXPADDEDBORDER works on 2000 & XP too:
// http://msdn.microsoft.com/en-nz/library/windows/desktop/ms724385(v=vs.85).aspx
2019-02-14 21:55:38 +00:00
// NB. GetSystemMetrics(SM_CXPADDEDBORDER) returns 0 for Win7, when built with VS2008 (see GH#571)
2013-01-05 22:01:15 +00:00
static void GetWidthHeight ( int & nWidth , int & nHeight )
2006-06-27 02:34:46 +00:00
{
2012-12-29 14:53:52 +00:00
nWidth = g_nViewportCX + VIEWPORTX * 2
2017-10-12 21:11:10 +00:00
+ BUTTONCX
2019-02-14 21:55:38 +00:00
+ ( GetSystemMetrics ( SM_CXFIXEDFRAME ) + GetSystemMetrics ( SM_CXPADDEDBORDER ) ) * 2 ;
2012-12-29 14:53:52 +00:00
nHeight = g_nViewportCY + VIEWPORTY * 2
2017-10-12 21:11:10 +00:00
+ ( GetSystemMetrics ( SM_CYFIXEDFRAME ) + GetSystemMetrics ( SM_CXPADDEDBORDER ) ) * 2 // NB. No SM_CYPADDEDBORDER
+ GetSystemMetrics ( SM_CYCAPTION ) ;
2019-02-14 21:55:38 +00:00
#if 0 // GH#571
LogOutput ( " g_nViewportCX = %d \n " , g_nViewportCX ) ;
LogOutput ( " VIEWPORTX = %d (const) \n " , VIEWPORTX ) ;
LogOutput ( " BUTTONCX = %d (const) \n " , BUTTONCX ) ;
LogOutput ( " GetSystemMetrics(SM_CXFRAME) = %d (unused) \n " , GetSystemMetrics ( SM_CXFRAME ) ) ;
LogOutput ( " GetSystemMetrics(SM_CXFIXEDFRAME) = %d \n " , GetSystemMetrics ( SM_CXFIXEDFRAME ) ) ;
LogOutput ( " GetSystemMetrics(SM_CXBORDER) = %d (unused) \n " , GetSystemMetrics ( SM_CXBORDER ) ) ;
LogOutput ( " GetSystemMetrics(SM_CXPADDEDBORDER) = %d \n " , GetSystemMetrics ( SM_CXPADDEDBORDER ) ) ;
LogOutput ( " nWidth = %d \n " , nWidth ) ;
LogOutput ( " g_nViewportCY = %d \n " , g_nViewportCY ) ;
LogOutput ( " VIEWPORTY = %d (const) \n " , VIEWPORTY ) ;
LogOutput ( " GetSystemMetrics(SM_CYFRAME) = %d (unused) \n " , GetSystemMetrics ( SM_CYFRAME ) ) ;
LogOutput ( " GetSystemMetrics(SM_CYFIXEDFRAME) = %d \n " , GetSystemMetrics ( SM_CYFIXEDFRAME ) ) ;
LogOutput ( " GetSystemMetrics(SM_CYBORDER) = %d (unused) \n " , GetSystemMetrics ( SM_CYBORDER ) ) ;
LogOutput ( " GetSystemMetrics(SM_CYCAPTION) = %d \n " , GetSystemMetrics ( SM_CYCAPTION ) ) ;
LogOutput ( " nHeight = %d \n \n " , nHeight ) ;
# endif
2012-12-29 14:53:52 +00:00
}
2010-01-17 18:43:06 +00:00
2013-01-06 13:47:52 +00:00
static void FrameResizeWindow ( int nNewScale )
2012-12-29 14:53:52 +00:00
{
2013-01-06 13:47:52 +00:00
int nOldWidth , nOldHeight ;
GetWidthHeight ( nOldWidth , nOldHeight ) ;
2013-03-07 23:23:26 +00:00
nNewScale = SetViewportScale ( nNewScale ) ;
2012-12-29 14:53:52 +00:00
GetWindowRect ( g_hFrameWindow , & framerect ) ;
int nXPos = framerect . left ;
int nYPos = framerect . top ;
2010-01-17 18:43:06 +00:00
2012-12-29 14:53:52 +00:00
//
2013-01-05 22:01:15 +00:00
buttonx = g_nViewportCX + VIEWPORTX * 2 ;
2012-12-29 14:53:52 +00:00
buttony = 0 ;
2013-01-05 22:01:15 +00:00
// Invalidate old rect region
{
RECT irect ;
irect . left = irect . top = 0 ;
irect . right = nOldWidth ;
irect . bottom = nOldHeight ;
InvalidateRect ( g_hFrameWindow , & irect , TRUE ) ;
}
// Resize the window
2013-01-06 13:47:52 +00:00
int nNewWidth , nNewHeight ;
GetWidthHeight ( nNewWidth , nNewHeight ) ;
2013-01-09 22:21:12 +00:00
MoveWindow ( g_hFrameWindow , nXPos , nYPos , nNewWidth , nNewHeight , TRUE ) ;
2012-12-29 14:53:52 +00:00
UpdateWindow ( g_hFrameWindow ) ;
2013-01-05 22:01:15 +00:00
// Remove the tooltips for the old window size
2012-12-29 14:53:52 +00:00
TOOLINFO toolinfo = { 0 } ;
toolinfo . cbSize = sizeof ( toolinfo ) ;
toolinfo . hwnd = g_hFrameWindow ;
toolinfo . uId = 0 ;
SendMessage ( tooltipwindow , TTM_DELTOOL , 0 , ( LPARAM ) & toolinfo ) ;
toolinfo . uId = 1 ;
SendMessage ( tooltipwindow , TTM_DELTOOL , 0 , ( LPARAM ) & toolinfo ) ;
2013-01-05 22:01:15 +00:00
// Setup the tooltips for the new window size
2012-12-29 14:53:52 +00:00
SetupTooltipControls ( ) ;
}
2013-01-05 22:01:15 +00:00
//
// ----- ALL GLOBALLY ACCESSIBLE FUNCTIONS ARE BELOW THIS LINE -----
//
//===========================================================================
2012-12-29 14:53:52 +00:00
void FrameCreateWindow ( void )
{
int nWidth , nHeight ;
2013-03-09 13:05:34 +00:00
// Set g_nMaxViewportScale
{
int nOldViewportCX = g_nViewportCX ;
int nOldViewportCY = g_nViewportCY ;
2017-10-11 16:55:10 +00:00
g_nViewportCX = GetFrameBufferBorderlessWidth ( ) * 2 ;
g_nViewportCY = GetFrameBufferBorderlessHeight ( ) * 2 ;
2013-03-09 13:05:34 +00:00
GetWidthHeight ( nWidth , nHeight ) ; // Probe with 2x dimensions
g_nViewportCX = nOldViewportCX ;
g_nViewportCY = nOldViewportCY ;
if ( nWidth > GetSystemMetrics ( SM_CXSCREEN ) | | nHeight > GetSystemMetrics ( SM_CYSCREEN ) )
g_nMaxViewportScale = 1 ;
}
2012-12-29 14:53:52 +00:00
GetWidthHeight ( nWidth , nHeight ) ;
2013-03-07 23:23:26 +00:00
// If screen is too small for 2x, then revert to 1x
if ( g_nViewportScale = = 2 & & ( nWidth > GetSystemMetrics ( SM_CXSCREEN ) | | nHeight > GetSystemMetrics ( SM_CYSCREEN ) ) )
{
g_nMaxViewportScale = 1 ;
SetViewportScale ( 1 ) ;
GetWidthHeight ( nWidth , nHeight ) ;
}
2012-12-29 14:53:52 +00:00
// Restore Window X Position
2010-01-17 18:43:06 +00:00
int nXPos = - 1 ;
{
2013-03-07 23:23:26 +00:00
const int nXScreen = GetSystemMetrics ( SM_CXSCREEN ) - nWidth ;
2010-01-17 18:43:06 +00:00
2012-12-29 14:53:52 +00:00
if ( RegLoadValue ( TEXT ( REG_PREFS ) , TEXT ( REGVALUE_PREF_WINDOW_X_POS ) , 1 , ( DWORD * ) & nXPos ) )
2010-01-17 18:43:06 +00:00
{
2011-02-20 18:59:53 +00:00
if ( ( nXPos > nXScreen ) & & ! g_bMultiMon )
2010-01-17 18:43:06 +00:00
nXPos = - 1 ; // Not fully visible, so default to centre position
}
2011-02-20 18:59:53 +00:00
if ( ( nXPos = = - 1 ) & & ! g_bMultiMon )
2010-01-17 18:43:06 +00:00
nXPos = nXScreen / 2 ;
}
2011-02-20 18:59:53 +00:00
// Restore Window Y Position
2010-01-17 18:43:06 +00:00
int nYPos = - 1 ;
{
2013-03-07 23:23:26 +00:00
const int nYScreen = GetSystemMetrics ( SM_CYSCREEN ) - nHeight ;
2010-01-17 18:43:06 +00:00
2012-12-29 14:53:52 +00:00
if ( RegLoadValue ( TEXT ( REG_PREFS ) , TEXT ( REGVALUE_PREF_WINDOW_Y_POS ) , 1 , ( DWORD * ) & nYPos ) )
2010-01-17 18:43:06 +00:00
{
2011-02-20 18:59:53 +00:00
if ( ( nYPos > nYScreen ) & & ! g_bMultiMon )
2010-01-17 18:43:06 +00:00
nYPos = - 1 ; // Not fully visible, so default to centre position
}
2013-03-07 23:23:26 +00:00
if ( ( nYPos = = - 1 ) & & ! g_bMultiMon )
2010-01-17 18:43:06 +00:00
nYPos = nYScreen / 2 ;
}
//
2012-12-29 14:53:52 +00:00
buttonx = ( g_nViewportCX + VIEWPORTX * 2 ) ;
buttony = 0 ;
2011-02-20 07:32:09 +00:00
GetAppleWindowTitle ( ) ;
2008-06-20 23:47:25 +00:00
2013-03-28 22:28:42 +00:00
// NB. g_hFrameWindow also set by WM_CREATE - NB. CreateWindow() must synchronously send WM_CREATE
2006-06-27 02:34:46 +00:00
g_hFrameWindow = CreateWindow (
TEXT ( " APPLE2FRAME " ) ,
2019-09-07 09:16:51 +00:00
g_pAppTitle . c_str ( ) ,
2006-06-27 02:34:46 +00:00
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
WS_MINIMIZEBOX | WS_VISIBLE ,
2010-01-17 18:43:06 +00:00
nXPos , nYPos , nWidth , nHeight ,
2006-07-02 09:56:50 +00:00
HWND_DESKTOP ,
( HMENU ) 0 ,
2010-01-17 18:43:06 +00:00
g_hInstance , NULL ) ;
2006-06-27 02:34:46 +00:00
InitCommonControls ( ) ;
tooltipwindow = CreateWindow (
TOOLTIPS_CLASS , NULL , TTS_ALWAYSTIP ,
CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT ,
2006-07-02 09:56:50 +00:00
g_hFrameWindow ,
( HMENU ) 0 ,
g_hInstance , NULL ) ;
2006-06-27 02:34:46 +00:00
2012-12-29 14:53:52 +00:00
SetupTooltipControls ( ) ;
2017-10-28 20:59:48 +00:00
_ASSERT ( g_TimerIDEvent_100msec = = 0 ) ;
g_TimerIDEvent_100msec = SetTimer ( g_hFrameWindow , IDEVENT_TIMER_100MSEC , 100 , NULL ) ;
LogFileOutput ( " FrameCreateWindow: SetTimer(), id=0x%08X \n " , g_TimerIDEvent_100msec ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
HDC FrameGetDC ( ) {
2006-07-02 09:56:50 +00:00
if ( ! g_hFrameDC ) {
g_hFrameDC = GetDC ( g_hFrameWindow ) ;
SetViewportOrgEx ( g_hFrameDC , viewportx , viewporty , NULL ) ;
2006-02-25 20:50:29 +00:00
}
2006-07-02 09:56:50 +00:00
return g_hFrameDC ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2017-10-11 18:18:53 +00:00
void FrameReleaseDC ( ) {
if ( g_hFrameDC ) {
SetViewportOrgEx ( g_hFrameDC , 0 , 0 , NULL ) ;
ReleaseDC ( g_hFrameWindow , g_hFrameDC ) ;
g_hFrameDC = ( HDC ) 0 ;
}
2006-02-25 20:50:29 +00:00
}
//===========================================================================
2014-07-29 14:56:55 +00:00
void FrameRefreshStatus ( int drawflags , bool bUpdateDiskStatus ) {
// NB. 99% of the time we draw the disk status. On DiskDriveSwap() we don't.
drawflags | = bUpdateDiskStatus ? DRAW_DISK_STATUS : 0 ;
DrawStatusArea ( ( HDC ) 0 , drawflags ) ;
2006-02-25 20:50:29 +00:00
}
//===========================================================================
void FrameRegisterClass ( ) {
WNDCLASSEX wndclass ;
ZeroMemory ( & wndclass , sizeof ( WNDCLASSEX ) ) ;
wndclass . cbSize = sizeof ( WNDCLASSEX ) ;
wndclass . style = CS_OWNDC | CS_BYTEALIGNCLIENT ;
wndclass . lpfnWndProc = FrameWndProc ;
2006-07-02 09:56:50 +00:00
wndclass . hInstance = g_hInstance ;
wndclass . hIcon = LoadIcon ( g_hInstance , TEXT ( " APPLEWIN_ICON " ) ) ;
2006-02-25 20:50:29 +00:00
wndclass . hCursor = LoadCursor ( 0 , IDC_ARROW ) ;
wndclass . hbrBackground = ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) ;
# if ENABLE_MENU
wndclass . lpszMenuName = ( LPCSTR ) IDR_MENU1 ;
# endif
wndclass . lpszClassName = TEXT ( " APPLE2FRAME " ) ;
2006-07-02 09:56:50 +00:00
wndclass . hIconSm = ( HICON ) LoadImage ( g_hInstance , TEXT ( " APPLEWIN_ICON " ) ,
2006-02-25 20:50:29 +00:00
IMAGE_ICON , 16 , 16 , LR_DEFAULTCOLOR ) ;
RegisterClassEx ( & wndclass ) ;
}
2008-05-17 23:20:33 +00:00
//===========================================================================
2009-02-16 19:11:33 +00:00
// TODO: FIXME: Util_TestFileExists()
2014-08-14 19:29:01 +00:00
static bool FileExists ( std : : string strFilename )
2008-06-20 23:47:25 +00:00
{
struct stat stFileInfo ;
int intStat = stat ( strFilename . c_str ( ) , & stFileInfo ) ;
return ( intStat = = 0 ) ? true : false ;
}
//===========================================================================
2008-05-17 23:20:33 +00:00
// Called when:
// . Mouse f/w sets abs position
// . UpdateMouseInAppleViewport() is called and inside Apple screen
void FrameSetCursorPosByMousePos ( )
{
if ( ! g_hFrameWindow | | g_bShowingCursor )
return ;
int iX , iMinX , iMaxX ;
int iY , iMinY , iMaxY ;
sg_Mouse . GetXY ( iX , iMinX , iMaxX , iY , iMinY , iMaxY ) ;
float fScaleX = ( float ) ( iX - iMinX ) / ( ( float ) ( iMaxX - iMinX ) ) ;
float fScaleY = ( float ) ( iY - iMinY ) / ( ( float ) ( iMaxY - iMinY ) ) ;
2012-12-29 14:53:52 +00:00
int iWindowX = ( int ) ( fScaleX * ( float ) g_nViewportCX ) ;
int iWindowY = ( int ) ( fScaleY * ( float ) g_nViewportCY ) ;
2008-05-17 23:20:33 +00:00
POINT Point = { viewportx + 2 , viewporty + 2 } ; // top-left
ClientToScreen ( g_hFrameWindow , & Point ) ;
2017-10-12 21:11:10 +00:00
SetCursorPos ( Point . x + iWindowX - VIEWPORTX , Point . y + iWindowY - VIEWPORTY ) ;
2008-05-17 23:20:33 +00:00
2017-10-12 21:11:10 +00:00
# if defined(_DEBUG) && 0 // OutputDebugString() when cursor position changes since last time
2008-05-17 23:20:33 +00:00
static int OldX = 0 , OldY = 0 ;
char szDbg [ 200 ] ;
2017-10-12 21:11:10 +00:00
int X = Point . x + iWindowX - VIEWPORTX ;
int Y = Point . y + iWindowY - VIEWPORTY ;
2008-05-17 23:20:33 +00:00
if ( X ! = OldX | | Y ! = OldY )
{
sprintf ( szDbg , " [FrameSetCursorPosByMousePos] x,y=%d,%d (MaxX,Y=%d,%d) \n " , X , Y , iMaxX , iMaxY ) ; OutputDebugString ( szDbg ) ;
OldX = X ; OldY = Y ;
}
# endif
}
2008-06-08 12:31:50 +00:00
// Called when:
// . UpdateMouseInAppleViewport() is called and mouse leaving/entering Apple screen area
// . NB. Not called when leaving & mouse clipped to Apple screen area
2008-05-17 23:20:33 +00:00
static void FrameSetCursorPosByMousePos ( int x , int y , int dx , int dy , bool bLeavingAppleScreen )
{
// char szDbg[200];
if ( ! g_hFrameWindow | | ( g_bShowingCursor & & bLeavingAppleScreen ) | | ( ! g_bShowingCursor & & ! bLeavingAppleScreen ) )
return ;
int iX , iMinX , iMaxX ;
int iY , iMinY , iMaxY ;
sg_Mouse . GetXY ( iX , iMinX , iMaxX , iY , iMinY , iMaxY ) ;
if ( bLeavingAppleScreen )
{
// Set mouse x/y pos to edge of mouse's window
if ( dx < 0 ) iX = iMinX ;
if ( dx > 0 ) iX = iMaxX ;
if ( dy < 0 ) iY = iMinY ;
if ( dy > 0 ) iY = iMaxY ;
float fScaleX = ( float ) ( iX - iMinX ) / ( ( float ) ( iMaxX - iMinX ) ) ;
float fScaleY = ( float ) ( iY - iMinY ) / ( ( float ) ( iMaxY - iMinY ) ) ;
2012-12-29 14:53:52 +00:00
int iWindowX = ( int ) ( fScaleX * ( float ) g_nViewportCX ) + dx ;
int iWindowY = ( int ) ( fScaleY * ( float ) g_nViewportCY ) + dy ;
2008-05-17 23:20:33 +00:00
POINT Point = { viewportx + 2 , viewporty + 2 } ; // top-left
ClientToScreen ( g_hFrameWindow , & Point ) ;
2017-10-12 21:11:10 +00:00
SetCursorPos ( Point . x + iWindowX - VIEWPORTX , Point . y + iWindowY - VIEWPORTY ) ;
2008-05-17 23:20:33 +00:00
// sprintf(szDbg, "[MOUSE_LEAVING ] x=%d, y=%d (Scale: x,y=%f,%f; iX,iY=%d,%d)\n", iWindowX, iWindowY, fScaleX, fScaleY, iX, iY); OutputDebugString(szDbg);
}
else // Mouse entering Apple screen area
{
// sprintf(szDbg, "[MOUSE_ENTERING] x=%d, y=%d\n", x, y); OutputDebugString(szDbg);
2017-10-10 21:11:36 +00:00
if ( ! g_bIsFullScreen ) // GH#464
{
2017-10-12 21:11:10 +00:00
x - = ( viewportx + 2 - VIEWPORTX ) ; if ( x < 0 ) x = 0 ;
y - = ( viewporty + 2 - VIEWPORTY ) ; if ( y < 0 ) y = 0 ;
2017-10-10 21:11:36 +00:00
}
2008-05-17 23:20:33 +00:00
2012-12-29 14:53:52 +00:00
_ASSERT ( x < = g_nViewportCX ) ;
_ASSERT ( y < = g_nViewportCY ) ;
float fScaleX = ( float ) x / ( float ) g_nViewportCX ;
float fScaleY = ( float ) y / ( float ) g_nViewportCY ;
2008-05-17 23:20:33 +00:00
int iAppleX = iMinX + ( int ) ( fScaleX * ( float ) ( iMaxX - iMinX ) ) ;
int iAppleY = iMinY + ( int ) ( fScaleY * ( float ) ( iMaxY - iMinY ) ) ;
sg_Mouse . SetCursorPos ( iAppleX , iAppleY ) ; // Set new entry position
// Dump initial deltas (otherwise can get big deltas since last read when entering Apple screen area)
DIMouse : : ReadImmediateData ( ) ;
}
}
static void DrawCrosshairsMouse ( )
{
2012-03-27 21:20:36 +00:00
if ( ! sg_PropertySheet . GetMouseShowCrosshair ( ) )
2008-05-17 23:20:33 +00:00
return ;
int iX , iMinX , iMaxX ;
int iY , iMinY , iMaxY ;
sg_Mouse . GetXY ( iX , iMinX , iMaxX , iY , iMinY , iMaxY ) ;
_ASSERT ( iMinX = = 0 & & iMinY = = 0 ) ;
float fScaleX = ( float ) ( iX - iMinX ) / ( ( float ) ( iMaxX - iMinX ) ) ;
float fScaleY = ( float ) ( iY - iMinY ) / ( ( float ) ( iMaxY - iMinY ) ) ;
2012-12-29 14:53:52 +00:00
int iWindowX = ( int ) ( fScaleX * ( float ) g_nViewportCX ) ;
int iWindowY = ( int ) ( fScaleY * ( float ) g_nViewportCY ) ;
2008-05-17 23:20:33 +00:00
DrawCrosshairs ( iWindowX , iWindowY ) ;
}
# ifdef _DEBUG
//#define _DEBUG_SHOW_CURSOR // NB. Get an ASSERT on LMB (after Ctrl+LMB)
# endif
static void UpdateMouseInAppleViewport ( int iOutOfBoundsX , int iOutOfBoundsY , int x , int y )
{
const bool bOutsideAppleViewport = iOutOfBoundsX | | iOutOfBoundsY ;
if ( bOutsideAppleViewport )
{
2012-03-27 21:20:36 +00:00
if ( sg_PropertySheet . GetMouseRestrictToWindow ( ) )
2008-05-18 18:23:25 +00:00
return ;
2008-05-17 23:20:33 +00:00
g_bLastCursorInAppleViewport = false ;
if ( ! g_bShowingCursor )
{
// Mouse leaving Apple screen area
FrameSetCursorPosByMousePos ( 0 , 0 , iOutOfBoundsX , iOutOfBoundsY , true ) ;
# ifdef _DEBUG_SHOW_CURSOR
2008-05-18 18:23:25 +00:00
g_bShowingCursor = true ;
2008-05-17 23:20:33 +00:00
# else
2008-05-18 18:23:25 +00:00
FrameShowCursor ( TRUE ) ;
2008-05-17 23:20:33 +00:00
# endif
}
}
else
{
g_bLastCursorInAppleViewport = true ;
if ( g_bShowingCursor )
{
// Mouse entering Apple screen area
FrameSetCursorPosByMousePos ( x , y , 0 , 0 , false ) ;
# ifdef _DEBUG_SHOW_CURSOR
2008-05-18 18:23:25 +00:00
g_bShowingCursor = false ;
2008-05-17 23:20:33 +00:00
# else
2008-05-18 18:23:25 +00:00
FrameShowCursor ( FALSE ) ;
2008-05-17 23:20:33 +00:00
# endif
2008-05-18 18:23:25 +00:00
//
2012-03-27 21:20:36 +00:00
if ( sg_PropertySheet . GetMouseRestrictToWindow ( ) )
2008-06-08 12:31:50 +00:00
SetUsingCursor ( TRUE ) ;
2008-05-17 23:20:33 +00:00
}
else
{
FrameSetCursorPosByMousePos ( ) ; // Set cursor to Apple position each time
}
DrawCrosshairsMouse ( ) ;
}
}
2012-12-29 14:53:52 +00:00
void GetViewportCXCY ( int & nViewportCX , int & nViewportCY )
{
nViewportCX = g_nViewportCX ;
nViewportCY = g_nViewportCY ;
}
2016-03-21 23:48:02 +00:00
// Call all funcs with dependency on g_Apple2Type
void FrameUpdateApple2Type ( void )
{
DeleteGdiObjects ( ) ;
CreateGdiObjects ( ) ;
// DRAW_TITLE : calls GetAppleWindowTitle()
// DRAW_LEDS : update LEDs (eg. CapsLock varies on Apple2 type)
DrawStatusArea ( ( HDC ) 0 , DRAW_TITLE | DRAW_LEDS ) ;
// Draw buttons & call DrawStatusArea(DRAW_BACKGROUND | DRAW_LEDS | DRAW_DISK_STATUS)
DrawFrameWindow ( ) ;
}
2017-09-29 19:33:30 +00:00
bool GetBestDisplayResolutionForFullScreen ( UINT & bestWidth , UINT & bestHeight , UINT userSpecifiedHeight /*= 0*/ )
{
typedef std : : vector < std : : pair < UINT , UINT > > VEC_PAIR ;
VEC_PAIR vecDisplayResolutions ;
for ( UINT iModeNum = 0 ; ; iModeNum + + )
{
DEVMODE devMode ;
devMode . dmSize = sizeof ( DEVMODE ) ;
devMode . dmDriverExtra = 0 ;
BOOL bValid = EnumDisplaySettings ( NULL , iModeNum , & devMode ) ;
if ( ! bValid )
break ;
if ( iModeNum = = 0 ) // 0 is the initial "cache info about display device" operation
continue ;
if ( devMode . dmBitsPerPel ! = 32 )
continue ;
if ( userSpecifiedHeight = = 0 | | userSpecifiedHeight = = devMode . dmPelsHeight )
{
if ( vecDisplayResolutions . size ( ) = = 0 | | vecDisplayResolutions . back ( ) ! = std : : pair < UINT , UINT > ( devMode . dmPelsWidth , devMode . dmPelsHeight ) ) // Skip duplicate resolutions
{
vecDisplayResolutions . push_back ( std : : pair < UINT , UINT > ( devMode . dmPelsWidth , devMode . dmPelsHeight ) ) ;
LogFileOutput ( " EnumDisplaySettings(%d) - %d x %d \n " , iModeNum , devMode . dmPelsWidth , devMode . dmPelsHeight ) ;
}
}
}
if ( userSpecifiedHeight )
{
if ( vecDisplayResolutions . size ( ) = = 0 )
return false ;
// Pick least width (such that it's wide enough to scale)
UINT width = ( UINT ) - 1 ;
for ( VEC_PAIR : : iterator it = vecDisplayResolutions . begin ( ) ; it ! = vecDisplayResolutions . end ( ) ; + + it )
{
if ( width > it - > first )
{
2017-10-11 16:55:10 +00:00
UINT scaleFactor = it - > second / GetFrameBufferBorderlessHeight ( ) ;
if ( it - > first > = ( GetFrameBufferBorderlessWidth ( ) * scaleFactor ) )
2017-09-29 19:33:30 +00:00
{
width = it - > first ;
}
}
}
if ( width = = ( UINT ) - 1 )
return false ;
bestWidth = width ;
bestHeight = userSpecifiedHeight ;
return true ;
}
2017-10-11 16:55:10 +00:00
// Pick max height that's an exact multiple of GetFrameBufferBorderlessHeight()
2017-09-29 19:33:30 +00:00
UINT tmpBestWidth = 0 ;
UINT tmpBestHeight = 0 ;
for ( VEC_PAIR : : iterator it = vecDisplayResolutions . begin ( ) ; it ! = vecDisplayResolutions . end ( ) ; + + it )
{
2017-10-11 16:55:10 +00:00
if ( ( it - > second % GetFrameBufferBorderlessHeight ( ) ) = = 0 )
2017-09-29 19:33:30 +00:00
{
if ( it - > second > tmpBestHeight )
{
2017-10-11 16:55:10 +00:00
UINT scaleFactor = it - > second / GetFrameBufferBorderlessHeight ( ) ;
if ( it - > first > = ( GetFrameBufferBorderlessWidth ( ) * scaleFactor ) )
2017-09-29 19:33:30 +00:00
{
tmpBestWidth = it - > first ;
tmpBestHeight = it - > second ;
}
}
}
}
if ( tmpBestWidth = = 0 )
return false ;
bestWidth = tmpBestWidth ;
bestHeight = tmpBestHeight ;
return true ;
}