ref: d488fabe62aabd0d42421eb3e423a9308ae1fa13
dir: /src/OSGLUWIN.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 "CNFGRAPI.h" #include "SYSDEPNS.h" #include "ENDIANAC.h" #include "MYOSGLUE.h" /* --- adapting to API/ABI version differences --- */ #ifdef UNICODE #define MyUseUni 1 #else #define MyUseUni 0 #endif #ifdef _WIN32_WCE #define UseWinCE 1 #else #define UseWinCE 0 #endif #define My_CSIDL_APPDATA 0x001a typedef BOOL (WINAPI *SHGetSpecialFolderPathProcPtr) ( HWND hwndOwner, LPTSTR lpszPath, int nFolder, BOOL fCreate ); LOCALVAR SHGetSpecialFolderPathProcPtr MySHGetSpecialFolderPath = NULL; LOCALVAR blnr DidSHGetSpecialFolderPath = falseblnr; LOCALFUNC blnr HaveMySHGetSpecialFolderPath(void) { if (! DidSHGetSpecialFolderPath) { HMODULE hLibModule = LoadLibrary(TEXT("shell32.dll")); if (NULL != hLibModule) { MySHGetSpecialFolderPath = (SHGetSpecialFolderPathProcPtr) GetProcAddress(hLibModule, #if MyUseUni TEXT("SHGetSpecialFolderPathW") #else TEXT("SHGetSpecialFolderPathA") #endif ); /* FreeLibrary(hLibModule); */ } DidSHGetSpecialFolderPath = trueblnr; } return (MySHGetSpecialFolderPath != NULL); } /* --- end of adapting to API/ABI version differences --- */ #include "STRCONST.h" #if MyUseUni #define NeedCell2UnicodeMap 1 #else #define NeedCell2WinAsciiMap 1 #endif #include "INTLCHAR.h" LOCALPROC NativeStrFromCStr(LPTSTR r, char *s, blnr AddEllipsis) { ui3b ps[ClStrMaxLength]; int i; int L; ClStrFromSubstCStr(&L, ps, s); for (i = 0; i < L; ++i) { r[i] = (TCHAR) #if MyUseUni Cell2UnicodeMap[ps[i]]; #else Cell2WinAsciiMap[ps[i]]; #endif } if (AddEllipsis) { #if MyUseUni 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 blnr GetAppDir(LPTSTR pathName) /* be sure at least _MAX_PATH long! */ { if (GetModuleFileName(AppInstance, pathName, _MAX_PATH) == 0) { /* MacMsg("error", "GetModuleFileName failed", falseblnr); */ } else { LPTSTR p = FindLastTerm(pathName, (TCHAR)('\\')); if (p == nullpr) { /* MacMsg("error", "strrchr failed", falseblnr); */ } else { *--p = (TCHAR)('\0'); return trueblnr; } } return falseblnr; } /* --- sending debugging info to file --- */ #if dbglog_HAVE LOCALVAR HANDLE dbglog_File = INVALID_HANDLE_VALUE; LOCALFUNC blnr 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 */ || ((ui5b)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 "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 MyMoveBytes(anyp srcPtr, anyp destPtr, si5b 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, ui5b 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(ui5b 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 ui3p PbufLock(tPbuf i) { HGLOBAL h = PbufDat[i]; return (ui3p)GlobalLock(h); } #endif #if IncludePbufs LOCALPROC PbufUnlock(tPbuf i) { (void) GlobalUnlock(PbufDat[i]); } #endif #if IncludePbufs GLOBALOSGLUPROC PbufTransfer(ui3p Buffer, tPbuf i, ui5r offset, ui5r count, blnr IsWrite) { HGLOBAL h = PbufDat[i]; ui3p 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 "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 blnr UseFullScreen = (WantInitFullScreen != 0); #endif #if EnableMagnify LOCALVAR blnr UseMagnify = (WantInitMagnify != 0); #endif #if MayFullScreen LOCALVAR short hOffset; LOCALVAR short vOffset; #endif /* cursor hiding */ LOCALVAR blnr HaveCursorHidden = falseblnr; LOCALVAR blnr WantCursorHidden = falseblnr; LOCALPROC ForceShowCursor(void) { if (HaveCursorHidden) { HaveCursorHidden = falseblnr; (void) ShowCursor(TRUE); SetCursor(LoadCursor(NULL, IDC_ARROW)); } } /* cursor moving */ LOCALFUNC blnr MyMoveMouse(si4b h, si4b v) { POINT NewMousePos; ui5b difftime; blnr 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 *= MyWindowScale; y *= MyWindowScale; } #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 = falseblnr; } else { IsOk = (x == NewMousePos.x) && (y == NewMousePos.y); } difftime = (ui5b)(GetTickCount() - StartTime); } while ((! IsOk) && (difftime < 100)); return IsOk; } #if EnableFSMouseMotion LOCALPROC StartSaveMouseMotion(void) { if (! HaveMouseMotion) { if (MyMoveMouse(ViewHStart + (ViewHSize / 2), ViewVStart + (ViewVSize / 2))) { SavedMouseH = ViewHStart + (ViewHSize / 2); SavedMouseV = ViewVStart + (ViewVSize / 2); HaveMouseMotion = trueblnr; } } } #endif #if EnableFSMouseMotion LOCALPROC StopSaveMouseMotion(void) { if (HaveMouseMotion) { (void) MyMoveMouse(CurMouseH, CurMouseV); HaveMouseMotion = falseblnr; } } #endif LOCALVAR blnr MyMouseCaptured = falseblnr; LOCALPROC MyMouseCaptureSet(blnr v) { if (v != MyMouseCaptured) { if (v) { (void) SetCapture(MainWnd); } else { (void) ReleaseCapture(); } MyMouseCaptured = v; } } LOCALPROC SetCurMouseButton(blnr v) { MyMouseButtonSet(v); MyMouseCaptureSet(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 ui3b MyVkMapA[256]; #endif #if ItnlKyBdFix LOCALPROC MyVkSwapZY(void) { MyVkMapA['Z'] = 'Y'; MyVkMapA['Y'] = 'Z'; } #endif #if ItnlKyBdFix LOCALPROC MyVkSwapGraveQuote(void) { MyVkMapA[myVK_Grave] = myVK_SingleQuote; MyVkMapA[myVK_SingleQuote] = myVK_Grave; } #endif #if ItnlKyBdFix LOCALPROC MyVkSwapSlashSubtract(void) { MyVkMapA[myVK_Slash] = myVK_Subtract; MyVkMapA[myVK_Subtract] = myVK_Slash; } #endif #if ItnlKyBdFix LOCALPROC MyVkSwapAQZWGraveQuote(void) { MyVkSwapGraveQuote(); MyVkMapA['A'] = 'Q'; MyVkMapA['Q'] = 'A'; MyVkMapA['Z'] = 'W'; MyVkMapA['W'] = 'Z'; } #endif #if ItnlKyBdFix LOCALPROC MyVkMapBelgian(void) { MyVkSwapAQZWGraveQuote(); MyVkMapA['M'] = myVK_SemiColon; MyVkMapA[myVK_SemiColon] = myVK_RightBracket; MyVkMapA[myVK_RightBracket] = myVK_LeftBracket; MyVkMapA[myVK_LeftBracket] = myVK_Subtract; MyVkMapA[myVK_Subtract] = myVK_Equal; MyVkMapA[myVK_Equal] = myVK_Slash; MyVkMapA[myVK_Slash] = myVK_Period; MyVkMapA[myVK_Period] = myVK_Comma; MyVkMapA[myVK_Comma] = 'M'; } #endif #if ItnlKyBdFix LOCALPROC MyVkMapSwiss(void) { MyVkSwapZY(); MyVkMapA[myVK_OEM_8] = myVK_BackSlash; MyVkMapA[myVK_BackSlash] = myVK_SingleQuote; MyVkMapA[myVK_SingleQuote] = myVK_SemiColon; MyVkMapA[myVK_SemiColon] = myVK_LeftBracket; MyVkMapA[myVK_LeftBracket] = myVK_Subtract; MyVkMapA[myVK_Subtract] = myVK_Slash; MyVkMapA[myVK_Slash] = myVK_Grave; MyVkMapA[myVK_Grave] = myVK_RightBracket; MyVkMapA[myVK_RightBracket] = myVK_Equal; } #endif #if ItnlKyBdFix LOCALPROC MyVkMapDanish(void) { MyVkMapA[myVK_Equal] = myVK_Subtract; MyVkMapA[myVK_Subtract] = myVK_Slash; MyVkMapA[myVK_Slash] = myVK_BackSlash; MyVkMapA[myVK_BackSlash] = myVK_Grave; MyVkMapA[myVK_Grave] = myVK_SemiColon; MyVkMapA[myVK_SemiColon] = myVK_RightBracket; MyVkMapA[myVK_RightBracket] = myVK_LeftBracket; MyVkMapA[myVK_LeftBracket] = myVK_Equal; } #endif #if ItnlKyBdFix LOCALPROC MyVkMapBritish(void) { MyVkMapA[myVK_OEM_8] = myVK_Grave; MyVkMapA[myVK_Grave] = myVK_SingleQuote; MyVkMapA[myVK_SingleQuote] = myVK_BackSlash; MyVkMapA[myVK_BackSlash] = myVK_OEM_102; } #endif #if ItnlKyBdFix LOCALPROC MyVkMapSpanish(void) { MyVkMapA[myVK_SemiColon] = myVK_LeftBracket; MyVkMapA[myVK_LeftBracket] = myVK_Subtract; MyVkMapA[myVK_Subtract] = myVK_Slash; MyVkMapA[myVK_Slash] = myVK_BackSlash; MyVkMapA[myVK_BackSlash] = myVK_Grave; MyVkMapA[myVK_Grave] = myVK_SemiColon; MyVkMapA[myVK_RightBracket] = myVK_Equal; MyVkMapA[myVK_Equal] = myVK_RightBracket; } #endif #if ItnlKyBdFix LOCALPROC MyVkMapDutch(void) { MyVkSwapGraveQuote(); MyVkMapA[myVK_SemiColon] = myVK_RightBracket; MyVkMapA[myVK_RightBracket] = myVK_LeftBracket; MyVkMapA[myVK_LeftBracket] = myVK_Subtract; MyVkMapA[myVK_Subtract] = myVK_Slash; MyVkMapA[myVK_Slash] = myVK_Equal; MyVkMapA[myVK_Equal] = myVK_SemiColon; } #endif #if ItnlKyBdFix LOCALPROC MyVkMapGreekIBM(void) { MyVkSwapSlashSubtract(); MyVkMapA[myVK_LeftBracket] = myVK_Equal; MyVkMapA[myVK_Equal] = myVK_LeftBracket; } #endif #if ItnlKyBdFix LOCALPROC MyVkMapFrench(void) { MyVkSwapAQZWGraveQuote(); MyVkMapA['M'] = myVK_SemiColon; MyVkMapA[myVK_SemiColon] = myVK_RightBracket; MyVkMapA[myVK_RightBracket] = myVK_LeftBracket; MyVkMapA[myVK_LeftBracket] = myVK_Subtract; MyVkMapA[myVK_Comma] = 'M'; MyVkMapA[myVK_Period] = myVK_Comma; MyVkMapA[myVK_Slash] = myVK_Period; MyVkMapA[myVK_OEM_8] = myVK_Slash; } #endif #if ItnlKyBdFix LOCALPROC MyVkMapGerman(void) { MyVkSwapZY(); MyVkMapSpanish(); } #endif #if ItnlKyBdFix LOCALPROC MyVkMapBosnian(void) { MyVkSwapZY(); /* not in Windows 95 */ MyVkSwapSlashSubtract(); } #endif #if ItnlKyBdFix LOCALPROC MyVkMapBulgarian(void) { MyVkMapA[myVK_OEM_8] = myVK_Comma; MyVkMapA[myVK_Comma] = 'Q'; MyVkMapA['Q'] = myVK_Period; MyVkMapA[myVK_Period] = myVK_Equal; } #endif #if ItnlKyBdFix LOCALPROC MyVkMapFromLayout(uimr sv) { int i; for (i = 0; i < 256; ++i) { MyVkMapA[i] = i; } switch (sv) { case 0x00000409: /* United States 101 */ break; case 0x0000041c: /* Albanian; */ MyVkSwapZY(); break; case 0x0000042B: /* Armenian Eastern; */ MyVkMapDutch(); break; case 0x0001042B: /* Armenian Western; */ MyVkMapDutch(); break; case 0x0000042C: /* not in Windows 95 */ /* Azeri Latin */ MyVkMapBritish(); break; case 0x0001080C: /* Belgian (comma) */ MyVkMapBelgian(); break; case 0x0000080c: /* Belgian French */ MyVkMapBelgian(); break; case 0x00000813: /* not in Windows 95 */ /* Belgian (period); */ MyVkMapBelgian(); break; case 0x0000141A: /* not in Windows 95 */ /* Bosnian */ MyVkMapBosnian(); break; case 0x00000809: /* British / United Kingdom */ MyVkMapBritish(); break; case 0x00000452: /* not in Windows 95 */ /* United Kingdom Extended */ MyVkMapBritish(); break; case 0x00000402: /* Bulgarian */ /* not same in Windows 95 */ MyVkMapBulgarian(); break; case 0x00030402: /* Bulgarian */ MyVkMapBulgarian(); break; case 0x00020402: /* Bulgarian (Phonetic) */ MyVkMapBosnian(); break; case 0x00001009: /* Canadian Multilingual */ /* not in Windows 95 */ MyVkSwapGraveQuote(); break; case 0x00011009: /* Canadian Standard */ MyVkSwapGraveQuote(); break; case 0x0000041a: /* Croatian */ MyVkMapBosnian(); break; case 0x00000405: /* Czech */ MyVkMapBosnian(); #if 0 /* but Windows 7 gives */ MyVkSwapZY(); MyVkMapA[myVK_Equal] = myVK_Subtract; MyVkMapA[myVK_Subtract] = myVK_Slash; MyVkMapA[myVK_Slash] = myVK_Equal; #endif break; case 0x00020405: /* Czech (Programmers) */ /* only in Windows 95 */ /* MyVkSwapZY(); */ break; case 0x00010405: /* Czech (Qwerty) */ /* only in Windows 95 */ /* MyVkSwapZY(); */ break; case 0x00000406: /* Danish */ MyVkMapDanish(); break; case 0x00000413: /* Dutch */ MyVkMapDutch(); break; case 0x00000425: /* Estonian */ MyVkMapA[myVK_Grave] = myVK_LeftBracket; MyVkMapA[myVK_LeftBracket] = myVK_RightBracket; MyVkMapA[myVK_RightBracket] = myVK_Slash; MyVkMapA[myVK_Slash] = myVK_SingleQuote; MyVkMapA[myVK_SingleQuote] = myVK_Grave; /* only in Windows 95 ? */ /* MyVkMapA[VK_DECIMAL] = VK_DELETE; */ break; case 0x00000438: /* Faeroe Islands */ MyVkMapDanish(); break; case 0x0000040b: /* Finnish */ MyVkMapDanish(); break; case 0x0001083B: /* not in Windows 95 */ /* Finnish with Sami */ MyVkMapDanish(); break; case 0x0000040c: /* v = kMyKbdFrench; */ /* French */ MyVkMapFrench(); break; case 0x00000c0c: /* French Canadian */ MyVkSwapGraveQuote(); break; case 0x00011809: /* not in Windows 95 */ /* Gaelic */ MyVkMapBritish(); break; case 0x00010407: /* German (IBM) */ MyVkMapGerman(); break; case 0x00000407: /* German (Standard) */ MyVkMapGerman(); break; case 0x00010408: /* Greek IBM 220 */ /* not in Windows 95 */ MyVkMapGreekIBM(); break; case 0x00030408: /* Greek IBM 319 */ /* not in Windows 95 */ MyVkMapGreekIBM(); break; case 0x00020408: /* Greek Latin IBM 220 */ /* not in Windows 95 */ MyVkSwapSlashSubtract(); break; case 0x00040408: /* Greek Latin IBM 319 */ /* not in Windows 95 */ MyVkSwapSlashSubtract(); break; case 0x0000040e: /* Hungarian */ MyVkMapBosnian(); MyVkMapA[myVK_Grave] = '0'; MyVkMapA['0'] = myVK_Grave; break; case 0x0001040E: /* Hungarian (101 Keys) */ MyVkMapA[myVK_Grave] = '0'; MyVkMapA['0'] = myVK_Grave; break; case 0x0000040f: /* Icelandic */ MyVkMapDanish(); break; case 0x00001809: /* Irish */ MyVkMapBritish(); break; case 0x00000410: /* Italian */ MyVkMapSpanish(); break; case 0x00010410: /* Italian 142 */ MyVkMapSpanish(); break; case 0x0000080a: /* Latin American */ MyVkMapSpanish(); break; case 0x0000046E: /* Luxembourgish */ MyVkMapSwiss(); break; case 0x00000414: /* Norwegian */ MyVkMapDanish(); break; case 0x0000043B: /* Norwegian with Sami */ MyVkMapDanish(); break; case 0x00010415: /* Polish (214) */ MyVkSwapZY(); /* not in windows 95 */ MyVkMapA[myVK_Equal] = myVK_Subtract; MyVkMapA[myVK_Subtract] = myVK_Slash; MyVkMapA[myVK_Slash] = myVK_Equal; break; case 0x00010416: /* Porguguese (Brazilian ABNT2) */ /* MyVkMapA[myVK_OEM_8] = ??; */ /* MyVkMapA[VK_SEPARATOR] = ??; */ break; case 0x00000816: /* Porguguese (Standard) */ MyVkMapA[myVK_SemiColon] = myVK_RightBracket; MyVkMapA[myVK_RightBracket] = myVK_Equal; MyVkMapA[myVK_Equal] = myVK_LeftBracket; MyVkMapA[myVK_LeftBracket] = myVK_Subtract; MyVkMapA[myVK_Subtract] = myVK_Slash; MyVkMapA[myVK_Slash] = myVK_BackSlash; MyVkMapA[myVK_BackSlash] = myVK_Grave; MyVkMapA[myVK_Grave] = myVK_SemiColon; break; case 0x00000418: /* Romanian (Legacy) */ MyVkSwapZY(); /* only in Windows 95 */ /* MyVkSwapSlashSubtract(); */ break; case 0x0002083B: /* Sami Extended Finland-Sweden */ MyVkMapDanish(); break; case 0x0001043B: /* Sami Extended Norway */ MyVkMapDanish(); break; case 0x00010C1A: /* in Windows 95 */ /* Serbian (Latin) */ MyVkSwapZY(); break; case 0x0000081A: /* not in Windows 95 */ /* Serbian (Latin) */ MyVkMapBosnian(); break; case 0x0000041b: /* Slovak */ MyVkMapBosnian(); /* not in Windows 95 */ MyVkMapA[myVK_OEM_8] = myVK_Equal; break; case 0x00000424: /* Slovenian */ MyVkMapBosnian(); break; case 0x0000040A: /* Spanish, not windows 95 */ MyVkMapSpanish(); break; case 0x0001040A: /* Spanish Variation, not windows 95 */ MyVkMapA[myVK_OEM_8] = myVK_Slash; MyVkMapA[myVK_Slash] = myVK_BackSlash; MyVkMapA[myVK_BackSlash] = myVK_Grave; MyVkMapA[myVK_Grave] = myVK_SemiColon; MyVkMapA[myVK_SemiColon] = myVK_RightBracket; MyVkMapA[myVK_RightBracket] = myVK_LeftBracket; MyVkMapA[myVK_LeftBracket] = myVK_Equal; break; case 0x00000c0a: /* kMyKbdSpanish; */ /* Spanish Modern, windows 95 */ MyVkMapSpanish(); break; case 0x00000403: /* Spanish Traditional */ MyVkMapSpanish(); break; case 0x0000041d: /* Swedish */ MyVkMapDanish(); break; case 0x0000083B: /* not in windows 95 */ /* Swedish with Sami */ MyVkMapDanish(); break; case 0x0000100c: /* Swiss French */ MyVkMapSwiss(); break; case 0x00000807: /* Swiss German */ MyVkMapSwiss(); break; case 0x0000085D: /* Inuktitut Latin */ /* in windows 7, not XP */ MyVkMapBritish(); break; case 0x0001045D: /* Inuktitut - Naqittaut */ MyVkMapBritish(); break; case 0x0000046F: /* Greenlandic */ MyVkMapDanish(); break; case 0x00020427: /* Lithuanian Standard */ MyVkMapDanish(); break; case 0x0000042f: /* Macedonian (FYROM) - Standard */ MyVkMapBosnian(); break; case 0x0000042E: /* Sorbian Standard (Legacy) */ MyVkMapGerman(); break; case 0x0001042E: /* Sorbian Extended */ MyVkMapGerman(); break; case 0x0002042E: /* Sorbian Standard */ MyVkMapGerman(); break; case 0x00000488: /* Wolof */ MyVkMapFrench(); break; case 0x0000041f: /* Turkish (Q type) */ /* windows 95 */ /* MyVkMapA[myVK_Equal] = myVK_Subtract; */ /* MyVkMapA[myVK_Subtract] = myVK_Equal; */ /* not windows 95 */ MyVkMapA[myVK_OEM_8] = myVK_Subtract; MyVkMapA[myVK_Subtract] = myVK_Equal; MyVkMapA[myVK_Comma] = myVK_BackSlash; MyVkMapA[myVK_BackSlash] = myVK_Period; MyVkMapA[myVK_Period] = myVK_Slash; MyVkMapA[myVK_Slash] = myVK_Comma; break; case 0x00010409: /* United States Dvorak */ MyVkMapA[myVK_LeftBracket] = myVK_Subtract; MyVkMapA[myVK_RightBracket] = myVK_Equal; MyVkMapA[myVK_SingleQuote] = 'Q'; MyVkMapA[myVK_Comma] = 'W'; MyVkMapA[myVK_Period] = 'E'; MyVkMapA['P'] = 'R'; MyVkMapA['Y'] = 'T'; MyVkMapA['F'] = 'Y'; MyVkMapA['G'] = 'U'; MyVkMapA['C'] = 'I'; MyVkMapA['R'] = 'O'; MyVkMapA['L'] = 'P'; MyVkMapA[myVK_Slash] = myVK_LeftBracket; MyVkMapA[myVK_Equal] = myVK_RightBracket; MyVkMapA['O'] = 'S'; MyVkMapA['E'] = 'D'; MyVkMapA['U'] = 'F'; MyVkMapA['I'] = 'G'; MyVkMapA['D'] = 'H'; MyVkMapA['H'] = 'J'; MyVkMapA['T'] = 'K'; MyVkMapA['N'] = 'L'; MyVkMapA['S'] = myVK_SemiColon; MyVkMapA[myVK_Subtract] = myVK_SingleQuote; MyVkMapA[myVK_SemiColon] = 'Z'; MyVkMapA['Q'] = 'X'; MyVkMapA['J'] = 'C'; MyVkMapA['K'] = 'V'; MyVkMapA['X'] = 'B'; MyVkMapA['B'] = 'N'; MyVkMapA['W'] = myVK_Comma; MyVkMapA['V'] = myVK_Period; MyVkMapA['Z'] = myVK_Slash; break; #if 0 /* too complicated, don't bother with */ case 0x0x00000426: /* Latvian */ MyVkMapA['F'] = myVK_Equal; MyVkMapA['G'] = 'W'; MyVkMapA['J'] = 'E'; MyVkMapA['M'] = 'T'; MyVkMapA['V'] = 'Y'; MyVkMapA['N'] = 'U'; MyVkMapA['Z'] = 'I'; MyVkMapA['W'] = 'O'; MyVkMapA['X'] = 'P'; MyVkMapA['Y'] = myVK_LeftBracket; MyVkMapA['H'] = myVK_RightBracket; MyVkMapA[myVK_SemiColon] = 'A'; MyVkMapA['U'] = 'S'; MyVkMapA['S'] = 'D'; MyVkMapA['I'] = 'F'; MyVkMapA['L'] = 'G'; MyVkMapA['D'] = 'H'; MyVkMapA['A'] = 'J'; MyVkMapA['T'] = 'K'; MyVkMapA['E'] = 'L'; MyVkMapA['C'] = myVK_SemiColon; MyVkMapA[myVK_LeftBracket] = 'Z'; MyVkMapA['B'] = 'X'; MyVkMapA[myVK_RightBracket] = 'C'; MyVkMapA['K'] = 'V'; MyVkMapA['P'] = 'B'; MyVkMapA['O'] = 'N'; MyVkMapA[myVK_OEM_8] = 'M'; break; case 0x0001041F: /* Turkish (F type) */ MyVkMapA[myVK_Equal] = myVK_Subtract; MyVkMapA[myVK_Subtract] = myVK_Equal; MyVkMapA['F'] = 'Q'; MyVkMapA['G'] = 'W'; MyVkMapA[myVK_SemiColon] = 'E'; MyVkMapA['I'] = 'R'; MyVkMapA['O'] = 'T'; MyVkMapA['D'] = 'Y'; MyVkMapA['R'] = 'U'; MyVkMapA['N'] = 'I'; MyVkMapA['H'] = 'O'; MyVkMapA['Q'] = myVK_LeftBracket; MyVkMapA['W'] = myVK_RightBracket; MyVkMapA['U'] = 'A'; MyVkMapA[myVK_LeftBracket] = 'S'; MyVkMapA['E'] = 'D'; MyVkMapA['A'] = 'F'; MyVkMapA[myVK_RightBracket] = 'G'; MyVkMapA['T'] = 'H'; MyVkMapA['K'] = 'J'; MyVkMapA['M'] = 'K'; MyVkMapA['Y'] = myVK_SemiColon; MyVkMapA['X'] = myVK_BackSlash; MyVkMapA['J'] = 'Z'; MyVkMapA[myVK_BackSlash] = 'X'; MyVkMapA['V'] = 'C'; MyVkMapA['C'] = 'V'; MyVkMapA[myVK_Slash] = 'B'; MyVkMapA['Z'] = 'N'; MyVkMapA['S'] = 'M'; MyVkMapA['B'] = myVK_Comma; MyVkMapA[myVK_Comma] = myVK_Slash; break; case 0x00030409: /* United States LH Dvorak */ MyVkMapA[myVK_LeftBracket] = '1'; MyVkMapA[myVK_RightBracket] = '2'; MyVkMapA[myVK_Slash] = '3'; MyVkMapA['P'] = '4'; MyVkMapA['F'] = '5'; MyVkMapA['M'] = '6'; MyVkMapA['L'] = '7'; MyVkMapA['J'] = '8'; MyVkMapA['4'] = '9'; MyVkMapA['3'] = '0'; MyVkMapA['2'] = myVK_Subtract; MyVkMapA['1'] = myVK_Equal; MyVkMapA[myVK_SemiColon] = 'Q'; MyVkMapA['Q'] = 'W'; MyVkMapA['B'] = 'E'; MyVkMapA['Y'] = 'R'; MyVkMapA['U'] = 'T'; MyVkMapA['R'] = 'Y'; MyVkMapA['S'] = 'U'; MyVkMapA['O'] = 'I'; MyVkMapA[myVK_Period] = 'O'; MyVkMapA['6'] = 'P'; MyVkMapA['5'] = myVK_LeftBracket; MyVkMapA[myVK_Equal] = myVK_RightBracket; MyVkMapA[myVK_Subtract] = 'A'; MyVkMapA['K'] = 'S'; MyVkMapA['C'] = 'D'; MyVkMapA['D'] = 'F'; MyVkMapA['T'] = 'G'; MyVkMapA['E'] = 'J'; MyVkMapA['A'] = 'K'; MyVkMapA['Z'] = 'L'; MyVkMapA['8'] = myVK_SemiColon; MyVkMapA['7'] = myVK_SingleQuote; MyVkMapA[myVK_SingleQuote] = 'Z'; MyVkMapA['G'] = 'C'; MyVkMapA['W'] = 'B'; MyVkMapA['I'] = 'M'; MyVkMapA['0'] = myVK_Period; MyVkMapA['9'] = myVK_Slash; break; case 0x00040409: /* United States RH Dvorak */ MyVkMapA['J'] = '5'; MyVkMapA['L'] = '6'; MyVkMapA['M'] = '7'; MyVkMapA['F'] = '8'; MyVkMapA['P'] = '9'; MyVkMapA[myVK_Slash] = '0'; MyVkMapA[myVK_LeftBracket] = myVK_Subtract; MyVkMapA[myVK_RightBracket] = myVK_Equal; MyVkMapA['5'] = 'Q'; MyVkMapA['6'] = 'W'; MyVkMapA['Q'] = 'E'; MyVkMapA[myVK_Period] = 'R'; MyVkMapA['O'] = 'T'; MyVkMapA['R'] = 'Y'; MyVkMapA['S'] = 'U'; MyVkMapA['U'] = 'I'; MyVkMapA['Y'] = 'O'; MyVkMapA['B'] = 'P'; MyVkMapA[myVK_SemiColon] = myVK_LeftBracket; MyVkMapA[myVK_Equal] = myVK_RightBracket; MyVkMapA['7'] = 'A'; MyVkMapA['8'] = 'S'; MyVkMapA['Z'] = 'D'; MyVkMapA['A'] = 'F'; MyVkMapA['E'] = 'G'; MyVkMapA['T'] = 'J'; MyVkMapA['D'] = 'K'; MyVkMapA['C'] = 'L'; MyVkMapA['K'] = myVK_SemiColon; MyVkMapA[myVK_Subtract] = myVK_SingleQuote; MyVkMapA['9'] = 'Z'; MyVkMapA['0'] = 'X'; MyVkMapA['X'] = 'C'; MyVkMapA[myVK_Comma] = 'V'; MyVkMapA['I'] = 'B'; MyVkMapA['W'] = 'M'; MyVkMapA['V'] = myVK_Comma; MyVkMapA['G'] = myVK_Period; MyVkMapA[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 */ MyVkMapA['J'] = 'Q'; MyVkMapA['C'] = 'W'; MyVkMapA['U'] = 'E'; MyVkMapA['K'] = 'R'; MyVkMapA['E'] = 'T'; MyVkMapA['N'] = 'Y'; MyVkMapA['G'] = 'U'; MyVkMapA[myVK_SemiColon] = 'I'; MyVkMapA[myVK_OEM_102] = 'O'; MyVkMapA['Z'] = 'P'; MyVkMapA['H'] = myVK_LeftBracket; MyVkMapA['F'] = 'A'; MyVkMapA['Y'] = 'S'; MyVkMapA['W'] = 'D'; MyVkMapA['A'] = 'F'; MyVkMapA['P'] = 'G'; MyVkMapA['R'] = 'H'; MyVkMapA['O'] = 'J'; MyVkMapA['L'] = 'K'; MyVkMapA['D'] = 'L'; MyVkMapA['V'] = myVK_SemiColon; MyVkMapA[myVK_LeftBracket] = 'Z'; MyVkMapA['S'] = 'X'; MyVkMapA['M'] = 'C'; MyVkMapA['I'] = 'V'; MyVkMapA['T'] = 'B'; MyVkMapA['X'] = 'N'; MyVkMapA['B'] = 'M'; MyVkMapA['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 */ /* MyVkMapA[??] = ??; */ break; case 0x00000412: /* Korean */ /* MyVkMapA[VK_ZOOM] = ??; */ /* MyVkMapA[VK_HELP] = VK_ZOOM; */ /* MyVkMapA[??] = VK_HELP; */ /* MyVkMapA[??] = ??; */ 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 blnr 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 falseblnr; } } *r = v; return trueblnr; } #endif #if ItnlKyBdFix LOCALFUNC blnr MyGetKeyboardLayoutHex(uimr *r) { TCHAR s[KL_NAMELENGTH]; blnr IsOk = falseblnr; 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 MyCheckKeyboardLayout(void) { uimr sv; if (! MyGetKeyboardLayoutHex(&sv)) { } else if (sv == CurKyBdLytNm) { /* no change */ } else { CurKyBdLytNm = sv; MyVkMapFromLayout(sv); } } #endif #if ItnlKyBdFix LOCALPROC MyInitCheckKeyboardLayout(void) { uimr sv; if (! MyGetKeyboardLayoutHex(&sv)) { sv = 0x00000409; } CurKyBdLytNm = sv; MyVkMapFromLayout(sv); } #endif LOCALVAR ui3b WinKey2Mac[256]; LOCALPROC AssignOneMacKey(ui3b WinKey, ui3r MacKey) { WinKey2Mac[WinKey] = MacKey; } LOCALFUNC blnr 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 MyInitCheckKeyboardLayout(); #endif return trueblnr; } LOCALPROC DoKeyCode(int i, blnr down) { ui3r key = WinKey2Mac[ #if ItnlKyBdFix MyVkMapA[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 blnr HaveSetSysParam = falseblnr; #endif LOCALPROC CheckTheCapsLock(void) { DoKeyCode(VK_CAPITAL, (GetKeyState(VK_CAPITAL) & 1) != 0); } #if EnableGrabSpecialKeys LOCALVAR blnr VK_LWIN_pressed = falseblnr; LOCALVAR blnr VK_RWIN_pressed = falseblnr; #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, falseblnr); VK_LWIN_pressed = falseblnr; } } if (VK_RWIN_pressed) { if ((GetAsyncKeyState(VK_RWIN) & 0x8000) == 0) { DoKeyCode(VK_RWIN, falseblnr); VK_RWIN_pressed = falseblnr; } } } } #endif LOCALPROC DoVKcode0(int i, blnr 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, ui3r flags, blnr 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 blnr WantCmdOptOnReconnect = falseblnr; LOCALPROC ReconnectKeyCodes3(void) { int i; CheckTheCapsLock(); if (WantCmdOptOnReconnect) { WantCmdOptOnReconnect = falseblnr; for (i = 0; i < 256; ++i) { if ((GetKeyState(i) & 0x8000) != 0) { if ((VK_CAPITAL != i) && (VK_RETURN != i)) { DoVKcode0(i, trueblnr); } } } } } LOCALPROC DisconnectKeyCodes3(void) { DisconnectKeyCodes2(); SetCurMouseButton(falseblnr); } #if EnableGrabSpecialKeys static HHOOK hKeyHook = NULL; #endif #if EnableGrabSpecialKeys typedef struct { DWORD vkCode; DWORD scanCode; DWORD flags; DWORD time; DWORD dwExtraInfo; } My_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) { My_KBDLLHOOKSTRUCT *p = (My_KBDLLHOOKSTRUCT *)lParam; if (p->vkCode != VK_CAPITAL) { switch (wParam) { case WM_KEYDOWN: case WM_SYSKEYDOWN: DoVKcode(p->vkCode, p->flags, trueblnr); return 1; break; case WM_KEYUP: case WM_SYSKEYUP: DoVKcode(p->vkCode, p->flags, falseblnr); 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 My_WH_KEYBOARD_LL 13 #define My_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( My_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(My_SPI_SETSCREENSAVERRUNNING, TRUE, &nPreviousState, 0); HaveSetSysParam = trueblnr; } } } #endif #if EnableGrabSpecialKeys LOCALPROC UnGrabSpecialKeys(void) { if (hKeyHook != NULL) { (void) UnhookWindowsHookEx(hKeyHook); hKeyHook = NULL; } if (HaveSetSysParam) { SystemParametersInfo(My_SPI_SETSCREENSAVERRUNNING, FALSE, &nPreviousState, 0); HaveSetSysParam = falseblnr; } } #endif /* --- priority --- */ #ifndef EnableChangePriority #if UseWinCE #define EnableChangePriority 0 #else #define EnableChangePriority MayFullScreen #endif #endif /* EnableChangePriority */ #if EnableChangePriority LOCALVAR blnr MyPriorityRaised = falseblnr; #endif #if EnableChangePriority LOCALPROC RaiseMyPriority(void) { if (! MyPriorityRaised) { 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.", trueblnr); */ } MyPriorityRaised = trueblnr; } } #endif #if EnableChangePriority LOCALPROC LowerMyPriority(void) { if (MyPriorityRaised) { 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.", trueblnr); */ } MyPriorityRaised = falseblnr; } } #endif /* --- time, date, location --- */ #define dbglog_TimeStuff (0 && dbglog_HAVE) LOCALVAR ui5b TrueEmulatedTime = 0; #define MyInvTimeDivPow 16 #define MyInvTimeDiv (1 << MyInvTimeDivPow) #define MyInvTimeDivMask (MyInvTimeDiv - 1) #define MyInvTimeStep 1089590 /* 1000 / 60.14742 * MyInvTimeDiv */ LOCALVAR DWORD LastTime; LOCALVAR DWORD NextIntTime; LOCALVAR ui5b NextFracTime; LOCALPROC IncrNextTime(void) { NextFracTime += MyInvTimeStep; NextIntTime += (NextFracTime >> MyInvTimeDivPow); NextFracTime &= MyInvTimeDivMask; } LOCALPROC InitNextTime(void) { NextIntTime = LastTime; NextFracTime = 0; IncrNextTime(); } LOCALFUNC blnr UpdateTrueEmulatedTime(void) { DWORD LatestTime; si5b 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 trueblnr; } else if (TimeDiff < -256) { /* clock goofed if ever get here, reset */ #if dbglog_TimeStuff dbglog_writeln("clock set back"); #endif InitNextTime(); } } return falseblnr; } LOCALVAR ui5b TimeSecBase; LOCALVAR DWORD TimeMilliBase; #include "DATE2SEC.h" LOCALFUNC blnr CheckDateTime(void) { ui5b NewMacDateInSecond; NewMacDateInSecond = ((ui5b)(LastTime - TimeMilliBase)) / 1000 + TimeSecBase; if (CurMacDateInSeconds != NewMacDateInSecond) { CurMacDateInSeconds = NewMacDateInSecond; return trueblnr; } else { return falseblnr; } } LOCALFUNC blnr 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)) { si5b dlsBias = (v != TIME_ZONE_ID_DAYLIGHT) ? r.StandardBias : r.DaylightBias; CurMacDelta = (((ui5b)(- (r.Bias + dlsBias) * 60)) & 0x00FFFFFF) | (((v != TIME_ZONE_ID_DAYLIGHT) ? 0 : 0x80) << 24); } #endif LastTime = timeGetTime(); InitNextTime(); OnTrueTime = TrueEmulatedTime; (void) CheckDateTime(); return trueblnr; } #ifndef MyTimeResolution #define MyTimeResolution 3 #endif /* Setting MyTimeResolution 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 (MyTimeResolution != 0) LOCALVAR blnr HaveSetTimeResolution = falseblnr; #endif #if (MyTimeResolution != 0) LOCALPROC MyTimer_Suspend(void) { if (HaveSetTimeResolution) { (void) timeEndPeriod(MyTimeResolution); HaveSetTimeResolution = falseblnr; } } #endif #if (MyTimeResolution != 0) LOCALPROC MyTimer_Resume(void) { TIMECAPS tc; if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) == TIMERR_NOERROR) { if ((MyTimeResolution >= tc.wPeriodMin) && (MyTimeResolution <= tc.wPeriodMax)) { if (timeBeginPeriod(MyTimeResolution) == TIMERR_NOERROR) { HaveSetTimeResolution = trueblnr; } } } } #endif /* --- sound --- */ #if MySoundEnabled #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 ui4b ThePlayOffset; LOCALVAR ui4b TheFillOffset; LOCALVAR blnr wantplaying; LOCALVAR ui4b MinFilledSoundBuffs; LOCALVAR ui4b 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 MySound_BeginPlaying(void) { #if dbglog_SoundStuff fprintf(stderr, "MySound_BeginPlaying\n"); #endif } LOCALPROC MySound_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.", trueblnr); */ } 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.", trueblnr); */ } else { pwh->dwFlags |= WHDR_DONE; } p += kOneBuffLen; ++pwh; } TheFillOffset = 0; ThePlayOffset = 0; TheWriteOffset = 0; MinFilledSoundBuffs = kSoundBuffers; wantplaying = falseblnr; } } } LOCALPROC MySound_Stop(void) { MMRESULT mmr; int i; wantplaying = falseblnr; if (hWaveOut != NULL) { DWORD StartTime = GetTickCount(); for (i = 0; i < kSoundBuffers; ++i) { while (((whdr[i].dwFlags & WHDR_DONE) == 0) && ((ui5b)(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.", trueblnr); */ } } mmr = waveOutClose(hWaveOut); if (mmr != MMSYSERR_NOERROR) { /* MacMsg("waveOutClose failed", "Sorry, Mini vMac encountered errors" " and cannot continue.", trueblnr); */ } hWaveOut = NULL; } } LOCALPROC SoundCheckVeryOften(void) { if ((hWaveOut != NULL) && (wantplaying)) { label_retry: { ui4b FilledSoundBuffs; ui4b ToPlaySize = TheFillOffset - ThePlayOffset; ui4b 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; ui4b PrevPlayOffset = ThePlayOffset - kOneBuffLen; ui4b PrevPlayBuffer = (PrevPlayOffset >> kLnOneBuffLen) & kSoundBuffMask; ui4b 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.", trueblnr); */ } 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 MySound_FilledBlocks(void) { while (0 != ((TheWriteOffset - TheFillOffset) >> kLnOneBuffLen)) { ui4b CurFillBuffer = (TheFillOffset >> kLnOneBuffLen) & kSoundBuffMask; blnr IsOk = falseblnr; ConvertSoundBlockToNative((tpSoundSamp) whdr[CurFillBuffer].lpData); if (hWaveOut != NULL) { MMRESULT mmr = waveOutWrite(hWaveOut, &whdr[CurFillBuffer], sizeof(WAVEHDR)); if (mmr == MMSYSERR_NOERROR) { IsOk = trueblnr; } } if (! IsOk) { /* not recursive: MacMsg("waveOutWrite failed", "Sorry, Mini vMac encountered errors" " and cannot continue.", trueblnr); */ whdr[CurFillBuffer].dwFlags |= WHDR_DONE; } TheFillOffset += kOneBuffLen; } } LOCALPROC MySound_WroteABlock(void) { if (wantplaying) { MySound_FilledBlocks(); } else if (((TheWriteOffset - ThePlayOffset) >> kLnOneBuffLen) < 12) { /* just wait */ } else { MySound_FilledBlocks(); wantplaying = trueblnr; MySound_BeginPlaying(); } } GLOBALOSGLUPROC MySound_EndWrite(ui4r actL) { TheWriteOffset += actL; if (0 == (TheWriteOffset & kOneBuffMask)) { /* just finished a block */ MySound_WroteABlock(); } } GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL) { ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset); ui4b WriteBuffContig = kOneBuffLen - (TheWriteOffset & kOneBuffMask); if (WriteBuffContig < n) { n = WriteBuffContig; } if (ToFillLen < n) { /* overwrite previous buffer */ TheWriteOffset -= kOneBuffLen; } *actL = n; return TheSoundBuffer + (TheWriteOffset & kAllBuffMask); } LOCALPROC MySound_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 ((ui3b) -1 == SpeedValue) { RaiseMyPriority(); } #endif #if EnableGrabSpecialKeys GrabSpecialKeys(); #endif } #endif #if MayFullScreen LOCALPROC UnGrabTheMachine(void) { #if EnableGrabSpecialKeys UnGrabSpecialKeys(); #endif #if EnableFSMouseMotion StopSaveMouseMotion(); #endif #if EnableChangePriority LowerMyPriority(); #endif } #endif #if MayFullScreen LOCALVAR blnr GrabMachine = falseblnr; #endif #if MayFullScreen LOCALPROC AdjustMachineGrab(void) { if (GrabMachine) { if (MainWnd != NULL) { GrabTheMachine(); } } else { UnGrabTheMachine(); } } #endif /* --- basic dialogs --- */ LOCALPROC MyBeginDialog(void) { DisconnectKeyCodes3(); #if MayFullScreen GrabMachine = falseblnr; UnGrabTheMachine(); #endif ForceShowCursor(); } LOCALPROC MyEndDialog(void) { ReconnectKeyCodes3(); } LOCALPROC CheckSavedMacMsg(void) { if (nullpr != SavedBriefMsg) { TCHAR briefMsg0[ClStrMaxLength + 1]; TCHAR longMsg0[ClStrMaxLength + 1]; NativeStrFromCStr(briefMsg0, SavedBriefMsg, falseblnr); NativeStrFromCStr(longMsg0, SavedLongMsg, falseblnr); 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 }; #if (1 == vMacScreenDepth) || (vMacScreenDepth >= 4) #define EnableScalingBuff 1 #else #define EnableScalingBuff (1 && EnableMagnify && (MyWindowScale == 2)) #endif #if EnableScalingBuff LOCALVAR ui3p ScalingBuff = NULL; #endif LOCALVAR HDC MainWndDC = NULL; LOCALVAR si5b CmdShow; LOCALVAR TCHAR WndTitle[_MAX_PATH]; LOCALVAR const TCHAR WndClassName[] = TEXT("minivmac"); LOCALVAR blnr gBackgroundFlag = falseblnr; LOCALVAR blnr gTrueBackgroundFlag = falseblnr; LOCALVAR blnr CurSpeedStopped = trueblnr; LOCALPROC GetWndTitle(void) { TCHAR pathName[_MAX_PATH]; WIN32_FIND_DATA fd; blnr IsOk = falseblnr; 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 = trueblnr; 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 blnr HavePositionWins[kNumMagStates]; LOCALVAR POINT WinPositionWins[kNumMagStates]; #endif #if MayNotFullScreen LOCALPROC MyAppendConvertMenuItem(HMENU hMenu, UINT uIDNewItem, char *s, blnr AddEllipsis) { TCHAR ts[ClStrMaxLength + 1]; NativeStrFromCStr(ts, s, AddEllipsis); (void) AppendMenu(hMenu, MF_ENABLED + MF_STRING, uIDNewItem, ts); } #endif #if MayNotFullScreen LOCALPROC MyAppendSubmenuConvertName(HMENU hMenu, HMENU hSubMenu, char *s) { TCHAR ts[ClStrMaxLength + 1]; MENUITEMINFO mii; NativeStrFromCStr(ts, s, falseblnr); #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 blnr 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 MyWStyle; DWORD MyWExStyle; #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 *= MyWindowScale; NewWindowWidth *= MyWindowScale; } #endif #if VarFullScreen if (WantFullScreen) #endif #if MayFullScreen { MyWStyle = WS_VISIBLE | WS_POPUP; MyWExStyle = 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 { MyWStyle = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; MyWExStyle = 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] = trueblnr; } NewWinR.left = WinPositionWins[WinIndx].x; NewWinR.top = WinPositionWins[WinIndx].y; NewWinR.right = NewWinR.left + NewWindowWidth; NewWinR.bottom = NewWinR.top + NewWindowHeight; (void) AdjustWindowRectEx(&NewWinR, MyWStyle, TRUE, MyWExStyle); 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, MyWStyle, TRUE, MyWExStyle); } } #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) { MyAppendConvertMenuItem(m, ID_FILE_INSERTDISK1, kStrMenuItemOpen, trueblnr); (void) AppendMenu(m, MF_SEPARATOR, 0, NULL); MyAppendConvertMenuItem(m, ID_FILE_QUIT, kStrMenuItemQuit, falseblnr); MyAppendSubmenuConvertName(mb, m, kStrMenuFile_win); } m = CreateMenu(); if (m != NULL) { MyAppendConvertMenuItem(m, ID_SPECIAL_MORECOMMANDS, kStrMenuItemMore, trueblnr); MyAppendSubmenuConvertName(mb, m, kStrMenuSpecial); } m = CreateMenu(); if (m != NULL) { MyAppendConvertMenuItem(m, ID_HELP_ABOUT, kStrMenuItemAbout, trueblnr); MyAppendSubmenuConvertName(mb, m, kStrMenuHelp); } } } #endif NewMainWindow = CreateWindowEx( MyWExStyle, WndClassName, WndTitle, MyWStyle, 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.", trueblnr); return falseblnr; } NewMainWndDC = GetDC(NewMainWindow); if (NewMainWndDC == NULL) { MacMsg("GetDC failed", "Sorry, Mini vMac encountered errors" " and cannot continue.", trueblnr); DestroyWindow(NewMainWindow); return falseblnr; } } 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 = trueblnr; #endif { 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 = (si4b)p.x; WndY = (si4b)p.y; } #if MayFullScreen GrabMachine = falseblnr; UnGrabTheMachine(); #endif #if UseWinCE && 0 /* Show the taskbar */ SHFullScreen(MainWnd, SHFS_SHOWTASKBAR); #endif #if MayNotFullScreen CurWinIndx = WinIndx; #endif MainWnd = NewMainWindow; MainWndDC = NewMainWndDC; gTrueBackgroundFlag = falseblnr; #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 /= MyWindowScale; ViewVSize /= MyWindowScale; } #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.", trueblnr); return falseblnr; } 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.", trueblnr); return falseblnr; } if (SelectPalette(MainWndDC, hpal, FALSE) == NULL) { free(lppal); MacMsg("CreateWindow failed", "Sorry, Mini vMac encountered errors" " and cannot continue.", trueblnr); return falseblnr; } if (RealizePalette(MainWndDC) == GDI_ERROR) { free(lppal); MacMsg("CreateWindow failed", "Sorry, Mini vMac encountered errors" " and cannot continue.", trueblnr); return falseblnr; } free(lppal); } #endif #if UseWinCE /* Hide the taskbar */ SHFullScreen(MainWnd, SHFS_HIDETASKBAR); (void) MoveWindow(MainWnd, 0, 0, ScreenX, ScreenY, TRUE); #endif if (HaveCursorHidden) { (void) MyMoveMouse(CurMouseH, CurMouseV); WantCursorHidden = trueblnr; } return trueblnr; } #if UseWinCE LOCALFUNC blnr 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 falseblnr; } 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 trueblnr; } } #endif typedef struct BITMAPINFOHEADER256 { BITMAPINFOHEADER bmi; #if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) RGBQUAD colors[CLUT_size]; #else RGBQUAD colors[2]; #endif } BITMAPINFOHEADER256; #if EnableMagnify #define MyScaledHeight (MyWindowScale * vMacScreenHeight) #define MyScaledWidth (MyWindowScale * vMacScreenWidth) #endif LOCALPROC HaveChangedScreenBuff(si4b top, si4b left, si4b bottom, si4b right) { BITMAPINFOHEADER256 bmh; ui3b *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 *= MyWindowScale; YDest *= MyWindowScale; } #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 0 != vMacScreenDepth if (UseColorMode) { int i; int nDestWidth = (right - left); int nDestHeight = (bottom - top); #if 1 == vMacScreenDepth ui3b *p = ScalingBuff + ((ui5r)vMacScreenWidth / 4) * top; #elif vMacScreenDepth >= 4 ui3b *p = ScalingBuff + (ui5r)vMacScreenByteWidth * top; #else ui3b *p = cdb + (ui5r)vMacScreenByteWidth * top; #endif 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); #endif bmh.bmi.biCompression= BI_RGB; bmh.bmi.biSizeImage = 0; bmh.bmi.biXPelsPerMeter = 0; bmh.bmi.biYPelsPerMeter = 0; #if 1 == vMacScreenDepth bmh.bmi.biClrUsed = 4; #else bmh.bmi.biClrUsed = 0; #endif 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; } #endif #if 1 == vMacScreenDepth { int j; ui3b *p1 = (ui3b *)(cdb + (ui5r)vMacScreenByteWidth * top); ui4b *p2 = (ui4b *)p; for (i = bottom - top; --i >= 0; ) { for (j = vMacScreenWidth / 4; --j >= 0; ) { ui4r t0 = *p1++; *p2 ++ = ((t0 & 0xC0) >> 2) | ((t0 & 0x30) >> 4) | ((t0 & 0x0C) << 10) | ((t0 & 0x03) << 8); } } } #elif 4 == vMacScreenDepth { int j; ui4b *p1 = (ui4b *)(cdb + (ui5r)vMacScreenByteWidth * top); ui4b *p2 = (ui4b *)p; for (i = bottom - top; --i >= 0; ) { for (j = vMacScreenWidth; --j >= 0; ) { ui4r t0 = *p1++; *p2 ++ = ((t0 & 0xFF00) >> 8) | ((t0 & 0x00FF) << 8); } } } #elif 5 == vMacScreenDepth { int j; ui5b *p1 = (ui5b *)(cdb + (ui5r)vMacScreenByteWidth * top); ui5b *p2 = (ui5b *)p; for (i = bottom - top; --i >= 0; ) { for (j = vMacScreenWidth; --j >= 0; ) { ui5r t0 = *p1++; *p2++ = ((t0 & 0xFF000000) >> 24) | ((t0 & 0x00FF0000) >> 8) | ((t0 & 0x0000FF00) << 8) | ((t0 & 0x000000FF) << 24); } } } #endif #if EnableMagnify if (UseMagnify) { nDestWidth *= MyWindowScale; nDestHeight *= MyWindowScale; } #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 #endif { ui3b *p = cdb + (ui5r)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; ui4r left1 = left & (~ 7); ui4r right1 = (right + 7) & (~ 7); ui4r jn = (right1 - left1) / 8; ui3b *p1 = cdb + ((left1 + vMacScreenWidth * (ui5r)top) / 8); ui3b *p2 = ScalingBuff /* + ((left1 + vMacScreenWidth * MyWindowScale * (ui5r)top) * MyWindowScale / 8) */ ; ui3b *p3; ui3b t0; ui3b t1; ui3b t2; ui3b 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 += MyScaledWidth / 8 - (MyWindowScale * jn); for (j = MyWindowScale * jn; --j >= 0; ) { *p2++ = *p3++; } p2 += MyScaledWidth / 8 - (MyWindowScale * jn); } bmh.bmi.biWidth = vMacScreenWidth * MyWindowScale; bmh.bmi.biHeight = - ((bottom - top) * MyWindowScale); 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) * MyWindowScale, /* source rectangle width */ (bottom - top) * MyWindowScale, /* source rectangle height */ (left & 7) * MyWindowScale, /* 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) * MyWindowScale, /* 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) * MyWindowScale, /* dest. rectangle width */ (bottom - top) * MyWindowScale, /* 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 MyDrawChangesAndClear(void) { if (ScreenChangedBottom > ScreenChangedTop) { HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft, ScreenChangedBottom, ScreenChangedRight); ScreenClearChanges(); } } GLOBALOSGLUPROC DoneWithDrawingForTick(void) { #if EnableFSMouseMotion if (HaveMouseMotion) { AutoScrollScreen(); } #endif MyDrawChangesAndClear(); } LOCALFUNC blnr InitTheCursor(void) { SetCursor(LoadCursor(NULL, IDC_ARROW)); return trueblnr; } #if EnableFSMouseMotion LOCALPROC MyMouseConstrain(void) { si4b shiftdh; si4b 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 (! MyMoveMouse(SavedMouseH, SavedMouseV)) { HaveMouseMotion = falseblnr; } } } #endif LOCALPROC MousePositionNotify(LONG NewMousePosx, LONG NewMousePosy) { blnr ShouldHaveCursorHidden = trueblnr; #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { NewMousePosx -= hOffset; NewMousePosy -= vOffset; } #endif #if EnableMagnify if (UseMagnify) { NewMousePosx /= MyWindowScale; NewMousePosy /= MyWindowScale; } #endif #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { NewMousePosx += ViewHStart; NewMousePosy += ViewVStart; } #endif #if EnableFSMouseMotion if (HaveMouseMotion) { MyMousePositionSetDelta(NewMousePosx - SavedMouseH, NewMousePosy - SavedMouseV); SavedMouseH = NewMousePosx; SavedMouseV = NewMousePosy; } else #endif { if (NewMousePosx < 0) { NewMousePosx = 0; ShouldHaveCursorHidden = falseblnr; } else if (NewMousePosx > vMacScreenWidth) { NewMousePosx = vMacScreenWidth - 1; ShouldHaveCursorHidden = falseblnr; } if (NewMousePosy < 0) { NewMousePosy = 0; ShouldHaveCursorHidden = falseblnr; } else if (NewMousePosy > vMacScreenHeight) { NewMousePosy = vMacScreenHeight - 1; ShouldHaveCursorHidden = falseblnr; } #if VarFullScreen if (UseFullScreen) #endif #if MayFullScreen { ShouldHaveCursorHidden = trueblnr; } #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 MyMousePositionSet(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 ui3b 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 MyUseUni #define MyUnsignedChar ui4b #else #define MyUnsignedChar ui3b #endif HGLOBAL h; LPTSTR p1; ui5b n; MyUnsignedChar 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) { ui3b *p2 = GlobalLock(h); if (p2 != NULL) { while ((v = (MyUnsignedChar)*p1++) != 0) { if (v >= 128) { *p2++ = Native2MacRomanTab[v & 0x7F]; /* if MyUseUni, 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 ui3b 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 blnr MacRomanTextToNativeHand(tPbuf Pbuf_no, blnr IsFileName, HGLOBAL *r) { HGLOBAL h; ui5b i; ui5b rn = 0; HGLOBAL bh = PbufDat[Pbuf_no]; ui5b L = PbufSize[Pbuf_no]; blnr IsOk = falseblnr; if (IsFileName) { if (L > 255) { L = 255; } } else { ui3b *Buffer = (ui3b *)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) { ui3b *Buffer = (ui3b *)GlobalLock(bh); if (Buffer != NULL) { LPTSTR p1 = GlobalLock(h); if (p1 != NULL) { for (i = 0; i < L; ++i) { TCHAR y; ui3b x = ((ui3b *)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 = trueblnr; (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, falseblnr, &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(blnr IsWrite, ui3p Buffer, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *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 != (ui5b)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 ((ui5b)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 ((ui5b)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, ui5r *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, blnr 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, falseblnr); } #if IncludeSonyNew GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No) { return vSonyEject0(Drive_No, trueblnr); } #endif LOCALPROC UnInitDrives(void) { tDrive i; for (i = 0; i < NumDrives; ++i) { if (vSonyIsInserted(i)) { (void) vSonyEject(i); } } } #if NeedDriveNames LOCALFUNC blnr LPTSTRtoHand(LPTSTR s, HGLOBAL *r) { blnr IsOk = falseblnr; 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 = trueblnr; (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 blnr Sony_Insert0(HANDLE refnum, blnr locked, LPTSTR drivepath) { tDrive Drive_No; #if ! NeedDriveNames UnusedParam(drivepath); #endif if (! FirstFreeDisk(&Drive_No)) { (void) CloseHandle(refnum); MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage, falseblnr); return falseblnr; } 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 trueblnr; } } LOCALFUNC blnr Sony_Insert1(LPTSTR drivepath, blnr SilentOnMissing) { blnr locked = falseblnr; 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 = trueblnr; 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, falseblnr); } else if ((ERROR_FILE_NOT_FOUND == err) && SilentOnMissing) { /* ignore it */ } else { MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr); } } else { return Sony_Insert0(refnum, locked, drivepath); } return falseblnr; } LOCALFUNC blnr LoadMacRomFromPath(LPTSTR drivepath) { HANDLE refnum = INVALID_HANDLE_VALUE; blnr IsOk = falseblnr; 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, trueblnr); */ } 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 ((ui5b)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 blnr COMinited = falseblnr; LOCALVAR blnr COMinitedOK; #endif #if EnableShellLinks LOCALPROC MyUninitCOM(void) { if (COMinited) { CoUninitialize(); } } #endif #if EnableShellLinks LOCALFUNC blnr MyNeedCOM(void) { HRESULT hres; if (! COMinited) { COMinitedOK = falseblnr; hres = CoInitialize(NULL); if (SUCCEEDED(hres)) { COMinitedOK = trueblnr; } COMinited = trueblnr; } return COMinitedOK; } #endif #if EnableShellLinks LOCALFUNC blnr MyResolveShortcut(LPTSTR FilePath, blnr *directory) /* adapted from Microsoft example code */ { HRESULT hres; IShellLink *psl; IPersistFile* ppf; TCHAR szGotPath[MAX_PATH]; WIN32_FIND_DATA wfd; blnr IsOk = falseblnr; if (MyNeedCOM()) { 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 MyUseUni #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 = trueblnr; } } } ppf->lpVtbl->Release(ppf); } psl->lpVtbl->Release(psl); } } return IsOk; } #endif #if EnableShellLinks LOCALFUNC blnr FileIsLink(LPTSTR drivepath) { LPTSTR p = FindLastTerm(drivepath, (TCHAR)('.')); if (p != nullpr) { if (_tcscmp(p, TEXT("lnk")) == 0) { return trueblnr; } } return falseblnr; } #endif LOCALFUNC blnr InsertDiskOrAlias(LPTSTR drivepath, blnr MaybeROM, blnr MaybeAlias) { #if EnableShellLinks if (MaybeAlias && FileIsLink(drivepath)) { if (! MyResolveShortcut(drivepath, NULL)) { return falseblnr; } } #endif if (MaybeROM && ! ROM_loaded) { return LoadMacRomFromPath(drivepath); } else { return Sony_Insert1(drivepath, falseblnr); } } LOCALFUNC blnr MyFileExists(LPTSTR pathName, blnr *directory) { WIN32_FIND_DATA fd; HANDLE hf = FindFirstFile(pathName, &fd); blnr IsOk = falseblnr; if (hf != INVALID_HANDLE_VALUE) { if (NULL != directory) { *directory = (0 != (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)); } IsOk = trueblnr; FindClose(hf); } return IsOk; } LOCALFUNC tMacErr ResolveNamedChild0(LPTSTR pathName, LPTSTR Child, blnr *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 (MyFileExists(pathName, directory)) { err = mnvm_noErr; } else { err = mnvm_fnfErr; #if EnableShellLinks if (newlen + 5 < _MAX_PATH) { _tcscat(pathName, TEXT(".lnk")); if (MyFileExists(pathName, NULL)) if (MyResolveShortcut(pathName, directory)) { err = mnvm_noErr; } if (mnvm_noErr != err) { pathName[newlen] = (TCHAR)('\0'); } } #endif } } return err; } LOCALFUNC tMacErr ResolveNamedChild(LPTSTR pathName, char *Child, blnr *directory) { TCHAR Child0[ClStrMaxLength + 1]; NativeStrFromCStr(Child0, Child, falseblnr); return ResolveNamedChild0(pathName, Child0, directory); } LOCALFUNC blnr ResolveNamedChildDir(LPTSTR pathName, char *Child) { blnr directory; return (mnvm_noErr == ResolveNamedChild( pathName, Child, &directory)) && directory; } LOCALFUNC blnr ResolveNamedChildFile(LPTSTR pathName, char *Child) { blnr directory; return (mnvm_noErr == ResolveNamedChild( pathName, Child, &directory)) && ! directory; } #if UseActvFile || (IncludeSonyNew && ! SaveDialogEnable) LOCALFUNC blnr MakeNamedChildDir(LPTSTR pathName, char *Child) { blnr directory; blnr IsOk = falseblnr; tMacErr err = ResolveNamedChild(pathName, Child, &directory); if (mnvm_noErr == err) { IsOk = directory; } else if (mnvm_fnfErr == err) { if (CreateDirectory(pathName, NULL)) { IsOk = trueblnr; } } return IsOk; } #endif LOCALFUNC blnr MyGetAppDataPath(LPTSTR lpszPath, BOOL fCreate) { blnr IsOk = falseblnr; if (HaveMySHGetSpecialFolderPath()) if (MySHGetSpecialFolderPath( NULL /* HWND hwndOwner */, lpszPath, My_CSIDL_APPDATA, fCreate)) { IsOk = trueblnr; } /* 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 blnr CtrlMode = falseblnr; #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]; blnr 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, falseblnr); } #endif } else { (void) InsertDiskOrAlias(ofn.lpstrFile, trueblnr, falseblnr); } #if UseWinCE CtrlMode = falseblnr; #endif } LOCALFUNC blnr LoadInitialImageFromName(char *ImageName) { TCHAR ImageFile[_MAX_PATH]; if (GetAppDir(ImageFile)) if (ResolveNamedChildFile(ImageFile, ImageName)) if (Sony_Insert1(ImageFile, trueblnr)) { return trueblnr; } return falseblnr; } LOCALFUNC blnr Sony_InsertIth(int i) { blnr v; if ((i > 9) || ! FirstFreeDisk(nullpr)) { v = falseblnr; } else { char s[] = "disk?.dsk"; s[4] = '0' + i; /* stop on first error (including file not found) */ v = LoadInitialImageFromName(s); } return v; } LOCALFUNC blnr LoadInitialImages(void) { if (! AnyDiskInserted()) { int i; for (i = 1; Sony_InsertIth(i); ++i) { /* stop on first error (including file not found) */ } } return trueblnr; } #if UseActvFile #define ActvCodeFileName "act_1" LOCALFUNC tMacErr ActvCodeFileLoad(ui3p p) { TCHAR pathName[_MAX_PATH]; DWORD BytesRead; HANDLE refnum = INVALID_HANDLE_VALUE; blnr IsOk = falseblnr; if (MyGetAppDataPath(pathName, FALSE)) if (ResolveNamedChildDir(pathName, "Gryphel")) if (ResolveNamedChildDir(pathName, "mnvm_act")) if (ResolveNamedChildFile(pathName, ActvCodeFileName)) { refnum = CreateFile( pathName, /* pointer to name of the file */ GENERIC_READ, /* access (read-write) mode */ FILE_SHARE_READ, /* share mode */ NULL, /* pointer to security descriptor */ OPEN_EXISTING, /* how to create */ FILE_ATTRIBUTE_NORMAL, /* file attributes */ NULL /* handle to file with attributes to copy */ ); if (INVALID_HANDLE_VALUE == refnum) { /* report error */ } else { 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) { /* report error */ } else if (! ReadFile(refnum, /* handle of file to read */ (LPVOID)p, /* address of buffer that receives data */ (DWORD)ActvCodeFileLen, /* number of bytes to read */ &BytesRead, /* address of number of bytes read */ nullpr) /* address of structure for data */ || ((ui5b)BytesRead != ActvCodeFileLen)) { /* report error */ } else { IsOk = trueblnr; } (void) CloseHandle(refnum); } } return IsOk ? mnvm_noErr : mnvm_miscErr; } LOCALFUNC blnr NewNamedChildFile(LPTSTR pathName, char *Child) { blnr directory; blnr IsOk = falseblnr; tMacErr err = ResolveNamedChild(pathName, Child, &directory); if (mnvm_noErr == err) { IsOk = ! directory; } else if (mnvm_fnfErr == err) { IsOk = trueblnr; } return IsOk; } LOCALFUNC tMacErr ActvCodeFileSave(ui3p p) { TCHAR pathName[_MAX_PATH]; DWORD BytesWritten; HANDLE refnum = INVALID_HANDLE_VALUE; blnr IsOk = falseblnr; if (MyGetAppDataPath(pathName, TRUE)) if (MakeNamedChildDir(pathName, "Gryphel")) if (MakeNamedChildDir(pathName, "mnvm_act")) if (NewNamedChildFile(pathName, ActvCodeFileName)) { refnum = 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 (INVALID_HANDLE_VALUE == refnum) { /* report error */ } else { 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) { /* report error */ } else if (! WriteFile(refnum, /* handle of file to read */ (LPVOID)p, /* address of buffer that receives data */ (DWORD)ActvCodeFileLen, /* number of bytes to read */ &BytesWritten, /* address of number of bytes read */ nullpr) /* address of structure for data */ || ((ui5b)BytesWritten != ActvCodeFileLen)) { /* report error */ } else { IsOk = trueblnr; } (void) CloseHandle(refnum); if (! IsOk) { (void) DeleteFile(pathName); } } } return IsOk ? mnvm_noErr : mnvm_miscErr; } #endif /* UseActvFile */ #if IncludeSonyNew LOCALFUNC blnr WriteZero(HANDLE refnum, ui5b 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 falseblnr; } else { #define ZeroBufferSize 2048 ui5b i; ui3b 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 */ || ((ui5b)BytesWritten != i)) { return falseblnr; } L -= i; } return trueblnr; } } #endif #define MaxSavePathSize MAX_PATH #if IncludeSonyNew LOCALPROC MakeNewDisk0(ui5b L, LPTSTR pathName) { blnr IsOk = falseblnr; HANDLE newrefNum; IsOk = falseblnr; 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, falseblnr, pathName); newrefNum = INVALID_HANDLE_VALUE; } if (INVALID_HANDLE_VALUE != newrefNum) { (void) CloseHandle(newrefNum); } if (! IsOk) { (void) DeleteFile(pathName); } } } #endif #if IncludeSonyNew LOCALPROC MakeNewDisk(ui5b L, HGLOBAL NewDiskNameDat) { #if SaveDialogEnable OPENFILENAME ofn; blnr IsOk = falseblnr; 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", falseblnr); } 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")) { blnr 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 blnr LoadMacRom(void) { TCHAR ROMFile[_MAX_PATH]; blnr IsOk = falseblnr; if (GetAppDir(ROMFile)) if (ResolveNamedChildFile(ROMFile, RomFileName)) { IsOk = trueblnr; } if (! IsOk) { if (MyGetAppDataPath(ROMFile, FALSE)) if (ResolveNamedChildDir(ROMFile, "Gryphel")) if (ResolveNamedChildDir(ROMFile, "mnvm_rom")) if (ResolveNamedChildFile(ROMFile, RomFileName)) { IsOk = trueblnr; } } if (IsOk) { IsOk = LoadMacRomFromPath(ROMFile); } return trueblnr; } #if InstallFileIcons LOCALPROC MySetRegKey(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, blnr CanOpen) { TCHAR strRegKey[_MAX_PATH]; TCHAR strRegValue[_MAX_PATH + 2]; /* extra room for ","{strIconId} */ MySetRegKey(HKEY_CLASSES_ROOT, strFileTypeId, strFileTypeName); MySetRegKey(HKEY_CLASSES_ROOT, strFilterExt, strFileTypeId); _tcscpy(strRegKey, strFileTypeId); _tcscat(strRegKey, TEXT("\\DefaultIcon")); _tcscpy(strRegValue, TEXT("\"")); _tcscat(strRegValue, AppPath); _tcscat(strRegValue, TEXT("\",")); _tcscat(strRegValue, strIconId); MySetRegKey(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\"")); MySetRegKey(HKEY_CLASSES_ROOT, strRegKey, strRegValue); } } LOCALFUNC blnr 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"), falseblnr); RegisterShellFileType(AppPath, TEXT(".dsk"), TEXT("minivmac.dsk"), TEXT("Mini vMac Disk Image"), TEXT("2"), trueblnr); return trueblnr; } #endif LOCALVAR LPTSTR CommandLine; LOCALFUNC blnr 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, falseblnr); } } else { (void) InsertDiskOrAlias(fileName, falseblnr, trueblnr); } } } } return trueblnr; } #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] = falseblnr; } } #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 = falseblnr; if (WantFullScreen) { if ((GetSystemMetrics(SM_CXSCREEN) >= vMacScreenWidth * MyWindowScale) && (GetSystemMetrics(SM_CYSCREEN) >= vMacScreenHeight * MyWindowScale) ) { WantMagnify = trueblnr; } } } } #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, trueblnr, trueblnr); } } DragFinish(hDrop); if (gTrueBackgroundFlag) { if (! SetForegroundWindow(MainWnd)) { /* error message here ? */ } WantCmdOptOnReconnect = trueblnr; } } #endif GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void) { #if MySoundEnabled 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 MySoundEnabled MySound_Start(); #endif #if (MyTimeResolution != 0) MyTimer_Resume(); #endif } LOCALPROC EnterSpeedStopped(void) { #if (MyTimeResolution != 0) MyTimer_Suspend(); #endif #if MySoundEnabled MySound_Stop(); #endif } LOCALPROC CheckForSavedTasks(void) { /* Check for things to do that rather wouldn't have done at an awkward time. */ if (MyEvtQNeedRecover) { MyEvtQNeedRecover = falseblnr; /* attempt cleanup, MyEvtQNeedRecover may get set again */ MyEvtQTryRecoverFromFull(); } #if EnableFSMouseMotion if (HaveMouseMotion) { MyMouseConstrain(); } #endif if (RequestMacOff) { RequestMacOff = falseblnr; if (AnyDiskInserted()) { MacMsgOverride(kStrQuitWarningTitle, kStrQuitWarningMessage); } else { ForceMacOff = trueblnr; } } if (ForceMacOff) { return; } if (gTrueBackgroundFlag != gBackgroundFlag) { gBackgroundFlag = gTrueBackgroundFlag; if (gTrueBackgroundFlag) { EnterBackground(); } else { LeaveBackground(); } } if (CurSpeedStopped != (SpeedStopped || (gBackgroundFlag && ! RunInBackground #if EnableAutoSlow && 0 && (QuietSubTicks >= 4092) #endif ))) { 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, trueblnr, &NewDiskNameDat)) { MakeNewDisk(vSonyNewDiskSize, NewDiskNameDat); GlobalFree(NewDiskNameDat); } PbufDispose(vSonyNewDiskName); vSonyNewDiskName = NotAPbuf; } else #endif { MakeNewDisk(vSonyNewDiskSize, NULL); } vSonyNewDiskWanted = falseblnr; /* must be done after may have gotten disk */ } #endif if (RequestInsertDisk) { RequestInsertDisk = falseblnr; 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 = falseblnr; ScreenChangedAll(); } } #if UseWinCE /* Sip Status ON/OFF */ LOCALVAR blnr SipOn = falseblnr; #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 = falseblnr; { 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, falseblnr); CtrlMode = falseblnr; break; } else if (wparam == VK_CONTROL) { DoVKcode0(wparam, trueblnr); CtrlMode = trueblnr; break; } #endif if (! TestBit(lparam, 30)) { /* ignore repeats */ DoVKcode(wparam, lparam >> 24, trueblnr); } #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 = falseblnr; { 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, falseblnr); #if UseWinCE return TRUE; /* So that hardware keys won't be processed by the default handler */ #endif break; #if ItnlKyBdFix && ! UseWinCE case WM_INPUTLANGCHANGE: MyCheckKeyboardLayout(); return TRUE; break; #endif case WM_CLOSE: RequestMacOff = trueblnr; break; #if ! UseWinCE case WM_QUERYENDSESSION: if (AnyDiskInserted()) { RequestMacOff = trueblnr; 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 = trueblnr; break; case ID_FILE_QUIT: RequestMacOff = trueblnr; break; case ID_SPECIAL_MORECOMMANDS: DoMoreCommandsMsg(); break; case ID_HELP_ABOUT: DoAboutMsg(); break; } break; case WM_MOVE: WndX = (si4b) LOWORD(lparam); WndY = (si4b) 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(trueblnr); break; case WM_LBUTTONUP: case WM_RBUTTONUP: MousePositionNotify(LOWORD (lparam), HIWORD (lparam)); SetCurMouseButton(falseblnr); 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 blnr 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.", trueblnr); return falseblnr; } else { return trueblnr; } } LOCALPROC WaitForTheNextEvent(void) { MSG msg; if (-1 != GetMessage(&msg, NULL, 0, 0)) { DispatchMessage(&msg); } } LOCALPROC CheckForSystemEvents(void) { MSG msg; ui3r 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 MySoundEnabled MySound_SecondNotify(); #endif #if EnableDemoMsg DemoModeSecondNotify(); #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 blnr 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.", falseblnr); } */ return trueblnr; } #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 blnr InitHotKeys(void) { UnregisterFunc1Proc procUndergisterFunc; int i; hCoreDLL = LoadLibrary(TEXT("coredll.dll")); if (! hCoreDLL) { MacMsg ("Fatal", "Could not load coredll.dll", trueblnr); } else { procUndergisterFunc = (UnregisterFunc1Proc) GetProcAddress(hCoreDLL, TEXT("UnregisterFunc1")); if (! procUndergisterFunc) { MacMsg ("Fatal", "Could not get UnregisterFunc1 procedure", trueblnr); } else { for (i = 0xc1; i <= 0xcf; ++i) { procUndergisterFunc(MOD_WIN, i); RegisterHotKey(MainWnd, i, MOD_WIN, i); } } } return trueblnr; } #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, falseblnr); ReserveAllocOneBlock(&screencomparebuff, vMacScreenNumBytes, 5, trueblnr); #if UseControlKeys ReserveAllocOneBlock(&CntrlDisplayBuff, vMacScreenNumBytes, 5, falseblnr); #endif #if EnableScalingBuff { ui5r n = vMacScreenMonoNumBytes #if EnableMagnify * MyWindowScale * MyWindowScale #endif ; #if 1 == vMacScreenDepth if (vMacScreenNumBytes * 2 > n) { n = vMacScreenNumBytes * 2; } #elif vMacScreenDepth >= 4 if (vMacScreenNumBytes > n) { n = vMacScreenNumBytes; } #endif ReserveAllocOneBlock(&ScalingBuff, n, 5, falseblnr); } #endif #if MySoundEnabled ReserveAllocOneBlock((ui3p *)&TheSoundBuffer, dbhBufferSize, 5, falseblnr); #endif EmulationReserveAlloc(); } LOCALFUNC blnr AllocMyMemory(void) { uimr n; blnr IsOk = falseblnr; ReserveAllocOffset = 0; ReserveAllocBigBlock = nullpr; ReserveAllocAll(); n = ReserveAllocOffset; ReserveAllocBigBlock = (ui3p)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, n); if (NULL == ReserveAllocBigBlock) { MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr); } else { ReserveAllocOffset = 0; ReserveAllocAll(); if (n != ReserveAllocOffset) { /* oops, program error */ } else { IsOk = trueblnr; } } return IsOk; } LOCALPROC UnallocMyMemory(void) { if (nullpr != ReserveAllocBigBlock) { if (GlobalFree(ReserveAllocBigBlock) != NULL) { MacMsg("error", "GlobalFree failed", falseblnr); } } } LOCALFUNC blnr InitOSGLU(void) { if (AllocMyMemory()) #if dbglog_HAVE if (dbglog_open()) #endif if (RegisterOurClass()) if (ScanCommandLine()) if (LoadInitialImages()) #if InstallFileIcons if (RegisterInRegistry()) #endif if (LoadMacRom()) #if UseActvCode if (ActvCodeInit()) #endif #if UseWinCE if (Init_ChangeOrientation()) #endif if (ReCreateMainWindow()) if (InitWinKey2Mac()) if (InitTheCursor()) #if UseWinCE if (InitHotKeys()) #endif if (Init60thCheck()) if (WaitForRom()) { return trueblnr; } return falseblnr; } LOCALPROC UnInitOSGLU(void) { #if (MyTimeResolution != 0) MyTimer_Suspend(); #endif MyMouseCaptureSet(falseblnr); if (MacMsgDisplayed) { MacMsgDisplayOff(); } #if MayFullScreen UnGrabTheMachine(); #endif #if MySoundEnabled MySound_Stop(); #endif #if IncludePbufs UnInitPbufs(); #endif UnInitDrives(); ForceShowCursor(); #if UseWinCE Uninit_ChangeOrientation(); UninitHotKeys(); #endif #if EnableShellLinks MyUninitCOM(); #endif if (! gTrueBackgroundFlag) { CheckSavedMacMsg(); } DisposeMainWindow(); #if dbglog_HAVE dbglog_close(); #endif UnallocMyMemory(); } 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); }