this repo has no description
1/*
2 OSGLUWIN.c
3
4 Copyright (C) 2009 Philip Cummins, Weston Pawlowski,
5 Bradford L. Barrett, Paul C. Pratt, Fabio Concas
6
7 You can redistribute this file and/or modify it under the terms
8 of version 2 of the GNU General Public License as published by
9 the Free Software Foundation. You should have received a copy
10 of the license along with this file; see the file COPYING.
11
12 This file is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 license for more details.
16*/
17
18/*
19 Operating System GLUe for microsoft WINdows
20
21 All operating system dependent code for the
22 Microsoft Windows platform should go here.
23
24 This code is descended from Weston Pawlowski's Windows
25 port of vMac, by Philip Cummins.
26 Adapted by Fabio Concas to run on Pocket PC 2003 devices.
27
28 The main entry point '_tWinMain' is at the end of this file.
29*/
30
31#include "OSGCOMUI.h"
32#include "OSGCOMUD.h"
33
34#ifdef WantOSGLUWIN
35
36
37/* --- adapting to API/ABI version differences --- */
38
39#ifdef UNICODE
40#define MyUseUni 1
41#else
42#define MyUseUni 0
43#endif
44
45#ifdef _WIN32_WCE
46#define UseWinCE 1
47#else
48#define UseWinCE 0
49#endif
50
51
52#define My_CSIDL_APPDATA 0x001a
53
54typedef BOOL (WINAPI *SHGetSpecialFolderPathProcPtr) (
55 HWND hwndOwner,
56 LPTSTR lpszPath,
57 int nFolder,
58 BOOL fCreate
59);
60LOCALVAR SHGetSpecialFolderPathProcPtr MySHGetSpecialFolderPath = NULL;
61LOCALVAR blnr DidSHGetSpecialFolderPath = falseblnr;
62
63LOCALFUNC blnr HaveMySHGetSpecialFolderPath(void)
64{
65 if (! DidSHGetSpecialFolderPath) {
66 HMODULE hLibModule = LoadLibrary(TEXT("shell32.dll"));
67 if (NULL != hLibModule) {
68 MySHGetSpecialFolderPath =
69 (SHGetSpecialFolderPathProcPtr)
70 GetProcAddress(hLibModule,
71#if MyUseUni
72 TEXT("SHGetSpecialFolderPathW")
73#else
74 TEXT("SHGetSpecialFolderPathA")
75#endif
76 );
77 /* FreeLibrary(hLibModule); */
78 }
79 DidSHGetSpecialFolderPath = trueblnr;
80 }
81 return (MySHGetSpecialFolderPath != NULL);
82}
83
84
85/* --- end of adapting to API/ABI version differences --- */
86
87#if MyUseUni
88#define NeedCell2UnicodeMap 1
89#else
90#define NeedCell2WinAsciiMap 1
91#endif
92#define NeedRequestInsertDisk 1
93#define NeedDoMoreCommandsMsg 1
94#define NeedDoAboutMsg 1
95
96#include "INTLCHAR.h"
97
98
99LOCALPROC NativeStrFromCStr(LPTSTR r, char *s, blnr AddEllipsis)
100{
101 ui3b ps[ClStrMaxLength];
102 int i;
103 int L;
104
105 ClStrFromSubstCStr(&L, ps, s);
106
107 for (i = 0; i < L; ++i) {
108 r[i] = (TCHAR)
109#if MyUseUni
110 Cell2UnicodeMap[ps[i]];
111#else
112 Cell2WinAsciiMap[ps[i]];
113#endif
114 }
115
116 if (AddEllipsis) {
117#if MyUseUni
118 r[L] = 0x2026;
119 ++L;
120#else
121 r[L] = '.';
122 ++L;
123 r[L] = '.';
124 ++L;
125 r[L] = '.';
126 ++L;
127#endif
128 }
129
130 r[L] = 0;
131}
132
133LOCALFUNC LPTSTR FindLastTerm(LPTSTR s, TCHAR delim)
134{
135 TCHAR c;
136 LPTSTR p0 = s;
137 LPTSTR p = (LPTSTR)nullpr;
138
139 while ((c = *p0++) != (TCHAR)('\0')) {
140 if (c == delim) {
141 p = p0;
142 }
143 }
144
145 return p;
146}
147
148LOCALVAR HINSTANCE AppInstance;
149
150LOCALFUNC blnr GetAppDir(LPTSTR pathName)
151/* be sure at least _MAX_PATH long! */
152{
153 if (GetModuleFileName(AppInstance, pathName, _MAX_PATH) == 0) {
154 /* MacMsg("error", "GetModuleFileName failed", falseblnr); */
155 } else {
156 LPTSTR p = FindLastTerm(pathName,
157 (TCHAR)('\\'));
158 if (p == nullpr) {
159 /* MacMsg("error", "strrchr failed", falseblnr); */
160 } else {
161 *--p = (TCHAR)('\0');
162 return trueblnr;
163 }
164 }
165 return falseblnr;
166}
167
168/* --- sending debugging info to file --- */
169
170#if dbglog_HAVE
171
172LOCALVAR HANDLE dbglog_File = INVALID_HANDLE_VALUE;
173
174LOCALFUNC blnr dbglog_open0(void)
175{
176 TCHAR pathName[_MAX_PATH];
177 TCHAR Child0[] = TEXT("\\dbglog.txt");
178 size_t newlen;
179
180 if (GetAppDir(pathName)) {
181 newlen = _tcslen(pathName) + _tcslen(Child0);
182 if (newlen + 1 < _MAX_PATH) {
183 _tcscat(pathName, Child0);
184
185 dbglog_File = CreateFile(
186 pathName, /* pointer to name of the file */
187 GENERIC_READ + GENERIC_WRITE,
188 /* access (read-write) mode */
189 0, /* share mode */
190 NULL, /* pointer to security descriptor */
191 OPEN_ALWAYS, /* how to create */
192 FILE_ATTRIBUTE_NORMAL, /* file attributes */
193 NULL /* handle to file with attributes to copy */
194 );
195 if (INVALID_HANDLE_VALUE == dbglog_File) {
196 /* report error (how?) */
197 } else if (SetFilePointer(
198 dbglog_File, /* handle of file */
199 0, /* number of bytes to move file pointer */
200 nullpr,
201 /* address of high-order word of distance to move */
202 FILE_BEGIN /* how to move */
203 ) != 0)
204 {
205 /* report error (how?) */
206 }
207 }
208 }
209
210 return (INVALID_HANDLE_VALUE != dbglog_File);
211}
212
213LOCALPROC dbglog_write0(char *s, uimr L)
214{
215 DWORD BytesWritten;
216
217 if (INVALID_HANDLE_VALUE != dbglog_File) {
218 if (! WriteFile(dbglog_File, /* handle of file to read */
219 (LPVOID)s, /* address of buffer that receives data */
220 (DWORD)L, /* number of bytes to read */
221 &BytesWritten, /* address of number of bytes read */
222 nullpr) /* address of structure for data */
223 || ((ui5b)BytesWritten != L))
224 {
225 /* report error (how?) */
226 }
227 }
228}
229
230LOCALPROC dbglog_close0(void)
231{
232 if (INVALID_HANDLE_VALUE != dbglog_File) {
233 if (! SetEndOfFile(dbglog_File)) {
234 /* report error (how?) */
235 }
236 (void) CloseHandle(dbglog_File);
237 dbglog_File = INVALID_HANDLE_VALUE;
238 }
239}
240
241#endif
242
243#include "COMOSGLU.h"
244
245#ifndef InstallFileIcons
246#define InstallFileIcons 0
247#endif
248
249/* Resource Ids */
250
251#define IDI_VMAC 256
252#if InstallFileIcons
253#define IDI_ROM 257
254#define IDI_DISK 258
255#endif
256
257/* --- some simple utilities --- */
258
259#define TestBit(i, p) (((unsigned long)(i) & PowOf2(p)) != 0)
260
261GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
262{
263/*
264 must work even if blocks overlap in memory
265*/
266 (void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
267}
268
269/* --- Parameter buffers --- */
270
271#if IncludePbufs
272LOCALVAR HGLOBAL PbufDat[NumPbufs];
273#endif
274
275#if IncludePbufs
276LOCALFUNC tMacErr PbufNewFromHandle(HGLOBAL h, ui5b count, tPbuf *r)
277{
278 tPbuf i;
279 tMacErr err;
280
281 if (! FirstFreePbuf(&i)) {
282 (void) GlobalFree(h);
283 err = mnvm_miscErr;
284 } else {
285 *r = i;
286 PbufDat[i] = h;
287 PbufNewNotify(i, count);
288 err = mnvm_noErr;
289 }
290
291 return err;
292}
293#endif
294
295#if IncludePbufs
296GLOBALOSGLUFUNC tMacErr PbufNew(ui5b count, tPbuf *r)
297{
298 HGLOBAL h;
299 tMacErr err = mnvm_miscErr;
300
301 h = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, count);
302 if (h != NULL) {
303 /* need to clear h */
304 err = PbufNewFromHandle(h, count, r);
305 }
306
307 return err;
308}
309#endif
310
311#if IncludePbufs
312GLOBALOSGLUPROC PbufDispose(tPbuf i)
313{
314 (void) GlobalFree(PbufDat[i]);
315 PbufDisposeNotify(i);
316}
317#endif
318
319#if IncludePbufs
320LOCALPROC UnInitPbufs(void)
321{
322 tPbuf i;
323
324 for (i = 0; i < NumPbufs; ++i) {
325 if (PbufIsAllocated(i)) {
326 PbufDispose(i);
327 }
328 }
329}
330#endif
331
332#if IncludePbufs
333#define PbufHaveLock 1
334#endif
335
336#if IncludePbufs
337LOCALFUNC ui3p PbufLock(tPbuf i)
338{
339 HGLOBAL h = PbufDat[i];
340 return (ui3p)GlobalLock(h);
341}
342#endif
343
344#if IncludePbufs
345LOCALPROC PbufUnlock(tPbuf i)
346{
347 (void) GlobalUnlock(PbufDat[i]);
348}
349#endif
350
351#if IncludePbufs
352GLOBALOSGLUPROC PbufTransfer(ui3p Buffer,
353 tPbuf i, ui5r offset, ui5r count, blnr IsWrite)
354{
355 HGLOBAL h = PbufDat[i];
356 ui3p p0 = GlobalLock(h);
357 if (p0 != NULL) {
358 void *p = p0 + offset;
359 if (IsWrite) {
360 (void) memcpy(p, Buffer, count);
361 } else {
362 (void) memcpy(Buffer, p, count);
363 }
364 }
365 (void) GlobalUnlock(h);
366}
367#endif
368
369/* --- control mode and internationalization --- */
370
371#include "CONTROLM.h"
372
373/* --- main window info --- */
374
375LOCALVAR HWND MainWnd = NULL;
376
377LOCALVAR int WndX;
378LOCALVAR int WndY;
379
380#if UseWinCE
381LOCALVAR short oldOrientation;
382LOCALVAR unsigned long oldDisplayOrientation;
383#endif
384
385#if VarFullScreen
386LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0);
387#endif
388
389#if EnableMagnify
390LOCALVAR blnr UseMagnify = (WantInitMagnify != 0);
391#endif
392
393#if MayFullScreen
394LOCALVAR short hOffset;
395LOCALVAR short vOffset;
396#endif
397
398/* cursor hiding */
399
400LOCALVAR blnr HaveCursorHidden = falseblnr;
401LOCALVAR blnr WantCursorHidden = falseblnr;
402
403LOCALPROC ForceShowCursor(void)
404{
405 if (HaveCursorHidden) {
406 HaveCursorHidden = falseblnr;
407 (void) ShowCursor(TRUE);
408 SetCursor(LoadCursor(NULL, IDC_ARROW));
409 }
410}
411
412/* cursor moving */
413
414LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
415{
416 POINT NewMousePos;
417 ui5b difftime;
418 blnr IsOk;
419 DWORD StartTime = GetTickCount();
420 LONG x = h;
421 LONG y = v;
422
423#if VarFullScreen
424 if (UseFullScreen)
425#endif
426#if MayFullScreen
427 {
428 x -= ViewHStart;
429 y -= ViewVStart;
430 }
431#endif
432
433#if EnableMagnify
434 if (UseMagnify) {
435 x *= MyWindowScale;
436 y *= MyWindowScale;
437 }
438#endif
439
440#if VarFullScreen
441 if (UseFullScreen)
442#endif
443#if MayFullScreen
444 {
445 x += hOffset;
446 y += vOffset;
447 }
448#endif
449
450 x += WndX;
451 y += WndY;
452
453 do {
454 (void) SetCursorPos(x, y);
455 if (! GetCursorPos(&NewMousePos)) {
456 IsOk = falseblnr;
457 } else {
458 IsOk = (x == NewMousePos.x) && (y == NewMousePos.y);
459 }
460 difftime = (ui5b)(GetTickCount() - StartTime);
461 } while ((! IsOk) && (difftime < 100));
462 return IsOk;
463}
464
465#if EnableFSMouseMotion
466LOCALPROC StartSaveMouseMotion(void)
467{
468 if (! HaveMouseMotion) {
469 if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
470 ViewVStart + (ViewVSize / 2)))
471 {
472 SavedMouseH = ViewHStart + (ViewHSize / 2);
473 SavedMouseV = ViewVStart + (ViewVSize / 2);
474 HaveMouseMotion = trueblnr;
475 }
476 }
477}
478#endif
479
480#if EnableFSMouseMotion
481LOCALPROC StopSaveMouseMotion(void)
482{
483 if (HaveMouseMotion) {
484 (void) MyMoveMouse(CurMouseH, CurMouseV);
485 HaveMouseMotion = falseblnr;
486 }
487}
488#endif
489
490LOCALVAR blnr MyMouseCaptured = falseblnr;
491
492LOCALPROC MyMouseCaptureSet(blnr v)
493{
494 if (v != MyMouseCaptured) {
495 if (v) {
496 (void) SetCapture(MainWnd);
497 } else {
498 (void) ReleaseCapture();
499 }
500 MyMouseCaptured = v;
501 }
502}
503
504LOCALPROC SetCurMouseButton(blnr v)
505{
506 MyMouseButtonSet(v);
507 MyMouseCaptureSet(v);
508}
509
510/* keyboard */
511
512/* these constants weren't in the header files I have */
513#define myVK_Subtract 0xBD
514#define myVK_Equal 0xBB
515#define myVK_BackSlash 0xDC
516#define myVK_Comma 0xBC
517#define myVK_Period 0xBE
518#define myVK_Slash 0xBF
519#define myVK_SemiColon 0xBA
520#define myVK_SingleQuote 0xDE
521#define myVK_LeftBracket 0xDB
522#define myVK_RightBracket 0xDD
523#define myVK_Grave 0xC0
524
525/* some new ones, need to check if in all header versions */
526#define myVK_PRIOR 0x21
527#define myVK_NEXT 0x22
528#define myVK_END 0x23
529#define myVK_HOME 0x24
530#define myVK_INSERT 0x2D
531#define myVK_DELETE 0x2E
532#define myVK_HELP 0x2F
533#define myVK_SCROLL 0x91
534#define myVK_SNAPSHOT 0x2C
535#define myVK_PAUSE 0x13
536#define myVK_CLEAR 0x0C
537
538#define myVK_OEM_8 0xDF
539#define myVK_OEM_102 0xE2
540
541#ifndef ItnlKyBdFix
542#define ItnlKyBdFix 0
543#endif
544
545#if ItnlKyBdFix
546LOCALVAR ui3b MyVkMapA[256];
547#endif
548
549#if ItnlKyBdFix
550LOCALPROC MyVkSwapZY(void)
551{
552 MyVkMapA['Z'] = 'Y';
553 MyVkMapA['Y'] = 'Z';
554}
555#endif
556
557#if ItnlKyBdFix
558LOCALPROC MyVkSwapGraveQuote(void)
559{
560 MyVkMapA[myVK_Grave] = myVK_SingleQuote;
561 MyVkMapA[myVK_SingleQuote] = myVK_Grave;
562}
563#endif
564
565#if ItnlKyBdFix
566LOCALPROC MyVkSwapSlashSubtract(void)
567{
568 MyVkMapA[myVK_Slash] = myVK_Subtract;
569 MyVkMapA[myVK_Subtract] = myVK_Slash;
570}
571#endif
572
573#if ItnlKyBdFix
574LOCALPROC MyVkSwapAQZWGraveQuote(void)
575{
576 MyVkSwapGraveQuote();
577 MyVkMapA['A'] = 'Q';
578 MyVkMapA['Q'] = 'A';
579 MyVkMapA['Z'] = 'W';
580 MyVkMapA['W'] = 'Z';
581}
582#endif
583
584#if ItnlKyBdFix
585LOCALPROC MyVkMapBelgian(void)
586{
587 MyVkSwapAQZWGraveQuote();
588 MyVkMapA['M'] = myVK_SemiColon;
589 MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
590 MyVkMapA[myVK_RightBracket] = myVK_LeftBracket;
591 MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
592 MyVkMapA[myVK_Subtract] = myVK_Equal;
593 MyVkMapA[myVK_Equal] = myVK_Slash;
594 MyVkMapA[myVK_Slash] = myVK_Period;
595 MyVkMapA[myVK_Period] = myVK_Comma;
596 MyVkMapA[myVK_Comma] = 'M';
597}
598#endif
599
600#if ItnlKyBdFix
601LOCALPROC MyVkMapSwiss(void)
602{
603 MyVkSwapZY();
604 MyVkMapA[myVK_OEM_8] = myVK_BackSlash;
605 MyVkMapA[myVK_BackSlash] = myVK_SingleQuote;
606 MyVkMapA[myVK_SingleQuote] = myVK_SemiColon;
607 MyVkMapA[myVK_SemiColon] = myVK_LeftBracket;
608 MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
609 MyVkMapA[myVK_Subtract] = myVK_Slash;
610 MyVkMapA[myVK_Slash] = myVK_Grave;
611 MyVkMapA[myVK_Grave] = myVK_RightBracket;
612 MyVkMapA[myVK_RightBracket] = myVK_Equal;
613}
614#endif
615
616#if ItnlKyBdFix
617LOCALPROC MyVkMapDanish(void)
618{
619 MyVkMapA[myVK_Equal] = myVK_Subtract;
620 MyVkMapA[myVK_Subtract] = myVK_Slash;
621 MyVkMapA[myVK_Slash] = myVK_BackSlash;
622 MyVkMapA[myVK_BackSlash] = myVK_Grave;
623 MyVkMapA[myVK_Grave] = myVK_SemiColon;
624 MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
625 MyVkMapA[myVK_RightBracket] = myVK_LeftBracket;
626 MyVkMapA[myVK_LeftBracket] = myVK_Equal;
627}
628#endif
629
630#if ItnlKyBdFix
631LOCALPROC MyVkMapBritish(void)
632{
633 MyVkMapA[myVK_OEM_8] = myVK_Grave;
634 MyVkMapA[myVK_Grave] = myVK_SingleQuote;
635 MyVkMapA[myVK_SingleQuote] = myVK_BackSlash;
636 MyVkMapA[myVK_BackSlash] = myVK_OEM_102;
637}
638#endif
639
640#if ItnlKyBdFix
641LOCALPROC MyVkMapSpanish(void)
642{
643 MyVkMapA[myVK_SemiColon] = myVK_LeftBracket;
644 MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
645 MyVkMapA[myVK_Subtract] = myVK_Slash;
646 MyVkMapA[myVK_Slash] = myVK_BackSlash;
647 MyVkMapA[myVK_BackSlash] = myVK_Grave;
648 MyVkMapA[myVK_Grave] = myVK_SemiColon;
649
650 MyVkMapA[myVK_RightBracket] = myVK_Equal;
651 MyVkMapA[myVK_Equal] = myVK_RightBracket;
652}
653#endif
654
655#if ItnlKyBdFix
656LOCALPROC MyVkMapDutch(void)
657{
658 MyVkSwapGraveQuote();
659 MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
660 MyVkMapA[myVK_RightBracket] = myVK_LeftBracket;
661 MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
662 MyVkMapA[myVK_Subtract] = myVK_Slash;
663 MyVkMapA[myVK_Slash] = myVK_Equal;
664 MyVkMapA[myVK_Equal] = myVK_SemiColon;
665}
666#endif
667
668#if ItnlKyBdFix
669LOCALPROC MyVkMapGreekIBM(void)
670{
671 MyVkSwapSlashSubtract();
672 MyVkMapA[myVK_LeftBracket] = myVK_Equal;
673 MyVkMapA[myVK_Equal] = myVK_LeftBracket;
674}
675#endif
676
677#if ItnlKyBdFix
678LOCALPROC MyVkMapFrench(void)
679{
680 MyVkSwapAQZWGraveQuote();
681 MyVkMapA['M'] = myVK_SemiColon;
682 MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
683 MyVkMapA[myVK_RightBracket] = myVK_LeftBracket;
684 MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
685 MyVkMapA[myVK_Comma] = 'M';
686 MyVkMapA[myVK_Period] = myVK_Comma;
687 MyVkMapA[myVK_Slash] = myVK_Period;
688 MyVkMapA[myVK_OEM_8] = myVK_Slash;
689}
690#endif
691
692#if ItnlKyBdFix
693LOCALPROC MyVkMapGerman(void)
694{
695 MyVkSwapZY();
696 MyVkMapSpanish();
697}
698#endif
699
700#if ItnlKyBdFix
701LOCALPROC MyVkMapBosnian(void)
702{
703 MyVkSwapZY();
704 /* not in Windows 95 */
705 MyVkSwapSlashSubtract();
706}
707#endif
708
709#if ItnlKyBdFix
710LOCALPROC MyVkMapBulgarian(void)
711{
712 MyVkMapA[myVK_OEM_8] = myVK_Comma;
713 MyVkMapA[myVK_Comma] = 'Q';
714 MyVkMapA['Q'] = myVK_Period;
715 MyVkMapA[myVK_Period] = myVK_Equal;
716}
717#endif
718
719#if ItnlKyBdFix
720LOCALPROC MyVkMapFromLayout(uimr sv)
721{
722 int i;
723
724 for (i = 0; i < 256; ++i) {
725 MyVkMapA[i] = i;
726 }
727
728 switch (sv) {
729 case 0x00000409:
730 /* United States 101 */
731 break;
732 case 0x0000041c:
733 /* Albanian; */
734 MyVkSwapZY();
735 break;
736 case 0x0000042B:
737 /* Armenian Eastern; */
738 MyVkMapDutch();
739 break;
740 case 0x0001042B:
741 /* Armenian Western; */
742 MyVkMapDutch();
743 break;
744 case 0x0000042C:
745 /* not in Windows 95 */
746 /* Azeri Latin */
747 MyVkMapBritish();
748 break;
749 case 0x0001080C:
750 /* Belgian (comma) */
751 MyVkMapBelgian();
752 break;
753 case 0x0000080c:
754 /* Belgian French */
755 MyVkMapBelgian();
756 break;
757 case 0x00000813:
758 /* not in Windows 95 */
759 /* Belgian (period); */
760 MyVkMapBelgian();
761 break;
762 case 0x0000141A:
763 /* not in Windows 95 */
764 /* Bosnian */
765 MyVkMapBosnian();
766 break;
767 case 0x00000809:
768 /* British / United Kingdom */
769 MyVkMapBritish();
770 break;
771 case 0x00000452:
772 /* not in Windows 95 */
773 /* United Kingdom Extended */
774 MyVkMapBritish();
775 break;
776 case 0x00000402:
777 /* Bulgarian */
778 /* not same in Windows 95 */
779 MyVkMapBulgarian();
780 break;
781 case 0x00030402:
782 /* Bulgarian */
783 MyVkMapBulgarian();
784 break;
785 case 0x00020402:
786 /* Bulgarian (Phonetic) */
787 MyVkMapBosnian();
788 break;
789 case 0x00001009:
790 /* Canadian Multilingual */
791 /* not in Windows 95 */
792 MyVkSwapGraveQuote();
793 break;
794 case 0x00011009:
795 /* Canadian Standard */
796 MyVkSwapGraveQuote();
797 break;
798 case 0x0000041a:
799 /* Croatian */
800 MyVkMapBosnian();
801 break;
802 case 0x00000405:
803 /* Czech */
804 MyVkMapBosnian();
805#if 0
806 /* but Windows 7 gives */
807 MyVkSwapZY();
808 MyVkMapA[myVK_Equal] = myVK_Subtract;
809 MyVkMapA[myVK_Subtract] = myVK_Slash;
810 MyVkMapA[myVK_Slash] = myVK_Equal;
811#endif
812 break;
813 case 0x00020405:
814 /* Czech (Programmers) */
815 /* only in Windows 95 */
816 /* MyVkSwapZY(); */
817 break;
818 case 0x00010405:
819 /* Czech (Qwerty) */
820 /* only in Windows 95 */
821 /* MyVkSwapZY(); */
822 break;
823 case 0x00000406:
824 /* Danish */
825 MyVkMapDanish();
826 break;
827 case 0x00000413:
828 /* Dutch */
829 MyVkMapDutch();
830 break;
831 case 0x00000425:
832 /* Estonian */
833 MyVkMapA[myVK_Grave] = myVK_LeftBracket;
834 MyVkMapA[myVK_LeftBracket] = myVK_RightBracket;
835 MyVkMapA[myVK_RightBracket] = myVK_Slash;
836 MyVkMapA[myVK_Slash] = myVK_SingleQuote;
837 MyVkMapA[myVK_SingleQuote] = myVK_Grave;
838 /* only in Windows 95 ? */
839 /* MyVkMapA[VK_DECIMAL] = VK_DELETE; */
840 break;
841 case 0x00000438:
842 /* Faeroe Islands */
843 MyVkMapDanish();
844 break;
845 case 0x0000040b:
846 /* Finnish */
847 MyVkMapDanish();
848 break;
849 case 0x0001083B:
850 /* not in Windows 95 */
851 /* Finnish with Sami */
852 MyVkMapDanish();
853 break;
854 case 0x0000040c:
855 /* v = kMyKbdFrench; */
856 /* French */
857 MyVkMapFrench();
858 break;
859 case 0x00000c0c:
860 /* French Canadian */
861 MyVkSwapGraveQuote();
862 break;
863 case 0x00011809:
864 /* not in Windows 95 */
865 /* Gaelic */
866 MyVkMapBritish();
867 break;
868 case 0x00010407:
869 /* German (IBM) */
870 MyVkMapGerman();
871 break;
872 case 0x00000407:
873 /* German (Standard) */
874 MyVkMapGerman();
875 break;
876 case 0x00010408:
877 /* Greek IBM 220 */
878 /* not in Windows 95 */
879 MyVkMapGreekIBM();
880 break;
881 case 0x00030408:
882 /* Greek IBM 319 */
883 /* not in Windows 95 */
884 MyVkMapGreekIBM();
885 break;
886 case 0x00020408:
887 /* Greek Latin IBM 220 */
888 /* not in Windows 95 */
889 MyVkSwapSlashSubtract();
890 break;
891 case 0x00040408:
892 /* Greek Latin IBM 319 */
893 /* not in Windows 95 */
894 MyVkSwapSlashSubtract();
895 break;
896 case 0x0000040e:
897 /* Hungarian */
898 MyVkMapBosnian();
899 MyVkMapA[myVK_Grave] = '0';
900 MyVkMapA['0'] = myVK_Grave;
901 break;
902 case 0x0001040E:
903 /* Hungarian (101 Keys) */
904 MyVkMapA[myVK_Grave] = '0';
905 MyVkMapA['0'] = myVK_Grave;
906 break;
907 case 0x0000040f:
908 /* Icelandic */
909 MyVkMapDanish();
910 break;
911 case 0x00001809:
912 /* Irish */
913 MyVkMapBritish();
914 break;
915 case 0x00000410:
916 /* Italian */
917 MyVkMapSpanish();
918 break;
919 case 0x00010410:
920 /* Italian 142 */
921 MyVkMapSpanish();
922 break;
923 case 0x0000080a:
924 /* Latin American */
925 MyVkMapSpanish();
926 break;
927 case 0x0000046E:
928 /* Luxembourgish */
929 MyVkMapSwiss();
930 break;
931 case 0x00000414:
932 /* Norwegian */
933 MyVkMapDanish();
934 break;
935 case 0x0000043B:
936 /* Norwegian with Sami */
937 MyVkMapDanish();
938 break;
939 case 0x00010415:
940 /* Polish (214) */
941 MyVkSwapZY();
942 /* not in windows 95 */
943 MyVkMapA[myVK_Equal] = myVK_Subtract;
944 MyVkMapA[myVK_Subtract] = myVK_Slash;
945 MyVkMapA[myVK_Slash] = myVK_Equal;
946 break;
947 case 0x00010416:
948 /* Porguguese (Brazilian ABNT2) */
949 /* MyVkMapA[myVK_OEM_8] = ??; */
950 /* MyVkMapA[VK_SEPARATOR] = ??; */
951 break;
952 case 0x00000816:
953 /* Porguguese (Standard) */
954 MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
955 MyVkMapA[myVK_RightBracket] = myVK_Equal;
956 MyVkMapA[myVK_Equal] = myVK_LeftBracket;
957 MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
958 MyVkMapA[myVK_Subtract] = myVK_Slash;
959 MyVkMapA[myVK_Slash] = myVK_BackSlash;
960 MyVkMapA[myVK_BackSlash] = myVK_Grave;
961 MyVkMapA[myVK_Grave] = myVK_SemiColon;
962 break;
963 case 0x00000418:
964 /* Romanian (Legacy) */
965 MyVkSwapZY();
966 /* only in Windows 95 */
967 /* MyVkSwapSlashSubtract(); */
968 break;
969 case 0x0002083B:
970 /* Sami Extended Finland-Sweden */
971 MyVkMapDanish();
972 break;
973 case 0x0001043B:
974 /* Sami Extended Norway */
975 MyVkMapDanish();
976 break;
977 case 0x00010C1A:
978 /* in Windows 95 */
979 /* Serbian (Latin) */
980 MyVkSwapZY();
981 break;
982 case 0x0000081A:
983 /* not in Windows 95 */
984 /* Serbian (Latin) */
985 MyVkMapBosnian();
986 break;
987 case 0x0000041b:
988 /* Slovak */
989 MyVkMapBosnian();
990 /* not in Windows 95 */
991 MyVkMapA[myVK_OEM_8] = myVK_Equal;
992 break;
993 case 0x00000424:
994 /* Slovenian */
995 MyVkMapBosnian();
996 break;
997 case 0x0000040A:
998 /* Spanish, not windows 95 */
999 MyVkMapSpanish();
1000 break;
1001 case 0x0001040A:
1002 /* Spanish Variation, not windows 95 */
1003 MyVkMapA[myVK_OEM_8] = myVK_Slash;
1004 MyVkMapA[myVK_Slash] = myVK_BackSlash;
1005 MyVkMapA[myVK_BackSlash] = myVK_Grave;
1006 MyVkMapA[myVK_Grave] = myVK_SemiColon;
1007 MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
1008 MyVkMapA[myVK_RightBracket] = myVK_LeftBracket;
1009 MyVkMapA[myVK_LeftBracket] = myVK_Equal;
1010 break;
1011 case 0x00000c0a:
1012 /* kMyKbdSpanish; */
1013 /* Spanish Modern, windows 95 */
1014 MyVkMapSpanish();
1015 break;
1016 case 0x00000403:
1017 /* Spanish Traditional */
1018 MyVkMapSpanish();
1019 break;
1020 case 0x0000041d:
1021 /* Swedish */
1022 MyVkMapDanish();
1023 break;
1024 case 0x0000083B:
1025 /* not in windows 95 */
1026 /* Swedish with Sami */
1027 MyVkMapDanish();
1028 break;
1029 case 0x0000100c:
1030 /* Swiss French */
1031 MyVkMapSwiss();
1032 break;
1033 case 0x00000807:
1034 /* Swiss German */
1035 MyVkMapSwiss();
1036 break;
1037 case 0x0000085D:
1038 /* Inuktitut Latin */
1039 /* in windows 7, not XP */
1040 MyVkMapBritish();
1041 break;
1042 case 0x0001045D:
1043 /* Inuktitut - Naqittaut */
1044 MyVkMapBritish();
1045 break;
1046 case 0x0000046F:
1047 /* Greenlandic */
1048 MyVkMapDanish();
1049 break;
1050 case 0x00020427:
1051 /* Lithuanian Standard */
1052 MyVkMapDanish();
1053 break;
1054 case 0x0000042f:
1055 /* Macedonian (FYROM) - Standard */
1056 MyVkMapBosnian();
1057 break;
1058 case 0x0000042E:
1059 /* Sorbian Standard (Legacy) */
1060 MyVkMapGerman();
1061 break;
1062 case 0x0001042E:
1063 /* Sorbian Extended */
1064 MyVkMapGerman();
1065 break;
1066 case 0x0002042E:
1067 /* Sorbian Standard */
1068 MyVkMapGerman();
1069 break;
1070 case 0x00000488:
1071 /* Wolof */
1072 MyVkMapFrench();
1073 break;
1074 case 0x0000041f:
1075 /* Turkish (Q type) */
1076 /* windows 95 */
1077 /* MyVkMapA[myVK_Equal] = myVK_Subtract; */
1078 /* MyVkMapA[myVK_Subtract] = myVK_Equal; */
1079 /* not windows 95 */
1080 MyVkMapA[myVK_OEM_8] = myVK_Subtract;
1081 MyVkMapA[myVK_Subtract] = myVK_Equal;
1082
1083 MyVkMapA[myVK_Comma] = myVK_BackSlash;
1084 MyVkMapA[myVK_BackSlash] = myVK_Period;
1085 MyVkMapA[myVK_Period] = myVK_Slash;
1086 MyVkMapA[myVK_Slash] = myVK_Comma;
1087 break;
1088 case 0x00010409:
1089 /* United States Dvorak */
1090 MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
1091 MyVkMapA[myVK_RightBracket] = myVK_Equal;
1092 MyVkMapA[myVK_SingleQuote] = 'Q';
1093 MyVkMapA[myVK_Comma] = 'W';
1094 MyVkMapA[myVK_Period] = 'E';
1095 MyVkMapA['P'] = 'R';
1096 MyVkMapA['Y'] = 'T';
1097 MyVkMapA['F'] = 'Y';
1098 MyVkMapA['G'] = 'U';
1099 MyVkMapA['C'] = 'I';
1100 MyVkMapA['R'] = 'O';
1101 MyVkMapA['L'] = 'P';
1102 MyVkMapA[myVK_Slash] = myVK_LeftBracket;
1103 MyVkMapA[myVK_Equal] = myVK_RightBracket;
1104 MyVkMapA['O'] = 'S';
1105 MyVkMapA['E'] = 'D';
1106 MyVkMapA['U'] = 'F';
1107 MyVkMapA['I'] = 'G';
1108 MyVkMapA['D'] = 'H';
1109 MyVkMapA['H'] = 'J';
1110 MyVkMapA['T'] = 'K';
1111 MyVkMapA['N'] = 'L';
1112 MyVkMapA['S'] = myVK_SemiColon;
1113 MyVkMapA[myVK_Subtract] = myVK_SingleQuote;
1114 MyVkMapA[myVK_SemiColon] = 'Z';
1115 MyVkMapA['Q'] = 'X';
1116 MyVkMapA['J'] = 'C';
1117 MyVkMapA['K'] = 'V';
1118 MyVkMapA['X'] = 'B';
1119 MyVkMapA['B'] = 'N';
1120 MyVkMapA['W'] = myVK_Comma;
1121 MyVkMapA['V'] = myVK_Period;
1122 MyVkMapA['Z'] = myVK_Slash;
1123 break;
1124#if 0
1125 /* too complicated, don't bother with */
1126 case 0x0x00000426:
1127 /* Latvian */
1128 MyVkMapA['F'] = myVK_Equal;
1129 MyVkMapA['G'] = 'W';
1130 MyVkMapA['J'] = 'E';
1131 MyVkMapA['M'] = 'T';
1132 MyVkMapA['V'] = 'Y';
1133 MyVkMapA['N'] = 'U';
1134 MyVkMapA['Z'] = 'I';
1135 MyVkMapA['W'] = 'O';
1136 MyVkMapA['X'] = 'P';
1137 MyVkMapA['Y'] = myVK_LeftBracket;
1138 MyVkMapA['H'] = myVK_RightBracket;
1139 MyVkMapA[myVK_SemiColon] = 'A';
1140 MyVkMapA['U'] = 'S';
1141 MyVkMapA['S'] = 'D';
1142 MyVkMapA['I'] = 'F';
1143 MyVkMapA['L'] = 'G';
1144 MyVkMapA['D'] = 'H';
1145 MyVkMapA['A'] = 'J';
1146 MyVkMapA['T'] = 'K';
1147 MyVkMapA['E'] = 'L';
1148 MyVkMapA['C'] = myVK_SemiColon;
1149 MyVkMapA[myVK_LeftBracket] = 'Z';
1150 MyVkMapA['B'] = 'X';
1151 MyVkMapA[myVK_RightBracket] = 'C';
1152 MyVkMapA['K'] = 'V';
1153 MyVkMapA['P'] = 'B';
1154 MyVkMapA['O'] = 'N';
1155 MyVkMapA[myVK_OEM_8] = 'M';
1156 break;
1157 case 0x0001041F:
1158 /* Turkish (F type) */
1159
1160 MyVkMapA[myVK_Equal] = myVK_Subtract;
1161 MyVkMapA[myVK_Subtract] = myVK_Equal;
1162 MyVkMapA['F'] = 'Q';
1163 MyVkMapA['G'] = 'W';
1164 MyVkMapA[myVK_SemiColon] = 'E';
1165 MyVkMapA['I'] = 'R';
1166 MyVkMapA['O'] = 'T';
1167 MyVkMapA['D'] = 'Y';
1168 MyVkMapA['R'] = 'U';
1169 MyVkMapA['N'] = 'I';
1170 MyVkMapA['H'] = 'O';
1171 MyVkMapA['Q'] = myVK_LeftBracket;
1172 MyVkMapA['W'] = myVK_RightBracket;
1173 MyVkMapA['U'] = 'A';
1174 MyVkMapA[myVK_LeftBracket] = 'S';
1175 MyVkMapA['E'] = 'D';
1176 MyVkMapA['A'] = 'F';
1177 MyVkMapA[myVK_RightBracket] = 'G';
1178 MyVkMapA['T'] = 'H';
1179 MyVkMapA['K'] = 'J';
1180 MyVkMapA['M'] = 'K';
1181 MyVkMapA['Y'] = myVK_SemiColon;
1182 MyVkMapA['X'] = myVK_BackSlash;
1183 MyVkMapA['J'] = 'Z';
1184 MyVkMapA[myVK_BackSlash] = 'X';
1185 MyVkMapA['V'] = 'C';
1186 MyVkMapA['C'] = 'V';
1187 MyVkMapA[myVK_Slash] = 'B';
1188 MyVkMapA['Z'] = 'N';
1189 MyVkMapA['S'] = 'M';
1190 MyVkMapA['B'] = myVK_Comma;
1191 MyVkMapA[myVK_Comma] = myVK_Slash;
1192 break;
1193 case 0x00030409:
1194 /* United States LH Dvorak */
1195 MyVkMapA[myVK_LeftBracket] = '1';
1196 MyVkMapA[myVK_RightBracket] = '2';
1197 MyVkMapA[myVK_Slash] = '3';
1198 MyVkMapA['P'] = '4';
1199 MyVkMapA['F'] = '5';
1200 MyVkMapA['M'] = '6';
1201 MyVkMapA['L'] = '7';
1202 MyVkMapA['J'] = '8';
1203 MyVkMapA['4'] = '9';
1204 MyVkMapA['3'] = '0';
1205 MyVkMapA['2'] = myVK_Subtract;
1206 MyVkMapA['1'] = myVK_Equal;
1207 MyVkMapA[myVK_SemiColon] = 'Q';
1208 MyVkMapA['Q'] = 'W';
1209 MyVkMapA['B'] = 'E';
1210 MyVkMapA['Y'] = 'R';
1211 MyVkMapA['U'] = 'T';
1212 MyVkMapA['R'] = 'Y';
1213 MyVkMapA['S'] = 'U';
1214 MyVkMapA['O'] = 'I';
1215 MyVkMapA[myVK_Period] = 'O';
1216 MyVkMapA['6'] = 'P';
1217 MyVkMapA['5'] = myVK_LeftBracket;
1218 MyVkMapA[myVK_Equal] = myVK_RightBracket;
1219 MyVkMapA[myVK_Subtract] = 'A';
1220 MyVkMapA['K'] = 'S';
1221 MyVkMapA['C'] = 'D';
1222 MyVkMapA['D'] = 'F';
1223 MyVkMapA['T'] = 'G';
1224 MyVkMapA['E'] = 'J';
1225 MyVkMapA['A'] = 'K';
1226 MyVkMapA['Z'] = 'L';
1227 MyVkMapA['8'] = myVK_SemiColon;
1228 MyVkMapA['7'] = myVK_SingleQuote;
1229 MyVkMapA[myVK_SingleQuote] = 'Z';
1230 MyVkMapA['G'] = 'C';
1231 MyVkMapA['W'] = 'B';
1232 MyVkMapA['I'] = 'M';
1233 MyVkMapA['0'] = myVK_Period;
1234 MyVkMapA['9'] = myVK_Slash;
1235 break;
1236 case 0x00040409:
1237 /* United States RH Dvorak */
1238 MyVkMapA['J'] = '5';
1239 MyVkMapA['L'] = '6';
1240 MyVkMapA['M'] = '7';
1241 MyVkMapA['F'] = '8';
1242 MyVkMapA['P'] = '9';
1243 MyVkMapA[myVK_Slash] = '0';
1244 MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
1245 MyVkMapA[myVK_RightBracket] = myVK_Equal;
1246 MyVkMapA['5'] = 'Q';
1247 MyVkMapA['6'] = 'W';
1248 MyVkMapA['Q'] = 'E';
1249 MyVkMapA[myVK_Period] = 'R';
1250 MyVkMapA['O'] = 'T';
1251 MyVkMapA['R'] = 'Y';
1252 MyVkMapA['S'] = 'U';
1253 MyVkMapA['U'] = 'I';
1254 MyVkMapA['Y'] = 'O';
1255 MyVkMapA['B'] = 'P';
1256 MyVkMapA[myVK_SemiColon] = myVK_LeftBracket;
1257 MyVkMapA[myVK_Equal] = myVK_RightBracket;
1258 MyVkMapA['7'] = 'A';
1259 MyVkMapA['8'] = 'S';
1260 MyVkMapA['Z'] = 'D';
1261 MyVkMapA['A'] = 'F';
1262 MyVkMapA['E'] = 'G';
1263 MyVkMapA['T'] = 'J';
1264 MyVkMapA['D'] = 'K';
1265 MyVkMapA['C'] = 'L';
1266 MyVkMapA['K'] = myVK_SemiColon;
1267 MyVkMapA[myVK_Subtract] = myVK_SingleQuote;
1268 MyVkMapA['9'] = 'Z';
1269 MyVkMapA['0'] = 'X';
1270 MyVkMapA['X'] = 'C';
1271 MyVkMapA[myVK_Comma] = 'V';
1272 MyVkMapA['I'] = 'B';
1273 MyVkMapA['W'] = 'M';
1274 MyVkMapA['V'] = myVK_Comma;
1275 MyVkMapA['G'] = myVK_Period;
1276 MyVkMapA[myVK_SingleQuote] = myVK_Slash;
1277 break;
1278#endif
1279#if 0
1280 case 0x0000082C:
1281 /* not in Windows 95 */
1282 /* Azeri Cyrillic */
1283 break;
1284 case 0x00000423:
1285 /* Belarusian */
1286 break;
1287 case 0x00000445:
1288 /* not in Windows 95 */
1289 /* Bengali */
1290 break;
1291 case 0x00010445:
1292 /* not in Windows 95 */
1293 /* Bengali (Inscript) */
1294 break;
1295 case 0x0000201A:
1296 /* not in Windows 95 */
1297 /* Bosnian Cyrillic*/
1298 break;
1299 case 0x00010402:
1300 /* Bulgarian Latin */
1301#if 0 /* Only in Windows 95 */
1302 MyVkMapA['J'] = 'Q';
1303 MyVkMapA['C'] = 'W';
1304 MyVkMapA['U'] = 'E';
1305 MyVkMapA['K'] = 'R';
1306 MyVkMapA['E'] = 'T';
1307 MyVkMapA['N'] = 'Y';
1308 MyVkMapA['G'] = 'U';
1309 MyVkMapA[myVK_SemiColon] = 'I';
1310 MyVkMapA[myVK_OEM_102] = 'O';
1311 MyVkMapA['Z'] = 'P';
1312 MyVkMapA['H'] = myVK_LeftBracket;
1313 MyVkMapA['F'] = 'A';
1314 MyVkMapA['Y'] = 'S';
1315 MyVkMapA['W'] = 'D';
1316 MyVkMapA['A'] = 'F';
1317 MyVkMapA['P'] = 'G';
1318 MyVkMapA['R'] = 'H';
1319 MyVkMapA['O'] = 'J';
1320 MyVkMapA['L'] = 'K';
1321 MyVkMapA['D'] = 'L';
1322 MyVkMapA['V'] = myVK_SemiColon;
1323 MyVkMapA[myVK_LeftBracket] = 'Z';
1324 MyVkMapA['S'] = 'X';
1325 MyVkMapA['M'] = 'C';
1326 MyVkMapA['I'] = 'V';
1327 MyVkMapA['T'] = 'B';
1328 MyVkMapA['X'] = 'N';
1329 MyVkMapA['B'] = 'M';
1330 MyVkMapA['Q'] = myVK_OEM_102;
1331#endif
1332 break;
1333 case 0x00000408:
1334 /* Greek */
1335 break;
1336 case 0x00050408:
1337 /* Greek Latin */
1338 break;
1339 case 0x00060408:
1340 /* Greek Polytonic */
1341 break;
1342 case 0x0000043F:
1343 /* Kazakh */
1344 break;
1345 case 0x00000440:
1346 /* Kyrgyz Cyrillic */
1347 break;
1348 case 0x00010426:
1349 /* Latvian Latin */
1350 break;
1351 case 0x00010427:
1352 /* Lithuanian */
1353 break;
1354 case 0x00000427:
1355 /* Lithuanian (IBM) */
1356 break;
1357 case 0x0000044C:
1358 /* Malayalam */
1359 break;
1360 case 0x0000042f:
1361 /* Macedonian (FYROM) */
1362 break;
1363 case 0x0000043A:
1364 /* Maltese 47-key */
1365 break;
1366 case 0x0001043A:
1367 /* Maltese 48-key */
1368 break;
1369 case 0x00000481:
1370 /* Maori */
1371 break;
1372 case 0x00000450:
1373 /* Mongolian Cyrillic */
1374 break;
1375 case 0x00000461:
1376 /* Nepali */
1377 break;
1378 case 0x00000463:
1379 /* Pashto */
1380 break;
1381 case 0x00000415:
1382 /* Polish (Programmers) */
1383 break;
1384 case 0x00000416:
1385 /* Porguguese (Brazilian standard) */
1386 break;
1387 case 0x00000419:
1388 /* Russian */
1389 break;
1390 case 0x00010419:
1391 /* Russian (Typewriter) */
1392 break;
1393 case 0x00000c1a:
1394 /* Serbian */
1395 break;
1396 case 0x0001041B:
1397 /* Slovak (Qwerty) */
1398 break;
1399 case 0x00000444:
1400 /* Tatar */
1401 break;
1402 case 0x00000422:
1403 /* Ukrainian */
1404 break;
1405 case 0x00020409:
1406 /* United States International */
1407 break;
1408 case 0x00000843:
1409 /* Uzbek Cyrillic */
1410 break;
1411 case 0x00010418:
1412 /* Romanian (Standard) */
1413 break;
1414 case 0x00020418:
1415 /* Romanian (Programmers) */
1416 break;
1417 case 0x00000401:
1418 /* Arabic (101) */
1419 break;
1420 case 0x00010401:
1421 /* Arabic (102) */
1422 break;
1423 case 0x0000044D:
1424 /* Assamese - INSCRIPT */
1425 break;
1426 case 0x0000046D:
1427 /* Bashkir */
1428 break;
1429 case 0x00040402:
1430 /* Bulgarian (Phonetic Traditional) */
1431 break;
1432 case 0x00000404:
1433 /* Chinese (Traditional) */
1434 break;
1435 case 0x00000804:
1436 /* Chinese (Simplified) */
1437 break;
1438 case 0x00000C04:
1439 /* Chinese (Traditional, Hong Kong S.A.R.) */
1440 break;
1441 case 0x00001004:
1442 /* Chinese (Simplified, Singapore) */
1443 break;
1444 case 0x00001404:
1445 /* Chinese (Traditional, Macao S.A.R.) */
1446 break;
1447 case 0x0000040D:
1448 /* Hebrew */
1449 break;
1450 case 0x00000447:
1451 /* Gujarati */
1452 break;
1453 case 0x00000468:
1454 /* Hausa */
1455 break;
1456 case 0x00010439:
1457 /* Hindi Traditional */
1458 break;
1459 case 0x00000439:
1460 /* Devanagari - INSCRIPT */
1461 break;
1462 case 0x00000465:
1463 /* Divehi Phonetic */
1464 break;
1465 case 0x00010465:
1466 /* Divehi Typewriter */
1467 break;
1468 case 0x00000437:
1469 /* Georgian */
1470 break;
1471 case 0x00010437:
1472 /* Georgian (QWERTY) */
1473 break;
1474 case 0x00020437:
1475 /* Georgian (Ergonomic) */
1476 break;
1477 case 0x00000470:
1478 /* Igbo */
1479 break;
1480 case 0x00000411:
1481 /* Japanese */
1482 /* MyVkMapA[??] = ??; */
1483 break;
1484 case 0x00000412:
1485 /* Korean */
1486 /* MyVkMapA[VK_ZOOM] = ??; */
1487 /* MyVkMapA[VK_HELP] = VK_ZOOM; */
1488 /* MyVkMapA[??] = VK_HELP; */
1489 /* MyVkMapA[??] = ??; */
1490 break;
1491 case 0x0000044B:
1492 /* Kannada */
1493 break;
1494 case 0x00000453:
1495 /* Khmer */
1496 break;
1497 case 0x00000454:
1498 /* Lao */
1499 break;
1500 case 0x00000448:
1501 /* Oriya */
1502 break;
1503 case 0x0000044E:
1504 /* Marathi */
1505 break;
1506 case 0x00000850:
1507 /* Mongolian (Mongolian Script) */
1508 break;
1509 case 0x00000429:
1510 /* Persion */
1511 break;
1512 case 0x00000446:
1513 /* Punjabi */
1514 break;
1515 case 0x0000046C:
1516 /* Sesotho sa Leboa */
1517 break;
1518 case 0x00000432:
1519 /* Setswana */
1520 break;
1521 case 0x0000045B:
1522 /* Sinhala */
1523 break;
1524 case 0x0001045B:
1525 /* Sinhala - Wij 9 */
1526 break;
1527 case 0x0000045A:
1528 /* Syriac */
1529 break;
1530 case 0x0001045A:
1531 /* Syriac Phonetic */
1532 break;
1533 case 0x00000428:
1534 /* Tajik */
1535 break;
1536 case 0x00000449:
1537 /* Tamil */
1538 break;
1539 case 0x0000044A:
1540 /* Telugu */
1541 break;
1542 case 0x0000041E:
1543 /* Thai Kedmanee */
1544 break;
1545 case 0x0001041E:
1546 /* Thai Pattachote */
1547 break;
1548 case 0x0002041E:
1549 /* Thai Kedmanee (non-ShiftLock) */
1550 break;
1551 case 0x0003041E:
1552 /* Thai Pattachote (non-ShiftLock) */
1553 break;
1554 case 0x00000451:
1555 /* Tibetan (PRC) */
1556 break;
1557 case 0x00000442:
1558 /* Turkmen */
1559 break;
1560 case 0x00020422:
1561 /* Ukrainian (Enhanced) */
1562 break;
1563 case 0x00000420:
1564 /* Urdu */
1565 break;
1566 case 0x00050409:
1567 /* US English Table for IBM Arabic 238_L */
1568 break;
1569 case 0x00000480:
1570 /* Uyghur (Legacy) */
1571 break;
1572 case 0x00010480:
1573 /* Uyghur */
1574 break;
1575 case 0x0000042A:
1576 /* Vietnamese */
1577 break;
1578 case 0x00000485:
1579 /* Yakut */
1580 break;
1581 case 0x0000046A:
1582 /* Yoruba */
1583 break;
1584#endif
1585 }
1586}
1587#endif
1588
1589#if ItnlKyBdFix
1590LOCALVAR uimr CurKyBdLytNm = 0;
1591#endif
1592
1593#if ItnlKyBdFix
1594LOCALFUNC blnr tStrIsHex(TCHAR *s, int n, uimr *r)
1595{
1596 short i;
1597 TCHAR c1;
1598 TCHAR *p = s;
1599 uimr v = 0;
1600
1601 for (i = n; --i >= 0; ) {
1602 v <<= 4;
1603 c1 = *p++;
1604 if ((c1 >= '0') && (c1 <= '9')) {
1605 v += c1 - '0';
1606 } else if ((c1 >= 'A') && (c1 <= 'F')) {
1607 v += c1 - ('A' - 10);
1608 } else if ((c1 >= 'a') && (c1 <= 'f')) {
1609 v += c1 - ('a' - 10);
1610 } else {
1611 return falseblnr;
1612 }
1613 }
1614
1615 *r = v;
1616 return trueblnr;
1617}
1618#endif
1619
1620#if ItnlKyBdFix
1621LOCALFUNC blnr MyGetKeyboardLayoutHex(uimr *r)
1622{
1623 TCHAR s[KL_NAMELENGTH];
1624 blnr IsOk = falseblnr;
1625
1626 if (! GetKeyboardLayoutName(s)) {
1627 /* ReportWinLastError(); */
1628 } else {
1629 size_t n = _tcslen(s);
1630
1631 if (8 != n) {
1632 /* fail */
1633 } else {
1634 IsOk = tStrIsHex(s, n, r);
1635 }
1636 }
1637
1638 return IsOk;
1639}
1640#endif
1641
1642#if ItnlKyBdFix && ! UseWinCE
1643LOCALPROC MyCheckKeyboardLayout(void)
1644{
1645 uimr sv;
1646
1647 if (! MyGetKeyboardLayoutHex(&sv)) {
1648 } else if (sv == CurKyBdLytNm) {
1649 /* no change */
1650 } else {
1651 CurKyBdLytNm = sv;
1652
1653 MyVkMapFromLayout(sv);
1654 }
1655}
1656#endif
1657
1658#if ItnlKyBdFix
1659LOCALPROC MyInitCheckKeyboardLayout(void)
1660{
1661 uimr sv;
1662
1663 if (! MyGetKeyboardLayoutHex(&sv)) {
1664 sv = 0x00000409;
1665 }
1666
1667 CurKyBdLytNm = sv;
1668
1669 MyVkMapFromLayout(sv);
1670}
1671#endif
1672
1673LOCALVAR ui3b WinKey2Mac[256];
1674
1675LOCALPROC AssignOneMacKey(ui3b WinKey, ui3r MacKey)
1676{
1677 WinKey2Mac[WinKey] = MacKey;
1678}
1679
1680LOCALFUNC blnr InitWinKey2Mac(void)
1681{
1682 int i;
1683
1684 for (i = 0; i < 256; ++i) {
1685 WinKey2Mac[i] = MKC_None;
1686 }
1687
1688 AssignOneMacKey('A', MKC_A);
1689 AssignOneMacKey('S', MKC_S);
1690 AssignOneMacKey('D', MKC_D);
1691 AssignOneMacKey('F', MKC_F);
1692 AssignOneMacKey('H', MKC_H);
1693 AssignOneMacKey('G', MKC_G);
1694 AssignOneMacKey('Z', MKC_Z);
1695 AssignOneMacKey('X', MKC_X);
1696 AssignOneMacKey('C', MKC_C);
1697 AssignOneMacKey('V', MKC_V);
1698 AssignOneMacKey('B', MKC_B);
1699 AssignOneMacKey('Q', MKC_Q);
1700 AssignOneMacKey('W', MKC_W);
1701 AssignOneMacKey('E', MKC_E);
1702 AssignOneMacKey('R', MKC_R);
1703 AssignOneMacKey('Y', MKC_Y);
1704 AssignOneMacKey('T', MKC_T);
1705 AssignOneMacKey('1', MKC_1);
1706 AssignOneMacKey('2', MKC_2);
1707 AssignOneMacKey('3', MKC_3);
1708 AssignOneMacKey('4', MKC_4);
1709 AssignOneMacKey('6', MKC_6);
1710 AssignOneMacKey('5', MKC_5);
1711 AssignOneMacKey(myVK_Equal, MKC_Equal);
1712 AssignOneMacKey('9', MKC_9);
1713 AssignOneMacKey('7', MKC_7);
1714 AssignOneMacKey(myVK_Subtract, MKC_Minus);
1715 AssignOneMacKey('8', MKC_8);
1716 AssignOneMacKey('0', MKC_0);
1717 AssignOneMacKey(myVK_RightBracket, MKC_RightBracket);
1718 AssignOneMacKey('O', MKC_O);
1719 AssignOneMacKey('U', MKC_U);
1720 AssignOneMacKey(myVK_LeftBracket, MKC_LeftBracket);
1721 AssignOneMacKey('I', MKC_I);
1722 AssignOneMacKey('P', MKC_P);
1723 AssignOneMacKey(VK_RETURN, MKC_Return);
1724 AssignOneMacKey('L', MKC_L);
1725 AssignOneMacKey('J', MKC_J);
1726 AssignOneMacKey(myVK_SingleQuote, MKC_SingleQuote);
1727 AssignOneMacKey('K', MKC_K);
1728 AssignOneMacKey(myVK_SemiColon, MKC_SemiColon);
1729 AssignOneMacKey(myVK_BackSlash, MKC_formac_BackSlash);
1730 AssignOneMacKey(myVK_Comma, MKC_Comma);
1731 AssignOneMacKey(myVK_Slash, MKC_formac_Slash);
1732 AssignOneMacKey('N', MKC_N);
1733 AssignOneMacKey('M', MKC_M);
1734 AssignOneMacKey(myVK_Period, MKC_Period);
1735
1736 AssignOneMacKey(VK_TAB, MKC_Tab);
1737 AssignOneMacKey(VK_SPACE, MKC_Space);
1738 AssignOneMacKey(myVK_Grave, MKC_formac_Grave);
1739 AssignOneMacKey(VK_BACK, MKC_BackSpace);
1740 AssignOneMacKey(VK_ESCAPE, MKC_formac_Escape);
1741
1742 AssignOneMacKey(VK_MENU, MKC_formac_Command);
1743
1744 AssignOneMacKey(VK_LMENU, MKC_formac_Command);
1745
1746 AssignOneMacKey(VK_RMENU, MKC_formac_RCommand);
1747
1748 AssignOneMacKey(VK_SHIFT, MKC_formac_Shift);
1749 AssignOneMacKey(VK_LSHIFT, MKC_formac_Shift);
1750 AssignOneMacKey(VK_RSHIFT, MKC_formac_RShift);
1751
1752 AssignOneMacKey(VK_CAPITAL, MKC_formac_CapsLock);
1753
1754 AssignOneMacKey(VK_APPS, MKC_formac_ROption);
1755
1756 AssignOneMacKey(VK_LWIN, MKC_formac_Option);
1757
1758 AssignOneMacKey(VK_RWIN, MKC_formac_ROption);
1759
1760 AssignOneMacKey(VK_CONTROL, MKC_formac_Control);
1761
1762 AssignOneMacKey(VK_LCONTROL, MKC_formac_Control);
1763
1764 AssignOneMacKey(VK_RCONTROL, MKC_formac_RControl);
1765
1766 AssignOneMacKey(VK_F1, MKC_formac_F1);
1767 AssignOneMacKey(VK_F2, MKC_formac_F2);
1768 AssignOneMacKey(VK_F3, MKC_formac_F3);
1769 AssignOneMacKey(VK_F4, MKC_formac_F4);
1770 AssignOneMacKey(VK_F5, MKC_formac_F5);
1771 AssignOneMacKey(VK_F6, MKC_F6);
1772 AssignOneMacKey(VK_F7, MKC_F7);
1773 AssignOneMacKey(VK_F8, MKC_F8);
1774 AssignOneMacKey(VK_F9, MKC_F9);
1775 AssignOneMacKey(VK_F10, MKC_F10);
1776 AssignOneMacKey(VK_F11, MKC_F11);
1777 AssignOneMacKey(VK_F12, MKC_F12);
1778
1779 AssignOneMacKey(VK_DECIMAL, MKC_Decimal);
1780 AssignOneMacKey(VK_DELETE, MKC_Decimal);
1781 /* AssignOneMacKey(VK_RIGHT, 0x42); */
1782 AssignOneMacKey(VK_MULTIPLY, MKC_KPMultiply);
1783 AssignOneMacKey(VK_ADD, MKC_KPAdd);
1784 /* AssignOneMacKey(VK_LEFT, 0x46); */
1785 AssignOneMacKey(VK_NUMLOCK, MKC_Clear);
1786
1787 /* AssignOneMacKey(VK_DOWN, 0x48); */
1788 AssignOneMacKey(VK_DIVIDE, MKC_KPDevide);
1789 /* AssignOneMacKey(VK_RETURN, MKC_formac_Enter); */
1790 /* AssignOneMacKey(VK_UP, 0x4D); */
1791 AssignOneMacKey(VK_DIVIDE, MKC_KPDevide);
1792 AssignOneMacKey(VK_SUBTRACT, MKC_KPSubtract);
1793
1794 AssignOneMacKey(VK_SEPARATOR, MKC_KPEqual);
1795 AssignOneMacKey(VK_NUMPAD0, MKC_KP0);
1796 AssignOneMacKey(VK_NUMPAD1, MKC_KP1);
1797 AssignOneMacKey(VK_NUMPAD2, MKC_KP2);
1798 AssignOneMacKey(VK_NUMPAD3, MKC_KP3);
1799 AssignOneMacKey(VK_NUMPAD4, MKC_KP4);
1800 AssignOneMacKey(VK_NUMPAD5, MKC_KP5);
1801
1802 AssignOneMacKey(VK_NUMPAD6, MKC_KP6);
1803 AssignOneMacKey(VK_NUMPAD7, MKC_KP7);
1804 AssignOneMacKey(VK_NUMPAD8, MKC_KP8);
1805 AssignOneMacKey(VK_NUMPAD9, MKC_KP9);
1806
1807 AssignOneMacKey(VK_LEFT, MKC_Left);
1808 AssignOneMacKey(VK_RIGHT, MKC_Right);
1809 AssignOneMacKey(VK_DOWN, MKC_Down);
1810 AssignOneMacKey(VK_UP, MKC_Up);
1811
1812 AssignOneMacKey(myVK_PRIOR, MKC_formac_PageUp);
1813 AssignOneMacKey(myVK_NEXT, MKC_formac_PageDown);
1814 AssignOneMacKey(myVK_END, MKC_formac_End);
1815 AssignOneMacKey(myVK_HOME, MKC_formac_Home);
1816 AssignOneMacKey(myVK_INSERT, MKC_formac_Help);
1817 AssignOneMacKey(myVK_DELETE, MKC_formac_ForwardDel);
1818 AssignOneMacKey(myVK_HELP, MKC_formac_Help);
1819 AssignOneMacKey(myVK_SNAPSHOT, MKC_Print);
1820 AssignOneMacKey(myVK_SCROLL, MKC_ScrollLock);
1821 AssignOneMacKey(myVK_PAUSE, MKC_Pause);
1822
1823 AssignOneMacKey(myVK_OEM_102, MKC_AngleBracket);
1824
1825 InitKeyCodes();
1826
1827#if ItnlKyBdFix
1828 MyInitCheckKeyboardLayout();
1829#endif
1830
1831 return trueblnr;
1832}
1833
1834LOCALPROC DoKeyCode(int i, blnr down)
1835{
1836 ui3r key = WinKey2Mac[
1837#if ItnlKyBdFix
1838 MyVkMapA[i]
1839#else
1840 i
1841#endif
1842 ];
1843 if (MKC_None != key) {
1844 Keyboard_UpdateKeyMap2(key, down);
1845 }
1846}
1847
1848#ifndef EnableGrabSpecialKeys
1849#if UseWinCE
1850#define EnableGrabSpecialKeys 0
1851#else
1852#define EnableGrabSpecialKeys (MayFullScreen && GrabKeysFullScreen)
1853#endif
1854#endif /* EnableGrabSpecialKeys */
1855
1856#if EnableGrabSpecialKeys
1857LOCALVAR blnr HaveSetSysParam = falseblnr;
1858#endif
1859
1860LOCALPROC CheckTheCapsLock(void)
1861{
1862 DoKeyCode(VK_CAPITAL, (GetKeyState(VK_CAPITAL) & 1) != 0);
1863}
1864
1865#if EnableGrabSpecialKeys
1866LOCALVAR blnr VK_LWIN_pressed = falseblnr;
1867LOCALVAR blnr VK_RWIN_pressed = falseblnr;
1868#endif
1869
1870#if EnableGrabSpecialKeys
1871LOCALPROC CheckForLostKeyUps(void)
1872{
1873 if (HaveSetSysParam) {
1874 /* check for lost key ups */
1875 if (VK_LWIN_pressed) {
1876 if ((GetAsyncKeyState(VK_LWIN) & 0x8000) == 0) {
1877 DoKeyCode(VK_LWIN, falseblnr);
1878 VK_LWIN_pressed = falseblnr;
1879 }
1880 }
1881 if (VK_RWIN_pressed) {
1882 if ((GetAsyncKeyState(VK_RWIN) & 0x8000) == 0) {
1883 DoKeyCode(VK_RWIN, falseblnr);
1884 VK_RWIN_pressed = falseblnr;
1885 }
1886 }
1887 }
1888}
1889#endif
1890
1891LOCALPROC DoVKcode0(int i, blnr down)
1892{
1893#if EnableGrabSpecialKeys
1894 if (HaveSetSysParam) {
1895 /* will need to check for lost key ups */
1896 if (VK_LWIN == i) {
1897 VK_LWIN_pressed = down;
1898 } else if (VK_RWIN == i) {
1899 VK_RWIN_pressed = down;
1900 }
1901 }
1902#endif
1903 DoKeyCode(i, down);
1904}
1905
1906LOCALPROC DoVKcode(int i, ui3r flags, blnr down)
1907{
1908 switch (i) {
1909#if MKC_formac_Control != MKC_formac_RControl
1910 case VK_CONTROL:
1911 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1912 ? MKC_formac_RControl : MKC_formac_Control,
1913 down);
1914 break;
1915#endif
1916#if MKC_formac_RCommand != MKC_formac_Command
1917 case VK_MENU:
1918 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1919 ? MKC_formac_RCommand : MKC_formac_Command,
1920 down);
1921 break;
1922#endif
1923 case VK_RETURN:
1924 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1925 ? MKC_formac_Enter : MKC_Return,
1926 down);
1927 break;
1928 case myVK_HOME:
1929 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1930 ? MKC_formac_Home : MKC_KP7,
1931 down);
1932 break;
1933 case VK_UP:
1934 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1935 ? MKC_Up : MKC_KP8,
1936 down);
1937 break;
1938 case myVK_PRIOR:
1939 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1940 ? MKC_formac_PageUp : MKC_KP9,
1941 down);
1942 break;
1943 case VK_LEFT:
1944 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1945 ? MKC_Left : MKC_KP4,
1946 down);
1947 break;
1948 case myVK_CLEAR:
1949 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1950 ? MKC_Clear : MKC_KP5,
1951 down);
1952 break;
1953 case VK_RIGHT:
1954 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1955 ? MKC_Right : MKC_KP6,
1956 down);
1957 break;
1958 case myVK_END:
1959 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1960 ? MKC_formac_End : MKC_KP1,
1961 down);
1962 break;
1963 case VK_DOWN:
1964 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1965 ? MKC_Down : MKC_KP2,
1966 down);
1967 break;
1968 case myVK_NEXT:
1969 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1970 ? MKC_formac_PageDown : MKC_KP3,
1971 down);
1972 break;
1973 case myVK_INSERT:
1974 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1975 ? MKC_formac_Help : MKC_KP0,
1976 down);
1977 break;
1978 case myVK_DELETE:
1979 Keyboard_UpdateKeyMap2(TestBit(flags, 0)
1980 ? MKC_formac_ForwardDel : MKC_Decimal,
1981 down);
1982 break;
1983 case VK_CAPITAL:
1984 CheckTheCapsLock();
1985 break;
1986 default:
1987 if ((i >= 0) && (i < 256)) {
1988 DoVKcode0(i, down);
1989 }
1990 break;
1991 }
1992}
1993
1994LOCALVAR blnr WantCmdOptOnReconnect = falseblnr;
1995
1996LOCALPROC ReconnectKeyCodes3(void)
1997{
1998 int i;
1999
2000 CheckTheCapsLock();
2001
2002 if (WantCmdOptOnReconnect) {
2003 WantCmdOptOnReconnect = falseblnr;
2004
2005 for (i = 0; i < 256; ++i) {
2006 if ((GetKeyState(i) & 0x8000) != 0) {
2007 if ((VK_CAPITAL != i)
2008 && (VK_RETURN != i))
2009 {
2010 DoVKcode0(i, trueblnr);
2011 }
2012 }
2013 }
2014 }
2015}
2016
2017LOCALPROC DisconnectKeyCodes3(void)
2018{
2019 DisconnectKeyCodes2();
2020 SetCurMouseButton(falseblnr);
2021}
2022
2023#if EnableGrabSpecialKeys
2024static HHOOK hKeyHook = NULL;
2025#endif
2026
2027#if EnableGrabSpecialKeys
2028typedef struct {
2029 DWORD vkCode;
2030 DWORD scanCode;
2031 DWORD flags;
2032 DWORD time;
2033 DWORD dwExtraInfo;
2034} My_KBDLLHOOKSTRUCT;
2035#endif
2036
2037#if EnableGrabSpecialKeys
2038LRESULT CALLBACK LowLevelKeyboardProc(
2039 int nCode, /* hook code */
2040 WPARAM wParam, /* message identifier */
2041 LPARAM lParam /* pointer to structure with message data */
2042);
2043#endif
2044
2045#if EnableGrabSpecialKeys
2046LRESULT CALLBACK LowLevelKeyboardProc(
2047 int nCode, /* hook code */
2048 WPARAM wParam, /* message identifier */
2049 LPARAM lParam /* pointer to structure with message data */
2050)
2051{
2052 if (nCode == HC_ACTION) {
2053 My_KBDLLHOOKSTRUCT *p = (My_KBDLLHOOKSTRUCT *)lParam;
2054 if (p->vkCode != VK_CAPITAL) {
2055 switch (wParam) {
2056 case WM_KEYDOWN:
2057 case WM_SYSKEYDOWN:
2058 DoVKcode(p->vkCode, p->flags, trueblnr);
2059 return 1;
2060 break;
2061 case WM_KEYUP:
2062 case WM_SYSKEYUP:
2063 DoVKcode(p->vkCode, p->flags, falseblnr);
2064 return 1;
2065 break;
2066 }
2067 }
2068 }
2069 return CallNextHookEx(hKeyHook, /* handle to current hook */
2070 nCode, /* hook code passed to hook procedure */
2071 wParam, /* value passed to hook procedure */
2072 lParam /* value passed to hook procedure */
2073 );
2074
2075}
2076#endif
2077
2078#if EnableGrabSpecialKeys
2079#define My_WH_KEYBOARD_LL 13
2080#define My_SPI_SETSCREENSAVERRUNNING 0x0061
2081#endif
2082
2083#if EnableGrabSpecialKeys
2084LOCALVAR UINT nPreviousState;
2085#endif
2086
2087#if EnableGrabSpecialKeys
2088LOCALPROC GrabSpecialKeys(void)
2089{
2090 if ((hKeyHook == NULL) && ! HaveSetSysParam) {
2091 /* this works on Windows XP */
2092 hKeyHook = SetWindowsHookEx(
2093 My_WH_KEYBOARD_LL, /* type of hook to install */
2094 (HOOKPROC)LowLevelKeyboardProc,
2095 /* address of hook procedure */
2096 AppInstance, /* handle to application instance */
2097 0 /* identity of thread to install hook for */
2098 );
2099 if (hKeyHook == NULL) {
2100 /* this works on Windows 95/98 */
2101 SystemParametersInfo(My_SPI_SETSCREENSAVERRUNNING, TRUE,
2102 &nPreviousState, 0);
2103 HaveSetSysParam = trueblnr;
2104 }
2105 }
2106}
2107#endif
2108
2109#if EnableGrabSpecialKeys
2110LOCALPROC UnGrabSpecialKeys(void)
2111{
2112 if (hKeyHook != NULL) {
2113 (void) UnhookWindowsHookEx(hKeyHook);
2114 hKeyHook = NULL;
2115 }
2116 if (HaveSetSysParam) {
2117 SystemParametersInfo(My_SPI_SETSCREENSAVERRUNNING, FALSE,
2118 &nPreviousState, 0);
2119 HaveSetSysParam = falseblnr;
2120 }
2121}
2122#endif
2123
2124/* --- priority --- */
2125
2126#ifndef EnableChangePriority
2127#if UseWinCE
2128#define EnableChangePriority 0
2129#else
2130#define EnableChangePriority MayFullScreen
2131#endif
2132#endif /* EnableChangePriority */
2133
2134#if EnableChangePriority
2135LOCALVAR blnr MyPriorityRaised = falseblnr;
2136#endif
2137
2138#if EnableChangePriority
2139LOCALPROC RaiseMyPriority(void)
2140{
2141 if (! MyPriorityRaised) {
2142 if (! SetPriorityClass(
2143 GetCurrentProcess(), /* handle to the process */
2144 HIGH_PRIORITY_CLASS
2145 /* REALTIME_PRIORITY_CLASS (not, killer) */
2146 /* priority class value */
2147 ))
2148 {
2149 /*
2150 not recursive:
2151 MacMsg("SetPriorityClass failed",
2152 "Sorry, Mini vMac encountered errors"
2153 " and cannot continue.", trueblnr);
2154 */
2155 }
2156 MyPriorityRaised = trueblnr;
2157 }
2158}
2159#endif
2160
2161#if EnableChangePriority
2162LOCALPROC LowerMyPriority(void)
2163{
2164 if (MyPriorityRaised) {
2165 if (! SetPriorityClass(
2166 GetCurrentProcess(), /* handle to the process */
2167 NORMAL_PRIORITY_CLASS /* priority class value */
2168 ))
2169 {
2170 /*
2171 not recursive:
2172 MacMsg("SetPriorityClass failed",
2173 "Sorry, Mini vMac encountered errors"
2174 " and cannot continue.", trueblnr);
2175 */
2176 }
2177 MyPriorityRaised = falseblnr;
2178 }
2179}
2180#endif
2181
2182
2183/* --- time, date, location --- */
2184
2185#define dbglog_TimeStuff (0 && dbglog_HAVE)
2186
2187LOCALVAR ui5b TrueEmulatedTime = 0;
2188
2189#define MyInvTimeDivPow 16
2190#define MyInvTimeDiv (1 << MyInvTimeDivPow)
2191#define MyInvTimeDivMask (MyInvTimeDiv - 1)
2192#define MyInvTimeStep 1089590 /* 1000 / 60.14742 * MyInvTimeDiv */
2193
2194LOCALVAR DWORD LastTime;
2195
2196LOCALVAR DWORD NextIntTime;
2197LOCALVAR ui5b NextFracTime;
2198
2199LOCALPROC IncrNextTime(void)
2200{
2201 NextFracTime += MyInvTimeStep;
2202 NextIntTime += (NextFracTime >> MyInvTimeDivPow);
2203 NextFracTime &= MyInvTimeDivMask;
2204}
2205
2206LOCALPROC InitNextTime(void)
2207{
2208 NextIntTime = LastTime;
2209 NextFracTime = 0;
2210 IncrNextTime();
2211}
2212
2213LOCALFUNC blnr UpdateTrueEmulatedTime(void)
2214{
2215 DWORD LatestTime;
2216 si5b TimeDiff;
2217
2218 LatestTime = timeGetTime();
2219 if (LatestTime != LastTime) {
2220 LastTime = LatestTime;
2221 TimeDiff = (LatestTime - NextIntTime);
2222 /* this should work even when time wraps */
2223 if (TimeDiff >= 0) {
2224 if (TimeDiff > 256) {
2225 /* emulation interrupted, forget it */
2226 ++TrueEmulatedTime;
2227 InitNextTime();
2228
2229#if dbglog_TimeStuff
2230 dbglog_writelnNum("emulation interrupted",
2231 TrueEmulatedTime);
2232#endif
2233 } else {
2234 do {
2235 ++TrueEmulatedTime;
2236 IncrNextTime();
2237 TimeDiff = (LatestTime - NextIntTime);
2238 } while (TimeDiff >= 0);
2239 }
2240 return trueblnr;
2241 } else if (TimeDiff < -256) {
2242 /* clock goofed if ever get here, reset */
2243#if dbglog_TimeStuff
2244 dbglog_writeln("clock set back");
2245#endif
2246
2247 InitNextTime();
2248 }
2249 }
2250 return falseblnr;
2251}
2252
2253LOCALVAR ui5b TimeSecBase;
2254LOCALVAR DWORD TimeMilliBase;
2255
2256#include "DATE2SEC.h"
2257
2258LOCALFUNC blnr CheckDateTime(void)
2259{
2260 ui5b NewMacDateInSecond;
2261
2262 NewMacDateInSecond =
2263 ((ui5b)(LastTime - TimeMilliBase)) / 1000 + TimeSecBase;
2264 if (CurMacDateInSeconds != NewMacDateInSecond) {
2265 CurMacDateInSeconds = NewMacDateInSecond;
2266
2267 return trueblnr;
2268 } else {
2269 return falseblnr;
2270 }
2271}
2272
2273LOCALFUNC blnr Init60thCheck(void)
2274{
2275 SYSTEMTIME s;
2276#if AutoTimeZone
2277 TIME_ZONE_INFORMATION r;
2278 DWORD v;
2279#endif
2280 DWORD t;
2281
2282 GetLocalTime(&s);
2283 t = timeGetTime();
2284 TimeSecBase = Date2MacSeconds(s.wSecond, s.wMinute, s.wHour,
2285 s.wDay, s.wMonth, s.wYear);
2286 TimeMilliBase = t - s.wMilliseconds;
2287
2288#if AutoTimeZone
2289 v = GetTimeZoneInformation(&r);
2290 if ((v != 0xFFFFFFFF) && (v != TIME_ZONE_ID_UNKNOWN)) {
2291 si5b dlsBias = (v != TIME_ZONE_ID_DAYLIGHT)
2292 ? r.StandardBias : r.DaylightBias;
2293 CurMacDelta = (((ui5b)(- (r.Bias + dlsBias) * 60))
2294 & 0x00FFFFFF)
2295 | (((v != TIME_ZONE_ID_DAYLIGHT) ? 0 : 0x80)
2296 << 24);
2297 }
2298#endif
2299
2300 LastTime = timeGetTime();
2301 InitNextTime();
2302
2303 OnTrueTime = TrueEmulatedTime;
2304
2305 (void) CheckDateTime();
2306
2307 return trueblnr;
2308}
2309
2310#ifndef MyTimeResolution
2311#define MyTimeResolution 3
2312#endif
2313 /*
2314 Setting MyTimeResolution to 1 seems to drastically slow down
2315 the clock in Virtual PC 7.0.2 for Mac. Using 3 is more polite
2316 anyway, and should not cause much observable difference.
2317 */
2318
2319#if (MyTimeResolution != 0)
2320LOCALVAR blnr HaveSetTimeResolution = falseblnr;
2321#endif
2322
2323#if (MyTimeResolution != 0)
2324LOCALPROC MyTimer_Suspend(void)
2325{
2326 if (HaveSetTimeResolution) {
2327 (void) timeEndPeriod(MyTimeResolution);
2328 HaveSetTimeResolution = falseblnr;
2329 }
2330}
2331#endif
2332
2333#if (MyTimeResolution != 0)
2334LOCALPROC MyTimer_Resume(void)
2335{
2336 TIMECAPS tc;
2337
2338 if (timeGetDevCaps(&tc, sizeof(TIMECAPS))
2339 == TIMERR_NOERROR)
2340 {
2341 if ((MyTimeResolution >= tc.wPeriodMin)
2342 && (MyTimeResolution <= tc.wPeriodMax))
2343 {
2344 if (timeBeginPeriod(MyTimeResolution)
2345 == TIMERR_NOERROR)
2346 {
2347 HaveSetTimeResolution = trueblnr;
2348 }
2349 }
2350 }
2351}
2352#endif
2353
2354/* --- sound --- */
2355
2356#if MySoundEnabled
2357
2358
2359#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
2360#define kSoundBuffers (1 << kLn2SoundBuffers)
2361#define kSoundBuffMask (kSoundBuffers - 1)
2362
2363#define DesiredMinFilledSoundBuffs 3
2364 /*
2365 if too big then sound lags behind emulation.
2366 if too small then sound will have pauses.
2367 */
2368
2369#define kLnOneBuffLen 9
2370#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
2371#define kOneBuffLen (1UL << kLnOneBuffLen)
2372#define kAllBuffLen (1UL << kLnAllBuffLen)
2373#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
2374#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
2375#define kOneBuffSz (1UL << kLnOneBuffSz)
2376#define kAllBuffSz (1UL << kLnAllBuffSz)
2377#define kOneBuffMask (kOneBuffLen - 1)
2378#define kAllBuffMask (kAllBuffLen - 1)
2379#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
2380
2381#define dbglog_SoundStuff (0 && dbglog_HAVE)
2382#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
2383
2384LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
2385LOCALVAR ui4b ThePlayOffset;
2386LOCALVAR ui4b TheFillOffset;
2387LOCALVAR blnr wantplaying;
2388LOCALVAR ui4b MinFilledSoundBuffs;
2389LOCALVAR ui4b TheWriteOffset;
2390
2391#define SOUND_SAMPLERATE /* 22050 */ 22255
2392 /* = round(7833600 * 2 / 704) */
2393
2394
2395LOCALPROC FillWithSilence(tpSoundSamp p, int n, trSoundSamp v)
2396{
2397 int i;
2398
2399 for (i = n; --i >= 0; ) {
2400 *p++ = v;
2401 }
2402}
2403
2404
2405LOCALVAR HWAVEOUT hWaveOut = NULL;
2406LOCALVAR WAVEHDR whdr[kSoundBuffers];
2407
2408
2409LOCALPROC MySound_BeginPlaying(void)
2410{
2411#if dbglog_SoundStuff
2412 fprintf(stderr, "MySound_BeginPlaying\n");
2413#endif
2414}
2415
2416LOCALPROC MySound_Start(void)
2417{
2418 if (hWaveOut == NULL) {
2419 WAVEFORMATEX wfex;
2420 MMRESULT mmr;
2421 int i;
2422 tpSoundSamp p;
2423 WAVEHDR *pwh;
2424
2425 wfex.wFormatTag = WAVE_FORMAT_PCM;
2426 wfex.nChannels = 1;
2427 wfex.nSamplesPerSec = SOUND_SAMPLERATE;
2428 wfex.nAvgBytesPerSec = SOUND_SAMPLERATE;
2429#if 3 == kLn2SoundSampSz
2430 wfex.nBlockAlign = 1;
2431 wfex.wBitsPerSample = 8;
2432#elif 4 == kLn2SoundSampSz
2433 wfex.nBlockAlign = 2;
2434 wfex.wBitsPerSample = 16;
2435#else
2436#error "unsupported audio format"
2437#endif
2438 wfex.cbSize = 0;
2439 mmr = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfex, 0,
2440 0 /* (DWORD) AppInstance */, CALLBACK_NULL);
2441 if (mmr != MMSYSERR_NOERROR) {
2442 /*
2443 not recursive:
2444 MacMsg("waveOutOpen failed",
2445 "Sorry, Mini vMac encountered errors"
2446 " and cannot continue.", trueblnr);
2447 */
2448 } else {
2449 p = TheSoundBuffer;
2450 pwh = whdr;
2451 for (i = 0; i < kSoundBuffers; ++i) {
2452 pwh->lpData = (LPSTR)p;
2453 pwh->dwBufferLength = kOneBuffSz;
2454 pwh->dwBytesRecorded = 0;
2455 pwh->dwUser = 0;
2456 pwh->dwFlags = 0;
2457 pwh->dwLoops = 0;
2458 mmr = waveOutPrepareHeader(hWaveOut, pwh,
2459 sizeof(WAVEHDR));
2460 if (mmr != MMSYSERR_NOERROR) {
2461 /*
2462 not recursive:
2463 MacMsg("waveOutPrepareHeader failed",
2464 "Sorry, Mini vMac encountered errors"
2465 " and cannot continue.", trueblnr);
2466 */
2467 } else {
2468 pwh->dwFlags |= WHDR_DONE;
2469 }
2470 p += kOneBuffLen;
2471 ++pwh;
2472 }
2473
2474 TheFillOffset = 0;
2475 ThePlayOffset = 0;
2476 TheWriteOffset = 0;
2477 MinFilledSoundBuffs = kSoundBuffers;
2478 wantplaying = falseblnr;
2479 }
2480 }
2481}
2482
2483LOCALPROC MySound_Stop(void)
2484{
2485 MMRESULT mmr;
2486 int i;
2487
2488 wantplaying = falseblnr;
2489 if (hWaveOut != NULL) {
2490 DWORD StartTime = GetTickCount();
2491 for (i = 0; i < kSoundBuffers; ++i) {
2492 while (((whdr[i].dwFlags & WHDR_DONE) == 0)
2493 && ((ui5b)(GetTickCount() - StartTime) < 1000))
2494 {
2495 Sleep(1);
2496 }
2497
2498 mmr = waveOutUnprepareHeader(hWaveOut, &whdr[i],
2499 sizeof(WAVEHDR));
2500 if (mmr != MMSYSERR_NOERROR) {
2501 /*
2502 not recursive:
2503 MacMsg("waveOutUnprepareHeader failed",
2504 "Sorry, Mini vMac encountered errors"
2505 " and cannot continue.", trueblnr);
2506 */
2507 }
2508 }
2509
2510 mmr = waveOutClose(hWaveOut);
2511 if (mmr != MMSYSERR_NOERROR) {
2512 /*
2513 MacMsg("waveOutClose failed",
2514 "Sorry, Mini vMac encountered errors"
2515 " and cannot continue.", trueblnr);
2516 */
2517 }
2518 hWaveOut = NULL;
2519 }
2520}
2521
2522LOCALPROC SoundCheckVeryOften(void)
2523{
2524 if ((hWaveOut != NULL) && (wantplaying)) {
2525label_retry:
2526 {
2527 ui4b FilledSoundBuffs;
2528 ui4b ToPlaySize = TheFillOffset - ThePlayOffset;
2529 ui4b CurPlayBuffer =
2530 (ThePlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
2531
2532 if ((ToPlaySize > kOneBuffLen)
2533 && ((whdr[CurPlayBuffer].dwFlags & WHDR_DONE) != 0))
2534 {
2535 ThePlayOffset += kOneBuffLen;
2536 goto label_retry;
2537 }
2538 FilledSoundBuffs = ToPlaySize >> kLnOneBuffLen;
2539
2540 if (FilledSoundBuffs < MinFilledSoundBuffs) {
2541 MinFilledSoundBuffs = FilledSoundBuffs;
2542 }
2543
2544 if (FilledSoundBuffs < 2) {
2545 MMRESULT mmr;
2546 ui4b PrevPlayOffset = ThePlayOffset - kOneBuffLen;
2547 ui4b PrevPlayBuffer =
2548 (PrevPlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
2549 ui4b LastPlayedOffset =
2550 ((TheFillOffset >> kLnOneBuffLen) << kLnOneBuffLen)
2551 - 1;
2552
2553 FillWithSilence(
2554 TheSoundBuffer + (PrevPlayOffset & kAllBuffMask),
2555 kOneBuffLen,
2556 *(TheSoundBuffer
2557 + (LastPlayedOffset & kAllBuffMask)));
2558 mmr = waveOutWrite(
2559 hWaveOut, &whdr[PrevPlayBuffer], sizeof(WAVEHDR));
2560 if (mmr != MMSYSERR_NOERROR) {
2561 whdr[PrevPlayBuffer].dwFlags |= WHDR_DONE;
2562 /*
2563 not recursive:
2564 MacMsg("waveOutWrite failed",
2565 "Sorry, Mini vMac encountered errors"
2566 " and cannot continue.", trueblnr);
2567 */
2568 }
2569 ThePlayOffset = PrevPlayOffset;
2570 goto label_retry;
2571 }
2572 }
2573 }
2574}
2575
2576#if 4 == kLn2SoundSampSz
2577LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
2578{
2579 int i;
2580
2581 for (i = kOneBuffLen; --i >= 0; ) {
2582 *p++ -= 0x8000;
2583 }
2584}
2585#else
2586#define ConvertSoundBlockToNative(p)
2587#endif
2588
2589LOCALPROC MySound_FilledBlocks(void)
2590{
2591 while (0 != ((TheWriteOffset - TheFillOffset) >> kLnOneBuffLen)) {
2592 ui4b CurFillBuffer =
2593 (TheFillOffset >> kLnOneBuffLen) & kSoundBuffMask;
2594 blnr IsOk = falseblnr;
2595
2596 ConvertSoundBlockToNative((tpSoundSamp)
2597 whdr[CurFillBuffer].lpData);
2598
2599 if (hWaveOut != NULL) {
2600 MMRESULT mmr = waveOutWrite(hWaveOut,
2601 &whdr[CurFillBuffer], sizeof(WAVEHDR));
2602 if (mmr == MMSYSERR_NOERROR) {
2603 IsOk = trueblnr;
2604 }
2605 }
2606
2607 if (! IsOk) {
2608 /*
2609 not recursive:
2610 MacMsg("waveOutWrite failed",
2611 "Sorry, Mini vMac encountered errors"
2612 " and cannot continue.", trueblnr);
2613 */
2614 whdr[CurFillBuffer].dwFlags |= WHDR_DONE;
2615 }
2616
2617 TheFillOffset += kOneBuffLen;
2618 }
2619}
2620
2621LOCALPROC MySound_WroteABlock(void)
2622{
2623 if (wantplaying) {
2624 MySound_FilledBlocks();
2625 } else if (((TheWriteOffset - ThePlayOffset) >> kLnOneBuffLen) < 12)
2626 {
2627 /* just wait */
2628 } else {
2629 MySound_FilledBlocks();
2630 wantplaying = trueblnr;
2631 MySound_BeginPlaying();
2632 }
2633}
2634
2635GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
2636{
2637 TheWriteOffset += actL;
2638
2639 if (0 == (TheWriteOffset & kOneBuffMask)) {
2640 /* just finished a block */
2641
2642 MySound_WroteABlock();
2643 }
2644}
2645
2646GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
2647{
2648 ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
2649 ui4b WriteBuffContig =
2650 kOneBuffLen - (TheWriteOffset & kOneBuffMask);
2651
2652 if (WriteBuffContig < n) {
2653 n = WriteBuffContig;
2654 }
2655 if (ToFillLen < n) {
2656 /* overwrite previous buffer */
2657 TheWriteOffset -= kOneBuffLen;
2658 }
2659
2660 *actL = n;
2661 return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
2662}
2663
2664LOCALPROC MySound_SecondNotify(void)
2665{
2666 if (hWaveOut != NULL) {
2667 if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
2668#if dbglog_SoundStuff
2669 dbglog_writeln("MinFilledSoundBuffs too high");
2670#endif
2671 IncrNextTime();
2672 } else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
2673#if dbglog_SoundStuff
2674 dbglog_writeln("MinFilledSoundBuffs too low");
2675#endif
2676 ++TrueEmulatedTime;
2677 }
2678 MinFilledSoundBuffs = kSoundBuffers;
2679 }
2680}
2681
2682#endif
2683
2684/* --- overall grab --- */
2685
2686#if MayFullScreen
2687LOCALPROC GrabTheMachine(void)
2688{
2689#if EnableFSMouseMotion
2690 StartSaveMouseMotion();
2691#endif
2692#if EnableChangePriority
2693 if ((ui3b) -1 == SpeedValue) {
2694 RaiseMyPriority();
2695 }
2696#endif
2697#if EnableGrabSpecialKeys
2698 GrabSpecialKeys();
2699#endif
2700}
2701#endif
2702
2703#if MayFullScreen
2704LOCALPROC UnGrabTheMachine(void)
2705{
2706#if EnableGrabSpecialKeys
2707 UnGrabSpecialKeys();
2708#endif
2709#if EnableFSMouseMotion
2710 StopSaveMouseMotion();
2711#endif
2712#if EnableChangePriority
2713 LowerMyPriority();
2714#endif
2715}
2716#endif
2717
2718#if MayFullScreen
2719LOCALVAR blnr GrabMachine = falseblnr;
2720#endif
2721
2722#if MayFullScreen
2723LOCALPROC AdjustMachineGrab(void)
2724{
2725 if (GrabMachine) {
2726 if (MainWnd != NULL) {
2727 GrabTheMachine();
2728 }
2729 } else {
2730 UnGrabTheMachine();
2731 }
2732}
2733#endif
2734
2735/* --- basic dialogs --- */
2736
2737LOCALPROC MyBeginDialog(void)
2738{
2739 DisconnectKeyCodes3();
2740#if MayFullScreen
2741 GrabMachine = falseblnr;
2742 UnGrabTheMachine();
2743#endif
2744 ForceShowCursor();
2745}
2746
2747LOCALPROC MyEndDialog(void)
2748{
2749 ReconnectKeyCodes3();
2750}
2751
2752LOCALPROC CheckSavedMacMsg(void)
2753{
2754 if (nullpr != SavedBriefMsg) {
2755 TCHAR briefMsg0[ClStrMaxLength + 1];
2756 TCHAR longMsg0[ClStrMaxLength + 1];
2757
2758 NativeStrFromCStr(briefMsg0, SavedBriefMsg, falseblnr);
2759 NativeStrFromCStr(longMsg0, SavedLongMsg, falseblnr);
2760
2761 MessageBox(MainWnd, longMsg0, briefMsg0,
2762 MB_APPLMODAL | MB_OK | (SavedFatalMsg ? MB_ICONSTOP : 0));
2763
2764 SavedBriefMsg = nullpr;
2765 }
2766}
2767
2768/* --- main window --- */
2769
2770enum {
2771 ID_MENU_NULL = 256,
2772 ID_FILE_INSERTDISK1,
2773 ID_FILE_QUIT,
2774 ID_SPECIAL_MORECOMMANDS,
2775 ID_HELP_ABOUT,
2776
2777 kNum_ID_MENU
2778};
2779
2780
2781#if (1 == vMacScreenDepth) || (vMacScreenDepth >= 4)
2782#define EnableScalingBuff 1
2783#else
2784#define EnableScalingBuff (1 && EnableMagnify && (MyWindowScale == 2))
2785#endif
2786
2787#if EnableScalingBuff
2788LOCALVAR ui3p ScalingBuff = NULL;
2789#endif
2790
2791LOCALVAR HDC MainWndDC = NULL;
2792
2793LOCALVAR si5b CmdShow;
2794
2795LOCALVAR TCHAR WndTitle[_MAX_PATH];
2796LOCALVAR const TCHAR WndClassName[] = TEXT("minivmac");
2797
2798LOCALVAR blnr gBackgroundFlag = falseblnr;
2799LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
2800LOCALVAR blnr CurSpeedStopped = trueblnr;
2801
2802LOCALPROC GetWndTitle(void)
2803{
2804 TCHAR pathName[_MAX_PATH];
2805 WIN32_FIND_DATA fd;
2806 blnr IsOk = falseblnr;
2807
2808 if (GetModuleFileName(AppInstance, pathName, _MAX_PATH) != 0) {
2809 HANDLE hf = FindFirstFile(pathName, &fd);
2810
2811 if (hf != INVALID_HANDLE_VALUE) {
2812 /* get rid of extension, presumably '.exe' */
2813 LPTSTR p = FindLastTerm(fd.cFileName,
2814 (TCHAR)('.'));
2815 if (p != nullpr) {
2816 *--p = (TCHAR)('\0');
2817 }
2818
2819 _tcscpy(WndTitle, fd.cFileName);
2820 IsOk = trueblnr;
2821 FindClose(hf);
2822 }
2823 }
2824 if (! IsOk) {
2825 _tcscpy(WndTitle, TEXT(kStrAppName));
2826 }
2827}
2828
2829LOCALPROC DisposeMainWindow(void)
2830{
2831#if UseWinCE
2832 /* Show the taskbar */
2833 SHFullScreen(MainWnd, SHFS_SHOWTASKBAR);
2834#endif
2835
2836 if (MainWndDC != NULL) {
2837 ReleaseDC(MainWnd, MainWndDC);
2838 }
2839 if (MainWnd != NULL) {
2840 DestroyWindow(MainWnd);
2841 MainWnd = NULL; /* so MacMsg will still work */
2842 }
2843}
2844
2845enum {
2846 kMagStateNormal,
2847#if EnableMagnify
2848 kMagStateMagnifgy,
2849#endif
2850 kNumMagStates
2851};
2852
2853#define kMagStateAuto kNumMagStates
2854
2855#if MayNotFullScreen
2856LOCALVAR int CurWinIndx;
2857LOCALVAR blnr HavePositionWins[kNumMagStates];
2858LOCALVAR POINT WinPositionWins[kNumMagStates];
2859#endif
2860
2861#if MayNotFullScreen
2862LOCALPROC MyAppendConvertMenuItem(HMENU hMenu,
2863 UINT uIDNewItem, char *s, blnr AddEllipsis)
2864{
2865 TCHAR ts[ClStrMaxLength + 1];
2866
2867 NativeStrFromCStr(ts, s, AddEllipsis);
2868
2869 (void) AppendMenu(hMenu, MF_ENABLED + MF_STRING,
2870 uIDNewItem, ts);
2871}
2872#endif
2873
2874#if MayNotFullScreen
2875LOCALPROC MyAppendSubmenuConvertName(HMENU hMenu,
2876 HMENU hSubMenu, char *s)
2877{
2878 TCHAR ts[ClStrMaxLength + 1];
2879 MENUITEMINFO mii;
2880
2881 NativeStrFromCStr(ts, s, falseblnr);
2882
2883#if 0
2884 (void) InsertMenu(hMenu, 0xFFFFFFFF,
2885 MF_BYPOSITION + MF_POPUP + MF_STRING + MF_ENABLED,
2886 (UINT)hSubMenu, ts);
2887#endif
2888
2889 memset(&mii, 0, sizeof(MENUITEMINFO));
2890 mii.cbSize = sizeof(MENUITEMINFO);
2891 mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
2892 mii.fType = MFT_STRING;
2893 mii.hSubMenu = hSubMenu;
2894 mii.dwTypeData = ts;
2895 mii.cch = (UINT)_tcslen(ts);
2896 (void) InsertMenuItem(hMenu, (UINT) -1, TRUE,
2897 &mii);
2898}
2899#endif
2900
2901#ifndef kStrMenuFile_win
2902#define kStrMenuFile_win kStrMenuFile
2903#endif
2904
2905LOCALFUNC blnr ReCreateMainWindow(void)
2906{
2907#if MayNotFullScreen
2908 HMENU m;
2909 int DfltWndX;
2910 int DfltWndY;
2911 int WinIndx;
2912#endif
2913 HMENU mb;
2914 HWND NewMainWindow;
2915 HDC NewMainWndDC = NULL;
2916 int ScreenX = GetSystemMetrics(SM_CXSCREEN);
2917 int ScreenY = GetSystemMetrics(SM_CYSCREEN);
2918 short NewWindowHeight = vMacScreenHeight;
2919 short NewWindowWidth = vMacScreenWidth;
2920 HWND OldMainWindow = MainWnd;
2921 HDC OldMainWndDC = MainWndDC;
2922 RECT NewWinR;
2923 DWORD MyWStyle;
2924 DWORD MyWExStyle;
2925
2926#if VarFullScreen
2927 if (! UseFullScreen)
2928#endif
2929#if MayNotFullScreen
2930 {
2931 /* save old position */
2932 if (OldMainWindow != NULL) {
2933 WinPositionWins[CurWinIndx].x = WndX;
2934 WinPositionWins[CurWinIndx].y = WndY;
2935 }
2936 }
2937#endif
2938
2939#if MayNotFullScreen
2940#if EnableMagnify
2941 if (WantMagnify) {
2942 WinIndx = kMagStateMagnifgy;
2943 } else
2944#endif
2945 {
2946 WinIndx = kMagStateNormal;
2947 }
2948#endif
2949
2950#if EnableMagnify
2951 if (WantMagnify) {
2952 NewWindowHeight *= MyWindowScale;
2953 NewWindowWidth *= MyWindowScale;
2954 }
2955#endif
2956
2957#if VarFullScreen
2958 if (WantFullScreen)
2959#endif
2960#if MayFullScreen
2961 {
2962 MyWStyle = WS_VISIBLE | WS_POPUP;
2963 MyWExStyle = WS_EX_TOPMOST;
2964
2965 hOffset = (ScreenX - NewWindowWidth) / 2;
2966 vOffset = (ScreenY - NewWindowHeight) / 2;
2967 if (hOffset < 0) {
2968 hOffset = 0;
2969 }
2970 if (vOffset < 0) {
2971 vOffset = 0;
2972 }
2973
2974 NewWinR.left = 0;
2975 NewWinR.top = 0;
2976 NewWinR.right = ScreenX;
2977 NewWinR.bottom = ScreenY;
2978 }
2979#endif
2980#if VarFullScreen
2981 else
2982#endif
2983#if MayNotFullScreen
2984 {
2985 MyWStyle = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
2986 | WS_MINIMIZEBOX;
2987 MyWExStyle = WS_EX_ACCEPTFILES;
2988
2989 DfltWndX = (ScreenX - NewWindowWidth) / 2;
2990 DfltWndY = (ScreenY - NewWindowHeight) / 2;
2991
2992 if (DfltWndX < 0) {
2993 DfltWndX = 0;
2994 }
2995 if (DfltWndY < 0) {
2996 DfltWndY = 0;
2997 }
2998
2999 if (! HavePositionWins[WinIndx]) {
3000 WinPositionWins[WinIndx].x = DfltWndX;
3001 WinPositionWins[WinIndx].y = DfltWndY;
3002 HavePositionWins[WinIndx] = trueblnr;
3003 }
3004
3005 NewWinR.left = WinPositionWins[WinIndx].x;
3006 NewWinR.top = WinPositionWins[WinIndx].y;
3007 NewWinR.right = NewWinR.left + NewWindowWidth;
3008 NewWinR.bottom = NewWinR.top + NewWindowHeight;
3009
3010 (void) AdjustWindowRectEx(&NewWinR, MyWStyle, TRUE, MyWExStyle);
3011
3012 if ((NewWinR.right <= 0)
3013 || (NewWinR.left >= ScreenX)
3014 || (NewWinR.bottom <= 0)
3015 || (NewWinR.top >= ScreenY))
3016 {
3017 NewWinR.left = DfltWndX;
3018 NewWinR.top = DfltWndY;
3019 NewWinR.right = DfltWndX + NewWindowWidth;
3020 NewWinR.bottom = DfltWndY + NewWindowHeight;
3021
3022 (void) AdjustWindowRectEx(&NewWinR,
3023 MyWStyle, TRUE, MyWExStyle);
3024 }
3025 }
3026#endif
3027
3028 if ((OldMainWindow == NULL)
3029#if VarFullScreen
3030 || (WantFullScreen != UseFullScreen)
3031#endif
3032 )
3033 {
3034
3035#if VarFullScreen
3036 if (WantFullScreen)
3037#endif
3038#if MayFullScreen
3039 {
3040 mb = NULL;
3041 }
3042#endif
3043#if VarFullScreen
3044 else
3045#endif
3046#if MayNotFullScreen
3047 {
3048 mb = CreateMenu();
3049 if (mb != NULL) {
3050 m = CreateMenu();
3051 if (m != NULL) {
3052 MyAppendConvertMenuItem(m, ID_FILE_INSERTDISK1,
3053 kStrMenuItemOpen, trueblnr);
3054 (void) AppendMenu(m, MF_SEPARATOR, 0, NULL);
3055 MyAppendConvertMenuItem(m, ID_FILE_QUIT,
3056 kStrMenuItemQuit, falseblnr);
3057 MyAppendSubmenuConvertName(mb, m, kStrMenuFile_win);
3058 }
3059 m = CreateMenu();
3060 if (m != NULL) {
3061 MyAppendConvertMenuItem(m, ID_SPECIAL_MORECOMMANDS,
3062 kStrMenuItemMore, trueblnr);
3063 MyAppendSubmenuConvertName(mb, m, kStrMenuSpecial);
3064 }
3065 m = CreateMenu();
3066 if (m != NULL) {
3067 MyAppendConvertMenuItem(m, ID_HELP_ABOUT,
3068 kStrMenuItemAbout, trueblnr);
3069 MyAppendSubmenuConvertName(mb, m, kStrMenuHelp);
3070 }
3071 }
3072 }
3073#endif
3074
3075 NewMainWindow = CreateWindowEx(
3076 MyWExStyle,
3077 WndClassName,
3078 WndTitle,
3079 MyWStyle,
3080 NewWinR.left, NewWinR.top,
3081 NewWinR.right - NewWinR.left, NewWinR.bottom - NewWinR.top,
3082 NULL,
3083 mb,
3084 AppInstance, NULL);
3085 if (NewMainWindow == NULL) {
3086 MacMsg("CreateWindow failed",
3087 "Sorry, Mini vMac encountered errors"
3088 " and cannot continue.", trueblnr);
3089 return falseblnr;
3090 }
3091
3092 NewMainWndDC = GetDC(NewMainWindow);
3093 if (NewMainWndDC == NULL) {
3094 MacMsg("GetDC failed",
3095 "Sorry, Mini vMac encountered errors"
3096 " and cannot continue.", trueblnr);
3097 DestroyWindow(NewMainWindow);
3098 return falseblnr;
3099 }
3100 } else {
3101 NewMainWndDC = OldMainWndDC;
3102 NewMainWindow = OldMainWindow;
3103 (void) MoveWindow(NewMainWindow, NewWinR.left, NewWinR.top,
3104 NewWinR.right - NewWinR.left, NewWinR.bottom - NewWinR.top,
3105 TRUE);
3106 }
3107
3108#if 0 != vMacScreenDepth
3109 ColorModeWorks = trueblnr;
3110#endif
3111
3112 {
3113 POINT p;
3114
3115 /*
3116 Find out where the window really went, on
3117 the off chance that the WM_MOVE message wasn't
3118 called on CreateWindowEx/MoveWindow, or that
3119 the window wasn't put where asked for.
3120 */
3121 p.x = 0;
3122 p.y = 0;
3123 (void) MapWindowPoints(NewMainWindow, NULL, &p, 1);
3124 WndX = (si4b)p.x;
3125 WndY = (si4b)p.y;
3126 }
3127
3128#if MayFullScreen
3129 GrabMachine = falseblnr;
3130 UnGrabTheMachine();
3131#endif
3132
3133#if UseWinCE && 0
3134 /* Show the taskbar */
3135 SHFullScreen(MainWnd, SHFS_SHOWTASKBAR);
3136#endif
3137
3138#if MayNotFullScreen
3139 CurWinIndx = WinIndx;
3140#endif
3141
3142 MainWnd = NewMainWindow;
3143 MainWndDC = NewMainWndDC;
3144 gTrueBackgroundFlag = falseblnr;
3145#if VarFullScreen
3146 UseFullScreen = WantFullScreen;
3147#endif
3148#if EnableMagnify
3149 UseMagnify = WantMagnify;
3150#endif
3151
3152#if VarFullScreen
3153 if (UseFullScreen)
3154#endif
3155#if MayFullScreen
3156 {
3157 ViewHSize = ScreenX;
3158 ViewVSize = ScreenY;
3159#if EnableMagnify
3160 if (UseMagnify) {
3161 ViewHSize /= MyWindowScale;
3162 ViewVSize /= MyWindowScale;
3163 }
3164#endif
3165 if (ViewHSize >= vMacScreenWidth) {
3166 ViewHStart = 0;
3167 ViewHSize = vMacScreenWidth;
3168 } else {
3169 ViewHSize &= ~ 1;
3170 }
3171 if (ViewVSize >= vMacScreenHeight) {
3172 ViewVStart = 0;
3173 ViewVSize = vMacScreenHeight;
3174 } else {
3175 ViewVSize &= ~ 1;
3176 }
3177 }
3178#endif
3179
3180 if (NewMainWindow != OldMainWindow) {
3181 ShowWindow(NewMainWindow, SW_SHOW /* CmdShow */);
3182 if (OldMainWndDC != NULL) {
3183 ReleaseDC(MainWnd, OldMainWndDC);
3184 }
3185 if (OldMainWindow != NULL) {
3186 /* ShowWindow(OldMainWindow, SW_HIDE); */
3187 DestroyWindow(OldMainWindow);
3188 }
3189
3190 DisconnectKeyCodes3();
3191 /* since key events per window */
3192 } else {
3193 (void) InvalidateRgn(MainWnd, NULL, FALSE);
3194 }
3195
3196#if UseWinCE
3197 /* Create and set logical palette for this window */
3198 {
3199 HPALETTE hpal;
3200 LOGPALETTE *lppal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
3201 sizeof(PALETTEENTRY) * 2);
3202
3203 if (! lppal)
3204 {
3205 MacMsg("CreateWindow failed",
3206 "Sorry, Mini vMac encountered errors"
3207 " and cannot continue.", trueblnr);
3208 return falseblnr;
3209 }
3210
3211 lppal->palNumEntries = 2;
3212 lppal->palVersion = 0x0300;
3213 lppal->palPalEntry[0].peRed = 255;
3214 lppal->palPalEntry[0].peGreen = 255;
3215 lppal->palPalEntry[0].peBlue = 255;
3216 lppal->palPalEntry[0].peFlags = 0;
3217 lppal->palPalEntry[1].peRed = 0;
3218 lppal->palPalEntry[1].peGreen = 0;
3219 lppal->palPalEntry[1].peBlue = 0;
3220 lppal->palPalEntry[1].peFlags = 0;
3221
3222 hpal = CreatePalette(lppal);
3223
3224 if (hpal == NULL) {
3225 free(lppal);
3226 MacMsg("CreateWindow failed",
3227 "Sorry, Mini vMac encountered errors"
3228 " and cannot continue.", trueblnr);
3229 return falseblnr;
3230 }
3231
3232 if (SelectPalette(MainWndDC, hpal, FALSE) == NULL) {
3233 free(lppal);
3234 MacMsg("CreateWindow failed",
3235 "Sorry, Mini vMac encountered errors"
3236 " and cannot continue.", trueblnr);
3237 return falseblnr;
3238 }
3239
3240 if (RealizePalette(MainWndDC) == GDI_ERROR) {
3241 free(lppal);
3242 MacMsg("CreateWindow failed",
3243 "Sorry, Mini vMac encountered errors"
3244 " and cannot continue.", trueblnr);
3245 return falseblnr;
3246 }
3247
3248 free(lppal);
3249 }
3250#endif
3251
3252#if UseWinCE
3253 /* Hide the taskbar */
3254 SHFullScreen(MainWnd, SHFS_HIDETASKBAR);
3255 (void) MoveWindow(MainWnd, 0, 0,
3256 ScreenX, ScreenY, TRUE);
3257#endif
3258
3259 if (HaveCursorHidden) {
3260 (void) MyMoveMouse(CurMouseH, CurMouseV);
3261 WantCursorHidden = trueblnr;
3262 }
3263
3264 return trueblnr;
3265}
3266
3267#if UseWinCE
3268LOCALFUNC blnr AlreadyRunningCheck(void)
3269{
3270 /*
3271 Adapted from example program from Microsoft eMbedded Visual C++
3272 */
3273
3274 /* If it is already running, then focus on the window */
3275 HWND hWnd = FindWindow(WndClassName, WndTitle);
3276 if (hWnd == NULL) {
3277 return falseblnr;
3278 } else {
3279 /*
3280 Set focus to foremost child window.
3281 The "| 0x01" is used to bring any owned
3282 windows to the foreground and activate them.
3283 */
3284 SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001));
3285 return trueblnr;
3286 }
3287}
3288#endif
3289
3290typedef struct BITMAPINFOHEADER256 {
3291 BITMAPINFOHEADER bmi;
3292#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
3293 RGBQUAD colors[CLUT_size];
3294#else
3295 RGBQUAD colors[2];
3296#endif
3297} BITMAPINFOHEADER256;
3298
3299#if EnableMagnify
3300#define MyScaledHeight (MyWindowScale * vMacScreenHeight)
3301#define MyScaledWidth (MyWindowScale * vMacScreenWidth)
3302#endif
3303
3304LOCALPROC HaveChangedScreenBuff(si4b top, si4b left,
3305 si4b bottom, si4b right)
3306{
3307 BITMAPINFOHEADER256 bmh;
3308 ui3b *cdb = GetCurDrawBuff();
3309 int XDest;
3310 int YDest;
3311
3312#if VarFullScreen
3313 if (UseFullScreen)
3314#endif
3315#if MayFullScreen
3316 {
3317 if (top < ViewVStart) {
3318 top = ViewVStart;
3319 }
3320 if (left < ViewHStart) {
3321 left = ViewHStart;
3322 }
3323 if (bottom > ViewVStart + ViewVSize) {
3324 bottom = ViewVStart + ViewVSize;
3325 }
3326 if (right > ViewHStart + ViewHSize) {
3327 right = ViewHStart + ViewHSize;
3328 }
3329
3330 if ((top >= bottom) || (left >= right)) {
3331 goto label_exit;
3332 }
3333 }
3334#endif
3335
3336 XDest = left;
3337 YDest = top;
3338
3339#if VarFullScreen
3340 if (UseFullScreen)
3341#endif
3342#if MayFullScreen
3343 {
3344 XDest -= ViewHStart;
3345 YDest -= ViewVStart;
3346 }
3347#endif
3348
3349#if EnableMagnify
3350 if (UseMagnify) {
3351 XDest *= MyWindowScale;
3352 YDest *= MyWindowScale;
3353 }
3354#endif
3355#if VarFullScreen
3356 if (UseFullScreen)
3357#endif
3358#if MayFullScreen
3359 {
3360 XDest += hOffset;
3361 YDest += vOffset;
3362 }
3363#endif
3364
3365#if 0
3366 { /* testing code */
3367 if (PatBlt(MainWndDC,
3368 (int)left - 1,
3369 (int)top - 1,
3370 (int)right - left + 2,
3371 (int)bottom - top + 2, PATCOPY)) {
3372 }
3373 }
3374#endif
3375#if 0 != vMacScreenDepth
3376 if (UseColorMode) {
3377 int i;
3378 int nDestWidth = (right - left);
3379 int nDestHeight = (bottom - top);
3380#if 1 == vMacScreenDepth
3381 ui3b *p
3382 = ScalingBuff + ((ui5r)vMacScreenWidth / 4) * top;
3383#elif vMacScreenDepth >= 4
3384 ui3b *p = ScalingBuff + (ui5r)vMacScreenByteWidth * top;
3385#else
3386 ui3b *p = cdb + (ui5r)vMacScreenByteWidth * top;
3387#endif
3388
3389 memset(&bmh, 0, sizeof (bmh));
3390 bmh.bmi.biSize = sizeof(BITMAPINFOHEADER);
3391 bmh.bmi.biWidth = vMacScreenWidth;
3392 bmh.bmi.biHeight = - (bottom - top);
3393 bmh.bmi.biPlanes = 1;
3394#if 1 == vMacScreenDepth
3395 bmh.bmi.biBitCount = 4;
3396#else
3397 bmh.bmi.biBitCount = (1 << vMacScreenDepth);
3398#endif
3399 bmh.bmi.biCompression= BI_RGB;
3400 bmh.bmi.biSizeImage = 0;
3401 bmh.bmi.biXPelsPerMeter = 0;
3402 bmh.bmi.biYPelsPerMeter = 0;
3403#if 1 == vMacScreenDepth
3404 bmh.bmi.biClrUsed = 4;
3405#else
3406 bmh.bmi.biClrUsed = 0;
3407#endif
3408 bmh.bmi.biClrImportant = 0;
3409
3410#if vMacScreenDepth < 4
3411 for (i = 0; i < CLUT_size; ++i) {
3412 bmh.colors[i].rgbRed = CLUT_reds[i] >> 8;
3413 bmh.colors[i].rgbGreen = CLUT_greens[i] >> 8;
3414 bmh.colors[i].rgbBlue = CLUT_blues[i] >> 8;
3415 bmh.colors[i].rgbReserved = 0;
3416 }
3417#endif
3418
3419#if 1 == vMacScreenDepth
3420 {
3421 int j;
3422 ui3b *p1 = (ui3b *)(cdb + (ui5r)vMacScreenByteWidth * top);
3423 ui4b *p2 = (ui4b *)p;
3424 for (i = bottom - top; --i >= 0; ) {
3425 for (j = vMacScreenWidth / 4; --j >= 0; ) {
3426 ui4r t0 = *p1++;
3427 *p2 ++
3428 = ((t0 & 0xC0) >> 2)
3429 | ((t0 & 0x30) >> 4)
3430 | ((t0 & 0x0C) << 10)
3431 | ((t0 & 0x03) << 8);
3432 }
3433 }
3434 }
3435#elif 4 == vMacScreenDepth
3436 {
3437 int j;
3438 ui4b *p1 = (ui4b *)(cdb + (ui5r)vMacScreenByteWidth * top);
3439 ui4b *p2 = (ui4b *)p;
3440 for (i = bottom - top; --i >= 0; ) {
3441 for (j = vMacScreenWidth; --j >= 0; ) {
3442 ui4r t0 = *p1++;
3443 *p2 ++ =
3444 ((t0 & 0xFF00) >> 8) | ((t0 & 0x00FF) << 8);
3445 }
3446 }
3447 }
3448#elif 5 == vMacScreenDepth
3449 {
3450 int j;
3451 ui5b *p1 = (ui5b *)(cdb + (ui5r)vMacScreenByteWidth * top);
3452 ui5b *p2 = (ui5b *)p;
3453 for (i = bottom - top; --i >= 0; ) {
3454 for (j = vMacScreenWidth; --j >= 0; ) {
3455 ui5r t0 = *p1++;
3456 *p2++
3457 = ((t0 & 0xFF000000) >> 24)
3458 | ((t0 & 0x00FF0000) >> 8)
3459 | ((t0 & 0x0000FF00) << 8)
3460 | ((t0 & 0x000000FF) << 24);
3461 }
3462 }
3463 }
3464#endif
3465
3466#if EnableMagnify
3467 if (UseMagnify) {
3468 nDestWidth *= MyWindowScale;
3469 nDestHeight *= MyWindowScale;
3470 }
3471#endif
3472
3473 if (StretchDIBits(
3474 MainWndDC, /* handle of device context */
3475 XDest,
3476 /* x-coordinate of upper-left corner of dest. rect. */
3477 YDest,
3478 /* y-coordinate of upper-left corner of dest. rect. */
3479 nDestWidth, /* dest. rectangle width */
3480 nDestHeight, /* dest. rectangle height */
3481 left,
3482 /* x-coordinate of lower-left corner of source rect. */
3483 0, /* y-coordinate of lower-left corner of source rect. */
3484 (right - left), /* source rectangle width */
3485 (bottom - top), /* source rectangle height */
3486 (CONST VOID *)p, /* address of array with DIB bits */
3487 (const struct tagBITMAPINFO *)&bmh,
3488 /* address of structure with bitmap info. */
3489 DIB_RGB_COLORS, /* RGB or palette indices */
3490 SRCCOPY
3491 ) == 0) {
3492 /* ReportWinLastError(); */
3493 }
3494 } else
3495#endif
3496 {
3497 ui3b *p = cdb + (ui5r)vMacScreenMonoByteWidth * top;
3498
3499 memset(&bmh, 0, sizeof (bmh));
3500 bmh.bmi.biSize = sizeof(BITMAPINFOHEADER);
3501 bmh.bmi.biWidth = vMacScreenWidth;
3502 bmh.bmi.biHeight = - (bottom - top);
3503 bmh.bmi.biPlanes = 1;
3504 bmh.bmi.biBitCount = 1;
3505 bmh.bmi.biCompression= BI_RGB;
3506 bmh.bmi.biSizeImage = 0;
3507 bmh.bmi.biXPelsPerMeter = 0;
3508 bmh.bmi.biYPelsPerMeter = 0;
3509 bmh.bmi.biClrUsed = 0;
3510 bmh.bmi.biClrImportant = 0;
3511#if ! UseWinCE
3512 bmh.colors[0].rgbRed = 255;
3513 bmh.colors[0].rgbGreen = 255;
3514 bmh.colors[0].rgbBlue = 255;
3515 bmh.colors[0].rgbReserved = 0;
3516 bmh.colors[1].rgbRed = 0;
3517 bmh.colors[1].rgbGreen = 0;
3518 bmh.colors[1].rgbBlue = 0;
3519 bmh.colors[1].rgbReserved = 0;
3520#endif
3521
3522#if EnableMagnify
3523 if (UseMagnify) {
3524#if EnableScalingBuff
3525 if (ScalingBuff != NULL) {
3526 int i;
3527 int j;
3528 int k;
3529 ui4r left1 = left & (~ 7);
3530 ui4r right1 = (right + 7) & (~ 7);
3531 ui4r jn = (right1 - left1) / 8;
3532 ui3b *p1 =
3533 cdb + ((left1 + vMacScreenWidth * (ui5r)top) / 8);
3534 ui3b *p2 = ScalingBuff
3535 /*
3536 + ((left1 + vMacScreenWidth * MyWindowScale
3537 * (ui5r)top)
3538 * MyWindowScale / 8)
3539 */
3540 ;
3541 ui3b *p3;
3542 ui3b t0;
3543 ui3b t1;
3544 ui3b t2;
3545 ui3b m;
3546
3547 for (i = bottom - top; --i >= 0; ) {
3548 p3 = p2;
3549 for (j = jn; --j >= 0; ) {
3550 t0 = *p1++;
3551 t1 = t0;
3552 m = 0x80;
3553 t2 = 0;
3554 for (k = 4; --k >= 0; ) {
3555 t2 |= t1 & m;
3556 t1 >>= 1;
3557 m >>= 2;
3558 }
3559 *p2++ = t2 | (t2 >> 1);
3560
3561 t1 = t0 << 4;
3562 m = 0x80;
3563 t2 = 0;
3564 for (k = 4; --k >= 0; ) {
3565 t2 |= t1 & m;
3566 t1 >>= 1;
3567 m >>= 2;
3568 }
3569 *p2++ = t2 | (t2 >> 1);
3570 }
3571 p1 += vMacScreenWidth / 8 - jn;
3572 p2 += MyScaledWidth / 8 - (MyWindowScale * jn);
3573 for (j = MyWindowScale * jn; --j >= 0; ) {
3574 *p2++ = *p3++;
3575 }
3576 p2 += MyScaledWidth / 8 - (MyWindowScale * jn);
3577 }
3578
3579 bmh.bmi.biWidth = vMacScreenWidth * MyWindowScale;
3580 bmh.bmi.biHeight = - ((bottom - top) * MyWindowScale);
3581 if (SetDIBitsToDevice(
3582 MainWndDC, /* handle of device context */
3583 XDest,
3584 /*
3585 x-coordinate of upper-left corner
3586 of dest. rect.
3587 */
3588 YDest,
3589 /*
3590 y-coordinate of upper-left corner
3591 of dest. rect.
3592 */
3593 (right - left) * MyWindowScale,
3594 /* source rectangle width */
3595 (bottom - top) * MyWindowScale,
3596 /* source rectangle height */
3597 (left & 7) * MyWindowScale,
3598 /*
3599 x-coordinate of lower-left corner
3600 of source rect.
3601 */
3602 0,
3603 /*
3604 y-coordinate of lower-left corner
3605 of source rect.
3606 */
3607 0, /* first scan line in array */
3608 (bottom - top) * MyWindowScale,
3609 /* number of scan lines */
3610 (CONST VOID *)ScalingBuff,
3611 /* address of array with DIB bits */
3612 (const struct tagBITMAPINFO *)&bmh,
3613 /* address of structure with bitmap info. */
3614#if ! UseWinCE
3615 DIB_RGB_COLORS /* RGB or palette indices */
3616#else
3617 DIB_PAL_COLORS /* palette indices */
3618#endif
3619 ) == 0) {
3620 /* ReportWinLastError(); */
3621 }
3622 }
3623#else
3624 if (StretchDIBits(
3625 MainWndDC, /* handle of device context */
3626 XDest,
3627 /*
3628 x-coordinate of upper-left corner of dest. rect.
3629 */
3630 YDest,
3631 /*
3632 y-coordinate of upper-left corner of dest. rect.
3633 */
3634 (right - left) * MyWindowScale,
3635 /* dest. rectangle width */
3636 (bottom - top) * MyWindowScale,
3637 /* dest. rectangle height */
3638 left,
3639 /*
3640 x-coordinate of lower-left corner
3641 of source rect.
3642 */
3643 0,
3644 /*
3645 y-coordinate of lower-left corner
3646 of source rect.
3647 */
3648 (right - left), /* source rectangle width */
3649 (bottom - top), /* source rectangle height */
3650 (CONST VOID *)p, /* address of array with DIB bits */
3651 (const struct tagBITMAPINFO *)&bmh,
3652 /* address of structure with bitmap info. */
3653#if ! UseWinCE
3654 DIB_RGB_COLORS, /* RGB or palette indices */
3655#else
3656 DIB_PAL_COLORS, /* palette indices */
3657#endif
3658 SRCCOPY
3659 ) == 0) {
3660 /* ReportWinLastError(); */
3661 }
3662#endif
3663 } else
3664#endif
3665
3666 {
3667 if (SetDIBitsToDevice(
3668 MainWndDC, /* handle of device context */
3669 XDest,
3670 /*
3671 x-coordinate of upper-left corner of dest. rect.
3672 */
3673 YDest,
3674 /*
3675 y-coordinate of upper-left corner of dest. rect.
3676 */
3677 (right - left), /* source rectangle width */
3678 (bottom - top), /* source rectangle height */
3679 left,
3680 /*
3681 x-coordinate of lower-left corner
3682 of source rect.
3683 */
3684 0,
3685 /*
3686 y-coordinate of lower-left corner
3687 of source rect.
3688 */
3689 0, /* first scan line in array */
3690 (bottom - top), /* number of scan lines */
3691 (CONST VOID *)p, /* address of array with DIB bits */
3692 (const struct tagBITMAPINFO *)&bmh,
3693 /* address of structure with bitmap info. */
3694#if ! UseWinCE
3695 DIB_RGB_COLORS /* RGB or palette indices */
3696#else
3697 DIB_PAL_COLORS /* palette indices */
3698#endif
3699 ) == 0) {
3700 /* ReportWinLastError(); */
3701 }
3702 }
3703 }
3704
3705#if MayFullScreen
3706label_exit:
3707 ;
3708#endif
3709}
3710
3711LOCALPROC Screen_DrawAll(void)
3712{
3713 HaveChangedScreenBuff(0, 0, vMacScreenHeight, vMacScreenWidth);
3714}
3715
3716LOCALPROC MyDrawChangesAndClear(void)
3717{
3718 if (ScreenChangedBottom > ScreenChangedTop) {
3719 HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
3720 ScreenChangedBottom, ScreenChangedRight);
3721 ScreenClearChanges();
3722 }
3723}
3724
3725GLOBALOSGLUPROC DoneWithDrawingForTick(void)
3726{
3727#if EnableFSMouseMotion
3728 if (HaveMouseMotion) {
3729 AutoScrollScreen();
3730 }
3731#endif
3732 MyDrawChangesAndClear();
3733}
3734
3735LOCALFUNC blnr InitTheCursor(void)
3736{
3737 SetCursor(LoadCursor(NULL, IDC_ARROW));
3738 return trueblnr;
3739}
3740
3741#if EnableFSMouseMotion
3742LOCALPROC MyMouseConstrain(void)
3743{
3744 si4b shiftdh;
3745 si4b shiftdv;
3746
3747 if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
3748 shiftdh = ViewHSize / 2;
3749 } else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4))
3750 {
3751 shiftdh = - ViewHSize / 2;
3752 } else {
3753 shiftdh = 0;
3754 }
3755 if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
3756 shiftdv = ViewVSize / 2;
3757 } else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4))
3758 {
3759 shiftdv = - ViewVSize / 2;
3760 } else {
3761 shiftdv = 0;
3762 }
3763 if ((shiftdh != 0) || (shiftdv != 0)) {
3764 SavedMouseH += shiftdh;
3765 SavedMouseV += shiftdv;
3766 if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
3767 HaveMouseMotion = falseblnr;
3768 }
3769 }
3770}
3771#endif
3772
3773LOCALPROC MousePositionNotify(LONG NewMousePosx, LONG NewMousePosy)
3774{
3775 blnr ShouldHaveCursorHidden = trueblnr;
3776
3777#if VarFullScreen
3778 if (UseFullScreen)
3779#endif
3780#if MayFullScreen
3781 {
3782 NewMousePosx -= hOffset;
3783 NewMousePosy -= vOffset;
3784 }
3785#endif
3786
3787#if EnableMagnify
3788 if (UseMagnify) {
3789 NewMousePosx /= MyWindowScale;
3790 NewMousePosy /= MyWindowScale;
3791 }
3792#endif
3793
3794#if VarFullScreen
3795 if (UseFullScreen)
3796#endif
3797#if MayFullScreen
3798 {
3799 NewMousePosx += ViewHStart;
3800 NewMousePosy += ViewVStart;
3801 }
3802#endif
3803
3804#if EnableFSMouseMotion
3805 if (HaveMouseMotion) {
3806 MyMousePositionSetDelta(NewMousePosx - SavedMouseH,
3807 NewMousePosy - SavedMouseV);
3808 SavedMouseH = NewMousePosx;
3809 SavedMouseV = NewMousePosy;
3810 } else
3811#endif
3812 {
3813 if (NewMousePosx < 0) {
3814 NewMousePosx = 0;
3815 ShouldHaveCursorHidden = falseblnr;
3816 } else if (NewMousePosx > vMacScreenWidth) {
3817 NewMousePosx = vMacScreenWidth - 1;
3818 ShouldHaveCursorHidden = falseblnr;
3819 }
3820 if (NewMousePosy < 0) {
3821 NewMousePosy = 0;
3822 ShouldHaveCursorHidden = falseblnr;
3823 } else if (NewMousePosy > vMacScreenHeight) {
3824 NewMousePosy = vMacScreenHeight - 1;
3825 ShouldHaveCursorHidden = falseblnr;
3826 }
3827
3828#if VarFullScreen
3829 if (UseFullScreen)
3830#endif
3831#if MayFullScreen
3832 {
3833 ShouldHaveCursorHidden = trueblnr;
3834 }
3835#endif
3836
3837#if ! UseWinCE
3838 /* if (ShouldHaveCursorHidden || CurMouseButton) */
3839 /*
3840 for a game like arkanoid, would like mouse to still
3841 move even when outside window in one direction
3842 */
3843#endif
3844 MyMousePositionSet(NewMousePosx, NewMousePosy);
3845 }
3846
3847 WantCursorHidden = ShouldHaveCursorHidden;
3848}
3849
3850#if ! UseWinCE
3851LOCALPROC CheckMouseState(void)
3852{
3853 POINT NewMousePos;
3854
3855 GetCursorPos(&NewMousePos);
3856 NewMousePos.x -= WndX;
3857 NewMousePos.y -= WndY;
3858 MousePositionNotify(NewMousePos.x, NewMousePos.y);
3859}
3860#endif
3861
3862LOCALVAR const ui3b Native2MacRomanTab[] = {
3863 0xAD, 0xB0, 0xE2, 0xC4, 0xE3, 0xC9, 0xA0, 0xE0,
3864 0xF6, 0xE4, 0xB6, 0xDC, 0xCE, 0xB2, 0xB3, 0xB7,
3865 0xB8, 0xD4, 0xD5, 0xD2, 0xD3, 0xA5, 0xD0, 0xD1,
3866 0xF7, 0xAA, 0xC5, 0xDD, 0xCF, 0xB9, 0xC3, 0xD9,
3867 0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0xBA, 0xA4,
3868 0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0xBD, 0xA8, 0xF8,
3869 0xA1, 0xB1, 0xC6, 0xD7, 0xAB, 0xB5, 0xA6, 0xE1,
3870 0xFC, 0xDA, 0xBC, 0xC8, 0xDE, 0xDF, 0xF0, 0xC0,
3871 0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,
3872 0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,
3873 0xF5, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0xF9,
3874 0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0xFA, 0xFB, 0xA7,
3875 0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,
3876 0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
3877 0xFD, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,
3878 0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0xFE, 0xFF, 0xD8
3879};
3880
3881#if IncludePbufs
3882LOCALFUNC tMacErr NativeTextToMacRomanPbuf(HGLOBAL x, tPbuf *r)
3883{
3884#if MyUseUni
3885#define MyUnsignedChar ui4b
3886#else
3887#define MyUnsignedChar ui3b
3888#endif
3889 HGLOBAL h;
3890 LPTSTR p1;
3891 ui5b n;
3892 MyUnsignedChar v;
3893 tMacErr err = mnvm_miscErr;
3894
3895 p1 = GlobalLock(x);
3896 if (p1 != NULL) {
3897 n = 0;
3898 while ((v = *p1++) != 0) {
3899 if (v != 10) {
3900 ++n;
3901 }
3902 }
3903 (void) GlobalUnlock(x);
3904
3905 h = GlobalAlloc(GMEM_DDESHARE, n);
3906 if (h != NULL) {
3907 p1 = GlobalLock(x);
3908 if (p1 != NULL) {
3909 ui3b *p2 = GlobalLock(h);
3910 if (p2 != NULL) {
3911 while ((v = (MyUnsignedChar)*p1++) != 0) {
3912 if (v >= 128) {
3913 *p2++ = Native2MacRomanTab[v & 0x7F];
3914 /*
3915 if MyUseUni, then for gives
3916 garbage for v > 256.
3917 */
3918 } else if (v != 10) {
3919 *p2++ = v;
3920 }
3921 }
3922
3923 err = mnvm_noErr;
3924
3925 (void) GlobalUnlock(h);
3926 }
3927 (void) GlobalUnlock(x);
3928 }
3929
3930 if (mnvm_noErr != err) {
3931 (void) GlobalFree(h);
3932 } else {
3933 err = PbufNewFromHandle(h, n, r);
3934 }
3935 }
3936 }
3937
3938 return err;
3939}
3940#endif
3941
3942LOCALVAR const ui3b MacRoman2NativeTab[] = {
3943 0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1,
3944 0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8,
3945 0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3,
3946 0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC,
3947 0x86, 0xB0, 0xA2, 0xA3, 0xA7, 0x95, 0xB6, 0xDF,
3948 0xAE, 0xA9, 0x99, 0xB4, 0xA8, 0x80, 0xC6, 0xD8,
3949 0x81, 0xB1, 0x8D, 0x8E, 0xA5, 0xB5, 0x8A, 0x8F,
3950 0x90, 0x9D, 0xA6, 0xAA, 0xBA, 0xAD, 0xE6, 0xF8,
3951 0xBF, 0xA1, 0xAC, 0x9E, 0x83, 0x9A, 0xB2, 0xAB,
3952 0xBB, 0x85, 0xA0, 0xC0, 0xC3, 0xD5, 0x8C, 0x9C,
3953 0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xF7, 0xB3,
3954 0xFF, 0x9F, 0xB9, 0xA4, 0x8B, 0x9B, 0xBC, 0xBD,
3955 0x87, 0xB7, 0x82, 0x84, 0x89, 0xC2, 0xCA, 0xC1,
3956 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0xD3, 0xD4,
3957 0xBE, 0xD2, 0xDA, 0xDB, 0xD9, 0xD0, 0x88, 0x98,
3958 0xAF, 0xD7, 0xDD, 0xDE, 0xB8, 0xF0, 0xFD, 0xFE
3959};
3960
3961#if IncludePbufs
3962LOCALFUNC blnr MacRomanTextToNativeHand(tPbuf Pbuf_no,
3963 blnr IsFileName, HGLOBAL *r)
3964{
3965 HGLOBAL h;
3966 ui5b i;
3967 ui5b rn = 0;
3968 HGLOBAL bh = PbufDat[Pbuf_no];
3969 ui5b L = PbufSize[Pbuf_no];
3970 blnr IsOk = falseblnr;
3971
3972 if (IsFileName) {
3973 if (L > 255) {
3974 L = 255;
3975 }
3976 } else {
3977 ui3b *Buffer = (ui3b *)GlobalLock(bh);
3978 if (Buffer != NULL) {
3979 for (i = 0; i < L; ++i) {
3980 if (Buffer[i] == 13) {
3981 ++rn;
3982 }
3983 }
3984 (void) GlobalUnlock(bh);
3985 }
3986 }
3987
3988 h = GlobalAlloc(GMEM_DDESHARE, (L + rn + 1) * sizeof(TCHAR));
3989 if (h != NULL) {
3990 ui3b *Buffer = (ui3b *)GlobalLock(bh);
3991 if (Buffer != NULL) {
3992 LPTSTR p1 = GlobalLock(h);
3993 if (p1 != NULL) {
3994 for (i = 0; i < L; ++i) {
3995 TCHAR y;
3996 ui3b x = ((ui3b *)Buffer)[i];
3997 if (x >= 128) {
3998 y = (TCHAR)MacRoman2NativeTab[x - 128];
3999 } else {
4000 if (IsFileName) {
4001 if ((x < 32)
4002 || ('\\' == x) || ('/' == x)
4003 || (':' == x) || ('*' == x)
4004 || ('?' == x) || ('"' == x)
4005 || ('<' == x) || ('>' == x)
4006 || ('|' == x))
4007 {
4008 y = (TCHAR)('-');
4009 } else {
4010 y = (TCHAR)x;
4011 }
4012 } else {
4013 if (13 == x) {
4014 *p1++ = (TCHAR)(13);
4015 y = (TCHAR)(10);
4016 } else {
4017 y = (TCHAR)x;
4018 }
4019 }
4020 }
4021 *p1++ = y;
4022 }
4023 *p1++ = (TCHAR) 0; /* null character */
4024
4025 *r = h;
4026 IsOk = trueblnr;
4027
4028 (void) GlobalUnlock(h);
4029 }
4030 (void) GlobalUnlock(bh);
4031 }
4032 if (! IsOk) {
4033 (void) GlobalFree(h);
4034 }
4035 }
4036
4037 return IsOk;
4038}
4039#endif
4040
4041#if IncludeHostTextClipExchange
4042GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
4043{
4044 HGLOBAL h;
4045 tMacErr err = mnvm_miscErr;
4046
4047 if (MacRomanTextToNativeHand(i, falseblnr, &h)) {
4048 if (! OpenClipboard(MainWnd)) {
4049 /* ReportGetLastError(); */
4050 } else {
4051 if (! EmptyClipboard()) {
4052 /* ReportGetLastError(); */
4053 }
4054 if (SetClipboardData(CF_TEXT, h) == NULL) {
4055 /* ReportGetLastError(); */
4056 } else {
4057 err = mnvm_noErr;
4058 }
4059 h = NULL;
4060 if (! CloseClipboard()) {
4061 /* ReportGetLastError(); */
4062 }
4063 }
4064 if (h != NULL) {
4065 (void) GlobalFree(h);
4066 }
4067 }
4068
4069 PbufDispose(i);
4070
4071 return err;
4072}
4073#endif
4074
4075#if IncludeHostTextClipExchange
4076GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
4077{
4078 tMacErr err = mnvm_miscErr;
4079
4080 if (IsClipboardFormatAvailable(CF_TEXT)) {
4081 if (! OpenClipboard(MainWnd)) {
4082 /* ReportGetLastError(); */
4083 } else {
4084 HGLOBAL h = GetClipboardData(CF_TEXT);
4085 if (h == NULL) {
4086 /* ReportGetLastError(); */
4087 } else {
4088 err = NativeTextToMacRomanPbuf(h, r);
4089 }
4090 if (! CloseClipboard()) {
4091 /* ReportGetLastError(); */
4092 }
4093 }
4094 }
4095
4096 return err;
4097}
4098#endif
4099
4100
4101#if EmLocalTalk
4102
4103LOCALFUNC blnr EntropyGather(void)
4104{
4105 /*
4106 gather some entropy from several places, just in case
4107 /dev/urandom is not available.
4108 */
4109
4110 {
4111 DWORD t = timeGetTime();
4112
4113 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b));
4114 }
4115
4116 {
4117 SYSTEMTIME t;
4118
4119 GetLocalTime(&t);
4120
4121 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b));
4122 }
4123
4124 {
4125 POINT t;
4126
4127 GetCursorPos(&t);
4128
4129 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b));
4130 }
4131
4132#if 0
4133 /*
4134 Another possible source of entropy. But if available,
4135 almost certainly /dev/urandom is also available.
4136 */
4137 /* #include <sys/sysinfo.h> */
4138 {
4139 struct sysinfo t;
4140
4141 if (0 != sysinfo(&t)) {
4142#if dbglog_HAVE
4143 dbglog_writeln("sysinfo fails");
4144#endif
4145 }
4146
4147 /*
4148 continue even if error, it doesn't hurt anything
4149 if t is garbage.
4150 */
4151 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b));
4152 }
4153#endif
4154
4155
4156 {
4157 DWORD t = GetCurrentProcessId();
4158
4159 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b));
4160 }
4161
4162 return trueblnr;
4163}
4164#endif
4165
4166#if EmLocalTalk
4167
4168#include "LOCALTLK.h"
4169
4170#endif
4171
4172
4173/* --- drives --- */
4174
4175#define NotAfileRef INVALID_HANDLE_VALUE
4176
4177LOCALVAR HANDLE Drives[NumDrives]; /* open disk image files */
4178
4179#define NeedDriveNames (IncludeSonyGetName || IncludeSonyNew)
4180
4181#if NeedDriveNames
4182LOCALVAR HGLOBAL DriveNames[NumDrives];
4183 /*
4184 It is supposed to be possible to use
4185 GetMappedFileName to get name of open file,
4186 but that seems ugly kludge, so instead
4187 save the name on open.
4188 */
4189#endif
4190
4191LOCALPROC InitDrives(void)
4192{
4193 /*
4194 This isn't really needed, Drives[i] and DriveNames[i]
4195 need not have valid values when not vSonyIsInserted[i].
4196 */
4197 tDrive i;
4198
4199 for (i = 0; i < NumDrives; ++i) {
4200 Drives[i] = NotAfileRef;
4201#if NeedDriveNames
4202 DriveNames[i] = NULL;
4203#endif
4204 }
4205}
4206
4207GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
4208 tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
4209 ui5r *Sony_ActCount)
4210{
4211 HANDLE refnum;
4212 DWORD newL;
4213 tMacErr result;
4214 DWORD BytesTransferred = 0;
4215
4216 refnum = Drives[Drive_No];
4217 newL = SetFilePointer(
4218 refnum, /* handle of file */
4219 Sony_Start, /* number of bytes to move file pointer */
4220 nullpr, /* address of high-order word of distance to move */
4221 FILE_BEGIN /* how to move */
4222 );
4223 if (newL == 0xFFFFFFFF) {
4224 result = mnvm_miscErr; /*& figure out what really to return &*/
4225 } else if (Sony_Start != (ui5b)newL) {
4226 /* not supposed to get here */
4227 result = mnvm_miscErr; /*& figure out what really to return &*/
4228 } else {
4229 if (IsWrite) {
4230 if (! WriteFile(refnum, /* handle of file to read */
4231 (LPVOID)Buffer
4232 , /* address of buffer that receives data */
4233 (DWORD)Sony_Count, /* number of bytes to read */
4234 &BytesTransferred, /* address of number of bytes read */
4235 nullpr)) /* address of structure for data */
4236 {
4237 result = mnvm_miscErr;
4238 /*& figure out what really to return &*/
4239 } else if ((ui5b)BytesTransferred != Sony_Count) {
4240 result = mnvm_miscErr;
4241 /*& figure out what really to return &*/
4242 } else {
4243 result = mnvm_noErr;
4244 }
4245 } else {
4246 if (! ReadFile(refnum, /* handle of file to read */
4247 (LPVOID)Buffer,
4248 /* address of buffer that receives data */
4249 (DWORD)Sony_Count, /* number of bytes to read */
4250 &BytesTransferred,
4251 /* address of number of bytes read */
4252 nullpr)) /* address of structure for data */
4253 {
4254 result = mnvm_miscErr;
4255 /*& figure out what really to return &*/
4256 } else if ((ui5b)BytesTransferred != Sony_Count) {
4257 result = mnvm_miscErr;
4258 /*& figure out what really to return &*/
4259 } else {
4260 result = mnvm_noErr;
4261 }
4262 }
4263 }
4264
4265 if (nullpr != Sony_ActCount) {
4266 *Sony_ActCount = BytesTransferred;
4267 }
4268
4269 return result;
4270}
4271
4272GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
4273{
4274 tMacErr result;
4275 DWORD L;
4276
4277 L = GetFileSize(Drives[Drive_No], nullpr);
4278 if (L == 0xFFFFFFFF) {
4279 result = mnvm_miscErr; /*& figure out what really to return &*/
4280 } else {
4281 *Sony_Count = L;
4282 result = mnvm_noErr;
4283 }
4284
4285 return result;
4286}
4287
4288LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit)
4289{
4290 HANDLE refnum = Drives[Drive_No];
4291
4292#if ! NeedDriveNames
4293 UnusedParam(deleteit);
4294#endif
4295
4296 Drives[Drive_No] = NotAfileRef; /* not really needed */
4297
4298 DiskEjectedNotify(Drive_No);
4299
4300 (void) FlushFileBuffers(refnum);
4301 (void) CloseHandle(refnum);
4302
4303#if NeedDriveNames
4304 {
4305 HGLOBAL h = DriveNames[Drive_No];
4306 if (NULL != h) {
4307 if (deleteit) {
4308 LPTSTR drivepath = GlobalLock(h);
4309 if (drivepath != NULL) {
4310 (void) DeleteFile(drivepath);
4311 (void) GlobalUnlock(h);
4312 }
4313 }
4314 (void) GlobalFree(h);
4315 DriveNames[Drive_No] = NULL; /* not really needed */
4316 }
4317 }
4318#endif
4319
4320 return mnvm_noErr;
4321}
4322
4323GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
4324{
4325 return vSonyEject0(Drive_No, falseblnr);
4326}
4327
4328#if IncludeSonyNew
4329GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
4330{
4331 return vSonyEject0(Drive_No, trueblnr);
4332}
4333#endif
4334
4335LOCALPROC UnInitDrives(void)
4336{
4337 tDrive i;
4338
4339 for (i = 0; i < NumDrives; ++i) {
4340 if (vSonyIsInserted(i)) {
4341 (void) vSonyEject(i);
4342 }
4343 }
4344}
4345
4346#if NeedDriveNames
4347LOCALFUNC blnr LPTSTRtoHand(LPTSTR s, HGLOBAL *r)
4348{
4349 blnr IsOk = falseblnr;
4350
4351 size_t L = _tcslen(s);
4352 HGLOBAL h = GlobalAlloc(GMEM_DDESHARE,
4353 (L + 1) * sizeof(TCHAR));
4354 if (h != NULL) {
4355 LPTSTR p = GlobalLock(h);
4356 if (p != NULL) {
4357 _tcscpy(p, s);
4358 IsOk = trueblnr;
4359 (void) GlobalUnlock(h);
4360 }
4361 if (! IsOk) {
4362 (void) GlobalFree(h);
4363 } else {
4364 *r = h;
4365 }
4366 }
4367
4368 return IsOk;
4369}
4370#endif
4371
4372#if IncludeSonyGetName
4373GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
4374{
4375 WIN32_FIND_DATA fd;
4376 tMacErr err = mnvm_miscErr;
4377 HGLOBAL ph = DriveNames[Drive_No];
4378 if (NULL != ph) {
4379 LPTSTR drivepath = GlobalLock(ph);
4380 if (drivepath != NULL) {
4381 HANDLE hf = FindFirstFile(drivepath, &fd);
4382 (void) GlobalUnlock(ph);
4383
4384 if (hf != INVALID_HANDLE_VALUE) {
4385 HGLOBAL h;
4386 if (LPTSTRtoHand(fd.cFileName, &h)) {
4387 err = NativeTextToMacRomanPbuf(h, r);
4388 }
4389 FindClose(hf);
4390 }
4391 }
4392 }
4393
4394 return err;
4395}
4396#endif
4397
4398LOCALFUNC blnr Sony_Insert0(HANDLE refnum, blnr locked,
4399 LPTSTR drivepath)
4400{
4401 tDrive Drive_No;
4402
4403#if ! NeedDriveNames
4404 UnusedParam(drivepath);
4405#endif
4406
4407 if (! FirstFreeDisk(&Drive_No)) {
4408 (void) CloseHandle(refnum);
4409 MacMsg(kStrTooManyImagesTitle,
4410 kStrTooManyImagesMessage, falseblnr);
4411 return falseblnr;
4412 } else {
4413 Drives[Drive_No] = refnum;
4414 DiskInsertNotify(Drive_No, locked);
4415#if NeedDriveNames
4416 {
4417 HGLOBAL h;
4418
4419 if (! LPTSTRtoHand(drivepath, &h)) {
4420 h = NULL;
4421 }
4422
4423 DriveNames[Drive_No] = h;
4424 }
4425#endif
4426 return trueblnr;
4427 }
4428}
4429
4430LOCALFUNC blnr Sony_Insert1(LPTSTR drivepath, blnr SilentOnMissing)
4431{
4432 blnr locked = falseblnr;
4433 HANDLE refnum = CreateFile(
4434 drivepath, /* pointer to name of the file */
4435 GENERIC_READ + GENERIC_WRITE, /* access (read-write) mode */
4436 0, /* share mode */
4437 nullpr, /* pointer to security descriptor */
4438 OPEN_EXISTING, /* how to create */
4439 FILE_ATTRIBUTE_NORMAL, /* file attributes */
4440 nullpr /* handle to file with attributes to copy */
4441 );
4442 if (refnum == INVALID_HANDLE_VALUE) {
4443 if (ERROR_ACCESS_DENIED == GetLastError()) {
4444 locked = trueblnr;
4445 refnum = CreateFile(
4446 drivepath, /* pointer to name of the file */
4447 GENERIC_READ, /* access (read-write) mode */
4448 FILE_SHARE_READ, /* share mode */
4449 nullpr, /* pointer to security descriptor */
4450 OPEN_EXISTING, /* how to create */
4451 FILE_ATTRIBUTE_NORMAL, /* file attributes */
4452 nullpr /* handle to file with attributes to copy */
4453 );
4454 }
4455 }
4456 if (refnum == INVALID_HANDLE_VALUE) {
4457 DWORD err = GetLastError();
4458 if (ERROR_SHARING_VIOLATION == err) {
4459 MacMsg(kStrImageInUseTitle,
4460 kStrImageInUseMessage, falseblnr);
4461 } else if ((ERROR_FILE_NOT_FOUND == err) && SilentOnMissing) {
4462 /* ignore it */
4463 } else {
4464 MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
4465 }
4466 } else {
4467 return Sony_Insert0(refnum, locked, drivepath);
4468 }
4469 return falseblnr;
4470}
4471
4472LOCALFUNC blnr LoadMacRomFromPath(LPTSTR drivepath)
4473{
4474 HANDLE refnum = INVALID_HANDLE_VALUE;
4475 blnr IsOk = falseblnr;
4476
4477 refnum = CreateFile(
4478 drivepath, /* pointer to name of the file */
4479 GENERIC_READ, /* access (read-write) mode */
4480 FILE_SHARE_READ, /* share mode */
4481 nullpr, /* pointer to security descriptor */
4482 OPEN_EXISTING, /* how to create */
4483 FILE_ATTRIBUTE_NORMAL, /* file attributes */
4484 nullpr /* handle to file with attributes to copy */
4485 );
4486
4487 if (refnum == INVALID_HANDLE_VALUE) {
4488 /* MacMsg(kStrNoROMTitle, kStrNoROMMessage, trueblnr); */
4489 } else {
4490 DWORD BytesRead;
4491
4492 if (! ReadFile(refnum, /* handle of file to read */
4493 (LPVOID)ROM, /* address of buffer that receives data */
4494 (DWORD)kROM_Size, /* number of bytes to read */
4495 &BytesRead, /* address of number of bytes read */
4496 nullpr)) /* address of structure for data */
4497 {
4498 MacMsgOverride(kStrNoReadROMTitle, kStrNoReadROMMessage);
4499 } else
4500 if ((ui5b)BytesRead != kROM_Size) {
4501 MacMsgOverride(kStrShortROMTitle, kStrShortROMMessage);
4502 } else
4503 {
4504 IsOk = (mnvm_noErr == ROM_IsValid());
4505 }
4506 (void) CloseHandle(refnum);
4507 }
4508
4509 return IsOk;
4510}
4511
4512#ifndef EnableShellLinks
4513#define EnableShellLinks 1
4514#endif
4515
4516#if EnableShellLinks
4517LOCALVAR blnr COMinited = falseblnr;
4518LOCALVAR blnr COMinitedOK;
4519#endif
4520
4521#if EnableShellLinks
4522LOCALPROC MyUninitCOM(void)
4523{
4524 if (COMinited) {
4525 CoUninitialize();
4526 }
4527}
4528#endif
4529
4530#if EnableShellLinks
4531LOCALFUNC blnr MyNeedCOM(void)
4532{
4533 HRESULT hres;
4534
4535 if (! COMinited) {
4536 COMinitedOK = falseblnr;
4537 hres = CoInitialize(NULL);
4538 if (SUCCEEDED(hres)) {
4539 COMinitedOK = trueblnr;
4540 }
4541
4542 COMinited = trueblnr;
4543 }
4544 return COMinitedOK;
4545}
4546#endif
4547
4548#if EnableShellLinks
4549LOCALFUNC blnr MyResolveShortcut(LPTSTR FilePath, blnr *directory)
4550/* adapted from Microsoft example code */
4551{
4552 HRESULT hres;
4553 IShellLink *psl;
4554 IPersistFile* ppf;
4555 TCHAR szGotPath[MAX_PATH];
4556 WIN32_FIND_DATA wfd;
4557 blnr IsOk = falseblnr;
4558
4559 if (MyNeedCOM()) {
4560 hres = CoCreateInstance(&CLSID_ShellLink, NULL,
4561 CLSCTX_INPROC_SERVER, &IID_IShellLink,
4562 (LPVOID *)(void *)&psl);
4563 /*
4564 the (void *) prevents a compiler warning
4565 from gcc
4566 */
4567 if (SUCCEEDED(hres)) {
4568 /* Get a pointer to the IPersistFile interface. */
4569 hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile,
4570 (void **)(void *)&ppf);
4571 if (SUCCEEDED(hres)) {
4572 /* Ensure that the string is Unicode. */
4573#if MyUseUni
4574#define wsz FilePath
4575#else
4576 WORD wsz[MAX_PATH];
4577 MultiByteToWideChar(CP_ACP, 0, FilePath, -1, wsz,
4578 MAX_PATH);
4579#endif
4580
4581 /* Load the shortcut. */
4582 hres = ppf->lpVtbl->Load(ppf, wsz, STGM_READ);
4583 if (SUCCEEDED(hres)) {
4584 /* Resolve the link. */
4585 hres = psl->lpVtbl->Resolve(psl, MainWnd,
4586 SLR_ANY_MATCH);
4587 if (SUCCEEDED(hres)) {
4588 /* Get the path to the link target. */
4589 hres = psl->lpVtbl->GetPath(psl, szGotPath,
4590 MAX_PATH, &wfd,
4591 SLGP_SHORTPATH);
4592 if (SUCCEEDED(hres)) {
4593 /*
4594 This is in the sample code, but doesn't
4595 seem to be needed:
4596 Get the description of the target.
4597 char szDescription[MAX_PATH];
4598 hres = psl->lpVtbl->GetDescription(psl,
4599 szDescription, MAX_PATH);
4600 if (SUCCEEDED(hres)) {
4601 }
4602 */
4603 lstrcpy(FilePath, szGotPath);
4604 if (NULL != directory) {
4605 *directory = (0 != (wfd.dwFileAttributes
4606 & FILE_ATTRIBUTE_DIRECTORY));
4607 }
4608 IsOk = trueblnr;
4609 }
4610 }
4611 }
4612
4613 ppf->lpVtbl->Release(ppf);
4614 }
4615 psl->lpVtbl->Release(psl);
4616 }
4617 }
4618 return IsOk;
4619}
4620#endif
4621
4622#if EnableShellLinks
4623LOCALFUNC blnr FileIsLink(LPTSTR drivepath)
4624{
4625 LPTSTR p = FindLastTerm(drivepath, (TCHAR)('.'));
4626
4627 if (p != nullpr) {
4628 if (_tcscmp(p, TEXT("lnk")) == 0) {
4629 return trueblnr;
4630 }
4631 }
4632 return falseblnr;
4633}
4634#endif
4635
4636LOCALFUNC blnr InsertDiskOrAlias(LPTSTR drivepath,
4637 blnr MaybeROM, blnr MaybeAlias)
4638{
4639#if EnableShellLinks
4640 if (MaybeAlias && FileIsLink(drivepath)) {
4641 if (! MyResolveShortcut(drivepath, NULL)) {
4642 return falseblnr;
4643 }
4644 }
4645#endif
4646
4647 if (MaybeROM && ! ROM_loaded) {
4648 return LoadMacRomFromPath(drivepath);
4649 } else {
4650 return Sony_Insert1(drivepath, falseblnr);
4651 }
4652}
4653
4654LOCALFUNC blnr MyFileExists(LPTSTR pathName, blnr *directory)
4655{
4656 WIN32_FIND_DATA fd;
4657 HANDLE hf = FindFirstFile(pathName, &fd);
4658 blnr IsOk = falseblnr;
4659
4660 if (hf != INVALID_HANDLE_VALUE) {
4661 if (NULL != directory) {
4662 *directory =
4663 (0 != (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
4664 }
4665 IsOk = trueblnr;
4666 FindClose(hf);
4667 }
4668
4669 return IsOk;
4670}
4671
4672LOCALFUNC tMacErr ResolveNamedChild0(LPTSTR pathName,
4673 LPTSTR Child, blnr *directory)
4674{
4675 size_t newlen;
4676 size_t oldlen = _tcslen(pathName);
4677 tMacErr err = mnvm_miscErr;
4678
4679 newlen = oldlen + 1 + _tcslen(Child);
4680 if (newlen + 1 < _MAX_PATH) {
4681 _tcscat(pathName, TEXT("\\"));
4682 _tcscat(pathName, Child);
4683
4684 if (MyFileExists(pathName, directory)) {
4685 err = mnvm_noErr;
4686 } else {
4687 err = mnvm_fnfErr;
4688#if EnableShellLinks
4689 if (newlen + 5 < _MAX_PATH) {
4690 _tcscat(pathName, TEXT(".lnk"));
4691 if (MyFileExists(pathName, NULL))
4692 if (MyResolveShortcut(pathName, directory))
4693 {
4694 err = mnvm_noErr;
4695 }
4696 if (mnvm_noErr != err) {
4697 pathName[newlen] = (TCHAR)('\0');
4698 }
4699 }
4700#endif
4701 }
4702 }
4703
4704 return err;
4705}
4706
4707LOCALFUNC tMacErr ResolveNamedChild(LPTSTR pathName,
4708 char *Child, blnr *directory)
4709{
4710 TCHAR Child0[ClStrMaxLength + 1];
4711
4712 NativeStrFromCStr(Child0, Child, falseblnr);
4713
4714 return ResolveNamedChild0(pathName, Child0, directory);
4715}
4716
4717LOCALFUNC blnr ResolveNamedChildDir(LPTSTR pathName, char *Child)
4718{
4719 blnr directory;
4720
4721 return (mnvm_noErr == ResolveNamedChild(
4722 pathName, Child, &directory))
4723 && directory;
4724}
4725
4726LOCALFUNC blnr ResolveNamedChildFile(LPTSTR pathName, char *Child)
4727{
4728 blnr directory;
4729
4730 return (mnvm_noErr == ResolveNamedChild(
4731 pathName, Child, &directory))
4732 && ! directory;
4733}
4734
4735#if UseActvFile || (IncludeSonyNew && ! SaveDialogEnable)
4736LOCALFUNC blnr MakeNamedChildDir(LPTSTR pathName, char *Child)
4737{
4738 blnr directory;
4739 blnr IsOk = falseblnr;
4740 tMacErr err = ResolveNamedChild(pathName, Child, &directory);
4741
4742 if (mnvm_noErr == err) {
4743 IsOk = directory;
4744 } else if (mnvm_fnfErr == err) {
4745 if (CreateDirectory(pathName, NULL)) {
4746 IsOk = trueblnr;
4747 }
4748 }
4749
4750 return IsOk;
4751}
4752#endif
4753
4754LOCALFUNC blnr MyGetAppDataPath(LPTSTR lpszPath,
4755 BOOL fCreate)
4756{
4757 blnr IsOk = falseblnr;
4758
4759 if (HaveMySHGetSpecialFolderPath())
4760 if (MySHGetSpecialFolderPath(
4761 NULL /* HWND hwndOwner */,
4762 lpszPath, My_CSIDL_APPDATA, fCreate))
4763 {
4764 IsOk = trueblnr;
4765 }
4766 /*
4767 if not available, could perhaps
4768 use GetWindowsDirectory.
4769 */
4770 /*
4771 SHGetFolderPath is more recent,
4772 could perhaps check for it first.
4773 might also be in "SHFolder.dll".
4774
4775 SHGetKnownFolderPath is even
4776 more recent.
4777 */
4778
4779 return IsOk;
4780}
4781
4782#if UseWinCE
4783/* Are we in control mode? */
4784/* Needed because you can't hold down a key with the virtual keyboard */
4785LOCALVAR blnr CtrlMode = falseblnr;
4786#endif
4787
4788LOCALPROC InsertADisk0(void)
4789{
4790 OPENFILENAME ofn;
4791 TCHAR szDirName[256];
4792 TCHAR szFile[256];
4793#if ! UseWinCE
4794 TCHAR szFileTitle[256];
4795#endif
4796 UINT i;
4797 size_t cbString;
4798 TCHAR chReplace;
4799 TCHAR szFilter[256];
4800 blnr IsOk;
4801
4802 szDirName[0] = (TCHAR)('\0');
4803 szFile[0] = (TCHAR)('\0');
4804 _tcscpy(szFilter,
4805 TEXT("Disk images|*.dsk;*.HF?;*.IMG;*.IMA;*.IMAGE")
4806 TEXT("|All files (*.*)|*.*|\0"));
4807
4808 cbString = _tcslen(szFilter);
4809
4810 chReplace = szFilter[cbString - 1];
4811
4812 for (i = 0; szFilter[i] != (TCHAR)('\0'); ++i)
4813 {
4814 if (szFilter[i] == chReplace) {
4815 szFilter[i] = (TCHAR)('\0');
4816 }
4817 }
4818
4819 memset(&ofn, 0, sizeof(OPENFILENAME));
4820
4821 ofn.lStructSize = sizeof(OPENFILENAME);
4822 ofn.hwndOwner = MainWnd;
4823 ofn.lpstrFilter = szFilter;
4824 ofn.nFilterIndex = 2;
4825 ofn.lpstrFile= szFile;
4826 ofn.nMaxFile = sizeof(szFile);
4827#if ! UseWinCE
4828 ofn.lpstrFileTitle = szFileTitle;
4829 ofn.nMaxFileTitle = sizeof(szFileTitle);
4830#endif
4831 ofn.lpstrInitialDir = szDirName;
4832 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST
4833 | OFN_HIDEREADONLY;
4834
4835 MyBeginDialog();
4836 IsOk = GetOpenFileName(&ofn);
4837 MyEndDialog();
4838
4839 if(! IsOk) {
4840 /* report error */
4841#if UseWinCE
4842 if (szFile[0]) {
4843 char wMsg[1024];
4844 sprintf(wMsg, "Couldn't open %ls", szFile);
4845 MacMsg("error", wMsg, falseblnr);
4846 }
4847#endif
4848 } else {
4849 (void) InsertDiskOrAlias(ofn.lpstrFile,
4850 trueblnr, falseblnr);
4851 }
4852
4853#if UseWinCE
4854 CtrlMode = falseblnr;
4855#endif
4856}
4857
4858LOCALFUNC blnr LoadInitialImageFromName(char *ImageName)
4859{
4860 TCHAR ImageFile[_MAX_PATH];
4861
4862 if (GetAppDir(ImageFile))
4863 if (ResolveNamedChildFile(ImageFile, ImageName))
4864 if (Sony_Insert1(ImageFile, trueblnr))
4865 {
4866 return trueblnr;
4867 }
4868 return falseblnr;
4869}
4870
4871LOCALFUNC blnr Sony_InsertIth(int i)
4872{
4873 blnr v;
4874
4875 if ((i > 9) || ! FirstFreeDisk(nullpr)) {
4876 v = falseblnr;
4877 } else {
4878 char s[] = "disk?.dsk";
4879
4880 s[4] = '0' + i;
4881
4882 /* stop on first error (including file not found) */
4883 v = LoadInitialImageFromName(s);
4884 }
4885
4886 return v;
4887}
4888
4889LOCALFUNC blnr LoadInitialImages(void)
4890{
4891 if (! AnyDiskInserted()) {
4892 int i;
4893
4894 for (i = 1; Sony_InsertIth(i); ++i) {
4895 /* stop on first error (including file not found) */
4896 }
4897 }
4898
4899 return trueblnr;
4900}
4901
4902#if UseActvFile
4903
4904#define ActvCodeFileName "act_1"
4905
4906LOCALFUNC tMacErr ActvCodeFileLoad(ui3p p)
4907{
4908 TCHAR pathName[_MAX_PATH];
4909 DWORD BytesRead;
4910 HANDLE refnum = INVALID_HANDLE_VALUE;
4911 blnr IsOk = falseblnr;
4912
4913 if (MyGetAppDataPath(pathName, FALSE))
4914 if (ResolveNamedChildDir(pathName, "Gryphel"))
4915 if (ResolveNamedChildDir(pathName, "mnvm_act"))
4916 if (ResolveNamedChildFile(pathName, ActvCodeFileName))
4917 {
4918 refnum = CreateFile(
4919 pathName, /* pointer to name of the file */
4920 GENERIC_READ, /* access (read-write) mode */
4921 FILE_SHARE_READ, /* share mode */
4922 NULL, /* pointer to security descriptor */
4923 OPEN_EXISTING, /* how to create */
4924 FILE_ATTRIBUTE_NORMAL, /* file attributes */
4925 NULL /* handle to file with attributes to copy */
4926 );
4927 if (INVALID_HANDLE_VALUE == refnum) {
4928 /* report error */
4929 } else {
4930 if (SetFilePointer(
4931 refnum, /* handle of file */
4932 0, /* number of bytes to move file pointer */
4933 nullpr,
4934 /* address of high-order word of distance to move */
4935 FILE_BEGIN /* how to move */
4936 ) != 0)
4937 {
4938 /* report error */
4939 } else if (! ReadFile(refnum, /* handle of file to read */
4940 (LPVOID)p, /* address of buffer that receives data */
4941 (DWORD)ActvCodeFileLen, /* number of bytes to read */
4942 &BytesRead, /* address of number of bytes read */
4943 nullpr) /* address of structure for data */
4944 || ((ui5b)BytesRead != ActvCodeFileLen))
4945 {
4946 /* report error */
4947 } else {
4948 IsOk = trueblnr;
4949 }
4950 (void) CloseHandle(refnum);
4951 }
4952 }
4953
4954 return IsOk ? mnvm_noErr : mnvm_miscErr;
4955}
4956
4957LOCALFUNC blnr NewNamedChildFile(LPTSTR pathName, char *Child)
4958{
4959 blnr directory;
4960 blnr IsOk = falseblnr;
4961 tMacErr err = ResolveNamedChild(pathName, Child, &directory);
4962
4963 if (mnvm_noErr == err) {
4964 IsOk = ! directory;
4965 } else if (mnvm_fnfErr == err) {
4966 IsOk = trueblnr;
4967 }
4968
4969 return IsOk;
4970}
4971
4972LOCALFUNC tMacErr ActvCodeFileSave(ui3p p)
4973{
4974 TCHAR pathName[_MAX_PATH];
4975 DWORD BytesWritten;
4976 HANDLE refnum = INVALID_HANDLE_VALUE;
4977 blnr IsOk = falseblnr;
4978
4979 if (MyGetAppDataPath(pathName, TRUE))
4980 if (MakeNamedChildDir(pathName, "Gryphel"))
4981 if (MakeNamedChildDir(pathName, "mnvm_act"))
4982 if (NewNamedChildFile(pathName, ActvCodeFileName))
4983 {
4984 refnum = CreateFile(
4985 pathName, /* pointer to name of the file */
4986 GENERIC_READ + GENERIC_WRITE, /* access (read-write) mode */
4987 0, /* share mode */
4988 NULL, /* pointer to security descriptor */
4989 CREATE_ALWAYS, /* how to create */
4990 FILE_ATTRIBUTE_NORMAL, /* file attributes */
4991 NULL /* handle to file with attributes to copy */
4992 );
4993 if (INVALID_HANDLE_VALUE == refnum) {
4994 /* report error */
4995 } else {
4996 if (SetFilePointer(
4997 refnum, /* handle of file */
4998 0, /* number of bytes to move file pointer */
4999 nullpr,
5000 /* address of high-order word of distance to move */
5001 FILE_BEGIN /* how to move */
5002 ) != 0)
5003 {
5004 /* report error */
5005 } else if (! WriteFile(refnum, /* handle of file to read */
5006 (LPVOID)p, /* address of buffer that receives data */
5007 (DWORD)ActvCodeFileLen, /* number of bytes to read */
5008 &BytesWritten, /* address of number of bytes read */
5009 nullpr) /* address of structure for data */
5010 || ((ui5b)BytesWritten != ActvCodeFileLen))
5011 {
5012 /* report error */
5013 } else {
5014 IsOk = trueblnr;
5015 }
5016 (void) CloseHandle(refnum);
5017 if (! IsOk) {
5018 (void) DeleteFile(pathName);
5019 }
5020 }
5021 }
5022
5023 return IsOk ? mnvm_noErr : mnvm_miscErr;
5024}
5025
5026#endif /* UseActvFile */
5027
5028#if IncludeSonyNew
5029LOCALFUNC blnr WriteZero(HANDLE refnum, ui5b L)
5030{
5031 if (SetFilePointer(
5032 refnum, /* handle of file */
5033 0, /* number of bytes to move file pointer */
5034 nullpr, /* address of high-order word of distance to move */
5035 FILE_BEGIN /* how to move */
5036 ) != 0)
5037 {
5038 return falseblnr;
5039 } else {
5040#define ZeroBufferSize 2048
5041 ui5b i;
5042 ui3b buffer[ZeroBufferSize];
5043 DWORD BytesWritten;
5044
5045 memset(&buffer, 0, ZeroBufferSize);
5046
5047 while (L > 0) {
5048 i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
5049 if (! WriteFile(refnum, /* handle of file to read */
5050 (LPVOID)buffer,
5051 /* address of buffer that receives data */
5052 (DWORD)i, /* number of bytes to read */
5053 &BytesWritten, /* address of number of bytes read */
5054 nullpr) /* address of structure for data */
5055 || ((ui5b)BytesWritten != i))
5056 {
5057 return falseblnr;
5058 }
5059 L -= i;
5060 }
5061 return trueblnr;
5062 }
5063}
5064#endif
5065
5066#define MaxSavePathSize MAX_PATH
5067
5068#if IncludeSonyNew
5069LOCALPROC MakeNewDisk0(ui5b L, LPTSTR pathName)
5070{
5071 blnr IsOk = falseblnr;
5072 HANDLE newrefNum;
5073
5074 IsOk = falseblnr;
5075 newrefNum = CreateFile(
5076 pathName, /* pointer to name of the file */
5077 GENERIC_READ + GENERIC_WRITE, /* access (read-write) mode */
5078 0, /* share mode */
5079 NULL, /* pointer to security descriptor */
5080 CREATE_ALWAYS, /* how to create */
5081 FILE_ATTRIBUTE_NORMAL, /* file attributes */
5082 NULL /* handle to file with attributes to copy */
5083 );
5084 if (newrefNum == INVALID_HANDLE_VALUE) {
5085 /* report error */
5086 } else {
5087 if (SetFilePointer(
5088 newrefNum, /* handle of file */
5089 L, /* number of bytes to move file pointer */
5090 nullpr,
5091 /* address of high-order word of distance to move */
5092 FILE_BEGIN /* how to move */
5093 ) != L)
5094 {
5095 /* report error */
5096 } else if (! SetEndOfFile(newrefNum)) {
5097 /* report error */
5098 } else if (! WriteZero(newrefNum, L)) {
5099 /* report error */
5100 } else {
5101 IsOk =
5102 Sony_Insert0(newrefNum, falseblnr, pathName);
5103 newrefNum = INVALID_HANDLE_VALUE;
5104 }
5105 if (INVALID_HANDLE_VALUE != newrefNum) {
5106 (void) CloseHandle(newrefNum);
5107 }
5108 if (! IsOk) {
5109 (void) DeleteFile(pathName);
5110 }
5111 }
5112}
5113#endif
5114
5115#if IncludeSonyNew
5116LOCALPROC MakeNewDisk(ui5b L, HGLOBAL NewDiskNameDat)
5117{
5118#if SaveDialogEnable
5119 OPENFILENAME ofn;
5120 blnr IsOk = falseblnr;
5121 TCHAR szFile[MaxSavePathSize];
5122 TCHAR szFileTitle[MaxSavePathSize];
5123
5124 memset(&ofn, 0, sizeof(OPENFILENAME));
5125 szFile[0] = 0;
5126 szFileTitle[0] = 0;
5127
5128#if IncludeSonyGetName
5129 if (NewDiskNameDat != NULL) {
5130 LPTSTR p = GlobalLock(NewDiskNameDat);
5131 if (p != NULL) {
5132 _tcscpy(szFile, p);
5133 (void) GlobalUnlock(NewDiskNameDat);
5134 }
5135 } else
5136#endif
5137 {
5138 NativeStrFromCStr(szFile, "untitled", falseblnr);
5139 }
5140
5141 ofn.lStructSize = sizeof(OPENFILENAME);
5142 ofn.lpstrFile = szFile;
5143 ofn.hwndOwner = MainWnd;
5144 /* ofn.lpstrFilter = "All\0*.*\0Text\0*.txt\0Datafile\0*.dsk\0"; */
5145 /* ofn.lpstrFilter = NULL; */ /* szFilter */
5146 ofn.nMaxFile = MaxSavePathSize;
5147 ofn.lpstrFileTitle = szFileTitle;
5148 ofn.nMaxFileTitle = MaxSavePathSize;
5149 ofn.lpstrInitialDir = NULL;
5150 ofn.Flags = OFN_OVERWRITEPROMPT + OFN_HIDEREADONLY;
5151 /* + OFN_SHOWHELP */
5152
5153 MyBeginDialog();
5154 IsOk = GetSaveFileName(&ofn);
5155 MyEndDialog();
5156
5157 if (! IsOk) {
5158 /* report error */
5159 } else {
5160 MakeNewDisk0(L, ofn.lpstrFile);
5161 }
5162#else /* SaveDialogEnable */
5163 TCHAR pathName[MaxSavePathSize];
5164
5165 if (GetAppDir(pathName))
5166 if (MakeNamedChildDir(pathName, "out"))
5167 {
5168 blnr directory;
5169 LPTSTR p = GlobalLock(NewDiskNameDat);
5170
5171 if (p != NULL) {
5172 tMacErr err = ResolveNamedChild0(pathName, p,
5173 &directory);
5174
5175 if (mnvm_fnfErr == err) {
5176 err = mnvm_noErr;
5177 } else if (mnvm_noErr == err) {
5178 if (directory) {
5179 err = mnvm_miscErr;
5180 }
5181 }
5182
5183 if (mnvm_noErr == err) {
5184 MakeNewDisk0(L, pathName);
5185 }
5186
5187 (void) GlobalUnlock(NewDiskNameDat);
5188 }
5189 }
5190#endif /* SaveDialogEnable */
5191}
5192#endif
5193
5194LOCALFUNC blnr LoadMacRom(void)
5195{
5196 TCHAR ROMFile[_MAX_PATH];
5197 blnr IsOk = falseblnr;
5198
5199 if (GetAppDir(ROMFile))
5200 if (ResolveNamedChildFile(ROMFile, RomFileName))
5201 {
5202 IsOk = trueblnr;
5203 }
5204
5205 if (! IsOk) {
5206 if (MyGetAppDataPath(ROMFile, FALSE))
5207 if (ResolveNamedChildDir(ROMFile, "Gryphel"))
5208 if (ResolveNamedChildDir(ROMFile, "mnvm_rom"))
5209 if (ResolveNamedChildFile(ROMFile, RomFileName))
5210 {
5211 IsOk = trueblnr;
5212 }
5213
5214 }
5215
5216 if (IsOk) {
5217 IsOk = LoadMacRomFromPath(ROMFile);
5218 }
5219
5220 return trueblnr;
5221}
5222
5223#if InstallFileIcons
5224LOCALPROC MySetRegKey(HKEY hKeyRoot,
5225 LPTSTR strRegKey, LPTSTR strRegValue)
5226{
5227 HKEY RegKey;
5228 DWORD dwDisposition;
5229
5230 if (ERROR_SUCCESS == RegCreateKeyEx(hKeyRoot, strRegKey, 0, NULL,
5231 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
5232 NULL, &RegKey, &dwDisposition))
5233 {
5234 RegSetValueEx(RegKey, NULL, 0, REG_SZ,
5235 (CONST BYTE *)strRegValue,
5236 (DWORD)((_tcslen(strRegValue) + 1) * sizeof(TCHAR)));
5237 RegCloseKey(RegKey);
5238 }
5239}
5240
5241LOCALPROC RegisterShellFileType(LPTSTR AppPath, LPTSTR strFilterExt,
5242 LPTSTR strFileTypeId, LPTSTR strFileTypeName,
5243 LPTSTR strIconId, blnr CanOpen)
5244{
5245 TCHAR strRegKey[_MAX_PATH];
5246 TCHAR strRegValue[_MAX_PATH + 2];
5247 /* extra room for ","{strIconId} */
5248
5249 MySetRegKey(HKEY_CLASSES_ROOT, strFileTypeId, strFileTypeName);
5250 MySetRegKey(HKEY_CLASSES_ROOT, strFilterExt, strFileTypeId);
5251
5252 _tcscpy(strRegKey, strFileTypeId);
5253 _tcscat(strRegKey, TEXT("\\DefaultIcon"));
5254 _tcscpy(strRegValue, TEXT("\""));
5255 _tcscat(strRegValue, AppPath);
5256 _tcscat(strRegValue, TEXT("\","));
5257 _tcscat(strRegValue, strIconId);
5258 MySetRegKey(HKEY_CLASSES_ROOT, strRegKey, strRegValue);
5259
5260 if (CanOpen) {
5261 _tcscpy(strRegKey, strFileTypeId);
5262 _tcscat(strRegKey, TEXT("\\shell\\open\\command"));
5263 _tcscpy(strRegValue, TEXT("\""));
5264 _tcscat(strRegValue, AppPath);
5265 _tcscat(strRegValue, TEXT("\" \"%1\""));
5266 MySetRegKey(HKEY_CLASSES_ROOT, strRegKey, strRegValue);
5267 }
5268}
5269
5270LOCALFUNC blnr RegisterInRegistry(void)
5271{
5272 TCHAR AppPath[_MAX_PATH];
5273
5274 GetModuleFileName(NULL, AppPath, _MAX_PATH);
5275#if 0
5276 GetShortPathName(AppPath, AppPath, _MAX_PATH);
5277#endif
5278
5279 RegisterShellFileType(AppPath, TEXT(".rom"), TEXT("minivmac.rom"),
5280 TEXT("Mini vMac ROM Image"), TEXT("1"), falseblnr);
5281 RegisterShellFileType(AppPath, TEXT(".dsk"), TEXT("minivmac.dsk"),
5282 TEXT("Mini vMac Disk Image"), TEXT("2"), trueblnr);
5283
5284 return trueblnr;
5285}
5286#endif
5287
5288LOCALVAR LPTSTR CommandLine;
5289
5290LOCALFUNC blnr ScanCommandLine(void)
5291{
5292 TCHAR *p = CommandLine;
5293 TCHAR *p1;
5294 TCHAR *p2;
5295 TCHAR v;
5296 size_t L;
5297
5298 v = *p;
5299 while (0 != v) {
5300 if (' ' == v) {
5301 v = *++p;
5302 } else {
5303 if ('\"' == v) {
5304 v = *++p;
5305 p1 = p;
5306 while (('\"' != v) && (0 != v)) {
5307 v = *++p;
5308 }
5309 p2 = p;
5310 if ('\"' == v) {
5311 v = *++p;
5312 }
5313 } else {
5314 p1 = p;
5315 while ((' ' != v) && (0 != v)) {
5316 v = *++p;
5317 }
5318 p2 = p;
5319 }
5320 L = p2 - p1;
5321 if (L + 1 <= _MAX_PATH) {
5322 TCHAR fileName[_MAX_PATH];
5323 TCHAR *filePtr = fileName;
5324 size_t i = L;
5325
5326 while (i > 0) {
5327 *filePtr++ = *p1++;
5328 --i;
5329 }
5330 *filePtr = (char)0;
5331
5332 if ((L > 0)
5333 && (('/' == fileName[0]) || ('-' == fileName[0])))
5334 {
5335#if 0
5336 TCHAR *p3 = &fileName[1];
5337 if (0 == _tcscmp(p3, TEXT("l"))) {
5338 SpeedValue = 0;
5339 } else
5340#endif
5341 {
5342 MacMsg(kStrBadArgTitle, kStrBadArgMessage,
5343 falseblnr);
5344 }
5345 } else {
5346 (void) InsertDiskOrAlias(fileName,
5347 falseblnr, trueblnr);
5348 }
5349 }
5350 }
5351 }
5352
5353 return trueblnr;
5354}
5355
5356#if EnableRecreateW
5357LOCALPROC CheckMagnifyAndFullScreen(void)
5358{
5359 if (
5360#if EnableMagnify
5361 (UseMagnify != WantMagnify)
5362#endif
5363#if EnableMagnify && VarFullScreen
5364 ||
5365#endif
5366#if VarFullScreen
5367 (UseFullScreen != WantFullScreen)
5368#endif
5369 )
5370 {
5371 (void) ReCreateMainWindow();
5372 }
5373}
5374#endif
5375
5376#if VarFullScreen && EnableMagnify
5377enum {
5378 kWinStateWindowed,
5379#if EnableMagnify
5380 kWinStateFullScreen,
5381#endif
5382 kNumWinStates
5383};
5384#endif
5385
5386#if VarFullScreen && EnableMagnify
5387LOCALVAR int WinMagStates[kNumWinStates];
5388#endif
5389
5390LOCALPROC ZapWinStateVars(void)
5391{
5392#if MayNotFullScreen
5393 {
5394 int i;
5395
5396 for (i = 0; i < kNumMagStates; ++i) {
5397 HavePositionWins[i] = falseblnr;
5398 }
5399 }
5400#endif
5401#if VarFullScreen && EnableMagnify
5402 {
5403 int i;
5404
5405 for (i = 0; i < kNumWinStates; ++i) {
5406 WinMagStates[i] = kMagStateAuto;
5407 }
5408 }
5409#endif
5410}
5411
5412#if VarFullScreen
5413LOCALPROC ToggleWantFullScreen(void)
5414{
5415 WantFullScreen = ! WantFullScreen;
5416
5417#if EnableMagnify
5418 {
5419 int OldWinState =
5420 UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
5421 int OldMagState =
5422 UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
5423 int NewWinState =
5424 WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
5425 int NewMagState = WinMagStates[NewWinState];
5426
5427 WinMagStates[OldWinState] = OldMagState;
5428 if (kMagStateAuto != NewMagState) {
5429 WantMagnify = (kMagStateMagnifgy == NewMagState);
5430 } else {
5431 WantMagnify = falseblnr;
5432 if (WantFullScreen) {
5433 if ((GetSystemMetrics(SM_CXSCREEN)
5434 >= vMacScreenWidth * MyWindowScale)
5435 && (GetSystemMetrics(SM_CYSCREEN)
5436 >= vMacScreenHeight * MyWindowScale)
5437 )
5438 {
5439 WantMagnify = trueblnr;
5440 }
5441 }
5442 }
5443 }
5444#endif
5445}
5446#endif
5447
5448#if EnableDragDrop
5449LOCALPROC DragFunc(HDROP hDrop)
5450{
5451 WORD n;
5452 WORD i;
5453 TCHAR a[_MAX_PATH];
5454
5455 n = DragQueryFile(hDrop, (UINT) -1, NULL, 0);
5456 for (i = 0; i < n; ++i) {
5457 if (DragQueryFile(hDrop, i, NULL, 0) < _MAX_PATH - 1) {
5458 (void) DragQueryFile(hDrop, i, a, _MAX_PATH);
5459 (void) InsertDiskOrAlias(a, trueblnr, trueblnr);
5460 }
5461 }
5462
5463 DragFinish(hDrop);
5464
5465 if (gTrueBackgroundFlag) {
5466 if (! SetForegroundWindow(MainWnd)) {
5467 /* error message here ? */
5468 }
5469
5470 WantCmdOptOnReconnect = trueblnr;
5471 }
5472}
5473#endif
5474
5475GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
5476{
5477#if MySoundEnabled
5478 SoundCheckVeryOften();
5479#endif
5480 (void) UpdateTrueEmulatedTime();
5481 return (TrueEmulatedTime == OnTrueTime);
5482}
5483
5484/* --- platform independent code can be thought of as going here --- */
5485
5486LOCALPROC LeaveBackground(void)
5487{
5488 ReconnectKeyCodes3();
5489}
5490
5491LOCALPROC EnterBackground(void)
5492{
5493 DisconnectKeyCodes3();
5494
5495#if VarFullScreen
5496 if (WantFullScreen) {
5497 ToggleWantFullScreen();
5498 }
5499#endif
5500}
5501
5502LOCALPROC LeaveSpeedStopped(void)
5503{
5504#if MySoundEnabled
5505 MySound_Start();
5506#endif
5507#if (MyTimeResolution != 0)
5508 MyTimer_Resume();
5509#endif
5510}
5511
5512LOCALPROC EnterSpeedStopped(void)
5513{
5514#if (MyTimeResolution != 0)
5515 MyTimer_Suspend();
5516#endif
5517#if MySoundEnabled
5518 MySound_Stop();
5519#endif
5520}
5521
5522LOCALPROC CheckForSavedTasks(void)
5523{
5524 /*
5525 Check for things to do that rather wouldn't
5526 have done at an awkward time.
5527 */
5528
5529 if (MyEvtQNeedRecover) {
5530 MyEvtQNeedRecover = falseblnr;
5531
5532 /* attempt cleanup, MyEvtQNeedRecover may get set again */
5533 MyEvtQTryRecoverFromFull();
5534 }
5535
5536#if EnableFSMouseMotion
5537 if (HaveMouseMotion) {
5538 MyMouseConstrain();
5539 }
5540#endif
5541
5542 if (RequestMacOff) {
5543 RequestMacOff = falseblnr;
5544 if (AnyDiskInserted()) {
5545 MacMsgOverride(kStrQuitWarningTitle,
5546 kStrQuitWarningMessage);
5547 } else {
5548 ForceMacOff = trueblnr;
5549 }
5550 }
5551
5552 if (ForceMacOff) {
5553 return;
5554 }
5555
5556 if (gTrueBackgroundFlag != gBackgroundFlag) {
5557 gBackgroundFlag = gTrueBackgroundFlag;
5558 if (gTrueBackgroundFlag) {
5559 EnterBackground();
5560 } else {
5561 LeaveBackground();
5562 }
5563 }
5564
5565 if (CurSpeedStopped != (SpeedStopped ||
5566 (gBackgroundFlag && ! RunInBackground
5567#if EnableAutoSlow && 0
5568 && (QuietSubTicks >= 4092)
5569#endif
5570 )))
5571 {
5572 CurSpeedStopped = ! CurSpeedStopped;
5573 if (CurSpeedStopped) {
5574 EnterSpeedStopped();
5575 } else {
5576 LeaveSpeedStopped();
5577 }
5578 }
5579
5580#if EnableRecreateW
5581 if (! (gTrueBackgroundFlag)) {
5582 CheckMagnifyAndFullScreen();
5583 }
5584#endif
5585
5586#if MayFullScreen
5587 if (GrabMachine != (
5588#if VarFullScreen
5589 UseFullScreen &&
5590#endif
5591 ! (gTrueBackgroundFlag || CurSpeedStopped)))
5592 {
5593 GrabMachine = ! GrabMachine;
5594 AdjustMachineGrab();
5595 }
5596#endif
5597
5598 if (gTrueBackgroundFlag) {
5599 /*
5600 wait til later
5601 */
5602 } else {
5603#if IncludeSonyNew
5604 if (vSonyNewDiskWanted) {
5605#if IncludeSonyNameNew
5606 if (vSonyNewDiskName != NotAPbuf) {
5607 HGLOBAL NewDiskNameDat;
5608 if (MacRomanTextToNativeHand(vSonyNewDiskName, trueblnr,
5609 &NewDiskNameDat))
5610 {
5611 MakeNewDisk(vSonyNewDiskSize, NewDiskNameDat);
5612 GlobalFree(NewDiskNameDat);
5613 }
5614 PbufDispose(vSonyNewDiskName);
5615 vSonyNewDiskName = NotAPbuf;
5616 } else
5617#endif
5618 {
5619 MakeNewDisk(vSonyNewDiskSize, NULL);
5620 }
5621 vSonyNewDiskWanted = falseblnr;
5622 /* must be done after may have gotten disk */
5623 }
5624#endif
5625 if (RequestInsertDisk) {
5626 RequestInsertDisk = falseblnr;
5627 InsertADisk0();
5628 }
5629 }
5630
5631#if NeedRequestIthDisk
5632 if (0 != RequestIthDisk) {
5633 Sony_InsertIth(RequestIthDisk);
5634 RequestIthDisk = 0;
5635 }
5636#endif
5637
5638 if (HaveCursorHidden != (WantCursorHidden
5639 && ! (gTrueBackgroundFlag || CurSpeedStopped)))
5640 {
5641 HaveCursorHidden = ! HaveCursorHidden;
5642 if (HaveCursorHidden) {
5643 (void) ShowCursor(FALSE);
5644 } else {
5645 (void) ShowCursor(TRUE);
5646 SetCursor(LoadCursor(NULL, IDC_ARROW));
5647 }
5648 }
5649
5650 if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
5651 MacMsgDisplayOn();
5652 }
5653
5654 if (NeedWholeScreenDraw) {
5655 NeedWholeScreenDraw = falseblnr;
5656 ScreenChangedAll();
5657 }
5658}
5659
5660#if UseWinCE
5661/* Sip Status ON/OFF */
5662LOCALVAR blnr SipOn = falseblnr;
5663#endif
5664
5665LRESULT CALLBACK Win32WMProc(HWND hwnd,
5666 UINT uMessage, WPARAM wparam, LPARAM lparam);
5667
5668LRESULT CALLBACK Win32WMProc(HWND hwnd,
5669 UINT uMessage, WPARAM wparam, LPARAM lparam)
5670{
5671 switch (uMessage)
5672 {
5673 case WM_PAINT:
5674 {
5675 PAINTSTRUCT ps;
5676
5677 BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
5678#if VarFullScreen
5679 if (UseFullScreen)
5680#endif
5681#if MayFullScreen
5682 {
5683 if (! FillRect(ps.hdc,
5684 &ps.rcPaint,
5685 GetStockObject(BLACK_BRUSH)))
5686 {
5687 /* ReportGetLastError(); */
5688 }
5689 }
5690#endif
5691 if (MainWnd == hwnd) {
5692 Screen_DrawAll();
5693 }
5694 EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
5695 }
5696 break;
5697
5698 case WM_KEYDOWN:
5699 case WM_SYSKEYDOWN:
5700#if UseWinCE
5701 SipOn = falseblnr;
5702
5703 {
5704 SIPINFO r;
5705
5706 memset(&r, 0 , sizeof(SIPINFO));
5707 r.cbSize = sizeof(SIPINFO);
5708 if (SipGetInfo(&r)) {
5709 SipOn = 0 != (r.fdwFlags & SIPF_ON);
5710 }
5711 }
5712
5713 if (wparam == 0xAE) {
5714 break;
5715 } else if ((! SipOn) && (wparam == VK_RETURN)) {
5716 break;
5717 } else if ((! SipOn)
5718 && (wparam >= VK_LEFT) && (wparam <= VK_DOWN))
5719 {
5720 break;
5721 } else if (wparam == VK_CONTROL && CtrlMode) {
5722 DoVKcode0(wparam, falseblnr);
5723 CtrlMode = falseblnr;
5724 break;
5725 } else if (wparam == VK_CONTROL) {
5726 DoVKcode0(wparam, trueblnr);
5727 CtrlMode = trueblnr;
5728 break;
5729 }
5730#endif
5731 if (! TestBit(lparam, 30)) { /* ignore repeats */
5732 DoVKcode(wparam, lparam >> 24, trueblnr);
5733 }
5734
5735#if UseWinCE
5736 return TRUE;
5737 /*
5738 So that hardware keys won't be
5739 processed by the default handler
5740 */
5741#endif
5742
5743 break;
5744 case WM_KEYUP:
5745 case WM_SYSKEYUP:
5746#if UseWinCE
5747 SipOn = falseblnr;
5748
5749 {
5750 SIPINFO r;
5751
5752 memset(&r, 0 , sizeof(SIPINFO));
5753 r.cbSize = sizeof(SIPINFO);
5754 if (SipGetInfo(&r)) {
5755 SipOn = 0 != (r.fdwFlags & SIPF_ON);
5756 }
5757 }
5758
5759 if (wparam == 0xAE) { /* to hide SoftInput panel */
5760 SipShowIM(SIPF_OFF);
5761 break;
5762 } else if ((! SipOn) && (wparam == VK_RETURN)) {
5763 /* DPad Action to show SIP */
5764 /* Show SoftInput Panel */
5765 SipShowIM(SIPF_ON);
5766 break;
5767 } else if ((! SipOn)
5768 && (wparam >= VK_LEFT) && (wparam <= VK_DOWN))
5769 {
5770 switch (wparam) {
5771 case VK_LEFT:
5772 if (ViewHStart < (ViewHSize / 2)) {
5773 ViewHStart = 0;
5774 } else {
5775 ViewHStart -= (ViewHSize / 2);
5776 }
5777 break;
5778 case VK_UP:
5779 if (ViewVStart < (ViewVSize / 2)) {
5780 ViewVStart = 0;
5781 } else {
5782 ViewVStart -= (ViewVSize / 2);
5783 }
5784 break;
5785 case VK_RIGHT:
5786 ViewHStart += (ViewHSize / 2);
5787 if (ViewHStart >= (vMacScreenWidth - ViewHSize))
5788 {
5789 ViewHStart = vMacScreenWidth - ViewHSize;
5790 }
5791 break;
5792 case VK_DOWN:
5793 ViewVStart += (ViewVSize / 2);
5794 if (ViewVStart
5795 >= (vMacScreenHeight - ViewVSize))
5796 {
5797 ViewVStart = vMacScreenHeight - ViewVSize;
5798 }
5799 break;
5800 }
5801 Screen_DrawAll();
5802 } else
5803 if (wparam == VK_CONTROL && CtrlMode) {
5804 break;
5805 }
5806#endif
5807 DoVKcode(wparam, lparam >> 24, falseblnr);
5808
5809#if UseWinCE
5810 return TRUE;
5811 /*
5812 So that hardware keys won't be
5813 processed by the default handler
5814 */
5815#endif
5816
5817 break;
5818#if ItnlKyBdFix && ! UseWinCE
5819 case WM_INPUTLANGCHANGE:
5820 MyCheckKeyboardLayout();
5821 return TRUE;
5822 break;
5823#endif
5824
5825 case WM_CLOSE:
5826 RequestMacOff = trueblnr;
5827 break;
5828#if ! UseWinCE
5829 case WM_QUERYENDSESSION:
5830 if (AnyDiskInserted()) {
5831 RequestMacOff = trueblnr;
5832 return FALSE;
5833 } else {
5834 return TRUE;
5835 }
5836 break;
5837#endif
5838 case WM_ACTIVATE:
5839 if (MainWnd == hwnd) {
5840 gTrueBackgroundFlag = (LOWORD(wparam) == WA_INACTIVE);
5841 }
5842 break;
5843 case WM_COMMAND:
5844 switch(LOWORD(wparam))
5845 {
5846 case ID_FILE_INSERTDISK1:
5847 RequestInsertDisk = trueblnr;
5848 break;
5849 case ID_FILE_QUIT:
5850 RequestMacOff = trueblnr;
5851 break;
5852 case ID_SPECIAL_MORECOMMANDS:
5853 DoMoreCommandsMsg();
5854 break;
5855 case ID_HELP_ABOUT:
5856 DoAboutMsg();
5857 break;
5858 }
5859 break;
5860 case WM_MOVE:
5861 WndX = (si4b) LOWORD(lparam);
5862 WndY = (si4b) HIWORD(lparam);
5863 break;
5864 case WM_SYSCHAR:
5865 case WM_CHAR:
5866 /* prevent any further processing */
5867 break;
5868 case WM_LBUTTONDOWN:
5869 case WM_RBUTTONDOWN:
5870 MousePositionNotify(LOWORD (lparam), HIWORD (lparam));
5871 SetCurMouseButton(trueblnr);
5872 break;
5873 case WM_LBUTTONUP:
5874 case WM_RBUTTONUP:
5875 MousePositionNotify(LOWORD (lparam), HIWORD (lparam));
5876 SetCurMouseButton(falseblnr);
5877 break;
5878 case WM_MOUSEMOVE:
5879#if UseWinCE
5880 MousePositionNotify(LOWORD (lparam), HIWORD (lparam));
5881#endif
5882 /* windows may have messed up cursor */
5883 /*
5884 there is no notification when the mouse moves
5885 outside the window, and the cursor is automatically
5886 changed
5887 */
5888 if (! HaveCursorHidden) {
5889 /* SetCursor(LoadCursor(NULL, IDC_ARROW)); */
5890 }
5891 break;
5892#if EnableDragDrop
5893 case WM_CREATE:
5894 DragAcceptFiles(hwnd, TRUE);
5895 break;
5896 case WM_DROPFILES:
5897 DragFunc((HDROP) wparam);
5898 break;
5899 case WM_DESTROY:
5900 DragAcceptFiles(hwnd, FALSE);
5901 break;
5902#endif
5903 default:
5904 return DefWindowProc(hwnd, uMessage, wparam, lparam);
5905 }
5906 return 0;
5907}
5908
5909LOCALFUNC blnr RegisterOurClass(void)
5910{
5911 WNDCLASS wc;
5912
5913 wc.style = CS_HREDRAW | CS_VREDRAW
5914#if ! UseWinCE
5915 | CS_OWNDC
5916#endif
5917 ;
5918 wc.lpfnWndProc = (WNDPROC)Win32WMProc;
5919 wc.cbClsExtra = 0;
5920 wc.cbWndExtra = 0;
5921 wc.hInstance = AppInstance;
5922 wc.hIcon = LoadIcon(AppInstance, MAKEINTRESOURCE(IDI_VMAC));
5923 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
5924 wc.hbrBackground = GetStockObject(BLACK_BRUSH);
5925 wc.lpszMenuName = NULL;
5926 wc.lpszClassName = WndClassName;
5927
5928 if (! RegisterClass(&wc)) {
5929 MacMsg("RegisterClass failed",
5930 "Sorry, Mini vMac encountered errors"
5931 " and cannot continue.", trueblnr);
5932 return falseblnr;
5933 } else {
5934 return trueblnr;
5935 }
5936}
5937
5938LOCALPROC WaitForTheNextEvent(void)
5939{
5940 MSG msg;
5941
5942 if (-1 != GetMessage(&msg, NULL, 0, 0)) {
5943 DispatchMessage(&msg);
5944 }
5945}
5946
5947LOCALPROC CheckForSystemEvents(void)
5948{
5949 MSG msg;
5950 ui3r i = 0;
5951
5952 while ((i < 32) && (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))) {
5953 DispatchMessage(&msg);
5954 ++i;
5955 }
5956}
5957
5958GLOBALOSGLUPROC WaitForNextTick(void)
5959{
5960label_retry:
5961 CheckForSystemEvents();
5962 CheckForSavedTasks();
5963
5964 if (ForceMacOff) {
5965 return;
5966 }
5967
5968 if (CurSpeedStopped) {
5969 DoneWithDrawingForTick();
5970 WaitForTheNextEvent();
5971 goto label_retry;
5972 }
5973
5974 if (ExtraTimeNotOver()) {
5975 Sleep(NextIntTime - LastTime);
5976 goto label_retry;
5977 }
5978
5979 if (CheckDateTime()) {
5980#if MySoundEnabled
5981 MySound_SecondNotify();
5982#endif
5983#if EnableDemoMsg
5984 DemoModeSecondNotify();
5985#endif
5986 }
5987
5988 if (! (gBackgroundFlag)) {
5989#if ! UseWinCE
5990 CheckMouseState();
5991#endif
5992
5993#if EnableGrabSpecialKeys
5994 CheckForLostKeyUps();
5995#endif
5996 }
5997
5998 OnTrueTime = TrueEmulatedTime;
5999
6000#if dbglog_TimeStuff
6001 dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
6002#endif
6003}
6004
6005#if UseWinCE
6006LOCALFUNC blnr Init_ChangeOrientation(void)
6007{
6008 DEVMODE dm;
6009
6010 /* initialize the DEVMODE structure */
6011 ZeroMemory(&dm, sizeof (dm));
6012 dm.dmSize = sizeof (dm);
6013
6014 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
6015
6016 /* Backup old values */
6017 oldOrientation = dm.dmOrientation;
6018 oldDisplayOrientation = dm.dmDisplayOrientation;
6019
6020
6021 /* Hide SIP (you can never tell...) */
6022 SipShowIM(SIPF_OFF);
6023
6024 /* Switch to Landscape mode if possible */
6025 dm.dmOrientation = DMORIENT_LANDSCAPE;
6026 dm.dmDisplayOrientation = DMDO_90;
6027 dm.dmFields = DM_ORIENTATION | DM_DISPLAYORIENTATION;
6028 (void) ChangeDisplaySettingsEx(NULL, &dm, NULL, 0, 0);
6029 /*
6030 if (ChangeDisplaySettingsEx(NULL, &dm, NULL, 0, 0) !=
6031 DISP_CHANGE_SUCCESSFUL)
6032 {
6033 MacMsg ("warning",
6034 "Couldn't switch to Landscape mode.", falseblnr);
6035 }
6036 */
6037
6038 return trueblnr;
6039}
6040#endif
6041
6042#if UseWinCE
6043LOCALPROC Uninit_ChangeOrientation(void)
6044{
6045 DEVMODE dm;
6046
6047 /* Restore old display orientation */
6048 ZeroMemory(&dm, sizeof (dm));
6049 dm.dmSize = sizeof(dm);
6050
6051 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
6052
6053 dm.dmOrientation = oldOrientation;
6054 dm.dmDisplayOrientation = oldDisplayOrientation;
6055 dm.dmFields = DM_ORIENTATION | DM_DISPLAYORIENTATION;
6056
6057 ChangeDisplaySettingsEx(NULL, &dm, 0, 0, 0);
6058}
6059#endif
6060
6061
6062/* ** code for handling hardware keys in Pocket PC devices ** */
6063
6064#if UseWinCE
6065typedef BOOL (__stdcall *UnregisterFunc1Proc)(UINT, UINT);
6066LOCALVAR HINSTANCE hCoreDLL = NULL;
6067#endif
6068
6069#if UseWinCE
6070LOCALFUNC blnr InitHotKeys(void)
6071{
6072 UnregisterFunc1Proc procUndergisterFunc;
6073 int i;
6074
6075 hCoreDLL = LoadLibrary(TEXT("coredll.dll"));
6076 if (! hCoreDLL) {
6077 MacMsg ("Fatal", "Could not load coredll.dll", trueblnr);
6078 } else {
6079 procUndergisterFunc =
6080 (UnregisterFunc1Proc) GetProcAddress(hCoreDLL,
6081 TEXT("UnregisterFunc1"));
6082 if (! procUndergisterFunc) {
6083 MacMsg ("Fatal",
6084 "Could not get UnregisterFunc1 procedure", trueblnr);
6085 } else {
6086 for (i = 0xc1; i <= 0xcf; ++i) {
6087 procUndergisterFunc(MOD_WIN, i);
6088 RegisterHotKey(MainWnd, i, MOD_WIN, i);
6089 }
6090 }
6091 }
6092 return trueblnr;
6093}
6094#endif
6095
6096#if UseWinCE
6097LOCALPROC UninitHotKeys(void)
6098{
6099 if (! hCoreDLL) {
6100 FreeLibrary(hCoreDLL);
6101 }
6102}
6103#endif
6104
6105#include "PROGMAIN.h"
6106
6107/* ************************ */
6108
6109LOCALPROC ZapOSGLUVars(void)
6110{
6111 InitDrives();
6112 ZapWinStateVars();
6113}
6114
6115LOCALPROC ReserveAllocAll(void)
6116{
6117#if dbglog_HAVE
6118 dbglog_ReserveAlloc();
6119#endif
6120 ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
6121 ReserveAllocOneBlock(&screencomparebuff,
6122 vMacScreenNumBytes, 5, trueblnr);
6123#if UseControlKeys
6124 ReserveAllocOneBlock(&CntrlDisplayBuff,
6125 vMacScreenNumBytes, 5, falseblnr);
6126#endif
6127#if EnableScalingBuff
6128 {
6129 ui5r n = vMacScreenMonoNumBytes
6130#if EnableMagnify
6131 * MyWindowScale * MyWindowScale
6132#endif
6133 ;
6134#if 1 == vMacScreenDepth
6135 if (vMacScreenNumBytes * 2 > n) {
6136 n = vMacScreenNumBytes * 2;
6137 }
6138#elif vMacScreenDepth >= 4
6139 if (vMacScreenNumBytes > n) {
6140 n = vMacScreenNumBytes;
6141 }
6142#endif
6143 ReserveAllocOneBlock(&ScalingBuff, n, 5, falseblnr);
6144 }
6145#endif
6146#if MySoundEnabled
6147 ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
6148 dbhBufferSize, 5, falseblnr);
6149#endif
6150
6151 EmulationReserveAlloc();
6152}
6153
6154LOCALFUNC blnr AllocMyMemory(void)
6155{
6156 uimr n;
6157 blnr IsOk = falseblnr;
6158
6159 ReserveAllocOffset = 0;
6160 ReserveAllocBigBlock = nullpr;
6161 ReserveAllocAll();
6162 n = ReserveAllocOffset;
6163 ReserveAllocBigBlock =
6164 (ui3p)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, n);
6165 if (NULL == ReserveAllocBigBlock) {
6166 MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
6167 } else {
6168 ReserveAllocOffset = 0;
6169 ReserveAllocAll();
6170 if (n != ReserveAllocOffset) {
6171 /* oops, program error */
6172 } else {
6173 IsOk = trueblnr;
6174 }
6175 }
6176
6177 return IsOk;
6178}
6179
6180LOCALPROC UnallocMyMemory(void)
6181{
6182 if (nullpr != ReserveAllocBigBlock) {
6183 if (GlobalFree(ReserveAllocBigBlock) != NULL) {
6184 MacMsg("error", "GlobalFree failed", falseblnr);
6185 }
6186 }
6187}
6188
6189LOCALFUNC blnr InitOSGLU(void)
6190{
6191 if (AllocMyMemory())
6192#if dbglog_HAVE
6193 if (dbglog_open())
6194#endif
6195 if (RegisterOurClass())
6196 if (ScanCommandLine())
6197 if (LoadInitialImages())
6198#if InstallFileIcons
6199 if (RegisterInRegistry())
6200#endif
6201 if (LoadMacRom())
6202#if UseActvCode
6203 if (ActvCodeInit())
6204#endif
6205#if UseWinCE
6206 if (Init_ChangeOrientation())
6207#endif
6208 if (ReCreateMainWindow())
6209 if (InitWinKey2Mac())
6210 if (InitTheCursor())
6211#if UseWinCE
6212 if (InitHotKeys())
6213#endif
6214 if (Init60thCheck())
6215#if EmLocalTalk
6216 if (EntropyGather())
6217 if (InitLocalTalk())
6218#endif
6219 if (WaitForRom())
6220 {
6221 return trueblnr;
6222 }
6223 return falseblnr;
6224}
6225
6226LOCALPROC UnInitOSGLU(void)
6227{
6228#if (MyTimeResolution != 0)
6229 MyTimer_Suspend();
6230#endif
6231 MyMouseCaptureSet(falseblnr);
6232
6233 if (MacMsgDisplayed) {
6234 MacMsgDisplayOff();
6235 }
6236
6237#if EmLocalTalk
6238 UnInitLocalTalk();
6239#endif
6240
6241#if MayFullScreen
6242 UnGrabTheMachine();
6243#endif
6244#if MySoundEnabled
6245 MySound_Stop();
6246#endif
6247#if IncludePbufs
6248 UnInitPbufs();
6249#endif
6250 UnInitDrives();
6251
6252 ForceShowCursor();
6253#if UseWinCE
6254 Uninit_ChangeOrientation();
6255 UninitHotKeys();
6256#endif
6257
6258#if EnableShellLinks
6259 MyUninitCOM();
6260#endif
6261
6262 if (! gTrueBackgroundFlag) {
6263 CheckSavedMacMsg();
6264 }
6265
6266 DisposeMainWindow();
6267
6268#if dbglog_HAVE
6269 dbglog_close();
6270#endif
6271
6272 UnallocMyMemory();
6273}
6274
6275int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
6276 LPTSTR lpCmdLine, int nCmdShow)
6277{
6278 UnusedParam(hPrevInstance);
6279 AppInstance = hInstance;
6280 CmdShow = nCmdShow;
6281 CommandLine = lpCmdLine;
6282
6283 GetWndTitle();
6284#if UseWinCE
6285 if (AlreadyRunningCheck()) {
6286 return 0;
6287 }
6288#endif
6289
6290 ZapOSGLUVars();
6291 if (InitOSGLU()) {
6292 ProgramMain();
6293 }
6294 UnInitOSGLU();
6295
6296 return(0);
6297}
6298
6299#endif /* WantOSGLUWIN */