mirror of
https://github.com/InvisibleUp/uvmac.git
synced 2024-06-11 05:29:26 +00:00
be71368cf7
Non-windows systems are probably broken right now. Color display in general is probably broken. But, soon, you will be able to change the screen size and color depth without recompiling. That would be nice.
6064 lines
124 KiB
C
6064 lines
124 KiB
C
/*
|
|
OSGLUWIN.c
|
|
|
|
Copyright (C) 2009 Philip Cummins, Weston Pawlowski,
|
|
Bradford L. Barrett, Paul C. Pratt, Fabio Concas
|
|
|
|
You can redistribute this file and/or modify it under the terms
|
|
of version 2 of the GNU General Public License as published by
|
|
the Free Software Foundation. You should have received a copy
|
|
of the license along with this file; see the file COPYING.
|
|
|
|
This file 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
|
|
license for more details.
|
|
*/
|
|
|
|
/*
|
|
Operating System GLUe for microsoft WINdows
|
|
|
|
All operating system dependent code for the
|
|
Microsoft Windows platform should go here.
|
|
|
|
This code is descended from Weston Pawlowski's Windows
|
|
port of vMac, by Philip Cummins.
|
|
Adapted by Fabio Concas to run on Pocket PC 2003 devices.
|
|
|
|
The main entry point '_tWinMain' is at the end of this file.
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include <time.h>
|
|
#include <shlobj.h>
|
|
#include <tchar.h>
|
|
|
|
#include "CNFGRAPI.h"
|
|
#include "SYSDEPNS.h"
|
|
#include "UTIL/ENDIANAC.h"
|
|
|
|
#include "UI/MYOSGLUE.h"
|
|
|
|
|
|
/* --- adapting to API/ABI version differences --- */
|
|
|
|
#ifdef UNICODE
|
|
#define UseUni 1
|
|
#else
|
|
#define UseUni 0
|
|
#endif
|
|
|
|
#ifdef _WIN32_WCE
|
|
#define UseWinCE 1
|
|
#else
|
|
#define UseWinCE 0
|
|
#endif
|
|
|
|
|
|
#define _CSIDL_APPDATA 0x001a
|
|
|
|
typedef BOOL (WINAPI *SHGetSpecialFolderPathProcPtr) (
|
|
HWND hwndOwner,
|
|
LPTSTR lpszPath,
|
|
int nFolder,
|
|
BOOL fCreate
|
|
);
|
|
LOCALVAR SHGetSpecialFolderPathProcPtr MySHGetSpecialFolderPath = NULL;
|
|
LOCALVAR bool DidSHGetSpecialFolderPath = false;
|
|
|
|
LOCALFUNC bool HaveMySHGetSpecialFolderPath(void)
|
|
{
|
|
if (! DidSHGetSpecialFolderPath) {
|
|
HMODULE hLibModule = LoadLibrary(TEXT("shell32.dll"));
|
|
if (NULL != hLibModule) {
|
|
MySHGetSpecialFolderPath =
|
|
(SHGetSpecialFolderPathProcPtr)
|
|
GetProcAddress(hLibModule,
|
|
#if UseUni
|
|
TEXT("SHGetSpecialFolderPathW")
|
|
#else
|
|
TEXT("SHGetSpecialFolderPathA")
|
|
#endif
|
|
);
|
|
/* FreeLibrary(hLibModule); */
|
|
}
|
|
DidSHGetSpecialFolderPath = true;
|
|
}
|
|
return (MySHGetSpecialFolderPath != NULL);
|
|
}
|
|
|
|
|
|
/* --- end of adapting to API/ABI version differences --- */
|
|
|
|
#include "STRCONST.h"
|
|
|
|
#if UseUni
|
|
#define NeedCell2UnicodeMap 1
|
|
#else
|
|
#define NeedCell2WinAsciiMap 1
|
|
#endif
|
|
|
|
#include "LANG/INTLCHAR.h"
|
|
|
|
|
|
LOCALPROC NativeStrFromCStr(LPTSTR r, char *s, bool AddEllipsis)
|
|
{
|
|
uint8_t ps[ClStrMaxLength];
|
|
int i;
|
|
int L;
|
|
|
|
ClStrFromSubstCStr(&L, ps, s);
|
|
|
|
for (i = 0; i < L; ++i) {
|
|
r[i] = (TCHAR)
|
|
#if UseUni
|
|
Cell2UnicodeMap[ps[i]];
|
|
#else
|
|
Cell2WinAsciiMap[ps[i]];
|
|
#endif
|
|
}
|
|
|
|
if (AddEllipsis) {
|
|
#if UseUni
|
|
r[L] = 0x2026;
|
|
++L;
|
|
#else
|
|
r[L] = '.';
|
|
++L;
|
|
r[L] = '.';
|
|
++L;
|
|
r[L] = '.';
|
|
++L;
|
|
#endif
|
|
}
|
|
|
|
r[L] = 0;
|
|
}
|
|
|
|
LOCALFUNC LPTSTR FindLastTerm(LPTSTR s, TCHAR delim)
|
|
{
|
|
TCHAR c;
|
|
LPTSTR p0 = s;
|
|
LPTSTR p = (LPTSTR)nullpr;
|
|
|
|
while ((c = *p0++) != (TCHAR)('\0')) {
|
|
if (c == delim) {
|
|
p = p0;
|
|
}
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
LOCALVAR HINSTANCE AppInstance;
|
|
|
|
LOCALFUNC bool GetAppDir(LPTSTR pathName)
|
|
/* be sure at least _MAX_PATH long! */
|
|
{
|
|
if (GetModuleFileName(AppInstance, pathName, _MAX_PATH) == 0) {
|
|
/* MacMsg("error", "GetModuleFileName failed", false); */
|
|
} else {
|
|
LPTSTR p = FindLastTerm(pathName,
|
|
(TCHAR)('\\'));
|
|
if (p == nullpr) {
|
|
/* MacMsg("error", "strrchr failed", false); */
|
|
} else {
|
|
*--p = (TCHAR)('\0');
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* --- sending debugging info to file --- */
|
|
|
|
#if dbglog_HAVE
|
|
|
|
LOCALVAR HANDLE dbglog_File = INVALID_HANDLE_VALUE;
|
|
|
|
LOCALFUNC bool dbglog_open0(void)
|
|
{
|
|
TCHAR pathName[_MAX_PATH];
|
|
TCHAR Child0[] = TEXT("\\dbglog.txt");
|
|
size_t newlen;
|
|
|
|
if (GetAppDir(pathName)) {
|
|
newlen = _tcslen(pathName) + _tcslen(Child0);
|
|
if (newlen + 1 < _MAX_PATH) {
|
|
_tcscat(pathName, Child0);
|
|
|
|
dbglog_File = CreateFile(
|
|
pathName, /* pointer to name of the file */
|
|
GENERIC_READ + GENERIC_WRITE,
|
|
/* access (read-write) mode */
|
|
0, /* share mode */
|
|
NULL, /* pointer to security descriptor */
|
|
OPEN_ALWAYS, /* how to create */
|
|
FILE_ATTRIBUTE_NORMAL, /* file attributes */
|
|
NULL /* handle to file with attributes to copy */
|
|
);
|
|
if (INVALID_HANDLE_VALUE == dbglog_File) {
|
|
/* report error (how?) */
|
|
} else if (SetFilePointer(
|
|
dbglog_File, /* handle of file */
|
|
0, /* number of bytes to move file pointer */
|
|
nullpr,
|
|
/* address of high-order word of distance to move */
|
|
FILE_BEGIN /* how to move */
|
|
) != 0)
|
|
{
|
|
/* report error (how?) */
|
|
}
|
|
}
|
|
}
|
|
|
|
return (INVALID_HANDLE_VALUE != dbglog_File);
|
|
}
|
|
|
|
LOCALPROC dbglog_write0(char *s, uimr L)
|
|
{
|
|
DWORD BytesWritten;
|
|
|
|
if (INVALID_HANDLE_VALUE != dbglog_File) {
|
|
if (! WriteFile(dbglog_File, /* handle of file to read */
|
|
(LPVOID)s, /* address of buffer that receives data */
|
|
(DWORD)L, /* number of bytes to read */
|
|
&BytesWritten, /* address of number of bytes read */
|
|
nullpr) /* address of structure for data */
|
|
|| ((uint32_t)BytesWritten != L))
|
|
{
|
|
/* report error (how?) */
|
|
}
|
|
}
|
|
}
|
|
|
|
LOCALPROC dbglog_close0(void)
|
|
{
|
|
if (INVALID_HANDLE_VALUE != dbglog_File) {
|
|
if (! SetEndOfFile(dbglog_File)) {
|
|
/* report error (how?) */
|
|
}
|
|
(void) CloseHandle(dbglog_File);
|
|
dbglog_File = INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#include "UI/COMOSGLU.h"
|
|
|
|
#ifndef InstallFileIcons
|
|
#define InstallFileIcons 0
|
|
#endif
|
|
|
|
/* Resource Ids */
|
|
|
|
#define IDI_VMAC 256
|
|
#if InstallFileIcons
|
|
#define IDI_ROM 257
|
|
#define IDI_DISK 258
|
|
#endif
|
|
|
|
/* --- some simple utilities --- */
|
|
|
|
#define TestBit(i, p) (((unsigned long)(i) & PowOf2(p)) != 0)
|
|
|
|
GLOBALOSGLUPROC MoveBytes(anyp srcPtr, anyp destPtr, int32_t byteCount)
|
|
{
|
|
/*
|
|
must work even if blocks overlap in memory
|
|
*/
|
|
(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
|
|
}
|
|
|
|
/* --- Parameter buffers --- */
|
|
|
|
#if IncludePbufs
|
|
LOCALVAR HGLOBAL PbufDat[NumPbufs];
|
|
#endif
|
|
|
|
#if IncludePbufs
|
|
LOCALFUNC tMacErr PbufNewFromHandle(HGLOBAL h, uint32_t count, tPbuf *r)
|
|
{
|
|
tPbuf i;
|
|
tMacErr err;
|
|
|
|
if (! FirstFreePbuf(&i)) {
|
|
(void) GlobalFree(h);
|
|
err = mnvm_miscErr;
|
|
} else {
|
|
*r = i;
|
|
PbufDat[i] = h;
|
|
PbufNewNotify(i, count);
|
|
err = mnvm_noErr;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
#if IncludePbufs
|
|
GLOBALOSGLUFUNC tMacErr PbufNew(uint32_t count, tPbuf *r)
|
|
{
|
|
HGLOBAL h;
|
|
tMacErr err = mnvm_miscErr;
|
|
|
|
h = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, count);
|
|
if (h != NULL) {
|
|
/* need to clear h */
|
|
err = PbufNewFromHandle(h, count, r);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
#if IncludePbufs
|
|
GLOBALOSGLUPROC PbufDispose(tPbuf i)
|
|
{
|
|
(void) GlobalFree(PbufDat[i]);
|
|
PbufDisposeNotify(i);
|
|
}
|
|
#endif
|
|
|
|
#if IncludePbufs
|
|
LOCALPROC UnInitPbufs(void)
|
|
{
|
|
tPbuf i;
|
|
|
|
for (i = 0; i < NumPbufs; ++i) {
|
|
if (PbufIsAllocated(i)) {
|
|
PbufDispose(i);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if IncludePbufs
|
|
#define PbufHaveLock 1
|
|
#endif
|
|
|
|
#if IncludePbufs
|
|
LOCALFUNC uint8_t * PbufLock(tPbuf i)
|
|
{
|
|
HGLOBAL h = PbufDat[i];
|
|
return (uint8_t *)GlobalLock(h);
|
|
}
|
|
#endif
|
|
|
|
#if IncludePbufs
|
|
LOCALPROC PbufUnlock(tPbuf i)
|
|
{
|
|
(void) GlobalUnlock(PbufDat[i]);
|
|
}
|
|
#endif
|
|
|
|
#if IncludePbufs
|
|
GLOBALOSGLUPROC PbufTransfer(uint8_t * Buffer,
|
|
tPbuf i, uint32_t offset, uint32_t count, bool IsWrite)
|
|
{
|
|
HGLOBAL h = PbufDat[i];
|
|
uint8_t * p0 = GlobalLock(h);
|
|
if (p0 != NULL) {
|
|
void *p = p0 + offset;
|
|
if (IsWrite) {
|
|
(void) memcpy(p, Buffer, count);
|
|
} else {
|
|
(void) memcpy(Buffer, p, count);
|
|
}
|
|
}
|
|
(void) GlobalUnlock(h);
|
|
}
|
|
#endif
|
|
|
|
/* --- control mode and internationalization --- */
|
|
|
|
#include "UI/CONTROLM.h"
|
|
|
|
/* --- main window info --- */
|
|
|
|
LOCALVAR HWND MainWnd = NULL;
|
|
|
|
LOCALVAR int WndX;
|
|
LOCALVAR int WndY;
|
|
|
|
#if UseWinCE
|
|
LOCALVAR short oldOrientation;
|
|
LOCALVAR unsigned long oldDisplayOrientation;
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
LOCALVAR bool UseFullScreen = (WantInitFullScreen != 0);
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
LOCALVAR bool UseMagnify = (WantInitMagnify != 0);
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
LOCALVAR short hOffset;
|
|
LOCALVAR short vOffset;
|
|
#endif
|
|
|
|
/* cursor hiding */
|
|
|
|
LOCALVAR bool HaveCursorHidden = false;
|
|
LOCALVAR bool WantCursorHidden = false;
|
|
|
|
LOCALPROC ForceShowCursor(void)
|
|
{
|
|
if (HaveCursorHidden) {
|
|
HaveCursorHidden = false;
|
|
(void) ShowCursor(TRUE);
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
}
|
|
}
|
|
|
|
/* cursor moving */
|
|
|
|
LOCALFUNC bool MoveMouse(int16_t h, int16_t v)
|
|
{
|
|
POINT NewMousePos;
|
|
uint32_t difftime;
|
|
bool IsOk;
|
|
DWORD StartTime = GetTickCount();
|
|
LONG x = h;
|
|
LONG y = v;
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
x -= ViewHStart;
|
|
y -= ViewVStart;
|
|
}
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
x *= WindowScale;
|
|
y *= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
x += hOffset;
|
|
y += vOffset;
|
|
}
|
|
#endif
|
|
|
|
x += WndX;
|
|
y += WndY;
|
|
|
|
do {
|
|
(void) SetCursorPos(x, y);
|
|
if (! GetCursorPos(&NewMousePos)) {
|
|
IsOk = false;
|
|
} else {
|
|
IsOk = (x == NewMousePos.x) && (y == NewMousePos.y);
|
|
}
|
|
difftime = (uint32_t)(GetTickCount() - StartTime);
|
|
} while ((! IsOk) && (difftime < 100));
|
|
return IsOk;
|
|
}
|
|
|
|
#if EnableFSMouseMotion
|
|
LOCALPROC StartSaveMouseMotion(void)
|
|
{
|
|
if (! HaveMouseMotion) {
|
|
if (MoveMouse(ViewHStart + (ViewHSize / 2),
|
|
ViewVStart + (ViewVSize / 2)))
|
|
{
|
|
SavedMouseH = ViewHStart + (ViewHSize / 2);
|
|
SavedMouseV = ViewVStart + (ViewVSize / 2);
|
|
HaveMouseMotion = true;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if EnableFSMouseMotion
|
|
LOCALPROC StopSaveMouseMotion(void)
|
|
{
|
|
if (HaveMouseMotion) {
|
|
(void) MoveMouse(CurMouseH, CurMouseV);
|
|
HaveMouseMotion = false;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
LOCALVAR bool MouseCaptured = false;
|
|
|
|
LOCALPROC MouseCaptureSet(bool v)
|
|
{
|
|
if (v != MouseCaptured) {
|
|
if (v) {
|
|
(void) SetCapture(MainWnd);
|
|
} else {
|
|
(void) ReleaseCapture();
|
|
}
|
|
MouseCaptured = v;
|
|
}
|
|
}
|
|
|
|
LOCALPROC SetCurMouseButton(bool v)
|
|
{
|
|
MouseButtonSet(v);
|
|
MouseCaptureSet(v);
|
|
}
|
|
|
|
/* keyboard */
|
|
|
|
/* these constants weren't in the header files I have */
|
|
#define myVK_Subtract 0xBD
|
|
#define myVK_Equal 0xBB
|
|
#define myVK_BackSlash 0xDC
|
|
#define myVK_Comma 0xBC
|
|
#define myVK_Period 0xBE
|
|
#define myVK_Slash 0xBF
|
|
#define myVK_SemiColon 0xBA
|
|
#define myVK_SingleQuote 0xDE
|
|
#define myVK_LeftBracket 0xDB
|
|
#define myVK_RightBracket 0xDD
|
|
#define myVK_Grave 0xC0
|
|
|
|
/* some new ones, need to check if in all header versions */
|
|
#define myVK_PRIOR 0x21
|
|
#define myVK_NEXT 0x22
|
|
#define myVK_END 0x23
|
|
#define myVK_HOME 0x24
|
|
#define myVK_INSERT 0x2D
|
|
#define myVK_DELETE 0x2E
|
|
#define myVK_HELP 0x2F
|
|
#define myVK_SCROLL 0x91
|
|
#define myVK_SNAPSHOT 0x2C
|
|
#define myVK_PAUSE 0x13
|
|
#define myVK_CLEAR 0x0C
|
|
|
|
#define myVK_OEM_8 0xDF
|
|
#define myVK_OEM_102 0xE2
|
|
|
|
#ifndef ItnlKyBdFix
|
|
#define ItnlKyBdFix 0
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALVAR uint8_t VkMapA[256];
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkSwapZY(void)
|
|
{
|
|
VkMapA['Z'] = 'Y';
|
|
VkMapA['Y'] = 'Z';
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkSwapGraveQuote(void)
|
|
{
|
|
VkMapA[myVK_Grave] = myVK_SingleQuote;
|
|
VkMapA[myVK_SingleQuote] = myVK_Grave;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkSwapSlashSubtract(void)
|
|
{
|
|
VkMapA[myVK_Slash] = myVK_Subtract;
|
|
VkMapA[myVK_Subtract] = myVK_Slash;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkSwapAQZWGraveQuote(void)
|
|
{
|
|
VkSwapGraveQuote();
|
|
VkMapA['A'] = 'Q';
|
|
VkMapA['Q'] = 'A';
|
|
VkMapA['Z'] = 'W';
|
|
VkMapA['W'] = 'Z';
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapBelgian(void)
|
|
{
|
|
VkSwapAQZWGraveQuote();
|
|
VkMapA['M'] = myVK_SemiColon;
|
|
VkMapA[myVK_SemiColon] = myVK_RightBracket;
|
|
VkMapA[myVK_RightBracket] = myVK_LeftBracket;
|
|
VkMapA[myVK_LeftBracket] = myVK_Subtract;
|
|
VkMapA[myVK_Subtract] = myVK_Equal;
|
|
VkMapA[myVK_Equal] = myVK_Slash;
|
|
VkMapA[myVK_Slash] = myVK_Period;
|
|
VkMapA[myVK_Period] = myVK_Comma;
|
|
VkMapA[myVK_Comma] = 'M';
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapSwiss(void)
|
|
{
|
|
VkSwapZY();
|
|
VkMapA[myVK_OEM_8] = myVK_BackSlash;
|
|
VkMapA[myVK_BackSlash] = myVK_SingleQuote;
|
|
VkMapA[myVK_SingleQuote] = myVK_SemiColon;
|
|
VkMapA[myVK_SemiColon] = myVK_LeftBracket;
|
|
VkMapA[myVK_LeftBracket] = myVK_Subtract;
|
|
VkMapA[myVK_Subtract] = myVK_Slash;
|
|
VkMapA[myVK_Slash] = myVK_Grave;
|
|
VkMapA[myVK_Grave] = myVK_RightBracket;
|
|
VkMapA[myVK_RightBracket] = myVK_Equal;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapDanish(void)
|
|
{
|
|
VkMapA[myVK_Equal] = myVK_Subtract;
|
|
VkMapA[myVK_Subtract] = myVK_Slash;
|
|
VkMapA[myVK_Slash] = myVK_BackSlash;
|
|
VkMapA[myVK_BackSlash] = myVK_Grave;
|
|
VkMapA[myVK_Grave] = myVK_SemiColon;
|
|
VkMapA[myVK_SemiColon] = myVK_RightBracket;
|
|
VkMapA[myVK_RightBracket] = myVK_LeftBracket;
|
|
VkMapA[myVK_LeftBracket] = myVK_Equal;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapBritish(void)
|
|
{
|
|
VkMapA[myVK_OEM_8] = myVK_Grave;
|
|
VkMapA[myVK_Grave] = myVK_SingleQuote;
|
|
VkMapA[myVK_SingleQuote] = myVK_BackSlash;
|
|
VkMapA[myVK_BackSlash] = myVK_OEM_102;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapSpanish(void)
|
|
{
|
|
VkMapA[myVK_SemiColon] = myVK_LeftBracket;
|
|
VkMapA[myVK_LeftBracket] = myVK_Subtract;
|
|
VkMapA[myVK_Subtract] = myVK_Slash;
|
|
VkMapA[myVK_Slash] = myVK_BackSlash;
|
|
VkMapA[myVK_BackSlash] = myVK_Grave;
|
|
VkMapA[myVK_Grave] = myVK_SemiColon;
|
|
|
|
VkMapA[myVK_RightBracket] = myVK_Equal;
|
|
VkMapA[myVK_Equal] = myVK_RightBracket;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapDutch(void)
|
|
{
|
|
VkSwapGraveQuote();
|
|
VkMapA[myVK_SemiColon] = myVK_RightBracket;
|
|
VkMapA[myVK_RightBracket] = myVK_LeftBracket;
|
|
VkMapA[myVK_LeftBracket] = myVK_Subtract;
|
|
VkMapA[myVK_Subtract] = myVK_Slash;
|
|
VkMapA[myVK_Slash] = myVK_Equal;
|
|
VkMapA[myVK_Equal] = myVK_SemiColon;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapGreekIBM(void)
|
|
{
|
|
VkSwapSlashSubtract();
|
|
VkMapA[myVK_LeftBracket] = myVK_Equal;
|
|
VkMapA[myVK_Equal] = myVK_LeftBracket;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapFrench(void)
|
|
{
|
|
VkSwapAQZWGraveQuote();
|
|
VkMapA['M'] = myVK_SemiColon;
|
|
VkMapA[myVK_SemiColon] = myVK_RightBracket;
|
|
VkMapA[myVK_RightBracket] = myVK_LeftBracket;
|
|
VkMapA[myVK_LeftBracket] = myVK_Subtract;
|
|
VkMapA[myVK_Comma] = 'M';
|
|
VkMapA[myVK_Period] = myVK_Comma;
|
|
VkMapA[myVK_Slash] = myVK_Period;
|
|
VkMapA[myVK_OEM_8] = myVK_Slash;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapGerman(void)
|
|
{
|
|
VkSwapZY();
|
|
VkMapSpanish();
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapBosnian(void)
|
|
{
|
|
VkSwapZY();
|
|
/* not in Windows 95 */
|
|
VkSwapSlashSubtract();
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapBulgarian(void)
|
|
{
|
|
VkMapA[myVK_OEM_8] = myVK_Comma;
|
|
VkMapA[myVK_Comma] = 'Q';
|
|
VkMapA['Q'] = myVK_Period;
|
|
VkMapA[myVK_Period] = myVK_Equal;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC VkMapFromLayout(uimr sv)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 256; ++i) {
|
|
VkMapA[i] = i;
|
|
}
|
|
|
|
switch (sv) {
|
|
case 0x00000409:
|
|
/* United States 101 */
|
|
break;
|
|
case 0x0000041c:
|
|
/* Albanian; */
|
|
VkSwapZY();
|
|
break;
|
|
case 0x0000042B:
|
|
/* Armenian Eastern; */
|
|
VkMapDutch();
|
|
break;
|
|
case 0x0001042B:
|
|
/* Armenian Western; */
|
|
VkMapDutch();
|
|
break;
|
|
case 0x0000042C:
|
|
/* not in Windows 95 */
|
|
/* Azeri Latin */
|
|
VkMapBritish();
|
|
break;
|
|
case 0x0001080C:
|
|
/* Belgian (comma) */
|
|
VkMapBelgian();
|
|
break;
|
|
case 0x0000080c:
|
|
/* Belgian French */
|
|
VkMapBelgian();
|
|
break;
|
|
case 0x00000813:
|
|
/* not in Windows 95 */
|
|
/* Belgian (period); */
|
|
VkMapBelgian();
|
|
break;
|
|
case 0x0000141A:
|
|
/* not in Windows 95 */
|
|
/* Bosnian */
|
|
VkMapBosnian();
|
|
break;
|
|
case 0x00000809:
|
|
/* British / United Kingdom */
|
|
VkMapBritish();
|
|
break;
|
|
case 0x00000452:
|
|
/* not in Windows 95 */
|
|
/* United Kingdom Extended */
|
|
VkMapBritish();
|
|
break;
|
|
case 0x00000402:
|
|
/* Bulgarian */
|
|
/* not same in Windows 95 */
|
|
VkMapBulgarian();
|
|
break;
|
|
case 0x00030402:
|
|
/* Bulgarian */
|
|
VkMapBulgarian();
|
|
break;
|
|
case 0x00020402:
|
|
/* Bulgarian (Phonetic) */
|
|
VkMapBosnian();
|
|
break;
|
|
case 0x00001009:
|
|
/* Canadian Multilingual */
|
|
/* not in Windows 95 */
|
|
VkSwapGraveQuote();
|
|
break;
|
|
case 0x00011009:
|
|
/* Canadian Standard */
|
|
VkSwapGraveQuote();
|
|
break;
|
|
case 0x0000041a:
|
|
/* Croatian */
|
|
VkMapBosnian();
|
|
break;
|
|
case 0x00000405:
|
|
/* Czech */
|
|
VkMapBosnian();
|
|
#if 0
|
|
/* but Windows 7 gives */
|
|
VkSwapZY();
|
|
VkMapA[myVK_Equal] = myVK_Subtract;
|
|
VkMapA[myVK_Subtract] = myVK_Slash;
|
|
VkMapA[myVK_Slash] = myVK_Equal;
|
|
#endif
|
|
break;
|
|
case 0x00020405:
|
|
/* Czech (Programmers) */
|
|
/* only in Windows 95 */
|
|
/* VkSwapZY(); */
|
|
break;
|
|
case 0x00010405:
|
|
/* Czech (Qwerty) */
|
|
/* only in Windows 95 */
|
|
/* VkSwapZY(); */
|
|
break;
|
|
case 0x00000406:
|
|
/* Danish */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x00000413:
|
|
/* Dutch */
|
|
VkMapDutch();
|
|
break;
|
|
case 0x00000425:
|
|
/* Estonian */
|
|
VkMapA[myVK_Grave] = myVK_LeftBracket;
|
|
VkMapA[myVK_LeftBracket] = myVK_RightBracket;
|
|
VkMapA[myVK_RightBracket] = myVK_Slash;
|
|
VkMapA[myVK_Slash] = myVK_SingleQuote;
|
|
VkMapA[myVK_SingleQuote] = myVK_Grave;
|
|
/* only in Windows 95 ? */
|
|
/* VkMapA[VK_DECIMAL] = VK_DELETE; */
|
|
break;
|
|
case 0x00000438:
|
|
/* Faeroe Islands */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x0000040b:
|
|
/* Finnish */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x0001083B:
|
|
/* not in Windows 95 */
|
|
/* Finnish with Sami */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x0000040c:
|
|
/* v = kKbdFrench; */
|
|
/* French */
|
|
VkMapFrench();
|
|
break;
|
|
case 0x00000c0c:
|
|
/* French Canadian */
|
|
VkSwapGraveQuote();
|
|
break;
|
|
case 0x00011809:
|
|
/* not in Windows 95 */
|
|
/* Gaelic */
|
|
VkMapBritish();
|
|
break;
|
|
case 0x00010407:
|
|
/* German (IBM) */
|
|
VkMapGerman();
|
|
break;
|
|
case 0x00000407:
|
|
/* German (Standard) */
|
|
VkMapGerman();
|
|
break;
|
|
case 0x00010408:
|
|
/* Greek IBM 220 */
|
|
/* not in Windows 95 */
|
|
VkMapGreekIBM();
|
|
break;
|
|
case 0x00030408:
|
|
/* Greek IBM 319 */
|
|
/* not in Windows 95 */
|
|
VkMapGreekIBM();
|
|
break;
|
|
case 0x00020408:
|
|
/* Greek Latin IBM 220 */
|
|
/* not in Windows 95 */
|
|
VkSwapSlashSubtract();
|
|
break;
|
|
case 0x00040408:
|
|
/* Greek Latin IBM 319 */
|
|
/* not in Windows 95 */
|
|
VkSwapSlashSubtract();
|
|
break;
|
|
case 0x0000040e:
|
|
/* Hungarian */
|
|
VkMapBosnian();
|
|
VkMapA[myVK_Grave] = '0';
|
|
VkMapA['0'] = myVK_Grave;
|
|
break;
|
|
case 0x0001040E:
|
|
/* Hungarian (101 Keys) */
|
|
VkMapA[myVK_Grave] = '0';
|
|
VkMapA['0'] = myVK_Grave;
|
|
break;
|
|
case 0x0000040f:
|
|
/* Icelandic */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x00001809:
|
|
/* Irish */
|
|
VkMapBritish();
|
|
break;
|
|
case 0x00000410:
|
|
/* Italian */
|
|
VkMapSpanish();
|
|
break;
|
|
case 0x00010410:
|
|
/* Italian 142 */
|
|
VkMapSpanish();
|
|
break;
|
|
case 0x0000080a:
|
|
/* Latin American */
|
|
VkMapSpanish();
|
|
break;
|
|
case 0x0000046E:
|
|
/* Luxembourgish */
|
|
VkMapSwiss();
|
|
break;
|
|
case 0x00000414:
|
|
/* Norwegian */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x0000043B:
|
|
/* Norwegian with Sami */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x00010415:
|
|
/* Polish (214) */
|
|
VkSwapZY();
|
|
/* not in windows 95 */
|
|
VkMapA[myVK_Equal] = myVK_Subtract;
|
|
VkMapA[myVK_Subtract] = myVK_Slash;
|
|
VkMapA[myVK_Slash] = myVK_Equal;
|
|
break;
|
|
case 0x00010416:
|
|
/* Porguguese (Brazilian ABNT2) */
|
|
/* VkMapA[myVK_OEM_8] = ??; */
|
|
/* VkMapA[VK_SEPARATOR] = ??; */
|
|
break;
|
|
case 0x00000816:
|
|
/* Porguguese (Standard) */
|
|
VkMapA[myVK_SemiColon] = myVK_RightBracket;
|
|
VkMapA[myVK_RightBracket] = myVK_Equal;
|
|
VkMapA[myVK_Equal] = myVK_LeftBracket;
|
|
VkMapA[myVK_LeftBracket] = myVK_Subtract;
|
|
VkMapA[myVK_Subtract] = myVK_Slash;
|
|
VkMapA[myVK_Slash] = myVK_BackSlash;
|
|
VkMapA[myVK_BackSlash] = myVK_Grave;
|
|
VkMapA[myVK_Grave] = myVK_SemiColon;
|
|
break;
|
|
case 0x00000418:
|
|
/* Romanian (Legacy) */
|
|
VkSwapZY();
|
|
/* only in Windows 95 */
|
|
/* VkSwapSlashSubtract(); */
|
|
break;
|
|
case 0x0002083B:
|
|
/* Sami Extended Finland-Sweden */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x0001043B:
|
|
/* Sami Extended Norway */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x00010C1A:
|
|
/* in Windows 95 */
|
|
/* Serbian (Latin) */
|
|
VkSwapZY();
|
|
break;
|
|
case 0x0000081A:
|
|
/* not in Windows 95 */
|
|
/* Serbian (Latin) */
|
|
VkMapBosnian();
|
|
break;
|
|
case 0x0000041b:
|
|
/* Slovak */
|
|
VkMapBosnian();
|
|
/* not in Windows 95 */
|
|
VkMapA[myVK_OEM_8] = myVK_Equal;
|
|
break;
|
|
case 0x00000424:
|
|
/* Slovenian */
|
|
VkMapBosnian();
|
|
break;
|
|
case 0x0000040A:
|
|
/* Spanish, not windows 95 */
|
|
VkMapSpanish();
|
|
break;
|
|
case 0x0001040A:
|
|
/* Spanish Variation, not windows 95 */
|
|
VkMapA[myVK_OEM_8] = myVK_Slash;
|
|
VkMapA[myVK_Slash] = myVK_BackSlash;
|
|
VkMapA[myVK_BackSlash] = myVK_Grave;
|
|
VkMapA[myVK_Grave] = myVK_SemiColon;
|
|
VkMapA[myVK_SemiColon] = myVK_RightBracket;
|
|
VkMapA[myVK_RightBracket] = myVK_LeftBracket;
|
|
VkMapA[myVK_LeftBracket] = myVK_Equal;
|
|
break;
|
|
case 0x00000c0a:
|
|
/* kKbdSpanish; */
|
|
/* Spanish Modern, windows 95 */
|
|
VkMapSpanish();
|
|
break;
|
|
case 0x00000403:
|
|
/* Spanish Traditional */
|
|
VkMapSpanish();
|
|
break;
|
|
case 0x0000041d:
|
|
/* Swedish */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x0000083B:
|
|
/* not in windows 95 */
|
|
/* Swedish with Sami */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x0000100c:
|
|
/* Swiss French */
|
|
VkMapSwiss();
|
|
break;
|
|
case 0x00000807:
|
|
/* Swiss German */
|
|
VkMapSwiss();
|
|
break;
|
|
case 0x0000085D:
|
|
/* Inuktitut Latin */
|
|
/* in windows 7, not XP */
|
|
VkMapBritish();
|
|
break;
|
|
case 0x0001045D:
|
|
/* Inuktitut - Naqittaut */
|
|
VkMapBritish();
|
|
break;
|
|
case 0x0000046F:
|
|
/* Greenlandic */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x00020427:
|
|
/* Lithuanian Standard */
|
|
VkMapDanish();
|
|
break;
|
|
case 0x0000042f:
|
|
/* Macedonian (FYROM) - Standard */
|
|
VkMapBosnian();
|
|
break;
|
|
case 0x0000042E:
|
|
/* Sorbian Standard (Legacy) */
|
|
VkMapGerman();
|
|
break;
|
|
case 0x0001042E:
|
|
/* Sorbian Extended */
|
|
VkMapGerman();
|
|
break;
|
|
case 0x0002042E:
|
|
/* Sorbian Standard */
|
|
VkMapGerman();
|
|
break;
|
|
case 0x00000488:
|
|
/* Wolof */
|
|
VkMapFrench();
|
|
break;
|
|
case 0x0000041f:
|
|
/* Turkish (Q type) */
|
|
/* windows 95 */
|
|
/* VkMapA[myVK_Equal] = myVK_Subtract; */
|
|
/* VkMapA[myVK_Subtract] = myVK_Equal; */
|
|
/* not windows 95 */
|
|
VkMapA[myVK_OEM_8] = myVK_Subtract;
|
|
VkMapA[myVK_Subtract] = myVK_Equal;
|
|
|
|
VkMapA[myVK_Comma] = myVK_BackSlash;
|
|
VkMapA[myVK_BackSlash] = myVK_Period;
|
|
VkMapA[myVK_Period] = myVK_Slash;
|
|
VkMapA[myVK_Slash] = myVK_Comma;
|
|
break;
|
|
case 0x00010409:
|
|
/* United States Dvorak */
|
|
VkMapA[myVK_LeftBracket] = myVK_Subtract;
|
|
VkMapA[myVK_RightBracket] = myVK_Equal;
|
|
VkMapA[myVK_SingleQuote] = 'Q';
|
|
VkMapA[myVK_Comma] = 'W';
|
|
VkMapA[myVK_Period] = 'E';
|
|
VkMapA['P'] = 'R';
|
|
VkMapA['Y'] = 'T';
|
|
VkMapA['F'] = 'Y';
|
|
VkMapA['G'] = 'U';
|
|
VkMapA['C'] = 'I';
|
|
VkMapA['R'] = 'O';
|
|
VkMapA['L'] = 'P';
|
|
VkMapA[myVK_Slash] = myVK_LeftBracket;
|
|
VkMapA[myVK_Equal] = myVK_RightBracket;
|
|
VkMapA['O'] = 'S';
|
|
VkMapA['E'] = 'D';
|
|
VkMapA['U'] = 'F';
|
|
VkMapA['I'] = 'G';
|
|
VkMapA['D'] = 'H';
|
|
VkMapA['H'] = 'J';
|
|
VkMapA['T'] = 'K';
|
|
VkMapA['N'] = 'L';
|
|
VkMapA['S'] = myVK_SemiColon;
|
|
VkMapA[myVK_Subtract] = myVK_SingleQuote;
|
|
VkMapA[myVK_SemiColon] = 'Z';
|
|
VkMapA['Q'] = 'X';
|
|
VkMapA['J'] = 'C';
|
|
VkMapA['K'] = 'V';
|
|
VkMapA['X'] = 'B';
|
|
VkMapA['B'] = 'N';
|
|
VkMapA['W'] = myVK_Comma;
|
|
VkMapA['V'] = myVK_Period;
|
|
VkMapA['Z'] = myVK_Slash;
|
|
break;
|
|
#if 0
|
|
/* too complicated, don't bother with */
|
|
case 0x0x00000426:
|
|
/* Latvian */
|
|
VkMapA['F'] = myVK_Equal;
|
|
VkMapA['G'] = 'W';
|
|
VkMapA['J'] = 'E';
|
|
VkMapA['M'] = 'T';
|
|
VkMapA['V'] = 'Y';
|
|
VkMapA['N'] = 'U';
|
|
VkMapA['Z'] = 'I';
|
|
VkMapA['W'] = 'O';
|
|
VkMapA['X'] = 'P';
|
|
VkMapA['Y'] = myVK_LeftBracket;
|
|
VkMapA['H'] = myVK_RightBracket;
|
|
VkMapA[myVK_SemiColon] = 'A';
|
|
VkMapA['U'] = 'S';
|
|
VkMapA['S'] = 'D';
|
|
VkMapA['I'] = 'F';
|
|
VkMapA['L'] = 'G';
|
|
VkMapA['D'] = 'H';
|
|
VkMapA['A'] = 'J';
|
|
VkMapA['T'] = 'K';
|
|
VkMapA['E'] = 'L';
|
|
VkMapA['C'] = myVK_SemiColon;
|
|
VkMapA[myVK_LeftBracket] = 'Z';
|
|
VkMapA['B'] = 'X';
|
|
VkMapA[myVK_RightBracket] = 'C';
|
|
VkMapA['K'] = 'V';
|
|
VkMapA['P'] = 'B';
|
|
VkMapA['O'] = 'N';
|
|
VkMapA[myVK_OEM_8] = 'M';
|
|
break;
|
|
case 0x0001041F:
|
|
/* Turkish (F type) */
|
|
|
|
VkMapA[myVK_Equal] = myVK_Subtract;
|
|
VkMapA[myVK_Subtract] = myVK_Equal;
|
|
VkMapA['F'] = 'Q';
|
|
VkMapA['G'] = 'W';
|
|
VkMapA[myVK_SemiColon] = 'E';
|
|
VkMapA['I'] = 'R';
|
|
VkMapA['O'] = 'T';
|
|
VkMapA['D'] = 'Y';
|
|
VkMapA['R'] = 'U';
|
|
VkMapA['N'] = 'I';
|
|
VkMapA['H'] = 'O';
|
|
VkMapA['Q'] = myVK_LeftBracket;
|
|
VkMapA['W'] = myVK_RightBracket;
|
|
VkMapA['U'] = 'A';
|
|
VkMapA[myVK_LeftBracket] = 'S';
|
|
VkMapA['E'] = 'D';
|
|
VkMapA['A'] = 'F';
|
|
VkMapA[myVK_RightBracket] = 'G';
|
|
VkMapA['T'] = 'H';
|
|
VkMapA['K'] = 'J';
|
|
VkMapA['M'] = 'K';
|
|
VkMapA['Y'] = myVK_SemiColon;
|
|
VkMapA['X'] = myVK_BackSlash;
|
|
VkMapA['J'] = 'Z';
|
|
VkMapA[myVK_BackSlash] = 'X';
|
|
VkMapA['V'] = 'C';
|
|
VkMapA['C'] = 'V';
|
|
VkMapA[myVK_Slash] = 'B';
|
|
VkMapA['Z'] = 'N';
|
|
VkMapA['S'] = 'M';
|
|
VkMapA['B'] = myVK_Comma;
|
|
VkMapA[myVK_Comma] = myVK_Slash;
|
|
break;
|
|
case 0x00030409:
|
|
/* United States LH Dvorak */
|
|
VkMapA[myVK_LeftBracket] = '1';
|
|
VkMapA[myVK_RightBracket] = '2';
|
|
VkMapA[myVK_Slash] = '3';
|
|
VkMapA['P'] = '4';
|
|
VkMapA['F'] = '5';
|
|
VkMapA['M'] = '6';
|
|
VkMapA['L'] = '7';
|
|
VkMapA['J'] = '8';
|
|
VkMapA['4'] = '9';
|
|
VkMapA['3'] = '0';
|
|
VkMapA['2'] = myVK_Subtract;
|
|
VkMapA['1'] = myVK_Equal;
|
|
VkMapA[myVK_SemiColon] = 'Q';
|
|
VkMapA['Q'] = 'W';
|
|
VkMapA['B'] = 'E';
|
|
VkMapA['Y'] = 'R';
|
|
VkMapA['U'] = 'T';
|
|
VkMapA['R'] = 'Y';
|
|
VkMapA['S'] = 'U';
|
|
VkMapA['O'] = 'I';
|
|
VkMapA[myVK_Period] = 'O';
|
|
VkMapA['6'] = 'P';
|
|
VkMapA['5'] = myVK_LeftBracket;
|
|
VkMapA[myVK_Equal] = myVK_RightBracket;
|
|
VkMapA[myVK_Subtract] = 'A';
|
|
VkMapA['K'] = 'S';
|
|
VkMapA['C'] = 'D';
|
|
VkMapA['D'] = 'F';
|
|
VkMapA['T'] = 'G';
|
|
VkMapA['E'] = 'J';
|
|
VkMapA['A'] = 'K';
|
|
VkMapA['Z'] = 'L';
|
|
VkMapA['8'] = myVK_SemiColon;
|
|
VkMapA['7'] = myVK_SingleQuote;
|
|
VkMapA[myVK_SingleQuote] = 'Z';
|
|
VkMapA['G'] = 'C';
|
|
VkMapA['W'] = 'B';
|
|
VkMapA['I'] = 'M';
|
|
VkMapA['0'] = myVK_Period;
|
|
VkMapA['9'] = myVK_Slash;
|
|
break;
|
|
case 0x00040409:
|
|
/* United States RH Dvorak */
|
|
VkMapA['J'] = '5';
|
|
VkMapA['L'] = '6';
|
|
VkMapA['M'] = '7';
|
|
VkMapA['F'] = '8';
|
|
VkMapA['P'] = '9';
|
|
VkMapA[myVK_Slash] = '0';
|
|
VkMapA[myVK_LeftBracket] = myVK_Subtract;
|
|
VkMapA[myVK_RightBracket] = myVK_Equal;
|
|
VkMapA['5'] = 'Q';
|
|
VkMapA['6'] = 'W';
|
|
VkMapA['Q'] = 'E';
|
|
VkMapA[myVK_Period] = 'R';
|
|
VkMapA['O'] = 'T';
|
|
VkMapA['R'] = 'Y';
|
|
VkMapA['S'] = 'U';
|
|
VkMapA['U'] = 'I';
|
|
VkMapA['Y'] = 'O';
|
|
VkMapA['B'] = 'P';
|
|
VkMapA[myVK_SemiColon] = myVK_LeftBracket;
|
|
VkMapA[myVK_Equal] = myVK_RightBracket;
|
|
VkMapA['7'] = 'A';
|
|
VkMapA['8'] = 'S';
|
|
VkMapA['Z'] = 'D';
|
|
VkMapA['A'] = 'F';
|
|
VkMapA['E'] = 'G';
|
|
VkMapA['T'] = 'J';
|
|
VkMapA['D'] = 'K';
|
|
VkMapA['C'] = 'L';
|
|
VkMapA['K'] = myVK_SemiColon;
|
|
VkMapA[myVK_Subtract] = myVK_SingleQuote;
|
|
VkMapA['9'] = 'Z';
|
|
VkMapA['0'] = 'X';
|
|
VkMapA['X'] = 'C';
|
|
VkMapA[myVK_Comma] = 'V';
|
|
VkMapA['I'] = 'B';
|
|
VkMapA['W'] = 'M';
|
|
VkMapA['V'] = myVK_Comma;
|
|
VkMapA['G'] = myVK_Period;
|
|
VkMapA[myVK_SingleQuote] = myVK_Slash;
|
|
break;
|
|
#endif
|
|
#if 0
|
|
case 0x0000082C:
|
|
/* not in Windows 95 */
|
|
/* Azeri Cyrillic */
|
|
break;
|
|
case 0x00000423:
|
|
/* Belarusian */
|
|
break;
|
|
case 0x00000445:
|
|
/* not in Windows 95 */
|
|
/* Bengali */
|
|
break;
|
|
case 0x00010445:
|
|
/* not in Windows 95 */
|
|
/* Bengali (Inscript) */
|
|
break;
|
|
case 0x0000201A:
|
|
/* not in Windows 95 */
|
|
/* Bosnian Cyrillic*/
|
|
break;
|
|
case 0x00010402:
|
|
/* Bulgarian Latin */
|
|
#if 0 /* Only in Windows 95 */
|
|
VkMapA['J'] = 'Q';
|
|
VkMapA['C'] = 'W';
|
|
VkMapA['U'] = 'E';
|
|
VkMapA['K'] = 'R';
|
|
VkMapA['E'] = 'T';
|
|
VkMapA['N'] = 'Y';
|
|
VkMapA['G'] = 'U';
|
|
VkMapA[myVK_SemiColon] = 'I';
|
|
VkMapA[myVK_OEM_102] = 'O';
|
|
VkMapA['Z'] = 'P';
|
|
VkMapA['H'] = myVK_LeftBracket;
|
|
VkMapA['F'] = 'A';
|
|
VkMapA['Y'] = 'S';
|
|
VkMapA['W'] = 'D';
|
|
VkMapA['A'] = 'F';
|
|
VkMapA['P'] = 'G';
|
|
VkMapA['R'] = 'H';
|
|
VkMapA['O'] = 'J';
|
|
VkMapA['L'] = 'K';
|
|
VkMapA['D'] = 'L';
|
|
VkMapA['V'] = myVK_SemiColon;
|
|
VkMapA[myVK_LeftBracket] = 'Z';
|
|
VkMapA['S'] = 'X';
|
|
VkMapA['M'] = 'C';
|
|
VkMapA['I'] = 'V';
|
|
VkMapA['T'] = 'B';
|
|
VkMapA['X'] = 'N';
|
|
VkMapA['B'] = 'M';
|
|
VkMapA['Q'] = myVK_OEM_102;
|
|
#endif
|
|
break;
|
|
case 0x00000408:
|
|
/* Greek */
|
|
break;
|
|
case 0x00050408:
|
|
/* Greek Latin */
|
|
break;
|
|
case 0x00060408:
|
|
/* Greek Polytonic */
|
|
break;
|
|
case 0x0000043F:
|
|
/* Kazakh */
|
|
break;
|
|
case 0x00000440:
|
|
/* Kyrgyz Cyrillic */
|
|
break;
|
|
case 0x00010426:
|
|
/* Latvian Latin */
|
|
break;
|
|
case 0x00010427:
|
|
/* Lithuanian */
|
|
break;
|
|
case 0x00000427:
|
|
/* Lithuanian (IBM) */
|
|
break;
|
|
case 0x0000044C:
|
|
/* Malayalam */
|
|
break;
|
|
case 0x0000042f:
|
|
/* Macedonian (FYROM) */
|
|
break;
|
|
case 0x0000043A:
|
|
/* Maltese 47-key */
|
|
break;
|
|
case 0x0001043A:
|
|
/* Maltese 48-key */
|
|
break;
|
|
case 0x00000481:
|
|
/* Maori */
|
|
break;
|
|
case 0x00000450:
|
|
/* Mongolian Cyrillic */
|
|
break;
|
|
case 0x00000461:
|
|
/* Nepali */
|
|
break;
|
|
case 0x00000463:
|
|
/* Pashto */
|
|
break;
|
|
case 0x00000415:
|
|
/* Polish (Programmers) */
|
|
break;
|
|
case 0x00000416:
|
|
/* Porguguese (Brazilian standard) */
|
|
break;
|
|
case 0x00000419:
|
|
/* Russian */
|
|
break;
|
|
case 0x00010419:
|
|
/* Russian (Typewriter) */
|
|
break;
|
|
case 0x00000c1a:
|
|
/* Serbian */
|
|
break;
|
|
case 0x0001041B:
|
|
/* Slovak (Qwerty) */
|
|
break;
|
|
case 0x00000444:
|
|
/* Tatar */
|
|
break;
|
|
case 0x00000422:
|
|
/* Ukrainian */
|
|
break;
|
|
case 0x00020409:
|
|
/* United States International */
|
|
break;
|
|
case 0x00000843:
|
|
/* Uzbek Cyrillic */
|
|
break;
|
|
case 0x00010418:
|
|
/* Romanian (Standard) */
|
|
break;
|
|
case 0x00020418:
|
|
/* Romanian (Programmers) */
|
|
break;
|
|
case 0x00000401:
|
|
/* Arabic (101) */
|
|
break;
|
|
case 0x00010401:
|
|
/* Arabic (102) */
|
|
break;
|
|
case 0x0000044D:
|
|
/* Assamese - INSCRIPT */
|
|
break;
|
|
case 0x0000046D:
|
|
/* Bashkir */
|
|
break;
|
|
case 0x00040402:
|
|
/* Bulgarian (Phonetic Traditional) */
|
|
break;
|
|
case 0x00000404:
|
|
/* Chinese (Traditional) */
|
|
break;
|
|
case 0x00000804:
|
|
/* Chinese (Simplified) */
|
|
break;
|
|
case 0x00000C04:
|
|
/* Chinese (Traditional, Hong Kong S.A.R.) */
|
|
break;
|
|
case 0x00001004:
|
|
/* Chinese (Simplified, Singapore) */
|
|
break;
|
|
case 0x00001404:
|
|
/* Chinese (Traditional, Macao S.A.R.) */
|
|
break;
|
|
case 0x0000040D:
|
|
/* Hebrew */
|
|
break;
|
|
case 0x00000447:
|
|
/* Gujarati */
|
|
break;
|
|
case 0x00000468:
|
|
/* Hausa */
|
|
break;
|
|
case 0x00010439:
|
|
/* Hindi Traditional */
|
|
break;
|
|
case 0x00000439:
|
|
/* Devanagari - INSCRIPT */
|
|
break;
|
|
case 0x00000465:
|
|
/* Divehi Phonetic */
|
|
break;
|
|
case 0x00010465:
|
|
/* Divehi Typewriter */
|
|
break;
|
|
case 0x00000437:
|
|
/* Georgian */
|
|
break;
|
|
case 0x00010437:
|
|
/* Georgian (QWERTY) */
|
|
break;
|
|
case 0x00020437:
|
|
/* Georgian (Ergonomic) */
|
|
break;
|
|
case 0x00000470:
|
|
/* Igbo */
|
|
break;
|
|
case 0x00000411:
|
|
/* Japanese */
|
|
/* VkMapA[??] = ??; */
|
|
break;
|
|
case 0x00000412:
|
|
/* Korean */
|
|
/* VkMapA[VK_ZOOM] = ??; */
|
|
/* VkMapA[VK_HELP] = VK_ZOOM; */
|
|
/* VkMapA[??] = VK_HELP; */
|
|
/* VkMapA[??] = ??; */
|
|
break;
|
|
case 0x0000044B:
|
|
/* Kannada */
|
|
break;
|
|
case 0x00000453:
|
|
/* Khmer */
|
|
break;
|
|
case 0x00000454:
|
|
/* Lao */
|
|
break;
|
|
case 0x00000448:
|
|
/* Oriya */
|
|
break;
|
|
case 0x0000044E:
|
|
/* Marathi */
|
|
break;
|
|
case 0x00000850:
|
|
/* Mongolian (Mongolian Script) */
|
|
break;
|
|
case 0x00000429:
|
|
/* Persion */
|
|
break;
|
|
case 0x00000446:
|
|
/* Punjabi */
|
|
break;
|
|
case 0x0000046C:
|
|
/* Sesotho sa Leboa */
|
|
break;
|
|
case 0x00000432:
|
|
/* Setswana */
|
|
break;
|
|
case 0x0000045B:
|
|
/* Sinhala */
|
|
break;
|
|
case 0x0001045B:
|
|
/* Sinhala - Wij 9 */
|
|
break;
|
|
case 0x0000045A:
|
|
/* Syriac */
|
|
break;
|
|
case 0x0001045A:
|
|
/* Syriac Phonetic */
|
|
break;
|
|
case 0x00000428:
|
|
/* Tajik */
|
|
break;
|
|
case 0x00000449:
|
|
/* Tamil */
|
|
break;
|
|
case 0x0000044A:
|
|
/* Telugu */
|
|
break;
|
|
case 0x0000041E:
|
|
/* Thai Kedmanee */
|
|
break;
|
|
case 0x0001041E:
|
|
/* Thai Pattachote */
|
|
break;
|
|
case 0x0002041E:
|
|
/* Thai Kedmanee (non-ShiftLock) */
|
|
break;
|
|
case 0x0003041E:
|
|
/* Thai Pattachote (non-ShiftLock) */
|
|
break;
|
|
case 0x00000451:
|
|
/* Tibetan (PRC) */
|
|
break;
|
|
case 0x00000442:
|
|
/* Turkmen */
|
|
break;
|
|
case 0x00020422:
|
|
/* Ukrainian (Enhanced) */
|
|
break;
|
|
case 0x00000420:
|
|
/* Urdu */
|
|
break;
|
|
case 0x00050409:
|
|
/* US English Table for IBM Arabic 238_L */
|
|
break;
|
|
case 0x00000480:
|
|
/* Uyghur (Legacy) */
|
|
break;
|
|
case 0x00010480:
|
|
/* Uyghur */
|
|
break;
|
|
case 0x0000042A:
|
|
/* Vietnamese */
|
|
break;
|
|
case 0x00000485:
|
|
/* Yakut */
|
|
break;
|
|
case 0x0000046A:
|
|
/* Yoruba */
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALVAR uimr CurKyBdLytNm = 0;
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALFUNC bool tStrIsHex(TCHAR *s, int n, uimr *r)
|
|
{
|
|
short i;
|
|
TCHAR c1;
|
|
TCHAR *p = s;
|
|
uimr v = 0;
|
|
|
|
for (i = n; --i >= 0; ) {
|
|
v <<= 4;
|
|
c1 = *p++;
|
|
if ((c1 >= '0') && (c1 <= '9')) {
|
|
v += c1 - '0';
|
|
} else if ((c1 >= 'A') && (c1 <= 'F')) {
|
|
v += c1 - ('A' - 10);
|
|
} else if ((c1 >= 'a') && (c1 <= 'f')) {
|
|
v += c1 - ('a' - 10);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
*r = v;
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALFUNC bool GetKeyboardLayoutHex(uimr *r)
|
|
{
|
|
TCHAR s[KL_NAMELENGTH];
|
|
bool IsOk = false;
|
|
|
|
if (! GetKeyboardLayoutName(s)) {
|
|
/* ReportWinLastError(); */
|
|
} else {
|
|
size_t n = _tcslen(s);
|
|
|
|
if (8 != n) {
|
|
/* fail */
|
|
} else {
|
|
IsOk = tStrIsHex(s, n, r);
|
|
}
|
|
}
|
|
|
|
return IsOk;
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix && ! UseWinCE
|
|
LOCALPROC CheckKeyboardLayout(void)
|
|
{
|
|
uimr sv;
|
|
|
|
if (! GetKeyboardLayoutHex(&sv)) {
|
|
} else if (sv == CurKyBdLytNm) {
|
|
/* no change */
|
|
} else {
|
|
CurKyBdLytNm = sv;
|
|
|
|
VkMapFromLayout(sv);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if ItnlKyBdFix
|
|
LOCALPROC InitCheckKeyboardLayout(void)
|
|
{
|
|
uimr sv;
|
|
|
|
if (! GetKeyboardLayoutHex(&sv)) {
|
|
sv = 0x00000409;
|
|
}
|
|
|
|
CurKyBdLytNm = sv;
|
|
|
|
VkMapFromLayout(sv);
|
|
}
|
|
#endif
|
|
|
|
LOCALVAR uint8_t WinKey2Mac[256];
|
|
|
|
LOCALPROC AssignOneMacKey(uint8_t WinKey, uint8_t MacKey)
|
|
{
|
|
WinKey2Mac[WinKey] = MacKey;
|
|
}
|
|
|
|
LOCALFUNC bool InitWinKey2Mac(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 256; ++i) {
|
|
WinKey2Mac[i] = MKC_None;
|
|
}
|
|
|
|
AssignOneMacKey('A', MKC_A);
|
|
AssignOneMacKey('S', MKC_S);
|
|
AssignOneMacKey('D', MKC_D);
|
|
AssignOneMacKey('F', MKC_F);
|
|
AssignOneMacKey('H', MKC_H);
|
|
AssignOneMacKey('G', MKC_G);
|
|
AssignOneMacKey('Z', MKC_Z);
|
|
AssignOneMacKey('X', MKC_X);
|
|
AssignOneMacKey('C', MKC_C);
|
|
AssignOneMacKey('V', MKC_V);
|
|
AssignOneMacKey('B', MKC_B);
|
|
AssignOneMacKey('Q', MKC_Q);
|
|
AssignOneMacKey('W', MKC_W);
|
|
AssignOneMacKey('E', MKC_E);
|
|
AssignOneMacKey('R', MKC_R);
|
|
AssignOneMacKey('Y', MKC_Y);
|
|
AssignOneMacKey('T', MKC_T);
|
|
AssignOneMacKey('1', MKC_1);
|
|
AssignOneMacKey('2', MKC_2);
|
|
AssignOneMacKey('3', MKC_3);
|
|
AssignOneMacKey('4', MKC_4);
|
|
AssignOneMacKey('6', MKC_6);
|
|
AssignOneMacKey('5', MKC_5);
|
|
AssignOneMacKey(myVK_Equal, MKC_Equal);
|
|
AssignOneMacKey('9', MKC_9);
|
|
AssignOneMacKey('7', MKC_7);
|
|
AssignOneMacKey(myVK_Subtract, MKC_Minus);
|
|
AssignOneMacKey('8', MKC_8);
|
|
AssignOneMacKey('0', MKC_0);
|
|
AssignOneMacKey(myVK_RightBracket, MKC_RightBracket);
|
|
AssignOneMacKey('O', MKC_O);
|
|
AssignOneMacKey('U', MKC_U);
|
|
AssignOneMacKey(myVK_LeftBracket, MKC_LeftBracket);
|
|
AssignOneMacKey('I', MKC_I);
|
|
AssignOneMacKey('P', MKC_P);
|
|
AssignOneMacKey(VK_RETURN, MKC_Return);
|
|
AssignOneMacKey('L', MKC_L);
|
|
AssignOneMacKey('J', MKC_J);
|
|
AssignOneMacKey(myVK_SingleQuote, MKC_SingleQuote);
|
|
AssignOneMacKey('K', MKC_K);
|
|
AssignOneMacKey(myVK_SemiColon, MKC_SemiColon);
|
|
AssignOneMacKey(myVK_BackSlash, MKC_formac_BackSlash);
|
|
AssignOneMacKey(myVK_Comma, MKC_Comma);
|
|
AssignOneMacKey(myVK_Slash, MKC_formac_Slash);
|
|
AssignOneMacKey('N', MKC_N);
|
|
AssignOneMacKey('M', MKC_M);
|
|
AssignOneMacKey(myVK_Period, MKC_Period);
|
|
|
|
AssignOneMacKey(VK_TAB, MKC_Tab);
|
|
AssignOneMacKey(VK_SPACE, MKC_Space);
|
|
AssignOneMacKey(myVK_Grave, MKC_formac_Grave);
|
|
AssignOneMacKey(VK_BACK, MKC_BackSpace);
|
|
AssignOneMacKey(VK_ESCAPE, MKC_formac_Escape);
|
|
|
|
AssignOneMacKey(VK_MENU, MKC_formac_Command);
|
|
|
|
AssignOneMacKey(VK_LMENU, MKC_formac_Command);
|
|
|
|
AssignOneMacKey(VK_RMENU, MKC_formac_RCommand);
|
|
|
|
AssignOneMacKey(VK_SHIFT, MKC_formac_Shift);
|
|
AssignOneMacKey(VK_LSHIFT, MKC_formac_Shift);
|
|
AssignOneMacKey(VK_RSHIFT, MKC_formac_RShift);
|
|
|
|
AssignOneMacKey(VK_CAPITAL, MKC_formac_CapsLock);
|
|
|
|
AssignOneMacKey(VK_APPS, MKC_formac_ROption);
|
|
|
|
AssignOneMacKey(VK_LWIN, MKC_formac_Option);
|
|
|
|
AssignOneMacKey(VK_RWIN, MKC_formac_ROption);
|
|
|
|
AssignOneMacKey(VK_CONTROL, MKC_formac_Control);
|
|
|
|
AssignOneMacKey(VK_LCONTROL, MKC_formac_Control);
|
|
|
|
AssignOneMacKey(VK_RCONTROL, MKC_formac_RControl);
|
|
|
|
AssignOneMacKey(VK_F1, MKC_formac_F1);
|
|
AssignOneMacKey(VK_F2, MKC_formac_F2);
|
|
AssignOneMacKey(VK_F3, MKC_formac_F3);
|
|
AssignOneMacKey(VK_F4, MKC_formac_F4);
|
|
AssignOneMacKey(VK_F5, MKC_formac_F5);
|
|
AssignOneMacKey(VK_F6, MKC_F6);
|
|
AssignOneMacKey(VK_F7, MKC_F7);
|
|
AssignOneMacKey(VK_F8, MKC_F8);
|
|
AssignOneMacKey(VK_F9, MKC_F9);
|
|
AssignOneMacKey(VK_F10, MKC_F10);
|
|
AssignOneMacKey(VK_F11, MKC_F11);
|
|
AssignOneMacKey(VK_F12, MKC_F12);
|
|
|
|
AssignOneMacKey(VK_DECIMAL, MKC_Decimal);
|
|
AssignOneMacKey(VK_DELETE, MKC_Decimal);
|
|
/* AssignOneMacKey(VK_RIGHT, 0x42); */
|
|
AssignOneMacKey(VK_MULTIPLY, MKC_KPMultiply);
|
|
AssignOneMacKey(VK_ADD, MKC_KPAdd);
|
|
/* AssignOneMacKey(VK_LEFT, 0x46); */
|
|
AssignOneMacKey(VK_NUMLOCK, MKC_Clear);
|
|
|
|
/* AssignOneMacKey(VK_DOWN, 0x48); */
|
|
AssignOneMacKey(VK_DIVIDE, MKC_KPDevide);
|
|
/* AssignOneMacKey(VK_RETURN, MKC_formac_Enter); */
|
|
/* AssignOneMacKey(VK_UP, 0x4D); */
|
|
AssignOneMacKey(VK_DIVIDE, MKC_KPDevide);
|
|
AssignOneMacKey(VK_SUBTRACT, MKC_KPSubtract);
|
|
|
|
AssignOneMacKey(VK_SEPARATOR, MKC_KPEqual);
|
|
AssignOneMacKey(VK_NUMPAD0, MKC_KP0);
|
|
AssignOneMacKey(VK_NUMPAD1, MKC_KP1);
|
|
AssignOneMacKey(VK_NUMPAD2, MKC_KP2);
|
|
AssignOneMacKey(VK_NUMPAD3, MKC_KP3);
|
|
AssignOneMacKey(VK_NUMPAD4, MKC_KP4);
|
|
AssignOneMacKey(VK_NUMPAD5, MKC_KP5);
|
|
|
|
AssignOneMacKey(VK_NUMPAD6, MKC_KP6);
|
|
AssignOneMacKey(VK_NUMPAD7, MKC_KP7);
|
|
AssignOneMacKey(VK_NUMPAD8, MKC_KP8);
|
|
AssignOneMacKey(VK_NUMPAD9, MKC_KP9);
|
|
|
|
AssignOneMacKey(VK_LEFT, MKC_Left);
|
|
AssignOneMacKey(VK_RIGHT, MKC_Right);
|
|
AssignOneMacKey(VK_DOWN, MKC_Down);
|
|
AssignOneMacKey(VK_UP, MKC_Up);
|
|
|
|
AssignOneMacKey(myVK_PRIOR, MKC_formac_PageUp);
|
|
AssignOneMacKey(myVK_NEXT, MKC_formac_PageDown);
|
|
AssignOneMacKey(myVK_END, MKC_formac_End);
|
|
AssignOneMacKey(myVK_HOME, MKC_formac_Home);
|
|
AssignOneMacKey(myVK_INSERT, MKC_formac_Help);
|
|
AssignOneMacKey(myVK_DELETE, MKC_formac_ForwardDel);
|
|
AssignOneMacKey(myVK_HELP, MKC_formac_Help);
|
|
AssignOneMacKey(myVK_SNAPSHOT, MKC_Print);
|
|
AssignOneMacKey(myVK_SCROLL, MKC_ScrollLock);
|
|
AssignOneMacKey(myVK_PAUSE, MKC_Pause);
|
|
|
|
AssignOneMacKey(myVK_OEM_102, MKC_AngleBracket);
|
|
|
|
InitKeyCodes();
|
|
|
|
#if ItnlKyBdFix
|
|
InitCheckKeyboardLayout();
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
LOCALPROC DoKeyCode(int i, bool down)
|
|
{
|
|
uint8_t key = WinKey2Mac[
|
|
#if ItnlKyBdFix
|
|
VkMapA[i]
|
|
#else
|
|
i
|
|
#endif
|
|
];
|
|
if (MKC_None != key) {
|
|
Keyboard_UpdateKeyMap2(key, down);
|
|
}
|
|
}
|
|
|
|
#ifndef EnableGrabSpecialKeys
|
|
#if UseWinCE
|
|
#define EnableGrabSpecialKeys 0
|
|
#else
|
|
#define EnableGrabSpecialKeys (MayFullScreen && GrabKeysFullScreen)
|
|
#endif
|
|
#endif /* EnableGrabSpecialKeys */
|
|
|
|
#if EnableGrabSpecialKeys
|
|
LOCALVAR bool HaveSetSysParam = false;
|
|
#endif
|
|
|
|
LOCALPROC CheckTheCapsLock(void)
|
|
{
|
|
DoKeyCode(VK_CAPITAL, (GetKeyState(VK_CAPITAL) & 1) != 0);
|
|
}
|
|
|
|
#if EnableGrabSpecialKeys
|
|
LOCALVAR bool VK_LWIN_pressed = false;
|
|
LOCALVAR bool VK_RWIN_pressed = false;
|
|
#endif
|
|
|
|
#if EnableGrabSpecialKeys
|
|
LOCALPROC CheckForLostKeyUps(void)
|
|
{
|
|
if (HaveSetSysParam) {
|
|
/* check for lost key ups */
|
|
if (VK_LWIN_pressed) {
|
|
if ((GetAsyncKeyState(VK_LWIN) & 0x8000) == 0) {
|
|
DoKeyCode(VK_LWIN, false);
|
|
VK_LWIN_pressed = false;
|
|
}
|
|
}
|
|
if (VK_RWIN_pressed) {
|
|
if ((GetAsyncKeyState(VK_RWIN) & 0x8000) == 0) {
|
|
DoKeyCode(VK_RWIN, false);
|
|
VK_RWIN_pressed = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
LOCALPROC DoVKcode0(int i, bool down)
|
|
{
|
|
#if EnableGrabSpecialKeys
|
|
if (HaveSetSysParam) {
|
|
/* will need to check for lost key ups */
|
|
if (VK_LWIN == i) {
|
|
VK_LWIN_pressed = down;
|
|
} else if (VK_RWIN == i) {
|
|
VK_RWIN_pressed = down;
|
|
}
|
|
}
|
|
#endif
|
|
DoKeyCode(i, down);
|
|
}
|
|
|
|
LOCALPROC DoVKcode(int i, uint8_t flags, bool down)
|
|
{
|
|
switch (i) {
|
|
#if MKC_formac_Control != MKC_formac_RControl
|
|
case VK_CONTROL:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_formac_RControl : MKC_formac_Control,
|
|
down);
|
|
break;
|
|
#endif
|
|
#if MKC_formac_RCommand != MKC_formac_Command
|
|
case VK_MENU:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_formac_RCommand : MKC_formac_Command,
|
|
down);
|
|
break;
|
|
#endif
|
|
case VK_RETURN:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_formac_Enter : MKC_Return,
|
|
down);
|
|
break;
|
|
case myVK_HOME:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_formac_Home : MKC_KP7,
|
|
down);
|
|
break;
|
|
case VK_UP:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_Up : MKC_KP8,
|
|
down);
|
|
break;
|
|
case myVK_PRIOR:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_formac_PageUp : MKC_KP9,
|
|
down);
|
|
break;
|
|
case VK_LEFT:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_Left : MKC_KP4,
|
|
down);
|
|
break;
|
|
case myVK_CLEAR:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_Clear : MKC_KP5,
|
|
down);
|
|
break;
|
|
case VK_RIGHT:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_Right : MKC_KP6,
|
|
down);
|
|
break;
|
|
case myVK_END:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_formac_End : MKC_KP1,
|
|
down);
|
|
break;
|
|
case VK_DOWN:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_Down : MKC_KP2,
|
|
down);
|
|
break;
|
|
case myVK_NEXT:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_formac_PageDown : MKC_KP3,
|
|
down);
|
|
break;
|
|
case myVK_INSERT:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_formac_Help : MKC_KP0,
|
|
down);
|
|
break;
|
|
case myVK_DELETE:
|
|
Keyboard_UpdateKeyMap2(TestBit(flags, 0)
|
|
? MKC_formac_ForwardDel : MKC_Decimal,
|
|
down);
|
|
break;
|
|
case VK_CAPITAL:
|
|
CheckTheCapsLock();
|
|
break;
|
|
default:
|
|
if ((i >= 0) && (i < 256)) {
|
|
DoVKcode0(i, down);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
LOCALVAR bool WantCmdOptOnReconnect = false;
|
|
|
|
LOCALPROC ReconnectKeyCodes3(void)
|
|
{
|
|
int i;
|
|
|
|
CheckTheCapsLock();
|
|
|
|
if (WantCmdOptOnReconnect) {
|
|
WantCmdOptOnReconnect = false;
|
|
|
|
for (i = 0; i < 256; ++i) {
|
|
if ((GetKeyState(i) & 0x8000) != 0) {
|
|
if ((VK_CAPITAL != i)
|
|
&& (VK_RETURN != i))
|
|
{
|
|
DoVKcode0(i, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LOCALPROC DisconnectKeyCodes3(void)
|
|
{
|
|
DisconnectKeyCodes2();
|
|
SetCurMouseButton(false);
|
|
}
|
|
|
|
#if EnableGrabSpecialKeys
|
|
static HHOOK hKeyHook = NULL;
|
|
#endif
|
|
|
|
#if EnableGrabSpecialKeys
|
|
typedef struct {
|
|
DWORD vkCode;
|
|
DWORD scanCode;
|
|
DWORD flags;
|
|
DWORD time;
|
|
DWORD dwExtraInfo;
|
|
} _KBDLLHOOKSTRUCT;
|
|
#endif
|
|
|
|
#if EnableGrabSpecialKeys
|
|
LRESULT CALLBACK LowLevelKeyboardProc(
|
|
int nCode, /* hook code */
|
|
WPARAM wParam, /* message identifier */
|
|
LPARAM lParam /* pointer to structure with message data */
|
|
);
|
|
#endif
|
|
|
|
#if EnableGrabSpecialKeys
|
|
LRESULT CALLBACK LowLevelKeyboardProc(
|
|
int nCode, /* hook code */
|
|
WPARAM wParam, /* message identifier */
|
|
LPARAM lParam /* pointer to structure with message data */
|
|
)
|
|
{
|
|
if (nCode == HC_ACTION) {
|
|
_KBDLLHOOKSTRUCT *p = (_KBDLLHOOKSTRUCT *)lParam;
|
|
if (p->vkCode != VK_CAPITAL) {
|
|
switch (wParam) {
|
|
case WM_KEYDOWN:
|
|
case WM_SYSKEYDOWN:
|
|
DoVKcode(p->vkCode, p->flags, true);
|
|
return 1;
|
|
break;
|
|
case WM_KEYUP:
|
|
case WM_SYSKEYUP:
|
|
DoVKcode(p->vkCode, p->flags, false);
|
|
return 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return CallNextHookEx(hKeyHook, /* handle to current hook */
|
|
nCode, /* hook code passed to hook procedure */
|
|
wParam, /* value passed to hook procedure */
|
|
lParam /* value passed to hook procedure */
|
|
);
|
|
|
|
}
|
|
#endif
|
|
|
|
#if EnableGrabSpecialKeys
|
|
#define _WH_KEYBOARD_LL 13
|
|
#define _SPI_SETSCREENSAVERRUNNING 0x0061
|
|
#endif
|
|
|
|
#if EnableGrabSpecialKeys
|
|
LOCALVAR UINT nPreviousState;
|
|
#endif
|
|
|
|
#if EnableGrabSpecialKeys
|
|
LOCALPROC GrabSpecialKeys(void)
|
|
{
|
|
if ((hKeyHook == NULL) && ! HaveSetSysParam) {
|
|
/* this works on Windows XP */
|
|
hKeyHook = SetWindowsHookEx(
|
|
_WH_KEYBOARD_LL, /* type of hook to install */
|
|
(HOOKPROC)LowLevelKeyboardProc,
|
|
/* address of hook procedure */
|
|
AppInstance, /* handle to application instance */
|
|
0 /* identity of thread to install hook for */
|
|
);
|
|
if (hKeyHook == NULL) {
|
|
/* this works on Windows 95/98 */
|
|
SystemParametersInfo(_SPI_SETSCREENSAVERRUNNING, TRUE,
|
|
&nPreviousState, 0);
|
|
HaveSetSysParam = true;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if EnableGrabSpecialKeys
|
|
LOCALPROC UnGrabSpecialKeys(void)
|
|
{
|
|
if (hKeyHook != NULL) {
|
|
(void) UnhookWindowsHookEx(hKeyHook);
|
|
hKeyHook = NULL;
|
|
}
|
|
if (HaveSetSysParam) {
|
|
SystemParametersInfo(_SPI_SETSCREENSAVERRUNNING, FALSE,
|
|
&nPreviousState, 0);
|
|
HaveSetSysParam = false;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* --- priority --- */
|
|
|
|
#ifndef EnableChangePriority
|
|
#if UseWinCE
|
|
#define EnableChangePriority 0
|
|
#else
|
|
#define EnableChangePriority MayFullScreen
|
|
#endif
|
|
#endif /* EnableChangePriority */
|
|
|
|
#if EnableChangePriority
|
|
LOCALVAR bool PriorityRaised = false;
|
|
#endif
|
|
|
|
#if EnableChangePriority
|
|
LOCALPROC RaisePriority(void)
|
|
{
|
|
if (! PriorityRaised) {
|
|
if (! SetPriorityClass(
|
|
GetCurrentProcess(), /* handle to the process */
|
|
HIGH_PRIORITY_CLASS
|
|
/* REALTIME_PRIORITY_CLASS (not, killer) */
|
|
/* priority class value */
|
|
))
|
|
{
|
|
/*
|
|
not recursive:
|
|
MacMsg("SetPriorityClass failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
*/
|
|
}
|
|
PriorityRaised = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if EnableChangePriority
|
|
LOCALPROC LowerPriority(void)
|
|
{
|
|
if (PriorityRaised) {
|
|
if (! SetPriorityClass(
|
|
GetCurrentProcess(), /* handle to the process */
|
|
NORMAL_PRIORITY_CLASS /* priority class value */
|
|
))
|
|
{
|
|
/*
|
|
not recursive:
|
|
MacMsg("SetPriorityClass failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
*/
|
|
}
|
|
PriorityRaised = false;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/* --- time, date, location --- */
|
|
|
|
#define dbglog_TimeStuff (0 && dbglog_HAVE)
|
|
|
|
LOCALVAR uint32_t TrueEmulatedTime = 0;
|
|
|
|
#define InvTimeDivPow 16
|
|
#define InvTimeDiv (1 << InvTimeDivPow)
|
|
#define InvTimeDivMask (InvTimeDiv - 1)
|
|
#define InvTimeStep 1089590 /* 1000 / 60.14742 * InvTimeDiv */
|
|
|
|
LOCALVAR DWORD LastTime;
|
|
|
|
LOCALVAR DWORD NextIntTime;
|
|
LOCALVAR uint32_t NextFracTime;
|
|
|
|
LOCALPROC IncrNextTime(void)
|
|
{
|
|
NextFracTime += InvTimeStep;
|
|
NextIntTime += (NextFracTime >> InvTimeDivPow);
|
|
NextFracTime &= InvTimeDivMask;
|
|
}
|
|
|
|
LOCALPROC InitNextTime(void)
|
|
{
|
|
NextIntTime = LastTime;
|
|
NextFracTime = 0;
|
|
IncrNextTime();
|
|
}
|
|
|
|
LOCALFUNC bool UpdateTrueEmulatedTime(void)
|
|
{
|
|
DWORD LatestTime;
|
|
int32_t TimeDiff;
|
|
|
|
LatestTime = timeGetTime();
|
|
if (LatestTime != LastTime) {
|
|
LastTime = LatestTime;
|
|
TimeDiff = (LatestTime - NextIntTime);
|
|
/* this should work even when time wraps */
|
|
if (TimeDiff >= 0) {
|
|
if (TimeDiff > 256) {
|
|
/* emulation interrupted, forget it */
|
|
++TrueEmulatedTime;
|
|
InitNextTime();
|
|
|
|
#if dbglog_TimeStuff
|
|
dbglog_writelnNum("emulation interrupted",
|
|
TrueEmulatedTime);
|
|
#endif
|
|
} else {
|
|
do {
|
|
++TrueEmulatedTime;
|
|
IncrNextTime();
|
|
TimeDiff = (LatestTime - NextIntTime);
|
|
} while (TimeDiff >= 0);
|
|
}
|
|
return true;
|
|
} else if (TimeDiff < -256) {
|
|
/* clock goofed if ever get here, reset */
|
|
#if dbglog_TimeStuff
|
|
dbglog_writeln("clock set back");
|
|
#endif
|
|
|
|
InitNextTime();
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
LOCALVAR uint32_t TimeSecBase;
|
|
LOCALVAR DWORD TimeMilliBase;
|
|
|
|
#include "UTIL/DATE2SEC.h"
|
|
|
|
LOCALFUNC bool CheckDateTime(void)
|
|
{
|
|
uint32_t NewMacDateInSecond;
|
|
|
|
NewMacDateInSecond =
|
|
((uint32_t)(LastTime - TimeMilliBase)) / 1000 + TimeSecBase;
|
|
if (CurMacDateInSeconds != NewMacDateInSecond) {
|
|
CurMacDateInSeconds = NewMacDateInSecond;
|
|
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
LOCALFUNC bool Init60thCheck(void)
|
|
{
|
|
SYSTEMTIME s;
|
|
#if AutoTimeZone
|
|
TIME_ZONE_INFORMATION r;
|
|
DWORD v;
|
|
#endif
|
|
DWORD t;
|
|
|
|
GetLocalTime(&s);
|
|
t = timeGetTime();
|
|
TimeSecBase = Date2MacSeconds(s.wSecond, s.wMinute, s.wHour,
|
|
s.wDay, s.wMonth, s.wYear);
|
|
TimeMilliBase = t - s.wMilliseconds;
|
|
|
|
#if AutoTimeZone
|
|
v = GetTimeZoneInformation(&r);
|
|
if ((v != 0xFFFFFFFF) && (v != TIME_ZONE_ID_UNKNOWN)) {
|
|
int32_t dlsBias = (v != TIME_ZONE_ID_DAYLIGHT)
|
|
? r.StandardBias : r.DaylightBias;
|
|
CurMacDelta = (((uint32_t)(- (r.Bias + dlsBias) * 60))
|
|
& 0x00FFFFFF)
|
|
| (((v != TIME_ZONE_ID_DAYLIGHT) ? 0 : 0x80)
|
|
<< 24);
|
|
}
|
|
#endif
|
|
|
|
LastTime = timeGetTime();
|
|
InitNextTime();
|
|
|
|
OnTrueTime = TrueEmulatedTime;
|
|
|
|
(void) CheckDateTime();
|
|
|
|
return true;
|
|
}
|
|
|
|
#ifndef TimeResolution
|
|
#define TimeResolution 3
|
|
#endif
|
|
/*
|
|
Setting TimeResolution to 1 seems to drastically slow down
|
|
the clock in Virtual PC 7.0.2 for Mac. Using 3 is more polite
|
|
anyway, and should not cause much observable difference.
|
|
*/
|
|
|
|
#if (TimeResolution != 0)
|
|
LOCALVAR bool HaveSetTimeResolution = false;
|
|
#endif
|
|
|
|
#if (TimeResolution != 0)
|
|
LOCALPROC Timer_Suspend(void)
|
|
{
|
|
if (HaveSetTimeResolution) {
|
|
(void) timeEndPeriod(TimeResolution);
|
|
HaveSetTimeResolution = false;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if (TimeResolution != 0)
|
|
LOCALPROC Timer_Resume(void)
|
|
{
|
|
TIMECAPS tc;
|
|
|
|
if (timeGetDevCaps(&tc, sizeof(TIMECAPS))
|
|
== TIMERR_NOERROR)
|
|
{
|
|
if ((TimeResolution >= tc.wPeriodMin)
|
|
&& (TimeResolution <= tc.wPeriodMax))
|
|
{
|
|
if (timeBeginPeriod(TimeResolution)
|
|
== TIMERR_NOERROR)
|
|
{
|
|
HaveSetTimeResolution = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* --- sound --- */
|
|
|
|
#if SoundEnabled
|
|
|
|
|
|
#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
|
|
#define kSoundBuffers (1 << kLn2SoundBuffers)
|
|
#define kSoundBuffMask (kSoundBuffers - 1)
|
|
|
|
#define DesiredMinFilledSoundBuffs 3
|
|
/*
|
|
if too big then sound lags behind emulation.
|
|
if too small then sound will have pauses.
|
|
*/
|
|
|
|
#define kLnOneBuffLen 9
|
|
#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
|
|
#define kOneBuffLen (1UL << kLnOneBuffLen)
|
|
#define kAllBuffLen (1UL << kLnAllBuffLen)
|
|
#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
|
|
#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
|
|
#define kOneBuffSz (1UL << kLnOneBuffSz)
|
|
#define kAllBuffSz (1UL << kLnAllBuffSz)
|
|
#define kOneBuffMask (kOneBuffLen - 1)
|
|
#define kAllBuffMask (kAllBuffLen - 1)
|
|
#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
|
|
|
|
#define dbglog_SoundStuff (0 && dbglog_HAVE)
|
|
#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
|
|
|
|
LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
|
|
LOCALVAR uint16_t ThePlayOffset;
|
|
LOCALVAR uint16_t TheFillOffset;
|
|
LOCALVAR bool wantplaying;
|
|
LOCALVAR uint16_t MinFilledSoundBuffs;
|
|
LOCALVAR uint16_t TheWriteOffset;
|
|
|
|
#define SOUND_SAMPLERATE /* 22050 */ 22255
|
|
/* = round(7833600 * 2 / 704) */
|
|
|
|
|
|
LOCALPROC FillWithSilence(tpSoundSamp p, int n, trSoundSamp v)
|
|
{
|
|
int i;
|
|
|
|
for (i = n; --i >= 0; ) {
|
|
*p++ = v;
|
|
}
|
|
}
|
|
|
|
|
|
LOCALVAR HWAVEOUT hWaveOut = NULL;
|
|
LOCALVAR WAVEHDR whdr[kSoundBuffers];
|
|
|
|
|
|
LOCALPROC Sound_BeginPlaying(void)
|
|
{
|
|
#if dbglog_SoundStuff
|
|
fprintf(stderr, "Sound_BeginPlaying\n");
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC Sound_Start(void)
|
|
{
|
|
if (hWaveOut == NULL) {
|
|
WAVEFORMATEX wfex;
|
|
MMRESULT mmr;
|
|
int i;
|
|
tpSoundSamp p;
|
|
WAVEHDR *pwh;
|
|
|
|
wfex.wFormatTag = WAVE_FORMAT_PCM;
|
|
wfex.nChannels = 1;
|
|
wfex.nSamplesPerSec = SOUND_SAMPLERATE;
|
|
wfex.nAvgBytesPerSec = SOUND_SAMPLERATE;
|
|
#if 3 == kLn2SoundSampSz
|
|
wfex.nBlockAlign = 1;
|
|
wfex.wBitsPerSample = 8;
|
|
#elif 4 == kLn2SoundSampSz
|
|
wfex.nBlockAlign = 2;
|
|
wfex.wBitsPerSample = 16;
|
|
#else
|
|
#error "unsupported audio format"
|
|
#endif
|
|
wfex.cbSize = 0;
|
|
mmr = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfex, 0,
|
|
0 /* (DWORD) AppInstance */, CALLBACK_NULL);
|
|
if (mmr != MMSYSERR_NOERROR) {
|
|
/*
|
|
not recursive:
|
|
MacMsg("waveOutOpen failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
*/
|
|
} else {
|
|
p = TheSoundBuffer;
|
|
pwh = whdr;
|
|
for (i = 0; i < kSoundBuffers; ++i) {
|
|
pwh->lpData = (LPSTR)p;
|
|
pwh->dwBufferLength = kOneBuffSz;
|
|
pwh->dwBytesRecorded = 0;
|
|
pwh->dwUser = 0;
|
|
pwh->dwFlags = 0;
|
|
pwh->dwLoops = 0;
|
|
mmr = waveOutPrepareHeader(hWaveOut, pwh,
|
|
sizeof(WAVEHDR));
|
|
if (mmr != MMSYSERR_NOERROR) {
|
|
/*
|
|
not recursive:
|
|
MacMsg("waveOutPrepareHeader failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
*/
|
|
} else {
|
|
pwh->dwFlags |= WHDR_DONE;
|
|
}
|
|
p += kOneBuffLen;
|
|
++pwh;
|
|
}
|
|
|
|
TheFillOffset = 0;
|
|
ThePlayOffset = 0;
|
|
TheWriteOffset = 0;
|
|
MinFilledSoundBuffs = kSoundBuffers;
|
|
wantplaying = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
LOCALPROC Sound_Stop(void)
|
|
{
|
|
MMRESULT mmr;
|
|
int i;
|
|
|
|
wantplaying = false;
|
|
if (hWaveOut != NULL) {
|
|
DWORD StartTime = GetTickCount();
|
|
for (i = 0; i < kSoundBuffers; ++i) {
|
|
while (((whdr[i].dwFlags & WHDR_DONE) == 0)
|
|
&& ((uint32_t)(GetTickCount() - StartTime) < 1000))
|
|
{
|
|
Sleep(1);
|
|
}
|
|
|
|
mmr = waveOutUnprepareHeader(hWaveOut, &whdr[i],
|
|
sizeof(WAVEHDR));
|
|
if (mmr != MMSYSERR_NOERROR) {
|
|
/*
|
|
not recursive:
|
|
MacMsg("waveOutUnprepareHeader failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
*/
|
|
}
|
|
}
|
|
|
|
mmr = waveOutClose(hWaveOut);
|
|
if (mmr != MMSYSERR_NOERROR) {
|
|
/*
|
|
MacMsg("waveOutClose failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
*/
|
|
}
|
|
hWaveOut = NULL;
|
|
}
|
|
}
|
|
|
|
LOCALPROC SoundCheckVeryOften(void)
|
|
{
|
|
if ((hWaveOut != NULL) && (wantplaying)) {
|
|
label_retry:
|
|
{
|
|
uint16_t FilledSoundBuffs;
|
|
uint16_t ToPlaySize = TheFillOffset - ThePlayOffset;
|
|
uint16_t CurPlayBuffer =
|
|
(ThePlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
|
|
|
|
if ((ToPlaySize > kOneBuffLen)
|
|
&& ((whdr[CurPlayBuffer].dwFlags & WHDR_DONE) != 0))
|
|
{
|
|
ThePlayOffset += kOneBuffLen;
|
|
goto label_retry;
|
|
}
|
|
FilledSoundBuffs = ToPlaySize >> kLnOneBuffLen;
|
|
|
|
if (FilledSoundBuffs < MinFilledSoundBuffs) {
|
|
MinFilledSoundBuffs = FilledSoundBuffs;
|
|
}
|
|
|
|
if (FilledSoundBuffs < 2) {
|
|
MMRESULT mmr;
|
|
uint16_t PrevPlayOffset = ThePlayOffset - kOneBuffLen;
|
|
uint16_t PrevPlayBuffer =
|
|
(PrevPlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
|
|
uint16_t LastPlayedOffset =
|
|
((TheFillOffset >> kLnOneBuffLen) << kLnOneBuffLen)
|
|
- 1;
|
|
|
|
FillWithSilence(
|
|
TheSoundBuffer + (PrevPlayOffset & kAllBuffMask),
|
|
kOneBuffLen,
|
|
*(TheSoundBuffer
|
|
+ (LastPlayedOffset & kAllBuffMask)));
|
|
mmr = waveOutWrite(
|
|
hWaveOut, &whdr[PrevPlayBuffer], sizeof(WAVEHDR));
|
|
if (mmr != MMSYSERR_NOERROR) {
|
|
whdr[PrevPlayBuffer].dwFlags |= WHDR_DONE;
|
|
/*
|
|
not recursive:
|
|
MacMsg("waveOutWrite failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
*/
|
|
}
|
|
ThePlayOffset = PrevPlayOffset;
|
|
goto label_retry;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 4 == kLn2SoundSampSz
|
|
LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
|
|
{
|
|
int i;
|
|
|
|
for (i = kOneBuffLen; --i >= 0; ) {
|
|
*p++ -= 0x8000;
|
|
}
|
|
}
|
|
#else
|
|
#define ConvertSoundBlockToNative(p)
|
|
#endif
|
|
|
|
LOCALPROC Sound_FilledBlocks(void)
|
|
{
|
|
while (0 != ((TheWriteOffset - TheFillOffset) >> kLnOneBuffLen)) {
|
|
uint16_t CurFillBuffer =
|
|
(TheFillOffset >> kLnOneBuffLen) & kSoundBuffMask;
|
|
bool IsOk = false;
|
|
|
|
ConvertSoundBlockToNative((tpSoundSamp)
|
|
whdr[CurFillBuffer].lpData);
|
|
|
|
if (hWaveOut != NULL) {
|
|
MMRESULT mmr = waveOutWrite(hWaveOut,
|
|
&whdr[CurFillBuffer], sizeof(WAVEHDR));
|
|
if (mmr == MMSYSERR_NOERROR) {
|
|
IsOk = true;
|
|
}
|
|
}
|
|
|
|
if (! IsOk) {
|
|
/*
|
|
not recursive:
|
|
MacMsg("waveOutWrite failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
*/
|
|
whdr[CurFillBuffer].dwFlags |= WHDR_DONE;
|
|
}
|
|
|
|
TheFillOffset += kOneBuffLen;
|
|
}
|
|
}
|
|
|
|
LOCALPROC Sound_WroteABlock(void)
|
|
{
|
|
if (wantplaying) {
|
|
Sound_FilledBlocks();
|
|
} else if (((TheWriteOffset - ThePlayOffset) >> kLnOneBuffLen) < 12)
|
|
{
|
|
/* just wait */
|
|
} else {
|
|
Sound_FilledBlocks();
|
|
wantplaying = true;
|
|
Sound_BeginPlaying();
|
|
}
|
|
}
|
|
|
|
GLOBALOSGLUPROC Sound_EndWrite(uint16_t actL)
|
|
{
|
|
TheWriteOffset += actL;
|
|
|
|
if (0 == (TheWriteOffset & kOneBuffMask)) {
|
|
/* just finished a block */
|
|
|
|
Sound_WroteABlock();
|
|
}
|
|
}
|
|
|
|
GLOBALOSGLUFUNC tpSoundSamp Sound_BeginWrite(uint16_t n, uint16_t *actL)
|
|
{
|
|
uint16_t ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
|
|
uint16_t WriteBuffContig =
|
|
kOneBuffLen - (TheWriteOffset & kOneBuffMask);
|
|
|
|
if (WriteBuffContig < n) {
|
|
n = WriteBuffContig;
|
|
}
|
|
if (ToFillLen < n) {
|
|
/* overwrite previous buffer */
|
|
TheWriteOffset -= kOneBuffLen;
|
|
}
|
|
|
|
*actL = n;
|
|
return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
|
|
}
|
|
|
|
LOCALPROC Sound_SecondNotify(void)
|
|
{
|
|
if (hWaveOut != NULL) {
|
|
if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
|
|
#if dbglog_SoundStuff
|
|
dbglog_writeln("MinFilledSoundBuffs too high");
|
|
#endif
|
|
IncrNextTime();
|
|
} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
|
|
#if dbglog_SoundStuff
|
|
dbglog_writeln("MinFilledSoundBuffs too low");
|
|
#endif
|
|
++TrueEmulatedTime;
|
|
}
|
|
MinFilledSoundBuffs = kSoundBuffers;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/* --- overall grab --- */
|
|
|
|
#if MayFullScreen
|
|
LOCALPROC GrabTheMachine(void)
|
|
{
|
|
#if EnableFSMouseMotion
|
|
StartSaveMouseMotion();
|
|
#endif
|
|
#if EnableChangePriority
|
|
if ((uint8_t) -1 == SpeedValue) {
|
|
RaisePriority();
|
|
}
|
|
#endif
|
|
#if EnableGrabSpecialKeys
|
|
GrabSpecialKeys();
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
LOCALPROC UnGrabTheMachine(void)
|
|
{
|
|
#if EnableGrabSpecialKeys
|
|
UnGrabSpecialKeys();
|
|
#endif
|
|
#if EnableFSMouseMotion
|
|
StopSaveMouseMotion();
|
|
#endif
|
|
#if EnableChangePriority
|
|
LowerPriority();
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
LOCALVAR bool GrabMachine = false;
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
LOCALPROC AdjustMachineGrab(void)
|
|
{
|
|
if (GrabMachine) {
|
|
if (MainWnd != NULL) {
|
|
GrabTheMachine();
|
|
}
|
|
} else {
|
|
UnGrabTheMachine();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* --- basic dialogs --- */
|
|
|
|
LOCALPROC MyBeginDialog(void)
|
|
{
|
|
DisconnectKeyCodes3();
|
|
#if MayFullScreen
|
|
GrabMachine = false;
|
|
UnGrabTheMachine();
|
|
#endif
|
|
ForceShowCursor();
|
|
}
|
|
|
|
LOCALPROC MyEndDialog(void)
|
|
{
|
|
ReconnectKeyCodes3();
|
|
}
|
|
|
|
LOCALPROC CheckSavedMacMsg(void)
|
|
{
|
|
if (nullpr != SavedBriefMsg) {
|
|
TCHAR briefMsg0[ClStrMaxLength + 1];
|
|
TCHAR longMsg0[ClStrMaxLength + 1];
|
|
|
|
NativeStrFromCStr(briefMsg0, SavedBriefMsg, false);
|
|
NativeStrFromCStr(longMsg0, SavedLongMsg, false);
|
|
|
|
MessageBox(MainWnd, longMsg0, briefMsg0,
|
|
MB_APPLMODAL | MB_OK | (SavedFatalMsg ? MB_ICONSTOP : 0));
|
|
|
|
SavedBriefMsg = nullpr;
|
|
}
|
|
}
|
|
|
|
/* --- main window --- */
|
|
|
|
enum {
|
|
ID_MENU_NULL = 256,
|
|
ID_FILE_INSERTDISK1,
|
|
ID_FILE_QUIT,
|
|
ID_SPECIAL_MORECOMMANDS,
|
|
ID_HELP_ABOUT,
|
|
|
|
kNum_ID_MENU
|
|
};
|
|
|
|
|
|
#define EnableScalingBuff 1
|
|
LOCALVAR uint8_t * ScalingBuff = NULL;
|
|
|
|
LOCALVAR HDC MainWndDC = NULL;
|
|
|
|
LOCALVAR int32_t CmdShow;
|
|
|
|
LOCALVAR TCHAR WndTitle[_MAX_PATH];
|
|
LOCALVAR const TCHAR WndClassName[] = TEXT("minivmac");
|
|
|
|
LOCALVAR bool gBackgroundFlag = false;
|
|
LOCALVAR bool gTrueBackgroundFlag = false;
|
|
LOCALVAR bool CurSpeedStopped = true;
|
|
|
|
LOCALPROC GetWndTitle(void)
|
|
{
|
|
TCHAR pathName[_MAX_PATH];
|
|
WIN32_FIND_DATA fd;
|
|
bool IsOk = false;
|
|
|
|
if (GetModuleFileName(AppInstance, pathName, _MAX_PATH) != 0) {
|
|
HANDLE hf = FindFirstFile(pathName, &fd);
|
|
|
|
if (hf != INVALID_HANDLE_VALUE) {
|
|
/* get rid of extension, presumably '.exe' */
|
|
LPTSTR p = FindLastTerm(fd.cFileName,
|
|
(TCHAR)('.'));
|
|
if (p != nullpr) {
|
|
*--p = (TCHAR)('\0');
|
|
}
|
|
|
|
_tcscpy(WndTitle, fd.cFileName);
|
|
IsOk = true;
|
|
FindClose(hf);
|
|
}
|
|
}
|
|
if (! IsOk) {
|
|
_tcscpy(WndTitle, TEXT(kStrAppName));
|
|
}
|
|
}
|
|
|
|
LOCALPROC DisposeMainWindow(void)
|
|
{
|
|
#if UseWinCE
|
|
/* Show the taskbar */
|
|
SHFullScreen(MainWnd, SHFS_SHOWTASKBAR);
|
|
#endif
|
|
|
|
if (MainWndDC != NULL) {
|
|
ReleaseDC(MainWnd, MainWndDC);
|
|
}
|
|
if (MainWnd != NULL) {
|
|
DestroyWindow(MainWnd);
|
|
MainWnd = NULL; /* so MacMsg will still work */
|
|
}
|
|
}
|
|
|
|
enum {
|
|
kMagStateNormal,
|
|
#if EnableMagnify
|
|
kMagStateMagnifgy,
|
|
#endif
|
|
kNumMagStates
|
|
};
|
|
|
|
#define kMagStateAuto kNumMagStates
|
|
|
|
#if MayNotFullScreen
|
|
LOCALVAR int CurWinIndx;
|
|
LOCALVAR bool HavePositionWins[kNumMagStates];
|
|
LOCALVAR POINT WinPositionWins[kNumMagStates];
|
|
#endif
|
|
|
|
#if MayNotFullScreen
|
|
LOCALPROC AppendConvertMenuItem(HMENU hMenu,
|
|
UINT uIDNewItem, char *s, bool AddEllipsis)
|
|
{
|
|
TCHAR ts[ClStrMaxLength + 1];
|
|
|
|
NativeStrFromCStr(ts, s, AddEllipsis);
|
|
|
|
(void) AppendMenu(hMenu, MF_ENABLED + MF_STRING,
|
|
uIDNewItem, ts);
|
|
}
|
|
#endif
|
|
|
|
#if MayNotFullScreen
|
|
LOCALPROC AppendSubmenuConvertName(HMENU hMenu,
|
|
HMENU hSubMenu, char *s)
|
|
{
|
|
TCHAR ts[ClStrMaxLength + 1];
|
|
MENUITEMINFO mii;
|
|
|
|
NativeStrFromCStr(ts, s, false);
|
|
|
|
#if 0
|
|
(void) InsertMenu(hMenu, 0xFFFFFFFF,
|
|
MF_BYPOSITION + MF_POPUP + MF_STRING + MF_ENABLED,
|
|
(UINT)hSubMenu, ts);
|
|
#endif
|
|
|
|
memset(&mii, 0, sizeof(MENUITEMINFO));
|
|
mii.cbSize = sizeof(MENUITEMINFO);
|
|
mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
|
|
mii.fType = MFT_STRING;
|
|
mii.hSubMenu = hSubMenu;
|
|
mii.dwTypeData = ts;
|
|
mii.cch = (UINT)_tcslen(ts);
|
|
(void) InsertMenuItem(hMenu, (UINT) -1, TRUE,
|
|
&mii);
|
|
}
|
|
#endif
|
|
|
|
#ifndef kStrMenuFile_win
|
|
#define kStrMenuFile_win kStrMenuFile
|
|
#endif
|
|
|
|
LOCALFUNC bool ReCreateMainWindow(void)
|
|
{
|
|
#if MayNotFullScreen
|
|
HMENU m;
|
|
int DfltWndX;
|
|
int DfltWndY;
|
|
int WinIndx;
|
|
#endif
|
|
HMENU mb;
|
|
HWND NewMainWindow;
|
|
HDC NewMainWndDC = NULL;
|
|
int ScreenX = GetSystemMetrics(SM_CXSCREEN);
|
|
int ScreenY = GetSystemMetrics(SM_CYSCREEN);
|
|
short NewWindowHeight = vMacScreenHeight;
|
|
short NewWindowWidth = vMacScreenWidth;
|
|
HWND OldMainWindow = MainWnd;
|
|
HDC OldMainWndDC = MainWndDC;
|
|
RECT NewWinR;
|
|
DWORD WStyle;
|
|
DWORD WExStyle;
|
|
|
|
#if VarFullScreen
|
|
if (! UseFullScreen)
|
|
#endif
|
|
#if MayNotFullScreen
|
|
{
|
|
/* save old position */
|
|
if (OldMainWindow != NULL) {
|
|
WinPositionWins[CurWinIndx].x = WndX;
|
|
WinPositionWins[CurWinIndx].y = WndY;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if MayNotFullScreen
|
|
#if EnableMagnify
|
|
if (WantMagnify) {
|
|
WinIndx = kMagStateMagnifgy;
|
|
} else
|
|
#endif
|
|
{
|
|
WinIndx = kMagStateNormal;
|
|
}
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
if (WantMagnify) {
|
|
NewWindowHeight *= WindowScale;
|
|
NewWindowWidth *= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
if (WantFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
WStyle = WS_VISIBLE | WS_POPUP;
|
|
WExStyle = WS_EX_TOPMOST;
|
|
|
|
hOffset = (ScreenX - NewWindowWidth) / 2;
|
|
vOffset = (ScreenY - NewWindowHeight) / 2;
|
|
if (hOffset < 0) {
|
|
hOffset = 0;
|
|
}
|
|
if (vOffset < 0) {
|
|
vOffset = 0;
|
|
}
|
|
|
|
NewWinR.left = 0;
|
|
NewWinR.top = 0;
|
|
NewWinR.right = ScreenX;
|
|
NewWinR.bottom = ScreenY;
|
|
}
|
|
#endif
|
|
#if VarFullScreen
|
|
else
|
|
#endif
|
|
#if MayNotFullScreen
|
|
{
|
|
WStyle = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
|
|
| WS_MINIMIZEBOX;
|
|
WExStyle = WS_EX_ACCEPTFILES;
|
|
|
|
DfltWndX = (ScreenX - NewWindowWidth) / 2;
|
|
DfltWndY = (ScreenY - NewWindowHeight) / 2;
|
|
|
|
if (DfltWndX < 0) {
|
|
DfltWndX = 0;
|
|
}
|
|
if (DfltWndY < 0) {
|
|
DfltWndY = 0;
|
|
}
|
|
|
|
if (! HavePositionWins[WinIndx]) {
|
|
WinPositionWins[WinIndx].x = DfltWndX;
|
|
WinPositionWins[WinIndx].y = DfltWndY;
|
|
HavePositionWins[WinIndx] = true;
|
|
}
|
|
|
|
NewWinR.left = WinPositionWins[WinIndx].x;
|
|
NewWinR.top = WinPositionWins[WinIndx].y;
|
|
NewWinR.right = NewWinR.left + NewWindowWidth;
|
|
NewWinR.bottom = NewWinR.top + NewWindowHeight;
|
|
|
|
(void) AdjustWindowRectEx(&NewWinR, WStyle, TRUE, WExStyle);
|
|
|
|
if ((NewWinR.right <= 0)
|
|
|| (NewWinR.left >= ScreenX)
|
|
|| (NewWinR.bottom <= 0)
|
|
|| (NewWinR.top >= ScreenY))
|
|
{
|
|
NewWinR.left = DfltWndX;
|
|
NewWinR.top = DfltWndY;
|
|
NewWinR.right = DfltWndX + NewWindowWidth;
|
|
NewWinR.bottom = DfltWndY + NewWindowHeight;
|
|
|
|
(void) AdjustWindowRectEx(&NewWinR,
|
|
WStyle, TRUE, WExStyle);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if ((OldMainWindow == NULL)
|
|
#if VarFullScreen
|
|
|| (WantFullScreen != UseFullScreen)
|
|
#endif
|
|
)
|
|
{
|
|
|
|
#if VarFullScreen
|
|
if (WantFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
mb = NULL;
|
|
}
|
|
#endif
|
|
#if VarFullScreen
|
|
else
|
|
#endif
|
|
#if MayNotFullScreen
|
|
{
|
|
mb = CreateMenu();
|
|
if (mb != NULL) {
|
|
m = CreateMenu();
|
|
if (m != NULL) {
|
|
AppendConvertMenuItem(m, ID_FILE_INSERTDISK1,
|
|
kStrMenuItemOpen, true);
|
|
(void) AppendMenu(m, MF_SEPARATOR, 0, NULL);
|
|
AppendConvertMenuItem(m, ID_FILE_QUIT,
|
|
kStrMenuItemQuit, false);
|
|
AppendSubmenuConvertName(mb, m, kStrMenuFile_win);
|
|
}
|
|
m = CreateMenu();
|
|
if (m != NULL) {
|
|
AppendConvertMenuItem(m, ID_SPECIAL_MORECOMMANDS,
|
|
kStrMenuItemMore, true);
|
|
AppendSubmenuConvertName(mb, m, kStrMenuSpecial);
|
|
}
|
|
m = CreateMenu();
|
|
if (m != NULL) {
|
|
AppendConvertMenuItem(m, ID_HELP_ABOUT,
|
|
kStrMenuItemAbout, true);
|
|
AppendSubmenuConvertName(mb, m, kStrMenuHelp);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
NewMainWindow = CreateWindowEx(
|
|
WExStyle,
|
|
WndClassName,
|
|
WndTitle,
|
|
WStyle,
|
|
NewWinR.left, NewWinR.top,
|
|
NewWinR.right - NewWinR.left, NewWinR.bottom - NewWinR.top,
|
|
NULL,
|
|
mb,
|
|
AppInstance, NULL);
|
|
if (NewMainWindow == NULL) {
|
|
MacMsg("CreateWindow failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
return false;
|
|
}
|
|
|
|
NewMainWndDC = GetDC(NewMainWindow);
|
|
if (NewMainWndDC == NULL) {
|
|
MacMsg("GetDC failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
DestroyWindow(NewMainWindow);
|
|
return false;
|
|
}
|
|
} else {
|
|
NewMainWndDC = OldMainWndDC;
|
|
NewMainWindow = OldMainWindow;
|
|
(void) MoveWindow(NewMainWindow, NewWinR.left, NewWinR.top,
|
|
NewWinR.right - NewWinR.left, NewWinR.bottom - NewWinR.top,
|
|
TRUE);
|
|
}
|
|
|
|
if (0 != vMacScreenDepth) {
|
|
ColorModeWorks = true;
|
|
}
|
|
|
|
{
|
|
POINT p;
|
|
|
|
/*
|
|
Find out where the window really went, on
|
|
the off chance that the WM_MOVE message wasn't
|
|
called on CreateWindowEx/MoveWindow, or that
|
|
the window wasn't put where asked for.
|
|
*/
|
|
p.x = 0;
|
|
p.y = 0;
|
|
(void) MapWindowPoints(NewMainWindow, NULL, &p, 1);
|
|
WndX = (int16_t)p.x;
|
|
WndY = (int16_t)p.y;
|
|
}
|
|
|
|
#if MayFullScreen
|
|
GrabMachine = false;
|
|
UnGrabTheMachine();
|
|
#endif
|
|
|
|
#if UseWinCE && 0
|
|
/* Show the taskbar */
|
|
SHFullScreen(MainWnd, SHFS_SHOWTASKBAR);
|
|
#endif
|
|
|
|
#if MayNotFullScreen
|
|
CurWinIndx = WinIndx;
|
|
#endif
|
|
|
|
MainWnd = NewMainWindow;
|
|
MainWndDC = NewMainWndDC;
|
|
gTrueBackgroundFlag = false;
|
|
#if VarFullScreen
|
|
UseFullScreen = WantFullScreen;
|
|
#endif
|
|
#if EnableMagnify
|
|
UseMagnify = WantMagnify;
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
ViewHSize = ScreenX;
|
|
ViewVSize = ScreenY;
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
ViewHSize /= WindowScale;
|
|
ViewVSize /= WindowScale;
|
|
}
|
|
#endif
|
|
if (ViewHSize >= vMacScreenWidth) {
|
|
ViewHStart = 0;
|
|
ViewHSize = vMacScreenWidth;
|
|
} else {
|
|
ViewHSize &= ~ 1;
|
|
}
|
|
if (ViewVSize >= vMacScreenHeight) {
|
|
ViewVStart = 0;
|
|
ViewVSize = vMacScreenHeight;
|
|
} else {
|
|
ViewVSize &= ~ 1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (NewMainWindow != OldMainWindow) {
|
|
ShowWindow(NewMainWindow, SW_SHOW /* CmdShow */);
|
|
if (OldMainWndDC != NULL) {
|
|
ReleaseDC(MainWnd, OldMainWndDC);
|
|
}
|
|
if (OldMainWindow != NULL) {
|
|
/* ShowWindow(OldMainWindow, SW_HIDE); */
|
|
DestroyWindow(OldMainWindow);
|
|
}
|
|
|
|
DisconnectKeyCodes3();
|
|
/* since key events per window */
|
|
} else {
|
|
(void) InvalidateRgn(MainWnd, NULL, FALSE);
|
|
}
|
|
|
|
#if UseWinCE
|
|
/* Create and set logical palette for this window */
|
|
{
|
|
HPALETTE hpal;
|
|
LOGPALETTE *lppal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
|
|
sizeof(PALETTEENTRY) * 2);
|
|
|
|
if (! lppal)
|
|
{
|
|
MacMsg("CreateWindow failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
return false;
|
|
}
|
|
|
|
lppal->palNumEntries = 2;
|
|
lppal->palVersion = 0x0300;
|
|
lppal->palPalEntry[0].peRed = 255;
|
|
lppal->palPalEntry[0].peGreen = 255;
|
|
lppal->palPalEntry[0].peBlue = 255;
|
|
lppal->palPalEntry[0].peFlags = 0;
|
|
lppal->palPalEntry[1].peRed = 0;
|
|
lppal->palPalEntry[1].peGreen = 0;
|
|
lppal->palPalEntry[1].peBlue = 0;
|
|
lppal->palPalEntry[1].peFlags = 0;
|
|
|
|
hpal = CreatePalette(lppal);
|
|
|
|
if (hpal == NULL) {
|
|
free(lppal);
|
|
MacMsg("CreateWindow failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
return false;
|
|
}
|
|
|
|
if (SelectPalette(MainWndDC, hpal, FALSE) == NULL) {
|
|
free(lppal);
|
|
MacMsg("CreateWindow failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
return false;
|
|
}
|
|
|
|
if (RealizePalette(MainWndDC) == GDI_ERROR) {
|
|
free(lppal);
|
|
MacMsg("CreateWindow failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
return false;
|
|
}
|
|
|
|
free(lppal);
|
|
}
|
|
#endif
|
|
|
|
#if UseWinCE
|
|
/* Hide the taskbar */
|
|
SHFullScreen(MainWnd, SHFS_HIDETASKBAR);
|
|
(void) MoveWindow(MainWnd, 0, 0,
|
|
ScreenX, ScreenY, TRUE);
|
|
#endif
|
|
|
|
if (HaveCursorHidden) {
|
|
(void) MoveMouse(CurMouseH, CurMouseV);
|
|
WantCursorHidden = true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#if UseWinCE
|
|
LOCALFUNC bool AlreadyRunningCheck(void)
|
|
{
|
|
/*
|
|
Adapted from example program from Microsoft eMbedded Visual C++
|
|
*/
|
|
|
|
/* If it is already running, then focus on the window */
|
|
HWND hWnd = FindWindow(WndClassName, WndTitle);
|
|
if (hWnd == NULL) {
|
|
return false;
|
|
} else {
|
|
/*
|
|
Set focus to foremost child window.
|
|
The "| 0x01" is used to bring any owned
|
|
windows to the foreground and activate them.
|
|
*/
|
|
SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001));
|
|
return true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
typedef struct BITMAPINFOHEADER256 {
|
|
BITMAPINFOHEADER bmi;
|
|
RGBQUAD colors[CLUT_size];
|
|
//RGBQUAD colors[2];
|
|
} BITMAPINFOHEADER256;
|
|
|
|
#if EnableMagnify
|
|
#define ScaledHeight (WindowScale * vMacScreenHeight)
|
|
#define ScaledWidth (WindowScale * vMacScreenWidth)
|
|
#endif
|
|
|
|
LOCALPROC HaveChangedScreenBuff(int16_t top, int16_t left,
|
|
int16_t bottom, int16_t right)
|
|
{
|
|
BITMAPINFOHEADER256 bmh;
|
|
uint8_t *cdb = GetCurDrawBuff();
|
|
int XDest;
|
|
int YDest;
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
if (top < ViewVStart) {
|
|
top = ViewVStart;
|
|
}
|
|
if (left < ViewHStart) {
|
|
left = ViewHStart;
|
|
}
|
|
if (bottom > ViewVStart + ViewVSize) {
|
|
bottom = ViewVStart + ViewVSize;
|
|
}
|
|
if (right > ViewHStart + ViewHSize) {
|
|
right = ViewHStart + ViewHSize;
|
|
}
|
|
|
|
if ((top >= bottom) || (left >= right)) {
|
|
goto label_exit;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
XDest = left;
|
|
YDest = top;
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
XDest -= ViewHStart;
|
|
YDest -= ViewVStart;
|
|
}
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
XDest *= WindowScale;
|
|
YDest *= WindowScale;
|
|
}
|
|
#endif
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
XDest += hOffset;
|
|
YDest += vOffset;
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
{ /* testing code */
|
|
if (PatBlt(MainWndDC,
|
|
(int)left - 1,
|
|
(int)top - 1,
|
|
(int)right - left + 2,
|
|
(int)bottom - top + 2, PATCOPY)) {
|
|
}
|
|
}
|
|
#endif
|
|
if (vMacScreenDepth > 0 && UseColorMode) {
|
|
int i;
|
|
int nDestWidth = (right - left);
|
|
int nDestHeight = (bottom - top);
|
|
uint8_t *p;
|
|
if (vMacScreenDepth == 1) {
|
|
p = ScalingBuff + ((uint32_t)vMacScreenWidth / 4) * top;
|
|
} else if (vMacScreenDepth >= 4) {
|
|
p = ScalingBuff + (uint32_t)vMacScreenByteWidth * top;
|
|
} else {
|
|
p = cdb + (uint32_t)vMacScreenByteWidth * top;
|
|
}
|
|
|
|
memset(&bmh, 0, sizeof (bmh));
|
|
bmh.bmi.biSize = sizeof(BITMAPINFOHEADER);
|
|
bmh.bmi.biWidth = vMacScreenWidth;
|
|
bmh.bmi.biHeight = - (bottom - top);
|
|
bmh.bmi.biPlanes = 1;
|
|
if (1 == vMacScreenDepth) {
|
|
bmh.bmi.biBitCount = 4;
|
|
} else {
|
|
bmh.bmi.biBitCount = (1 << vMacScreenDepth);
|
|
}
|
|
bmh.bmi.biCompression= BI_RGB;
|
|
bmh.bmi.biSizeImage = 0;
|
|
bmh.bmi.biXPelsPerMeter = 0;
|
|
bmh.bmi.biYPelsPerMeter = 0;
|
|
if (vMacScreenDepth == 1) {
|
|
bmh.bmi.biClrUsed = 4;
|
|
} else {
|
|
bmh.bmi.biClrUsed = 0;
|
|
}
|
|
bmh.bmi.biClrImportant = 0;
|
|
|
|
if (vMacScreenDepth < 4) {
|
|
for (i = 0; i < CLUT_size; ++i) {
|
|
bmh.colors[i].rgbRed = CLUT_reds[i] >> 8;
|
|
bmh.colors[i].rgbGreen = CLUT_greens[i] >> 8;
|
|
bmh.colors[i].rgbBlue = CLUT_blues[i] >> 8;
|
|
bmh.colors[i].rgbReserved = 0;
|
|
}
|
|
}
|
|
|
|
if (1 == vMacScreenDepth) {
|
|
int j;
|
|
uint8_t *p1 = (uint8_t *)(cdb + (uint32_t)vMacScreenByteWidth * top);
|
|
uint16_t *p2 = (uint16_t *)p;
|
|
for (i = bottom - top; --i >= 0; ) {
|
|
for (j = vMacScreenWidth / 4; --j >= 0; ) {
|
|
uint16_t t0 = *p1++;
|
|
*p2 ++
|
|
= ((t0 & 0xC0) >> 2)
|
|
| ((t0 & 0x30) >> 4)
|
|
| ((t0 & 0x0C) << 10)
|
|
| ((t0 & 0x03) << 8);
|
|
}
|
|
}
|
|
} else if (4 == vMacScreenDepth) {
|
|
int j;
|
|
uint16_t *p1 = (uint16_t *)(cdb + (uint32_t)vMacScreenByteWidth * top);
|
|
uint16_t *p2 = (uint16_t *)p;
|
|
for (i = bottom - top; --i >= 0; ) {
|
|
for (j = vMacScreenWidth; --j >= 0; ) {
|
|
uint16_t t0 = *p1++;
|
|
*p2 ++ =
|
|
((t0 & 0xFF00) >> 8) | ((t0 & 0x00FF) << 8);
|
|
}
|
|
}
|
|
} else if (5 == vMacScreenDepth) {
|
|
int j;
|
|
uint32_t *p1 = (uint32_t *)(cdb + (uint32_t)vMacScreenByteWidth * top);
|
|
uint32_t *p2 = (uint32_t *)p;
|
|
for (i = bottom - top; --i >= 0; ) {
|
|
for (j = vMacScreenWidth; --j >= 0; ) {
|
|
uint32_t t0 = *p1++;
|
|
*p2++
|
|
= ((t0 & 0xFF000000) >> 24)
|
|
| ((t0 & 0x00FF0000) >> 8)
|
|
| ((t0 & 0x0000FF00) << 8)
|
|
| ((t0 & 0x000000FF) << 24);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
nDestWidth *= WindowScale;
|
|
nDestHeight *= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
if (StretchDIBits(
|
|
MainWndDC, /* handle of device context */
|
|
XDest,
|
|
/* x-coordinate of upper-left corner of dest. rect. */
|
|
YDest,
|
|
/* y-coordinate of upper-left corner of dest. rect. */
|
|
nDestWidth, /* dest. rectangle width */
|
|
nDestHeight, /* dest. rectangle height */
|
|
left,
|
|
/* x-coordinate of lower-left corner of source rect. */
|
|
0, /* y-coordinate of lower-left corner of source rect. */
|
|
(right - left), /* source rectangle width */
|
|
(bottom - top), /* source rectangle height */
|
|
(CONST VOID *)p, /* address of array with DIB bits */
|
|
(const struct tagBITMAPINFO *)&bmh,
|
|
/* address of structure with bitmap info. */
|
|
DIB_RGB_COLORS, /* RGB or palette indices */
|
|
SRCCOPY
|
|
) == 0) {
|
|
/* ReportWinLastError(); */
|
|
}
|
|
} else {
|
|
uint8_t *p = cdb + (uint32_t)vMacScreenMonoByteWidth * top;
|
|
|
|
memset(&bmh, 0, sizeof (bmh));
|
|
bmh.bmi.biSize = sizeof(BITMAPINFOHEADER);
|
|
bmh.bmi.biWidth = vMacScreenWidth;
|
|
bmh.bmi.biHeight = - (bottom - top);
|
|
bmh.bmi.biPlanes = 1;
|
|
bmh.bmi.biBitCount = 1;
|
|
bmh.bmi.biCompression= BI_RGB;
|
|
bmh.bmi.biSizeImage = 0;
|
|
bmh.bmi.biXPelsPerMeter = 0;
|
|
bmh.bmi.biYPelsPerMeter = 0;
|
|
bmh.bmi.biClrUsed = 0;
|
|
bmh.bmi.biClrImportant = 0;
|
|
#if ! UseWinCE
|
|
bmh.colors[0].rgbRed = 255;
|
|
bmh.colors[0].rgbGreen = 255;
|
|
bmh.colors[0].rgbBlue = 255;
|
|
bmh.colors[0].rgbReserved = 0;
|
|
bmh.colors[1].rgbRed = 0;
|
|
bmh.colors[1].rgbGreen = 0;
|
|
bmh.colors[1].rgbBlue = 0;
|
|
bmh.colors[1].rgbReserved = 0;
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
#if EnableScalingBuff
|
|
if (ScalingBuff != NULL) {
|
|
int i;
|
|
int j;
|
|
int k;
|
|
uint16_t left1 = left & (~ 7);
|
|
uint16_t right1 = (right + 7) & (~ 7);
|
|
uint16_t jn = (right1 - left1) / 8;
|
|
uint8_t *p1 =
|
|
cdb + ((left1 + vMacScreenWidth * (uint32_t)top) / 8);
|
|
uint8_t *p2 = ScalingBuff
|
|
/*
|
|
+ ((left1 + vMacScreenWidth * WindowScale
|
|
* (uint32_t)top)
|
|
* WindowScale / 8)
|
|
*/
|
|
;
|
|
uint8_t *p3;
|
|
uint8_t t0;
|
|
uint8_t t1;
|
|
uint8_t t2;
|
|
uint8_t m;
|
|
|
|
for (i = bottom - top; --i >= 0; ) {
|
|
p3 = p2;
|
|
for (j = jn; --j >= 0; ) {
|
|
t0 = *p1++;
|
|
t1 = t0;
|
|
m = 0x80;
|
|
t2 = 0;
|
|
for (k = 4; --k >= 0; ) {
|
|
t2 |= t1 & m;
|
|
t1 >>= 1;
|
|
m >>= 2;
|
|
}
|
|
*p2++ = t2 | (t2 >> 1);
|
|
|
|
t1 = t0 << 4;
|
|
m = 0x80;
|
|
t2 = 0;
|
|
for (k = 4; --k >= 0; ) {
|
|
t2 |= t1 & m;
|
|
t1 >>= 1;
|
|
m >>= 2;
|
|
}
|
|
*p2++ = t2 | (t2 >> 1);
|
|
}
|
|
p1 += vMacScreenWidth / 8 - jn;
|
|
p2 += ScaledWidth / 8 - (WindowScale * jn);
|
|
for (j = WindowScale * jn; --j >= 0; ) {
|
|
*p2++ = *p3++;
|
|
}
|
|
p2 += ScaledWidth / 8 - (WindowScale * jn);
|
|
}
|
|
|
|
bmh.bmi.biWidth = vMacScreenWidth * WindowScale;
|
|
bmh.bmi.biHeight = - ((bottom - top) * WindowScale);
|
|
if (SetDIBitsToDevice(
|
|
MainWndDC, /* handle of device context */
|
|
XDest,
|
|
/*
|
|
x-coordinate of upper-left corner
|
|
of dest. rect.
|
|
*/
|
|
YDest,
|
|
/*
|
|
y-coordinate of upper-left corner
|
|
of dest. rect.
|
|
*/
|
|
(right - left) * WindowScale,
|
|
/* source rectangle width */
|
|
(bottom - top) * WindowScale,
|
|
/* source rectangle height */
|
|
(left & 7) * WindowScale,
|
|
/*
|
|
x-coordinate of lower-left corner
|
|
of source rect.
|
|
*/
|
|
0,
|
|
/*
|
|
y-coordinate of lower-left corner
|
|
of source rect.
|
|
*/
|
|
0, /* first scan line in array */
|
|
(bottom - top) * WindowScale,
|
|
/* number of scan lines */
|
|
(CONST VOID *)ScalingBuff,
|
|
/* address of array with DIB bits */
|
|
(const struct tagBITMAPINFO *)&bmh,
|
|
/* address of structure with bitmap info. */
|
|
#if ! UseWinCE
|
|
DIB_RGB_COLORS /* RGB or palette indices */
|
|
#else
|
|
DIB_PAL_COLORS /* palette indices */
|
|
#endif
|
|
) == 0) {
|
|
/* ReportWinLastError(); */
|
|
}
|
|
}
|
|
#else
|
|
if (StretchDIBits(
|
|
MainWndDC, /* handle of device context */
|
|
XDest,
|
|
/*
|
|
x-coordinate of upper-left corner of dest. rect.
|
|
*/
|
|
YDest,
|
|
/*
|
|
y-coordinate of upper-left corner of dest. rect.
|
|
*/
|
|
(right - left) * WindowScale,
|
|
/* dest. rectangle width */
|
|
(bottom - top) * WindowScale,
|
|
/* dest. rectangle height */
|
|
left,
|
|
/*
|
|
x-coordinate of lower-left corner
|
|
of source rect.
|
|
*/
|
|
0,
|
|
/*
|
|
y-coordinate of lower-left corner
|
|
of source rect.
|
|
*/
|
|
(right - left), /* source rectangle width */
|
|
(bottom - top), /* source rectangle height */
|
|
(CONST VOID *)p, /* address of array with DIB bits */
|
|
(const struct tagBITMAPINFO *)&bmh,
|
|
/* address of structure with bitmap info. */
|
|
#if ! UseWinCE
|
|
DIB_RGB_COLORS, /* RGB or palette indices */
|
|
#else
|
|
DIB_PAL_COLORS, /* palette indices */
|
|
#endif
|
|
SRCCOPY
|
|
) == 0) {
|
|
/* ReportWinLastError(); */
|
|
}
|
|
#endif
|
|
} else
|
|
#endif
|
|
|
|
{
|
|
if (SetDIBitsToDevice(
|
|
MainWndDC, /* handle of device context */
|
|
XDest,
|
|
/*
|
|
x-coordinate of upper-left corner of dest. rect.
|
|
*/
|
|
YDest,
|
|
/*
|
|
y-coordinate of upper-left corner of dest. rect.
|
|
*/
|
|
(right - left), /* source rectangle width */
|
|
(bottom - top), /* source rectangle height */
|
|
left,
|
|
/*
|
|
x-coordinate of lower-left corner
|
|
of source rect.
|
|
*/
|
|
0,
|
|
/*
|
|
y-coordinate of lower-left corner
|
|
of source rect.
|
|
*/
|
|
0, /* first scan line in array */
|
|
(bottom - top), /* number of scan lines */
|
|
(CONST VOID *)p, /* address of array with DIB bits */
|
|
(const struct tagBITMAPINFO *)&bmh,
|
|
/* address of structure with bitmap info. */
|
|
#if ! UseWinCE
|
|
DIB_RGB_COLORS /* RGB or palette indices */
|
|
#else
|
|
DIB_PAL_COLORS /* palette indices */
|
|
#endif
|
|
) == 0) {
|
|
/* ReportWinLastError(); */
|
|
}
|
|
}
|
|
}
|
|
|
|
#if MayFullScreen
|
|
label_exit:
|
|
;
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC Screen_DrawAll(void)
|
|
{
|
|
HaveChangedScreenBuff(0, 0, vMacScreenHeight, vMacScreenWidth);
|
|
}
|
|
|
|
LOCALPROC DrawChangesAndClear(void)
|
|
{
|
|
if (ScreenChangedBottom > ScreenChangedTop) {
|
|
HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
|
|
ScreenChangedBottom, ScreenChangedRight);
|
|
ScreenClearChanges();
|
|
}
|
|
}
|
|
|
|
GLOBALOSGLUPROC DoneWithDrawingForTick(void)
|
|
{
|
|
#if EnableFSMouseMotion
|
|
if (HaveMouseMotion) {
|
|
AutoScrollScreen();
|
|
}
|
|
#endif
|
|
DrawChangesAndClear();
|
|
}
|
|
|
|
LOCALFUNC bool InitTheCursor(void)
|
|
{
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
return true;
|
|
}
|
|
|
|
#if EnableFSMouseMotion
|
|
LOCALPROC MouseConstrain(void)
|
|
{
|
|
int16_t shiftdh;
|
|
int16_t shiftdv;
|
|
|
|
if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
|
|
shiftdh = ViewHSize / 2;
|
|
} else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4))
|
|
{
|
|
shiftdh = - ViewHSize / 2;
|
|
} else {
|
|
shiftdh = 0;
|
|
}
|
|
if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
|
|
shiftdv = ViewVSize / 2;
|
|
} else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4))
|
|
{
|
|
shiftdv = - ViewVSize / 2;
|
|
} else {
|
|
shiftdv = 0;
|
|
}
|
|
if ((shiftdh != 0) || (shiftdv != 0)) {
|
|
SavedMouseH += shiftdh;
|
|
SavedMouseV += shiftdv;
|
|
if (! MoveMouse(SavedMouseH, SavedMouseV)) {
|
|
HaveMouseMotion = false;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
LOCALPROC MousePositionNotify(LONG NewMousePosx, LONG NewMousePosy)
|
|
{
|
|
bool ShouldHaveCursorHidden = true;
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
NewMousePosx -= hOffset;
|
|
NewMousePosy -= vOffset;
|
|
}
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
if (UseMagnify) {
|
|
NewMousePosx /= WindowScale;
|
|
NewMousePosy /= WindowScale;
|
|
}
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
NewMousePosx += ViewHStart;
|
|
NewMousePosy += ViewVStart;
|
|
}
|
|
#endif
|
|
|
|
#if EnableFSMouseMotion
|
|
if (HaveMouseMotion) {
|
|
MousePositionSetDelta(NewMousePosx - SavedMouseH,
|
|
NewMousePosy - SavedMouseV);
|
|
SavedMouseH = NewMousePosx;
|
|
SavedMouseV = NewMousePosy;
|
|
} else
|
|
#endif
|
|
{
|
|
if (NewMousePosx < 0) {
|
|
NewMousePosx = 0;
|
|
ShouldHaveCursorHidden = false;
|
|
} else if (NewMousePosx > vMacScreenWidth) {
|
|
NewMousePosx = vMacScreenWidth - 1;
|
|
ShouldHaveCursorHidden = false;
|
|
}
|
|
if (NewMousePosy < 0) {
|
|
NewMousePosy = 0;
|
|
ShouldHaveCursorHidden = false;
|
|
} else if (NewMousePosy > vMacScreenHeight) {
|
|
NewMousePosy = vMacScreenHeight - 1;
|
|
ShouldHaveCursorHidden = false;
|
|
}
|
|
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
ShouldHaveCursorHidden = true;
|
|
}
|
|
#endif
|
|
|
|
#if ! UseWinCE
|
|
/* if (ShouldHaveCursorHidden || CurMouseButton) */
|
|
/*
|
|
for a game like arkanoid, would like mouse to still
|
|
move even when outside window in one direction
|
|
*/
|
|
#endif
|
|
MousePositionSet(NewMousePosx, NewMousePosy);
|
|
}
|
|
|
|
WantCursorHidden = ShouldHaveCursorHidden;
|
|
}
|
|
|
|
#if ! UseWinCE
|
|
LOCALPROC CheckMouseState(void)
|
|
{
|
|
POINT NewMousePos;
|
|
|
|
GetCursorPos(&NewMousePos);
|
|
NewMousePos.x -= WndX;
|
|
NewMousePos.y -= WndY;
|
|
MousePositionNotify(NewMousePos.x, NewMousePos.y);
|
|
}
|
|
#endif
|
|
|
|
LOCALVAR const uint8_t Native2MacRomanTab[] = {
|
|
0xAD, 0xB0, 0xE2, 0xC4, 0xE3, 0xC9, 0xA0, 0xE0,
|
|
0xF6, 0xE4, 0xB6, 0xDC, 0xCE, 0xB2, 0xB3, 0xB7,
|
|
0xB8, 0xD4, 0xD5, 0xD2, 0xD3, 0xA5, 0xD0, 0xD1,
|
|
0xF7, 0xAA, 0xC5, 0xDD, 0xCF, 0xB9, 0xC3, 0xD9,
|
|
0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0xBA, 0xA4,
|
|
0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0xBD, 0xA8, 0xF8,
|
|
0xA1, 0xB1, 0xC6, 0xD7, 0xAB, 0xB5, 0xA6, 0xE1,
|
|
0xFC, 0xDA, 0xBC, 0xC8, 0xDE, 0xDF, 0xF0, 0xC0,
|
|
0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,
|
|
0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,
|
|
0xF5, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0xF9,
|
|
0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0xFA, 0xFB, 0xA7,
|
|
0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,
|
|
0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
|
|
0xFD, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,
|
|
0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0xFE, 0xFF, 0xD8
|
|
};
|
|
|
|
#if IncludePbufs
|
|
LOCALFUNC tMacErr NativeTextToMacRomanPbuf(HGLOBAL x, tPbuf *r)
|
|
{
|
|
#if UseUni
|
|
#define UnsignedChar uint16_t
|
|
#else
|
|
#define UnsignedChar uint8_t
|
|
#endif
|
|
HGLOBAL h;
|
|
LPTSTR p1;
|
|
uint32_t n;
|
|
UnsignedChar v;
|
|
tMacErr err = mnvm_miscErr;
|
|
|
|
p1 = GlobalLock(x);
|
|
if (p1 != NULL) {
|
|
n = 0;
|
|
while ((v = *p1++) != 0) {
|
|
if (v != 10) {
|
|
++n;
|
|
}
|
|
}
|
|
(void) GlobalUnlock(x);
|
|
|
|
h = GlobalAlloc(GMEM_DDESHARE, n);
|
|
if (h != NULL) {
|
|
p1 = GlobalLock(x);
|
|
if (p1 != NULL) {
|
|
uint8_t *p2 = GlobalLock(h);
|
|
if (p2 != NULL) {
|
|
while ((v = (UnsignedChar)*p1++) != 0) {
|
|
if (v >= 128) {
|
|
*p2++ = Native2MacRomanTab[v & 0x7F];
|
|
/*
|
|
if UseUni, then for gives
|
|
garbage for v > 256.
|
|
*/
|
|
} else if (v != 10) {
|
|
*p2++ = v;
|
|
}
|
|
}
|
|
|
|
err = mnvm_noErr;
|
|
|
|
(void) GlobalUnlock(h);
|
|
}
|
|
(void) GlobalUnlock(x);
|
|
}
|
|
|
|
if (mnvm_noErr != err) {
|
|
(void) GlobalFree(h);
|
|
} else {
|
|
err = PbufNewFromHandle(h, n, r);
|
|
}
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
LOCALVAR const uint8_t MacRoman2NativeTab[] = {
|
|
0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1,
|
|
0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8,
|
|
0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3,
|
|
0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC,
|
|
0x86, 0xB0, 0xA2, 0xA3, 0xA7, 0x95, 0xB6, 0xDF,
|
|
0xAE, 0xA9, 0x99, 0xB4, 0xA8, 0x80, 0xC6, 0xD8,
|
|
0x81, 0xB1, 0x8D, 0x8E, 0xA5, 0xB5, 0x8A, 0x8F,
|
|
0x90, 0x9D, 0xA6, 0xAA, 0xBA, 0xAD, 0xE6, 0xF8,
|
|
0xBF, 0xA1, 0xAC, 0x9E, 0x83, 0x9A, 0xB2, 0xAB,
|
|
0xBB, 0x85, 0xA0, 0xC0, 0xC3, 0xD5, 0x8C, 0x9C,
|
|
0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xF7, 0xB3,
|
|
0xFF, 0x9F, 0xB9, 0xA4, 0x8B, 0x9B, 0xBC, 0xBD,
|
|
0x87, 0xB7, 0x82, 0x84, 0x89, 0xC2, 0xCA, 0xC1,
|
|
0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0xD3, 0xD4,
|
|
0xBE, 0xD2, 0xDA, 0xDB, 0xD9, 0xD0, 0x88, 0x98,
|
|
0xAF, 0xD7, 0xDD, 0xDE, 0xB8, 0xF0, 0xFD, 0xFE
|
|
};
|
|
|
|
#if IncludePbufs
|
|
LOCALFUNC bool MacRomanTextToNativeHand(tPbuf Pbuf_no,
|
|
bool IsFileName, HGLOBAL *r)
|
|
{
|
|
HGLOBAL h;
|
|
uint32_t i;
|
|
uint32_t rn = 0;
|
|
HGLOBAL bh = PbufDat[Pbuf_no];
|
|
uint32_t L = PbufSize[Pbuf_no];
|
|
bool IsOk = false;
|
|
|
|
if (IsFileName) {
|
|
if (L > 255) {
|
|
L = 255;
|
|
}
|
|
} else {
|
|
uint8_t *Buffer = (uint8_t *)GlobalLock(bh);
|
|
if (Buffer != NULL) {
|
|
for (i = 0; i < L; ++i) {
|
|
if (Buffer[i] == 13) {
|
|
++rn;
|
|
}
|
|
}
|
|
(void) GlobalUnlock(bh);
|
|
}
|
|
}
|
|
|
|
h = GlobalAlloc(GMEM_DDESHARE, (L + rn + 1) * sizeof(TCHAR));
|
|
if (h != NULL) {
|
|
uint8_t *Buffer = (uint8_t *)GlobalLock(bh);
|
|
if (Buffer != NULL) {
|
|
LPTSTR p1 = GlobalLock(h);
|
|
if (p1 != NULL) {
|
|
for (i = 0; i < L; ++i) {
|
|
TCHAR y;
|
|
uint8_t x = ((uint8_t *)Buffer)[i];
|
|
if (x >= 128) {
|
|
y = (TCHAR)MacRoman2NativeTab[x - 128];
|
|
} else {
|
|
if (IsFileName) {
|
|
if ((x < 32)
|
|
|| ('\\' == x) || ('/' == x)
|
|
|| (':' == x) || ('*' == x)
|
|
|| ('?' == x) || ('"' == x)
|
|
|| ('<' == x) || ('>' == x)
|
|
|| ('|' == x))
|
|
{
|
|
y = (TCHAR)('-');
|
|
} else {
|
|
y = (TCHAR)x;
|
|
}
|
|
} else {
|
|
if (13 == x) {
|
|
*p1++ = (TCHAR)(13);
|
|
y = (TCHAR)(10);
|
|
} else {
|
|
y = (TCHAR)x;
|
|
}
|
|
}
|
|
}
|
|
*p1++ = y;
|
|
}
|
|
*p1++ = (TCHAR) 0; /* null character */
|
|
|
|
*r = h;
|
|
IsOk = true;
|
|
|
|
(void) GlobalUnlock(h);
|
|
}
|
|
(void) GlobalUnlock(bh);
|
|
}
|
|
if (! IsOk) {
|
|
(void) GlobalFree(h);
|
|
}
|
|
}
|
|
|
|
return IsOk;
|
|
}
|
|
#endif
|
|
|
|
#if IncludeHostTextClipExchange
|
|
GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
|
|
{
|
|
HGLOBAL h;
|
|
tMacErr err = mnvm_miscErr;
|
|
|
|
if (MacRomanTextToNativeHand(i, false, &h)) {
|
|
if (! OpenClipboard(MainWnd)) {
|
|
/* ReportGetLastError(); */
|
|
} else {
|
|
if (! EmptyClipboard()) {
|
|
/* ReportGetLastError(); */
|
|
}
|
|
if (SetClipboardData(CF_TEXT, h) == NULL) {
|
|
/* ReportGetLastError(); */
|
|
} else {
|
|
err = mnvm_noErr;
|
|
}
|
|
h = NULL;
|
|
if (! CloseClipboard()) {
|
|
/* ReportGetLastError(); */
|
|
}
|
|
}
|
|
if (h != NULL) {
|
|
(void) GlobalFree(h);
|
|
}
|
|
}
|
|
|
|
PbufDispose(i);
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
#if IncludeHostTextClipExchange
|
|
GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
|
|
{
|
|
tMacErr err = mnvm_miscErr;
|
|
|
|
if (IsClipboardFormatAvailable(CF_TEXT)) {
|
|
if (! OpenClipboard(MainWnd)) {
|
|
/* ReportGetLastError(); */
|
|
} else {
|
|
HGLOBAL h = GetClipboardData(CF_TEXT);
|
|
if (h == NULL) {
|
|
/* ReportGetLastError(); */
|
|
} else {
|
|
err = NativeTextToMacRomanPbuf(h, r);
|
|
}
|
|
if (! CloseClipboard()) {
|
|
/* ReportGetLastError(); */
|
|
}
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
/* --- drives --- */
|
|
|
|
#define NotAfileRef INVALID_HANDLE_VALUE
|
|
|
|
LOCALVAR HANDLE Drives[NumDrives]; /* open disk image files */
|
|
|
|
#define NeedDriveNames (IncludeSonyGetName || IncludeSonyNew)
|
|
|
|
#if NeedDriveNames
|
|
LOCALVAR HGLOBAL DriveNames[NumDrives];
|
|
/*
|
|
It is supposed to be possible to use
|
|
GetMappedFileName to get name of open file,
|
|
but that seems ugly kludge, so instead
|
|
save the name on open.
|
|
*/
|
|
#endif
|
|
|
|
LOCALPROC InitDrives(void)
|
|
{
|
|
/*
|
|
This isn't really needed, Drives[i] and DriveNames[i]
|
|
need not have valid values when not vSonyIsInserted[i].
|
|
*/
|
|
tDrive i;
|
|
|
|
for (i = 0; i < NumDrives; ++i) {
|
|
Drives[i] = NotAfileRef;
|
|
#if NeedDriveNames
|
|
DriveNames[i] = NULL;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyTransfer(bool IsWrite, uint8_t * Buffer,
|
|
tDrive Drive_No, uint32_t Sony_Start, uint32_t Sony_Count,
|
|
uint32_t *Sony_ActCount)
|
|
{
|
|
HANDLE refnum;
|
|
DWORD newL;
|
|
tMacErr result;
|
|
DWORD BytesTransferred = 0;
|
|
|
|
refnum = Drives[Drive_No];
|
|
newL = SetFilePointer(
|
|
refnum, /* handle of file */
|
|
Sony_Start, /* number of bytes to move file pointer */
|
|
nullpr, /* address of high-order word of distance to move */
|
|
FILE_BEGIN /* how to move */
|
|
);
|
|
if (newL == 0xFFFFFFFF) {
|
|
result = mnvm_miscErr; /*& figure out what really to return &*/
|
|
} else if (Sony_Start != (uint32_t)newL) {
|
|
/* not supposed to get here */
|
|
result = mnvm_miscErr; /*& figure out what really to return &*/
|
|
} else {
|
|
if (IsWrite) {
|
|
if (! WriteFile(refnum, /* handle of file to read */
|
|
(LPVOID)Buffer
|
|
, /* address of buffer that receives data */
|
|
(DWORD)Sony_Count, /* number of bytes to read */
|
|
&BytesTransferred, /* address of number of bytes read */
|
|
nullpr)) /* address of structure for data */
|
|
{
|
|
result = mnvm_miscErr;
|
|
/*& figure out what really to return &*/
|
|
} else if ((uint32_t)BytesTransferred != Sony_Count) {
|
|
result = mnvm_miscErr;
|
|
/*& figure out what really to return &*/
|
|
} else {
|
|
result = mnvm_noErr;
|
|
}
|
|
} else {
|
|
if (! ReadFile(refnum, /* handle of file to read */
|
|
(LPVOID)Buffer,
|
|
/* address of buffer that receives data */
|
|
(DWORD)Sony_Count, /* number of bytes to read */
|
|
&BytesTransferred,
|
|
/* address of number of bytes read */
|
|
nullpr)) /* address of structure for data */
|
|
{
|
|
result = mnvm_miscErr;
|
|
/*& figure out what really to return &*/
|
|
} else if ((uint32_t)BytesTransferred != Sony_Count) {
|
|
result = mnvm_miscErr;
|
|
/*& figure out what really to return &*/
|
|
} else {
|
|
result = mnvm_noErr;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nullpr != Sony_ActCount) {
|
|
*Sony_ActCount = BytesTransferred;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, uint32_t *Sony_Count)
|
|
{
|
|
tMacErr result;
|
|
DWORD L;
|
|
|
|
L = GetFileSize(Drives[Drive_No], nullpr);
|
|
if (L == 0xFFFFFFFF) {
|
|
result = mnvm_miscErr; /*& figure out what really to return &*/
|
|
} else {
|
|
*Sony_Count = L;
|
|
result = mnvm_noErr;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, bool deleteit)
|
|
{
|
|
HANDLE refnum = Drives[Drive_No];
|
|
|
|
#if ! NeedDriveNames
|
|
UnusedParam(deleteit);
|
|
#endif
|
|
|
|
Drives[Drive_No] = NotAfileRef; /* not really needed */
|
|
|
|
DiskEjectedNotify(Drive_No);
|
|
|
|
(void) FlushFileBuffers(refnum);
|
|
(void) CloseHandle(refnum);
|
|
|
|
#if NeedDriveNames
|
|
{
|
|
HGLOBAL h = DriveNames[Drive_No];
|
|
if (NULL != h) {
|
|
if (deleteit) {
|
|
LPTSTR drivepath = GlobalLock(h);
|
|
if (drivepath != NULL) {
|
|
(void) DeleteFile(drivepath);
|
|
(void) GlobalUnlock(h);
|
|
}
|
|
}
|
|
(void) GlobalFree(h);
|
|
DriveNames[Drive_No] = NULL; /* not really needed */
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return mnvm_noErr;
|
|
}
|
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
|
|
{
|
|
return vSonyEject0(Drive_No, false);
|
|
}
|
|
|
|
#if IncludeSonyNew
|
|
GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
|
|
{
|
|
return vSonyEject0(Drive_No, true);
|
|
}
|
|
#endif
|
|
|
|
LOCALPROC UnInitDrives(void)
|
|
{
|
|
tDrive i;
|
|
|
|
for (i = 0; i < NumDrives; ++i) {
|
|
if (vSonyIsInserted(i)) {
|
|
(void) vSonyEject(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if NeedDriveNames
|
|
LOCALFUNC bool LPTSTRtoHand(LPTSTR s, HGLOBAL *r)
|
|
{
|
|
bool IsOk = false;
|
|
|
|
size_t L = _tcslen(s);
|
|
HGLOBAL h = GlobalAlloc(GMEM_DDESHARE,
|
|
(L + 1) * sizeof(TCHAR));
|
|
if (h != NULL) {
|
|
LPTSTR p = GlobalLock(h);
|
|
if (p != NULL) {
|
|
_tcscpy(p, s);
|
|
IsOk = true;
|
|
(void) GlobalUnlock(h);
|
|
}
|
|
if (! IsOk) {
|
|
(void) GlobalFree(h);
|
|
} else {
|
|
*r = h;
|
|
}
|
|
}
|
|
|
|
return IsOk;
|
|
}
|
|
#endif
|
|
|
|
#if IncludeSonyGetName
|
|
GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
|
|
{
|
|
WIN32_FIND_DATA fd;
|
|
tMacErr err = mnvm_miscErr;
|
|
HGLOBAL ph = DriveNames[Drive_No];
|
|
if (NULL != ph) {
|
|
LPTSTR drivepath = GlobalLock(ph);
|
|
if (drivepath != NULL) {
|
|
HANDLE hf = FindFirstFile(drivepath, &fd);
|
|
(void) GlobalUnlock(ph);
|
|
|
|
if (hf != INVALID_HANDLE_VALUE) {
|
|
HGLOBAL h;
|
|
if (LPTSTRtoHand(fd.cFileName, &h)) {
|
|
err = NativeTextToMacRomanPbuf(h, r);
|
|
}
|
|
FindClose(hf);
|
|
}
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
|
|
LOCALFUNC bool Sony_Insert0(HANDLE refnum, bool locked,
|
|
LPTSTR drivepath)
|
|
{
|
|
tDrive Drive_No;
|
|
|
|
#if ! NeedDriveNames
|
|
UnusedParam(drivepath);
|
|
#endif
|
|
|
|
if (! FirstFreeDisk(&Drive_No)) {
|
|
(void) CloseHandle(refnum);
|
|
MacMsg(kStrTooManyImagesTitle,
|
|
kStrTooManyImagesMessage, false);
|
|
return false;
|
|
} else {
|
|
Drives[Drive_No] = refnum;
|
|
DiskInsertNotify(Drive_No, locked);
|
|
#if NeedDriveNames
|
|
{
|
|
HGLOBAL h;
|
|
|
|
if (! LPTSTRtoHand(drivepath, &h)) {
|
|
h = NULL;
|
|
}
|
|
|
|
DriveNames[Drive_No] = h;
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
}
|
|
|
|
LOCALFUNC bool Sony_Insert1(LPTSTR drivepath, bool SilentOnMissing)
|
|
{
|
|
bool locked = false;
|
|
HANDLE refnum = CreateFile(
|
|
drivepath, /* pointer to name of the file */
|
|
GENERIC_READ + GENERIC_WRITE, /* access (read-write) mode */
|
|
0, /* share mode */
|
|
nullpr, /* pointer to security descriptor */
|
|
OPEN_EXISTING, /* how to create */
|
|
FILE_ATTRIBUTE_NORMAL, /* file attributes */
|
|
nullpr /* handle to file with attributes to copy */
|
|
);
|
|
if (refnum == INVALID_HANDLE_VALUE) {
|
|
if (ERROR_ACCESS_DENIED == GetLastError()) {
|
|
locked = true;
|
|
refnum = CreateFile(
|
|
drivepath, /* pointer to name of the file */
|
|
GENERIC_READ, /* access (read-write) mode */
|
|
FILE_SHARE_READ, /* share mode */
|
|
nullpr, /* pointer to security descriptor */
|
|
OPEN_EXISTING, /* how to create */
|
|
FILE_ATTRIBUTE_NORMAL, /* file attributes */
|
|
nullpr /* handle to file with attributes to copy */
|
|
);
|
|
}
|
|
}
|
|
if (refnum == INVALID_HANDLE_VALUE) {
|
|
DWORD err = GetLastError();
|
|
if (ERROR_SHARING_VIOLATION == err) {
|
|
MacMsg(kStrImageInUseTitle,
|
|
kStrImageInUseMessage, false);
|
|
} else if ((ERROR_FILE_NOT_FOUND == err) && SilentOnMissing) {
|
|
/* ignore it */
|
|
} else {
|
|
MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, false);
|
|
}
|
|
} else {
|
|
return Sony_Insert0(refnum, locked, drivepath);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
LOCALFUNC bool LoadMacRomFromPath(LPTSTR drivepath)
|
|
{
|
|
HANDLE refnum = INVALID_HANDLE_VALUE;
|
|
bool IsOk = false;
|
|
|
|
refnum = CreateFile(
|
|
drivepath, /* pointer to name of the file */
|
|
GENERIC_READ, /* access (read-write) mode */
|
|
FILE_SHARE_READ, /* share mode */
|
|
nullpr, /* pointer to security descriptor */
|
|
OPEN_EXISTING, /* how to create */
|
|
FILE_ATTRIBUTE_NORMAL, /* file attributes */
|
|
nullpr /* handle to file with attributes to copy */
|
|
);
|
|
|
|
if (refnum == INVALID_HANDLE_VALUE) {
|
|
/* MacMsg(kStrNoROMTitle, kStrNoROMMessage, true); */
|
|
} else {
|
|
DWORD BytesRead;
|
|
|
|
if (! ReadFile(refnum, /* handle of file to read */
|
|
(LPVOID)ROM, /* address of buffer that receives data */
|
|
(DWORD)kROM_Size, /* number of bytes to read */
|
|
&BytesRead, /* address of number of bytes read */
|
|
nullpr)) /* address of structure for data */
|
|
{
|
|
MacMsgOverride(kStrNoReadROMTitle, kStrNoReadROMMessage);
|
|
} else
|
|
if ((uint32_t)BytesRead != kROM_Size) {
|
|
MacMsgOverride(kStrShortROMTitle, kStrShortROMMessage);
|
|
} else
|
|
{
|
|
IsOk = (mnvm_noErr == ROM_IsValid());
|
|
}
|
|
(void) CloseHandle(refnum);
|
|
}
|
|
|
|
return IsOk;
|
|
}
|
|
|
|
#ifndef EnableShellLinks
|
|
#define EnableShellLinks 1
|
|
#endif
|
|
|
|
#if EnableShellLinks
|
|
LOCALVAR bool COMinited = false;
|
|
LOCALVAR bool COMinitedOK;
|
|
#endif
|
|
|
|
#if EnableShellLinks
|
|
LOCALPROC UninitCOM(void)
|
|
{
|
|
if (COMinited) {
|
|
CoUninitialize();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if EnableShellLinks
|
|
LOCALFUNC bool NeedCOM(void)
|
|
{
|
|
HRESULT hres;
|
|
|
|
if (! COMinited) {
|
|
COMinitedOK = false;
|
|
hres = CoInitialize(NULL);
|
|
if (SUCCEEDED(hres)) {
|
|
COMinitedOK = true;
|
|
}
|
|
|
|
COMinited = true;
|
|
}
|
|
return COMinitedOK;
|
|
}
|
|
#endif
|
|
|
|
#if EnableShellLinks
|
|
LOCALFUNC bool ResolveShortcut(LPTSTR FilePath, bool *directory)
|
|
/* adapted from Microsoft example code */
|
|
{
|
|
HRESULT hres;
|
|
IShellLink *psl;
|
|
IPersistFile* ppf;
|
|
TCHAR szGotPath[MAX_PATH];
|
|
WIN32_FIND_DATA wfd;
|
|
bool IsOk = false;
|
|
|
|
if (NeedCOM()) {
|
|
hres = CoCreateInstance(&CLSID_ShellLink, NULL,
|
|
CLSCTX_INPROC_SERVER, &IID_IShellLink,
|
|
(LPVOID *)(void *)&psl);
|
|
/*
|
|
the (void *) prevents a compiler warning
|
|
from gcc
|
|
*/
|
|
if (SUCCEEDED(hres)) {
|
|
/* Get a pointer to the IPersistFile interface. */
|
|
hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile,
|
|
(void **)(void *)&ppf);
|
|
if (SUCCEEDED(hres)) {
|
|
/* Ensure that the string is Unicode. */
|
|
#if UseUni
|
|
#define wsz FilePath
|
|
#else
|
|
WORD wsz[MAX_PATH];
|
|
MultiByteToWideChar(CP_ACP, 0, FilePath, -1, wsz,
|
|
MAX_PATH);
|
|
#endif
|
|
|
|
/* Load the shortcut. */
|
|
hres = ppf->lpVtbl->Load(ppf, wsz, STGM_READ);
|
|
if (SUCCEEDED(hres)) {
|
|
/* Resolve the link. */
|
|
hres = psl->lpVtbl->Resolve(psl, MainWnd,
|
|
SLR_ANY_MATCH);
|
|
if (SUCCEEDED(hres)) {
|
|
/* Get the path to the link target. */
|
|
hres = psl->lpVtbl->GetPath(psl, szGotPath,
|
|
MAX_PATH, &wfd,
|
|
SLGP_SHORTPATH);
|
|
if (SUCCEEDED(hres)) {
|
|
/*
|
|
This is in the sample code, but doesn't
|
|
seem to be needed:
|
|
Get the description of the target.
|
|
char szDescription[MAX_PATH];
|
|
hres = psl->lpVtbl->GetDescription(psl,
|
|
szDescription, MAX_PATH);
|
|
if (SUCCEEDED(hres)) {
|
|
}
|
|
*/
|
|
lstrcpy(FilePath, szGotPath);
|
|
if (NULL != directory) {
|
|
*directory = (0 != (wfd.dwFileAttributes
|
|
& FILE_ATTRIBUTE_DIRECTORY));
|
|
}
|
|
IsOk = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
ppf->lpVtbl->Release(ppf);
|
|
}
|
|
psl->lpVtbl->Release(psl);
|
|
}
|
|
}
|
|
return IsOk;
|
|
}
|
|
#endif
|
|
|
|
#if EnableShellLinks
|
|
LOCALFUNC bool FileIsLink(LPTSTR drivepath)
|
|
{
|
|
LPTSTR p = FindLastTerm(drivepath, (TCHAR)('.'));
|
|
|
|
if (p != nullpr) {
|
|
if (_tcscmp(p, TEXT("lnk")) == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|
|
|
|
LOCALFUNC bool InsertDiskOrAlias(LPTSTR drivepath,
|
|
bool MaybeROM, bool MaybeAlias)
|
|
{
|
|
#if EnableShellLinks
|
|
if (MaybeAlias && FileIsLink(drivepath)) {
|
|
if (! ResolveShortcut(drivepath, NULL)) {
|
|
return false;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (MaybeROM && ! ROM_loaded) {
|
|
return LoadMacRomFromPath(drivepath);
|
|
} else {
|
|
return Sony_Insert1(drivepath, false);
|
|
}
|
|
}
|
|
|
|
LOCALFUNC bool FileExists(LPTSTR pathName, bool *directory)
|
|
{
|
|
WIN32_FIND_DATA fd;
|
|
HANDLE hf = FindFirstFile(pathName, &fd);
|
|
bool IsOk = false;
|
|
|
|
if (hf != INVALID_HANDLE_VALUE) {
|
|
if (NULL != directory) {
|
|
*directory =
|
|
(0 != (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
|
|
}
|
|
IsOk = true;
|
|
FindClose(hf);
|
|
}
|
|
|
|
return IsOk;
|
|
}
|
|
|
|
LOCALFUNC tMacErr ResolveNamedChild0(LPTSTR pathName,
|
|
LPTSTR Child, bool *directory)
|
|
{
|
|
size_t newlen;
|
|
size_t oldlen = _tcslen(pathName);
|
|
tMacErr err = mnvm_miscErr;
|
|
|
|
newlen = oldlen + 1 + _tcslen(Child);
|
|
if (newlen + 1 < _MAX_PATH) {
|
|
_tcscat(pathName, TEXT("\\"));
|
|
_tcscat(pathName, Child);
|
|
|
|
if (FileExists(pathName, directory)) {
|
|
err = mnvm_noErr;
|
|
} else {
|
|
err = mnvm_fnfErr;
|
|
#if EnableShellLinks
|
|
if (newlen + 5 < _MAX_PATH) {
|
|
_tcscat(pathName, TEXT(".lnk"));
|
|
if (FileExists(pathName, NULL))
|
|
if (ResolveShortcut(pathName, directory))
|
|
{
|
|
err = mnvm_noErr;
|
|
}
|
|
if (mnvm_noErr != err) {
|
|
pathName[newlen] = (TCHAR)('\0');
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
LOCALFUNC tMacErr ResolveNamedChild(LPTSTR pathName,
|
|
char *Child, bool *directory)
|
|
{
|
|
TCHAR Child0[ClStrMaxLength + 1];
|
|
|
|
NativeStrFromCStr(Child0, Child, false);
|
|
|
|
return ResolveNamedChild0(pathName, Child0, directory);
|
|
}
|
|
|
|
LOCALFUNC bool ResolveNamedChildDir(LPTSTR pathName, char *Child)
|
|
{
|
|
bool directory;
|
|
|
|
return (mnvm_noErr == ResolveNamedChild(
|
|
pathName, Child, &directory))
|
|
&& directory;
|
|
}
|
|
|
|
LOCALFUNC bool ResolveNamedChildFile(LPTSTR pathName, char *Child)
|
|
{
|
|
bool directory;
|
|
|
|
return (mnvm_noErr == ResolveNamedChild(
|
|
pathName, Child, &directory))
|
|
&& ! directory;
|
|
}
|
|
|
|
#if (IncludeSonyNew && ! SaveDialogEnable)
|
|
LOCALFUNC bool MakeNamedChildDir(LPTSTR pathName, char *Child)
|
|
{
|
|
bool directory;
|
|
bool IsOk = false;
|
|
tMacErr err = ResolveNamedChild(pathName, Child, &directory);
|
|
|
|
if (mnvm_noErr == err) {
|
|
IsOk = directory;
|
|
} else if (mnvm_fnfErr == err) {
|
|
if (CreateDirectory(pathName, NULL)) {
|
|
IsOk = true;
|
|
}
|
|
}
|
|
|
|
return IsOk;
|
|
}
|
|
#endif
|
|
|
|
LOCALFUNC bool GetAppDataPath(LPTSTR lpszPath,
|
|
BOOL fCreate)
|
|
{
|
|
bool IsOk = false;
|
|
|
|
if (HaveMySHGetSpecialFolderPath())
|
|
if (MySHGetSpecialFolderPath(
|
|
NULL /* HWND hwndOwner */,
|
|
lpszPath, _CSIDL_APPDATA, fCreate))
|
|
{
|
|
IsOk = true;
|
|
}
|
|
/*
|
|
if not available, could perhaps
|
|
use GetWindowsDirectory.
|
|
*/
|
|
/*
|
|
SHGetFolderPath is more recent,
|
|
could perhaps check for it first.
|
|
might also be in "SHFolder.dll".
|
|
|
|
SHGetKnownFolderPath is even
|
|
more recent.
|
|
*/
|
|
|
|
return IsOk;
|
|
}
|
|
|
|
#if UseWinCE
|
|
/* Are we in control mode? */
|
|
/* Needed because you can't hold down a key with the virtual keyboard */
|
|
LOCALVAR bool CtrlMode = false;
|
|
#endif
|
|
|
|
LOCALPROC InsertADisk0(void)
|
|
{
|
|
OPENFILENAME ofn;
|
|
TCHAR szDirName[256];
|
|
TCHAR szFile[256];
|
|
#if ! UseWinCE
|
|
TCHAR szFileTitle[256];
|
|
#endif
|
|
UINT i;
|
|
size_t cbString;
|
|
TCHAR chReplace;
|
|
TCHAR szFilter[256];
|
|
bool IsOk;
|
|
|
|
szDirName[0] = (TCHAR)('\0');
|
|
szFile[0] = (TCHAR)('\0');
|
|
_tcscpy(szFilter,
|
|
TEXT("Disk images|*.dsk;*.HF?;*.IMG;*.IMA;*.IMAGE")
|
|
TEXT("|All files (*.*)|*.*|\0"));
|
|
|
|
cbString = _tcslen(szFilter);
|
|
|
|
chReplace = szFilter[cbString - 1];
|
|
|
|
for (i = 0; szFilter[i] != (TCHAR)('\0'); ++i)
|
|
{
|
|
if (szFilter[i] == chReplace) {
|
|
szFilter[i] = (TCHAR)('\0');
|
|
}
|
|
}
|
|
|
|
memset(&ofn, 0, sizeof(OPENFILENAME));
|
|
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.hwndOwner = MainWnd;
|
|
ofn.lpstrFilter = szFilter;
|
|
ofn.nFilterIndex = 2;
|
|
ofn.lpstrFile= szFile;
|
|
ofn.nMaxFile = sizeof(szFile);
|
|
#if ! UseWinCE
|
|
ofn.lpstrFileTitle = szFileTitle;
|
|
ofn.nMaxFileTitle = sizeof(szFileTitle);
|
|
#endif
|
|
ofn.lpstrInitialDir = szDirName;
|
|
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST
|
|
| OFN_HIDEREADONLY;
|
|
|
|
MyBeginDialog();
|
|
IsOk = GetOpenFileName(&ofn);
|
|
MyEndDialog();
|
|
|
|
if(! IsOk) {
|
|
/* report error */
|
|
#if UseWinCE
|
|
if (szFile[0]) {
|
|
char wMsg[1024];
|
|
sprintf(wMsg, "Couldn't open %ls", szFile);
|
|
MacMsg("error", wMsg, false);
|
|
}
|
|
#endif
|
|
} else {
|
|
(void) InsertDiskOrAlias(ofn.lpstrFile,
|
|
true, false);
|
|
}
|
|
|
|
#if UseWinCE
|
|
CtrlMode = false;
|
|
#endif
|
|
}
|
|
|
|
LOCALFUNC bool LoadInitialImageFromName(char *ImageName)
|
|
{
|
|
TCHAR ImageFile[_MAX_PATH];
|
|
|
|
if (GetAppDir(ImageFile))
|
|
if (ResolveNamedChildFile(ImageFile, ImageName))
|
|
if (Sony_Insert1(ImageFile, true))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
LOCALFUNC bool Sony_InsertIth(int i)
|
|
{
|
|
bool v;
|
|
|
|
if ((i > 9) || ! FirstFreeDisk(nullpr)) {
|
|
v = false;
|
|
} else {
|
|
char s[] = "disk?.dsk";
|
|
|
|
s[4] = '0' + i;
|
|
|
|
/* stop on first error (including file not found) */
|
|
v = LoadInitialImageFromName(s);
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
LOCALFUNC bool LoadInitialImages(void)
|
|
{
|
|
if (! AnyDiskInserted()) {
|
|
int i;
|
|
|
|
for (i = 1; Sony_InsertIth(i); ++i) {
|
|
/* stop on first error (including file not found) */
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#if IncludeSonyNew
|
|
LOCALFUNC bool WriteZero(HANDLE refnum, uint32_t L)
|
|
{
|
|
if (SetFilePointer(
|
|
refnum, /* handle of file */
|
|
0, /* number of bytes to move file pointer */
|
|
nullpr, /* address of high-order word of distance to move */
|
|
FILE_BEGIN /* how to move */
|
|
) != 0)
|
|
{
|
|
return false;
|
|
} else {
|
|
#define ZeroBufferSize 2048
|
|
uint32_t i;
|
|
uint8_t buffer[ZeroBufferSize];
|
|
DWORD BytesWritten;
|
|
|
|
memset(&buffer, 0, ZeroBufferSize);
|
|
|
|
while (L > 0) {
|
|
i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
|
|
if (! WriteFile(refnum, /* handle of file to read */
|
|
(LPVOID)buffer,
|
|
/* address of buffer that receives data */
|
|
(DWORD)i, /* number of bytes to read */
|
|
&BytesWritten, /* address of number of bytes read */
|
|
nullpr) /* address of structure for data */
|
|
|| ((uint32_t)BytesWritten != i))
|
|
{
|
|
return false;
|
|
}
|
|
L -= i;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#define MaxSavePathSize MAX_PATH
|
|
|
|
#if IncludeSonyNew
|
|
LOCALPROC MakeNewDisk0(uint32_t L, LPTSTR pathName)
|
|
{
|
|
bool IsOk = false;
|
|
HANDLE newrefNum;
|
|
|
|
IsOk = false;
|
|
newrefNum = CreateFile(
|
|
pathName, /* pointer to name of the file */
|
|
GENERIC_READ + GENERIC_WRITE, /* access (read-write) mode */
|
|
0, /* share mode */
|
|
NULL, /* pointer to security descriptor */
|
|
CREATE_ALWAYS, /* how to create */
|
|
FILE_ATTRIBUTE_NORMAL, /* file attributes */
|
|
NULL /* handle to file with attributes to copy */
|
|
);
|
|
if (newrefNum == INVALID_HANDLE_VALUE) {
|
|
/* report error */
|
|
} else {
|
|
if (SetFilePointer(
|
|
newrefNum, /* handle of file */
|
|
L, /* number of bytes to move file pointer */
|
|
nullpr,
|
|
/* address of high-order word of distance to move */
|
|
FILE_BEGIN /* how to move */
|
|
) != L)
|
|
{
|
|
/* report error */
|
|
} else if (! SetEndOfFile(newrefNum)) {
|
|
/* report error */
|
|
} else if (! WriteZero(newrefNum, L)) {
|
|
/* report error */
|
|
} else {
|
|
IsOk =
|
|
Sony_Insert0(newrefNum, false, pathName);
|
|
newrefNum = INVALID_HANDLE_VALUE;
|
|
}
|
|
if (INVALID_HANDLE_VALUE != newrefNum) {
|
|
(void) CloseHandle(newrefNum);
|
|
}
|
|
if (! IsOk) {
|
|
(void) DeleteFile(pathName);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if IncludeSonyNew
|
|
LOCALPROC MakeNewDisk(uint32_t L, HGLOBAL NewDiskNameDat)
|
|
{
|
|
#if SaveDialogEnable
|
|
OPENFILENAME ofn;
|
|
bool IsOk = false;
|
|
TCHAR szFile[MaxSavePathSize];
|
|
TCHAR szFileTitle[MaxSavePathSize];
|
|
|
|
memset(&ofn, 0, sizeof(OPENFILENAME));
|
|
szFile[0] = 0;
|
|
szFileTitle[0] = 0;
|
|
|
|
#if IncludeSonyGetName
|
|
if (NewDiskNameDat != NULL) {
|
|
LPTSTR p = GlobalLock(NewDiskNameDat);
|
|
if (p != NULL) {
|
|
_tcscpy(szFile, p);
|
|
(void) GlobalUnlock(NewDiskNameDat);
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
NativeStrFromCStr(szFile, "untitled", false);
|
|
}
|
|
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
ofn.lpstrFile = szFile;
|
|
ofn.hwndOwner = MainWnd;
|
|
/* ofn.lpstrFilter = "All\0*.*\0Text\0*.txt\0Datafile\0*.dsk\0"; */
|
|
/* ofn.lpstrFilter = NULL; */ /* szFilter */
|
|
ofn.nMaxFile = MaxSavePathSize;
|
|
ofn.lpstrFileTitle = szFileTitle;
|
|
ofn.nMaxFileTitle = MaxSavePathSize;
|
|
ofn.lpstrInitialDir = NULL;
|
|
ofn.Flags = OFN_OVERWRITEPROMPT + OFN_HIDEREADONLY;
|
|
/* + OFN_SHOWHELP */
|
|
|
|
MyBeginDialog();
|
|
IsOk = GetSaveFileName(&ofn);
|
|
MyEndDialog();
|
|
|
|
if (! IsOk) {
|
|
/* report error */
|
|
} else {
|
|
MakeNewDisk0(L, ofn.lpstrFile);
|
|
}
|
|
#else /* SaveDialogEnable */
|
|
TCHAR pathName[MaxSavePathSize];
|
|
|
|
if (GetAppDir(pathName))
|
|
if (MakeNamedChildDir(pathName, "out"))
|
|
{
|
|
bool directory;
|
|
LPTSTR p = GlobalLock(NewDiskNameDat);
|
|
|
|
if (p != NULL) {
|
|
tMacErr err = ResolveNamedChild0(pathName, p,
|
|
&directory);
|
|
|
|
if (mnvm_fnfErr == err) {
|
|
err = mnvm_noErr;
|
|
} else if (mnvm_noErr == err) {
|
|
if (directory) {
|
|
err = mnvm_miscErr;
|
|
}
|
|
}
|
|
|
|
if (mnvm_noErr == err) {
|
|
MakeNewDisk0(L, pathName);
|
|
}
|
|
|
|
(void) GlobalUnlock(NewDiskNameDat);
|
|
}
|
|
}
|
|
#endif /* SaveDialogEnable */
|
|
}
|
|
#endif
|
|
|
|
LOCALFUNC bool LoadMacRom(void)
|
|
{
|
|
TCHAR ROMFile[_MAX_PATH];
|
|
bool IsOk = false;
|
|
|
|
if (GetAppDir(ROMFile))
|
|
if (ResolveNamedChildFile(ROMFile, RomFileName))
|
|
{
|
|
IsOk = true;
|
|
}
|
|
|
|
if (! IsOk) {
|
|
if (GetAppDataPath(ROMFile, FALSE))
|
|
if (ResolveNamedChildDir(ROMFile, "Gryphel"))
|
|
if (ResolveNamedChildDir(ROMFile, "mnvm_rom"))
|
|
if (ResolveNamedChildFile(ROMFile, RomFileName))
|
|
{
|
|
IsOk = true;
|
|
}
|
|
|
|
}
|
|
|
|
if (IsOk) {
|
|
IsOk = LoadMacRomFromPath(ROMFile);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#if InstallFileIcons
|
|
LOCALPROC SetRegKey(HKEY hKeyRoot,
|
|
LPTSTR strRegKey, LPTSTR strRegValue)
|
|
{
|
|
HKEY RegKey;
|
|
DWORD dwDisposition;
|
|
|
|
if (ERROR_SUCCESS == RegCreateKeyEx(hKeyRoot, strRegKey, 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
|
|
NULL, &RegKey, &dwDisposition))
|
|
{
|
|
RegSetValueEx(RegKey, NULL, 0, REG_SZ,
|
|
(CONST BYTE *)strRegValue,
|
|
(DWORD)((_tcslen(strRegValue) + 1) * sizeof(TCHAR)));
|
|
RegCloseKey(RegKey);
|
|
}
|
|
}
|
|
|
|
LOCALPROC RegisterShellFileType(LPTSTR AppPath, LPTSTR strFilterExt,
|
|
LPTSTR strFileTypeId, LPTSTR strFileTypeName,
|
|
LPTSTR strIconId, bool CanOpen)
|
|
{
|
|
TCHAR strRegKey[_MAX_PATH];
|
|
TCHAR strRegValue[_MAX_PATH + 2];
|
|
/* extra room for ","{strIconId} */
|
|
|
|
SetRegKey(HKEY_CLASSES_ROOT, strFileTypeId, strFileTypeName);
|
|
SetRegKey(HKEY_CLASSES_ROOT, strFilterExt, strFileTypeId);
|
|
|
|
_tcscpy(strRegKey, strFileTypeId);
|
|
_tcscat(strRegKey, TEXT("\\DefaultIcon"));
|
|
_tcscpy(strRegValue, TEXT("\""));
|
|
_tcscat(strRegValue, AppPath);
|
|
_tcscat(strRegValue, TEXT("\","));
|
|
_tcscat(strRegValue, strIconId);
|
|
SetRegKey(HKEY_CLASSES_ROOT, strRegKey, strRegValue);
|
|
|
|
if (CanOpen) {
|
|
_tcscpy(strRegKey, strFileTypeId);
|
|
_tcscat(strRegKey, TEXT("\\shell\\open\\command"));
|
|
_tcscpy(strRegValue, TEXT("\""));
|
|
_tcscat(strRegValue, AppPath);
|
|
_tcscat(strRegValue, TEXT("\" \"%1\""));
|
|
SetRegKey(HKEY_CLASSES_ROOT, strRegKey, strRegValue);
|
|
}
|
|
}
|
|
|
|
LOCALFUNC bool RegisterInRegistry(void)
|
|
{
|
|
TCHAR AppPath[_MAX_PATH];
|
|
|
|
GetModuleFileName(NULL, AppPath, _MAX_PATH);
|
|
#if 0
|
|
GetShortPathName(AppPath, AppPath, _MAX_PATH);
|
|
#endif
|
|
|
|
RegisterShellFileType(AppPath, TEXT(".rom"), TEXT("minivmac.rom"),
|
|
TEXT("Mini vMac ROM Image"), TEXT("1"), false);
|
|
RegisterShellFileType(AppPath, TEXT(".dsk"), TEXT("minivmac.dsk"),
|
|
TEXT("Mini vMac Disk Image"), TEXT("2"), true);
|
|
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
LOCALVAR LPTSTR CommandLine;
|
|
|
|
LOCALFUNC bool ScanCommandLine(void)
|
|
{
|
|
TCHAR *p = CommandLine;
|
|
TCHAR *p1;
|
|
TCHAR *p2;
|
|
TCHAR v;
|
|
size_t L;
|
|
|
|
v = *p;
|
|
while (0 != v) {
|
|
if (' ' == v) {
|
|
v = *++p;
|
|
} else {
|
|
if ('\"' == v) {
|
|
v = *++p;
|
|
p1 = p;
|
|
while (('\"' != v) && (0 != v)) {
|
|
v = *++p;
|
|
}
|
|
p2 = p;
|
|
if ('\"' == v) {
|
|
v = *++p;
|
|
}
|
|
} else {
|
|
p1 = p;
|
|
while ((' ' != v) && (0 != v)) {
|
|
v = *++p;
|
|
}
|
|
p2 = p;
|
|
}
|
|
L = p2 - p1;
|
|
if (L + 1 <= _MAX_PATH) {
|
|
TCHAR fileName[_MAX_PATH];
|
|
TCHAR *filePtr = fileName;
|
|
size_t i = L;
|
|
|
|
while (i > 0) {
|
|
*filePtr++ = *p1++;
|
|
--i;
|
|
}
|
|
*filePtr = (char)0;
|
|
|
|
if ((L > 0)
|
|
&& (('/' == fileName[0]) || ('-' == fileName[0])))
|
|
{
|
|
#if 0
|
|
TCHAR *p3 = &fileName[1];
|
|
if (0 == _tcscmp(p3, TEXT("l"))) {
|
|
SpeedValue = 0;
|
|
} else
|
|
#endif
|
|
{
|
|
MacMsg(kStrBadArgTitle, kStrBadArgMessage,
|
|
false);
|
|
}
|
|
} else {
|
|
(void) InsertDiskOrAlias(fileName,
|
|
false, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
#if EnableRecreateW
|
|
LOCALPROC CheckMagnifyAndFullScreen(void)
|
|
{
|
|
if (
|
|
#if EnableMagnify
|
|
(UseMagnify != WantMagnify)
|
|
#endif
|
|
#if EnableMagnify && VarFullScreen
|
|
||
|
|
#endif
|
|
#if VarFullScreen
|
|
(UseFullScreen != WantFullScreen)
|
|
#endif
|
|
)
|
|
{
|
|
(void) ReCreateMainWindow();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if VarFullScreen && EnableMagnify
|
|
enum {
|
|
kWinStateWindowed,
|
|
#if EnableMagnify
|
|
kWinStateFullScreen,
|
|
#endif
|
|
kNumWinStates
|
|
};
|
|
#endif
|
|
|
|
#if VarFullScreen && EnableMagnify
|
|
LOCALVAR int WinMagStates[kNumWinStates];
|
|
#endif
|
|
|
|
LOCALPROC ZapWinStateVars(void)
|
|
{
|
|
#if MayNotFullScreen
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < kNumMagStates; ++i) {
|
|
HavePositionWins[i] = false;
|
|
}
|
|
}
|
|
#endif
|
|
#if VarFullScreen && EnableMagnify
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < kNumWinStates; ++i) {
|
|
WinMagStates[i] = kMagStateAuto;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if VarFullScreen
|
|
LOCALPROC ToggleWantFullScreen(void)
|
|
{
|
|
WantFullScreen = ! WantFullScreen;
|
|
|
|
#if EnableMagnify
|
|
{
|
|
int OldWinState =
|
|
UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
|
|
int OldMagState =
|
|
UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
|
|
int NewWinState =
|
|
WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
|
|
int NewMagState = WinMagStates[NewWinState];
|
|
|
|
WinMagStates[OldWinState] = OldMagState;
|
|
if (kMagStateAuto != NewMagState) {
|
|
WantMagnify = (kMagStateMagnifgy == NewMagState);
|
|
} else {
|
|
WantMagnify = false;
|
|
if (WantFullScreen) {
|
|
if ((GetSystemMetrics(SM_CXSCREEN)
|
|
>= vMacScreenWidth * WindowScale)
|
|
&& (GetSystemMetrics(SM_CYSCREEN)
|
|
>= vMacScreenHeight * WindowScale)
|
|
)
|
|
{
|
|
WantMagnify = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if EnableDragDrop
|
|
LOCALPROC DragFunc(HDROP hDrop)
|
|
{
|
|
WORD n;
|
|
WORD i;
|
|
TCHAR a[_MAX_PATH];
|
|
|
|
n = DragQueryFile(hDrop, (UINT) -1, NULL, 0);
|
|
for (i = 0; i < n; ++i) {
|
|
if (DragQueryFile(hDrop, i, NULL, 0) < _MAX_PATH - 1) {
|
|
(void) DragQueryFile(hDrop, i, a, _MAX_PATH);
|
|
(void) InsertDiskOrAlias(a, true, true);
|
|
}
|
|
}
|
|
|
|
DragFinish(hDrop);
|
|
|
|
if (gTrueBackgroundFlag) {
|
|
if (! SetForegroundWindow(MainWnd)) {
|
|
/* error message here ? */
|
|
}
|
|
|
|
WantCmdOptOnReconnect = true;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
GLOBALOSGLUFUNC bool ExtraTimeNotOver(void)
|
|
{
|
|
#if SoundEnabled
|
|
SoundCheckVeryOften();
|
|
#endif
|
|
(void) UpdateTrueEmulatedTime();
|
|
return (TrueEmulatedTime == OnTrueTime);
|
|
}
|
|
|
|
/* --- platform independent code can be thought of as going here --- */
|
|
|
|
LOCALPROC LeaveBackground(void)
|
|
{
|
|
ReconnectKeyCodes3();
|
|
}
|
|
|
|
LOCALPROC EnterBackground(void)
|
|
{
|
|
DisconnectKeyCodes3();
|
|
|
|
#if VarFullScreen
|
|
if (WantFullScreen) {
|
|
ToggleWantFullScreen();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC LeaveSpeedStopped(void)
|
|
{
|
|
#if SoundEnabled
|
|
Sound_Start();
|
|
#endif
|
|
#if (TimeResolution != 0)
|
|
Timer_Resume();
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC EnterSpeedStopped(void)
|
|
{
|
|
#if (TimeResolution != 0)
|
|
Timer_Suspend();
|
|
#endif
|
|
#if SoundEnabled
|
|
Sound_Stop();
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC CheckForSavedTasks(void)
|
|
{
|
|
/*
|
|
Check for things to do that rather wouldn't
|
|
have done at an awkward time.
|
|
*/
|
|
|
|
if (EvtQNeedRecover) {
|
|
EvtQNeedRecover = false;
|
|
|
|
/* attempt cleanup, EvtQNeedRecover may get set again */
|
|
EvtQTryRecoverFromFull();
|
|
}
|
|
|
|
#if EnableFSMouseMotion
|
|
if (HaveMouseMotion) {
|
|
MouseConstrain();
|
|
}
|
|
#endif
|
|
|
|
if (RequestMacOff) {
|
|
RequestMacOff = false;
|
|
if (AnyDiskInserted()) {
|
|
MacMsgOverride(kStrQuitWarningTitle,
|
|
kStrQuitWarningMessage);
|
|
} else {
|
|
ForceMacOff = true;
|
|
}
|
|
}
|
|
|
|
if (ForceMacOff) {
|
|
return;
|
|
}
|
|
|
|
if (gTrueBackgroundFlag != gBackgroundFlag) {
|
|
gBackgroundFlag = gTrueBackgroundFlag;
|
|
if (gTrueBackgroundFlag) {
|
|
EnterBackground();
|
|
} else {
|
|
LeaveBackground();
|
|
}
|
|
}
|
|
|
|
if (CurSpeedStopped != (SpeedStopped ||
|
|
(gBackgroundFlag && ! RunInBackground)))
|
|
{
|
|
CurSpeedStopped = ! CurSpeedStopped;
|
|
if (CurSpeedStopped) {
|
|
EnterSpeedStopped();
|
|
} else {
|
|
LeaveSpeedStopped();
|
|
}
|
|
}
|
|
|
|
#if EnableRecreateW
|
|
if (! (gTrueBackgroundFlag)) {
|
|
CheckMagnifyAndFullScreen();
|
|
}
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
if (GrabMachine != (
|
|
#if VarFullScreen
|
|
UseFullScreen &&
|
|
#endif
|
|
! (gTrueBackgroundFlag || CurSpeedStopped)))
|
|
{
|
|
GrabMachine = ! GrabMachine;
|
|
AdjustMachineGrab();
|
|
}
|
|
#endif
|
|
|
|
if (gTrueBackgroundFlag) {
|
|
/*
|
|
wait til later
|
|
*/
|
|
} else {
|
|
#if IncludeSonyNew
|
|
if (vSonyNewDiskWanted) {
|
|
#if IncludeSonyNameNew
|
|
if (vSonyNewDiskName != NotAPbuf) {
|
|
HGLOBAL NewDiskNameDat;
|
|
if (MacRomanTextToNativeHand(vSonyNewDiskName, true,
|
|
&NewDiskNameDat))
|
|
{
|
|
MakeNewDisk(vSonyNewDiskSize, NewDiskNameDat);
|
|
GlobalFree(NewDiskNameDat);
|
|
}
|
|
PbufDispose(vSonyNewDiskName);
|
|
vSonyNewDiskName = NotAPbuf;
|
|
} else
|
|
#endif
|
|
{
|
|
MakeNewDisk(vSonyNewDiskSize, NULL);
|
|
}
|
|
vSonyNewDiskWanted = false;
|
|
/* must be done after may have gotten disk */
|
|
}
|
|
#endif
|
|
if (RequestInsertDisk) {
|
|
RequestInsertDisk = false;
|
|
InsertADisk0();
|
|
}
|
|
}
|
|
|
|
#if NeedRequestIthDisk
|
|
if (0 != RequestIthDisk) {
|
|
Sony_InsertIth(RequestIthDisk);
|
|
RequestIthDisk = 0;
|
|
}
|
|
#endif
|
|
|
|
if (HaveCursorHidden != (WantCursorHidden
|
|
&& ! (gTrueBackgroundFlag || CurSpeedStopped)))
|
|
{
|
|
HaveCursorHidden = ! HaveCursorHidden;
|
|
if (HaveCursorHidden) {
|
|
(void) ShowCursor(FALSE);
|
|
} else {
|
|
(void) ShowCursor(TRUE);
|
|
SetCursor(LoadCursor(NULL, IDC_ARROW));
|
|
}
|
|
}
|
|
|
|
if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
|
|
MacMsgDisplayOn();
|
|
}
|
|
|
|
if (NeedWholeScreenDraw) {
|
|
NeedWholeScreenDraw = false;
|
|
ScreenChangedAll();
|
|
}
|
|
}
|
|
|
|
#if UseWinCE
|
|
/* Sip Status ON/OFF */
|
|
LOCALVAR bool SipOn = false;
|
|
#endif
|
|
|
|
LRESULT CALLBACK Win32WMProc(HWND hwnd,
|
|
UINT uMessage, WPARAM wparam, LPARAM lparam);
|
|
|
|
LRESULT CALLBACK Win32WMProc(HWND hwnd,
|
|
UINT uMessage, WPARAM wparam, LPARAM lparam)
|
|
{
|
|
switch (uMessage)
|
|
{
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT ps;
|
|
|
|
BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
|
|
#if VarFullScreen
|
|
if (UseFullScreen)
|
|
#endif
|
|
#if MayFullScreen
|
|
{
|
|
if (! FillRect(ps.hdc,
|
|
&ps.rcPaint,
|
|
GetStockObject(BLACK_BRUSH)))
|
|
{
|
|
/* ReportGetLastError(); */
|
|
}
|
|
}
|
|
#endif
|
|
if (MainWnd == hwnd) {
|
|
Screen_DrawAll();
|
|
}
|
|
EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
|
|
}
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
case WM_SYSKEYDOWN:
|
|
#if UseWinCE
|
|
SipOn = false;
|
|
|
|
{
|
|
SIPINFO r;
|
|
|
|
memset(&r, 0 , sizeof(SIPINFO));
|
|
r.cbSize = sizeof(SIPINFO);
|
|
if (SipGetInfo(&r)) {
|
|
SipOn = 0 != (r.fdwFlags & SIPF_ON);
|
|
}
|
|
}
|
|
|
|
if (wparam == 0xAE) {
|
|
break;
|
|
} else if ((! SipOn) && (wparam == VK_RETURN)) {
|
|
break;
|
|
} else if ((! SipOn)
|
|
&& (wparam >= VK_LEFT) && (wparam <= VK_DOWN))
|
|
{
|
|
break;
|
|
} else if (wparam == VK_CONTROL && CtrlMode) {
|
|
DoVKcode0(wparam, false);
|
|
CtrlMode = false;
|
|
break;
|
|
} else if (wparam == VK_CONTROL) {
|
|
DoVKcode0(wparam, true);
|
|
CtrlMode = true;
|
|
break;
|
|
}
|
|
#endif
|
|
if (! TestBit(lparam, 30)) { /* ignore repeats */
|
|
DoVKcode(wparam, lparam >> 24, true);
|
|
}
|
|
|
|
#if UseWinCE
|
|
return TRUE;
|
|
/*
|
|
So that hardware keys won't be
|
|
processed by the default handler
|
|
*/
|
|
#endif
|
|
|
|
break;
|
|
case WM_KEYUP:
|
|
case WM_SYSKEYUP:
|
|
#if UseWinCE
|
|
SipOn = false;
|
|
|
|
{
|
|
SIPINFO r;
|
|
|
|
memset(&r, 0 , sizeof(SIPINFO));
|
|
r.cbSize = sizeof(SIPINFO);
|
|
if (SipGetInfo(&r)) {
|
|
SipOn = 0 != (r.fdwFlags & SIPF_ON);
|
|
}
|
|
}
|
|
|
|
if (wparam == 0xAE) { /* to hide SoftInput panel */
|
|
SipShowIM(SIPF_OFF);
|
|
break;
|
|
} else if ((! SipOn) && (wparam == VK_RETURN)) {
|
|
/* DPad Action to show SIP */
|
|
/* Show SoftInput Panel */
|
|
SipShowIM(SIPF_ON);
|
|
break;
|
|
} else if ((! SipOn)
|
|
&& (wparam >= VK_LEFT) && (wparam <= VK_DOWN))
|
|
{
|
|
switch (wparam) {
|
|
case VK_LEFT:
|
|
if (ViewHStart < (ViewHSize / 2)) {
|
|
ViewHStart = 0;
|
|
} else {
|
|
ViewHStart -= (ViewHSize / 2);
|
|
}
|
|
break;
|
|
case VK_UP:
|
|
if (ViewVStart < (ViewVSize / 2)) {
|
|
ViewVStart = 0;
|
|
} else {
|
|
ViewVStart -= (ViewVSize / 2);
|
|
}
|
|
break;
|
|
case VK_RIGHT:
|
|
ViewHStart += (ViewHSize / 2);
|
|
if (ViewHStart >= (vMacScreenWidth - ViewHSize))
|
|
{
|
|
ViewHStart = vMacScreenWidth - ViewHSize;
|
|
}
|
|
break;
|
|
case VK_DOWN:
|
|
ViewVStart += (ViewVSize / 2);
|
|
if (ViewVStart
|
|
>= (vMacScreenHeight - ViewVSize))
|
|
{
|
|
ViewVStart = vMacScreenHeight - ViewVSize;
|
|
}
|
|
break;
|
|
}
|
|
Screen_DrawAll();
|
|
} else
|
|
if (wparam == VK_CONTROL && CtrlMode) {
|
|
break;
|
|
}
|
|
#endif
|
|
DoVKcode(wparam, lparam >> 24, false);
|
|
|
|
#if UseWinCE
|
|
return TRUE;
|
|
/*
|
|
So that hardware keys won't be
|
|
processed by the default handler
|
|
*/
|
|
#endif
|
|
|
|
break;
|
|
#if ItnlKyBdFix && ! UseWinCE
|
|
case WM_INPUTLANGCHANGE:
|
|
CheckKeyboardLayout();
|
|
return TRUE;
|
|
break;
|
|
#endif
|
|
|
|
case WM_CLOSE:
|
|
RequestMacOff = true;
|
|
break;
|
|
#if ! UseWinCE
|
|
case WM_QUERYENDSESSION:
|
|
if (AnyDiskInserted()) {
|
|
RequestMacOff = true;
|
|
return FALSE;
|
|
} else {
|
|
return TRUE;
|
|
}
|
|
break;
|
|
#endif
|
|
case WM_ACTIVATE:
|
|
if (MainWnd == hwnd) {
|
|
gTrueBackgroundFlag = (LOWORD(wparam) == WA_INACTIVE);
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
switch(LOWORD(wparam))
|
|
{
|
|
case ID_FILE_INSERTDISK1:
|
|
RequestInsertDisk = true;
|
|
break;
|
|
case ID_FILE_QUIT:
|
|
RequestMacOff = true;
|
|
break;
|
|
case ID_SPECIAL_MORECOMMANDS:
|
|
DoMoreCommandsMsg();
|
|
break;
|
|
case ID_HELP_ABOUT:
|
|
DoAboutMsg();
|
|
break;
|
|
}
|
|
break;
|
|
case WM_MOVE:
|
|
WndX = (int16_t) LOWORD(lparam);
|
|
WndY = (int16_t) HIWORD(lparam);
|
|
break;
|
|
case WM_SYSCHAR:
|
|
case WM_CHAR:
|
|
/* prevent any further processing */
|
|
break;
|
|
case WM_LBUTTONDOWN:
|
|
case WM_RBUTTONDOWN:
|
|
MousePositionNotify(LOWORD (lparam), HIWORD (lparam));
|
|
SetCurMouseButton(true);
|
|
break;
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONUP:
|
|
MousePositionNotify(LOWORD (lparam), HIWORD (lparam));
|
|
SetCurMouseButton(false);
|
|
break;
|
|
case WM_MOUSEMOVE:
|
|
#if UseWinCE
|
|
MousePositionNotify(LOWORD (lparam), HIWORD (lparam));
|
|
#endif
|
|
/* windows may have messed up cursor */
|
|
/*
|
|
there is no notification when the mouse moves
|
|
outside the window, and the cursor is automatically
|
|
changed
|
|
*/
|
|
if (! HaveCursorHidden) {
|
|
/* SetCursor(LoadCursor(NULL, IDC_ARROW)); */
|
|
}
|
|
break;
|
|
#if EnableDragDrop
|
|
case WM_CREATE:
|
|
DragAcceptFiles(hwnd, TRUE);
|
|
break;
|
|
case WM_DROPFILES:
|
|
DragFunc((HDROP) wparam);
|
|
break;
|
|
case WM_DESTROY:
|
|
DragAcceptFiles(hwnd, FALSE);
|
|
break;
|
|
#endif
|
|
default:
|
|
return DefWindowProc(hwnd, uMessage, wparam, lparam);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
LOCALFUNC bool RegisterOurClass(void)
|
|
{
|
|
WNDCLASS wc;
|
|
|
|
wc.style = CS_HREDRAW | CS_VREDRAW
|
|
#if ! UseWinCE
|
|
| CS_OWNDC
|
|
#endif
|
|
;
|
|
wc.lpfnWndProc = (WNDPROC)Win32WMProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = AppInstance;
|
|
wc.hIcon = LoadIcon(AppInstance, MAKEINTRESOURCE(IDI_VMAC));
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wc.hbrBackground = GetStockObject(BLACK_BRUSH);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = WndClassName;
|
|
|
|
if (! RegisterClass(&wc)) {
|
|
MacMsg("RegisterClass failed",
|
|
"Sorry, Mini vMac encountered errors"
|
|
" and cannot continue.", true);
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
LOCALPROC WaitForTheNextEvent(void)
|
|
{
|
|
MSG msg;
|
|
|
|
if (-1 != GetMessage(&msg, NULL, 0, 0)) {
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
LOCALPROC CheckForSystemEvents(void)
|
|
{
|
|
MSG msg;
|
|
uint8_t i = 0;
|
|
|
|
while ((i < 32) && (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))) {
|
|
DispatchMessage(&msg);
|
|
++i;
|
|
}
|
|
}
|
|
|
|
GLOBALOSGLUPROC WaitForNextTick(void)
|
|
{
|
|
label_retry:
|
|
CheckForSystemEvents();
|
|
CheckForSavedTasks();
|
|
|
|
if (ForceMacOff) {
|
|
return;
|
|
}
|
|
|
|
if (CurSpeedStopped) {
|
|
DoneWithDrawingForTick();
|
|
WaitForTheNextEvent();
|
|
goto label_retry;
|
|
}
|
|
|
|
if (ExtraTimeNotOver()) {
|
|
Sleep(NextIntTime - LastTime);
|
|
goto label_retry;
|
|
}
|
|
|
|
if (CheckDateTime()) {
|
|
#if SoundEnabled
|
|
Sound_SecondNotify();
|
|
#endif
|
|
}
|
|
|
|
if (! (gBackgroundFlag)) {
|
|
#if ! UseWinCE
|
|
CheckMouseState();
|
|
#endif
|
|
|
|
#if EnableGrabSpecialKeys
|
|
CheckForLostKeyUps();
|
|
#endif
|
|
}
|
|
|
|
OnTrueTime = TrueEmulatedTime;
|
|
|
|
#if dbglog_TimeStuff
|
|
dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
|
|
#endif
|
|
}
|
|
|
|
#if UseWinCE
|
|
LOCALFUNC bool Init_ChangeOrientation(void)
|
|
{
|
|
DEVMODE dm;
|
|
|
|
/* initialize the DEVMODE structure */
|
|
ZeroMemory(&dm, sizeof (dm));
|
|
dm.dmSize = sizeof (dm);
|
|
|
|
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
|
|
|
|
/* Backup old values */
|
|
oldOrientation = dm.dmOrientation;
|
|
oldDisplayOrientation = dm.dmDisplayOrientation;
|
|
|
|
|
|
/* Hide SIP (you can never tell...) */
|
|
SipShowIM(SIPF_OFF);
|
|
|
|
/* Switch to Landscape mode if possible */
|
|
dm.dmOrientation = DMORIENT_LANDSCAPE;
|
|
dm.dmDisplayOrientation = DMDO_90;
|
|
dm.dmFields = DM_ORIENTATION | DM_DISPLAYORIENTATION;
|
|
(void) ChangeDisplaySettingsEx(NULL, &dm, NULL, 0, 0);
|
|
/*
|
|
if (ChangeDisplaySettingsEx(NULL, &dm, NULL, 0, 0) !=
|
|
DISP_CHANGE_SUCCESSFUL)
|
|
{
|
|
MacMsg ("warning",
|
|
"Couldn't switch to Landscape mode.", false);
|
|
}
|
|
*/
|
|
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
#if UseWinCE
|
|
LOCALPROC Uninit_ChangeOrientation(void)
|
|
{
|
|
DEVMODE dm;
|
|
|
|
/* Restore old display orientation */
|
|
ZeroMemory(&dm, sizeof (dm));
|
|
dm.dmSize = sizeof(dm);
|
|
|
|
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
|
|
|
|
dm.dmOrientation = oldOrientation;
|
|
dm.dmDisplayOrientation = oldDisplayOrientation;
|
|
dm.dmFields = DM_ORIENTATION | DM_DISPLAYORIENTATION;
|
|
|
|
ChangeDisplaySettingsEx(NULL, &dm, 0, 0, 0);
|
|
}
|
|
#endif
|
|
|
|
|
|
/* ** code for handling hardware keys in Pocket PC devices ** */
|
|
|
|
#if UseWinCE
|
|
typedef BOOL (__stdcall *UnregisterFunc1Proc)(UINT, UINT);
|
|
LOCALVAR HINSTANCE hCoreDLL = NULL;
|
|
#endif
|
|
|
|
#if UseWinCE
|
|
LOCALFUNC bool InitHotKeys(void)
|
|
{
|
|
UnregisterFunc1Proc procUndergisterFunc;
|
|
int i;
|
|
|
|
hCoreDLL = LoadLibrary(TEXT("coredll.dll"));
|
|
if (! hCoreDLL) {
|
|
MacMsg ("Fatal", "Could not load coredll.dll", true);
|
|
} else {
|
|
procUndergisterFunc =
|
|
(UnregisterFunc1Proc) GetProcAddress(hCoreDLL,
|
|
TEXT("UnregisterFunc1"));
|
|
if (! procUndergisterFunc) {
|
|
MacMsg ("Fatal",
|
|
"Could not get UnregisterFunc1 procedure", true);
|
|
} else {
|
|
for (i = 0xc1; i <= 0xcf; ++i) {
|
|
procUndergisterFunc(MOD_WIN, i);
|
|
RegisterHotKey(MainWnd, i, MOD_WIN, i);
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
#if UseWinCE
|
|
LOCALPROC UninitHotKeys(void)
|
|
{
|
|
if (! hCoreDLL) {
|
|
FreeLibrary(hCoreDLL);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#include "PROGMAIN.h"
|
|
|
|
/* ************************ */
|
|
|
|
LOCALPROC ZapOSGLUVars(void)
|
|
{
|
|
InitDrives();
|
|
ZapWinStateVars();
|
|
}
|
|
|
|
LOCALPROC ReserveAllocAll(void)
|
|
{
|
|
#if dbglog_HAVE
|
|
dbglog_ReserveAlloc();
|
|
#endif
|
|
ReserveAllocOneBlock(&ROM, kROM_Size, 5, false);
|
|
ReserveAllocOneBlock(&screencomparebuff,
|
|
vMacScreenNumBytes, 5, true);
|
|
#if UseControlKeys
|
|
ReserveAllocOneBlock(&CntrlDisplayBuff,
|
|
vMacScreenNumBytes, 5, false);
|
|
#endif
|
|
#if EnableScalingBuff
|
|
{
|
|
uint32_t n = vMacScreenMonoNumBytes
|
|
#if EnableMagnify
|
|
* WindowScale * WindowScale
|
|
#endif
|
|
;
|
|
if ((vMacScreenDepth == 1) && (vMacScreenNumBytes * 2 > n)) {
|
|
n = vMacScreenNumBytes * 2;
|
|
}
|
|
else if ((vMacScreenDepth >= 4) && (vMacScreenNumBytes > n)) {
|
|
n = vMacScreenNumBytes;
|
|
}
|
|
ReserveAllocOneBlock(&ScalingBuff, n, 5, false);
|
|
}
|
|
#endif
|
|
#if SoundEnabled
|
|
ReserveAllocOneBlock((uint8_t * *)&TheSoundBuffer,
|
|
dbhBufferSize, 5, false);
|
|
#endif
|
|
|
|
EmulationReserveAlloc();
|
|
}
|
|
|
|
LOCALFUNC bool AllocMemory(void)
|
|
{
|
|
uimr n;
|
|
bool IsOk = false;
|
|
|
|
ReserveAllocOffset = 0;
|
|
ReserveAllocBigBlock = nullpr;
|
|
ReserveAllocAll();
|
|
n = ReserveAllocOffset;
|
|
ReserveAllocBigBlock =
|
|
(uint8_t *)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, n);
|
|
if (NULL == ReserveAllocBigBlock) {
|
|
MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, true);
|
|
} else {
|
|
ReserveAllocOffset = 0;
|
|
ReserveAllocAll();
|
|
if (n != ReserveAllocOffset) {
|
|
/* oops, program error */
|
|
} else {
|
|
IsOk = true;
|
|
}
|
|
}
|
|
|
|
return IsOk;
|
|
}
|
|
|
|
LOCALPROC UnallocMemory(void)
|
|
{
|
|
if (nullpr != ReserveAllocBigBlock) {
|
|
if (GlobalFree(ReserveAllocBigBlock) != NULL) {
|
|
MacMsg("error", "GlobalFree failed", false);
|
|
}
|
|
}
|
|
}
|
|
|
|
LOCALFUNC bool InitOSGLU(void)
|
|
{
|
|
if (AllocMemory())
|
|
#if dbglog_HAVE
|
|
if (dbglog_open())
|
|
#endif
|
|
if (RegisterOurClass())
|
|
if (ScanCommandLine())
|
|
if (LoadInitialImages())
|
|
#if InstallFileIcons
|
|
if (RegisterInRegistry())
|
|
#endif
|
|
if (LoadMacRom())
|
|
#if UseWinCE
|
|
if (Init_ChangeOrientation())
|
|
#endif
|
|
if (ReCreateMainWindow())
|
|
if (InitWinKey2Mac())
|
|
if (InitTheCursor())
|
|
#if UseWinCE
|
|
if (InitHotKeys())
|
|
#endif
|
|
if (Init60thCheck())
|
|
if (WaitForRom())
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
LOCALPROC UnInitOSGLU(void)
|
|
{
|
|
#if (TimeResolution != 0)
|
|
Timer_Suspend();
|
|
#endif
|
|
MouseCaptureSet(false);
|
|
|
|
if (MacMsgDisplayed) {
|
|
MacMsgDisplayOff();
|
|
}
|
|
|
|
#if MayFullScreen
|
|
UnGrabTheMachine();
|
|
#endif
|
|
#if SoundEnabled
|
|
Sound_Stop();
|
|
#endif
|
|
#if IncludePbufs
|
|
UnInitPbufs();
|
|
#endif
|
|
UnInitDrives();
|
|
|
|
ForceShowCursor();
|
|
#if UseWinCE
|
|
Uninit_ChangeOrientation();
|
|
UninitHotKeys();
|
|
#endif
|
|
|
|
#if EnableShellLinks
|
|
UninitCOM();
|
|
#endif
|
|
|
|
if (! gTrueBackgroundFlag) {
|
|
CheckSavedMacMsg();
|
|
}
|
|
|
|
DisposeMainWindow();
|
|
|
|
#if dbglog_HAVE
|
|
dbglog_close();
|
|
#endif
|
|
|
|
UnallocMemory();
|
|
}
|
|
|
|
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|
LPTSTR lpCmdLine, int nCmdShow)
|
|
{
|
|
UnusedParam(hPrevInstance);
|
|
AppInstance = hInstance;
|
|
CmdShow = nCmdShow;
|
|
CommandLine = lpCmdLine;
|
|
|
|
GetWndTitle();
|
|
#if UseWinCE
|
|
if (AlreadyRunningCheck()) {
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
ZapOSGLUVars();
|
|
if (InitOSGLU()) {
|
|
ProgramMain();
|
|
}
|
|
UnInitOSGLU();
|
|
|
|
return(0);
|
|
}
|