this repo has no description
1/*
2 OSGLUXWN.c
3
4 Copyright (C) 2009 Michael Hanni, Christian Bauer,
5 Stephan Kochen, Paul C. Pratt, and others
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 X WiNdow system
20
21 All operating system dependent code for the
22 X Window System should go here.
23
24 This code is descended from Michael Hanni's X
25 port of vMac, by Philip Cummins.
26 I learned more about how X programs work by
27 looking at other programs such as Basilisk II,
28 the UAE Amiga Emulator, Bochs, QuakeForge,
29 DooM Legacy, and the FLTK. A few snippets
30 from them are used here.
31
32 Drag and Drop support is based on the specification
33 "XDND: Drag-and-Drop Protocol for the X Window System"
34 developed by John Lindal at New Planet Software, and
35 looking at included examples, one by Paul Sheer.
36*/
37
38#include "OSGCOMUI.h"
39#include "OSGCOMUD.h"
40
41#ifdef WantOSGLUXWN
42
43/* --- some simple utilities --- */
44
45GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
46{
47 (void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
48}
49
50/* --- control mode and internationalization --- */
51
52#define NeedCell2PlainAsciiMap 1
53
54#include "INTLCHAR.h"
55
56
57LOCALVAR char *d_arg = NULL;
58LOCALVAR char *n_arg = NULL;
59
60#if CanGetAppPath
61LOCALVAR char *app_parent = NULL;
62LOCALVAR char *app_name = NULL;
63#endif
64
65LOCALFUNC tMacErr ChildPath(char *x, char *y, char **r)
66{
67 tMacErr err = mnvm_miscErr;
68 int nx = strlen(x);
69 int ny = strlen(y);
70 {
71 if ((nx > 0) && ('/' == x[nx - 1])) {
72 --nx;
73 }
74 {
75 int nr = nx + 1 + ny;
76 char *p = malloc(nr + 1);
77 if (p != NULL) {
78 char *p2 = p;
79 (void) memcpy(p2, x, nx);
80 p2 += nx;
81 *p2++ = '/';
82 (void) memcpy(p2, y, ny);
83 p2 += ny;
84 *p2 = 0;
85 *r = p;
86 err = mnvm_noErr;
87 }
88 }
89 }
90
91 return err;
92}
93
94#if UseActvFile || IncludeSonyNew
95LOCALFUNC tMacErr FindOrMakeChild(char *x, char *y, char **r)
96{
97 tMacErr err;
98 struct stat folder_info;
99 char *r0;
100
101 if (mnvm_noErr == (err = ChildPath(x, y, &r0))) {
102 if (0 != stat(r0, &folder_info)) {
103 if (0 != mkdir(r0, S_IRWXU)) {
104 err = mnvm_miscErr;
105 } else {
106 *r = r0;
107 err = mnvm_noErr;
108 }
109 } else {
110 if (! S_ISDIR(folder_info.st_mode)) {
111 err = mnvm_miscErr;
112 } else {
113 *r = r0;
114 err = mnvm_noErr;
115 }
116 }
117 }
118
119 return err;
120}
121#endif
122
123LOCALPROC MyMayFree(char *p)
124{
125 if (NULL != p) {
126 free(p);
127 }
128}
129
130/* --- sending debugging info to file --- */
131
132#if dbglog_HAVE
133
134#ifndef dbglog_ToStdErr
135#define dbglog_ToStdErr 0
136#endif
137
138#if ! dbglog_ToStdErr
139LOCALVAR FILE *dbglog_File = NULL;
140#endif
141
142LOCALFUNC blnr dbglog_open0(void)
143{
144#if dbglog_ToStdErr
145 return trueblnr;
146#else
147 dbglog_File = fopen("dbglog.txt", "w");
148 return (NULL != dbglog_File);
149#endif
150}
151
152LOCALPROC dbglog_write0(char *s, uimr L)
153{
154#if dbglog_ToStdErr
155 (void) fwrite(s, 1, L, stderr);
156#else
157 if (dbglog_File != NULL) {
158 (void) fwrite(s, 1, L, dbglog_File);
159 }
160#endif
161}
162
163LOCALPROC dbglog_close0(void)
164{
165#if ! dbglog_ToStdErr
166 if (dbglog_File != NULL) {
167 fclose(dbglog_File);
168 dbglog_File = NULL;
169 }
170#endif
171}
172
173#endif
174
175/* --- debug settings and utilities --- */
176
177#if ! dbglog_HAVE
178#define WriteExtraErr(s)
179#else
180LOCALPROC WriteExtraErr(char *s)
181{
182 dbglog_writeCStr("*** error: ");
183 dbglog_writeCStr(s);
184 dbglog_writeReturn();
185}
186#endif
187
188LOCALVAR Display *x_display = NULL;
189
190#define MyDbgEvents (dbglog_HAVE && 0)
191
192#if MyDbgEvents
193LOCALPROC WriteDbgAtom(char *s, Atom x)
194{
195 char *name = XGetAtomName(x_display, x);
196 if (name != NULL) {
197 dbglog_writeCStr("Atom ");
198 dbglog_writeCStr(s);
199 dbglog_writeCStr(": ");
200 dbglog_writeCStr(name);
201 dbglog_writeReturn();
202 XFree(name);
203 }
204}
205#endif
206
207/* --- information about the environment --- */
208
209LOCALVAR Atom MyXA_DeleteW = (Atom)0;
210#if EnableDragDrop
211LOCALVAR Atom MyXA_UriList = (Atom)0;
212LOCALVAR Atom MyXA_DndAware = (Atom)0;
213LOCALVAR Atom MyXA_DndEnter = (Atom)0;
214LOCALVAR Atom MyXA_DndLeave = (Atom)0;
215LOCALVAR Atom MyXA_DndDrop = (Atom)0;
216LOCALVAR Atom MyXA_DndPosition = (Atom)0;
217LOCALVAR Atom MyXA_DndStatus = (Atom)0;
218LOCALVAR Atom MyXA_DndActionCopy = (Atom)0;
219LOCALVAR Atom MyXA_DndActionPrivate = (Atom)0;
220LOCALVAR Atom MyXA_DndSelection = (Atom)0;
221LOCALVAR Atom MyXA_DndFinished = (Atom)0;
222LOCALVAR Atom MyXA_MinivMac_DndXchng = (Atom)0;
223LOCALVAR Atom MyXA_NetActiveWindow = (Atom)0;
224LOCALVAR Atom MyXA_NetSupported = (Atom)0;
225#endif
226#if IncludeHostTextClipExchange
227LOCALVAR Atom MyXA_CLIPBOARD = (Atom)0;
228LOCALVAR Atom MyXA_TARGETS = (Atom)0;
229LOCALVAR Atom MyXA_MinivMac_Clip = (Atom)0;
230#endif
231
232LOCALPROC LoadMyXA(void)
233{
234 MyXA_DeleteW = XInternAtom(x_display, "WM_DELETE_WINDOW", False);
235#if EnableDragDrop
236 MyXA_UriList = XInternAtom (x_display, "text/uri-list", False);
237 MyXA_DndAware = XInternAtom (x_display, "XdndAware", False);
238 MyXA_DndEnter = XInternAtom(x_display, "XdndEnter", False);
239 MyXA_DndLeave = XInternAtom(x_display, "XdndLeave", False);
240 MyXA_DndDrop = XInternAtom(x_display, "XdndDrop", False);
241 MyXA_DndPosition = XInternAtom(x_display, "XdndPosition", False);
242 MyXA_DndStatus = XInternAtom(x_display, "XdndStatus", False);
243 MyXA_DndActionCopy = XInternAtom(x_display,
244 "XdndActionCopy", False);
245 MyXA_DndActionPrivate = XInternAtom(x_display,
246 "XdndActionPrivate", False);
247 MyXA_DndSelection = XInternAtom(x_display, "XdndSelection", False);
248 MyXA_DndFinished = XInternAtom(x_display, "XdndFinished", False);
249 MyXA_MinivMac_DndXchng = XInternAtom(x_display,
250 "_MinivMac_DndXchng", False);
251 MyXA_NetActiveWindow = XInternAtom(x_display,
252 "_NET_ACTIVE_WINDOW", False);
253 MyXA_NetSupported = XInternAtom(x_display,
254 "_NET_SUPPORTED", False);
255#endif
256#if IncludeHostTextClipExchange
257 MyXA_CLIPBOARD = XInternAtom(x_display, "CLIPBOARD", False);
258 MyXA_TARGETS = XInternAtom(x_display, "TARGETS", False);
259 MyXA_MinivMac_Clip = XInternAtom(x_display,
260 "_MinivMac_Clip", False);
261#endif
262}
263
264#if EnableDragDrop
265LOCALFUNC blnr NetSupportedContains(Atom x)
266{
267 /*
268 Note that the window manager could be replaced at
269 any time, so don't cache results of this function.
270 */
271 Atom ret_type;
272 int ret_format;
273 unsigned long ret_item;
274 unsigned long remain_byte;
275 unsigned long i;
276 unsigned char *s = 0;
277 blnr foundit = falseblnr;
278 Window rootwin = XRootWindow(x_display,
279 DefaultScreen(x_display));
280
281 if (Success != XGetWindowProperty(x_display, rootwin,
282 MyXA_NetSupported,
283 0, 65535, False, XA_ATOM, &ret_type, &ret_format,
284 &ret_item, &remain_byte, &s))
285 {
286 WriteExtraErr("XGetWindowProperty failed");
287 } else if (! s) {
288 WriteExtraErr("XGetWindowProperty failed");
289 } else if (ret_type != XA_ATOM) {
290 WriteExtraErr("XGetWindowProperty returns wrong type");
291 } else {
292 Atom *v = (Atom *)s;
293
294 for (i = 0; i < ret_item; ++i) {
295 if (v[i] == x) {
296 foundit = trueblnr;
297 /* fprintf(stderr, "found the hint\n"); */
298 }
299 }
300 }
301 if (s) {
302 XFree(s);
303 }
304 return foundit;
305}
306#endif
307
308#define WantColorTransValid 1
309
310#include "COMOSGLU.h"
311
312#include "PBUFSTDC.h"
313
314#include "CONTROLM.h"
315
316/* --- text translation --- */
317
318#if IncludePbufs
319/* this is table for Windows, any changes needed for X? */
320LOCALVAR const ui3b Native2MacRomanTab[] = {
321 0xAD, 0xB0, 0xE2, 0xC4, 0xE3, 0xC9, 0xA0, 0xE0,
322 0xF6, 0xE4, 0xB6, 0xDC, 0xCE, 0xB2, 0xB3, 0xB7,
323 0xB8, 0xD4, 0xD5, 0xD2, 0xD3, 0xA5, 0xD0, 0xD1,
324 0xF7, 0xAA, 0xC5, 0xDD, 0xCF, 0xB9, 0xC3, 0xD9,
325 0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0xBA, 0xA4,
326 0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0xBD, 0xA8, 0xF8,
327 0xA1, 0xB1, 0xC6, 0xD7, 0xAB, 0xB5, 0xA6, 0xE1,
328 0xFC, 0xDA, 0xBC, 0xC8, 0xDE, 0xDF, 0xF0, 0xC0,
329 0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,
330 0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,
331 0xF5, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0xF9,
332 0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0xFA, 0xFB, 0xA7,
333 0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,
334 0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
335 0xFD, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,
336 0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0xFE, 0xFF, 0xD8
337};
338#endif
339
340#if IncludePbufs
341LOCALFUNC tMacErr NativeTextToMacRomanPbuf(char *x, tPbuf *r)
342{
343 if (NULL == x) {
344 return mnvm_miscErr;
345 } else {
346 ui3p p;
347 ui5b L = strlen(x);
348
349 p = (ui3p)malloc(L);
350 if (NULL == p) {
351 return mnvm_miscErr;
352 } else {
353 ui3b *p0 = (ui3b *)x;
354 ui3b *p1 = (ui3b *)p;
355 int i;
356
357 for (i = L; --i >= 0; ) {
358 ui3b v = *p0++;
359 if (v >= 128) {
360 v = Native2MacRomanTab[v - 128];
361 } else if (10 == v) {
362 v = 13;
363 }
364 *p1++ = v;
365 }
366
367 return PbufNewFromPtr(p, L, r);
368 }
369 }
370}
371#endif
372
373#if IncludePbufs
374/* this is table for Windows, any changes needed for X? */
375LOCALVAR const ui3b MacRoman2NativeTab[] = {
376 0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1,
377 0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8,
378 0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3,
379 0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC,
380 0x86, 0xB0, 0xA2, 0xA3, 0xA7, 0x95, 0xB6, 0xDF,
381 0xAE, 0xA9, 0x99, 0xB4, 0xA8, 0x80, 0xC6, 0xD8,
382 0x81, 0xB1, 0x8D, 0x8E, 0xA5, 0xB5, 0x8A, 0x8F,
383 0x90, 0x9D, 0xA6, 0xAA, 0xBA, 0xAD, 0xE6, 0xF8,
384 0xBF, 0xA1, 0xAC, 0x9E, 0x83, 0x9A, 0xB2, 0xAB,
385 0xBB, 0x85, 0xA0, 0xC0, 0xC3, 0xD5, 0x8C, 0x9C,
386 0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xF7, 0xB3,
387 0xFF, 0x9F, 0xB9, 0xA4, 0x8B, 0x9B, 0xBC, 0xBD,
388 0x87, 0xB7, 0x82, 0x84, 0x89, 0xC2, 0xCA, 0xC1,
389 0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0xD3, 0xD4,
390 0xBE, 0xD2, 0xDA, 0xDB, 0xD9, 0xD0, 0x88, 0x98,
391 0xAF, 0xD7, 0xDD, 0xDE, 0xB8, 0xF0, 0xFD, 0xFE
392};
393#endif
394
395#if IncludePbufs
396LOCALFUNC blnr MacRomanTextToNativePtr(tPbuf i, blnr IsFileName,
397 ui3p *r)
398{
399 ui3p p;
400 void *Buffer = PbufDat[i];
401 ui5b L = PbufSize[i];
402
403 p = (ui3p)malloc(L + 1);
404 if (p != NULL) {
405 ui3b *p0 = (ui3b *)Buffer;
406 ui3b *p1 = (ui3b *)p;
407 int j;
408
409 if (IsFileName) {
410 for (j = L; --j >= 0; ) {
411 ui3b x = *p0++;
412 if (x < 32) {
413 x = '-';
414 } else if (x >= 128) {
415 x = MacRoman2NativeTab[x - 128];
416 } else {
417 switch (x) {
418 case '/':
419 case '<':
420 case '>':
421 case '|':
422 case ':':
423 x = '-';
424 default:
425 break;
426 }
427 }
428 *p1++ = x;
429 }
430 if ('.' == p[0]) {
431 p[0] = '-';
432 }
433 } else {
434 for (j = L; --j >= 0; ) {
435 ui3b x = *p0++;
436 if (x >= 128) {
437 x = MacRoman2NativeTab[x - 128];
438 } else if (13 == x) {
439 x = '\n';
440 }
441 *p1++ = x;
442 }
443 }
444 *p1 = 0;
445
446 *r = p;
447 return trueblnr;
448 }
449 return falseblnr;
450}
451#endif
452
453LOCALPROC NativeStrFromCStr(char *r, char *s)
454{
455 ui3b ps[ClStrMaxLength];
456 int i;
457 int L;
458
459 ClStrFromSubstCStr(&L, ps, s);
460
461 for (i = 0; i < L; ++i) {
462 r[i] = Cell2PlainAsciiMap[ps[i]];
463 }
464
465 r[L] = 0;
466}
467
468/* --- drives --- */
469
470#define NotAfileRef NULL
471
472LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */
473#if IncludeSonyGetName || IncludeSonyNew
474LOCALVAR char *DriveNames[NumDrives];
475#endif
476
477LOCALPROC InitDrives(void)
478{
479 /*
480 This isn't really needed, Drives[i] and DriveNames[i]
481 need not have valid values when not vSonyIsInserted[i].
482 */
483 tDrive i;
484
485 for (i = 0; i < NumDrives; ++i) {
486 Drives[i] = NotAfileRef;
487#if IncludeSonyGetName || IncludeSonyNew
488 DriveNames[i] = NULL;
489#endif
490 }
491}
492
493GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
494 tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
495 ui5r *Sony_ActCount)
496{
497 tMacErr err = mnvm_miscErr;
498 FILE *refnum = Drives[Drive_No];
499 ui5r NewSony_Count = 0;
500
501 if (0 == fseek(refnum, Sony_Start, SEEK_SET)) {
502 if (IsWrite) {
503 NewSony_Count = fwrite(Buffer, 1, Sony_Count, refnum);
504 } else {
505 NewSony_Count = fread(Buffer, 1, Sony_Count, refnum);
506 }
507
508 if (NewSony_Count == Sony_Count) {
509 err = mnvm_noErr;
510 }
511 }
512
513 if (nullpr != Sony_ActCount) {
514 *Sony_ActCount = NewSony_Count;
515 }
516
517 return err; /*& figure out what really to return &*/
518}
519
520GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
521{
522 tMacErr err = mnvm_miscErr;
523 FILE *refnum = Drives[Drive_No];
524 long v;
525
526 if (0 == fseek(refnum, 0, SEEK_END)) {
527 v = ftell(refnum);
528 if (v >= 0) {
529 *Sony_Count = v;
530 err = mnvm_noErr;
531 }
532 }
533
534 return err; /*& figure out what really to return &*/
535}
536
537#ifndef HaveAdvisoryLocks
538#define HaveAdvisoryLocks 1
539#endif
540
541/*
542 What is the difference between fcntl(fd, F_SETLK ...
543 and flock(fd ... ?
544*/
545
546#if HaveAdvisoryLocks
547LOCALFUNC blnr MyLockFile(FILE *refnum)
548{
549 blnr IsOk = falseblnr;
550
551#if 1
552 struct flock fl;
553 int fd = fileno(refnum);
554
555 fl.l_start = 0; /* starting offset */
556 fl.l_len = 0; /* len = 0 means until end of file */
557 /* fl.pid_t l_pid; */ /* lock owner, don't need to set */
558 fl.l_type = F_WRLCK; /* lock type: read/write, etc. */
559 fl.l_whence = SEEK_SET; /* type of l_start */
560 if (-1 == fcntl(fd, F_SETLK, &fl)) {
561 MacMsg(kStrImageInUseTitle, kStrImageInUseMessage,
562 falseblnr);
563 } else {
564 IsOk = trueblnr;
565 }
566#else
567 int fd = fileno(refnum);
568
569 if (-1 == flock(fd, LOCK_EX | LOCK_NB)) {
570 MacMsg(kStrImageInUseTitle, kStrImageInUseMessage,
571 falseblnr);
572 } else {
573 IsOk = trueblnr;
574 }
575#endif
576
577 return IsOk;
578}
579#endif
580
581#if HaveAdvisoryLocks
582LOCALPROC MyUnlockFile(FILE *refnum)
583{
584#if 1
585 struct flock fl;
586 int fd = fileno(refnum);
587
588 fl.l_start = 0; /* starting offset */
589 fl.l_len = 0; /* len = 0 means until end of file */
590 /* fl.pid_t l_pid; */ /* lock owner, don't need to set */
591 fl.l_type = F_UNLCK; /* lock type: read/write, etc. */
592 fl.l_whence = SEEK_SET; /* type of l_start */
593 if (-1 == fcntl(fd, F_SETLK, &fl)) {
594 /* an error occurred */
595 }
596#else
597 int fd = fileno(refnum);
598
599 if (-1 == flock(fd, LOCK_UN)) {
600 }
601#endif
602}
603#endif
604
605LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit)
606{
607 FILE *refnum = Drives[Drive_No];
608
609 DiskEjectedNotify(Drive_No);
610
611#if HaveAdvisoryLocks
612 MyUnlockFile(refnum);
613#endif
614
615 fclose(refnum);
616 Drives[Drive_No] = NotAfileRef; /* not really needed */
617
618#if IncludeSonyGetName || IncludeSonyNew
619 {
620 char *s = DriveNames[Drive_No];
621 if (NULL != s) {
622 if (deleteit) {
623 remove(s);
624 }
625 free(s);
626 DriveNames[Drive_No] = NULL; /* not really needed */
627 }
628 }
629#endif
630
631 return mnvm_noErr;
632}
633
634GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
635{
636 return vSonyEject0(Drive_No, falseblnr);
637}
638
639#if IncludeSonyNew
640GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
641{
642 return vSonyEject0(Drive_No, trueblnr);
643}
644#endif
645
646LOCALPROC UnInitDrives(void)
647{
648 tDrive i;
649
650 for (i = 0; i < NumDrives; ++i) {
651 if (vSonyIsInserted(i)) {
652 (void) vSonyEject(i);
653 }
654 }
655}
656
657#if IncludeSonyGetName
658GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
659{
660 char *drivepath = DriveNames[Drive_No];
661 if (NULL == drivepath) {
662 return mnvm_miscErr;
663 } else {
664 char *s = strrchr(drivepath, '/');
665 if (NULL == s) {
666 s = drivepath;
667 } else {
668 ++s;
669 }
670 return NativeTextToMacRomanPbuf(s, r);
671 }
672}
673#endif
674
675LOCALFUNC blnr Sony_Insert0(FILE *refnum, blnr locked,
676 char *drivepath)
677{
678 tDrive Drive_No;
679 blnr IsOk = falseblnr;
680
681 if (! FirstFreeDisk(&Drive_No)) {
682 MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage,
683 falseblnr);
684 } else {
685 /* printf("Sony_Insert0 %d\n", (int)Drive_No); */
686
687#if HaveAdvisoryLocks
688 if (locked || MyLockFile(refnum))
689#endif
690 {
691 Drives[Drive_No] = refnum;
692 DiskInsertNotify(Drive_No, locked);
693
694#if IncludeSonyGetName || IncludeSonyNew
695 {
696 ui5b L = strlen(drivepath);
697 char *p = malloc(L + 1);
698 if (p != NULL) {
699 (void) memcpy(p, drivepath, L + 1);
700 }
701 DriveNames[Drive_No] = p;
702 }
703#endif
704
705 IsOk = trueblnr;
706 }
707 }
708
709 if (! IsOk) {
710 fclose(refnum);
711 }
712
713 return IsOk;
714}
715
716LOCALFUNC blnr Sony_Insert1(char *drivepath, blnr silentfail)
717{
718 blnr locked = falseblnr;
719 /* printf("Sony_Insert1 %s\n", drivepath); */
720 FILE *refnum = fopen(drivepath, "rb+");
721 if (NULL == refnum) {
722 locked = trueblnr;
723 refnum = fopen(drivepath, "rb");
724 }
725 if (NULL == refnum) {
726 if (! silentfail) {
727 MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
728 }
729 } else {
730 return Sony_Insert0(refnum, locked, drivepath);
731 }
732 return falseblnr;
733}
734
735LOCALFUNC tMacErr LoadMacRomFrom(char *path)
736{
737 tMacErr err;
738 FILE *ROM_File;
739 int File_Size;
740
741 ROM_File = fopen(path, "rb");
742 if (NULL == ROM_File) {
743 err = mnvm_fnfErr;
744 } else {
745 File_Size = fread(ROM, 1, kROM_Size, ROM_File);
746 if (kROM_Size != File_Size) {
747 if (feof(ROM_File)) {
748 MacMsgOverride(kStrShortROMTitle,
749 kStrShortROMMessage);
750 err = mnvm_eofErr;
751 } else {
752 MacMsgOverride(kStrNoReadROMTitle,
753 kStrNoReadROMMessage);
754 err = mnvm_miscErr;
755 }
756 } else {
757 err = ROM_IsValid();
758 }
759 fclose(ROM_File);
760 }
761
762 return err;
763}
764
765LOCALFUNC blnr Sony_Insert1a(char *drivepath, blnr silentfail)
766{
767 blnr v;
768
769 if (! ROM_loaded) {
770 v = (mnvm_noErr == LoadMacRomFrom(drivepath));
771 } else {
772 v = Sony_Insert1(drivepath, silentfail);
773 }
774
775 return v;
776}
777
778LOCALFUNC blnr Sony_Insert2(char *s)
779{
780 char *d =
781#if CanGetAppPath
782 (NULL == d_arg) ? app_parent :
783#endif
784 d_arg;
785 blnr IsOk = falseblnr;
786
787 if (NULL == d) {
788 IsOk = Sony_Insert1(s, trueblnr);
789 } else {
790 char *t;
791
792 if (mnvm_noErr == ChildPath(d, s, &t)) {
793 IsOk = Sony_Insert1(t, trueblnr);
794 free(t);
795 }
796 }
797
798 return IsOk;
799}
800
801LOCALFUNC blnr Sony_InsertIth(int i)
802{
803 blnr v;
804
805 if ((i > 9) || ! FirstFreeDisk(nullpr)) {
806 v = falseblnr;
807 } else {
808 char s[] = "disk?.dsk";
809
810 s[4] = '0' + i;
811
812 v = Sony_Insert2(s);
813 }
814
815 return v;
816}
817
818LOCALFUNC blnr LoadInitialImages(void)
819{
820 if (! AnyDiskInserted()) {
821 int i;
822
823 for (i = 1; Sony_InsertIth(i); ++i) {
824 /* stop on first error (including file not found) */
825 }
826 }
827
828 return trueblnr;
829}
830
831#if IncludeSonyNew
832LOCALFUNC blnr WriteZero(FILE *refnum, ui5b L)
833{
834#define ZeroBufferSize 2048
835 ui5b i;
836 ui3b buffer[ZeroBufferSize];
837
838 memset(&buffer, 0, ZeroBufferSize);
839
840 while (L > 0) {
841 i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
842 if (fwrite(buffer, 1, i, refnum) != i) {
843 return falseblnr;
844 }
845 L -= i;
846 }
847 return trueblnr;
848}
849#endif
850
851#if IncludeSonyNew
852LOCALPROC MakeNewDisk0(ui5b L, char *drivepath)
853{
854 blnr IsOk = falseblnr;
855 FILE *refnum = fopen(drivepath, "wb+");
856 if (NULL == refnum) {
857 MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
858 } else {
859 if (WriteZero(refnum, L)) {
860 IsOk = Sony_Insert0(refnum, falseblnr, drivepath);
861 refnum = NULL;
862 }
863 if (refnum != NULL) {
864 fclose(refnum);
865 }
866 if (! IsOk) {
867 (void) remove(drivepath);
868 }
869 }
870}
871#endif
872
873#if IncludeSonyNew
874LOCALPROC MakeNewDisk(ui5b L, char *drivename)
875{
876 char *d =
877#if CanGetAppPath
878 (NULL == d_arg) ? app_parent :
879#endif
880 d_arg;
881
882 if (NULL == d) {
883 MakeNewDisk0(L, drivename); /* in current directory */
884 } else {
885 tMacErr err;
886 char *t = NULL;
887 char *t2 = NULL;
888
889 if (mnvm_noErr == (err = FindOrMakeChild(d, "out", &t)))
890 if (mnvm_noErr == (err = ChildPath(t, drivename, &t2)))
891 {
892 MakeNewDisk0(L, t2);
893 }
894
895 MyMayFree(t2);
896 MyMayFree(t);
897 }
898}
899#endif
900
901#if IncludeSonyNew
902LOCALPROC MakeNewDiskAtDefault(ui5b L)
903{
904 char s[ClStrMaxLength + 1];
905
906 NativeStrFromCStr(s, "untitled.dsk");
907 MakeNewDisk(L, s);
908}
909#endif
910
911/* --- ROM --- */
912
913LOCALVAR char *rom_path = NULL;
914
915#if 0
916#include <pwd.h>
917#include <unistd.h>
918#endif
919
920LOCALFUNC tMacErr FindUserHomeFolder(char **r)
921{
922 tMacErr err;
923 char *s;
924#if 0
925 struct passwd *user;
926#endif
927
928 if (NULL != (s = getenv("HOME"))) {
929 *r = s;
930 err = mnvm_noErr;
931 } else
932#if 0
933 if ((NULL != (user = getpwuid(getuid())))
934 && (NULL != (s = user->pw_dir)))
935 {
936 /*
937 From getpwuid man page:
938 "An application that wants to determine its user's
939 home directory should inspect the value of HOME
940 (rather than the value getpwuid(getuid())->pw_dir)
941 since this allows the user to modify their notion of
942 "the home directory" during a login session."
943
944 But it is possible for HOME to not be set.
945 Some sources say to use getpwuid in that case.
946 */
947 *r = s;
948 err = mnvm_noErr;
949 } else
950#endif
951 {
952 err = mnvm_fnfErr;
953 }
954
955 return err;
956}
957
958LOCALFUNC tMacErr LoadMacRomFromHome(void)
959{
960 tMacErr err;
961 char *s;
962 char *t = NULL;
963 char *t2 = NULL;
964 char *t3 = NULL;
965
966 if (mnvm_noErr == (err = FindUserHomeFolder(&s)))
967 if (mnvm_noErr == (err = ChildPath(s, ".gryphel", &t)))
968 if (mnvm_noErr == (err = ChildPath(t, "mnvm_rom", &t2)))
969 if (mnvm_noErr == (err = ChildPath(t2, RomFileName, &t3)))
970 {
971 err = LoadMacRomFrom(t3);
972 }
973
974 MyMayFree(t3);
975 MyMayFree(t2);
976 MyMayFree(t);
977
978 return err;
979}
980
981#if CanGetAppPath
982LOCALFUNC tMacErr LoadMacRomFromAppPar(void)
983{
984 tMacErr err;
985 char *d =
986#if CanGetAppPath
987 (NULL == d_arg) ? app_parent :
988#endif
989 d_arg;
990 char *t = NULL;
991
992 if (NULL == d) {
993 err = mnvm_fnfErr;
994 } else {
995 if (mnvm_noErr == (err = ChildPath(d, RomFileName,
996 &t)))
997 {
998 err = LoadMacRomFrom(t);
999 }
1000 }
1001
1002 MyMayFree(t);
1003
1004 return err;
1005}
1006#endif
1007
1008LOCALFUNC blnr LoadMacRom(void)
1009{
1010 tMacErr err;
1011
1012 if ((NULL == rom_path)
1013 || (mnvm_fnfErr == (err = LoadMacRomFrom(rom_path))))
1014#if CanGetAppPath
1015 if (mnvm_fnfErr == (err = LoadMacRomFromAppPar()))
1016#endif
1017 if (mnvm_fnfErr == (err = LoadMacRomFromHome()))
1018 if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName)))
1019 {
1020 }
1021
1022 return trueblnr; /* keep launching Mini vMac, regardless */
1023}
1024
1025#if UseActvFile
1026
1027#define ActvCodeFileName "act_1"
1028
1029LOCALFUNC tMacErr ActvCodeFileLoad(ui3p p)
1030{
1031 tMacErr err;
1032 char *s;
1033 char *t = NULL;
1034 char *t2 = NULL;
1035 char *t3 = NULL;
1036
1037 if (mnvm_noErr == (err = FindUserHomeFolder(&s)))
1038 if (mnvm_noErr == (err = ChildPath(s, ".gryphel", &t)))
1039 if (mnvm_noErr == (err = ChildPath(t, "mnvm_act", &t2)))
1040 if (mnvm_noErr == (err = ChildPath(t2, ActvCodeFileName, &t3)))
1041 {
1042 FILE *Actv_File;
1043 int File_Size;
1044
1045 Actv_File = fopen(t3, "rb");
1046 if (NULL == Actv_File) {
1047 err = mnvm_fnfErr;
1048 } else {
1049 File_Size = fread(p, 1, ActvCodeFileLen, Actv_File);
1050 if (File_Size != ActvCodeFileLen) {
1051 if (feof(Actv_File)) {
1052 err = mnvm_eofErr;
1053 } else {
1054 err = mnvm_miscErr;
1055 }
1056 } else {
1057 err = mnvm_noErr;
1058 }
1059 fclose(Actv_File);
1060 }
1061 }
1062
1063 MyMayFree(t3);
1064 MyMayFree(t2);
1065 MyMayFree(t);
1066
1067 return err;
1068}
1069
1070LOCALFUNC tMacErr ActvCodeFileSave(ui3p p)
1071{
1072 tMacErr err;
1073 char *s;
1074 char *t = NULL;
1075 char *t2 = NULL;
1076 char *t3 = NULL;
1077
1078 if (mnvm_noErr == (err = FindUserHomeFolder(&s)))
1079 if (mnvm_noErr == (err = FindOrMakeChild(s, ".gryphel", &t)))
1080 if (mnvm_noErr == (err = FindOrMakeChild(t, "mnvm_act", &t2)))
1081 if (mnvm_noErr == (err = ChildPath(t2, ActvCodeFileName, &t3)))
1082 {
1083 FILE *Actv_File;
1084 int File_Size;
1085
1086 Actv_File = fopen(t3, "wb+");
1087 if (NULL == Actv_File) {
1088 err = mnvm_fnfErr;
1089 } else {
1090 File_Size = fwrite(p, 1, ActvCodeFileLen, Actv_File);
1091 if (File_Size != ActvCodeFileLen) {
1092 err = mnvm_miscErr;
1093 } else {
1094 err = mnvm_noErr;
1095 }
1096 fclose(Actv_File);
1097 }
1098 }
1099
1100 MyMayFree(t3);
1101 MyMayFree(t2);
1102 MyMayFree(t);
1103
1104 return err;
1105}
1106
1107#endif /* UseActvFile */
1108
1109/* --- video out --- */
1110
1111LOCALVAR Window my_main_wind = 0;
1112LOCALVAR GC my_gc = NULL;
1113LOCALVAR blnr NeedFinishOpen1 = falseblnr;
1114LOCALVAR blnr NeedFinishOpen2 = falseblnr;
1115
1116LOCALVAR XColor x_black;
1117LOCALVAR XColor x_white;
1118
1119#if MayFullScreen
1120LOCALVAR short hOffset;
1121LOCALVAR short vOffset;
1122#endif
1123
1124#if VarFullScreen
1125LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0);
1126#endif
1127
1128#if EnableMagnify
1129LOCALVAR blnr UseMagnify = (WantInitMagnify != 0);
1130#endif
1131
1132LOCALVAR blnr gBackgroundFlag = falseblnr;
1133LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
1134LOCALVAR blnr CurSpeedStopped = trueblnr;
1135
1136#ifndef UseColorImage
1137#define UseColorImage (0 != vMacScreenDepth)
1138#endif
1139
1140LOCALVAR XImage *my_image = NULL;
1141
1142#if EnableMagnify
1143LOCALVAR XImage *my_Scaled_image = NULL;
1144#endif
1145
1146#if EnableMagnify
1147#define MaxScale MyWindowScale
1148#else
1149#define MaxScale 1
1150#endif
1151
1152#define WantScalingTabl (EnableMagnify || UseColorImage)
1153
1154#if WantScalingTabl
1155
1156LOCALVAR ui3p ScalingTabl = nullpr;
1157
1158#define ScalingTablsz1 (256 * MaxScale)
1159
1160#if UseColorImage
1161#define ScalingTablsz (ScalingTablsz1 << 5)
1162#else
1163#define ScalingTablsz ScalingTablsz1
1164#endif
1165
1166#endif /* WantScalingTabl */
1167
1168
1169#define WantScalingBuff (EnableMagnify || UseColorImage)
1170
1171#if WantScalingBuff
1172
1173LOCALVAR ui3p ScalingBuff = nullpr;
1174
1175
1176#if UseColorImage
1177#define ScalingBuffsz \
1178 (vMacScreenNumPixels * 4 * MaxScale * MaxScale)
1179#else
1180#define ScalingBuffsz ((long)vMacScreenMonoNumBytes \
1181 * MaxScale * MaxScale)
1182#endif
1183
1184#endif /* WantScalingBuff */
1185
1186
1187#if EnableMagnify && ! UseColorImage
1188LOCALPROC SetUpScalingTabl(void)
1189{
1190 ui3b *p4;
1191 int i;
1192 int j;
1193 int k;
1194 ui3r bitsRemaining;
1195 ui3b t1;
1196 ui3b t2;
1197
1198 p4 = ScalingTabl;
1199 for (i = 0; i < 256; ++i) {
1200 bitsRemaining = 8;
1201 t2 = 0;
1202 for (j = 8; --j >= 0; ) {
1203 t1 = (i >> j) & 1;
1204 for (k = MyWindowScale; --k >= 0; ) {
1205 t2 = (t2 << 1) | t1;
1206 if (--bitsRemaining == 0) {
1207 *p4++ = t2;
1208 bitsRemaining = 8;
1209 t2 = 0;
1210 }
1211 }
1212 }
1213 }
1214}
1215#endif
1216
1217#if EnableMagnify && (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
1218LOCALPROC SetUpColorScalingTabl(void)
1219{
1220 int i;
1221 int j;
1222 int k;
1223 int a;
1224 ui5r v;
1225 ui5p p4;
1226
1227 p4 = (ui5p)ScalingTabl;
1228 for (i = 0; i < 256; ++i) {
1229 for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) {
1230 j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1);
1231 v = (((long)CLUT_reds[j] & 0xFF00) << 8)
1232 | ((long)CLUT_greens[j] & 0xFF00)
1233 | (((long)CLUT_blues[j] & 0xFF00) >> 8);
1234 for (a = MyWindowScale; --a >= 0; ) {
1235 *p4++ = v;
1236 }
1237 }
1238 }
1239}
1240#endif
1241
1242#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
1243LOCALPROC SetUpColorTabl(void)
1244{
1245 int i;
1246 int j;
1247 int k;
1248 ui5p p4;
1249
1250 p4 = (ui5p)ScalingTabl;
1251 for (i = 0; i < 256; ++i) {
1252 for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) {
1253 j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1);
1254 *p4++ = (((long)CLUT_reds[j] & 0xFF00) << 8)
1255 | ((long)CLUT_greens[j] & 0xFF00)
1256 | (((long)CLUT_blues[j] & 0xFF00) >> 8);
1257 }
1258 }
1259}
1260#endif
1261
1262#if EnableMagnify && UseColorImage
1263LOCALPROC SetUpBW2ColorScalingTabl(void)
1264{
1265 int i;
1266 int k;
1267 int a;
1268 ui5r v;
1269 ui5p p4;
1270
1271 p4 = (ui5p)ScalingTabl;
1272 for (i = 0; i < 256; ++i) {
1273 for (k = 8; --k >= 0; ) {
1274 if (0 != ((i >> k) & 1)) {
1275 v = 0;
1276 } else {
1277 v = 0xFFFFFF;
1278 }
1279
1280 for (a = MyWindowScale; --a >= 0; ) {
1281 *p4++ = v;
1282 }
1283 }
1284 }
1285}
1286#endif
1287
1288#if UseColorImage
1289LOCALPROC SetUpBW2ColorTabl(void)
1290{
1291 int i;
1292 int k;
1293 ui5r v;
1294 ui5p p4;
1295
1296 p4 = (ui5p)ScalingTabl;
1297 for (i = 0; i < 256; ++i) {
1298 for (k = 8; --k >= 0; ) {
1299 if (0 != ((i >> k) & 1)) {
1300 v = 0;
1301 } else {
1302 v = 0xFFFFFF;
1303 }
1304 *p4++ = v;
1305 }
1306 }
1307}
1308#endif
1309
1310
1311#if EnableMagnify && ! UseColorImage
1312
1313#define ScrnMapr_DoMap UpdateScaledBWCopy
1314#define ScrnMapr_Src GetCurDrawBuff()
1315#define ScrnMapr_Dst ScalingBuff
1316#define ScrnMapr_SrcDepth 0
1317#define ScrnMapr_DstDepth 0
1318#define ScrnMapr_Map ScalingTabl
1319#define ScrnMapr_Scale MyWindowScale
1320
1321#include "SCRNMAPR.h"
1322
1323#endif
1324
1325
1326#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
1327
1328#define ScrnMapr_DoMap UpdateMappedColorCopy
1329#define ScrnMapr_Src GetCurDrawBuff()
1330#define ScrnMapr_Dst ScalingBuff
1331#define ScrnMapr_SrcDepth vMacScreenDepth
1332#define ScrnMapr_DstDepth 5
1333#define ScrnMapr_Map ScalingTabl
1334
1335#include "SCRNMAPR.h"
1336
1337#endif
1338
1339
1340#if EnableMagnify && (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
1341
1342#define ScrnMapr_DoMap UpdateMappedScaledColorCopy
1343#define ScrnMapr_Src GetCurDrawBuff()
1344#define ScrnMapr_Dst ScalingBuff
1345#define ScrnMapr_SrcDepth vMacScreenDepth
1346#define ScrnMapr_DstDepth 5
1347#define ScrnMapr_Map ScalingTabl
1348#define ScrnMapr_Scale MyWindowScale
1349
1350#include "SCRNMAPR.h"
1351
1352#endif
1353
1354
1355#if vMacScreenDepth >= 4
1356
1357#define ScrnTrns_DoTrans UpdateTransColorCopy
1358#define ScrnTrns_Src GetCurDrawBuff()
1359#define ScrnTrns_Dst ScalingBuff
1360#define ScrnTrns_SrcDepth vMacScreenDepth
1361#define ScrnTrns_DstDepth 5
1362
1363#include "SCRNTRNS.h"
1364
1365#endif
1366
1367#if EnableMagnify && (vMacScreenDepth >= 4)
1368
1369#define ScrnTrns_DoTrans UpdateTransScaledColorCopy
1370#define ScrnTrns_Src GetCurDrawBuff()
1371#define ScrnTrns_Dst ScalingBuff
1372#define ScrnTrns_SrcDepth vMacScreenDepth
1373#define ScrnTrns_DstDepth 5
1374#define ScrnTrns_Scale MyWindowScale
1375
1376#include "SCRNTRNS.h"
1377
1378#endif
1379
1380
1381#if EnableMagnify && UseColorImage
1382
1383#define ScrnMapr_DoMap UpdateMappedScaledBW2ColorCopy
1384#define ScrnMapr_Src GetCurDrawBuff()
1385#define ScrnMapr_Dst ScalingBuff
1386#define ScrnMapr_SrcDepth 0
1387#define ScrnMapr_DstDepth 5
1388#define ScrnMapr_Map ScalingTabl
1389#define ScrnMapr_Scale MyWindowScale
1390
1391#include "SCRNMAPR.h"
1392
1393#endif
1394
1395
1396#if UseColorImage
1397
1398#define ScrnMapr_DoMap UpdateMappedBW2ColorCopy
1399#define ScrnMapr_Src GetCurDrawBuff()
1400#define ScrnMapr_Dst ScalingBuff
1401#define ScrnMapr_SrcDepth 0
1402#define ScrnMapr_DstDepth 5
1403#define ScrnMapr_Map ScalingTabl
1404
1405#include "SCRNMAPR.h"
1406
1407#endif
1408
1409
1410LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left,
1411 ui4r bottom, ui4r right)
1412{
1413 int XDest;
1414 int YDest;
1415 char *the_data;
1416
1417#if VarFullScreen
1418 if (UseFullScreen)
1419#endif
1420#if MayFullScreen
1421 {
1422 if (top < ViewVStart) {
1423 top = ViewVStart;
1424 }
1425 if (left < ViewHStart) {
1426 left = ViewHStart;
1427 }
1428 if (bottom > ViewVStart + ViewVSize) {
1429 bottom = ViewVStart + ViewVSize;
1430 }
1431 if (right > ViewHStart + ViewHSize) {
1432 right = ViewHStart + ViewHSize;
1433 }
1434
1435 if ((top >= bottom) || (left >= right)) {
1436 goto label_exit;
1437 }
1438 }
1439#endif
1440
1441 XDest = left;
1442 YDest = top;
1443
1444#if VarFullScreen
1445 if (UseFullScreen)
1446#endif
1447#if MayFullScreen
1448 {
1449 XDest -= ViewHStart;
1450 YDest -= ViewVStart;
1451 }
1452#endif
1453
1454#if EnableMagnify
1455 if (UseMagnify) {
1456 XDest *= MyWindowScale;
1457 YDest *= MyWindowScale;
1458 }
1459#endif
1460
1461#if VarFullScreen
1462 if (UseFullScreen)
1463#endif
1464#if MayFullScreen
1465 {
1466 XDest += hOffset;
1467 YDest += vOffset;
1468 }
1469#endif
1470
1471#if EnableMagnify
1472 if (UseMagnify) {
1473#if UseColorImage
1474#if 0 != vMacScreenDepth
1475 if (UseColorMode) {
1476#if vMacScreenDepth < 4
1477 if (! ColorTransValid) {
1478 SetUpColorScalingTabl();
1479 ColorTransValid = trueblnr;
1480 }
1481
1482 UpdateMappedScaledColorCopy(top, left, bottom, right);
1483#else
1484 UpdateTransScaledColorCopy(top, left, bottom, right);
1485#endif
1486 } else
1487#endif /* 0 != vMacScreenDepth */
1488 {
1489 if (! ColorTransValid) {
1490 SetUpBW2ColorScalingTabl();
1491 ColorTransValid = trueblnr;
1492 }
1493
1494 UpdateMappedScaledBW2ColorCopy(top, left, bottom, right);
1495 }
1496#else /* ! UseColorImage */
1497 /* assume 0 == vMacScreenDepth */
1498 {
1499 if (! ColorTransValid) {
1500 SetUpScalingTabl();
1501 ColorTransValid = trueblnr;
1502 }
1503
1504 UpdateScaledBWCopy(top, left, bottom, right);
1505 }
1506#endif /* UseColorImage */
1507
1508 {
1509 char *saveData = my_Scaled_image->data;
1510 my_Scaled_image->data = (char *)ScalingBuff;
1511
1512 XPutImage(x_display, my_main_wind, my_gc, my_Scaled_image,
1513 left * MyWindowScale, top * MyWindowScale,
1514 XDest, YDest,
1515 (right - left) * MyWindowScale,
1516 (bottom - top) * MyWindowScale);
1517
1518 my_Scaled_image->data = saveData;
1519 }
1520 } else
1521#endif /* EnableMagnify */
1522 {
1523#if UseColorImage
1524#if 0 != vMacScreenDepth
1525 if (UseColorMode) {
1526#if vMacScreenDepth < 4
1527
1528 if (! ColorTransValid) {
1529 SetUpColorTabl();
1530 ColorTransValid = trueblnr;
1531 }
1532
1533 UpdateMappedColorCopy(top, left, bottom, right);
1534
1535 the_data = (char *)ScalingBuff;
1536#else
1537 /*
1538 if vMacScreenDepth == 5 and MSBFirst, could
1539 copy directly with the_data = (char *)GetCurDrawBuff();
1540 */
1541 UpdateTransColorCopy(top, left, bottom, right);
1542
1543 the_data = (char *)ScalingBuff;
1544#endif
1545 } else
1546#endif /* 0 != vMacScreenDepth */
1547 {
1548 if (! ColorTransValid) {
1549 SetUpBW2ColorTabl();
1550 ColorTransValid = trueblnr;
1551 }
1552
1553 UpdateMappedBW2ColorCopy(top, left, bottom, right);
1554
1555 the_data = (char *)ScalingBuff;
1556 }
1557#else /* ! UseColorImage */
1558 {
1559 the_data = (char *)GetCurDrawBuff();
1560 }
1561#endif /* UseColorImage */
1562
1563 {
1564 char *saveData = my_image->data;
1565 my_image->data = the_data;
1566
1567 XPutImage(x_display, my_main_wind, my_gc, my_image,
1568 left, top, XDest, YDest,
1569 right - left, bottom - top);
1570
1571 my_image->data = saveData;
1572 }
1573 }
1574
1575#if MayFullScreen
1576label_exit:
1577 ;
1578#endif
1579}
1580
1581LOCALPROC MyDrawChangesAndClear(void)
1582{
1583 if (ScreenChangedBottom > ScreenChangedTop) {
1584 HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
1585 ScreenChangedBottom, ScreenChangedRight);
1586 ScreenClearChanges();
1587 }
1588}
1589
1590/* --- mouse --- */
1591
1592/* cursor hiding */
1593
1594LOCALVAR blnr HaveCursorHidden = falseblnr;
1595LOCALVAR blnr WantCursorHidden = falseblnr;
1596
1597LOCALPROC ForceShowCursor(void)
1598{
1599 if (HaveCursorHidden) {
1600 HaveCursorHidden = falseblnr;
1601 if (my_main_wind) {
1602 XUndefineCursor(x_display, my_main_wind);
1603 }
1604 }
1605}
1606
1607LOCALVAR Cursor blankCursor = None;
1608
1609LOCALFUNC blnr CreateMyBlankCursor(Window rootwin)
1610/*
1611 adapted from X11_CreateNullCursor in context.x11.c
1612 in quakeforge 0.5.5, copyright Id Software, Inc.
1613 Zephaniah E. Hull, and Jeff Teunissen.
1614*/
1615{
1616 Pixmap cursormask;
1617 XGCValues xgc;
1618 GC gc;
1619 blnr IsOk = falseblnr;
1620
1621 cursormask = XCreatePixmap(x_display, rootwin, 1, 1, 1);
1622 if (None == cursormask) {
1623 WriteExtraErr("XCreatePixmap failed.");
1624 } else {
1625 xgc.function = GXclear;
1626 gc = XCreateGC(x_display, cursormask, GCFunction, &xgc);
1627 if (None == gc) {
1628 WriteExtraErr("XCreateGC failed.");
1629 } else {
1630 XFillRectangle(x_display, cursormask, gc, 0, 0, 1, 1);
1631 XFreeGC(x_display, gc);
1632
1633 blankCursor = XCreatePixmapCursor(x_display, cursormask,
1634 cursormask, &x_black, &x_white, 0, 0);
1635 if (None == blankCursor) {
1636 WriteExtraErr("XCreatePixmapCursor failed.");
1637 } else {
1638 IsOk = trueblnr;
1639 }
1640 }
1641
1642 XFreePixmap(x_display, cursormask);
1643 /*
1644 assuming that XCreatePixmapCursor doesn't think it
1645 owns the pixmaps passed to it. I've seen code that
1646 assumes this, and other code that seems to assume
1647 the opposite.
1648 */
1649 }
1650 return IsOk;
1651}
1652
1653/* cursor moving */
1654
1655#if EnableMoveMouse
1656LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
1657{
1658 int NewMousePosh;
1659 int NewMousePosv;
1660 int root_x_return;
1661 int root_y_return;
1662 Window root_return;
1663 Window child_return;
1664 unsigned int mask_return;
1665 blnr IsOk;
1666 int attempts = 0;
1667
1668#if VarFullScreen
1669 if (UseFullScreen)
1670#endif
1671#if MayFullScreen
1672 {
1673 h -= ViewHStart;
1674 v -= ViewVStart;
1675 }
1676#endif
1677
1678#if EnableMagnify
1679 if (UseMagnify) {
1680 h *= MyWindowScale;
1681 v *= MyWindowScale;
1682 }
1683#endif
1684
1685#if VarFullScreen
1686 if (UseFullScreen)
1687#endif
1688#if MayFullScreen
1689 {
1690 h += hOffset;
1691 v += vOffset;
1692 }
1693#endif
1694
1695 do {
1696 XWarpPointer(x_display, None, my_main_wind, 0, 0, 0, 0, h, v);
1697 XQueryPointer(x_display, my_main_wind,
1698 &root_return, &child_return,
1699 &root_x_return, &root_y_return,
1700 &NewMousePosh, &NewMousePosv,
1701 &mask_return);
1702 IsOk = (h == NewMousePosh) && (v == NewMousePosv);
1703 ++attempts;
1704 } while ((! IsOk) && (attempts < 10));
1705 return IsOk;
1706}
1707#endif
1708
1709#if EnableFSMouseMotion
1710LOCALPROC StartSaveMouseMotion(void)
1711{
1712 if (! HaveMouseMotion) {
1713 if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
1714 ViewVStart + (ViewVSize / 2)))
1715 {
1716 SavedMouseH = ViewHStart + (ViewHSize / 2);
1717 SavedMouseV = ViewVStart + (ViewVSize / 2);
1718 HaveMouseMotion = trueblnr;
1719 }
1720 }
1721}
1722#endif
1723
1724#if EnableFSMouseMotion
1725LOCALPROC StopSaveMouseMotion(void)
1726{
1727 if (HaveMouseMotion) {
1728 (void) MyMoveMouse(CurMouseH, CurMouseV);
1729 HaveMouseMotion = falseblnr;
1730 }
1731}
1732#endif
1733
1734/* cursor state */
1735
1736#if EnableFSMouseMotion
1737LOCALPROC MyMouseConstrain(void)
1738{
1739 si4b shiftdh;
1740 si4b shiftdv;
1741
1742 if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
1743 shiftdh = ViewHSize / 2;
1744 } else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) {
1745 shiftdh = - ViewHSize / 2;
1746 } else {
1747 shiftdh = 0;
1748 }
1749 if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
1750 shiftdv = ViewVSize / 2;
1751 } else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) {
1752 shiftdv = - ViewVSize / 2;
1753 } else {
1754 shiftdv = 0;
1755 }
1756 if ((shiftdh != 0) || (shiftdv != 0)) {
1757 SavedMouseH += shiftdh;
1758 SavedMouseV += shiftdv;
1759 if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
1760 HaveMouseMotion = falseblnr;
1761 }
1762 }
1763}
1764#endif
1765
1766LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
1767{
1768 blnr ShouldHaveCursorHidden = trueblnr;
1769
1770#if VarFullScreen
1771 if (UseFullScreen)
1772#endif
1773#if MayFullScreen
1774 {
1775 NewMousePosh -= hOffset;
1776 NewMousePosv -= vOffset;
1777 }
1778#endif
1779
1780#if EnableMagnify
1781 if (UseMagnify) {
1782 NewMousePosh /= MyWindowScale;
1783 NewMousePosv /= MyWindowScale;
1784 }
1785#endif
1786
1787#if VarFullScreen
1788 if (UseFullScreen)
1789#endif
1790#if MayFullScreen
1791 {
1792 NewMousePosh += ViewHStart;
1793 NewMousePosv += ViewVStart;
1794 }
1795#endif
1796
1797#if EnableFSMouseMotion
1798 if (HaveMouseMotion) {
1799 MyMousePositionSetDelta(NewMousePosh - SavedMouseH,
1800 NewMousePosv - SavedMouseV);
1801 SavedMouseH = NewMousePosh;
1802 SavedMouseV = NewMousePosv;
1803 } else
1804#endif
1805 {
1806 if (NewMousePosh < 0) {
1807 NewMousePosh = 0;
1808 ShouldHaveCursorHidden = falseblnr;
1809 } else if (NewMousePosh >= vMacScreenWidth) {
1810 NewMousePosh = vMacScreenWidth - 1;
1811 ShouldHaveCursorHidden = falseblnr;
1812 }
1813 if (NewMousePosv < 0) {
1814 NewMousePosv = 0;
1815 ShouldHaveCursorHidden = falseblnr;
1816 } else if (NewMousePosv >= vMacScreenHeight) {
1817 NewMousePosv = vMacScreenHeight - 1;
1818 ShouldHaveCursorHidden = falseblnr;
1819 }
1820
1821#if VarFullScreen
1822 if (UseFullScreen)
1823#endif
1824#if MayFullScreen
1825 {
1826 ShouldHaveCursorHidden = trueblnr;
1827 }
1828#endif
1829
1830 /* if (ShouldHaveCursorHidden || CurMouseButton) */
1831 /*
1832 for a game like arkanoid, would like mouse to still
1833 move even when outside window in one direction
1834 */
1835 MyMousePositionSet(NewMousePosh, NewMousePosv);
1836 }
1837
1838 WantCursorHidden = ShouldHaveCursorHidden;
1839}
1840
1841LOCALPROC CheckMouseState(void)
1842{
1843 int NewMousePosh;
1844 int NewMousePosv;
1845 int root_x_return;
1846 int root_y_return;
1847 Window root_return;
1848 Window child_return;
1849 unsigned int mask_return;
1850
1851 XQueryPointer(x_display, my_main_wind,
1852 &root_return, &child_return,
1853 &root_x_return, &root_y_return,
1854 &NewMousePosh, &NewMousePosv,
1855 &mask_return);
1856 MousePositionNotify(NewMousePosh, NewMousePosv);
1857}
1858
1859/* --- keyboard input --- */
1860
1861/*
1862 translation table - X11 KeySym -> Mac key code
1863
1864 Used to create KC2MKC table (X11 key code -> Mac key code)
1865
1866 Includes effect of any key mapping set with the
1867 mini vmac '-km' compile time option.
1868
1869 The real CapsLock key needs special treatment,
1870 so use MKC_real_CapsLock here,
1871 which is later remapped to MKC_formac_CapsLock.
1872
1873 Ordered to match order of keycodes on Linux, the most
1874 common port using this X11 code, making the code using
1875 this table more efficient.
1876*/
1877
1878/*
1879 The actual data is in the comments of this enum,
1880 from which MT2KeySym and MT2MKC are created by script.
1881*/
1882enum {
1883 kMT_Escape, /* XK_Escape MKC_formac_Escape */
1884 kMT_1, /* XK_1 MKC_1 */
1885 kMT_2, /* XK_2 MKC_2 */
1886 kMT_3, /* XK_3 MKC_3 */
1887 kMT_4, /* XK_4 MKC_4 */
1888 kMT_5, /* XK_5 MKC_5 */
1889 kMT_6, /* XK_6 MKC_6 */
1890 kMT_7, /* XK_7 MKC_7 */
1891 kMT_8, /* XK_8 MKC_8 */
1892 kMT_9, /* XK_9 MKC_9 */
1893 kMT_0, /* XK_0 MKC_0 */
1894 kMT_minus, /* XK_minus MKC_Minus */
1895 kMT_underscore, /* XK_underscore MKC_Minus */
1896 kMT_equal, /* XK_equal MKC_Equal */
1897 kMT_plus, /* XK_plus MKC_Equal */
1898 kMT_BackSpace, /* XK_BackSpace MKC_BackSpace */
1899 kMT_Tab, /* XK_Tab MKC_Tab */
1900 kMT_q, /* XK_q MKC_Q */
1901 kMT_Q, /* XK_Q MKC_Q */
1902 kMT_w, /* XK_w MKC_W */
1903 kMT_W, /* XK_W MKC_W */
1904 kMT_e, /* XK_e MKC_E */
1905 kMT_E, /* XK_E MKC_E */
1906 kMT_r, /* XK_r MKC_R */
1907 kMT_R, /* XK_R MKC_R */
1908 kMT_t, /* XK_t MKC_T */
1909 kMT_T, /* XK_T MKC_T */
1910 kMT_y, /* XK_y MKC_Y */
1911 kMT_Y, /* XK_Y MKC_Y */
1912 kMT_u, /* XK_u MKC_U */
1913 kMT_U, /* XK_U MKC_U */
1914 kMT_i, /* XK_i MKC_I */
1915 kMT_I, /* XK_I MKC_I */
1916 kMT_o, /* XK_o MKC_O */
1917 kMT_O, /* XK_O MKC_O */
1918 kMT_p, /* XK_p MKC_P */
1919 kMT_P, /* XK_P MKC_P */
1920 kMT_bracketleft, /* XK_bracketleft MKC_LeftBracket */
1921 kMT_braceleft, /* XK_braceleft MKC_LeftBracket */
1922 kMT_bracketright, /* XK_bracketright MKC_RightBracket */
1923 kMT_braceright, /* XK_braceright MKC_RightBracket */
1924 kMT_Return, /* XK_Return MKC_Return */
1925 kMT_Control_L, /* XK_Control_L MKC_formac_Control */
1926 kMT_a, /* XK_a MKC_A */
1927 kMT_A, /* XK_A MKC_A */
1928 kMT_s, /* XK_s MKC_S */
1929 kMT_S, /* XK_S MKC_S */
1930 kMT_d, /* XK_d MKC_D */
1931 kMT_D, /* XK_D MKC_D */
1932 kMT_f, /* XK_f MKC_F */
1933 kMT_F, /* XK_F MKC_F */
1934 kMT_g, /* XK_g MKC_G */
1935 kMT_G, /* XK_G MKC_G */
1936 kMT_h, /* XK_h MKC_H */
1937 kMT_H, /* XK_H MKC_H */
1938 kMT_j, /* XK_j MKC_J */
1939 kMT_J, /* XK_J MKC_J */
1940 kMT_k, /* XK_k MKC_K */
1941 kMT_K, /* XK_K MKC_K */
1942 kMT_l, /* XK_l MKC_L */
1943 kMT_L, /* XK_L MKC_L */
1944 kMT_semicolon, /* XK_semicolon MKC_SemiColon */
1945 kMT_colon, /* XK_colon MKC_SemiColon */
1946 kMT_apostrophe, /* XK_apostrophe MKC_SingleQuote */
1947 kMT_quotedbl, /* XK_quotedbl MKC_SingleQuote */
1948 kMT_grave, /* XK_grave MKC_formac_Grave */
1949 kMT_asciitilde, /* XK_asciitilde MKC_formac_Grave */
1950 kMT_Shift_L, /* XK_Shift_L MKC_formac_Shift */
1951 kMT_backslash, /* XK_backslash MKC_formac_BackSlash */
1952 kMT_bar, /* XK_bar MKC_formac_BackSlash */
1953 kMT_z, /* XK_z MKC_Z */
1954 kMT_Z, /* XK_Z MKC_Z */
1955 kMT_x, /* XK_x MKC_X */
1956 kMT_X, /* XK_X MKC_X */
1957 kMT_c, /* XK_c MKC_C */
1958 kMT_C, /* XK_C MKC_C */
1959 kMT_v, /* XK_v MKC_V */
1960 kMT_V, /* XK_V MKC_V */
1961 kMT_b, /* XK_b MKC_B */
1962 kMT_B, /* XK_B MKC_B */
1963 kMT_n, /* XK_n MKC_N */
1964 kMT_N, /* XK_N MKC_N */
1965 kMT_m, /* XK_m MKC_M */
1966 kMT_M, /* XK_M MKC_M */
1967 kMT_comma, /* XK_comma MKC_Comma */
1968 kMT_period, /* XK_period MKC_Period */
1969 kMT_greater, /* XK_greater MKC_Period */
1970 kMT_slash, /* XK_slash MKC_formac_Slash */
1971 kMT_question, /* XK_question MKC_formac_Slash */
1972 kMT_Shift_R, /* XK_Shift_R MKC_formac_RShift */
1973 kMT_KP_Multiply, /* XK_KP_Multiply MKC_KPMultiply */
1974 kMT_Alt_L, /* XK_Alt_L MKC_formac_Command */
1975 kMT_space, /* XK_space MKC_Space */
1976 kMT_Caps_Lock, /* XK_Caps_Lock MKC_real_CapsLock */
1977 kMT_F1, /* XK_F1 MKC_formac_F1 */
1978 kMT_F2, /* XK_F2 MKC_formac_F2 */
1979 kMT_F3, /* XK_F3 MKC_formac_F3 */
1980 kMT_F4, /* XK_F4 MKC_formac_F4 */
1981 kMT_F5, /* XK_F5 MKC_formac_F5 */
1982 kMT_F6, /* XK_F6 MKC_F6 */
1983 kMT_F7, /* XK_F7 MKC_F7 */
1984 kMT_F8, /* XK_F8 MKC_F8 */
1985 kMT_F9, /* XK_F9 MKC_F9 */
1986 kMT_F10, /* XK_F10 MKC_F10 */
1987 kMT_Num_Lock, /* XK_Num_Lock MKC_Clear */
1988#ifdef XK_Scroll_Lock
1989 kMT_Scroll_Lock, /* XK_Scroll_Lock MKC_ScrollLock */
1990#endif
1991#ifdef XK_F14
1992 kMT_F14, /* XK_F14 MKC_ScrollLock */
1993#endif
1994
1995 kMT_KP_7, /* XK_KP_7 MKC_KP7 */
1996#ifdef XK_KP_Home
1997 kMT_KP_Home, /* XK_KP_Home MKC_KP7 */
1998#endif
1999
2000 kMT_KP_8, /* XK_KP_8 MKC_KP8 */
2001#ifdef XK_KP_Up
2002 kMT_KP_Up, /* XK_KP_Up MKC_KP8 */
2003#endif
2004
2005 kMT_KP_9, /* XK_KP_9 MKC_KP9 */
2006#ifdef XK_KP_Page_Up
2007 kMT_KP_Page_Up, /* XK_KP_Page_Up MKC_KP9 */
2008#else
2009#ifdef XK_KP_Prior
2010 kMT_KP_Prior, /* XK_KP_Prior MKC_KP9 */
2011#endif
2012#endif
2013
2014 kMT_KP_Subtract, /* XK_KP_Subtract MKC_KPSubtract */
2015
2016 kMT_KP_4, /* XK_KP_4 MKC_KP4 */
2017#ifdef XK_KP_Left
2018 kMT_KP_Left, /* XK_KP_Left MKC_KP4 */
2019#endif
2020
2021 kMT_KP_5, /* XK_KP_5 MKC_KP5 */
2022#ifdef XK_KP_Begin
2023 kMT_KP_Begin, /* XK_KP_Begin MKC_KP5 */
2024#endif
2025
2026 kMT_KP_6, /* XK_KP_6 MKC_KP6 */
2027#ifdef XK_KP_Right
2028 kMT_KP_Right, /* XK_KP_Right MKC_KP6 */
2029#endif
2030
2031 kMT_KP_Add, /* XK_KP_Add MKC_KPAdd */
2032
2033 kMT_KP_1, /* XK_KP_1 MKC_KP1 */
2034#ifdef XK_KP_End
2035 kMT_KP_End, /* XK_KP_End MKC_KP1 */
2036#endif
2037
2038 kMT_KP_2, /* XK_KP_2 MKC_KP2 */
2039#ifdef XK_KP_Down
2040 kMT_KP_Down, /* XK_KP_Down MKC_KP2 */
2041#endif
2042
2043 kMT_KP_3, /* XK_KP_3 MKC_KP3 */
2044#ifdef XK_Page_Down
2045 kMT_KP_Page_Down, /* XK_KP_Page_Down MKC_KP3 */
2046#else
2047#ifdef XK_KP_Next
2048 kMT_KP_Next, /* XK_KP_Next MKC_KP3 */
2049#endif
2050#endif
2051
2052 kMT_KP_0, /* XK_KP_0 MKC_KP0 */
2053#ifdef XK_KP_Insert
2054 kMT_KP_Insert, /* XK_KP_Insert MKC_KP0 */
2055#endif
2056#ifdef XK_KP_Delete
2057 kMT_KP_Delete, /* XK_KP_Delete MKC_Decimal */
2058#endif
2059
2060 /* XK_ISO_Level3_Shift */
2061 /* nothing */
2062#ifdef XK_less
2063 kMT_less, /* XK_less MKC_Comma */
2064#endif
2065 kMT_F11, /* XK_F11 MKC_F11 */
2066 kMT_F12, /* XK_F12 MKC_F12 */
2067 /* nothing */
2068 /* XK_Katakana */
2069 /* XK_Hiragana */
2070 /* XK_Henkan */
2071 /* XK_Hiragana_Katakana */
2072 /* XK_Muhenkan */
2073 /* nothing */
2074 kMT_KP_Enter, /* XK_KP_Enter MKC_formac_Enter */
2075 kMT_Control_R, /* XK_Control_R MKC_formac_RControl */
2076 kMT_KP_Divide, /* XK_KP_Divide MKC_KPDevide */
2077#ifdef XK_Print
2078 kMT_Print, /* XK_Print MKC_Print */
2079#endif
2080 kMT_Alt_R, /* XK_Alt_R MKC_formac_RCommand */
2081 /* XK_Linefeed */
2082#ifdef XK_Home
2083 kMT_Home, /* XK_Home MKC_formac_Home */
2084#endif
2085 kMT_Up, /* XK_Up MKC_Up */
2086
2087#ifdef XK_Page_Up
2088 kMT_Page_Up, /* XK_Page_Up MKC_formac_PageUp */
2089#else
2090#ifdef XK_Prior
2091 kMT_Prior, /* XK_Prior MKC_formac_PageUp */
2092#endif
2093#endif
2094
2095 kMT_Left, /* XK_Left MKC_Left */
2096 kMT_Right, /* XK_Right MKC_Right */
2097#ifdef XK_End
2098 kMT_End, /* XK_End MKC_formac_End */
2099#endif
2100 kMT_Down, /* XK_Down MKC_Down */
2101
2102#ifdef XK_Page_Down
2103 kMT_Page_Down, /* XK_Page_Down MKC_formac_PageDown */
2104#else
2105#ifdef XK_Next
2106 kMT_Next, /* XK_Next MKC_formac_PageDown */
2107#endif
2108#endif
2109
2110#ifdef XK_Insert
2111 kMT_Insert, /* XK_Insert MKC_formac_Help */
2112#endif
2113#ifdef XK_Delete
2114 kMT_Delete, /* XK_Delete MKC_formac_ForwardDel */
2115#endif
2116 /* nothing */
2117 /* ? */
2118 /* ? */
2119 /* ? */
2120 /* ? */
2121 kMT_KP_Equal, /* XK_KP_Equal MKC_KPEqual */
2122 /* XK_plusminus */
2123#ifdef XK_Pause
2124 kMT_Pause, /* XK_Pause MKC_Pause */
2125#endif
2126#ifdef XK_F15
2127 kMT_F15, /* XK_F15 MKC_Pause */
2128#endif
2129 /* ? */
2130 kMT_KP_Decimal, /* XK_KP_Decimal MKC_Decimal */
2131 /* XK_Hangul */
2132 /* XK_Hangul_Hanja */
2133 /* nothing */
2134 kMT_Super_L, /* XK_Super_L MKC_formac_Option */
2135 kMT_Super_R, /* XK_Super_R MKC_formac_ROption */
2136 kMT_Menu, /* XK_Menu MKC_formac_Option */
2137 /* XK_Cancel */
2138 /* XK_Redo */
2139 /* ? */
2140 /* XK_Undo */
2141 /* ? */
2142 /* ? */
2143 /* ? */
2144 /* ? */
2145 /* XK_Find */
2146 /* ? */
2147#ifdef XK_Help
2148 kMT_Help, /* XK_Help MKC_formac_Help */
2149#endif
2150 /* ? */
2151 /* ? */
2152 /* nothing */
2153 /* ? */
2154 /* ? */
2155 /* ? */
2156 /* ? */
2157 /* nothing */
2158
2159 /* XK_parenleft */
2160 /* XK_parenright */
2161
2162 /* XK_Mode_switch */
2163
2164
2165
2166 kMT_Meta_L, /* XK_Meta_L MKC_formac_Command */
2167 kMT_Meta_R, /* XK_Meta_R MKC_formac_RCommand */
2168
2169 kMT_Mode_switch, /* XK_Mode_switch MKC_formac_Option */
2170 kMT_Hyper_L, /* XK_Hyper_L MKC_formac_Option */
2171 kMT_Hyper_R, /* XK_Hyper_R MKC_formac_ROption */
2172
2173 kMT_F13, /* XK_F13 MKC_formac_Option */
2174 /*
2175 seen being used in Mandrake Linux 9.2
2176 for windows key
2177 */
2178
2179 kNumMTs
2180};
2181
2182/*
2183 MT2KeySym was generated by a script from
2184 enum and comments above.
2185*/
2186LOCALVAR const KeySym MT2KeySym[kNumMTs + 1] = {
2187 XK_Escape, /* kMT_Escape */
2188 XK_1, /* kMT_1 */
2189 XK_2, /* kMT_2 */
2190 XK_3, /* kMT_3 */
2191 XK_4, /* kMT_4 */
2192 XK_5, /* kMT_5 */
2193 XK_6, /* kMT_6 */
2194 XK_7, /* kMT_7 */
2195 XK_8, /* kMT_8 */
2196 XK_9, /* kMT_9 */
2197 XK_0, /* kMT_0 */
2198 XK_minus, /* kMT_minus */
2199 XK_underscore, /* kMT_underscore */
2200 XK_equal, /* kMT_equal */
2201 XK_plus, /* kMT_plus */
2202 XK_BackSpace, /* kMT_BackSpace */
2203 XK_Tab, /* kMT_Tab */
2204 XK_q, /* kMT_q */
2205 XK_Q, /* kMT_Q */
2206 XK_w, /* kMT_w */
2207 XK_W, /* kMT_W */
2208 XK_e, /* kMT_e */
2209 XK_E, /* kMT_E */
2210 XK_r, /* kMT_r */
2211 XK_R, /* kMT_R */
2212 XK_t, /* kMT_t */
2213 XK_T, /* kMT_T */
2214 XK_y, /* kMT_y */
2215 XK_Y, /* kMT_Y */
2216 XK_u, /* kMT_u */
2217 XK_U, /* kMT_U */
2218 XK_i, /* kMT_i */
2219 XK_I, /* kMT_I */
2220 XK_o, /* kMT_o */
2221 XK_O, /* kMT_O */
2222 XK_p, /* kMT_p */
2223 XK_P, /* kMT_P */
2224 XK_bracketleft, /* kMT_bracketleft */
2225 XK_braceleft, /* kMT_braceleft */
2226 XK_bracketright, /* kMT_bracketright */
2227 XK_braceright, /* kMT_braceright */
2228 XK_Return, /* kMT_Return */
2229 XK_Control_L, /* kMT_Control_L */
2230 XK_a, /* kMT_a */
2231 XK_A, /* kMT_A */
2232 XK_s, /* kMT_s */
2233 XK_S, /* kMT_S */
2234 XK_d, /* kMT_d */
2235 XK_D, /* kMT_D */
2236 XK_f, /* kMT_f */
2237 XK_F, /* kMT_F */
2238 XK_g, /* kMT_g */
2239 XK_G, /* kMT_G */
2240 XK_h, /* kMT_h */
2241 XK_H, /* kMT_H */
2242 XK_j, /* kMT_j */
2243 XK_J, /* kMT_J */
2244 XK_k, /* kMT_k */
2245 XK_K, /* kMT_K */
2246 XK_l, /* kMT_l */
2247 XK_L, /* kMT_L */
2248 XK_semicolon, /* kMT_semicolon */
2249 XK_colon, /* kMT_colon */
2250 XK_apostrophe, /* kMT_apostrophe */
2251 XK_quotedbl, /* kMT_quotedbl */
2252 XK_grave, /* kMT_grave */
2253 XK_asciitilde, /* kMT_asciitilde */
2254 XK_Shift_L, /* kMT_Shift_L */
2255 XK_backslash, /* kMT_backslash */
2256 XK_bar, /* kMT_bar */
2257 XK_z, /* kMT_z */
2258 XK_Z, /* kMT_Z */
2259 XK_x, /* kMT_x */
2260 XK_X, /* kMT_X */
2261 XK_c, /* kMT_c */
2262 XK_C, /* kMT_C */
2263 XK_v, /* kMT_v */
2264 XK_V, /* kMT_V */
2265 XK_b, /* kMT_b */
2266 XK_B, /* kMT_B */
2267 XK_n, /* kMT_n */
2268 XK_N, /* kMT_N */
2269 XK_m, /* kMT_m */
2270 XK_M, /* kMT_M */
2271 XK_comma, /* kMT_comma */
2272 XK_period, /* kMT_period */
2273 XK_greater, /* kMT_greater */
2274 XK_slash, /* kMT_slash */
2275 XK_question, /* kMT_question */
2276 XK_Shift_R, /* kMT_Shift_R */
2277 XK_KP_Multiply, /* kMT_KP_Multiply */
2278 XK_Alt_L, /* kMT_Alt_L */
2279 XK_space, /* kMT_space */
2280 XK_Caps_Lock, /* kMT_Caps_Lock */
2281 XK_F1, /* kMT_F1 */
2282 XK_F2, /* kMT_F2 */
2283 XK_F3, /* kMT_F3 */
2284 XK_F4, /* kMT_F4 */
2285 XK_F5, /* kMT_F5 */
2286 XK_F6, /* kMT_F6 */
2287 XK_F7, /* kMT_F7 */
2288 XK_F8, /* kMT_F8 */
2289 XK_F9, /* kMT_F9 */
2290 XK_F10, /* kMT_F10 */
2291 XK_Num_Lock, /* kMT_Num_Lock */
2292#ifdef XK_Scroll_Lock
2293 XK_Scroll_Lock, /* kMT_Scroll_Lock */
2294#endif
2295#ifdef XK_F14
2296 XK_F14, /* kMT_F14 */
2297#endif
2298
2299 XK_KP_7, /* kMT_KP_7 */
2300#ifdef XK_KP_Home
2301 XK_KP_Home, /* kMT_KP_Home */
2302#endif
2303
2304 XK_KP_8, /* kMT_KP_8 */
2305#ifdef XK_KP_Up
2306 XK_KP_Up, /* kMT_KP_Up */
2307#endif
2308
2309 XK_KP_9, /* kMT_KP_9 */
2310#ifdef XK_KP_Page_Up
2311 XK_KP_Page_Up, /* kMT_KP_Page_Up */
2312#else
2313#ifdef XK_KP_Prior
2314 XK_KP_Prior, /* kMT_KP_Prior */
2315#endif
2316#endif
2317
2318 XK_KP_Subtract, /* kMT_KP_Subtract */
2319
2320 XK_KP_4, /* kMT_KP_4 */
2321#ifdef XK_KP_Left
2322 XK_KP_Left, /* kMT_KP_Left */
2323#endif
2324
2325 XK_KP_5, /* kMT_KP_5 */
2326#ifdef XK_KP_Begin
2327 XK_KP_Begin, /* kMT_KP_Begin */
2328#endif
2329
2330 XK_KP_6, /* kMT_KP_6 */
2331#ifdef XK_KP_Right
2332 XK_KP_Right, /* kMT_KP_Right */
2333#endif
2334
2335 XK_KP_Add, /* kMT_KP_Add */
2336
2337 XK_KP_1, /* kMT_KP_1 */
2338#ifdef XK_KP_End
2339 XK_KP_End, /* kMT_KP_End */
2340#endif
2341
2342 XK_KP_2, /* kMT_KP_2 */
2343#ifdef XK_KP_Down
2344 XK_KP_Down, /* kMT_KP_Down */
2345#endif
2346
2347 XK_KP_3, /* kMT_KP_3 */
2348#ifdef XK_Page_Down
2349 XK_KP_Page_Down, /* kMT_KP_Page_Down */
2350#else
2351#ifdef XK_KP_Next
2352 XK_KP_Next, /* kMT_KP_Next */
2353#endif
2354#endif
2355
2356 XK_KP_0, /* kMT_KP_0 */
2357#ifdef XK_KP_Insert
2358 XK_KP_Insert, /* kMT_KP_Insert */
2359#endif
2360#ifdef XK_KP_Delete
2361 XK_KP_Delete, /* kMT_KP_Delete */
2362#endif
2363
2364 /* XK_ISO_Level3_Shift */
2365 /* nothing */
2366#ifdef XK_less
2367 XK_less, /* kMT_less */
2368#endif
2369 XK_F11, /* kMT_F11 */
2370 XK_F12, /* kMT_F12 */
2371 /* nothing */
2372 /* XK_Katakana */
2373 /* XK_Hiragana */
2374 /* XK_Henkan */
2375 /* XK_Hiragana_Katakana */
2376 /* XK_Muhenkan */
2377 /* nothing */
2378 XK_KP_Enter, /* kMT_KP_Enter */
2379 XK_Control_R, /* kMT_Control_R */
2380 XK_KP_Divide, /* kMT_KP_Divide */
2381#ifdef XK_Print
2382 XK_Print, /* kMT_Print */
2383#endif
2384 XK_Alt_R, /* kMT_Alt_R */
2385 /* XK_Linefeed */
2386#ifdef XK_Home
2387 XK_Home, /* kMT_Home */
2388#endif
2389 XK_Up, /* kMT_Up */
2390
2391#ifdef XK_Page_Up
2392 XK_Page_Up, /* kMT_Page_Up */
2393#else
2394#ifdef XK_Prior
2395 XK_Prior, /* kMT_Prior */
2396#endif
2397#endif
2398
2399 XK_Left, /* kMT_Left */
2400 XK_Right, /* kMT_Right */
2401#ifdef XK_End
2402 XK_End, /* kMT_End */
2403#endif
2404 XK_Down, /* kMT_Down */
2405
2406#ifdef XK_Page_Down
2407 XK_Page_Down, /* kMT_Page_Down */
2408#else
2409#ifdef XK_Next
2410 XK_Next, /* kMT_Next */
2411#endif
2412#endif
2413
2414#ifdef XK_Insert
2415 XK_Insert, /* kMT_Insert */
2416#endif
2417#ifdef XK_Delete
2418 XK_Delete, /* kMT_Delete */
2419#endif
2420 /* nothing */
2421 /* ? */
2422 /* ? */
2423 /* ? */
2424 /* ? */
2425 XK_KP_Equal, /* kMT_KP_Equal */
2426 /* XK_plusminus */
2427#ifdef XK_Pause
2428 XK_Pause, /* kMT_Pause */
2429#endif
2430#ifdef XK_F15
2431 XK_F15, /* kMT_F15 */
2432#endif
2433 /* ? */
2434 XK_KP_Decimal, /* kMT_KP_Decimal */
2435 /* XK_Hangul */
2436 /* XK_Hangul_Hanja */
2437 /* nothing */
2438 XK_Super_L, /* kMT_Super_L */
2439 XK_Super_R, /* kMT_Super_R */
2440 XK_Menu, /* kMT_Menu */
2441 /* XK_Cancel */
2442 /* XK_Redo */
2443 /* ? */
2444 /* XK_Undo */
2445 /* ? */
2446 /* ? */
2447 /* ? */
2448 /* ? */
2449 /* XK_Find */
2450 /* ? */
2451#ifdef XK_Help
2452 XK_Help, /* kMT_Help */
2453#endif
2454 /* ? */
2455 /* ? */
2456 /* nothing */
2457 /* ? */
2458 /* ? */
2459 /* ? */
2460 /* ? */
2461 /* nothing */
2462
2463 /* XK_parenleft */
2464 /* XK_parenright */
2465
2466 /* XK_Mode_switch */
2467
2468
2469
2470 XK_Meta_L, /* kMT_Meta_L */
2471 XK_Meta_R, /* kMT_Meta_R */
2472
2473 XK_Mode_switch, /* kMT_Mode_switch */
2474 XK_Hyper_L, /* kMT_Hyper_L */
2475 XK_Hyper_R, /* kMT_Hyper_R */
2476
2477 XK_F13, /* kMT_F13 */
2478 /*
2479 seen being used in Mandrake Linux 9.2
2480 for windows key
2481 */
2482
2483 0 /* just so last above line can end in ',' */
2484};
2485
2486/*
2487 MT2MKC was generated by a script from
2488 enum and comments above.
2489*/
2490LOCALVAR const ui3r MT2MKC[kNumMTs + 1] = {
2491 MKC_formac_Escape, /* kMT_Escape */
2492 MKC_1, /* kMT_1 */
2493 MKC_2, /* kMT_2 */
2494 MKC_3, /* kMT_3 */
2495 MKC_4, /* kMT_4 */
2496 MKC_5, /* kMT_5 */
2497 MKC_6, /* kMT_6 */
2498 MKC_7, /* kMT_7 */
2499 MKC_8, /* kMT_8 */
2500 MKC_9, /* kMT_9 */
2501 MKC_0, /* kMT_0 */
2502 MKC_Minus, /* kMT_minus */
2503 MKC_Minus, /* kMT_underscore */
2504 MKC_Equal, /* kMT_equal */
2505 MKC_Equal, /* kMT_plus */
2506 MKC_BackSpace, /* kMT_BackSpace */
2507 MKC_Tab, /* kMT_Tab */
2508 MKC_Q, /* kMT_q */
2509 MKC_Q, /* kMT_Q */
2510 MKC_W, /* kMT_w */
2511 MKC_W, /* kMT_W */
2512 MKC_E, /* kMT_e */
2513 MKC_E, /* kMT_E */
2514 MKC_R, /* kMT_r */
2515 MKC_R, /* kMT_R */
2516 MKC_T, /* kMT_t */
2517 MKC_T, /* kMT_T */
2518 MKC_Y, /* kMT_y */
2519 MKC_Y, /* kMT_Y */
2520 MKC_U, /* kMT_u */
2521 MKC_U, /* kMT_U */
2522 MKC_I, /* kMT_i */
2523 MKC_I, /* kMT_I */
2524 MKC_O, /* kMT_o */
2525 MKC_O, /* kMT_O */
2526 MKC_P, /* kMT_p */
2527 MKC_P, /* kMT_P */
2528 MKC_LeftBracket, /* kMT_bracketleft */
2529 MKC_LeftBracket, /* kMT_braceleft */
2530 MKC_RightBracket, /* kMT_bracketright */
2531 MKC_RightBracket, /* kMT_braceright */
2532 MKC_Return, /* kMT_Return */
2533 MKC_formac_Control, /* kMT_Control_L */
2534 MKC_A, /* kMT_a */
2535 MKC_A, /* kMT_A */
2536 MKC_S, /* kMT_s */
2537 MKC_S, /* kMT_S */
2538 MKC_D, /* kMT_d */
2539 MKC_D, /* kMT_D */
2540 MKC_F, /* kMT_f */
2541 MKC_F, /* kMT_F */
2542 MKC_G, /* kMT_g */
2543 MKC_G, /* kMT_G */
2544 MKC_H, /* kMT_h */
2545 MKC_H, /* kMT_H */
2546 MKC_J, /* kMT_j */
2547 MKC_J, /* kMT_J */
2548 MKC_K, /* kMT_k */
2549 MKC_K, /* kMT_K */
2550 MKC_L, /* kMT_l */
2551 MKC_L, /* kMT_L */
2552 MKC_SemiColon, /* kMT_semicolon */
2553 MKC_SemiColon, /* kMT_colon */
2554 MKC_SingleQuote, /* kMT_apostrophe */
2555 MKC_SingleQuote, /* kMT_quotedbl */
2556 MKC_formac_Grave, /* kMT_grave */
2557 MKC_formac_Grave, /* kMT_asciitilde */
2558 MKC_formac_Shift, /* kMT_Shift_L */
2559 MKC_formac_BackSlash, /* kMT_backslash */
2560 MKC_formac_BackSlash, /* kMT_bar */
2561 MKC_Z, /* kMT_z */
2562 MKC_Z, /* kMT_Z */
2563 MKC_X, /* kMT_x */
2564 MKC_X, /* kMT_X */
2565 MKC_C, /* kMT_c */
2566 MKC_C, /* kMT_C */
2567 MKC_V, /* kMT_v */
2568 MKC_V, /* kMT_V */
2569 MKC_B, /* kMT_b */
2570 MKC_B, /* kMT_B */
2571 MKC_N, /* kMT_n */
2572 MKC_N, /* kMT_N */
2573 MKC_M, /* kMT_m */
2574 MKC_M, /* kMT_M */
2575 MKC_Comma, /* kMT_comma */
2576 MKC_Period, /* kMT_period */
2577 MKC_Period, /* kMT_greater */
2578 MKC_formac_Slash, /* kMT_slash */
2579 MKC_formac_Slash, /* kMT_question */
2580 MKC_formac_RShift, /* kMT_Shift_R */
2581 MKC_KPMultiply, /* kMT_KP_Multiply */
2582 MKC_formac_Command, /* kMT_Alt_L */
2583 MKC_Space, /* kMT_space */
2584 MKC_real_CapsLock, /* kMT_Caps_Lock */
2585 MKC_formac_F1, /* kMT_F1 */
2586 MKC_formac_F2, /* kMT_F2 */
2587 MKC_formac_F3, /* kMT_F3 */
2588 MKC_formac_F4, /* kMT_F4 */
2589 MKC_formac_F5, /* kMT_F5 */
2590 MKC_F6, /* kMT_F6 */
2591 MKC_F7, /* kMT_F7 */
2592 MKC_F8, /* kMT_F8 */
2593 MKC_F9, /* kMT_F9 */
2594 MKC_F10, /* kMT_F10 */
2595 MKC_Clear, /* kMT_Num_Lock */
2596#ifdef XK_Scroll_Lock
2597 MKC_ScrollLock, /* kMT_Scroll_Lock */
2598#endif
2599#ifdef XK_F14
2600 MKC_ScrollLock, /* kMT_F14 */
2601#endif
2602
2603 MKC_KP7, /* kMT_KP_7 */
2604#ifdef XK_KP_Home
2605 MKC_KP7, /* kMT_KP_Home */
2606#endif
2607
2608 MKC_KP8, /* kMT_KP_8 */
2609#ifdef XK_KP_Up
2610 MKC_KP8, /* kMT_KP_Up */
2611#endif
2612
2613 MKC_KP9, /* kMT_KP_9 */
2614#ifdef XK_KP_Page_Up
2615 MKC_KP9, /* kMT_KP_Page_Up */
2616#else
2617#ifdef XK_KP_Prior
2618 MKC_KP9, /* kMT_KP_Prior */
2619#endif
2620#endif
2621
2622 MKC_KPSubtract, /* kMT_KP_Subtract */
2623
2624 MKC_KP4, /* kMT_KP_4 */
2625#ifdef XK_KP_Left
2626 MKC_KP4, /* kMT_KP_Left */
2627#endif
2628
2629 MKC_KP5, /* kMT_KP_5 */
2630#ifdef XK_KP_Begin
2631 MKC_KP5, /* kMT_KP_Begin */
2632#endif
2633
2634 MKC_KP6, /* kMT_KP_6 */
2635#ifdef XK_KP_Right
2636 MKC_KP6, /* kMT_KP_Right */
2637#endif
2638
2639 MKC_KPAdd, /* kMT_KP_Add */
2640
2641 MKC_KP1, /* kMT_KP_1 */
2642#ifdef XK_KP_End
2643 MKC_KP1, /* kMT_KP_End */
2644#endif
2645
2646 MKC_KP2, /* kMT_KP_2 */
2647#ifdef XK_KP_Down
2648 MKC_KP2, /* kMT_KP_Down */
2649#endif
2650
2651 MKC_KP3, /* kMT_KP_3 */
2652#ifdef XK_Page_Down
2653 MKC_KP3, /* kMT_KP_Page_Down */
2654#else
2655#ifdef XK_KP_Next
2656 MKC_KP3, /* kMT_KP_Next */
2657#endif
2658#endif
2659
2660 MKC_KP0, /* kMT_KP_0 */
2661#ifdef XK_KP_Insert
2662 MKC_KP0, /* kMT_KP_Insert */
2663#endif
2664#ifdef XK_KP_Delete
2665 MKC_Decimal, /* kMT_KP_Delete */
2666#endif
2667
2668 /* XK_ISO_Level3_Shift */
2669 /* nothing */
2670#ifdef XK_less
2671 MKC_Comma, /* kMT_less */
2672#endif
2673 MKC_F11, /* kMT_F11 */
2674 MKC_F12, /* kMT_F12 */
2675 /* nothing */
2676 /* XK_Katakana */
2677 /* XK_Hiragana */
2678 /* XK_Henkan */
2679 /* XK_Hiragana_Katakana */
2680 /* XK_Muhenkan */
2681 /* nothing */
2682 MKC_formac_Enter, /* kMT_KP_Enter */
2683 MKC_formac_RControl, /* kMT_Control_R */
2684 MKC_KPDevide, /* kMT_KP_Divide */
2685#ifdef XK_Print
2686 MKC_Print, /* kMT_Print */
2687#endif
2688 MKC_formac_RCommand, /* kMT_Alt_R */
2689 /* XK_Linefeed */
2690#ifdef XK_Home
2691 MKC_formac_Home, /* kMT_Home */
2692#endif
2693 MKC_Up, /* kMT_Up */
2694
2695#ifdef XK_Page_Up
2696 MKC_formac_PageUp, /* kMT_Page_Up */
2697#else
2698#ifdef XK_Prior
2699 MKC_formac_PageUp, /* kMT_Prior */
2700#endif
2701#endif
2702
2703 MKC_Left, /* kMT_Left */
2704 MKC_Right, /* kMT_Right */
2705#ifdef XK_End
2706 MKC_formac_End, /* kMT_End */
2707#endif
2708 MKC_Down, /* kMT_Down */
2709
2710#ifdef XK_Page_Down
2711 MKC_formac_PageDown, /* kMT_Page_Down */
2712#else
2713#ifdef XK_Next
2714 MKC_formac_PageDown, /* kMT_Next */
2715#endif
2716#endif
2717
2718#ifdef XK_Insert
2719 MKC_formac_Help, /* kMT_Insert */
2720#endif
2721#ifdef XK_Delete
2722 MKC_formac_ForwardDel, /* kMT_Delete */
2723#endif
2724 /* nothing */
2725 /* ? */
2726 /* ? */
2727 /* ? */
2728 /* ? */
2729 MKC_KPEqual, /* kMT_KP_Equal */
2730 /* XK_plusminus */
2731#ifdef XK_Pause
2732 MKC_Pause, /* kMT_Pause */
2733#endif
2734#ifdef XK_F15
2735 MKC_Pause, /* kMT_F15 */
2736#endif
2737 /* ? */
2738 MKC_Decimal, /* kMT_KP_Decimal */
2739 /* XK_Hangul */
2740 /* XK_Hangul_Hanja */
2741 /* nothing */
2742 MKC_formac_Option, /* kMT_Super_L */
2743 MKC_formac_ROption, /* kMT_Super_R */
2744 MKC_formac_Option, /* kMT_Menu */
2745 /* XK_Cancel */
2746 /* XK_Redo */
2747 /* ? */
2748 /* XK_Undo */
2749 /* ? */
2750 /* ? */
2751 /* ? */
2752 /* ? */
2753 /* XK_Find */
2754 /* ? */
2755#ifdef XK_Help
2756 MKC_formac_Help, /* kMT_Help */
2757#endif
2758 /* ? */
2759 /* ? */
2760 /* nothing */
2761 /* ? */
2762 /* ? */
2763 /* ? */
2764 /* ? */
2765 /* nothing */
2766
2767 /* XK_parenleft */
2768 /* XK_parenright */
2769
2770 /* XK_Mode_switch */
2771
2772
2773
2774 MKC_formac_Command, /* kMT_Meta_L */
2775 MKC_formac_RCommand, /* kMT_Meta_R */
2776
2777 MKC_formac_Option, /* kMT_Mode_switch */
2778 MKC_formac_Option, /* kMT_Hyper_L */
2779 MKC_formac_ROption, /* kMT_Hyper_R */
2780
2781 MKC_formac_Option, /* kMT_F13 */
2782 /*
2783 seen being used in Mandrake Linux 9.2
2784 for windows key
2785 */
2786
2787 0 /* just so last above line can end in ',' */
2788};
2789
2790LOCALVAR ui3b KC2MKC[256];
2791 /*
2792 translate X11 key code to Macintosh key code
2793 */
2794
2795#define KMInit_dolog (dbglog_HAVE && 0)
2796
2797LOCALFUNC blnr KC2MKCInit(void)
2798{
2799 int i;
2800 int j;
2801 int last_j;
2802 int first_keycode;
2803 int last_keycode;
2804 int keysyms_per_keycode;
2805 KeySym *KeyMap;
2806 KeySym MaxUsedKeySym;
2807
2808 /*
2809 In Linux, observe that most KeySyms not
2810 found in our translation table are large.
2811 So saves time to find largest KeySym we
2812 are interested in.
2813 */
2814 MaxUsedKeySym = 0;
2815 for (j = 0; j < kNumMTs; j++) {
2816 KeySym x = MT2KeySym[j];
2817 if (x > MaxUsedKeySym) {
2818 MaxUsedKeySym = x;
2819 }
2820 }
2821
2822#if KMInit_dolog
2823 dbglog_writelnHex("MaxUsedKeySym", MaxUsedKeySym);
2824#endif
2825
2826 for (i = 0; i < 256; ++i) {
2827 KC2MKC[i] = MKC_None;
2828 }
2829
2830 XDisplayKeycodes(x_display, &first_keycode, &last_keycode);
2831 KeyMap = XGetKeyboardMapping(x_display,
2832 first_keycode,
2833 last_keycode - first_keycode + 1,
2834 &keysyms_per_keycode);
2835
2836 last_j = kNumMTs - 1;
2837
2838 for (i = first_keycode; i <= last_keycode; i++) {
2839 KeySym ks = KeyMap[(i - first_keycode) * keysyms_per_keycode];
2840
2841#if KMInit_dolog
2842 dbglog_writeNum(i);
2843 dbglog_writeSpace();
2844 dbglog_writeHex(ks);
2845 dbglog_writeSpace();
2846#endif
2847 if (0 == ks) {
2848#if KMInit_dolog
2849 dbglog_writeCStr("zero");
2850#endif
2851 } else
2852 if (ks > MaxUsedKeySym) {
2853#if KMInit_dolog
2854 dbglog_writeCStr("too large");
2855#endif
2856 } else
2857 {
2858 /*
2859 look up in the translation table, and try to be more
2860 efficient if the order of this table is similar
2861 to the order of the X11 KeyboardMapping.
2862 */
2863 j = last_j;
2864label_retry:
2865 ++j;
2866 if (j >= kNumMTs) {
2867 j = 0;
2868 }
2869
2870 if (j == last_j) {
2871 /* back where we started */
2872#if KMInit_dolog
2873 dbglog_writeCStr("not found");
2874#endif
2875 } else
2876 if (ks != MT2KeySym[j]) {
2877#if KMInit_dolog && 1
2878 dbglog_writeCStr("*");
2879#endif
2880 goto label_retry; /* try the next one */
2881 } else
2882 {
2883#if KMInit_dolog
2884 dbglog_writeCStr("match");
2885 dbglog_writeSpace();
2886 dbglog_writeHex(MT2MKC[j]);
2887#endif
2888 KC2MKC[i] = MT2MKC[j];
2889 last_j = j;
2890 }
2891 }
2892#if KMInit_dolog
2893 dbglog_writeReturn();
2894#endif
2895 }
2896
2897 XFree(KeyMap);
2898
2899 InitKeyCodes();
2900
2901 return trueblnr;
2902}
2903
2904LOCALPROC CheckTheCapsLock(void)
2905{
2906 int NewMousePosh;
2907 int NewMousePosv;
2908 int root_x_return;
2909 int root_y_return;
2910 Window root_return;
2911 Window child_return;
2912 unsigned int mask_return;
2913
2914 XQueryPointer(x_display, my_main_wind,
2915 &root_return, &child_return,
2916 &root_x_return, &root_y_return,
2917 &NewMousePosh, &NewMousePosv,
2918 &mask_return);
2919
2920 Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
2921 (mask_return & LockMask) != 0);
2922}
2923
2924LOCALPROC DoKeyCode0(int i, blnr down)
2925{
2926 ui3r key = KC2MKC[i];
2927
2928 if (MKC_None == key) {
2929 /* ignore */
2930 } else
2931 if (MKC_real_CapsLock == key) {
2932 /* also ignore */
2933 } else
2934 {
2935 Keyboard_UpdateKeyMap2(key, down);
2936 }
2937}
2938
2939LOCALPROC DoKeyCode(int i, blnr down)
2940{
2941 if ((i >= 0) && (i < 256)) {
2942 ui3r key = KC2MKC[i];
2943
2944 if (MKC_None == key) {
2945 /* ignore */
2946 } else
2947 if (MKC_real_CapsLock == key) {
2948 CheckTheCapsLock();
2949 } else
2950 {
2951 Keyboard_UpdateKeyMap2(key, down);
2952 }
2953 }
2954}
2955
2956#if MayFullScreen && GrabKeysFullScreen
2957LOCALVAR blnr KeyboardIsGrabbed = falseblnr;
2958#endif
2959
2960#if MayFullScreen && GrabKeysFullScreen
2961LOCALPROC MyGrabKeyboard(void)
2962{
2963 if (! KeyboardIsGrabbed) {
2964 (void) XGrabKeyboard(x_display, my_main_wind,
2965 False, GrabModeAsync, GrabModeAsync,
2966 CurrentTime);
2967 KeyboardIsGrabbed = trueblnr;
2968 }
2969}
2970#endif
2971
2972#if MayFullScreen && GrabKeysFullScreen
2973LOCALPROC MyUnGrabKeyboard(void)
2974{
2975 if (KeyboardIsGrabbed && my_main_wind) {
2976 XUngrabKeyboard(x_display, CurrentTime);
2977 KeyboardIsGrabbed = falseblnr;
2978 }
2979}
2980#endif
2981
2982LOCALVAR blnr NoKeyRepeat = falseblnr;
2983LOCALVAR int SaveKeyRepeat;
2984
2985LOCALPROC DisableKeyRepeat(void)
2986{
2987 XKeyboardState r;
2988 XKeyboardControl k;
2989
2990 if ((! NoKeyRepeat) && (x_display != NULL)) {
2991 NoKeyRepeat = trueblnr;
2992
2993 XGetKeyboardControl(x_display, &r);
2994 SaveKeyRepeat = r.global_auto_repeat;
2995
2996 k.auto_repeat_mode = AutoRepeatModeOff;
2997 XChangeKeyboardControl(x_display, KBAutoRepeatMode, &k);
2998 }
2999}
3000
3001LOCALPROC RestoreKeyRepeat(void)
3002{
3003 XKeyboardControl k;
3004
3005 if (NoKeyRepeat && (x_display != NULL)) {
3006 NoKeyRepeat = falseblnr;
3007
3008 k.auto_repeat_mode = SaveKeyRepeat;
3009 XChangeKeyboardControl(x_display, KBAutoRepeatMode, &k);
3010 }
3011}
3012
3013LOCALVAR blnr WantCmdOptOnReconnect = falseblnr;
3014
3015LOCALPROC GetTheDownKeys(void)
3016{
3017 char keys_return[32];
3018 int i;
3019 int v;
3020 int j;
3021
3022 XQueryKeymap(x_display, keys_return);
3023
3024 for (i = 0; i < 32; ++i) {
3025 v = keys_return[i];
3026 for (j = 0; j < 8; ++j) {
3027 if (0 != ((1 << j) & v)) {
3028 int k = i * 8 + j;
3029
3030 DoKeyCode0(k, trueblnr);
3031 }
3032 }
3033 }
3034}
3035
3036LOCALPROC ReconnectKeyCodes3(void)
3037{
3038 CheckTheCapsLock();
3039
3040 if (WantCmdOptOnReconnect) {
3041 WantCmdOptOnReconnect = falseblnr;
3042
3043 GetTheDownKeys();
3044 }
3045}
3046
3047LOCALPROC DisconnectKeyCodes3(void)
3048{
3049 DisconnectKeyCodes2();
3050 MyMouseButtonSet(falseblnr);
3051}
3052
3053/* --- time, date, location --- */
3054
3055#define dbglog_TimeStuff (0 && dbglog_HAVE)
3056
3057LOCALVAR ui5b TrueEmulatedTime = 0;
3058
3059#include "DATE2SEC.h"
3060
3061#define TicksPerSecond 1000000
3062
3063LOCALVAR blnr HaveTimeDelta = falseblnr;
3064LOCALVAR ui5b TimeDelta;
3065
3066LOCALVAR ui5b NewMacDateInSeconds;
3067
3068LOCALVAR ui5b LastTimeSec;
3069LOCALVAR ui5b LastTimeUsec;
3070
3071LOCALPROC GetCurrentTicks(void)
3072{
3073 struct timeval t;
3074
3075 gettimeofday(&t, NULL);
3076 if (! HaveTimeDelta) {
3077 time_t Current_Time;
3078 struct tm *s;
3079
3080 (void) time(&Current_Time);
3081 s = localtime(&Current_Time);
3082 TimeDelta = Date2MacSeconds(s->tm_sec, s->tm_min, s->tm_hour,
3083 s->tm_mday, 1 + s->tm_mon, 1900 + s->tm_year) - t.tv_sec;
3084#if 0 && AutoTimeZone /* how portable is this ? */
3085 CurMacDelta = ((ui5b)(s->tm_gmtoff) & 0x00FFFFFF)
3086 | ((s->tm_isdst ? 0x80 : 0) << 24);
3087#endif
3088 HaveTimeDelta = trueblnr;
3089 }
3090
3091 NewMacDateInSeconds = t.tv_sec + TimeDelta;
3092 LastTimeSec = (ui5b)t.tv_sec;
3093 LastTimeUsec = (ui5b)t.tv_usec;
3094}
3095
3096#define MyInvTimeStep 16626 /* TicksPerSecond / 60.14742 */
3097
3098LOCALVAR ui5b NextTimeSec;
3099LOCALVAR ui5b NextTimeUsec;
3100
3101LOCALPROC IncrNextTime(void)
3102{
3103 NextTimeUsec += MyInvTimeStep;
3104 if (NextTimeUsec >= TicksPerSecond) {
3105 NextTimeUsec -= TicksPerSecond;
3106 NextTimeSec += 1;
3107 }
3108}
3109
3110LOCALPROC InitNextTime(void)
3111{
3112 NextTimeSec = LastTimeSec;
3113 NextTimeUsec = LastTimeUsec;
3114 IncrNextTime();
3115}
3116
3117LOCALPROC StartUpTimeAdjust(void)
3118{
3119 GetCurrentTicks();
3120 InitNextTime();
3121}
3122
3123LOCALFUNC si5b GetTimeDiff(void)
3124{
3125 return ((si5b)(LastTimeSec - NextTimeSec)) * TicksPerSecond
3126 + ((si5b)(LastTimeUsec - NextTimeUsec));
3127}
3128
3129LOCALPROC UpdateTrueEmulatedTime(void)
3130{
3131 si5b TimeDiff;
3132
3133 GetCurrentTicks();
3134
3135 TimeDiff = GetTimeDiff();
3136 if (TimeDiff >= 0) {
3137 if (TimeDiff > 16 * MyInvTimeStep) {
3138 /* emulation interrupted, forget it */
3139 ++TrueEmulatedTime;
3140 InitNextTime();
3141
3142#if dbglog_TimeStuff
3143 dbglog_writelnNum("emulation interrupted",
3144 TrueEmulatedTime);
3145#endif
3146 } else {
3147 do {
3148 ++TrueEmulatedTime;
3149 IncrNextTime();
3150 TimeDiff -= TicksPerSecond;
3151 } while (TimeDiff >= 0);
3152 }
3153 } else if (TimeDiff < - 16 * MyInvTimeStep) {
3154 /* clock goofed if ever get here, reset */
3155#if dbglog_TimeStuff
3156 dbglog_writeln("clock set back");
3157#endif
3158
3159 InitNextTime();
3160 }
3161}
3162
3163LOCALFUNC blnr CheckDateTime(void)
3164{
3165 if (CurMacDateInSeconds != NewMacDateInSeconds) {
3166 CurMacDateInSeconds = NewMacDateInSeconds;
3167 return trueblnr;
3168 } else {
3169 return falseblnr;
3170 }
3171}
3172
3173LOCALFUNC blnr InitLocationDat(void)
3174{
3175 GetCurrentTicks();
3176 CurMacDateInSeconds = NewMacDateInSeconds;
3177
3178 return trueblnr;
3179}
3180
3181/* --- sound --- */
3182
3183#if MySoundEnabled
3184
3185#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
3186#define kSoundBuffers (1 << kLn2SoundBuffers)
3187#define kSoundBuffMask (kSoundBuffers - 1)
3188
3189#define DesiredMinFilledSoundBuffs 3
3190 /*
3191 if too big then sound lags behind emulation.
3192 if too small then sound will have pauses.
3193 */
3194
3195#define kLnOneBuffLen 9
3196#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
3197#define kOneBuffLen (1UL << kLnOneBuffLen)
3198#define kAllBuffLen (1UL << kLnAllBuffLen)
3199#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
3200#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
3201#define kOneBuffSz (1UL << kLnOneBuffSz)
3202#define kAllBuffSz (1UL << kLnAllBuffSz)
3203#define kOneBuffMask (kOneBuffLen - 1)
3204#define kAllBuffMask (kAllBuffLen - 1)
3205#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
3206
3207#define dbglog_SoundStuff (0 && dbglog_HAVE)
3208#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
3209
3210LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
3211LOCALVAR ui4b ThePlayOffset;
3212LOCALVAR ui4b TheFillOffset;
3213LOCALVAR ui4b TheWriteOffset;
3214LOCALVAR ui4b MinFilledSoundBuffs;
3215
3216LOCALPROC MySound_Start0(void)
3217{
3218 /* Reset variables */
3219 ThePlayOffset = 0;
3220 TheFillOffset = 0;
3221 TheWriteOffset = 0;
3222 MinFilledSoundBuffs = kSoundBuffers;
3223}
3224
3225GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
3226{
3227 ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
3228 ui4b WriteBuffContig =
3229 kOneBuffLen - (TheWriteOffset & kOneBuffMask);
3230
3231 if (WriteBuffContig < n) {
3232 n = WriteBuffContig;
3233 }
3234 if (ToFillLen < n) {
3235 /* overwrite previous buffer */
3236#if dbglog_SoundStuff
3237 dbglog_writeln("sound buffer over flow");
3238#endif
3239 TheWriteOffset -= kOneBuffLen;
3240 }
3241
3242 *actL = n;
3243 return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
3244}
3245
3246LOCALFUNC blnr MySound_EndWrite0(ui4r actL)
3247{
3248 blnr v;
3249
3250 TheWriteOffset += actL;
3251
3252 if (0 != (TheWriteOffset & kOneBuffMask)) {
3253 v = falseblnr;
3254 } else {
3255 /* just finished a block */
3256
3257 TheFillOffset = TheWriteOffset;
3258
3259 v = trueblnr;
3260 }
3261
3262 return v;
3263}
3264
3265LOCALPROC MySound_SecondNotify0(void)
3266{
3267 if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
3268#if dbglog_SoundStuff
3269 dbglog_writeln("MinFilledSoundBuffs too high");
3270#endif
3271 IncrNextTime();
3272 } else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
3273#if dbglog_SoundStuff
3274 dbglog_writeln("MinFilledSoundBuffs too low");
3275#endif
3276 ++TrueEmulatedTime;
3277 }
3278 MinFilledSoundBuffs = kSoundBuffers;
3279}
3280
3281#define SOUND_SAMPLERATE 22255 /* = round(7833600 * 2 / 704) */
3282
3283#include "SOUNDGLU.h"
3284
3285#endif
3286
3287/* --- basic dialogs --- */
3288
3289LOCALPROC CheckSavedMacMsg(void)
3290{
3291 if (nullpr != SavedBriefMsg) {
3292 char briefMsg0[ClStrMaxLength + 1];
3293 char longMsg0[ClStrMaxLength + 1];
3294
3295 NativeStrFromCStr(briefMsg0, SavedBriefMsg);
3296 NativeStrFromCStr(longMsg0, SavedLongMsg);
3297
3298 fprintf(stderr, "%s\n", briefMsg0);
3299 fprintf(stderr, "%s\n", longMsg0);
3300
3301 SavedBriefMsg = nullpr;
3302 }
3303}
3304
3305/* --- clipboard --- */
3306
3307#if IncludeHostTextClipExchange
3308LOCALVAR ui3p MyClipBuffer = NULL;
3309#endif
3310
3311#if IncludeHostTextClipExchange
3312LOCALPROC FreeMyClipBuffer(void)
3313{
3314 if (MyClipBuffer != NULL) {
3315 free(MyClipBuffer);
3316 MyClipBuffer = NULL;
3317 }
3318}
3319#endif
3320
3321#if IncludeHostTextClipExchange
3322GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
3323{
3324 tMacErr err = mnvm_miscErr;
3325
3326 FreeMyClipBuffer();
3327 if (MacRomanTextToNativePtr(i, falseblnr,
3328 &MyClipBuffer))
3329 {
3330 XSetSelectionOwner(x_display, MyXA_CLIPBOARD,
3331 my_main_wind, CurrentTime);
3332 err = mnvm_noErr;
3333 }
3334
3335 PbufDispose(i);
3336
3337 return err;
3338}
3339#endif
3340
3341#if IncludeHostTextClipExchange
3342LOCALFUNC blnr WaitForClipboardSelection(XEvent *xevent)
3343{
3344 struct timespec rqt;
3345 struct timespec rmt;
3346 int i;
3347
3348 for (i = 100; --i >= 0; ) {
3349 while (XCheckTypedWindowEvent(x_display, my_main_wind,
3350 SelectionNotify, xevent))
3351 {
3352 if (xevent->xselection.selection != MyXA_CLIPBOARD) {
3353 /*
3354 not what we were looking for. lose it.
3355 (and hope it wasn't too important).
3356 */
3357 WriteExtraErr("Discarding unwanted SelectionNotify");
3358 } else {
3359 /* this is our event */
3360 return trueblnr;
3361 }
3362 }
3363
3364 rqt.tv_sec = 0;
3365 rqt.tv_nsec = 10000000;
3366 (void) nanosleep(&rqt, &rmt);
3367 }
3368 return falseblnr;
3369}
3370#endif
3371
3372#if IncludeHostTextClipExchange
3373LOCALPROC HTCEimport_do(void)
3374{
3375 Window w = XGetSelectionOwner(x_display, MyXA_CLIPBOARD);
3376
3377 if (w == my_main_wind) {
3378 /* We own the clipboard, already have MyClipBuffer */
3379 } else {
3380 FreeMyClipBuffer();
3381 if (w != None) {
3382 XEvent xevent;
3383
3384 XDeleteProperty(x_display, my_main_wind,
3385 MyXA_MinivMac_Clip);
3386 XConvertSelection(x_display, MyXA_CLIPBOARD, XA_STRING,
3387 MyXA_MinivMac_Clip, my_main_wind, CurrentTime);
3388
3389 if (WaitForClipboardSelection(&xevent)) {
3390 if (None == xevent.xselection.property) {
3391 /* oops, target not supported */
3392 } else {
3393 if (xevent.xselection.property
3394 != MyXA_MinivMac_Clip)
3395 {
3396 /* not where we expected it */
3397 } else {
3398 Atom ret_type;
3399 int ret_format;
3400 unsigned long ret_item;
3401 unsigned long remain_byte;
3402 unsigned char *s = NULL;
3403
3404 if ((Success != XGetWindowProperty(
3405 x_display, my_main_wind, MyXA_MinivMac_Clip,
3406 0, 65535, False, AnyPropertyType, &ret_type,
3407 &ret_format, &ret_item, &remain_byte, &s))
3408 || (ret_type != XA_STRING)
3409 || (ret_format != 8)
3410 || (NULL == s))
3411 {
3412 WriteExtraErr(
3413 "XGetWindowProperty failed"
3414 " in HTCEimport_do");
3415 } else {
3416 MyClipBuffer = (ui3p)malloc(ret_item + 1);
3417 if (NULL == MyClipBuffer) {
3418 MacMsg(kStrOutOfMemTitle,
3419 kStrOutOfMemMessage, falseblnr);
3420 } else {
3421 MyMoveBytes((anyp)s, (anyp)MyClipBuffer,
3422 ret_item);
3423 MyClipBuffer[ret_item] = 0;
3424 }
3425 XFree(s);
3426 }
3427 }
3428 XDeleteProperty(x_display, my_main_wind,
3429 MyXA_MinivMac_Clip);
3430 }
3431 }
3432 }
3433 }
3434}
3435#endif
3436
3437#if IncludeHostTextClipExchange
3438GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
3439{
3440 HTCEimport_do();
3441
3442 return NativeTextToMacRomanPbuf((char *)MyClipBuffer, r);
3443}
3444#endif
3445
3446#if IncludeHostTextClipExchange
3447LOCALFUNC blnr HandleSelectionRequestClipboard(XEvent *theEvent)
3448{
3449 blnr RequestFilled = falseblnr;
3450
3451#if MyDbgEvents
3452 dbglog_writeln("Requested MyXA_CLIPBOARD");
3453#endif
3454
3455 if (NULL == MyClipBuffer) {
3456 /* our clipboard is empty */
3457 } else if (theEvent->xselectionrequest.target == MyXA_TARGETS) {
3458 Atom a[2];
3459
3460 a[0] = MyXA_TARGETS;
3461 a[1] = XA_STRING;
3462
3463 XChangeProperty(x_display,
3464 theEvent->xselectionrequest.requestor,
3465 theEvent->xselectionrequest.property,
3466 MyXA_TARGETS,
3467 32,
3468 /*
3469 most, but not all, other programs I've
3470 look at seem to use 8 here, but that
3471 can't be right. can it?
3472 */
3473 PropModeReplace,
3474 (unsigned char *)a,
3475 sizeof(a) / sizeof(Atom));
3476
3477 RequestFilled = trueblnr;
3478 } else if (theEvent->xselectionrequest.target == XA_STRING) {
3479 XChangeProperty(x_display,
3480 theEvent->xselectionrequest.requestor,
3481 theEvent->xselectionrequest.property,
3482 XA_STRING,
3483 8,
3484 PropModeReplace,
3485 (unsigned char *)MyClipBuffer,
3486 strlen((char *)MyClipBuffer));
3487
3488 RequestFilled = trueblnr;
3489 }
3490
3491 return RequestFilled;
3492}
3493#endif
3494
3495/* --- drag and drop --- */
3496
3497#if EnableDragDrop
3498LOCALPROC MyActivateWind(Time time)
3499{
3500 if (NetSupportedContains(MyXA_NetActiveWindow)) {
3501 XEvent xevent;
3502 Window rootwin = XRootWindow(x_display,
3503 DefaultScreen(x_display));
3504
3505 memset(&xevent, 0, sizeof (xevent));
3506
3507 xevent.xany.type = ClientMessage;
3508 xevent.xclient.send_event = True;
3509 xevent.xclient.window = my_main_wind;
3510 xevent.xclient.message_type = MyXA_NetActiveWindow;
3511 xevent.xclient.format = 32;
3512 xevent.xclient.data.l[0] = 1;
3513 xevent.xclient.data.l[1]= time;
3514
3515 if (0 == XSendEvent(x_display, rootwin, 0,
3516 SubstructureRedirectMask | SubstructureNotifyMask,
3517 &xevent))
3518 {
3519 WriteExtraErr("XSendEvent failed in MyActivateWind");
3520 }
3521 }
3522
3523 XRaiseWindow(x_display, my_main_wind);
3524 /*
3525 In RedHat 7.1, _NET_ACTIVE_WINDOW supported,
3526 but XSendEvent of _NET_ACTIVE_WINDOW
3527 doesn't raise the window. So just always
3528 call XRaiseWindow. Hopefully calling
3529 XRaiseWindow won't do any harm on window
3530 managers where it isn't needed.
3531 (Such as in Ubuntu 5.10)
3532 */
3533 XSetInputFocus(x_display, my_main_wind,
3534 RevertToPointerRoot, time);
3535 /* And call this always too, just in case */
3536}
3537#endif
3538
3539#if EnableDragDrop
3540LOCALPROC ParseOneUri(char *s)
3541{
3542 /* printf("ParseOneUri %s\n", s); */
3543 if (('f' == s[0]) && ('i' == s[1]) && ('l' == s[2])
3544 && ('e' == s[3]) && (':' == s[4]))
3545 {
3546 s += 5;
3547 if (('/' == s[0]) && ('/' == s[1])) {
3548 /* skip hostname */
3549 char c;
3550
3551 s += 2;
3552 while ((c = *s) != '/') {
3553 if (0 == c) {
3554 return;
3555 }
3556 ++s;
3557 }
3558 }
3559 (void) Sony_Insert1a(s, falseblnr);
3560 }
3561}
3562#endif
3563
3564#if EnableDragDrop
3565LOCALFUNC int HexChar2Nib(char x)
3566{
3567 if ((x >= '0') && (x <= '9')) {
3568 return x - '0';
3569 } else if ((x >= 'A') && (x <= 'F')) {
3570 return x - 'A' + 10;
3571 } else if ((x >= 'a') && (x <= 'f')) {
3572 return x - 'a' + 10;
3573 } else {
3574 return -1;
3575 }
3576}
3577#endif
3578
3579#if EnableDragDrop
3580LOCALPROC ParseUriList(char *s)
3581{
3582 char *p1 = s;
3583 char *p0 = s;
3584 char *p = s;
3585 char c;
3586
3587 /* printf("ParseUriList %s\n", s); */
3588 while ((c = *p++) != 0) {
3589 if ('%' == c) {
3590 int a;
3591 int b;
3592
3593 if (((a = HexChar2Nib(p[0])) >= 0) &&
3594 ((b = HexChar2Nib(p[1])) >= 0))
3595 {
3596 p += 2;
3597 *p1++ = (a << 4) + b;
3598 } else {
3599 *p1++ = c;
3600 }
3601 } else if (('\n' == c) || ('\r' == c)) {
3602 *p1++ = 0;
3603 ParseOneUri(p0);
3604 p0 = p1;
3605 } else {
3606 *p1++ = c;
3607 }
3608 }
3609 *p1++ = 0;
3610 ParseOneUri(p0);
3611}
3612#endif
3613
3614#if EnableDragDrop
3615LOCALVAR Window PendingDragWindow = None;
3616#endif
3617
3618#if EnableDragDrop
3619LOCALPROC HandleSelectionNotifyDnd(XEvent *theEvent)
3620{
3621 blnr DropOk = falseblnr;
3622
3623#if MyDbgEvents
3624 dbglog_writeln("Got MyXA_DndSelection");
3625#endif
3626
3627 if ((theEvent->xselection.property == MyXA_MinivMac_DndXchng)
3628 && (theEvent->xselection.target == MyXA_UriList))
3629 {
3630 Atom ret_type;
3631 int ret_format;
3632 unsigned long ret_item;
3633 unsigned long remain_byte;
3634 unsigned char *s = NULL;
3635
3636 if ((Success != XGetWindowProperty(x_display, my_main_wind,
3637 MyXA_MinivMac_DndXchng,
3638 0, 65535, False, MyXA_UriList, &ret_type, &ret_format,
3639 &ret_item, &remain_byte, &s))
3640 || (NULL == s))
3641 {
3642 WriteExtraErr(
3643 "XGetWindowProperty failed in SelectionNotify");
3644 } else {
3645 ParseUriList((char *)s);
3646 DropOk = trueblnr;
3647 XFree(s);
3648 }
3649 } else {
3650 WriteExtraErr("Got Unknown SelectionNotify");
3651 }
3652
3653 XDeleteProperty(x_display, my_main_wind,
3654 MyXA_MinivMac_DndXchng);
3655
3656 if (PendingDragWindow != None) {
3657 XEvent xevent;
3658
3659 memset(&xevent, 0, sizeof(xevent));
3660
3661 xevent.xany.type = ClientMessage;
3662 xevent.xany.display = x_display;
3663 xevent.xclient.window = PendingDragWindow;
3664 xevent.xclient.message_type = MyXA_DndFinished;
3665 xevent.xclient.format = 32;
3666
3667 xevent.xclient.data.l[0] = my_main_wind;
3668 if (DropOk) {
3669 xevent.xclient.data.l[1] = 1;
3670 }
3671 xevent.xclient.data.l[2] = MyXA_DndActionPrivate;
3672
3673 if (0 == XSendEvent(x_display,
3674 PendingDragWindow, 0, 0, &xevent))
3675 {
3676 WriteExtraErr("XSendEvent failed in SelectionNotify");
3677 }
3678 }
3679 if (DropOk && gTrueBackgroundFlag) {
3680 MyActivateWind(theEvent->xselection.time);
3681
3682 WantCmdOptOnReconnect = trueblnr;
3683 }
3684}
3685#endif
3686
3687#if EnableDragDrop
3688LOCALPROC HandleClientMessageDndPosition(XEvent *theEvent)
3689{
3690 XEvent xevent;
3691 int xr;
3692 int yr;
3693 unsigned int dr;
3694 unsigned int wr;
3695 unsigned int hr;
3696 unsigned int bwr;
3697 Window rr;
3698 Window srcwin = theEvent->xclient.data.l[0];
3699
3700#if MyDbgEvents
3701 dbglog_writeln("Got XdndPosition");
3702#endif
3703
3704 XGetGeometry(x_display, my_main_wind,
3705 &rr, &xr, &yr, &wr, &hr, &bwr, &dr);
3706 memset (&xevent, 0, sizeof(xevent));
3707 xevent.xany.type = ClientMessage;
3708 xevent.xany.display = x_display;
3709 xevent.xclient.window = srcwin;
3710 xevent.xclient.message_type = MyXA_DndStatus;
3711 xevent.xclient.format = 32;
3712
3713 xevent.xclient.data.l[0] = theEvent->xclient.window;
3714 /* Target Window */
3715 xevent.xclient.data.l[1] = 1; /* Accept */
3716 xevent.xclient.data.l[2] = ((xr) << 16) | ((yr) & 0xFFFFUL);
3717 xevent.xclient.data.l[3] = ((wr) << 16) | ((hr) & 0xFFFFUL);
3718 xevent.xclient.data.l[4] = MyXA_DndActionPrivate; /* Action */
3719
3720 if (0 == XSendEvent(x_display, srcwin, 0, 0, &xevent)) {
3721 WriteExtraErr(
3722 "XSendEvent failed in HandleClientMessageDndPosition");
3723 }
3724}
3725#endif
3726
3727#if EnableDragDrop
3728LOCALPROC HandleClientMessageDndDrop(XEvent *theEvent)
3729{
3730 Time timestamp = theEvent->xclient.data.l[2];
3731 PendingDragWindow = (Window) theEvent->xclient.data.l[0];
3732
3733#if MyDbgEvents
3734 dbglog_writeln("Got XdndDrop");
3735#endif
3736
3737 XConvertSelection(x_display, MyXA_DndSelection, MyXA_UriList,
3738 MyXA_MinivMac_DndXchng, my_main_wind, timestamp);
3739}
3740#endif
3741
3742
3743#if EmLocalTalk
3744
3745struct xqpr {
3746 int NewMousePosh;
3747 int NewMousePosv;
3748 int root_x_return;
3749 int root_y_return;
3750 Window root_return;
3751 Window child_return;
3752 unsigned int mask_return;
3753};
3754typedef struct xqpr xqpr;
3755
3756
3757LOCALFUNC blnr EntropyGather(void)
3758{
3759 /*
3760 gather some entropy from several places, just in case
3761 /dev/urandom is not available.
3762 */
3763
3764 {
3765 struct timeval t;
3766
3767 gettimeofday(&t, NULL);
3768
3769 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b));
3770 }
3771
3772 {
3773 xqpr t;
3774
3775 XQueryPointer(x_display, my_main_wind,
3776 &t.root_return, &t.child_return,
3777 &t.root_x_return, &t.root_y_return,
3778 &t.NewMousePosh, &t.NewMousePosv,
3779 &t.mask_return);
3780
3781 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b));
3782 }
3783
3784#if 0
3785 /*
3786 Another possible source of entropy. But if available,
3787 almost certainly /dev/urandom is also available.
3788 */
3789 /* #include <sys/sysinfo.h> */
3790 {
3791 struct sysinfo t;
3792
3793 if (0 != sysinfo(&t)) {
3794#if dbglog_HAVE
3795 dbglog_writeln("sysinfo fails");
3796#endif
3797 }
3798
3799 /*
3800 continue even if error, it doesn't hurt anything
3801 if t is garbage.
3802 */
3803 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b));
3804 }
3805#endif
3806
3807 {
3808 pid_t t = getpid();
3809
3810 EntropyPoolAddPtr((ui3p)&t, sizeof(t) / sizeof(ui3b));
3811 }
3812
3813 {
3814 ui5b dat[2];
3815 int fd;
3816
3817 if (-1 == (fd = open("/dev/urandom", O_RDONLY))) {
3818#if dbglog_HAVE
3819 dbglog_writeCStr("open /dev/urandom fails");
3820 dbglog_writeNum(errno);
3821 dbglog_writeCStr(" (");
3822 dbglog_writeCStr(strerror(errno));
3823 dbglog_writeCStr(")");
3824 dbglog_writeReturn();
3825#endif
3826 } else {
3827
3828 if (read(fd, &dat, sizeof(dat)) < 0) {
3829#if dbglog_HAVE
3830 dbglog_writeCStr("open /dev/urandom fails");
3831 dbglog_writeNum(errno);
3832 dbglog_writeCStr(" (");
3833 dbglog_writeCStr(strerror(errno));
3834 dbglog_writeCStr(")");
3835 dbglog_writeReturn();
3836#endif
3837 } else {
3838
3839#if dbglog_HAVE
3840 dbglog_writeCStr("dat: ");
3841 dbglog_writeHex(dat[0]);
3842 dbglog_writeCStr(" ");
3843 dbglog_writeHex(dat[1]);
3844 dbglog_writeReturn();
3845#endif
3846
3847 e_p[0] ^= dat[0];
3848 e_p[1] ^= dat[1];
3849 /*
3850 if "/dev/urandom" is working correctly,
3851 this should make the previous contents of e_p
3852 irrelevant. if it is completely broken, like
3853 returning 0, this will not make e_p any less
3854 random.
3855 */
3856
3857#if dbglog_HAVE
3858 dbglog_writeCStr("ep: ");
3859 dbglog_writeHex(e_p[0]);
3860 dbglog_writeCStr(" ");
3861 dbglog_writeHex(e_p[1]);
3862 dbglog_writeReturn();
3863#endif
3864 }
3865
3866 close(fd);
3867 }
3868 }
3869
3870 return trueblnr;
3871}
3872#endif
3873
3874#if EmLocalTalk
3875
3876#include "LOCALTLK.h"
3877
3878#endif
3879
3880
3881#define UseMotionEvents 1
3882
3883#if UseMotionEvents
3884LOCALVAR blnr CaughtMouse = falseblnr;
3885#endif
3886
3887#if MayNotFullScreen
3888LOCALVAR int SavedTransH;
3889LOCALVAR int SavedTransV;
3890#endif
3891
3892/* --- event handling for main window --- */
3893
3894LOCALPROC HandleTheEvent(XEvent *theEvent)
3895{
3896 if (theEvent->xany.display != x_display) {
3897 WriteExtraErr("Got event for some other display");
3898 } else switch(theEvent->type) {
3899 case KeyPress:
3900 if (theEvent->xkey.window != my_main_wind) {
3901 WriteExtraErr("Got KeyPress for some other window");
3902 } else {
3903#if MyDbgEvents
3904 dbglog_writeln("- event - KeyPress");
3905#endif
3906
3907 MousePositionNotify(theEvent->xkey.x, theEvent->xkey.y);
3908 DoKeyCode(theEvent->xkey.keycode, trueblnr);
3909 }
3910 break;
3911 case KeyRelease:
3912 if (theEvent->xkey.window != my_main_wind) {
3913 WriteExtraErr("Got KeyRelease for some other window");
3914 } else {
3915#if MyDbgEvents
3916 dbglog_writeln("- event - KeyRelease");
3917#endif
3918
3919 MousePositionNotify(theEvent->xkey.x, theEvent->xkey.y);
3920 DoKeyCode(theEvent->xkey.keycode, falseblnr);
3921 }
3922 break;
3923 case ButtonPress:
3924 /* any mouse button, we don't care which */
3925 if (theEvent->xbutton.window != my_main_wind) {
3926 WriteExtraErr("Got ButtonPress for some other window");
3927 } else {
3928 /*
3929 could check some modifiers, but don't bother for now
3930 Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
3931 (theEvent->xbutton.state & LockMask) != 0);
3932 */
3933 MousePositionNotify(
3934 theEvent->xbutton.x, theEvent->xbutton.y);
3935 MyMouseButtonSet(trueblnr);
3936 }
3937 break;
3938 case ButtonRelease:
3939 /* any mouse button, we don't care which */
3940 if (theEvent->xbutton.window != my_main_wind) {
3941 WriteExtraErr(
3942 "Got ButtonRelease for some other window");
3943 } else {
3944 MousePositionNotify(
3945 theEvent->xbutton.x, theEvent->xbutton.y);
3946 MyMouseButtonSet(falseblnr);
3947 }
3948 break;
3949#if UseMotionEvents
3950 case MotionNotify:
3951 if (theEvent->xmotion.window != my_main_wind) {
3952 WriteExtraErr("Got MotionNotify for some other window");
3953 } else {
3954 MousePositionNotify(
3955 theEvent->xmotion.x, theEvent->xmotion.y);
3956 }
3957 break;
3958 case EnterNotify:
3959 if (theEvent->xcrossing.window != my_main_wind) {
3960 WriteExtraErr("Got EnterNotify for some other window");
3961 } else {
3962#if MyDbgEvents
3963 dbglog_writeln("- event - EnterNotify");
3964#endif
3965
3966 CaughtMouse = trueblnr;
3967 MousePositionNotify(
3968 theEvent->xcrossing.x, theEvent->xcrossing.y);
3969 }
3970 break;
3971 case LeaveNotify:
3972 if (theEvent->xcrossing.window != my_main_wind) {
3973 WriteExtraErr("Got LeaveNotify for some other window");
3974 } else {
3975#if MyDbgEvents
3976 dbglog_writeln("- event - LeaveNotify");
3977#endif
3978
3979 MousePositionNotify(
3980 theEvent->xcrossing.x, theEvent->xcrossing.y);
3981 CaughtMouse = falseblnr;
3982 }
3983 break;
3984#endif
3985 case Expose:
3986 if (theEvent->xexpose.window != my_main_wind) {
3987 WriteExtraErr(
3988 "Got SelectionRequest for some other window");
3989 } else {
3990 int x0 = theEvent->xexpose.x;
3991 int y0 = theEvent->xexpose.y;
3992 int x1 = x0 + theEvent->xexpose.width;
3993 int y1 = y0 + theEvent->xexpose.height;
3994
3995#if 0 && MyDbgEvents
3996 dbglog_writeln("- event - Expose");
3997#endif
3998
3999#if VarFullScreen
4000 if (UseFullScreen)
4001#endif
4002#if MayFullScreen
4003 {
4004 x0 -= hOffset;
4005 y0 -= vOffset;
4006 x1 -= hOffset;
4007 y1 -= vOffset;
4008 }
4009#endif
4010
4011#if EnableMagnify
4012 if (UseMagnify) {
4013 x0 /= MyWindowScale;
4014 y0 /= MyWindowScale;
4015 x1 = (x1 + (MyWindowScale - 1)) / MyWindowScale;
4016 y1 = (y1 + (MyWindowScale - 1)) / MyWindowScale;
4017 }
4018#endif
4019
4020#if VarFullScreen
4021 if (UseFullScreen)
4022#endif
4023#if MayFullScreen
4024 {
4025 x0 += ViewHStart;
4026 y0 += ViewVStart;
4027 x1 += ViewHStart;
4028 y1 += ViewVStart;
4029 }
4030#endif
4031
4032 if (x0 < 0) {
4033 x0 = 0;
4034 }
4035 if (x1 > vMacScreenWidth) {
4036 x1 = vMacScreenWidth;
4037 }
4038 if (y0 < 0) {
4039 y0 = 0;
4040 }
4041 if (y1 > vMacScreenHeight) {
4042 y1 = vMacScreenHeight;
4043 }
4044 if ((x0 < x1) && (y0 < y1)) {
4045 HaveChangedScreenBuff(y0, x0, y1, x1);
4046 }
4047
4048 NeedFinishOpen1 = falseblnr;
4049 }
4050 break;
4051#if IncludeHostTextClipExchange
4052 case SelectionRequest:
4053 if (theEvent->xselectionrequest.owner != my_main_wind) {
4054 WriteExtraErr(
4055 "Got SelectionRequest for some other window");
4056 } else {
4057 XEvent xevent;
4058 blnr RequestFilled = falseblnr;
4059
4060#if MyDbgEvents
4061 dbglog_writeln("- event - SelectionRequest");
4062 WriteDbgAtom("selection",
4063 theEvent->xselectionrequest.selection);
4064 WriteDbgAtom("target",
4065 theEvent->xselectionrequest.target);
4066 WriteDbgAtom("property",
4067 theEvent->xselectionrequest.property);
4068#endif
4069
4070 if (theEvent->xselectionrequest.selection ==
4071 MyXA_CLIPBOARD)
4072 {
4073 RequestFilled =
4074 HandleSelectionRequestClipboard(theEvent);
4075 }
4076
4077
4078 memset(&xevent, 0, sizeof(xevent));
4079 xevent.xselection.type = SelectionNotify;
4080 xevent.xselection.display = x_display;
4081 xevent.xselection.requestor =
4082 theEvent->xselectionrequest.requestor;
4083 xevent.xselection.selection =
4084 theEvent->xselectionrequest.selection;
4085 xevent.xselection.target =
4086 theEvent->xselectionrequest.target;
4087 xevent.xselection.property = (! RequestFilled) ? None
4088 : theEvent->xselectionrequest.property ;
4089 xevent.xselection.time =
4090 theEvent->xselectionrequest.time;
4091
4092 if (0 == XSendEvent(x_display,
4093 xevent.xselection.requestor, False, 0, &xevent))
4094 {
4095 WriteExtraErr(
4096 "XSendEvent failed in SelectionRequest");
4097 }
4098 }
4099 break;
4100 case SelectionClear:
4101 if (theEvent->xselectionclear.window != my_main_wind) {
4102 WriteExtraErr(
4103 "Got SelectionClear for some other window");
4104 } else {
4105#if MyDbgEvents
4106 dbglog_writeln("- event - SelectionClear");
4107 WriteDbgAtom("selection",
4108 theEvent->xselectionclear.selection);
4109#endif
4110
4111 if (theEvent->xselectionclear.selection ==
4112 MyXA_CLIPBOARD)
4113 {
4114 FreeMyClipBuffer();
4115 }
4116 }
4117 break;
4118#endif
4119#if EnableDragDrop
4120 case SelectionNotify:
4121 if (theEvent->xselection.requestor != my_main_wind) {
4122 WriteExtraErr(
4123 "Got SelectionNotify for some other window");
4124 } else {
4125#if MyDbgEvents
4126 dbglog_writeln("- event - SelectionNotify");
4127 WriteDbgAtom("selection",
4128 theEvent->xselection.selection);
4129 WriteDbgAtom("target", theEvent->xselection.target);
4130 WriteDbgAtom("property", theEvent->xselection.property);
4131#endif
4132
4133 if (theEvent->xselection.selection == MyXA_DndSelection)
4134 {
4135 HandleSelectionNotifyDnd(theEvent);
4136 } else {
4137 WriteExtraErr(
4138 "Got Unknown selection in SelectionNotify");
4139 }
4140 }
4141 break;
4142#endif
4143 case ClientMessage:
4144 if (theEvent->xclient.window != my_main_wind) {
4145 WriteExtraErr(
4146 "Got ClientMessage for some other window");
4147 } else {
4148#if MyDbgEvents
4149 dbglog_writeln("- event - ClientMessage");
4150 WriteDbgAtom("message_type",
4151 theEvent->xclient.message_type);
4152#endif
4153
4154#if EnableDragDrop
4155 if (theEvent->xclient.message_type == MyXA_DndEnter) {
4156 /* printf("Got XdndEnter\n"); */
4157 } else if (theEvent->xclient.message_type ==
4158 MyXA_DndLeave)
4159 {
4160 /* printf("Got XdndLeave\n"); */
4161 } else if (theEvent->xclient.message_type ==
4162 MyXA_DndPosition)
4163 {
4164 HandleClientMessageDndPosition(theEvent);
4165 } else if (theEvent->xclient.message_type ==
4166 MyXA_DndDrop)
4167 {
4168 HandleClientMessageDndDrop(theEvent);
4169 } else
4170#endif
4171 {
4172 if ((32 == theEvent->xclient.format) &&
4173 (theEvent->xclient.data.l[0] == MyXA_DeleteW))
4174 {
4175 /*
4176 I would think that should test that
4177 WM_PROTOCOLS == message_type
4178 but none of the other programs I looked
4179 at did.
4180 */
4181 RequestMacOff = trueblnr;
4182 }
4183 }
4184 }
4185 break;
4186 case FocusIn:
4187 if (theEvent->xfocus.window != my_main_wind) {
4188 WriteExtraErr("Got FocusIn for some other window");
4189 } else {
4190#if MyDbgEvents
4191 dbglog_writeln("- event - FocusIn");
4192#endif
4193
4194 gTrueBackgroundFlag = falseblnr;
4195#if UseMotionEvents
4196 CheckMouseState();
4197 /*
4198 Doesn't help on x11 for OS X,
4199 can't get new mouse position
4200 in any fashion until mouse moves.
4201 */
4202#endif
4203 }
4204 break;
4205 case FocusOut:
4206 if (theEvent->xfocus.window != my_main_wind) {
4207 WriteExtraErr("Got FocusOut for some other window");
4208 } else {
4209#if MyDbgEvents
4210 dbglog_writeln("- event - FocusOut");
4211#endif
4212
4213 gTrueBackgroundFlag = trueblnr;
4214 }
4215 break;
4216 default:
4217 break;
4218 }
4219}
4220
4221/* --- main window creation and disposal --- */
4222
4223LOCALVAR int my_argc;
4224LOCALVAR char **my_argv;
4225
4226LOCALVAR char *display_name = NULL;
4227
4228LOCALFUNC blnr Screen_Init(void)
4229{
4230 Window rootwin;
4231 int screen;
4232 Colormap Xcmap;
4233 Visual *Xvisual;
4234
4235 x_display = XOpenDisplay(display_name);
4236 if (NULL == x_display) {
4237 fprintf(stderr, "Cannot connect to X server.\n");
4238 return falseblnr;
4239 }
4240
4241 screen = DefaultScreen(x_display);
4242
4243 rootwin = XRootWindow(x_display, screen);
4244
4245 Xcmap = DefaultColormap(x_display, screen);
4246
4247 Xvisual = DefaultVisual(x_display, screen);
4248
4249 LoadMyXA();
4250
4251 XParseColor(x_display, Xcmap, "#000000", &x_black);
4252 if (! XAllocColor(x_display, Xcmap, &x_black)) {
4253 WriteExtraErr("XParseColor black fails");
4254 }
4255 XParseColor(x_display, Xcmap, "#ffffff", &x_white);
4256 if (! XAllocColor(x_display, Xcmap, &x_white)) {
4257 WriteExtraErr("XParseColor white fails");
4258 }
4259
4260 if (! CreateMyBlankCursor(rootwin)) {
4261 return falseblnr;
4262 }
4263
4264#if ! UseColorImage
4265 my_image = XCreateImage(x_display, Xvisual, 1, XYBitmap, 0,
4266 NULL /* (char *)image_Mem1 */,
4267 vMacScreenWidth, vMacScreenHeight, 32,
4268 vMacScreenMonoByteWidth);
4269 if (NULL == my_image) {
4270 fprintf(stderr, "XCreateImage failed.\n");
4271 return falseblnr;
4272 }
4273
4274#if 0
4275 fprintf(stderr, "bitmap_bit_order = %d\n",
4276 (int)my_image->bitmap_bit_order);
4277 fprintf(stderr, "byte_order = %d\n", (int)my_image->byte_order);
4278#endif
4279
4280 my_image->bitmap_bit_order = MSBFirst;
4281 my_image->byte_order = MSBFirst;
4282#endif
4283
4284#if UseColorImage
4285 my_image = XCreateImage(x_display, Xvisual, 24, ZPixmap, 0,
4286 NULL /* (char *)image_Mem1 */,
4287 vMacScreenWidth, vMacScreenHeight, 32,
4288 4 * (ui5r)vMacScreenWidth);
4289 if (NULL == my_image) {
4290 fprintf(stderr, "XCreateImage Color failed.\n");
4291 return falseblnr;
4292 }
4293
4294#if 0
4295 fprintf(stderr, "DefaultDepth = %d\n",
4296 (int)DefaultDepth(x_display, screen));
4297
4298 fprintf(stderr, "MSBFirst = %d\n", (int)MSBFirst);
4299 fprintf(stderr, "LSBFirst = %d\n", (int)LSBFirst);
4300
4301 fprintf(stderr, "bitmap_bit_order = %d\n",
4302 (int)my_image->bitmap_bit_order);
4303 fprintf(stderr, "byte_order = %d\n",
4304 (int)my_image->byte_order);
4305 fprintf(stderr, "bitmap_unit = %d\n",
4306 (int)my_image->bitmap_unit);
4307 fprintf(stderr, "bits_per_pixel = %d\n",
4308 (int)my_image->bits_per_pixel);
4309 fprintf(stderr, "red_mask = %d\n",
4310 (int)my_image->red_mask);
4311 fprintf(stderr, "green_mask = %d\n",
4312 (int)my_image->green_mask);
4313 fprintf(stderr, "blue_mask = %d\n",
4314 (int)my_image->blue_mask);
4315#endif
4316
4317#endif /* UseColorImage */
4318
4319#if EnableMagnify && (! UseColorImage)
4320 my_Scaled_image = XCreateImage(x_display, Xvisual,
4321 1, XYBitmap, 0,
4322 NULL /* (char *)image_Mem1 */,
4323 vMacScreenWidth * MyWindowScale,
4324 vMacScreenHeight * MyWindowScale,
4325 32, vMacScreenMonoByteWidth * MyWindowScale);
4326 if (NULL == my_Scaled_image) {
4327 fprintf(stderr, "XCreateImage failed.\n");
4328 return falseblnr;
4329 }
4330
4331 my_Scaled_image->bitmap_bit_order = MSBFirst;
4332 my_Scaled_image->byte_order = MSBFirst;
4333#endif
4334
4335#if EnableMagnify && UseColorImage
4336 my_Scaled_image = XCreateImage(x_display, Xvisual,
4337 24, ZPixmap, 0,
4338 NULL /* (char *)image_Mem1 */,
4339 vMacScreenWidth * MyWindowScale,
4340 vMacScreenHeight * MyWindowScale,
4341 32, 4 * (ui5r)vMacScreenWidth * MyWindowScale);
4342 if (NULL == my_Scaled_image) {
4343 fprintf(stderr, "XCreateImage Scaled failed.\n");
4344 return falseblnr;
4345 }
4346#endif
4347
4348#if 0 != vMacScreenDepth
4349 ColorModeWorks = trueblnr;
4350#endif
4351
4352 DisableKeyRepeat();
4353
4354 return trueblnr;
4355}
4356
4357LOCALPROC CloseMainWindow(void)
4358{
4359 if (my_gc != NULL) {
4360 XFreeGC(x_display, my_gc);
4361 my_gc = NULL;
4362 }
4363 if (my_main_wind) {
4364 XDestroyWindow(x_display, my_main_wind);
4365 my_main_wind = 0;
4366 }
4367}
4368
4369enum {
4370 kMagStateNormal,
4371#if EnableMagnify
4372 kMagStateMagnifgy,
4373#endif
4374 kNumMagStates
4375};
4376
4377#define kMagStateAuto kNumMagStates
4378
4379#if MayNotFullScreen
4380LOCALVAR int CurWinIndx;
4381LOCALVAR blnr HavePositionWins[kNumMagStates];
4382LOCALVAR int WinPositionWinsH[kNumMagStates];
4383LOCALVAR int WinPositionWinsV[kNumMagStates];
4384#endif
4385
4386#if EnableRecreateW
4387LOCALPROC ZapMyWState(void)
4388{
4389 my_main_wind = 0;
4390 my_gc = NULL;
4391}
4392#endif
4393
4394LOCALFUNC blnr CreateMainWindow(void)
4395{
4396 Window rootwin;
4397 int screen;
4398 int xr;
4399 int yr;
4400 unsigned int dr;
4401 unsigned int wr;
4402 unsigned int hr;
4403 unsigned int bwr;
4404 Window rr;
4405 int leftPos;
4406 int topPos;
4407#if MayNotFullScreen
4408 int WinIndx;
4409#endif
4410#if EnableDragDrop
4411 long int xdnd_version = 5;
4412#endif
4413 int NewWindowHeight = vMacScreenHeight;
4414 int NewWindowWidth = vMacScreenWidth;
4415
4416 /* Get connection to X Server */
4417 screen = DefaultScreen(x_display);
4418
4419 rootwin = XRootWindow(x_display, screen);
4420
4421 XGetGeometry(x_display, rootwin,
4422 &rr, &xr, &yr, &wr, &hr, &bwr, &dr);
4423
4424#if EnableMagnify
4425 if (UseMagnify) {
4426 NewWindowHeight *= MyWindowScale;
4427 NewWindowWidth *= MyWindowScale;
4428 }
4429#endif
4430
4431 if (wr > NewWindowWidth) {
4432 leftPos = (wr - NewWindowWidth) / 2;
4433 } else {
4434 leftPos = 0;
4435 }
4436 if (hr > NewWindowHeight) {
4437 topPos = (hr - NewWindowHeight) / 2;
4438 } else {
4439 topPos = 0;
4440 }
4441
4442#if VarFullScreen
4443 if (UseFullScreen)
4444#endif
4445#if MayFullScreen
4446 {
4447 ViewHSize = wr;
4448 ViewVSize = hr;
4449#if EnableMagnify
4450 if (UseMagnify) {
4451 ViewHSize /= MyWindowScale;
4452 ViewVSize /= MyWindowScale;
4453 }
4454#endif
4455 if (ViewHSize >= vMacScreenWidth) {
4456 ViewHStart = 0;
4457 ViewHSize = vMacScreenWidth;
4458 } else {
4459 ViewHSize &= ~ 1;
4460 }
4461 if (ViewVSize >= vMacScreenHeight) {
4462 ViewVStart = 0;
4463 ViewVSize = vMacScreenHeight;
4464 } else {
4465 ViewVSize &= ~ 1;
4466 }
4467 }
4468#endif
4469
4470#if VarFullScreen
4471 if (! UseFullScreen)
4472#endif
4473#if MayNotFullScreen
4474 {
4475#if EnableMagnify
4476 if (UseMagnify) {
4477 WinIndx = kMagStateMagnifgy;
4478 } else
4479#endif
4480 {
4481 WinIndx = kMagStateNormal;
4482 }
4483
4484 if (! HavePositionWins[WinIndx]) {
4485 WinPositionWinsH[WinIndx] = leftPos;
4486 WinPositionWinsV[WinIndx] = topPos;
4487 HavePositionWins[WinIndx] = trueblnr;
4488 } else {
4489 leftPos = WinPositionWinsH[WinIndx];
4490 topPos = WinPositionWinsV[WinIndx];
4491 }
4492 }
4493#endif
4494
4495#if VarFullScreen
4496 if (UseFullScreen)
4497#endif
4498#if MayFullScreen
4499 {
4500 XSetWindowAttributes xattr;
4501 xattr.override_redirect = True;
4502 xattr.background_pixel = x_black.pixel;
4503 xattr.border_pixel = x_white.pixel;
4504
4505 my_main_wind = XCreateWindow(x_display, rr,
4506 0, 0, wr, hr, 0,
4507 CopyFromParent, /* depth */
4508 InputOutput, /* class */
4509 CopyFromParent, /* visual */
4510 CWOverrideRedirect | CWBackPixel | CWBorderPixel,
4511 /* valuemask */
4512 &xattr /* attributes */);
4513 }
4514#endif
4515#if VarFullScreen
4516 else
4517#endif
4518#if MayNotFullScreen
4519 {
4520 my_main_wind = XCreateSimpleWindow(x_display, rootwin,
4521 leftPos,
4522 topPos,
4523 NewWindowWidth, NewWindowHeight, 4,
4524 x_white.pixel,
4525 x_black.pixel);
4526 }
4527#endif
4528
4529 if (! my_main_wind) {
4530 WriteExtraErr("XCreateSimpleWindow failed.");
4531 return falseblnr;
4532 } else {
4533 char *win_name =
4534 (NULL != n_arg) ? n_arg : (
4535#if CanGetAppPath
4536 (NULL != app_name) ? app_name :
4537#endif
4538 kStrAppName);
4539 XSelectInput(x_display, my_main_wind,
4540 ExposureMask | KeyPressMask | KeyReleaseMask
4541 | ButtonPressMask | ButtonReleaseMask
4542#if UseMotionEvents
4543 | PointerMotionMask | EnterWindowMask | LeaveWindowMask
4544#endif
4545 | FocusChangeMask);
4546
4547 XStoreName(x_display, my_main_wind, win_name);
4548 XSetIconName(x_display, my_main_wind, win_name);
4549
4550 {
4551 XClassHint *hints = XAllocClassHint();
4552 if (hints) {
4553 hints->res_name = "minivmac";
4554 hints->res_class = "minivmac";
4555 XSetClassHint(x_display, my_main_wind, hints);
4556 XFree(hints);
4557 }
4558 }
4559
4560 {
4561 XWMHints *hints = XAllocWMHints();
4562 if (hints) {
4563 hints->input = True;
4564 hints->initial_state = NormalState;
4565 hints->flags = InputHint | StateHint;
4566 XSetWMHints(x_display, my_main_wind, hints);
4567 XFree(hints);
4568 }
4569
4570 }
4571
4572 XSetCommand(x_display, my_main_wind, my_argv, my_argc);
4573
4574 /* let us handle a click on the close box */
4575 XSetWMProtocols(x_display, my_main_wind, &MyXA_DeleteW, 1);
4576
4577#if EnableDragDrop
4578 XChangeProperty (x_display, my_main_wind, MyXA_DndAware,
4579 XA_ATOM, 32, PropModeReplace,
4580 (unsigned char *) &xdnd_version, 1);
4581#endif
4582
4583 my_gc = XCreateGC(x_display, my_main_wind, 0, NULL);
4584 if (NULL == my_gc) {
4585 WriteExtraErr("XCreateGC failed.");
4586 return falseblnr;
4587 }
4588 XSetState(x_display, my_gc, x_black.pixel, x_white.pixel,
4589 GXcopy, AllPlanes);
4590
4591#if VarFullScreen
4592 if (! UseFullScreen)
4593#endif
4594#if MayNotFullScreen
4595 {
4596 XSizeHints *hints = XAllocSizeHints();
4597 if (hints) {
4598 hints->min_width = NewWindowWidth;
4599 hints->max_width = NewWindowWidth;
4600 hints->min_height = NewWindowHeight;
4601 hints->max_height = NewWindowHeight;
4602
4603 /*
4604 Try again to say where the window ought to go.
4605 I've seen this described as obsolete, but it
4606 seems to work on all x implementations tried
4607 so far, and nothing else does.
4608 */
4609 hints->x = leftPos;
4610 hints->y = topPos;
4611 hints->width = NewWindowWidth;
4612 hints->height = NewWindowHeight;
4613
4614 hints->flags = PMinSize | PMaxSize | PPosition | PSize;
4615 XSetWMNormalHints(x_display, my_main_wind, hints);
4616 XFree(hints);
4617 }
4618 }
4619#endif
4620
4621#if VarFullScreen
4622 if (UseFullScreen)
4623#endif
4624#if MayFullScreen
4625 {
4626 hOffset = leftPos;
4627 vOffset = topPos;
4628 }
4629#endif
4630
4631 DisconnectKeyCodes3();
4632 /* since will lose keystrokes to old window */
4633
4634#if MayNotFullScreen
4635 CurWinIndx = WinIndx;
4636#endif
4637
4638 XMapRaised(x_display, my_main_wind);
4639
4640#if 0
4641 XSync(x_display, 0);
4642#endif
4643
4644#if 0
4645 /*
4646 This helps in Red Hat 9 to get the new window
4647 activated, and I've seen other programs
4648 do similar things.
4649 */
4650 /*
4651 In current scheme, haven't closed old window
4652 yet. If old window full screen, never receive
4653 expose event for new one.
4654 */
4655 {
4656 XEvent event;
4657
4658 do {
4659 XNextEvent(x_display, &event);
4660 HandleTheEvent(&event);
4661 } while (! ((Expose == event.type)
4662 && (event.xexpose.window == my_main_wind)));
4663 }
4664#endif
4665
4666 NeedFinishOpen1 = trueblnr;
4667 NeedFinishOpen2 = trueblnr;
4668
4669 return trueblnr;
4670 }
4671}
4672
4673#if MayFullScreen
4674LOCALVAR blnr GrabMachine = falseblnr;
4675#endif
4676
4677#if MayFullScreen
4678LOCALPROC GrabTheMachine(void)
4679{
4680#if EnableFSMouseMotion
4681 StartSaveMouseMotion();
4682#endif
4683#if GrabKeysFullScreen
4684 MyGrabKeyboard();
4685#endif
4686}
4687#endif
4688
4689#if MayFullScreen
4690LOCALPROC UngrabMachine(void)
4691{
4692#if EnableFSMouseMotion
4693 StopSaveMouseMotion();
4694#endif
4695#if GrabKeysFullScreen
4696 MyUnGrabKeyboard();
4697#endif
4698}
4699#endif
4700
4701#if EnableRecreateW
4702struct MyWState {
4703 Window f_my_main_wind;
4704 GC f_my_gc;
4705#if MayFullScreen
4706 short f_hOffset;
4707 short f_vOffset;
4708 ui4r f_ViewHSize;
4709 ui4r f_ViewVSize;
4710 ui4r f_ViewHStart;
4711 ui4r f_ViewVStart;
4712#endif
4713#if VarFullScreen
4714 blnr f_UseFullScreen;
4715#endif
4716#if EnableMagnify
4717 blnr f_UseMagnify;
4718#endif
4719};
4720typedef struct MyWState MyWState;
4721#endif
4722
4723#if EnableRecreateW
4724LOCALPROC GetMyWState(MyWState *r)
4725{
4726 r->f_my_main_wind = my_main_wind;
4727 r->f_my_gc = my_gc;
4728#if MayFullScreen
4729 r->f_hOffset = hOffset;
4730 r->f_vOffset = vOffset;
4731 r->f_ViewHSize = ViewHSize;
4732 r->f_ViewVSize = ViewVSize;
4733 r->f_ViewHStart = ViewHStart;
4734 r->f_ViewVStart = ViewVStart;
4735#endif
4736#if VarFullScreen
4737 r->f_UseFullScreen = UseFullScreen;
4738#endif
4739#if EnableMagnify
4740 r->f_UseMagnify = UseMagnify;
4741#endif
4742}
4743#endif
4744
4745#if EnableRecreateW
4746LOCALPROC SetMyWState(MyWState *r)
4747{
4748 my_main_wind = r->f_my_main_wind;
4749 my_gc = r->f_my_gc;
4750#if MayFullScreen
4751 hOffset = r->f_hOffset;
4752 vOffset = r->f_vOffset;
4753 ViewHSize = r->f_ViewHSize;
4754 ViewVSize = r->f_ViewVSize;
4755 ViewHStart = r->f_ViewHStart;
4756 ViewVStart = r->f_ViewVStart;
4757#endif
4758#if VarFullScreen
4759 UseFullScreen = r->f_UseFullScreen;
4760#endif
4761#if EnableMagnify
4762 UseMagnify = r->f_UseMagnify;
4763#endif
4764}
4765#endif
4766
4767#if EnableRecreateW
4768LOCALVAR blnr WantRestoreCursPos = falseblnr;
4769LOCALVAR ui4b RestoreMouseH;
4770LOCALVAR ui4b RestoreMouseV;
4771#endif
4772
4773#if EnableRecreateW
4774LOCALFUNC blnr ReCreateMainWindow(void)
4775{
4776 MyWState old_state;
4777 MyWState new_state;
4778#if IncludeHostTextClipExchange
4779 blnr OwnClipboard = falseblnr;
4780#endif
4781
4782 if (HaveCursorHidden) {
4783 WantRestoreCursPos = trueblnr;
4784 RestoreMouseH = CurMouseH;
4785 RestoreMouseV = CurMouseV;
4786 }
4787
4788 ForceShowCursor(); /* hide/show cursor api is per window */
4789
4790#if MayNotFullScreen
4791#if VarFullScreen
4792 if (! UseFullScreen)
4793#endif
4794 if (my_main_wind)
4795 if (! NeedFinishOpen2)
4796 {
4797 /* save old position */
4798 int xr;
4799 int yr;
4800 unsigned int dr;
4801 unsigned int wr;
4802 unsigned int hr;
4803 unsigned int bwr;
4804 Window rr;
4805 Window rr2;
4806
4807 /* Get connection to X Server */
4808 int screen = DefaultScreen(x_display);
4809
4810 Window rootwin = XRootWindow(x_display, screen);
4811
4812 XGetGeometry(x_display, rootwin,
4813 &rr, &xr, &yr, &wr, &hr, &bwr, &dr);
4814
4815 /*
4816 Couldn't reliably find out where window
4817 is now, due to what seem to be some
4818 broken X implementations, and so instead
4819 track how far window has moved.
4820 */
4821 XSync(x_display, 0);
4822 if (XTranslateCoordinates(x_display, my_main_wind, rootwin,
4823 0, 0, &xr, &yr, &rr2))
4824 {
4825 int newposh =
4826 WinPositionWinsH[CurWinIndx] + (xr - SavedTransH);
4827 int newposv =
4828 WinPositionWinsV[CurWinIndx] + (yr - SavedTransV);
4829 if ((newposv > 0) && (newposv < hr) && (newposh < wr)) {
4830 WinPositionWinsH[CurWinIndx] = newposh;
4831 WinPositionWinsV[CurWinIndx] = newposv;
4832 SavedTransH = xr;
4833 SavedTransV = yr;
4834 }
4835 }
4836 }
4837#endif
4838
4839#if MayFullScreen
4840 if (GrabMachine) {
4841 GrabMachine = falseblnr;
4842 UngrabMachine();
4843 }
4844#endif
4845
4846 GetMyWState(&old_state);
4847 ZapMyWState();
4848
4849#if EnableMagnify
4850 UseMagnify = WantMagnify;
4851#endif
4852#if VarFullScreen
4853 UseFullScreen = WantFullScreen;
4854#endif
4855
4856 ColorTransValid = falseblnr;
4857
4858 if (! CreateMainWindow()) {
4859 CloseMainWindow();
4860 SetMyWState(&old_state);
4861
4862 /* avoid retry */
4863#if VarFullScreen
4864 WantFullScreen = UseFullScreen;
4865#endif
4866#if EnableMagnify
4867 WantMagnify = UseMagnify;
4868#endif
4869
4870 return falseblnr;
4871 } else {
4872 GetMyWState(&new_state);
4873 SetMyWState(&old_state);
4874
4875#if IncludeHostTextClipExchange
4876 if (my_main_wind) {
4877 if (XGetSelectionOwner(x_display, MyXA_CLIPBOARD) ==
4878 my_main_wind)
4879 {
4880 OwnClipboard = trueblnr;
4881 }
4882 }
4883#endif
4884
4885 CloseMainWindow();
4886
4887 SetMyWState(&new_state);
4888
4889#if IncludeHostTextClipExchange
4890 if (OwnClipboard) {
4891 XSetSelectionOwner(x_display, MyXA_CLIPBOARD,
4892 my_main_wind, CurrentTime);
4893 }
4894#endif
4895 }
4896
4897 return trueblnr;
4898}
4899#endif
4900
4901#if VarFullScreen && EnableMagnify
4902enum {
4903 kWinStateWindowed,
4904#if EnableMagnify
4905 kWinStateFullScreen,
4906#endif
4907 kNumWinStates
4908};
4909#endif
4910
4911#if VarFullScreen && EnableMagnify
4912LOCALVAR int WinMagStates[kNumWinStates];
4913#endif
4914
4915LOCALPROC ZapWinStateVars(void)
4916{
4917#if MayNotFullScreen
4918 {
4919 int i;
4920
4921 for (i = 0; i < kNumMagStates; ++i) {
4922 HavePositionWins[i] = falseblnr;
4923 }
4924 }
4925#endif
4926#if VarFullScreen && EnableMagnify
4927 {
4928 int i;
4929
4930 for (i = 0; i < kNumWinStates; ++i) {
4931 WinMagStates[i] = kMagStateAuto;
4932 }
4933 }
4934#endif
4935}
4936
4937#if VarFullScreen
4938LOCALPROC ToggleWantFullScreen(void)
4939{
4940 WantFullScreen = ! WantFullScreen;
4941
4942#if EnableMagnify
4943 {
4944 int OldWinState =
4945 UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
4946 int OldMagState =
4947 UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
4948 int NewWinState =
4949 WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
4950 int NewMagState = WinMagStates[NewWinState];
4951
4952 WinMagStates[OldWinState] = OldMagState;
4953 if (kMagStateAuto != NewMagState) {
4954 WantMagnify = (kMagStateMagnifgy == NewMagState);
4955 } else {
4956 WantMagnify = falseblnr;
4957 if (WantFullScreen) {
4958 Window rootwin;
4959 int xr;
4960 int yr;
4961 unsigned int dr;
4962 unsigned int wr;
4963 unsigned int hr;
4964 unsigned int bwr;
4965 Window rr;
4966
4967 rootwin =
4968 XRootWindow(x_display, DefaultScreen(x_display));
4969 XGetGeometry(x_display, rootwin,
4970 &rr, &xr, &yr, &wr, &hr, &bwr, &dr);
4971 if ((wr >= vMacScreenWidth * MyWindowScale)
4972 && (hr >= vMacScreenHeight * MyWindowScale)
4973 )
4974 {
4975 WantMagnify = trueblnr;
4976 }
4977 }
4978 }
4979 }
4980#endif
4981}
4982#endif
4983
4984/* --- SavedTasks --- */
4985
4986LOCALPROC LeaveBackground(void)
4987{
4988 ReconnectKeyCodes3();
4989 DisableKeyRepeat();
4990}
4991
4992LOCALPROC EnterBackground(void)
4993{
4994 RestoreKeyRepeat();
4995 DisconnectKeyCodes3();
4996
4997 ForceShowCursor();
4998}
4999
5000LOCALPROC LeaveSpeedStopped(void)
5001{
5002#if MySoundEnabled
5003 MySound_Start();
5004#endif
5005
5006 StartUpTimeAdjust();
5007}
5008
5009LOCALPROC EnterSpeedStopped(void)
5010{
5011#if MySoundEnabled
5012 MySound_Stop();
5013#endif
5014}
5015
5016LOCALPROC CheckForSavedTasks(void)
5017{
5018 if (MyEvtQNeedRecover) {
5019 MyEvtQNeedRecover = falseblnr;
5020
5021 /* attempt cleanup, MyEvtQNeedRecover may get set again */
5022 MyEvtQTryRecoverFromFull();
5023 }
5024
5025 if (NeedFinishOpen2 && ! NeedFinishOpen1) {
5026 NeedFinishOpen2 = falseblnr;
5027
5028#if VarFullScreen
5029 if (UseFullScreen)
5030#endif
5031#if MayFullScreen
5032 {
5033 XSetInputFocus(x_display, my_main_wind,
5034 RevertToPointerRoot, CurrentTime);
5035 }
5036#endif
5037#if VarFullScreen
5038 else
5039#endif
5040#if MayNotFullScreen
5041 {
5042 Window rr;
5043 int screen = DefaultScreen(x_display);
5044 Window rootwin = XRootWindow(x_display, screen);
5045#if 0
5046 /*
5047 This doesn't work right in Red Hat 6, and may not
5048 be needed anymore, now that using PPosition hint.
5049 */
5050 XMoveWindow(x_display, my_main_wind,
5051 leftPos, topPos);
5052 /*
5053 Needed after XMapRaised, because some window
5054 managers will apparently ignore where the
5055 window was asked to be put.
5056 */
5057#endif
5058
5059 XSync(x_display, 0);
5060 /*
5061 apparently, XTranslateCoordinates can be inaccurate
5062 without this
5063 */
5064 XTranslateCoordinates(x_display, my_main_wind, rootwin,
5065 0, 0, &SavedTransH, &SavedTransV, &rr);
5066 }
5067#endif
5068
5069#if EnableRecreateW
5070 if (WantRestoreCursPos) {
5071#if EnableFSMouseMotion
5072 if (! HaveMouseMotion)
5073#endif
5074 {
5075 (void) MyMoveMouse(RestoreMouseH, RestoreMouseV);
5076 WantCursorHidden = trueblnr;
5077 }
5078 WantRestoreCursPos = falseblnr;
5079 }
5080#endif
5081 }
5082
5083#if EnableFSMouseMotion
5084 if (HaveMouseMotion) {
5085 MyMouseConstrain();
5086 }
5087#endif
5088
5089 if (RequestMacOff) {
5090 RequestMacOff = falseblnr;
5091 if (AnyDiskInserted()) {
5092 MacMsgOverride(kStrQuitWarningTitle,
5093 kStrQuitWarningMessage);
5094 } else {
5095 ForceMacOff = trueblnr;
5096 }
5097 }
5098
5099 if (ForceMacOff) {
5100 return;
5101 }
5102
5103 if (gTrueBackgroundFlag != gBackgroundFlag) {
5104 gBackgroundFlag = gTrueBackgroundFlag;
5105 if (gTrueBackgroundFlag) {
5106 EnterBackground();
5107 } else {
5108 LeaveBackground();
5109 }
5110 }
5111
5112 if (CurSpeedStopped != (SpeedStopped ||
5113 (gBackgroundFlag && ! RunInBackground
5114#if EnableAutoSlow && 0
5115 && (QuietSubTicks >= 4092)
5116#endif
5117 )))
5118 {
5119 CurSpeedStopped = ! CurSpeedStopped;
5120 if (CurSpeedStopped) {
5121 EnterSpeedStopped();
5122 } else {
5123 LeaveSpeedStopped();
5124 }
5125 }
5126
5127#if MayFullScreen
5128 if (gTrueBackgroundFlag
5129#if VarFullScreen
5130 && WantFullScreen
5131#endif
5132 )
5133 {
5134 /*
5135 Since often get here on Ubuntu Linux 5.10
5136 running on a slow machine (emulated) when
5137 attempt to enter full screen, don't abort
5138 full screen, but try to fix it.
5139 */
5140#if 0
5141 ToggleWantFullScreen();
5142#else
5143 XRaiseWindow(x_display, my_main_wind);
5144 XSetInputFocus(x_display, my_main_wind,
5145 RevertToPointerRoot, CurrentTime);
5146#endif
5147 }
5148#endif
5149
5150#if EnableRecreateW
5151 if (0
5152#if EnableMagnify
5153 || (UseMagnify != WantMagnify)
5154#endif
5155#if VarFullScreen
5156 || (UseFullScreen != WantFullScreen)
5157#endif
5158 )
5159 {
5160 (void) ReCreateMainWindow();
5161 }
5162#endif
5163
5164
5165#if MayFullScreen
5166 if (GrabMachine != (
5167#if VarFullScreen
5168 UseFullScreen &&
5169#endif
5170 ! (gTrueBackgroundFlag || CurSpeedStopped)))
5171 {
5172 GrabMachine = ! GrabMachine;
5173 if (GrabMachine) {
5174 GrabTheMachine();
5175 } else {
5176 UngrabMachine();
5177 }
5178 }
5179#endif
5180
5181#if IncludeSonyNew
5182 if (vSonyNewDiskWanted) {
5183#if IncludeSonyNameNew
5184 if (vSonyNewDiskName != NotAPbuf) {
5185 ui3p NewDiskNameDat;
5186 if (MacRomanTextToNativePtr(vSonyNewDiskName, trueblnr,
5187 &NewDiskNameDat))
5188 {
5189 MakeNewDisk(vSonyNewDiskSize, (char *)NewDiskNameDat);
5190 free(NewDiskNameDat);
5191 }
5192 PbufDispose(vSonyNewDiskName);
5193 vSonyNewDiskName = NotAPbuf;
5194 } else
5195#endif
5196 {
5197 MakeNewDiskAtDefault(vSonyNewDiskSize);
5198 }
5199 vSonyNewDiskWanted = falseblnr;
5200 /* must be done after may have gotten disk */
5201 }
5202#endif
5203
5204 if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
5205 MacMsgDisplayOn();
5206 }
5207
5208 if (NeedWholeScreenDraw) {
5209 NeedWholeScreenDraw = falseblnr;
5210 ScreenChangedAll();
5211 }
5212
5213#if NeedRequestIthDisk
5214 if (0 != RequestIthDisk) {
5215 Sony_InsertIth(RequestIthDisk);
5216 RequestIthDisk = 0;
5217 }
5218#endif
5219
5220 if (HaveCursorHidden != (WantCursorHidden
5221 && ! (gTrueBackgroundFlag || CurSpeedStopped)))
5222 {
5223 HaveCursorHidden = ! HaveCursorHidden;
5224 if (HaveCursorHidden) {
5225 XDefineCursor(x_display, my_main_wind, blankCursor);
5226 } else {
5227 XUndefineCursor(x_display, my_main_wind);
5228 }
5229 }
5230}
5231
5232/* --- command line parsing --- */
5233
5234LOCALFUNC blnr ScanCommandLine(void)
5235{
5236 char *pa;
5237 int i = 1;
5238
5239label_retry:
5240 if (i < my_argc) {
5241 pa = my_argv[i++];
5242 if ('-' == pa[0]) {
5243 if ((0 == strcmp(pa, "--display"))
5244 || (0 == strcmp(pa, "-display")))
5245 {
5246 if (i < my_argc) {
5247 display_name = my_argv[i++];
5248 goto label_retry;
5249 }
5250 } else
5251 if ((0 == strcmp(pa, "--rom"))
5252 || (0 == strcmp(pa, "-r")))
5253 {
5254 if (i < my_argc) {
5255 rom_path = my_argv[i++];
5256 goto label_retry;
5257 }
5258 } else
5259 if (0 == strcmp(pa, "-n"))
5260 {
5261 if (i < my_argc) {
5262 n_arg = my_argv[i++];
5263 goto label_retry;
5264 }
5265 } else
5266 if (0 == strcmp(pa, "-d"))
5267 {
5268 if (i < my_argc) {
5269 d_arg = my_argv[i++];
5270 goto label_retry;
5271 }
5272 } else
5273#ifndef UsingAlsa
5274#define UsingAlsa 0
5275#endif
5276
5277#if UsingAlsa
5278 if ((0 == strcmp(pa, "--alsadev"))
5279 || (0 == strcmp(pa, "-alsadev")))
5280 {
5281 if (i < my_argc) {
5282 alsadev_name = my_argv[i++];
5283 goto label_retry;
5284 }
5285 } else
5286#endif
5287#if 0
5288 if (0 == strcmp(pa, "-l")) {
5289 SpeedValue = 0;
5290 goto label_retry;
5291 } else
5292#endif
5293 {
5294 MacMsg(kStrBadArgTitle, kStrBadArgMessage, falseblnr);
5295 }
5296 } else {
5297 (void) Sony_Insert1(pa, falseblnr);
5298 goto label_retry;
5299 }
5300 }
5301
5302 return trueblnr;
5303}
5304
5305/* --- main program flow --- */
5306
5307GLOBALOSGLUPROC DoneWithDrawingForTick(void)
5308{
5309#if EnableFSMouseMotion
5310 if (HaveMouseMotion) {
5311 AutoScrollScreen();
5312 }
5313#endif
5314 MyDrawChangesAndClear();
5315 XFlush(x_display);
5316}
5317
5318GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
5319{
5320 UpdateTrueEmulatedTime();
5321 return TrueEmulatedTime == OnTrueTime;
5322}
5323
5324LOCALPROC WaitForTheNextEvent(void)
5325{
5326 XEvent event;
5327
5328 XNextEvent(x_display, &event);
5329 HandleTheEvent(&event);
5330}
5331
5332LOCALPROC CheckForSystemEvents(void)
5333{
5334 int i = 10;
5335
5336 while ((XEventsQueued(x_display, QueuedAfterReading) > 0)
5337 && (--i >= 0))
5338 {
5339 WaitForTheNextEvent();
5340 }
5341}
5342
5343GLOBALOSGLUPROC WaitForNextTick(void)
5344{
5345label_retry:
5346 CheckForSystemEvents();
5347 CheckForSavedTasks();
5348 if (ForceMacOff) {
5349 return;
5350 }
5351
5352 if (CurSpeedStopped) {
5353 DoneWithDrawingForTick();
5354 WaitForTheNextEvent();
5355 goto label_retry;
5356 }
5357
5358 if (ExtraTimeNotOver()) {
5359 struct timespec rqt;
5360 struct timespec rmt;
5361
5362 si5b TimeDiff = GetTimeDiff();
5363 if (TimeDiff < 0) {
5364 rqt.tv_sec = 0;
5365 rqt.tv_nsec = (- TimeDiff) * 1000;
5366 (void) nanosleep(&rqt, &rmt);
5367 }
5368 goto label_retry;
5369 }
5370
5371 if (CheckDateTime()) {
5372#if MySoundEnabled
5373 MySound_SecondNotify();
5374#endif
5375#if EnableDemoMsg
5376 DemoModeSecondNotify();
5377#endif
5378 }
5379
5380 if ((! gBackgroundFlag)
5381#if UseMotionEvents
5382 && (! CaughtMouse)
5383#endif
5384 )
5385 {
5386 CheckMouseState();
5387 }
5388
5389 OnTrueTime = TrueEmulatedTime;
5390
5391#if dbglog_TimeStuff
5392 dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
5393#endif
5394}
5395
5396/* --- platform independent code can be thought of as going here --- */
5397
5398#include "PROGMAIN.h"
5399
5400LOCALPROC ZapOSGLUVars(void)
5401{
5402 InitDrives();
5403 ZapWinStateVars();
5404}
5405
5406LOCALPROC ReserveAllocAll(void)
5407{
5408#if dbglog_HAVE
5409 dbglog_ReserveAlloc();
5410#endif
5411 ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
5412
5413 ReserveAllocOneBlock(&screencomparebuff,
5414 vMacScreenNumBytes, 5, trueblnr);
5415#if UseControlKeys
5416 ReserveAllocOneBlock(&CntrlDisplayBuff,
5417 vMacScreenNumBytes, 5, falseblnr);
5418#endif
5419#if WantScalingBuff
5420 ReserveAllocOneBlock(&ScalingBuff,
5421 ScalingBuffsz, 5, falseblnr);
5422#endif
5423#if WantScalingTabl
5424 ReserveAllocOneBlock(&ScalingTabl,
5425 ScalingTablsz, 5, falseblnr);
5426#endif
5427
5428#if MySoundEnabled
5429 ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
5430 dbhBufferSize, 5, falseblnr);
5431#endif
5432
5433 EmulationReserveAlloc();
5434}
5435
5436LOCALFUNC blnr AllocMyMemory(void)
5437{
5438 uimr n;
5439 blnr IsOk = falseblnr;
5440
5441 ReserveAllocOffset = 0;
5442 ReserveAllocBigBlock = nullpr;
5443 ReserveAllocAll();
5444 n = ReserveAllocOffset;
5445 ReserveAllocBigBlock = (ui3p)calloc(1, n);
5446 if (NULL == ReserveAllocBigBlock) {
5447 MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
5448 } else {
5449 ReserveAllocOffset = 0;
5450 ReserveAllocAll();
5451 if (n != ReserveAllocOffset) {
5452 /* oops, program error */
5453 } else {
5454 IsOk = trueblnr;
5455 }
5456 }
5457
5458 return IsOk;
5459}
5460
5461LOCALPROC UnallocMyMemory(void)
5462{
5463 if (nullpr != ReserveAllocBigBlock) {
5464 free((char *)ReserveAllocBigBlock);
5465 }
5466}
5467
5468#if HaveAppPathLink
5469LOCALFUNC blnr ReadLink_Alloc(char *path, char **r)
5470{
5471 /*
5472 This should work to find size:
5473
5474 struct stat r;
5475
5476 if (lstat(path, &r) != -1) {
5477 r = r.st_size;
5478 IsOk = trueblnr;
5479 }
5480
5481 But observed to return 0 in Ubuntu 10.04 x86-64
5482 */
5483
5484 char *s;
5485 int sz;
5486 char *p;
5487 blnr IsOk = falseblnr;
5488 size_t s_alloc = 256;
5489
5490label_retry:
5491 s = (char *)malloc(s_alloc);
5492 if (NULL == s) {
5493 fprintf(stderr, "malloc failed.\n");
5494 } else {
5495 sz = readlink(path, s, s_alloc);
5496 if ((sz < 0) || (sz >= s_alloc)) {
5497 free(s);
5498 if (sz == s_alloc) {
5499 s_alloc <<= 1;
5500 goto label_retry;
5501 } else {
5502 fprintf(stderr, "readlink failed.\n");
5503 }
5504 } else {
5505 /* ok */
5506 p = (char *)malloc(sz + 1);
5507 if (NULL == p) {
5508 fprintf(stderr, "malloc failed.\n");
5509 } else {
5510 (void) memcpy(p, s, sz);
5511 p[sz] = 0;
5512 *r = p;
5513 IsOk = trueblnr;
5514 }
5515 free(s);
5516 }
5517 }
5518
5519 return IsOk;
5520}
5521#endif
5522
5523#if HaveSysctlPath
5524LOCALFUNC blnr ReadKernProcPathname(char **r)
5525{
5526 size_t s_alloc;
5527 char *s;
5528 int mib[] = {
5529 CTL_KERN,
5530 KERN_PROC,
5531 KERN_PROC_PATHNAME,
5532 -1
5533 };
5534 blnr IsOk = falseblnr;
5535
5536 if (0 != sysctl(mib, sizeof(mib) / sizeof(int),
5537 NULL, &s_alloc, NULL, 0))
5538 {
5539 fprintf(stderr, "sysctl failed.\n");
5540 } else {
5541 s = (char *)malloc(s_alloc);
5542 if (NULL == s) {
5543 fprintf(stderr, "malloc failed.\n");
5544 } else {
5545 if (0 != sysctl(mib, sizeof(mib) / sizeof(int),
5546 s, &s_alloc, NULL, 0))
5547 {
5548 fprintf(stderr, "sysctl 2 failed.\n");
5549 } else {
5550 *r = s;
5551 IsOk = trueblnr;
5552 }
5553 if (! IsOk) {
5554 free(s);
5555 }
5556 }
5557 }
5558
5559 return IsOk;
5560}
5561#endif
5562
5563#if CanGetAppPath
5564LOCALFUNC blnr Path2ParentAndName(char *path,
5565 char **parent, char **name)
5566{
5567 blnr IsOk = falseblnr;
5568
5569 char *t = strrchr(path, '/');
5570 if (NULL == t) {
5571 fprintf(stderr, "no directory.\n");
5572 } else {
5573 int par_sz = t - path;
5574 char *par = (char *)malloc(par_sz + 1);
5575 if (NULL == par) {
5576 fprintf(stderr, "malloc failed.\n");
5577 } else {
5578 (void) memcpy(par, path, par_sz);
5579 par[par_sz] = 0;
5580 {
5581 int s_sz = strlen(path);
5582 int child_sz = s_sz - par_sz - 1;
5583 char *child = (char *)malloc(child_sz + 1);
5584 if (NULL == child) {
5585 fprintf(stderr, "malloc failed.\n");
5586 } else {
5587 (void) memcpy(child, t + 1, child_sz);
5588 child[child_sz] = 0;
5589
5590 *name = child;
5591 IsOk = trueblnr;
5592 /* free(child); */
5593 }
5594 }
5595 if (! IsOk) {
5596 free(par);
5597 } else {
5598 *parent = par;
5599 }
5600 }
5601 }
5602
5603 return IsOk;
5604}
5605#endif
5606
5607#if CanGetAppPath
5608LOCALFUNC blnr InitWhereAmI(void)
5609{
5610 char *s;
5611
5612 if (!
5613#if HaveAppPathLink
5614 ReadLink_Alloc(TheAppPathLink, &s)
5615#endif
5616#if HaveSysctlPath
5617 ReadKernProcPathname(&s)
5618#endif
5619 )
5620 {
5621 fprintf(stderr, "InitWhereAmI fails.\n");
5622 } else {
5623 if (! Path2ParentAndName(s, &app_parent, &app_name)) {
5624 fprintf(stderr, "Path2ParentAndName fails.\n");
5625 } else {
5626 /* ok */
5627 /*
5628 fprintf(stderr, "parent = %s.\n", app_parent);
5629 fprintf(stderr, "name = %s.\n", app_name);
5630 */
5631 }
5632
5633 free(s);
5634 }
5635
5636 return trueblnr; /* keep going regardless */
5637}
5638#endif
5639
5640#if CanGetAppPath
5641LOCALPROC UninitWhereAmI(void)
5642{
5643 MyMayFree(app_parent);
5644 MyMayFree(app_name);
5645}
5646#endif
5647
5648LOCALFUNC blnr InitOSGLU(void)
5649{
5650 if (AllocMyMemory())
5651#if CanGetAppPath
5652 if (InitWhereAmI())
5653#endif
5654#if dbglog_HAVE
5655 if (dbglog_open())
5656#endif
5657 if (ScanCommandLine())
5658 if (LoadMacRom())
5659 if (LoadInitialImages())
5660#if UseActvCode
5661 if (ActvCodeInit())
5662#endif
5663 if (InitLocationDat())
5664#if MySoundEnabled
5665 if (MySound_Init())
5666#endif
5667 if (Screen_Init())
5668 if (CreateMainWindow())
5669 if (KC2MKCInit())
5670#if EmLocalTalk
5671 if (EntropyGather())
5672 if (InitLocalTalk())
5673#endif
5674 if (WaitForRom())
5675 {
5676 return trueblnr;
5677 }
5678 return falseblnr;
5679}
5680
5681LOCALPROC UnInitOSGLU(void)
5682{
5683 if (MacMsgDisplayed) {
5684 MacMsgDisplayOff();
5685 }
5686
5687#if EmLocalTalk
5688 UnInitLocalTalk();
5689#endif
5690
5691 RestoreKeyRepeat();
5692#if MayFullScreen
5693 UngrabMachine();
5694#endif
5695#if MySoundEnabled
5696 MySound_Stop();
5697#endif
5698#if MySoundEnabled
5699 MySound_UnInit();
5700#endif
5701#if IncludeHostTextClipExchange
5702 FreeMyClipBuffer();
5703#endif
5704#if IncludePbufs
5705 UnInitPbufs();
5706#endif
5707 UnInitDrives();
5708
5709 ForceShowCursor();
5710 if (blankCursor != None) {
5711 XFreeCursor(x_display, blankCursor);
5712 }
5713
5714 if (my_image != NULL) {
5715 XDestroyImage(my_image);
5716 }
5717#if EnableMagnify
5718 if (my_Scaled_image != NULL) {
5719 XDestroyImage(my_Scaled_image);
5720 }
5721#endif
5722
5723 CloseMainWindow();
5724 if (x_display != NULL) {
5725 XCloseDisplay(x_display);
5726 }
5727
5728#if dbglog_HAVE
5729 dbglog_close();
5730#endif
5731
5732#if CanGetAppPath
5733 UninitWhereAmI();
5734#endif
5735 UnallocMyMemory();
5736
5737 CheckSavedMacMsg();
5738}
5739
5740int main(int argc, char **argv)
5741{
5742 my_argc = argc;
5743 my_argv = argv;
5744
5745 ZapOSGLUVars();
5746 if (InitOSGLU()) {
5747 ProgramMain();
5748 }
5749 UnInitOSGLU();
5750
5751 return 0;
5752}
5753
5754#endif /* WantOSGLUXWN */