2019-07-23 02:50:34 +00:00
|
|
|
/*
|
|
|
|
OSGLUXWN.c
|
|
|
|
|
|
|
|
Copyright (C) 2009 Michael Hanni, Christian Bauer,
|
|
|
|
Stephan Kochen, Paul C. Pratt, and others
|
|
|
|
|
|
|
|
You can redistribute this file and/or modify it under the terms
|
|
|
|
of version 2 of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation. You should have received a copy
|
|
|
|
of the license along with this file; see the file COPYING.
|
|
|
|
|
|
|
|
This file is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
license for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Operating System GLUe for X WiNdow system
|
|
|
|
|
|
|
|
All operating system dependent code for the
|
|
|
|
X Window System should go here.
|
|
|
|
|
|
|
|
This code is descended from Michael Hanni's X
|
|
|
|
port of vMac, by Philip Cummins.
|
|
|
|
I learned more about how X programs work by
|
|
|
|
looking at other programs such as Basilisk II,
|
|
|
|
the UAE Amiga Emulator, Bochs, QuakeForge,
|
|
|
|
DooM Legacy, and the FLTK. A few snippets
|
|
|
|
from them are used here.
|
|
|
|
|
|
|
|
Drag and Drop support is based on the specification
|
|
|
|
"XDND: Drag-and-Drop Protocol for the X Window System"
|
|
|
|
developed by John Lindal at New Planet Software, and
|
|
|
|
looking at included examples, one by Paul Sheer.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "CNFGRAPI.h"
|
|
|
|
#include "SYSDEPNS.h"
|
|
|
|
#include "ENDIANAC.h"
|
|
|
|
|
2020-02-11 04:12:22 +00:00
|
|
|
#include "UI/MYOSGLUE.h"
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#include "STRCONST.h"
|
|
|
|
|
|
|
|
/* --- some simple utilities --- */
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
GLOBALOSGLUPROC MoveBytes(anyp srcPtr, anyp destPtr, int32_t byteCount)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- control mode and internationalization --- */
|
|
|
|
|
|
|
|
#define NeedCell2PlainAsciiMap 1
|
|
|
|
|
|
|
|
#include "INTLCHAR.h"
|
|
|
|
|
|
|
|
|
|
|
|
LOCALVAR char *d_arg = NULL;
|
|
|
|
LOCALVAR char *n_arg = NULL;
|
|
|
|
|
|
|
|
#if CanGetAppPath
|
|
|
|
LOCALVAR char *app_parent = NULL;
|
|
|
|
LOCALVAR char *app_name = NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LOCALFUNC tMacErr ChildPath(char *x, char *y, char **r)
|
|
|
|
{
|
|
|
|
tMacErr err = mnvm_miscErr;
|
|
|
|
int nx = strlen(x);
|
|
|
|
int ny = strlen(y);
|
|
|
|
{
|
|
|
|
if ((nx > 0) && ('/' == x[nx - 1])) {
|
|
|
|
--nx;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
int nr = nx + 1 + ny;
|
|
|
|
char *p = malloc(nr + 1);
|
|
|
|
if (p != NULL) {
|
|
|
|
char *p2 = p;
|
|
|
|
(void) memcpy(p2, x, nx);
|
|
|
|
p2 += nx;
|
|
|
|
*p2++ = '/';
|
|
|
|
(void) memcpy(p2, y, ny);
|
|
|
|
p2 += ny;
|
|
|
|
*p2 = 0;
|
|
|
|
*r = p;
|
|
|
|
err = mnvm_noErr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if UseActvFile || IncludeSonyNew
|
|
|
|
LOCALFUNC tMacErr FindOrMakeChild(char *x, char *y, char **r)
|
|
|
|
{
|
|
|
|
tMacErr err;
|
|
|
|
struct stat folder_info;
|
|
|
|
char *r0;
|
|
|
|
|
|
|
|
if (mnvm_noErr == (err = ChildPath(x, y, &r0))) {
|
|
|
|
if (0 != stat(r0, &folder_info)) {
|
|
|
|
if (0 != mkdir(r0, S_IRWXU)) {
|
|
|
|
err = mnvm_miscErr;
|
|
|
|
} else {
|
|
|
|
*r = r0;
|
|
|
|
err = mnvm_noErr;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (! S_ISDIR(folder_info.st_mode)) {
|
|
|
|
err = mnvm_miscErr;
|
|
|
|
} else {
|
|
|
|
*r = r0;
|
|
|
|
err = mnvm_noErr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC MayFree(char *p)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
if (NULL != p) {
|
|
|
|
free(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- sending debugging info to file --- */
|
|
|
|
|
|
|
|
#if dbglog_HAVE
|
|
|
|
|
|
|
|
#define dbglog_ToStdErr 0
|
|
|
|
|
|
|
|
#if ! dbglog_ToStdErr
|
|
|
|
LOCALVAR FILE *dbglog_File = NULL;
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool dbglog_open0(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
#if dbglog_ToStdErr
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
#else
|
|
|
|
dbglog_File = fopen("dbglog.txt", "w");
|
|
|
|
return (NULL != dbglog_File);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC dbglog_write0(char *s, uimr L)
|
|
|
|
{
|
|
|
|
#if dbglog_ToStdErr
|
|
|
|
(void) fwrite(s, 1, L, stderr);
|
|
|
|
#else
|
|
|
|
if (dbglog_File != NULL) {
|
|
|
|
(void) fwrite(s, 1, L, dbglog_File);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC dbglog_close0(void)
|
|
|
|
{
|
|
|
|
#if ! dbglog_ToStdErr
|
|
|
|
if (dbglog_File != NULL) {
|
|
|
|
fclose(dbglog_File);
|
|
|
|
dbglog_File = NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* --- debug settings and utilities --- */
|
|
|
|
|
|
|
|
#if ! dbglog_HAVE
|
|
|
|
#define WriteExtraErr(s)
|
|
|
|
#else
|
|
|
|
LOCALPROC WriteExtraErr(char *s)
|
|
|
|
{
|
|
|
|
dbglog_writeCStr("*** error: ");
|
|
|
|
dbglog_writeCStr(s);
|
|
|
|
dbglog_writeReturn();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LOCALVAR Display *x_display = NULL;
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
#define DbgEvents (dbglog_HAVE && 0)
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
LOCALPROC WriteDbgAtom(char *s, Atom x)
|
|
|
|
{
|
|
|
|
char *name = XGetAtomName(x_display, x);
|
|
|
|
if (name != NULL) {
|
|
|
|
dbglog_writeCStr("Atom ");
|
|
|
|
dbglog_writeCStr(s);
|
|
|
|
dbglog_writeCStr(": ");
|
|
|
|
dbglog_writeCStr(name);
|
|
|
|
dbglog_writeReturn();
|
|
|
|
XFree(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* --- information about the environment --- */
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALVAR Atom XA_DeleteW = (Atom)0;
|
2019-07-23 02:50:34 +00:00
|
|
|
#if EnableDragDrop
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALVAR Atom XA_UriList = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_DndAware = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_DndEnter = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_DndLeave = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_DndDrop = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_DndPosition = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_DndStatus = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_DndActionCopy = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_DndActionPrivate = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_DndSelection = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_DndFinished = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_MinivMac_DndXchng = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_NetActiveWindow = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_NetSupported = (Atom)0;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
#if IncludeHostTextClipExchange
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALVAR Atom XA_CLIPBOARD = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_TARGETS = (Atom)0;
|
|
|
|
LOCALVAR Atom XA_MinivMac_Clip = (Atom)0;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC LoadXA(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_DeleteW = XInternAtom(x_display, "WM_DELETE_WINDOW", False);
|
2019-07-23 02:50:34 +00:00
|
|
|
#if EnableDragDrop
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_UriList = XInternAtom (x_display, "text/uri-list", False);
|
|
|
|
XA_DndAware = XInternAtom (x_display, "XdndAware", False);
|
|
|
|
XA_DndEnter = XInternAtom(x_display, "XdndEnter", False);
|
|
|
|
XA_DndLeave = XInternAtom(x_display, "XdndLeave", False);
|
|
|
|
XA_DndDrop = XInternAtom(x_display, "XdndDrop", False);
|
|
|
|
XA_DndPosition = XInternAtom(x_display, "XdndPosition", False);
|
|
|
|
XA_DndStatus = XInternAtom(x_display, "XdndStatus", False);
|
|
|
|
XA_DndActionCopy = XInternAtom(x_display,
|
2019-07-23 02:50:34 +00:00
|
|
|
"XdndActionCopy", False);
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_DndActionPrivate = XInternAtom(x_display,
|
2019-07-23 02:50:34 +00:00
|
|
|
"XdndActionPrivate", False);
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_DndSelection = XInternAtom(x_display, "XdndSelection", False);
|
|
|
|
XA_DndFinished = XInternAtom(x_display, "XdndFinished", False);
|
|
|
|
XA_MinivMac_DndXchng = XInternAtom(x_display,
|
2019-07-23 02:50:34 +00:00
|
|
|
"_MinivMac_DndXchng", False);
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_NetActiveWindow = XInternAtom(x_display,
|
2019-07-23 02:50:34 +00:00
|
|
|
"_NET_ACTIVE_WINDOW", False);
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_NetSupported = XInternAtom(x_display,
|
2019-07-23 02:50:34 +00:00
|
|
|
"_NET_SUPPORTED", False);
|
|
|
|
#endif
|
|
|
|
#if IncludeHostTextClipExchange
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_CLIPBOARD = XInternAtom(x_display, "CLIPBOARD", False);
|
|
|
|
XA_TARGETS = XInternAtom(x_display, "TARGETS", False);
|
|
|
|
XA_MinivMac_Clip = XInternAtom(x_display,
|
2019-07-23 02:50:34 +00:00
|
|
|
"_MinivMac_Clip", False);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if EnableDragDrop
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool NetSupportedContains(Atom x)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
Note that the window manager could be replaced at
|
|
|
|
any time, so don't cache results of this function.
|
|
|
|
*/
|
|
|
|
Atom ret_type;
|
|
|
|
int ret_format;
|
|
|
|
unsigned long ret_item;
|
|
|
|
unsigned long remain_byte;
|
|
|
|
unsigned long i;
|
|
|
|
unsigned char *s = 0;
|
2020-02-11 05:34:32 +00:00
|
|
|
bool foundit = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
Window rootwin = XRootWindow(x_display,
|
|
|
|
DefaultScreen(x_display));
|
|
|
|
|
|
|
|
if (Success != XGetWindowProperty(x_display, rootwin,
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_NetSupported,
|
2019-07-23 02:50:34 +00:00
|
|
|
0, 65535, False, XA_ATOM, &ret_type, &ret_format,
|
|
|
|
&ret_item, &remain_byte, &s))
|
|
|
|
{
|
|
|
|
WriteExtraErr("XGetWindowProperty failed");
|
|
|
|
} else if (! s) {
|
|
|
|
WriteExtraErr("XGetWindowProperty failed");
|
|
|
|
} else if (ret_type != XA_ATOM) {
|
|
|
|
WriteExtraErr("XGetWindowProperty returns wrong type");
|
|
|
|
} else {
|
|
|
|
Atom *v = (Atom *)s;
|
|
|
|
|
|
|
|
for (i = 0; i < ret_item; ++i) {
|
|
|
|
if (v[i] == x) {
|
2020-02-11 05:34:32 +00:00
|
|
|
foundit = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
/* fprintf(stderr, "found the hint\n"); */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (s) {
|
|
|
|
XFree(s);
|
|
|
|
}
|
|
|
|
return foundit;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define WantColorTransValid 1
|
|
|
|
|
|
|
|
#include "COMOSGLU.h"
|
|
|
|
|
|
|
|
#include "PBUFSTDC.h"
|
|
|
|
|
|
|
|
#include "CONTROLM.h"
|
|
|
|
|
|
|
|
/* --- text translation --- */
|
|
|
|
|
|
|
|
#if IncludePbufs
|
|
|
|
/* this is table for Windows, any changes needed for X? */
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALVAR const uint8_t Native2MacRomanTab[] = {
|
2019-07-23 02:50:34 +00:00
|
|
|
0xAD, 0xB0, 0xE2, 0xC4, 0xE3, 0xC9, 0xA0, 0xE0,
|
|
|
|
0xF6, 0xE4, 0xB6, 0xDC, 0xCE, 0xB2, 0xB3, 0xB7,
|
|
|
|
0xB8, 0xD4, 0xD5, 0xD2, 0xD3, 0xA5, 0xD0, 0xD1,
|
|
|
|
0xF7, 0xAA, 0xC5, 0xDD, 0xCF, 0xB9, 0xC3, 0xD9,
|
|
|
|
0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0xBA, 0xA4,
|
|
|
|
0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0xBD, 0xA8, 0xF8,
|
|
|
|
0xA1, 0xB1, 0xC6, 0xD7, 0xAB, 0xB5, 0xA6, 0xE1,
|
|
|
|
0xFC, 0xDA, 0xBC, 0xC8, 0xDE, 0xDF, 0xF0, 0xC0,
|
|
|
|
0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,
|
|
|
|
0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,
|
|
|
|
0xF5, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0xF9,
|
|
|
|
0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0xFA, 0xFB, 0xA7,
|
|
|
|
0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,
|
|
|
|
0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
|
|
|
|
0xFD, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,
|
|
|
|
0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0xFE, 0xFF, 0xD8
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludePbufs
|
|
|
|
LOCALFUNC tMacErr NativeTextToMacRomanPbuf(char *x, tPbuf *r)
|
|
|
|
{
|
|
|
|
if (NULL == x) {
|
|
|
|
return mnvm_miscErr;
|
|
|
|
} else {
|
2020-02-11 05:34:32 +00:00
|
|
|
uint8_t * p;
|
2020-02-11 03:46:59 +00:00
|
|
|
uint32_t L = strlen(x);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
p = (uint8_t *)malloc(L);
|
2019-07-23 02:50:34 +00:00
|
|
|
if (NULL == p) {
|
|
|
|
return mnvm_miscErr;
|
|
|
|
} else {
|
2020-02-11 03:46:59 +00:00
|
|
|
uint8_t *p0 = (uint8_t *)x;
|
|
|
|
uint8_t *p1 = (uint8_t *)p;
|
2019-07-23 02:50:34 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = L; --i >= 0; ) {
|
2020-02-11 03:46:59 +00:00
|
|
|
uint8_t v = *p0++;
|
2019-07-23 02:50:34 +00:00
|
|
|
if (v >= 128) {
|
|
|
|
v = Native2MacRomanTab[v - 128];
|
|
|
|
} else if (10 == v) {
|
|
|
|
v = 13;
|
|
|
|
}
|
|
|
|
*p1++ = v;
|
|
|
|
}
|
|
|
|
|
|
|
|
return PbufNewFromPtr(p, L, r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludePbufs
|
|
|
|
/* this is table for Windows, any changes needed for X? */
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALVAR const uint8_t MacRoman2NativeTab[] = {
|
2019-07-23 02:50:34 +00:00
|
|
|
0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1,
|
|
|
|
0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8,
|
|
|
|
0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3,
|
|
|
|
0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC,
|
|
|
|
0x86, 0xB0, 0xA2, 0xA3, 0xA7, 0x95, 0xB6, 0xDF,
|
|
|
|
0xAE, 0xA9, 0x99, 0xB4, 0xA8, 0x80, 0xC6, 0xD8,
|
|
|
|
0x81, 0xB1, 0x8D, 0x8E, 0xA5, 0xB5, 0x8A, 0x8F,
|
|
|
|
0x90, 0x9D, 0xA6, 0xAA, 0xBA, 0xAD, 0xE6, 0xF8,
|
|
|
|
0xBF, 0xA1, 0xAC, 0x9E, 0x83, 0x9A, 0xB2, 0xAB,
|
|
|
|
0xBB, 0x85, 0xA0, 0xC0, 0xC3, 0xD5, 0x8C, 0x9C,
|
|
|
|
0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xF7, 0xB3,
|
|
|
|
0xFF, 0x9F, 0xB9, 0xA4, 0x8B, 0x9B, 0xBC, 0xBD,
|
|
|
|
0x87, 0xB7, 0x82, 0x84, 0x89, 0xC2, 0xCA, 0xC1,
|
|
|
|
0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0xD3, 0xD4,
|
|
|
|
0xBE, 0xD2, 0xDA, 0xDB, 0xD9, 0xD0, 0x88, 0x98,
|
|
|
|
0xAF, 0xD7, 0xDD, 0xDE, 0xB8, 0xF0, 0xFD, 0xFE
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludePbufs
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool MacRomanTextToNativePtr(tPbuf i, bool IsFileName,
|
|
|
|
uint8_t * *r)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
uint8_t * p;
|
2019-07-23 02:50:34 +00:00
|
|
|
void *Buffer = PbufDat[i];
|
2020-02-11 03:46:59 +00:00
|
|
|
uint32_t L = PbufSize[i];
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
p = (uint8_t *)malloc(L + 1);
|
2019-07-23 02:50:34 +00:00
|
|
|
if (p != NULL) {
|
2020-02-11 03:46:59 +00:00
|
|
|
uint8_t *p0 = (uint8_t *)Buffer;
|
|
|
|
uint8_t *p1 = (uint8_t *)p;
|
2019-07-23 02:50:34 +00:00
|
|
|
int j;
|
|
|
|
|
|
|
|
if (IsFileName) {
|
|
|
|
for (j = L; --j >= 0; ) {
|
2020-02-11 03:46:59 +00:00
|
|
|
uint8_t x = *p0++;
|
2019-07-23 02:50:34 +00:00
|
|
|
if (x < 32) {
|
|
|
|
x = '-';
|
|
|
|
} else if (x >= 128) {
|
|
|
|
x = MacRoman2NativeTab[x - 128];
|
|
|
|
} else {
|
|
|
|
switch (x) {
|
|
|
|
case '/':
|
|
|
|
case '<':
|
|
|
|
case '>':
|
|
|
|
case '|':
|
|
|
|
case ':':
|
|
|
|
x = '-';
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*p1++ = x;
|
|
|
|
}
|
|
|
|
if ('.' == p[0]) {
|
|
|
|
p[0] = '-';
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (j = L; --j >= 0; ) {
|
2020-02-11 03:46:59 +00:00
|
|
|
uint8_t x = *p0++;
|
2019-07-23 02:50:34 +00:00
|
|
|
if (x >= 128) {
|
|
|
|
x = MacRoman2NativeTab[x - 128];
|
|
|
|
} else if (13 == x) {
|
|
|
|
x = '\n';
|
|
|
|
}
|
|
|
|
*p1++ = x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*p1 = 0;
|
|
|
|
|
|
|
|
*r = p;
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LOCALPROC NativeStrFromCStr(char *r, char *s)
|
|
|
|
{
|
2020-02-11 03:46:59 +00:00
|
|
|
uint8_t ps[ClStrMaxLength];
|
2019-07-23 02:50:34 +00:00
|
|
|
int i;
|
|
|
|
int L;
|
|
|
|
|
|
|
|
ClStrFromSubstCStr(&L, ps, s);
|
|
|
|
|
|
|
|
for (i = 0; i < L; ++i) {
|
|
|
|
r[i] = Cell2PlainAsciiMap[ps[i]];
|
|
|
|
}
|
|
|
|
|
|
|
|
r[L] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- drives --- */
|
|
|
|
|
|
|
|
#define NotAfileRef NULL
|
|
|
|
|
|
|
|
LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */
|
|
|
|
#if IncludeSonyGetName || IncludeSonyNew
|
|
|
|
LOCALVAR char *DriveNames[NumDrives];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LOCALPROC InitDrives(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
This isn't really needed, Drives[i] and DriveNames[i]
|
|
|
|
need not have valid values when not vSonyIsInserted[i].
|
|
|
|
*/
|
|
|
|
tDrive i;
|
|
|
|
|
|
|
|
for (i = 0; i < NumDrives; ++i) {
|
|
|
|
Drives[i] = NotAfileRef;
|
|
|
|
#if IncludeSonyGetName || IncludeSonyNew
|
|
|
|
DriveNames[i] = NULL;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyTransfer(bool IsWrite, uint8_t * Buffer,
|
2020-02-11 03:46:59 +00:00
|
|
|
tDrive Drive_No, uint32_t Sony_Start, uint32_t Sony_Count,
|
|
|
|
uint32_t *Sony_ActCount)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
tMacErr err = mnvm_miscErr;
|
|
|
|
FILE *refnum = Drives[Drive_No];
|
2020-02-11 03:46:59 +00:00
|
|
|
uint32_t NewSony_Count = 0;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if (0 == fseek(refnum, Sony_Start, SEEK_SET)) {
|
|
|
|
if (IsWrite) {
|
|
|
|
NewSony_Count = fwrite(Buffer, 1, Sony_Count, refnum);
|
|
|
|
} else {
|
|
|
|
NewSony_Count = fread(Buffer, 1, Sony_Count, refnum);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NewSony_Count == Sony_Count) {
|
|
|
|
err = mnvm_noErr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nullpr != Sony_ActCount) {
|
|
|
|
*Sony_ActCount = NewSony_Count;
|
|
|
|
}
|
|
|
|
|
|
|
|
return err; /*& figure out what really to return &*/
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:46:59 +00:00
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, uint32_t *Sony_Count)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
tMacErr err = mnvm_miscErr;
|
|
|
|
FILE *refnum = Drives[Drive_No];
|
|
|
|
long v;
|
|
|
|
|
|
|
|
if (0 == fseek(refnum, 0, SEEK_END)) {
|
|
|
|
v = ftell(refnum);
|
|
|
|
if (v >= 0) {
|
|
|
|
*Sony_Count = v;
|
|
|
|
err = mnvm_noErr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return err; /*& figure out what really to return &*/
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef HaveAdvisoryLocks
|
|
|
|
#define HaveAdvisoryLocks 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
What is the difference between fcntl(fd, F_SETLK ...
|
|
|
|
and flock(fd ... ?
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if HaveAdvisoryLocks
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool LockFile(FILE *refnum)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
bool IsOk = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#if 1
|
|
|
|
struct flock fl;
|
|
|
|
int fd = fileno(refnum);
|
|
|
|
|
|
|
|
fl.l_start = 0; /* starting offset */
|
|
|
|
fl.l_len = 0; /* len = 0 means until end of file */
|
|
|
|
/* fl.pid_t l_pid; */ /* lock owner, don't need to set */
|
|
|
|
fl.l_type = F_WRLCK; /* lock type: read/write, etc. */
|
|
|
|
fl.l_whence = SEEK_SET; /* type of l_start */
|
|
|
|
if (-1 == fcntl(fd, F_SETLK, &fl)) {
|
|
|
|
MacMsg(kStrImageInUseTitle, kStrImageInUseMessage,
|
2020-02-11 05:34:32 +00:00
|
|
|
false);
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
int fd = fileno(refnum);
|
|
|
|
|
|
|
|
if (-1 == flock(fd, LOCK_EX | LOCK_NB)) {
|
|
|
|
MacMsg(kStrImageInUseTitle, kStrImageInUseMessage,
|
2020-02-11 05:34:32 +00:00
|
|
|
false);
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return IsOk;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if HaveAdvisoryLocks
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC UnlockFile(FILE *refnum)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
#if 1
|
|
|
|
struct flock fl;
|
|
|
|
int fd = fileno(refnum);
|
|
|
|
|
|
|
|
fl.l_start = 0; /* starting offset */
|
|
|
|
fl.l_len = 0; /* len = 0 means until end of file */
|
|
|
|
/* fl.pid_t l_pid; */ /* lock owner, don't need to set */
|
|
|
|
fl.l_type = F_UNLCK; /* lock type: read/write, etc. */
|
|
|
|
fl.l_whence = SEEK_SET; /* type of l_start */
|
|
|
|
if (-1 == fcntl(fd, F_SETLK, &fl)) {
|
|
|
|
/* an error occurred */
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
int fd = fileno(refnum);
|
|
|
|
|
|
|
|
if (-1 == flock(fd, LOCK_UN)) {
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, bool deleteit)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
FILE *refnum = Drives[Drive_No];
|
|
|
|
|
|
|
|
DiskEjectedNotify(Drive_No);
|
|
|
|
|
|
|
|
#if HaveAdvisoryLocks
|
2020-02-11 03:56:58 +00:00
|
|
|
UnlockFile(refnum);
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
fclose(refnum);
|
|
|
|
Drives[Drive_No] = NotAfileRef; /* not really needed */
|
|
|
|
|
|
|
|
#if IncludeSonyGetName || IncludeSonyNew
|
|
|
|
{
|
|
|
|
char *s = DriveNames[Drive_No];
|
|
|
|
if (NULL != s) {
|
|
|
|
if (deleteit) {
|
|
|
|
remove(s);
|
|
|
|
}
|
|
|
|
free(s);
|
|
|
|
DriveNames[Drive_No] = NULL; /* not really needed */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return mnvm_noErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
return vSonyEject0(Drive_No, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if IncludeSonyNew
|
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
return vSonyEject0(Drive_No, true);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LOCALPROC UnInitDrives(void)
|
|
|
|
{
|
|
|
|
tDrive i;
|
|
|
|
|
|
|
|
for (i = 0; i < NumDrives; ++i) {
|
|
|
|
if (vSonyIsInserted(i)) {
|
|
|
|
(void) vSonyEject(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if IncludeSonyGetName
|
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
|
|
|
|
{
|
|
|
|
char *drivepath = DriveNames[Drive_No];
|
|
|
|
if (NULL == drivepath) {
|
|
|
|
return mnvm_miscErr;
|
|
|
|
} else {
|
|
|
|
char *s = strrchr(drivepath, '/');
|
|
|
|
if (NULL == s) {
|
|
|
|
s = drivepath;
|
|
|
|
} else {
|
|
|
|
++s;
|
|
|
|
}
|
|
|
|
return NativeTextToMacRomanPbuf(s, r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool Sony_Insert0(FILE *refnum, bool locked,
|
2019-07-23 02:50:34 +00:00
|
|
|
char *drivepath)
|
|
|
|
{
|
|
|
|
tDrive Drive_No;
|
2020-02-11 05:34:32 +00:00
|
|
|
bool IsOk = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if (! FirstFreeDisk(&Drive_No)) {
|
|
|
|
MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage,
|
2020-02-11 05:34:32 +00:00
|
|
|
false);
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
|
|
|
/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
|
|
|
|
|
|
|
|
#if HaveAdvisoryLocks
|
2020-02-11 03:56:58 +00:00
|
|
|
if (locked || LockFile(refnum))
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
{
|
|
|
|
Drives[Drive_No] = refnum;
|
|
|
|
DiskInsertNotify(Drive_No, locked);
|
|
|
|
|
|
|
|
#if IncludeSonyGetName || IncludeSonyNew
|
|
|
|
{
|
2020-02-11 03:46:59 +00:00
|
|
|
uint32_t L = strlen(drivepath);
|
2019-07-23 02:50:34 +00:00
|
|
|
char *p = malloc(L + 1);
|
|
|
|
if (p != NULL) {
|
|
|
|
(void) memcpy(p, drivepath, L + 1);
|
|
|
|
}
|
|
|
|
DriveNames[Drive_No] = p;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! IsOk) {
|
|
|
|
fclose(refnum);
|
|
|
|
}
|
|
|
|
|
|
|
|
return IsOk;
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool Sony_Insert1(char *drivepath, bool silentfail)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
bool locked = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
/* printf("Sony_Insert1 %s\n", drivepath); */
|
|
|
|
FILE *refnum = fopen(drivepath, "rb+");
|
|
|
|
if (NULL == refnum) {
|
2020-02-11 05:34:32 +00:00
|
|
|
locked = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
refnum = fopen(drivepath, "rb");
|
|
|
|
}
|
|
|
|
if (NULL == refnum) {
|
|
|
|
if (! silentfail) {
|
2020-02-11 05:34:32 +00:00
|
|
|
MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return Sony_Insert0(refnum, locked, drivepath);
|
|
|
|
}
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LOCALFUNC tMacErr LoadMacRomFrom(char *path)
|
|
|
|
{
|
|
|
|
tMacErr err;
|
|
|
|
FILE *ROM_File;
|
|
|
|
int File_Size;
|
|
|
|
|
|
|
|
ROM_File = fopen(path, "rb");
|
|
|
|
if (NULL == ROM_File) {
|
|
|
|
err = mnvm_fnfErr;
|
|
|
|
} else {
|
|
|
|
File_Size = fread(ROM, 1, kROM_Size, ROM_File);
|
|
|
|
if (kROM_Size != File_Size) {
|
|
|
|
if (feof(ROM_File)) {
|
|
|
|
MacMsgOverride(kStrShortROMTitle,
|
|
|
|
kStrShortROMMessage);
|
|
|
|
err = mnvm_eofErr;
|
|
|
|
} else {
|
|
|
|
MacMsgOverride(kStrNoReadROMTitle,
|
|
|
|
kStrNoReadROMMessage);
|
|
|
|
err = mnvm_miscErr;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
err = ROM_IsValid();
|
|
|
|
}
|
|
|
|
fclose(ROM_File);
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool Sony_Insert1a(char *drivepath, bool silentfail)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
bool v;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if (! ROM_loaded) {
|
|
|
|
v = (mnvm_noErr == LoadMacRomFrom(drivepath));
|
|
|
|
} else {
|
|
|
|
v = Sony_Insert1(drivepath, silentfail);
|
|
|
|
}
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool Sony_Insert2(char *s)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
char *d =
|
|
|
|
#if CanGetAppPath
|
|
|
|
(NULL == d_arg) ? app_parent :
|
|
|
|
#endif
|
|
|
|
d_arg;
|
2020-02-11 05:34:32 +00:00
|
|
|
bool IsOk = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if (NULL == d) {
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = Sony_Insert1(s, true);
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
|
|
|
char *t;
|
|
|
|
|
|
|
|
if (mnvm_noErr == ChildPath(d, s, &t)) {
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = Sony_Insert1(t, true);
|
2019-07-23 02:50:34 +00:00
|
|
|
free(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return IsOk;
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool Sony_InsertIth(int i)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
bool v;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if ((i > 9) || ! FirstFreeDisk(nullpr)) {
|
2020-02-11 05:34:32 +00:00
|
|
|
v = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
|
|
|
char s[] = "disk?.dsk";
|
|
|
|
|
|
|
|
s[4] = '0' + i;
|
|
|
|
|
|
|
|
v = Sony_Insert2(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool LoadInitialImages(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
if (! AnyDiskInserted()) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 1; Sony_InsertIth(i); ++i) {
|
|
|
|
/* stop on first error (including file not found) */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if IncludeSonyNew
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool WriteZero(FILE *refnum, uint32_t L)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
#define ZeroBufferSize 2048
|
2020-02-11 03:46:59 +00:00
|
|
|
uint32_t i;
|
|
|
|
uint8_t buffer[ZeroBufferSize];
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
memset(&buffer, 0, ZeroBufferSize);
|
|
|
|
|
|
|
|
while (L > 0) {
|
|
|
|
i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
|
|
|
|
if (fwrite(buffer, 1, i, refnum) != i) {
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
L -= i;
|
|
|
|
}
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludeSonyNew
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALPROC MakeNewDisk0(uint32_t L, char *drivepath)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
bool IsOk = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
FILE *refnum = fopen(drivepath, "wb+");
|
|
|
|
if (NULL == refnum) {
|
2020-02-11 05:34:32 +00:00
|
|
|
MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
|
|
|
if (WriteZero(refnum, L)) {
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = Sony_Insert0(refnum, false, drivepath);
|
2019-07-23 02:50:34 +00:00
|
|
|
refnum = NULL;
|
|
|
|
}
|
|
|
|
if (refnum != NULL) {
|
|
|
|
fclose(refnum);
|
|
|
|
}
|
|
|
|
if (! IsOk) {
|
|
|
|
(void) remove(drivepath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludeSonyNew
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALPROC MakeNewDisk(uint32_t L, char *drivename)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
char *d =
|
|
|
|
#if CanGetAppPath
|
|
|
|
(NULL == d_arg) ? app_parent :
|
|
|
|
#endif
|
|
|
|
d_arg;
|
|
|
|
|
|
|
|
if (NULL == d) {
|
|
|
|
MakeNewDisk0(L, drivename); /* in current directory */
|
|
|
|
} else {
|
|
|
|
tMacErr err;
|
|
|
|
char *t = NULL;
|
|
|
|
char *t2 = NULL;
|
|
|
|
|
|
|
|
if (mnvm_noErr == (err = FindOrMakeChild(d, "out", &t)))
|
|
|
|
if (mnvm_noErr == (err = ChildPath(t, drivename, &t2)))
|
|
|
|
{
|
|
|
|
MakeNewDisk0(L, t2);
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
MayFree(t2);
|
|
|
|
MayFree(t);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludeSonyNew
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALPROC MakeNewDiskAtDefault(uint32_t L)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
char s[ClStrMaxLength + 1];
|
|
|
|
|
|
|
|
NativeStrFromCStr(s, "untitled.dsk");
|
|
|
|
MakeNewDisk(L, s);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* --- ROM --- */
|
|
|
|
|
|
|
|
LOCALVAR char *rom_path = NULL;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LOCALFUNC tMacErr FindUserHomeFolder(char **r)
|
|
|
|
{
|
|
|
|
tMacErr err;
|
|
|
|
char *s;
|
|
|
|
#if 0
|
|
|
|
struct passwd *user;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (NULL != (s = getenv("HOME"))) {
|
|
|
|
*r = s;
|
|
|
|
err = mnvm_noErr;
|
|
|
|
} else
|
|
|
|
#if 0
|
|
|
|
if ((NULL != (user = getpwuid(getuid())))
|
|
|
|
&& (NULL != (s = user->pw_dir)))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
From getpwuid man page:
|
|
|
|
"An application that wants to determine its user's
|
|
|
|
home directory should inspect the value of HOME
|
|
|
|
(rather than the value getpwuid(getuid())->pw_dir)
|
|
|
|
since this allows the user to modify their notion of
|
|
|
|
"the home directory" during a login session."
|
|
|
|
|
|
|
|
But it is possible for HOME to not be set.
|
|
|
|
Some sources say to use getpwuid in that case.
|
|
|
|
*/
|
|
|
|
*r = s;
|
|
|
|
err = mnvm_noErr;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
err = mnvm_fnfErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALFUNC tMacErr LoadMacRomFromHome(void)
|
|
|
|
{
|
|
|
|
tMacErr err;
|
|
|
|
char *s;
|
|
|
|
char *t = NULL;
|
|
|
|
char *t2 = NULL;
|
|
|
|
char *t3 = NULL;
|
|
|
|
|
|
|
|
if (mnvm_noErr == (err = FindUserHomeFolder(&s)))
|
|
|
|
if (mnvm_noErr == (err = ChildPath(s, ".gryphel", &t)))
|
|
|
|
if (mnvm_noErr == (err = ChildPath(t, "mnvm_rom", &t2)))
|
|
|
|
if (mnvm_noErr == (err = ChildPath(t2, RomFileName, &t3)))
|
|
|
|
{
|
|
|
|
err = LoadMacRomFrom(t3);
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
MayFree(t3);
|
|
|
|
MayFree(t2);
|
|
|
|
MayFree(t);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if CanGetAppPath
|
|
|
|
LOCALFUNC tMacErr LoadMacRomFromAppPar(void)
|
|
|
|
{
|
|
|
|
tMacErr err;
|
|
|
|
char *d =
|
|
|
|
#if CanGetAppPath
|
|
|
|
(NULL == d_arg) ? app_parent :
|
|
|
|
#endif
|
|
|
|
d_arg;
|
|
|
|
char *t = NULL;
|
|
|
|
|
|
|
|
if (NULL == d) {
|
|
|
|
err = mnvm_fnfErr;
|
|
|
|
} else {
|
|
|
|
if (mnvm_noErr == (err = ChildPath(d, RomFileName,
|
|
|
|
&t)))
|
|
|
|
{
|
|
|
|
err = LoadMacRomFrom(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
MayFree(t);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool LoadMacRom(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
tMacErr err;
|
|
|
|
|
|
|
|
if ((NULL == rom_path)
|
|
|
|
|| (mnvm_fnfErr == (err = LoadMacRomFrom(rom_path))))
|
|
|
|
#if CanGetAppPath
|
|
|
|
if (mnvm_fnfErr == (err = LoadMacRomFromAppPar()))
|
|
|
|
#endif
|
|
|
|
if (mnvm_fnfErr == (err = LoadMacRomFromHome()))
|
|
|
|
if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName)))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
return true; /* keep launching Mini vMac, regardless */
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if UseActvFile
|
|
|
|
|
|
|
|
#define ActvCodeFileName "act_1"
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC tMacErr ActvCodeFileLoad(uint8_t * p)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
tMacErr err;
|
|
|
|
char *s;
|
|
|
|
char *t = NULL;
|
|
|
|
char *t2 = NULL;
|
|
|
|
char *t3 = NULL;
|
|
|
|
|
|
|
|
if (mnvm_noErr == (err = FindUserHomeFolder(&s)))
|
|
|
|
if (mnvm_noErr == (err = ChildPath(s, ".gryphel", &t)))
|
|
|
|
if (mnvm_noErr == (err = ChildPath(t, "mnvm_act", &t2)))
|
|
|
|
if (mnvm_noErr == (err = ChildPath(t2, ActvCodeFileName, &t3)))
|
|
|
|
{
|
|
|
|
FILE *Actv_File;
|
|
|
|
int File_Size;
|
|
|
|
|
|
|
|
Actv_File = fopen(t3, "rb");
|
|
|
|
if (NULL == Actv_File) {
|
|
|
|
err = mnvm_fnfErr;
|
|
|
|
} else {
|
|
|
|
File_Size = fread(p, 1, ActvCodeFileLen, Actv_File);
|
|
|
|
if (File_Size != ActvCodeFileLen) {
|
|
|
|
if (feof(Actv_File)) {
|
|
|
|
err = mnvm_eofErr;
|
|
|
|
} else {
|
|
|
|
err = mnvm_miscErr;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
err = mnvm_noErr;
|
|
|
|
}
|
|
|
|
fclose(Actv_File);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
MayFree(t3);
|
|
|
|
MayFree(t2);
|
|
|
|
MayFree(t);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC tMacErr ActvCodeFileSave(uint8_t * p)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
tMacErr err;
|
|
|
|
char *s;
|
|
|
|
char *t = NULL;
|
|
|
|
char *t2 = NULL;
|
|
|
|
char *t3 = NULL;
|
|
|
|
|
|
|
|
if (mnvm_noErr == (err = FindUserHomeFolder(&s)))
|
|
|
|
if (mnvm_noErr == (err = FindOrMakeChild(s, ".gryphel", &t)))
|
|
|
|
if (mnvm_noErr == (err = FindOrMakeChild(t, "mnvm_act", &t2)))
|
|
|
|
if (mnvm_noErr == (err = ChildPath(t2, ActvCodeFileName, &t3)))
|
|
|
|
{
|
|
|
|
FILE *Actv_File;
|
|
|
|
int File_Size;
|
|
|
|
|
|
|
|
Actv_File = fopen(t3, "wb+");
|
|
|
|
if (NULL == Actv_File) {
|
|
|
|
err = mnvm_fnfErr;
|
|
|
|
} else {
|
|
|
|
File_Size = fwrite(p, 1, ActvCodeFileLen, Actv_File);
|
|
|
|
if (File_Size != ActvCodeFileLen) {
|
|
|
|
err = mnvm_miscErr;
|
|
|
|
} else {
|
|
|
|
err = mnvm_noErr;
|
|
|
|
}
|
|
|
|
fclose(Actv_File);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
MayFree(t3);
|
|
|
|
MayFree(t2);
|
|
|
|
MayFree(t);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* UseActvFile */
|
|
|
|
|
|
|
|
/* --- video out --- */
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR Window main_wind = 0;
|
|
|
|
LOCALVAR GC gc = NULL;
|
|
|
|
LOCALVAR bool NeedFinishOpen1 = false;
|
|
|
|
LOCALVAR bool NeedFinishOpen2 = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
LOCALVAR XColor x_black;
|
|
|
|
LOCALVAR XColor x_white;
|
|
|
|
|
|
|
|
#if MayFullScreen
|
|
|
|
LOCALVAR short hOffset;
|
|
|
|
LOCALVAR short vOffset;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if VarFullScreen
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool UseFullScreen = (WantInitFullScreen != 0);
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableMagnify
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool UseMagnify = (WantInitMagnify != 0);
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool gBackgroundFlag = false;
|
|
|
|
LOCALVAR bool gTrueBackgroundFlag = false;
|
|
|
|
LOCALVAR bool CurSpeedStopped = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#ifndef UseColorImage
|
|
|
|
#define UseColorImage (0 != vMacScreenDepth)
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR XImage *image = NULL;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#if EnableMagnify
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR XImage *Scaled_image = NULL;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableMagnify
|
2020-02-11 03:56:58 +00:00
|
|
|
#define MaxScale WindowScale
|
2019-07-23 02:50:34 +00:00
|
|
|
#else
|
|
|
|
#define MaxScale 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define WantScalingTabl (EnableMagnify || UseColorImage)
|
|
|
|
|
|
|
|
#if WantScalingTabl
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR uint8_t * ScalingTabl = nullpr;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#define ScalingTablsz1 (256 * MaxScale)
|
|
|
|
|
|
|
|
#if UseColorImage
|
|
|
|
#define ScalingTablsz (ScalingTablsz1 << 5)
|
|
|
|
#else
|
|
|
|
#define ScalingTablsz ScalingTablsz1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* WantScalingTabl */
|
|
|
|
|
|
|
|
|
|
|
|
#define WantScalingBuff (EnableMagnify || UseColorImage)
|
|
|
|
|
|
|
|
#if WantScalingBuff
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR uint8_t * ScalingBuff = nullpr;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
#if UseColorImage
|
|
|
|
#define ScalingBuffsz \
|
|
|
|
(vMacScreenNumPixels * 4 * MaxScale * MaxScale)
|
|
|
|
#else
|
|
|
|
#define ScalingBuffsz ((long)vMacScreenMonoNumBytes \
|
|
|
|
* MaxScale * MaxScale)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* WantScalingBuff */
|
|
|
|
|
|
|
|
|
|
|
|
#if EnableMagnify && ! UseColorImage
|
|
|
|
LOCALPROC SetUpScalingTabl(void)
|
|
|
|
{
|
2020-02-11 03:46:59 +00:00
|
|
|
uint8_t *p4;
|
2019-07-23 02:50:34 +00:00
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
int k;
|
2020-02-11 03:46:59 +00:00
|
|
|
uint8_t bitsRemaining;
|
|
|
|
uint8_t t1;
|
|
|
|
uint8_t t2;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
p4 = ScalingTabl;
|
|
|
|
for (i = 0; i < 256; ++i) {
|
|
|
|
bitsRemaining = 8;
|
|
|
|
t2 = 0;
|
|
|
|
for (j = 8; --j >= 0; ) {
|
|
|
|
t1 = (i >> j) & 1;
|
2020-02-11 03:56:58 +00:00
|
|
|
for (k = WindowScale; --k >= 0; ) {
|
2019-07-23 02:50:34 +00:00
|
|
|
t2 = (t2 << 1) | t1;
|
|
|
|
if (--bitsRemaining == 0) {
|
|
|
|
*p4++ = t2;
|
|
|
|
bitsRemaining = 8;
|
|
|
|
t2 = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableMagnify && (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
|
|
|
|
LOCALPROC SetUpColorScalingTabl(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
int k;
|
|
|
|
int a;
|
2020-02-11 03:46:59 +00:00
|
|
|
uint32_t v;
|
2020-02-11 05:34:32 +00:00
|
|
|
uint32_t * p4;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
p4 = (uint32_t *)ScalingTabl;
|
2019-07-23 02:50:34 +00:00
|
|
|
for (i = 0; i < 256; ++i) {
|
|
|
|
for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) {
|
|
|
|
j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1);
|
|
|
|
v = (((long)CLUT_reds[j] & 0xFF00) << 8)
|
|
|
|
| ((long)CLUT_greens[j] & 0xFF00)
|
|
|
|
| (((long)CLUT_blues[j] & 0xFF00) >> 8);
|
2020-02-11 03:56:58 +00:00
|
|
|
for (a = WindowScale; --a >= 0; ) {
|
2019-07-23 02:50:34 +00:00
|
|
|
*p4++ = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
|
|
|
|
LOCALPROC SetUpColorTabl(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int j;
|
|
|
|
int k;
|
2020-02-11 05:34:32 +00:00
|
|
|
uint32_t * p4;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
p4 = (uint32_t *)ScalingTabl;
|
2019-07-23 02:50:34 +00:00
|
|
|
for (i = 0; i < 256; ++i) {
|
|
|
|
for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) {
|
|
|
|
j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1);
|
|
|
|
*p4++ = (((long)CLUT_reds[j] & 0xFF00) << 8)
|
|
|
|
| ((long)CLUT_greens[j] & 0xFF00)
|
|
|
|
| (((long)CLUT_blues[j] & 0xFF00) >> 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableMagnify && UseColorImage
|
|
|
|
LOCALPROC SetUpBW2ColorScalingTabl(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int k;
|
|
|
|
int a;
|
2020-02-11 03:46:59 +00:00
|
|
|
uint32_t v;
|
2020-02-11 05:34:32 +00:00
|
|
|
uint32_t * p4;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
p4 = (uint32_t *)ScalingTabl;
|
2019-07-23 02:50:34 +00:00
|
|
|
for (i = 0; i < 256; ++i) {
|
|
|
|
for (k = 8; --k >= 0; ) {
|
|
|
|
if (0 != ((i >> k) & 1)) {
|
|
|
|
v = 0;
|
|
|
|
} else {
|
|
|
|
v = 0xFFFFFF;
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
for (a = WindowScale; --a >= 0; ) {
|
2019-07-23 02:50:34 +00:00
|
|
|
*p4++ = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if UseColorImage
|
|
|
|
LOCALPROC SetUpBW2ColorTabl(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int k;
|
2020-02-11 03:46:59 +00:00
|
|
|
uint32_t v;
|
2020-02-11 05:34:32 +00:00
|
|
|
uint32_t * p4;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
p4 = (uint32_t *)ScalingTabl;
|
2019-07-23 02:50:34 +00:00
|
|
|
for (i = 0; i < 256; ++i) {
|
|
|
|
for (k = 8; --k >= 0; ) {
|
|
|
|
if (0 != ((i >> k) & 1)) {
|
|
|
|
v = 0;
|
|
|
|
} else {
|
|
|
|
v = 0xFFFFFF;
|
|
|
|
}
|
|
|
|
*p4++ = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if EnableMagnify && ! UseColorImage
|
|
|
|
|
|
|
|
#define ScrnMapr_DoMap UpdateScaledBWCopy
|
|
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
|
|
#define ScrnMapr_SrcDepth 0
|
|
|
|
#define ScrnMapr_DstDepth 0
|
|
|
|
#define ScrnMapr_Map ScalingTabl
|
2020-02-11 03:56:58 +00:00
|
|
|
#define ScrnMapr_Scale WindowScale
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
|
|
|
|
|
|
|
|
#define ScrnMapr_DoMap UpdateMappedColorCopy
|
|
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
|
|
#define ScrnMapr_SrcDepth vMacScreenDepth
|
|
|
|
#define ScrnMapr_DstDepth 5
|
|
|
|
#define ScrnMapr_Map ScalingTabl
|
|
|
|
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if EnableMagnify && (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
|
|
|
|
|
|
|
|
#define ScrnMapr_DoMap UpdateMappedScaledColorCopy
|
|
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
|
|
#define ScrnMapr_SrcDepth vMacScreenDepth
|
|
|
|
#define ScrnMapr_DstDepth 5
|
|
|
|
#define ScrnMapr_Map ScalingTabl
|
2020-02-11 03:56:58 +00:00
|
|
|
#define ScrnMapr_Scale WindowScale
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if vMacScreenDepth >= 4
|
|
|
|
|
|
|
|
#define ScrnTrns_DoTrans UpdateTransColorCopy
|
|
|
|
#define ScrnTrns_Src GetCurDrawBuff()
|
|
|
|
#define ScrnTrns_Dst ScalingBuff
|
|
|
|
#define ScrnTrns_SrcDepth vMacScreenDepth
|
|
|
|
#define ScrnTrns_DstDepth 5
|
|
|
|
|
|
|
|
#include "SCRNTRNS.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableMagnify && (vMacScreenDepth >= 4)
|
|
|
|
|
|
|
|
#define ScrnTrns_DoTrans UpdateTransScaledColorCopy
|
|
|
|
#define ScrnTrns_Src GetCurDrawBuff()
|
|
|
|
#define ScrnTrns_Dst ScalingBuff
|
|
|
|
#define ScrnTrns_SrcDepth vMacScreenDepth
|
|
|
|
#define ScrnTrns_DstDepth 5
|
2020-02-11 03:56:58 +00:00
|
|
|
#define ScrnTrns_Scale WindowScale
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#include "SCRNTRNS.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if EnableMagnify && UseColorImage
|
|
|
|
|
|
|
|
#define ScrnMapr_DoMap UpdateMappedScaledBW2ColorCopy
|
|
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
|
|
#define ScrnMapr_SrcDepth 0
|
|
|
|
#define ScrnMapr_DstDepth 5
|
|
|
|
#define ScrnMapr_Map ScalingTabl
|
2020-02-11 03:56:58 +00:00
|
|
|
#define ScrnMapr_Scale WindowScale
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if UseColorImage
|
|
|
|
|
|
|
|
#define ScrnMapr_DoMap UpdateMappedBW2ColorCopy
|
|
|
|
#define ScrnMapr_Src GetCurDrawBuff()
|
|
|
|
#define ScrnMapr_Dst ScalingBuff
|
|
|
|
#define ScrnMapr_SrcDepth 0
|
|
|
|
#define ScrnMapr_DstDepth 5
|
|
|
|
#define ScrnMapr_Map ScalingTabl
|
|
|
|
|
|
|
|
#include "SCRNMAPR.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALPROC HaveChangedScreenBuff(uint16_t top, uint16_t left,
|
|
|
|
uint16_t bottom, uint16_t right)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
int XDest;
|
|
|
|
int YDest;
|
|
|
|
char *the_data;
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
if (top < ViewVStart) {
|
|
|
|
top = ViewVStart;
|
|
|
|
}
|
|
|
|
if (left < ViewHStart) {
|
|
|
|
left = ViewHStart;
|
|
|
|
}
|
|
|
|
if (bottom > ViewVStart + ViewVSize) {
|
|
|
|
bottom = ViewVStart + ViewVSize;
|
|
|
|
}
|
|
|
|
if (right > ViewHStart + ViewHSize) {
|
|
|
|
right = ViewHStart + ViewHSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((top >= bottom) || (left >= right)) {
|
|
|
|
goto label_exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
XDest = left;
|
|
|
|
YDest = top;
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
XDest -= ViewHStart;
|
|
|
|
YDest -= ViewVStart;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableMagnify
|
|
|
|
if (UseMagnify) {
|
2020-02-11 03:56:58 +00:00
|
|
|
XDest *= WindowScale;
|
|
|
|
YDest *= WindowScale;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
XDest += hOffset;
|
|
|
|
YDest += vOffset;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableMagnify
|
|
|
|
if (UseMagnify) {
|
|
|
|
#if UseColorImage
|
|
|
|
#if 0 != vMacScreenDepth
|
|
|
|
if (UseColorMode) {
|
|
|
|
#if vMacScreenDepth < 4
|
|
|
|
if (! ColorTransValid) {
|
|
|
|
SetUpColorScalingTabl();
|
2020-02-11 05:34:32 +00:00
|
|
|
ColorTransValid = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UpdateMappedScaledColorCopy(top, left, bottom, right);
|
|
|
|
#else
|
|
|
|
UpdateTransScaledColorCopy(top, left, bottom, right);
|
|
|
|
#endif
|
|
|
|
} else
|
|
|
|
#endif /* 0 != vMacScreenDepth */
|
|
|
|
{
|
|
|
|
if (! ColorTransValid) {
|
|
|
|
SetUpBW2ColorScalingTabl();
|
2020-02-11 05:34:32 +00:00
|
|
|
ColorTransValid = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UpdateMappedScaledBW2ColorCopy(top, left, bottom, right);
|
|
|
|
}
|
|
|
|
#else /* ! UseColorImage */
|
|
|
|
/* assume 0 == vMacScreenDepth */
|
|
|
|
{
|
|
|
|
if (! ColorTransValid) {
|
|
|
|
SetUpScalingTabl();
|
2020-02-11 05:34:32 +00:00
|
|
|
ColorTransValid = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UpdateScaledBWCopy(top, left, bottom, right);
|
|
|
|
}
|
|
|
|
#endif /* UseColorImage */
|
|
|
|
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
char *saveData = Scaled_image->data;
|
|
|
|
Scaled_image->data = (char *)ScalingBuff;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
XPutImage(x_display, main_wind, gc, Scaled_image,
|
2020-02-11 03:56:58 +00:00
|
|
|
left * WindowScale, top * WindowScale,
|
2019-07-23 02:50:34 +00:00
|
|
|
XDest, YDest,
|
2020-02-11 03:56:58 +00:00
|
|
|
(right - left) * WindowScale,
|
|
|
|
(bottom - top) * WindowScale);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
Scaled_image->data = saveData;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
} else
|
|
|
|
#endif /* EnableMagnify */
|
|
|
|
{
|
|
|
|
#if UseColorImage
|
|
|
|
#if 0 != vMacScreenDepth
|
|
|
|
if (UseColorMode) {
|
|
|
|
#if vMacScreenDepth < 4
|
|
|
|
|
|
|
|
if (! ColorTransValid) {
|
|
|
|
SetUpColorTabl();
|
2020-02-11 05:34:32 +00:00
|
|
|
ColorTransValid = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UpdateMappedColorCopy(top, left, bottom, right);
|
|
|
|
|
|
|
|
the_data = (char *)ScalingBuff;
|
|
|
|
#else
|
|
|
|
/*
|
|
|
|
if vMacScreenDepth == 5 and MSBFirst, could
|
|
|
|
copy directly with the_data = (char *)GetCurDrawBuff();
|
|
|
|
*/
|
|
|
|
UpdateTransColorCopy(top, left, bottom, right);
|
|
|
|
|
|
|
|
the_data = (char *)ScalingBuff;
|
|
|
|
#endif
|
|
|
|
} else
|
|
|
|
#endif /* 0 != vMacScreenDepth */
|
|
|
|
{
|
|
|
|
if (! ColorTransValid) {
|
|
|
|
SetUpBW2ColorTabl();
|
2020-02-11 05:34:32 +00:00
|
|
|
ColorTransValid = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
UpdateMappedBW2ColorCopy(top, left, bottom, right);
|
|
|
|
|
|
|
|
the_data = (char *)ScalingBuff;
|
|
|
|
}
|
|
|
|
#else /* ! UseColorImage */
|
|
|
|
{
|
|
|
|
the_data = (char *)GetCurDrawBuff();
|
|
|
|
}
|
|
|
|
#endif /* UseColorImage */
|
|
|
|
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
char *saveData = image->data;
|
|
|
|
image->data = the_data;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
XPutImage(x_display, main_wind, gc, image,
|
2019-07-23 02:50:34 +00:00
|
|
|
left, top, XDest, YDest,
|
|
|
|
right - left, bottom - top);
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
image->data = saveData;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if MayFullScreen
|
|
|
|
label_exit:
|
|
|
|
;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC DrawChangesAndClear(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
if (ScreenChangedBottom > ScreenChangedTop) {
|
|
|
|
HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
|
|
|
|
ScreenChangedBottom, ScreenChangedRight);
|
|
|
|
ScreenClearChanges();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- mouse --- */
|
|
|
|
|
|
|
|
/* cursor hiding */
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool HaveCursorHidden = false;
|
|
|
|
LOCALVAR bool WantCursorHidden = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
LOCALPROC ForceShowCursor(void)
|
|
|
|
{
|
|
|
|
if (HaveCursorHidden) {
|
2020-02-11 05:34:32 +00:00
|
|
|
HaveCursorHidden = false;
|
|
|
|
if (main_wind) {
|
|
|
|
XUndefineCursor(x_display, main_wind);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALVAR Cursor blankCursor = None;
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool CreateBlankCursor(Window rootwin)
|
2019-07-23 02:50:34 +00:00
|
|
|
/*
|
|
|
|
adapted from X11_CreateNullCursor in context.x11.c
|
|
|
|
in quakeforge 0.5.5, copyright Id Software, Inc.
|
|
|
|
Zephaniah E. Hull, and Jeff Teunissen.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
Pixmap cursormask;
|
|
|
|
XGCValues xgc;
|
|
|
|
GC gc;
|
2020-02-11 05:34:32 +00:00
|
|
|
bool IsOk = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
cursormask = XCreatePixmap(x_display, rootwin, 1, 1, 1);
|
|
|
|
if (None == cursormask) {
|
|
|
|
WriteExtraErr("XCreatePixmap failed.");
|
|
|
|
} else {
|
|
|
|
xgc.function = GXclear;
|
|
|
|
gc = XCreateGC(x_display, cursormask, GCFunction, &xgc);
|
|
|
|
if (None == gc) {
|
|
|
|
WriteExtraErr("XCreateGC failed.");
|
|
|
|
} else {
|
|
|
|
XFillRectangle(x_display, cursormask, gc, 0, 0, 1, 1);
|
|
|
|
XFreeGC(x_display, gc);
|
|
|
|
|
|
|
|
blankCursor = XCreatePixmapCursor(x_display, cursormask,
|
|
|
|
cursormask, &x_black, &x_white, 0, 0);
|
|
|
|
if (None == blankCursor) {
|
|
|
|
WriteExtraErr("XCreatePixmapCursor failed.");
|
|
|
|
} else {
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XFreePixmap(x_display, cursormask);
|
|
|
|
/*
|
|
|
|
assuming that XCreatePixmapCursor doesn't think it
|
|
|
|
owns the pixmaps passed to it. I've seen code that
|
|
|
|
assumes this, and other code that seems to assume
|
|
|
|
the opposite.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
return IsOk;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* cursor moving */
|
|
|
|
|
|
|
|
#if EnableMoveMouse
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool MoveMouse(int16_t h, int16_t v)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
int NewMousePosh;
|
|
|
|
int NewMousePosv;
|
|
|
|
int root_x_return;
|
|
|
|
int root_y_return;
|
|
|
|
Window root_return;
|
|
|
|
Window child_return;
|
|
|
|
unsigned int mask_return;
|
2020-02-11 05:34:32 +00:00
|
|
|
bool IsOk;
|
2019-07-23 02:50:34 +00:00
|
|
|
int attempts = 0;
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
h -= ViewHStart;
|
|
|
|
v -= ViewVStart;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableMagnify
|
|
|
|
if (UseMagnify) {
|
2020-02-11 03:56:58 +00:00
|
|
|
h *= WindowScale;
|
|
|
|
v *= WindowScale;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
h += hOffset;
|
|
|
|
v += vOffset;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
do {
|
2020-02-11 05:34:32 +00:00
|
|
|
XWarpPointer(x_display, None, main_wind, 0, 0, 0, 0, h, v);
|
|
|
|
XQueryPointer(x_display, main_wind,
|
2019-07-23 02:50:34 +00:00
|
|
|
&root_return, &child_return,
|
|
|
|
&root_x_return, &root_y_return,
|
|
|
|
&NewMousePosh, &NewMousePosv,
|
|
|
|
&mask_return);
|
|
|
|
IsOk = (h == NewMousePosh) && (v == NewMousePosv);
|
|
|
|
++attempts;
|
|
|
|
} while ((! IsOk) && (attempts < 10));
|
|
|
|
return IsOk;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableFSMouseMotion
|
|
|
|
LOCALPROC StartSaveMouseMotion(void)
|
|
|
|
{
|
|
|
|
if (! HaveMouseMotion) {
|
2020-02-11 03:56:58 +00:00
|
|
|
if (MoveMouse(ViewHStart + (ViewHSize / 2),
|
2019-07-23 02:50:34 +00:00
|
|
|
ViewVStart + (ViewVSize / 2)))
|
|
|
|
{
|
|
|
|
SavedMouseH = ViewHStart + (ViewHSize / 2);
|
|
|
|
SavedMouseV = ViewVStart + (ViewVSize / 2);
|
2020-02-11 05:34:32 +00:00
|
|
|
HaveMouseMotion = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableFSMouseMotion
|
|
|
|
LOCALPROC StopSaveMouseMotion(void)
|
|
|
|
{
|
|
|
|
if (HaveMouseMotion) {
|
2020-02-11 03:56:58 +00:00
|
|
|
(void) MoveMouse(CurMouseH, CurMouseV);
|
2020-02-11 05:34:32 +00:00
|
|
|
HaveMouseMotion = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* cursor state */
|
|
|
|
|
|
|
|
#if EnableFSMouseMotion
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC MouseConstrain(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 03:46:59 +00:00
|
|
|
int16_t shiftdh;
|
|
|
|
int16_t shiftdv;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
|
|
|
|
shiftdh = ViewHSize / 2;
|
|
|
|
} else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) {
|
|
|
|
shiftdh = - ViewHSize / 2;
|
|
|
|
} else {
|
|
|
|
shiftdh = 0;
|
|
|
|
}
|
|
|
|
if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
|
|
|
|
shiftdv = ViewVSize / 2;
|
|
|
|
} else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) {
|
|
|
|
shiftdv = - ViewVSize / 2;
|
|
|
|
} else {
|
|
|
|
shiftdv = 0;
|
|
|
|
}
|
|
|
|
if ((shiftdh != 0) || (shiftdv != 0)) {
|
|
|
|
SavedMouseH += shiftdh;
|
|
|
|
SavedMouseV += shiftdv;
|
2020-02-11 03:56:58 +00:00
|
|
|
if (! MoveMouse(SavedMouseH, SavedMouseV)) {
|
2020-02-11 05:34:32 +00:00
|
|
|
HaveMouseMotion = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
bool ShouldHaveCursorHidden = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
NewMousePosh -= hOffset;
|
|
|
|
NewMousePosv -= vOffset;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableMagnify
|
|
|
|
if (UseMagnify) {
|
2020-02-11 03:56:58 +00:00
|
|
|
NewMousePosh /= WindowScale;
|
|
|
|
NewMousePosv /= WindowScale;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
NewMousePosh += ViewHStart;
|
|
|
|
NewMousePosv += ViewVStart;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableFSMouseMotion
|
|
|
|
if (HaveMouseMotion) {
|
2020-02-11 03:56:58 +00:00
|
|
|
MousePositionSetDelta(NewMousePosh - SavedMouseH,
|
2019-07-23 02:50:34 +00:00
|
|
|
NewMousePosv - SavedMouseV);
|
|
|
|
SavedMouseH = NewMousePosh;
|
|
|
|
SavedMouseV = NewMousePosv;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
if (NewMousePosh < 0) {
|
|
|
|
NewMousePosh = 0;
|
2020-02-11 05:34:32 +00:00
|
|
|
ShouldHaveCursorHidden = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
} else if (NewMousePosh >= vMacScreenWidth) {
|
|
|
|
NewMousePosh = vMacScreenWidth - 1;
|
2020-02-11 05:34:32 +00:00
|
|
|
ShouldHaveCursorHidden = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
if (NewMousePosv < 0) {
|
|
|
|
NewMousePosv = 0;
|
2020-02-11 05:34:32 +00:00
|
|
|
ShouldHaveCursorHidden = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
} else if (NewMousePosv >= vMacScreenHeight) {
|
|
|
|
NewMousePosv = vMacScreenHeight - 1;
|
2020-02-11 05:34:32 +00:00
|
|
|
ShouldHaveCursorHidden = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
ShouldHaveCursorHidden = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* if (ShouldHaveCursorHidden || CurMouseButton) */
|
|
|
|
/*
|
|
|
|
for a game like arkanoid, would like mouse to still
|
|
|
|
move even when outside window in one direction
|
|
|
|
*/
|
2020-02-11 03:56:58 +00:00
|
|
|
MousePositionSet(NewMousePosh, NewMousePosv);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WantCursorHidden = ShouldHaveCursorHidden;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC CheckMouseState(void)
|
|
|
|
{
|
|
|
|
int NewMousePosh;
|
|
|
|
int NewMousePosv;
|
|
|
|
int root_x_return;
|
|
|
|
int root_y_return;
|
|
|
|
Window root_return;
|
|
|
|
Window child_return;
|
|
|
|
unsigned int mask_return;
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
XQueryPointer(x_display, main_wind,
|
2019-07-23 02:50:34 +00:00
|
|
|
&root_return, &child_return,
|
|
|
|
&root_x_return, &root_y_return,
|
|
|
|
&NewMousePosh, &NewMousePosv,
|
|
|
|
&mask_return);
|
|
|
|
MousePositionNotify(NewMousePosh, NewMousePosv);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- keyboard input --- */
|
|
|
|
|
|
|
|
LOCALVAR KeyCode TheCapsLockCode;
|
|
|
|
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALVAR uint8_t KC2MKC[256];
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALPROC KC2MKCAssignOne(KeySym ks, uint8_t key)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
KeyCode code = XKeysymToKeycode(x_display, ks);
|
|
|
|
if (code != NoSymbol) {
|
|
|
|
KC2MKC[code] = key;
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
fprintf(stderr, "%d %d %d\n", (int)ks, key, (int)code);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool KC2MKCInit(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 256; ++i) {
|
|
|
|
KC2MKC[i] = MKC_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0 /* find Keysym for a code */
|
|
|
|
for (i = 0; i < 64 * 1024; ++i) {
|
|
|
|
KeyCode code = XKeysymToKeycode(x_display, i);
|
|
|
|
if (115 == code) {
|
|
|
|
fprintf(stderr, "i %d\n", i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
start with redundant mappings, should get overwritten
|
|
|
|
by main mappings but define them just in case
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef XK_KP_Insert
|
|
|
|
KC2MKCAssignOne(XK_KP_Insert, MKC_KP0);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_KP_End
|
|
|
|
KC2MKCAssignOne(XK_KP_End, MKC_KP1);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_KP_Down
|
|
|
|
KC2MKCAssignOne(XK_KP_Down, MKC_KP2);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_KP_Next
|
|
|
|
KC2MKCAssignOne(XK_KP_Next, MKC_KP3);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_KP_Left
|
|
|
|
KC2MKCAssignOne(XK_KP_Left, MKC_KP4);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_KP_Begin
|
|
|
|
KC2MKCAssignOne(XK_KP_Begin, MKC_KP5);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_KP_Right
|
|
|
|
KC2MKCAssignOne(XK_KP_Right, MKC_KP6);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_KP_Home
|
|
|
|
KC2MKCAssignOne(XK_KP_Home, MKC_KP7);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_KP_Up
|
|
|
|
KC2MKCAssignOne(XK_KP_Up, MKC_KP8);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_KP_Prior
|
|
|
|
KC2MKCAssignOne(XK_KP_Prior, MKC_KP9);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_KP_Delete
|
|
|
|
KC2MKCAssignOne(XK_KP_Delete, MKC_Decimal);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_asciitilde, MKC_formac_Grave);
|
|
|
|
KC2MKCAssignOne(XK_underscore, MKC_Minus);
|
|
|
|
KC2MKCAssignOne(XK_plus, MKC_Equal);
|
|
|
|
KC2MKCAssignOne(XK_braceleft, MKC_LeftBracket);
|
|
|
|
KC2MKCAssignOne(XK_braceright, MKC_RightBracket);
|
|
|
|
KC2MKCAssignOne(XK_bar, MKC_formac_BackSlash);
|
|
|
|
KC2MKCAssignOne(XK_colon, MKC_SemiColon);
|
|
|
|
KC2MKCAssignOne(XK_quotedbl, MKC_SingleQuote);
|
|
|
|
KC2MKCAssignOne(XK_less, MKC_Comma);
|
|
|
|
KC2MKCAssignOne(XK_greater, MKC_Period);
|
|
|
|
KC2MKCAssignOne(XK_question, MKC_formac_Slash);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_a, MKC_A);
|
|
|
|
KC2MKCAssignOne(XK_b, MKC_B);
|
|
|
|
KC2MKCAssignOne(XK_c, MKC_C);
|
|
|
|
KC2MKCAssignOne(XK_d, MKC_D);
|
|
|
|
KC2MKCAssignOne(XK_e, MKC_E);
|
|
|
|
KC2MKCAssignOne(XK_f, MKC_F);
|
|
|
|
KC2MKCAssignOne(XK_g, MKC_G);
|
|
|
|
KC2MKCAssignOne(XK_h, MKC_H);
|
|
|
|
KC2MKCAssignOne(XK_i, MKC_I);
|
|
|
|
KC2MKCAssignOne(XK_j, MKC_J);
|
|
|
|
KC2MKCAssignOne(XK_k, MKC_K);
|
|
|
|
KC2MKCAssignOne(XK_l, MKC_L);
|
|
|
|
KC2MKCAssignOne(XK_m, MKC_M);
|
|
|
|
KC2MKCAssignOne(XK_n, MKC_N);
|
|
|
|
KC2MKCAssignOne(XK_o, MKC_O);
|
|
|
|
KC2MKCAssignOne(XK_p, MKC_P);
|
|
|
|
KC2MKCAssignOne(XK_q, MKC_Q);
|
|
|
|
KC2MKCAssignOne(XK_r, MKC_R);
|
|
|
|
KC2MKCAssignOne(XK_s, MKC_S);
|
|
|
|
KC2MKCAssignOne(XK_t, MKC_T);
|
|
|
|
KC2MKCAssignOne(XK_u, MKC_U);
|
|
|
|
KC2MKCAssignOne(XK_v, MKC_V);
|
|
|
|
KC2MKCAssignOne(XK_w, MKC_W);
|
|
|
|
KC2MKCAssignOne(XK_x, MKC_X);
|
|
|
|
KC2MKCAssignOne(XK_y, MKC_Y);
|
|
|
|
KC2MKCAssignOne(XK_z, MKC_Z);
|
|
|
|
|
|
|
|
/*
|
|
|
|
main mappings
|
|
|
|
*/
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_F1, MKC_formac_F1);
|
|
|
|
KC2MKCAssignOne(XK_F2, MKC_formac_F2);
|
|
|
|
KC2MKCAssignOne(XK_F3, MKC_formac_F3);
|
|
|
|
KC2MKCAssignOne(XK_F4, MKC_formac_F4);
|
|
|
|
KC2MKCAssignOne(XK_F5, MKC_formac_F5);
|
|
|
|
KC2MKCAssignOne(XK_F6, MKC_F6);
|
|
|
|
KC2MKCAssignOne(XK_F7, MKC_F7);
|
|
|
|
KC2MKCAssignOne(XK_F8, MKC_F8);
|
|
|
|
KC2MKCAssignOne(XK_F9, MKC_F9);
|
|
|
|
KC2MKCAssignOne(XK_F10, MKC_F10);
|
|
|
|
KC2MKCAssignOne(XK_F11, MKC_F11);
|
|
|
|
KC2MKCAssignOne(XK_F12, MKC_F12);
|
|
|
|
|
|
|
|
#ifdef XK_Delete
|
|
|
|
KC2MKCAssignOne(XK_Delete, MKC_formac_ForwardDel);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_Insert
|
|
|
|
KC2MKCAssignOne(XK_Insert, MKC_formac_Help);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_Help
|
|
|
|
KC2MKCAssignOne(XK_Help, MKC_formac_Help);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_Home
|
|
|
|
KC2MKCAssignOne(XK_Home, MKC_formac_Home);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_End
|
|
|
|
KC2MKCAssignOne(XK_End, MKC_formac_End);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef XK_Page_Up
|
|
|
|
KC2MKCAssignOne(XK_Page_Up, MKC_formac_PageUp);
|
|
|
|
#else
|
|
|
|
#ifdef XK_Prior
|
|
|
|
KC2MKCAssignOne(XK_Prior, MKC_formac_PageUp);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef XK_Page_Down
|
|
|
|
KC2MKCAssignOne(XK_Page_Down, MKC_formac_PageDown);
|
|
|
|
#else
|
|
|
|
#ifdef XK_Next
|
|
|
|
KC2MKCAssignOne(XK_Next, MKC_formac_PageDown);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef XK_Print
|
|
|
|
KC2MKCAssignOne(XK_Print, MKC_Print);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_Scroll_Lock
|
|
|
|
KC2MKCAssignOne(XK_Scroll_Lock, MKC_ScrollLock);
|
|
|
|
#endif
|
|
|
|
#ifdef XK_Pause
|
|
|
|
KC2MKCAssignOne(XK_Pause, MKC_Pause);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_KP_Add, MKC_KPAdd);
|
|
|
|
KC2MKCAssignOne(XK_KP_Subtract, MKC_KPSubtract);
|
|
|
|
KC2MKCAssignOne(XK_KP_Multiply, MKC_KPMultiply);
|
|
|
|
KC2MKCAssignOne(XK_KP_Divide, MKC_KPDevide);
|
|
|
|
KC2MKCAssignOne(XK_KP_Enter, MKC_formac_Enter);
|
|
|
|
KC2MKCAssignOne(XK_KP_Equal, MKC_KPEqual);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_KP_0, MKC_KP0);
|
|
|
|
KC2MKCAssignOne(XK_KP_1, MKC_KP1);
|
|
|
|
KC2MKCAssignOne(XK_KP_2, MKC_KP2);
|
|
|
|
KC2MKCAssignOne(XK_KP_3, MKC_KP3);
|
|
|
|
KC2MKCAssignOne(XK_KP_4, MKC_KP4);
|
|
|
|
KC2MKCAssignOne(XK_KP_5, MKC_KP5);
|
|
|
|
KC2MKCAssignOne(XK_KP_6, MKC_KP6);
|
|
|
|
KC2MKCAssignOne(XK_KP_7, MKC_KP7);
|
|
|
|
KC2MKCAssignOne(XK_KP_8, MKC_KP8);
|
|
|
|
KC2MKCAssignOne(XK_KP_9, MKC_KP9);
|
|
|
|
KC2MKCAssignOne(XK_KP_Decimal, MKC_Decimal);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Left, MKC_Left);
|
|
|
|
KC2MKCAssignOne(XK_Right, MKC_Right);
|
|
|
|
KC2MKCAssignOne(XK_Up, MKC_Up);
|
|
|
|
KC2MKCAssignOne(XK_Down, MKC_Down);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_grave, MKC_formac_Grave);
|
|
|
|
KC2MKCAssignOne(XK_minus, MKC_Minus);
|
|
|
|
KC2MKCAssignOne(XK_equal, MKC_Equal);
|
|
|
|
KC2MKCAssignOne(XK_bracketleft, MKC_LeftBracket);
|
|
|
|
KC2MKCAssignOne(XK_bracketright, MKC_RightBracket);
|
|
|
|
KC2MKCAssignOne(XK_backslash, MKC_formac_BackSlash);
|
|
|
|
KC2MKCAssignOne(XK_semicolon, MKC_SemiColon);
|
|
|
|
KC2MKCAssignOne(XK_apostrophe, MKC_SingleQuote);
|
|
|
|
KC2MKCAssignOne(XK_comma, MKC_Comma);
|
|
|
|
KC2MKCAssignOne(XK_period, MKC_Period);
|
|
|
|
KC2MKCAssignOne(XK_slash, MKC_formac_Slash);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Escape, MKC_formac_Escape);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Tab, MKC_Tab);
|
|
|
|
KC2MKCAssignOne(XK_Return, MKC_Return);
|
|
|
|
KC2MKCAssignOne(XK_space, MKC_Space);
|
|
|
|
KC2MKCAssignOne(XK_BackSpace, MKC_BackSpace);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Caps_Lock, MKC_formac_CapsLock);
|
|
|
|
KC2MKCAssignOne(XK_Num_Lock, MKC_Clear);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Meta_L, MKC_formac_Command);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Meta_R, MKC_formac_RCommand);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Mode_switch, MKC_formac_Option);
|
|
|
|
KC2MKCAssignOne(XK_Menu, MKC_formac_Option);
|
|
|
|
KC2MKCAssignOne(XK_Super_L, MKC_formac_Option);
|
|
|
|
KC2MKCAssignOne(XK_Super_R, MKC_formac_ROption);
|
|
|
|
KC2MKCAssignOne(XK_Hyper_L, MKC_formac_Option);
|
|
|
|
KC2MKCAssignOne(XK_Hyper_R, MKC_formac_ROption);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_F13, MKC_formac_Option);
|
|
|
|
/*
|
|
|
|
seen being used in Mandrake Linux 9.2
|
|
|
|
for windows key
|
|
|
|
*/
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Shift_L, MKC_formac_Shift);
|
|
|
|
KC2MKCAssignOne(XK_Shift_R, MKC_formac_RShift);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Alt_L, MKC_formac_Command);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Alt_R, MKC_formac_RCommand);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Control_L, MKC_formac_Control);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_Control_R, MKC_formac_RControl);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_1, MKC_1);
|
|
|
|
KC2MKCAssignOne(XK_2, MKC_2);
|
|
|
|
KC2MKCAssignOne(XK_3, MKC_3);
|
|
|
|
KC2MKCAssignOne(XK_4, MKC_4);
|
|
|
|
KC2MKCAssignOne(XK_5, MKC_5);
|
|
|
|
KC2MKCAssignOne(XK_6, MKC_6);
|
|
|
|
KC2MKCAssignOne(XK_7, MKC_7);
|
|
|
|
KC2MKCAssignOne(XK_8, MKC_8);
|
|
|
|
KC2MKCAssignOne(XK_9, MKC_9);
|
|
|
|
KC2MKCAssignOne(XK_0, MKC_0);
|
|
|
|
|
|
|
|
KC2MKCAssignOne(XK_A, MKC_A);
|
|
|
|
KC2MKCAssignOne(XK_B, MKC_B);
|
|
|
|
KC2MKCAssignOne(XK_C, MKC_C);
|
|
|
|
KC2MKCAssignOne(XK_D, MKC_D);
|
|
|
|
KC2MKCAssignOne(XK_E, MKC_E);
|
|
|
|
KC2MKCAssignOne(XK_F, MKC_F);
|
|
|
|
KC2MKCAssignOne(XK_G, MKC_G);
|
|
|
|
KC2MKCAssignOne(XK_H, MKC_H);
|
|
|
|
KC2MKCAssignOne(XK_I, MKC_I);
|
|
|
|
KC2MKCAssignOne(XK_J, MKC_J);
|
|
|
|
KC2MKCAssignOne(XK_K, MKC_K);
|
|
|
|
KC2MKCAssignOne(XK_L, MKC_L);
|
|
|
|
KC2MKCAssignOne(XK_M, MKC_M);
|
|
|
|
KC2MKCAssignOne(XK_N, MKC_N);
|
|
|
|
KC2MKCAssignOne(XK_O, MKC_O);
|
|
|
|
KC2MKCAssignOne(XK_P, MKC_P);
|
|
|
|
KC2MKCAssignOne(XK_Q, MKC_Q);
|
|
|
|
KC2MKCAssignOne(XK_R, MKC_R);
|
|
|
|
KC2MKCAssignOne(XK_S, MKC_S);
|
|
|
|
KC2MKCAssignOne(XK_T, MKC_T);
|
|
|
|
KC2MKCAssignOne(XK_U, MKC_U);
|
|
|
|
KC2MKCAssignOne(XK_V, MKC_V);
|
|
|
|
KC2MKCAssignOne(XK_W, MKC_W);
|
|
|
|
KC2MKCAssignOne(XK_X, MKC_X);
|
|
|
|
KC2MKCAssignOne(XK_Y, MKC_Y);
|
|
|
|
KC2MKCAssignOne(XK_Z, MKC_Z);
|
|
|
|
|
|
|
|
TheCapsLockCode = XKeysymToKeycode(x_display, XK_Caps_Lock);
|
|
|
|
|
|
|
|
InitKeyCodes();
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC CheckTheCapsLock(void)
|
|
|
|
{
|
|
|
|
int NewMousePosh;
|
|
|
|
int NewMousePosv;
|
|
|
|
int root_x_return;
|
|
|
|
int root_y_return;
|
|
|
|
Window root_return;
|
|
|
|
Window child_return;
|
|
|
|
unsigned int mask_return;
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
XQueryPointer(x_display, main_wind,
|
2019-07-23 02:50:34 +00:00
|
|
|
&root_return, &child_return,
|
|
|
|
&root_x_return, &root_y_return,
|
|
|
|
&NewMousePosh, &NewMousePosv,
|
|
|
|
&mask_return);
|
|
|
|
|
|
|
|
Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
|
|
|
|
(mask_return & LockMask) != 0);
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALPROC DoKeyCode0(int i, bool down)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 03:46:59 +00:00
|
|
|
uint8_t key = KC2MKC[i];
|
2019-07-23 02:50:34 +00:00
|
|
|
if (MKC_None != key) {
|
|
|
|
Keyboard_UpdateKeyMap2(key, down);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALPROC DoKeyCode(int i, bool down)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
if (i == TheCapsLockCode) {
|
|
|
|
CheckTheCapsLock();
|
|
|
|
} else if (i >= 0 && i < 256) {
|
|
|
|
DoKeyCode0(i, down);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if MayFullScreen && GrabKeysFullScreen
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool KeyboardIsGrabbed = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if MayFullScreen && GrabKeysFullScreen
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC GrabKeyboard(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
if (! KeyboardIsGrabbed) {
|
2020-02-11 05:34:32 +00:00
|
|
|
(void) XGrabKeyboard(x_display, main_wind,
|
2019-07-23 02:50:34 +00:00
|
|
|
False, GrabModeAsync, GrabModeAsync,
|
|
|
|
CurrentTime);
|
2020-02-11 05:34:32 +00:00
|
|
|
KeyboardIsGrabbed = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if MayFullScreen && GrabKeysFullScreen
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC UnGrabKeyboard(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
if (KeyboardIsGrabbed && main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
XUngrabKeyboard(x_display, CurrentTime);
|
2020-02-11 05:34:32 +00:00
|
|
|
KeyboardIsGrabbed = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool NoKeyRepeat = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
LOCALVAR int SaveKeyRepeat;
|
|
|
|
|
|
|
|
LOCALPROC DisableKeyRepeat(void)
|
|
|
|
{
|
|
|
|
XKeyboardState r;
|
|
|
|
XKeyboardControl k;
|
|
|
|
|
|
|
|
if ((! NoKeyRepeat) && (x_display != NULL)) {
|
2020-02-11 05:34:32 +00:00
|
|
|
NoKeyRepeat = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
XGetKeyboardControl(x_display, &r);
|
|
|
|
SaveKeyRepeat = r.global_auto_repeat;
|
|
|
|
|
|
|
|
k.auto_repeat_mode = AutoRepeatModeOff;
|
|
|
|
XChangeKeyboardControl(x_display, KBAutoRepeatMode, &k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC RestoreKeyRepeat(void)
|
|
|
|
{
|
|
|
|
XKeyboardControl k;
|
|
|
|
|
|
|
|
if (NoKeyRepeat && (x_display != NULL)) {
|
2020-02-11 05:34:32 +00:00
|
|
|
NoKeyRepeat = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
k.auto_repeat_mode = SaveKeyRepeat;
|
|
|
|
XChangeKeyboardControl(x_display, KBAutoRepeatMode, &k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool WantCmdOptOnReconnect = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
LOCALPROC GetTheDownKeys(void)
|
|
|
|
{
|
|
|
|
char keys_return[32];
|
|
|
|
int i;
|
|
|
|
int v;
|
|
|
|
int j;
|
|
|
|
|
|
|
|
XQueryKeymap(x_display, keys_return);
|
|
|
|
|
|
|
|
for (i = 0; i < 32; ++i) {
|
|
|
|
v = keys_return[i];
|
|
|
|
for (j = 0; j < 8; ++j) {
|
|
|
|
if (0 != ((1 << j) & v)) {
|
|
|
|
int k = i * 8 + j;
|
|
|
|
if (k != TheCapsLockCode) {
|
2020-02-11 05:34:32 +00:00
|
|
|
DoKeyCode0(k, true);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC ReconnectKeyCodes3(void)
|
|
|
|
{
|
|
|
|
CheckTheCapsLock();
|
|
|
|
|
|
|
|
if (WantCmdOptOnReconnect) {
|
2020-02-11 05:34:32 +00:00
|
|
|
WantCmdOptOnReconnect = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
GetTheDownKeys();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC DisconnectKeyCodes3(void)
|
|
|
|
{
|
|
|
|
DisconnectKeyCodes2();
|
2020-02-11 05:34:32 +00:00
|
|
|
MouseButtonSet(false);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --- time, date, location --- */
|
|
|
|
|
|
|
|
#define dbglog_TimeStuff (0 && dbglog_HAVE)
|
|
|
|
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALVAR uint32_t TrueEmulatedTime = 0;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#include "DATE2SEC.h"
|
|
|
|
|
|
|
|
#define TicksPerSecond 1000000
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool HaveTimeDelta = false;
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALVAR uint32_t TimeDelta;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALVAR uint32_t NewMacDateInSeconds;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALVAR uint32_t LastTimeSec;
|
|
|
|
LOCALVAR uint32_t LastTimeUsec;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
LOCALPROC GetCurrentTicks(void)
|
|
|
|
{
|
|
|
|
struct timeval t;
|
|
|
|
|
|
|
|
gettimeofday(&t, NULL);
|
|
|
|
if (! HaveTimeDelta) {
|
|
|
|
time_t Current_Time;
|
|
|
|
struct tm *s;
|
|
|
|
|
|
|
|
(void) time(&Current_Time);
|
|
|
|
s = localtime(&Current_Time);
|
|
|
|
TimeDelta = Date2MacSeconds(s->tm_sec, s->tm_min, s->tm_hour,
|
|
|
|
s->tm_mday, 1 + s->tm_mon, 1900 + s->tm_year) - t.tv_sec;
|
|
|
|
#if 0 && AutoTimeZone /* how portable is this ? */
|
2020-02-11 03:46:59 +00:00
|
|
|
CurMacDelta = ((uint32_t)(s->tm_gmtoff) & 0x00FFFFFF)
|
2019-07-23 02:50:34 +00:00
|
|
|
| ((s->tm_isdst ? 0x80 : 0) << 24);
|
|
|
|
#endif
|
2020-02-11 05:34:32 +00:00
|
|
|
HaveTimeDelta = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NewMacDateInSeconds = t.tv_sec + TimeDelta;
|
2020-02-11 03:46:59 +00:00
|
|
|
LastTimeSec = (uint32_t)t.tv_sec;
|
|
|
|
LastTimeUsec = (uint32_t)t.tv_usec;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
#define InvTimeStep 16626 /* TicksPerSecond / 60.14742 */
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALVAR uint32_t NextTimeSec;
|
|
|
|
LOCALVAR uint32_t NextTimeUsec;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
LOCALPROC IncrNextTime(void)
|
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
NextTimeUsec += InvTimeStep;
|
2019-07-23 02:50:34 +00:00
|
|
|
if (NextTimeUsec >= TicksPerSecond) {
|
|
|
|
NextTimeUsec -= TicksPerSecond;
|
|
|
|
NextTimeSec += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC InitNextTime(void)
|
|
|
|
{
|
|
|
|
NextTimeSec = LastTimeSec;
|
|
|
|
NextTimeUsec = LastTimeUsec;
|
|
|
|
IncrNextTime();
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC StartUpTimeAdjust(void)
|
|
|
|
{
|
|
|
|
GetCurrentTicks();
|
|
|
|
InitNextTime();
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALFUNC int32_t GetTimeDiff(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 03:46:59 +00:00
|
|
|
return ((int32_t)(LastTimeSec - NextTimeSec)) * TicksPerSecond
|
|
|
|
+ ((int32_t)(LastTimeUsec - NextTimeUsec));
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC UpdateTrueEmulatedTime(void)
|
|
|
|
{
|
2020-02-11 03:46:59 +00:00
|
|
|
int32_t TimeDiff;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
GetCurrentTicks();
|
|
|
|
|
|
|
|
TimeDiff = GetTimeDiff();
|
|
|
|
if (TimeDiff >= 0) {
|
2020-02-11 03:56:58 +00:00
|
|
|
if (TimeDiff > 16 * InvTimeStep) {
|
2019-07-23 02:50:34 +00:00
|
|
|
/* emulation interrupted, forget it */
|
|
|
|
++TrueEmulatedTime;
|
|
|
|
InitNextTime();
|
|
|
|
|
|
|
|
#if dbglog_TimeStuff
|
|
|
|
dbglog_writelnNum("emulation interrupted",
|
|
|
|
TrueEmulatedTime);
|
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
do {
|
|
|
|
++TrueEmulatedTime;
|
|
|
|
IncrNextTime();
|
|
|
|
TimeDiff -= TicksPerSecond;
|
|
|
|
} while (TimeDiff >= 0);
|
|
|
|
}
|
2020-02-11 03:56:58 +00:00
|
|
|
} else if (TimeDiff < - 16 * InvTimeStep) {
|
2019-07-23 02:50:34 +00:00
|
|
|
/* clock goofed if ever get here, reset */
|
|
|
|
#if dbglog_TimeStuff
|
|
|
|
dbglog_writeln("clock set back");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
InitNextTime();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool CheckDateTime(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
if (CurMacDateInSeconds != NewMacDateInSeconds) {
|
|
|
|
CurMacDateInSeconds = NewMacDateInSeconds;
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool InitLocationDat(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
GetCurrentTicks();
|
|
|
|
CurMacDateInSeconds = NewMacDateInSeconds;
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --- sound --- */
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
#if SoundEnabled
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
|
|
|
|
#define kSoundBuffers (1 << kLn2SoundBuffers)
|
|
|
|
#define kSoundBuffMask (kSoundBuffers - 1)
|
|
|
|
|
|
|
|
#define DesiredMinFilledSoundBuffs 3
|
|
|
|
/*
|
|
|
|
if too big then sound lags behind emulation.
|
|
|
|
if too small then sound will have pauses.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define kLnOneBuffLen 9
|
|
|
|
#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
|
|
|
|
#define kOneBuffLen (1UL << kLnOneBuffLen)
|
|
|
|
#define kAllBuffLen (1UL << kLnAllBuffLen)
|
|
|
|
#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
|
|
|
|
#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
|
|
|
|
#define kOneBuffSz (1UL << kLnOneBuffSz)
|
|
|
|
#define kAllBuffSz (1UL << kLnAllBuffSz)
|
|
|
|
#define kOneBuffMask (kOneBuffLen - 1)
|
|
|
|
#define kAllBuffMask (kAllBuffLen - 1)
|
|
|
|
#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
|
|
|
|
|
|
|
|
#define dbglog_SoundStuff (0 && dbglog_HAVE)
|
|
|
|
#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
|
|
|
|
|
|
|
|
LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALVAR uint16_t ThePlayOffset;
|
|
|
|
LOCALVAR uint16_t TheFillOffset;
|
|
|
|
LOCALVAR uint16_t TheWriteOffset;
|
|
|
|
LOCALVAR uint16_t MinFilledSoundBuffs;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC Sound_Start0(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
/* Reset variables */
|
|
|
|
ThePlayOffset = 0;
|
|
|
|
TheFillOffset = 0;
|
|
|
|
TheWriteOffset = 0;
|
|
|
|
MinFilledSoundBuffs = kSoundBuffers;
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
GLOBALOSGLUFUNC tpSoundSamp Sound_BeginWrite(uint16_t n, uint16_t *actL)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 03:46:59 +00:00
|
|
|
uint16_t ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
|
|
|
|
uint16_t WriteBuffContig =
|
2019-07-23 02:50:34 +00:00
|
|
|
kOneBuffLen - (TheWriteOffset & kOneBuffMask);
|
|
|
|
|
|
|
|
if (WriteBuffContig < n) {
|
|
|
|
n = WriteBuffContig;
|
|
|
|
}
|
|
|
|
if (ToFillLen < n) {
|
|
|
|
/* overwrite previous buffer */
|
|
|
|
#if dbglog_SoundStuff
|
|
|
|
dbglog_writeln("sound buffer over flow");
|
|
|
|
#endif
|
|
|
|
TheWriteOffset -= kOneBuffLen;
|
|
|
|
}
|
|
|
|
|
|
|
|
*actL = n;
|
|
|
|
return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool Sound_EndWrite0(uint16_t actL)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
bool v;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
TheWriteOffset += actL;
|
|
|
|
|
|
|
|
if (0 != (TheWriteOffset & kOneBuffMask)) {
|
2020-02-11 05:34:32 +00:00
|
|
|
v = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
|
|
|
/* just finished a block */
|
|
|
|
|
|
|
|
TheFillOffset = TheWriteOffset;
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
v = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC Sound_SecondNotify0(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
|
|
|
|
#if dbglog_SoundStuff
|
|
|
|
dbglog_writeln("MinFilledSoundBuffs too high");
|
|
|
|
#endif
|
|
|
|
IncrNextTime();
|
|
|
|
} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
|
|
|
|
#if dbglog_SoundStuff
|
|
|
|
dbglog_writeln("MinFilledSoundBuffs too low");
|
|
|
|
#endif
|
|
|
|
++TrueEmulatedTime;
|
|
|
|
}
|
|
|
|
MinFilledSoundBuffs = kSoundBuffers;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SOUND_SAMPLERATE 22255 /* = round(7833600 * 2 / 704) */
|
|
|
|
|
|
|
|
#include "SOUNDGLU.h"
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* --- basic dialogs --- */
|
|
|
|
|
|
|
|
LOCALPROC CheckSavedMacMsg(void)
|
|
|
|
{
|
|
|
|
/* called only on quit, if error saved but not yet reported */
|
|
|
|
|
|
|
|
if (nullpr != SavedBriefMsg) {
|
|
|
|
char briefMsg0[ClStrMaxLength + 1];
|
|
|
|
char longMsg0[ClStrMaxLength + 1];
|
|
|
|
|
|
|
|
NativeStrFromCStr(briefMsg0, SavedBriefMsg);
|
|
|
|
NativeStrFromCStr(longMsg0, SavedLongMsg);
|
|
|
|
|
|
|
|
fprintf(stderr, "%s\n", briefMsg0);
|
|
|
|
fprintf(stderr, "%s\n", longMsg0);
|
|
|
|
|
|
|
|
SavedBriefMsg = nullpr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- clipboard --- */
|
|
|
|
|
|
|
|
#if IncludeHostTextClipExchange
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR uint8_t * ClipBuffer = NULL;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludeHostTextClipExchange
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC FreeClipBuffer(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
if (ClipBuffer != NULL) {
|
|
|
|
free(ClipBuffer);
|
|
|
|
ClipBuffer = NULL;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludeHostTextClipExchange
|
|
|
|
GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
|
|
|
|
{
|
|
|
|
tMacErr err = mnvm_miscErr;
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
FreeClipBuffer();
|
2020-02-11 05:34:32 +00:00
|
|
|
if (MacRomanTextToNativePtr(i, false,
|
2020-02-11 03:56:58 +00:00
|
|
|
&ClipBuffer))
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
XSetSelectionOwner(x_display, XA_CLIPBOARD,
|
2020-02-11 05:34:32 +00:00
|
|
|
main_wind, CurrentTime);
|
2019-07-23 02:50:34 +00:00
|
|
|
err = mnvm_noErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
PbufDispose(i);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludeHostTextClipExchange
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool WaitForClipboardSelection(XEvent *xevent)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
struct timespec rqt;
|
|
|
|
struct timespec rmt;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 100; --i >= 0; ) {
|
2020-02-11 05:34:32 +00:00
|
|
|
while (XCheckTypedWindowEvent(x_display, main_wind,
|
2019-07-23 02:50:34 +00:00
|
|
|
SelectionNotify, xevent))
|
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
if (xevent->xselection.selection != XA_CLIPBOARD) {
|
2019-07-23 02:50:34 +00:00
|
|
|
/*
|
|
|
|
not what we were looking for. lose it.
|
|
|
|
(and hope it wasn't too important).
|
|
|
|
*/
|
|
|
|
WriteExtraErr("Discarding unwanted SelectionNotify");
|
|
|
|
} else {
|
|
|
|
/* this is our event */
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rqt.tv_sec = 0;
|
|
|
|
rqt.tv_nsec = 10000000;
|
|
|
|
(void) nanosleep(&rqt, &rmt);
|
|
|
|
}
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludeHostTextClipExchange
|
|
|
|
LOCALPROC HTCEimport_do(void)
|
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
Window w = XGetSelectionOwner(x_display, XA_CLIPBOARD);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
if (w == main_wind) {
|
2020-02-11 03:56:58 +00:00
|
|
|
/* We own the clipboard, already have ClipBuffer */
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
FreeClipBuffer();
|
2019-07-23 02:50:34 +00:00
|
|
|
if (w != None) {
|
|
|
|
XEvent xevent;
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
XDeleteProperty(x_display, main_wind,
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_MinivMac_Clip);
|
|
|
|
XConvertSelection(x_display, XA_CLIPBOARD, XA_STRING,
|
2020-02-11 05:34:32 +00:00
|
|
|
XA_MinivMac_Clip, main_wind, CurrentTime);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if (WaitForClipboardSelection(&xevent)) {
|
|
|
|
if (None == xevent.xselection.property) {
|
|
|
|
/* oops, target not supported */
|
|
|
|
} else {
|
|
|
|
if (xevent.xselection.property
|
2020-02-11 03:56:58 +00:00
|
|
|
!= XA_MinivMac_Clip)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
/* not where we expected it */
|
|
|
|
} else {
|
|
|
|
Atom ret_type;
|
|
|
|
int ret_format;
|
|
|
|
unsigned long ret_item;
|
|
|
|
unsigned long remain_byte;
|
|
|
|
unsigned char *s = NULL;
|
|
|
|
|
|
|
|
if ((Success != XGetWindowProperty(
|
2020-02-11 05:34:32 +00:00
|
|
|
x_display, main_wind, XA_MinivMac_Clip,
|
2019-07-23 02:50:34 +00:00
|
|
|
0, 65535, False, AnyPropertyType, &ret_type,
|
|
|
|
&ret_format, &ret_item, &remain_byte, &s))
|
|
|
|
|| (ret_type != XA_STRING)
|
|
|
|
|| (ret_format != 8)
|
|
|
|
|| (NULL == s))
|
|
|
|
{
|
|
|
|
WriteExtraErr(
|
|
|
|
"XGetWindowProperty failed"
|
|
|
|
" in HTCEimport_do");
|
|
|
|
} else {
|
2020-02-11 05:34:32 +00:00
|
|
|
ClipBuffer = (uint8_t *)malloc(ret_item + 1);
|
2020-02-11 03:56:58 +00:00
|
|
|
if (NULL == ClipBuffer) {
|
2019-07-23 02:50:34 +00:00
|
|
|
MacMsg(kStrOutOfMemTitle,
|
2020-02-11 05:34:32 +00:00
|
|
|
kStrOutOfMemMessage, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
MoveBytes((anyp)s, (anyp)ClipBuffer,
|
2019-07-23 02:50:34 +00:00
|
|
|
ret_item);
|
2020-02-11 03:56:58 +00:00
|
|
|
ClipBuffer[ret_item] = 0;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
XFree(s);
|
|
|
|
}
|
|
|
|
}
|
2020-02-11 05:34:32 +00:00
|
|
|
XDeleteProperty(x_display, main_wind,
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_MinivMac_Clip);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludeHostTextClipExchange
|
|
|
|
GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
|
|
|
|
{
|
|
|
|
HTCEimport_do();
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
return NativeTextToMacRomanPbuf((char *)ClipBuffer, r);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludeHostTextClipExchange
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool HandleSelectionRequestClipboard(XEvent *theEvent)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
bool RequestFilled = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
|
|
|
dbglog_writeln("Requested XA_CLIPBOARD");
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
if (NULL == ClipBuffer) {
|
2019-07-23 02:50:34 +00:00
|
|
|
/* our clipboard is empty */
|
2020-02-11 03:56:58 +00:00
|
|
|
} else if (theEvent->xselectionrequest.target == XA_TARGETS) {
|
2019-07-23 02:50:34 +00:00
|
|
|
Atom a[2];
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
a[0] = XA_TARGETS;
|
2019-07-23 02:50:34 +00:00
|
|
|
a[1] = XA_STRING;
|
|
|
|
|
|
|
|
XChangeProperty(x_display,
|
|
|
|
theEvent->xselectionrequest.requestor,
|
|
|
|
theEvent->xselectionrequest.property,
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_TARGETS,
|
2019-07-23 02:50:34 +00:00
|
|
|
32,
|
|
|
|
/*
|
|
|
|
most, but not all, other programs I've
|
|
|
|
look at seem to use 8 here, but that
|
|
|
|
can't be right. can it?
|
|
|
|
*/
|
|
|
|
PropModeReplace,
|
|
|
|
(unsigned char *)a,
|
|
|
|
sizeof(a) / sizeof(Atom));
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
RequestFilled = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
} else if (theEvent->xselectionrequest.target == XA_STRING) {
|
|
|
|
XChangeProperty(x_display,
|
|
|
|
theEvent->xselectionrequest.requestor,
|
|
|
|
theEvent->xselectionrequest.property,
|
|
|
|
XA_STRING,
|
|
|
|
8,
|
|
|
|
PropModeReplace,
|
2020-02-11 03:56:58 +00:00
|
|
|
(unsigned char *)ClipBuffer,
|
|
|
|
strlen((char *)ClipBuffer));
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
RequestFilled = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return RequestFilled;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* --- drag and drop --- */
|
|
|
|
|
|
|
|
#if EnableDragDrop
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC ActivateWind(Time time)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
if (NetSupportedContains(XA_NetActiveWindow)) {
|
2019-07-23 02:50:34 +00:00
|
|
|
XEvent xevent;
|
|
|
|
Window rootwin = XRootWindow(x_display,
|
|
|
|
DefaultScreen(x_display));
|
|
|
|
|
|
|
|
memset(&xevent, 0, sizeof (xevent));
|
|
|
|
|
|
|
|
xevent.xany.type = ClientMessage;
|
|
|
|
xevent.xclient.send_event = True;
|
2020-02-11 05:34:32 +00:00
|
|
|
xevent.xclient.window = main_wind;
|
2020-02-11 03:56:58 +00:00
|
|
|
xevent.xclient.message_type = XA_NetActiveWindow;
|
2019-07-23 02:50:34 +00:00
|
|
|
xevent.xclient.format = 32;
|
|
|
|
xevent.xclient.data.l[0] = 1;
|
|
|
|
xevent.xclient.data.l[1]= time;
|
|
|
|
|
|
|
|
if (0 == XSendEvent(x_display, rootwin, 0,
|
|
|
|
SubstructureRedirectMask | SubstructureNotifyMask,
|
|
|
|
&xevent))
|
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
WriteExtraErr("XSendEvent failed in ActivateWind");
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
XRaiseWindow(x_display, main_wind);
|
2019-07-23 02:50:34 +00:00
|
|
|
/*
|
|
|
|
In RedHat 7.1, _NET_ACTIVE_WINDOW supported,
|
|
|
|
but XSendEvent of _NET_ACTIVE_WINDOW
|
|
|
|
doesn't raise the window. So just always
|
|
|
|
call XRaiseWindow. Hopefully calling
|
|
|
|
XRaiseWindow won't do any harm on window
|
|
|
|
managers where it isn't needed.
|
|
|
|
(Such as in Ubuntu 5.10)
|
|
|
|
*/
|
2020-02-11 05:34:32 +00:00
|
|
|
XSetInputFocus(x_display, main_wind,
|
2019-07-23 02:50:34 +00:00
|
|
|
RevertToPointerRoot, time);
|
|
|
|
/* And call this always too, just in case */
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableDragDrop
|
|
|
|
LOCALPROC ParseOneUri(char *s)
|
|
|
|
{
|
|
|
|
/* printf("ParseOneUri %s\n", s); */
|
|
|
|
if (('f' == s[0]) && ('i' == s[1]) && ('l' == s[2])
|
|
|
|
&& ('e' == s[3]) && (':' == s[4]))
|
|
|
|
{
|
|
|
|
s += 5;
|
|
|
|
if (('/' == s[0]) && ('/' == s[1])) {
|
|
|
|
/* skip hostname */
|
|
|
|
char c;
|
|
|
|
|
|
|
|
s += 2;
|
|
|
|
while ((c = *s) != '/') {
|
|
|
|
if (0 == c) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
++s;
|
|
|
|
}
|
|
|
|
}
|
2020-02-11 05:34:32 +00:00
|
|
|
(void) Sony_Insert1a(s, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableDragDrop
|
|
|
|
LOCALFUNC int HexChar2Nib(char x)
|
|
|
|
{
|
|
|
|
if ((x >= '0') && (x <= '9')) {
|
|
|
|
return x - '0';
|
|
|
|
} else if ((x >= 'A') && (x <= 'F')) {
|
|
|
|
return x - 'A' + 10;
|
|
|
|
} else if ((x >= 'a') && (x <= 'f')) {
|
|
|
|
return x - 'a' + 10;
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableDragDrop
|
|
|
|
LOCALPROC ParseUriList(char *s)
|
|
|
|
{
|
|
|
|
char *p1 = s;
|
|
|
|
char *p0 = s;
|
|
|
|
char *p = s;
|
|
|
|
char c;
|
|
|
|
|
|
|
|
/* printf("ParseUriList %s\n", s); */
|
|
|
|
while ((c = *p++) != 0) {
|
|
|
|
if ('%' == c) {
|
|
|
|
int a;
|
|
|
|
int b;
|
|
|
|
|
|
|
|
if (((a = HexChar2Nib(p[0])) >= 0) &&
|
|
|
|
((b = HexChar2Nib(p[1])) >= 0))
|
|
|
|
{
|
|
|
|
p += 2;
|
|
|
|
*p1++ = (a << 4) + b;
|
|
|
|
} else {
|
|
|
|
*p1++ = c;
|
|
|
|
}
|
|
|
|
} else if (('\n' == c) || ('\r' == c)) {
|
|
|
|
*p1++ = 0;
|
|
|
|
ParseOneUri(p0);
|
|
|
|
p0 = p1;
|
|
|
|
} else {
|
|
|
|
*p1++ = c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*p1++ = 0;
|
|
|
|
ParseOneUri(p0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableDragDrop
|
|
|
|
LOCALVAR Window PendingDragWindow = None;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableDragDrop
|
|
|
|
LOCALPROC HandleSelectionNotifyDnd(XEvent *theEvent)
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
bool DropOk = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
|
|
|
dbglog_writeln("Got XA_DndSelection");
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
if ((theEvent->xselection.property == XA_MinivMac_DndXchng)
|
|
|
|
&& (theEvent->xselection.target == XA_UriList))
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
Atom ret_type;
|
|
|
|
int ret_format;
|
|
|
|
unsigned long ret_item;
|
|
|
|
unsigned long remain_byte;
|
|
|
|
unsigned char *s = NULL;
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
if ((Success != XGetWindowProperty(x_display, main_wind,
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_MinivMac_DndXchng,
|
|
|
|
0, 65535, False, XA_UriList, &ret_type, &ret_format,
|
2019-07-23 02:50:34 +00:00
|
|
|
&ret_item, &remain_byte, &s))
|
|
|
|
|| (NULL == s))
|
|
|
|
{
|
|
|
|
WriteExtraErr(
|
|
|
|
"XGetWindowProperty failed in SelectionNotify");
|
|
|
|
} else {
|
|
|
|
ParseUriList((char *)s);
|
2020-02-11 05:34:32 +00:00
|
|
|
DropOk = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
XFree(s);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
WriteExtraErr("Got Unknown SelectionNotify");
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
XDeleteProperty(x_display, main_wind,
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_MinivMac_DndXchng);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if (PendingDragWindow != None) {
|
|
|
|
XEvent xevent;
|
|
|
|
|
|
|
|
memset(&xevent, 0, sizeof(xevent));
|
|
|
|
|
|
|
|
xevent.xany.type = ClientMessage;
|
|
|
|
xevent.xany.display = x_display;
|
|
|
|
xevent.xclient.window = PendingDragWindow;
|
2020-02-11 03:56:58 +00:00
|
|
|
xevent.xclient.message_type = XA_DndFinished;
|
2019-07-23 02:50:34 +00:00
|
|
|
xevent.xclient.format = 32;
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
xevent.xclient.data.l[0] = main_wind;
|
2019-07-23 02:50:34 +00:00
|
|
|
if (DropOk) {
|
|
|
|
xevent.xclient.data.l[1] = 1;
|
|
|
|
}
|
2020-02-11 03:56:58 +00:00
|
|
|
xevent.xclient.data.l[2] = XA_DndActionPrivate;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if (0 == XSendEvent(x_display,
|
|
|
|
PendingDragWindow, 0, 0, &xevent))
|
|
|
|
{
|
|
|
|
WriteExtraErr("XSendEvent failed in SelectionNotify");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (DropOk && gTrueBackgroundFlag) {
|
2020-02-11 03:56:58 +00:00
|
|
|
ActivateWind(theEvent->xselection.time);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
WantCmdOptOnReconnect = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableDragDrop
|
|
|
|
LOCALPROC HandleClientMessageDndPosition(XEvent *theEvent)
|
|
|
|
{
|
|
|
|
XEvent xevent;
|
|
|
|
int xr;
|
|
|
|
int yr;
|
|
|
|
unsigned int dr;
|
|
|
|
unsigned int wr;
|
|
|
|
unsigned int hr;
|
|
|
|
unsigned int bwr;
|
|
|
|
Window rr;
|
|
|
|
Window srcwin = theEvent->xclient.data.l[0];
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("Got XdndPosition");
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
XGetGeometry(x_display, main_wind,
|
2019-07-23 02:50:34 +00:00
|
|
|
&rr, &xr, &yr, &wr, &hr, &bwr, &dr);
|
|
|
|
memset (&xevent, 0, sizeof(xevent));
|
|
|
|
xevent.xany.type = ClientMessage;
|
|
|
|
xevent.xany.display = x_display;
|
|
|
|
xevent.xclient.window = srcwin;
|
2020-02-11 03:56:58 +00:00
|
|
|
xevent.xclient.message_type = XA_DndStatus;
|
2019-07-23 02:50:34 +00:00
|
|
|
xevent.xclient.format = 32;
|
|
|
|
|
|
|
|
xevent.xclient.data.l[0] = theEvent->xclient.window;
|
|
|
|
/* Target Window */
|
|
|
|
xevent.xclient.data.l[1] = 1; /* Accept */
|
|
|
|
xevent.xclient.data.l[2] = ((xr) << 16) | ((yr) & 0xFFFFUL);
|
|
|
|
xevent.xclient.data.l[3] = ((wr) << 16) | ((hr) & 0xFFFFUL);
|
2020-02-11 03:56:58 +00:00
|
|
|
xevent.xclient.data.l[4] = XA_DndActionPrivate; /* Action */
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if (0 == XSendEvent(x_display, srcwin, 0, 0, &xevent)) {
|
|
|
|
WriteExtraErr(
|
|
|
|
"XSendEvent failed in HandleClientMessageDndPosition");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableDragDrop
|
|
|
|
LOCALPROC HandleClientMessageDndDrop(XEvent *theEvent)
|
|
|
|
{
|
|
|
|
Time timestamp = theEvent->xclient.data.l[2];
|
|
|
|
PendingDragWindow = (Window) theEvent->xclient.data.l[0];
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("Got XdndDrop");
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
XConvertSelection(x_display, XA_DndSelection, XA_UriList,
|
2020-02-11 05:34:32 +00:00
|
|
|
XA_MinivMac_DndXchng, main_wind, timestamp);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define UseMotionEvents 1
|
|
|
|
|
|
|
|
#if UseMotionEvents
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool CaughtMouse = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if MayNotFullScreen
|
|
|
|
LOCALVAR int SavedTransH;
|
|
|
|
LOCALVAR int SavedTransV;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* --- event handling for main window --- */
|
|
|
|
|
|
|
|
LOCALPROC HandleTheEvent(XEvent *theEvent)
|
|
|
|
{
|
|
|
|
if (theEvent->xany.display != x_display) {
|
|
|
|
WriteExtraErr("Got event for some other display");
|
|
|
|
} else switch(theEvent->type) {
|
|
|
|
case KeyPress:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xkey.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr("Got KeyPress for some other window");
|
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("- event - KeyPress");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
MousePositionNotify(theEvent->xkey.x, theEvent->xkey.y);
|
2020-02-11 05:34:32 +00:00
|
|
|
DoKeyCode(theEvent->xkey.keycode, true);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case KeyRelease:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xkey.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr("Got KeyRelease for some other window");
|
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("- event - KeyRelease");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
MousePositionNotify(theEvent->xkey.x, theEvent->xkey.y);
|
2020-02-11 05:34:32 +00:00
|
|
|
DoKeyCode(theEvent->xkey.keycode, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ButtonPress:
|
|
|
|
/* any mouse button, we don't care which */
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xbutton.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr("Got ButtonPress for some other window");
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
could check some modifiers, but don't bother for now
|
|
|
|
Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
|
|
|
|
(theEvent->xbutton.state & LockMask) != 0);
|
|
|
|
*/
|
|
|
|
MousePositionNotify(
|
|
|
|
theEvent->xbutton.x, theEvent->xbutton.y);
|
2020-02-11 05:34:32 +00:00
|
|
|
MouseButtonSet(true);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ButtonRelease:
|
|
|
|
/* any mouse button, we don't care which */
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xbutton.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr(
|
|
|
|
"Got ButtonRelease for some other window");
|
|
|
|
} else {
|
|
|
|
MousePositionNotify(
|
|
|
|
theEvent->xbutton.x, theEvent->xbutton.y);
|
2020-02-11 05:34:32 +00:00
|
|
|
MouseButtonSet(false);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#if UseMotionEvents
|
|
|
|
case MotionNotify:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xmotion.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr("Got MotionNotify for some other window");
|
|
|
|
} else {
|
|
|
|
MousePositionNotify(
|
|
|
|
theEvent->xmotion.x, theEvent->xmotion.y);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EnterNotify:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xcrossing.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr("Got EnterNotify for some other window");
|
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("- event - EnterNotify");
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
CaughtMouse = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
MousePositionNotify(
|
|
|
|
theEvent->xcrossing.x, theEvent->xcrossing.y);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case LeaveNotify:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xcrossing.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr("Got LeaveNotify for some other window");
|
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("- event - LeaveNotify");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
MousePositionNotify(
|
|
|
|
theEvent->xcrossing.x, theEvent->xcrossing.y);
|
2020-02-11 05:34:32 +00:00
|
|
|
CaughtMouse = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case Expose:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xexpose.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr(
|
|
|
|
"Got SelectionRequest for some other window");
|
|
|
|
} else {
|
|
|
|
int x0 = theEvent->xexpose.x;
|
|
|
|
int y0 = theEvent->xexpose.y;
|
|
|
|
int x1 = x0 + theEvent->xexpose.width;
|
|
|
|
int y1 = y0 + theEvent->xexpose.height;
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
#if 0 && DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("- event - Expose");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
x0 -= hOffset;
|
|
|
|
y0 -= vOffset;
|
|
|
|
x1 -= hOffset;
|
|
|
|
y1 -= vOffset;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableMagnify
|
|
|
|
if (UseMagnify) {
|
2020-02-11 03:56:58 +00:00
|
|
|
x0 /= WindowScale;
|
|
|
|
y0 /= WindowScale;
|
|
|
|
x1 = (x1 + (WindowScale - 1)) / WindowScale;
|
|
|
|
y1 = (y1 + (WindowScale - 1)) / WindowScale;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
x0 += ViewHStart;
|
|
|
|
y0 += ViewVStart;
|
|
|
|
x1 += ViewHStart;
|
|
|
|
y1 += ViewVStart;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (x0 < 0) {
|
|
|
|
x0 = 0;
|
|
|
|
}
|
|
|
|
if (x1 > vMacScreenWidth) {
|
|
|
|
x1 = vMacScreenWidth;
|
|
|
|
}
|
|
|
|
if (y0 < 0) {
|
|
|
|
y0 = 0;
|
|
|
|
}
|
|
|
|
if (y1 > vMacScreenHeight) {
|
|
|
|
y1 = vMacScreenHeight;
|
|
|
|
}
|
|
|
|
if ((x0 < x1) && (y0 < y1)) {
|
|
|
|
HaveChangedScreenBuff(y0, x0, y1, x1);
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
NeedFinishOpen1 = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
#if IncludeHostTextClipExchange
|
|
|
|
case SelectionRequest:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xselectionrequest.owner != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr(
|
|
|
|
"Got SelectionRequest for some other window");
|
|
|
|
} else {
|
|
|
|
XEvent xevent;
|
2020-02-11 05:34:32 +00:00
|
|
|
bool RequestFilled = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("- event - SelectionRequest");
|
|
|
|
WriteDbgAtom("selection",
|
|
|
|
theEvent->xselectionrequest.selection);
|
|
|
|
WriteDbgAtom("target",
|
|
|
|
theEvent->xselectionrequest.target);
|
|
|
|
WriteDbgAtom("property",
|
|
|
|
theEvent->xselectionrequest.property);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (theEvent->xselectionrequest.selection ==
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_CLIPBOARD)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
RequestFilled =
|
|
|
|
HandleSelectionRequestClipboard(theEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
memset(&xevent, 0, sizeof(xevent));
|
|
|
|
xevent.xselection.type = SelectionNotify;
|
|
|
|
xevent.xselection.display = x_display;
|
|
|
|
xevent.xselection.requestor =
|
|
|
|
theEvent->xselectionrequest.requestor;
|
|
|
|
xevent.xselection.selection =
|
|
|
|
theEvent->xselectionrequest.selection;
|
|
|
|
xevent.xselection.target =
|
|
|
|
theEvent->xselectionrequest.target;
|
|
|
|
xevent.xselection.property = (! RequestFilled) ? None
|
|
|
|
: theEvent->xselectionrequest.property ;
|
|
|
|
xevent.xselection.time =
|
|
|
|
theEvent->xselectionrequest.time;
|
|
|
|
|
|
|
|
if (0 == XSendEvent(x_display,
|
|
|
|
xevent.xselection.requestor, False, 0, &xevent))
|
|
|
|
{
|
|
|
|
WriteExtraErr(
|
|
|
|
"XSendEvent failed in SelectionRequest");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SelectionClear:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xselectionclear.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr(
|
|
|
|
"Got SelectionClear for some other window");
|
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("- event - SelectionClear");
|
|
|
|
WriteDbgAtom("selection",
|
|
|
|
theEvent->xselectionclear.selection);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (theEvent->xselectionclear.selection ==
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_CLIPBOARD)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
FreeClipBuffer();
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#if EnableDragDrop
|
|
|
|
case SelectionNotify:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xselection.requestor != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr(
|
|
|
|
"Got SelectionNotify for some other window");
|
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("- event - SelectionNotify");
|
|
|
|
WriteDbgAtom("selection",
|
|
|
|
theEvent->xselection.selection);
|
|
|
|
WriteDbgAtom("target", theEvent->xselection.target);
|
|
|
|
WriteDbgAtom("property", theEvent->xselection.property);
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
if (theEvent->xselection.selection == XA_DndSelection)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
HandleSelectionNotifyDnd(theEvent);
|
|
|
|
} else {
|
|
|
|
WriteExtraErr(
|
|
|
|
"Got Unknown selection in SelectionNotify");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case ClientMessage:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xclient.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr(
|
|
|
|
"Got ClientMessage for some other window");
|
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("- event - ClientMessage");
|
|
|
|
WriteDbgAtom("message_type",
|
|
|
|
theEvent->xclient.message_type);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableDragDrop
|
2020-02-11 03:56:58 +00:00
|
|
|
if (theEvent->xclient.message_type == XA_DndEnter) {
|
2019-07-23 02:50:34 +00:00
|
|
|
/* printf("Got XdndEnter\n"); */
|
|
|
|
} else if (theEvent->xclient.message_type ==
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_DndLeave)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
/* printf("Got XdndLeave\n"); */
|
|
|
|
} else if (theEvent->xclient.message_type ==
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_DndPosition)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
HandleClientMessageDndPosition(theEvent);
|
|
|
|
} else if (theEvent->xclient.message_type ==
|
2020-02-11 03:56:58 +00:00
|
|
|
XA_DndDrop)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
HandleClientMessageDndDrop(theEvent);
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
if ((32 == theEvent->xclient.format) &&
|
2020-02-11 03:56:58 +00:00
|
|
|
(theEvent->xclient.data.l[0] == XA_DeleteW))
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
I would think that should test that
|
|
|
|
WM_PROTOCOLS == message_type
|
|
|
|
but none of the other programs I looked
|
|
|
|
at did.
|
|
|
|
*/
|
2020-02-11 05:34:32 +00:00
|
|
|
RequestMacOff = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FocusIn:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xfocus.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr("Got FocusIn for some other window");
|
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("- event - FocusIn");
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
gTrueBackgroundFlag = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
#if UseMotionEvents
|
|
|
|
CheckMouseState();
|
|
|
|
/*
|
|
|
|
Doesn't help on x11 for OS X,
|
|
|
|
can't get new mouse position
|
|
|
|
in any fashion until mouse moves.
|
|
|
|
*/
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FocusOut:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (theEvent->xfocus.window != main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr("Got FocusOut for some other window");
|
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
#if DbgEvents
|
2019-07-23 02:50:34 +00:00
|
|
|
dbglog_writeln("- event - FocusOut");
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
gTrueBackgroundFlag = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- main window creation and disposal --- */
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR int argc;
|
|
|
|
LOCALVAR char **argv;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
LOCALVAR char *display_name = NULL;
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool Screen_Init(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
Window rootwin;
|
|
|
|
int screen;
|
|
|
|
Colormap Xcmap;
|
|
|
|
Visual *Xvisual;
|
|
|
|
|
|
|
|
x_display = XOpenDisplay(display_name);
|
|
|
|
if (NULL == x_display) {
|
|
|
|
fprintf(stderr, "Cannot connect to X server.\n");
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
screen = DefaultScreen(x_display);
|
|
|
|
|
|
|
|
rootwin = XRootWindow(x_display, screen);
|
|
|
|
|
|
|
|
Xcmap = DefaultColormap(x_display, screen);
|
|
|
|
|
|
|
|
Xvisual = DefaultVisual(x_display, screen);
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
LoadXA();
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
XParseColor(x_display, Xcmap, "#000000", &x_black);
|
|
|
|
if (! XAllocColor(x_display, Xcmap, &x_black)) {
|
|
|
|
WriteExtraErr("XParseColor black fails");
|
|
|
|
}
|
|
|
|
XParseColor(x_display, Xcmap, "#ffffff", &x_white);
|
|
|
|
if (! XAllocColor(x_display, Xcmap, &x_white)) {
|
|
|
|
WriteExtraErr("XParseColor white fails");
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
if (! CreateBlankCursor(rootwin)) {
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if ! UseColorImage
|
2020-02-11 05:34:32 +00:00
|
|
|
image = XCreateImage(x_display, Xvisual, 1, XYBitmap, 0,
|
2019-07-23 02:50:34 +00:00
|
|
|
NULL /* (char *)image_Mem1 */,
|
|
|
|
vMacScreenWidth, vMacScreenHeight, 32,
|
|
|
|
vMacScreenMonoByteWidth);
|
2020-02-11 05:34:32 +00:00
|
|
|
if (NULL == image) {
|
2019-07-23 02:50:34 +00:00
|
|
|
fprintf(stderr, "XCreateImage failed.\n");
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
fprintf(stderr, "bitmap_bit_order = %d\n",
|
2020-02-11 05:34:32 +00:00
|
|
|
(int)image->bitmap_bit_order);
|
|
|
|
fprintf(stderr, "byte_order = %d\n", (int)image->byte_order);
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
image->bitmap_bit_order = MSBFirst;
|
|
|
|
image->byte_order = MSBFirst;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if UseColorImage
|
2020-02-11 05:34:32 +00:00
|
|
|
image = XCreateImage(x_display, Xvisual, 24, ZPixmap, 0,
|
2019-07-23 02:50:34 +00:00
|
|
|
NULL /* (char *)image_Mem1 */,
|
|
|
|
vMacScreenWidth, vMacScreenHeight, 32,
|
2020-02-11 03:46:59 +00:00
|
|
|
4 * (uint32_t)vMacScreenWidth);
|
2020-02-11 05:34:32 +00:00
|
|
|
if (NULL == image) {
|
2019-07-23 02:50:34 +00:00
|
|
|
fprintf(stderr, "XCreateImage Color failed.\n");
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
fprintf(stderr, "DefaultDepth = %d\n",
|
|
|
|
(int)DefaultDepth(x_display, screen));
|
|
|
|
|
|
|
|
fprintf(stderr, "MSBFirst = %d\n", (int)MSBFirst);
|
|
|
|
fprintf(stderr, "LSBFirst = %d\n", (int)LSBFirst);
|
|
|
|
|
|
|
|
fprintf(stderr, "bitmap_bit_order = %d\n",
|
2020-02-11 05:34:32 +00:00
|
|
|
(int)image->bitmap_bit_order);
|
2019-07-23 02:50:34 +00:00
|
|
|
fprintf(stderr, "byte_order = %d\n",
|
2020-02-11 05:34:32 +00:00
|
|
|
(int)image->byte_order);
|
2019-07-23 02:50:34 +00:00
|
|
|
fprintf(stderr, "bitmap_unit = %d\n",
|
2020-02-11 05:34:32 +00:00
|
|
|
(int)image->bitmap_unit);
|
2019-07-23 02:50:34 +00:00
|
|
|
fprintf(stderr, "bits_per_pixel = %d\n",
|
2020-02-11 05:34:32 +00:00
|
|
|
(int)image->bits_per_pixel);
|
2019-07-23 02:50:34 +00:00
|
|
|
fprintf(stderr, "red_mask = %d\n",
|
2020-02-11 05:34:32 +00:00
|
|
|
(int)image->red_mask);
|
2019-07-23 02:50:34 +00:00
|
|
|
fprintf(stderr, "green_mask = %d\n",
|
2020-02-11 05:34:32 +00:00
|
|
|
(int)image->green_mask);
|
2019-07-23 02:50:34 +00:00
|
|
|
fprintf(stderr, "blue_mask = %d\n",
|
2020-02-11 05:34:32 +00:00
|
|
|
(int)image->blue_mask);
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* UseColorImage */
|
|
|
|
|
|
|
|
#if EnableMagnify && (! UseColorImage)
|
2020-02-11 05:34:32 +00:00
|
|
|
Scaled_image = XCreateImage(x_display, Xvisual,
|
2019-07-23 02:50:34 +00:00
|
|
|
1, XYBitmap, 0,
|
|
|
|
NULL /* (char *)image_Mem1 */,
|
2020-02-11 03:56:58 +00:00
|
|
|
vMacScreenWidth * WindowScale,
|
|
|
|
vMacScreenHeight * WindowScale,
|
|
|
|
32, vMacScreenMonoByteWidth * WindowScale);
|
2020-02-11 05:34:32 +00:00
|
|
|
if (NULL == Scaled_image) {
|
2019-07-23 02:50:34 +00:00
|
|
|
fprintf(stderr, "XCreateImage failed.\n");
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
Scaled_image->bitmap_bit_order = MSBFirst;
|
|
|
|
Scaled_image->byte_order = MSBFirst;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableMagnify && UseColorImage
|
2020-02-11 05:34:32 +00:00
|
|
|
Scaled_image = XCreateImage(x_display, Xvisual,
|
2019-07-23 02:50:34 +00:00
|
|
|
24, ZPixmap, 0,
|
|
|
|
NULL /* (char *)image_Mem1 */,
|
2020-02-11 03:56:58 +00:00
|
|
|
vMacScreenWidth * WindowScale,
|
|
|
|
vMacScreenHeight * WindowScale,
|
|
|
|
32, 4 * (uint32_t)vMacScreenWidth * WindowScale);
|
2020-02-11 05:34:32 +00:00
|
|
|
if (NULL == Scaled_image) {
|
2019-07-23 02:50:34 +00:00
|
|
|
fprintf(stderr, "XCreateImage Scaled failed.\n");
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0 != vMacScreenDepth
|
2020-02-11 05:34:32 +00:00
|
|
|
ColorModeWorks = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
DisableKeyRepeat();
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC CloseMainWindow(void)
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
if (gc != NULL) {
|
|
|
|
XFreeGC(x_display, gc);
|
|
|
|
gc = NULL;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
2020-02-11 05:34:32 +00:00
|
|
|
if (main_wind) {
|
|
|
|
XDestroyWindow(x_display, main_wind);
|
|
|
|
main_wind = 0;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
enum {
|
|
|
|
kMagStateNormal,
|
|
|
|
#if EnableMagnify
|
|
|
|
kMagStateMagnifgy,
|
|
|
|
#endif
|
|
|
|
kNumMagStates
|
|
|
|
};
|
|
|
|
|
|
|
|
#define kMagStateAuto kNumMagStates
|
|
|
|
|
|
|
|
#if MayNotFullScreen
|
|
|
|
LOCALVAR int CurWinIndx;
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool HavePositionWins[kNumMagStates];
|
2019-07-23 02:50:34 +00:00
|
|
|
LOCALVAR int WinPositionWinsH[kNumMagStates];
|
|
|
|
LOCALVAR int WinPositionWinsV[kNumMagStates];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableRecreateW
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC ZapWState(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
main_wind = 0;
|
|
|
|
gc = NULL;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool CreateMainWindow(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
Window rootwin;
|
|
|
|
int screen;
|
|
|
|
int xr;
|
|
|
|
int yr;
|
|
|
|
unsigned int dr;
|
|
|
|
unsigned int wr;
|
|
|
|
unsigned int hr;
|
|
|
|
unsigned int bwr;
|
|
|
|
Window rr;
|
|
|
|
int leftPos;
|
|
|
|
int topPos;
|
|
|
|
#if MayNotFullScreen
|
|
|
|
int WinIndx;
|
|
|
|
#endif
|
|
|
|
#if EnableDragDrop
|
|
|
|
long int xdnd_version = 5;
|
|
|
|
#endif
|
|
|
|
int NewWindowHeight = vMacScreenHeight;
|
|
|
|
int NewWindowWidth = vMacScreenWidth;
|
|
|
|
|
|
|
|
/* Get connection to X Server */
|
|
|
|
screen = DefaultScreen(x_display);
|
|
|
|
|
|
|
|
rootwin = XRootWindow(x_display, screen);
|
|
|
|
|
|
|
|
XGetGeometry(x_display, rootwin,
|
|
|
|
&rr, &xr, &yr, &wr, &hr, &bwr, &dr);
|
|
|
|
|
|
|
|
#if EnableMagnify
|
|
|
|
if (UseMagnify) {
|
2020-02-11 03:56:58 +00:00
|
|
|
NewWindowHeight *= WindowScale;
|
|
|
|
NewWindowWidth *= WindowScale;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (wr > NewWindowWidth) {
|
|
|
|
leftPos = (wr - NewWindowWidth) / 2;
|
|
|
|
} else {
|
|
|
|
leftPos = 0;
|
|
|
|
}
|
|
|
|
if (hr > NewWindowHeight) {
|
|
|
|
topPos = (hr - NewWindowHeight) / 2;
|
|
|
|
} else {
|
|
|
|
topPos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
ViewHSize = wr;
|
|
|
|
ViewVSize = hr;
|
|
|
|
#if EnableMagnify
|
|
|
|
if (UseMagnify) {
|
2020-02-11 03:56:58 +00:00
|
|
|
ViewHSize /= WindowScale;
|
|
|
|
ViewVSize /= WindowScale;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (ViewHSize >= vMacScreenWidth) {
|
|
|
|
ViewHStart = 0;
|
|
|
|
ViewHSize = vMacScreenWidth;
|
|
|
|
} else {
|
|
|
|
ViewHSize &= ~ 1;
|
|
|
|
}
|
|
|
|
if (ViewVSize >= vMacScreenHeight) {
|
|
|
|
ViewVStart = 0;
|
|
|
|
ViewVSize = vMacScreenHeight;
|
|
|
|
} else {
|
|
|
|
ViewVSize &= ~ 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (! UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayNotFullScreen
|
|
|
|
{
|
|
|
|
#if EnableMagnify
|
|
|
|
if (UseMagnify) {
|
|
|
|
WinIndx = kMagStateMagnifgy;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
WinIndx = kMagStateNormal;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! HavePositionWins[WinIndx]) {
|
|
|
|
WinPositionWinsH[WinIndx] = leftPos;
|
|
|
|
WinPositionWinsV[WinIndx] = topPos;
|
2020-02-11 05:34:32 +00:00
|
|
|
HavePositionWins[WinIndx] = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
|
|
|
leftPos = WinPositionWinsH[WinIndx];
|
|
|
|
topPos = WinPositionWinsV[WinIndx];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
XSetWindowAttributes xattr;
|
|
|
|
xattr.override_redirect = True;
|
|
|
|
xattr.background_pixel = x_black.pixel;
|
|
|
|
xattr.border_pixel = x_white.pixel;
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
main_wind = XCreateWindow(x_display, rr,
|
2019-07-23 02:50:34 +00:00
|
|
|
0, 0, wr, hr, 0,
|
|
|
|
CopyFromParent, /* depth */
|
|
|
|
InputOutput, /* class */
|
|
|
|
CopyFromParent, /* visual */
|
|
|
|
CWOverrideRedirect | CWBackPixel | CWBorderPixel,
|
|
|
|
/* valuemask */
|
|
|
|
&xattr /* attributes */);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
#if MayNotFullScreen
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
main_wind = XCreateSimpleWindow(x_display, rootwin,
|
2019-07-23 02:50:34 +00:00
|
|
|
leftPos,
|
|
|
|
topPos,
|
|
|
|
NewWindowWidth, NewWindowHeight, 4,
|
|
|
|
x_white.pixel,
|
|
|
|
x_black.pixel);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
if (! main_wind) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr("XCreateSimpleWindow failed.");
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
|
|
|
char *win_name =
|
|
|
|
(NULL != n_arg) ? n_arg : (
|
|
|
|
#if CanGetAppPath
|
|
|
|
(NULL != app_name) ? app_name :
|
|
|
|
#endif
|
|
|
|
kStrAppName);
|
2020-02-11 05:34:32 +00:00
|
|
|
XSelectInput(x_display, main_wind,
|
2019-07-23 02:50:34 +00:00
|
|
|
ExposureMask | KeyPressMask | KeyReleaseMask
|
|
|
|
| ButtonPressMask | ButtonReleaseMask
|
|
|
|
#if UseMotionEvents
|
|
|
|
| PointerMotionMask | EnterWindowMask | LeaveWindowMask
|
|
|
|
#endif
|
|
|
|
| FocusChangeMask);
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
XStoreName(x_display, main_wind, win_name);
|
|
|
|
XSetIconName(x_display, main_wind, win_name);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
XClassHint *hints = XAllocClassHint();
|
|
|
|
if (hints) {
|
|
|
|
hints->res_name = "minivmac";
|
|
|
|
hints->res_class = "minivmac";
|
2020-02-11 05:34:32 +00:00
|
|
|
XSetClassHint(x_display, main_wind, hints);
|
2019-07-23 02:50:34 +00:00
|
|
|
XFree(hints);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
XWMHints *hints = XAllocWMHints();
|
|
|
|
if (hints) {
|
|
|
|
hints->input = True;
|
|
|
|
hints->initial_state = NormalState;
|
|
|
|
hints->flags = InputHint | StateHint;
|
2020-02-11 05:34:32 +00:00
|
|
|
XSetWMHints(x_display, main_wind, hints);
|
2019-07-23 02:50:34 +00:00
|
|
|
XFree(hints);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
XSetCommand(x_display, main_wind, argv, argc);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
/* let us handle a click on the close box */
|
2020-02-11 05:34:32 +00:00
|
|
|
XSetWMProtocols(x_display, main_wind, &XA_DeleteW, 1);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#if EnableDragDrop
|
2020-02-11 05:34:32 +00:00
|
|
|
XChangeProperty (x_display, main_wind, XA_DndAware,
|
2019-07-23 02:50:34 +00:00
|
|
|
XA_ATOM, 32, PropModeReplace,
|
|
|
|
(unsigned char *) &xdnd_version, 1);
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
gc = XCreateGC(x_display, main_wind, 0, NULL);
|
|
|
|
if (NULL == gc) {
|
2019-07-23 02:50:34 +00:00
|
|
|
WriteExtraErr("XCreateGC failed.");
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
2020-02-11 05:34:32 +00:00
|
|
|
XSetState(x_display, gc, x_black.pixel, x_white.pixel,
|
2019-07-23 02:50:34 +00:00
|
|
|
GXcopy, AllPlanes);
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (! UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayNotFullScreen
|
|
|
|
{
|
|
|
|
XSizeHints *hints = XAllocSizeHints();
|
|
|
|
if (hints) {
|
|
|
|
hints->min_width = NewWindowWidth;
|
|
|
|
hints->max_width = NewWindowWidth;
|
|
|
|
hints->min_height = NewWindowHeight;
|
|
|
|
hints->max_height = NewWindowHeight;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Try again to say where the window ought to go.
|
|
|
|
I've seen this described as obsolete, but it
|
|
|
|
seems to work on all x implementations tried
|
|
|
|
so far, and nothing else does.
|
|
|
|
*/
|
|
|
|
hints->x = leftPos;
|
|
|
|
hints->y = topPos;
|
|
|
|
hints->width = NewWindowWidth;
|
|
|
|
hints->height = NewWindowHeight;
|
|
|
|
|
|
|
|
hints->flags = PMinSize | PMaxSize | PPosition | PSize;
|
2020-02-11 05:34:32 +00:00
|
|
|
XSetWMNormalHints(x_display, main_wind, hints);
|
2019-07-23 02:50:34 +00:00
|
|
|
XFree(hints);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
|
|
|
hOffset = leftPos;
|
|
|
|
vOffset = topPos;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
DisconnectKeyCodes3();
|
|
|
|
/* since will lose keystrokes to old window */
|
|
|
|
|
|
|
|
#if MayNotFullScreen
|
|
|
|
CurWinIndx = WinIndx;
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
XMapRaised(x_display, main_wind);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
XSync(x_display, 0);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
This helps in Red Hat 9 to get the new window
|
|
|
|
activated, and I've seen other programs
|
|
|
|
do similar things.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
In current scheme, haven't closed old window
|
|
|
|
yet. If old window full screen, never receive
|
|
|
|
expose event for new one.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
XEvent event;
|
|
|
|
|
|
|
|
do {
|
|
|
|
XNextEvent(x_display, &event);
|
|
|
|
HandleTheEvent(&event);
|
|
|
|
} while (! ((Expose == event.type)
|
2020-02-11 05:34:32 +00:00
|
|
|
&& (event.xexpose.window == main_wind)));
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
NeedFinishOpen1 = true;
|
|
|
|
NeedFinishOpen2 = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if MayFullScreen
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool GrabMachine = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if MayFullScreen
|
|
|
|
LOCALPROC GrabTheMachine(void)
|
|
|
|
{
|
|
|
|
#if EnableFSMouseMotion
|
|
|
|
StartSaveMouseMotion();
|
|
|
|
#endif
|
|
|
|
#if GrabKeysFullScreen
|
2020-02-11 03:56:58 +00:00
|
|
|
GrabKeyboard();
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if MayFullScreen
|
|
|
|
LOCALPROC UngrabMachine(void)
|
|
|
|
{
|
|
|
|
#if EnableFSMouseMotion
|
|
|
|
StopSaveMouseMotion();
|
|
|
|
#endif
|
|
|
|
#if GrabKeysFullScreen
|
2020-02-11 03:56:58 +00:00
|
|
|
UnGrabKeyboard();
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableRecreateW
|
2020-02-11 03:56:58 +00:00
|
|
|
struct WState {
|
2020-02-11 05:34:32 +00:00
|
|
|
Window f_main_wind;
|
|
|
|
GC f_gc;
|
2019-07-23 02:50:34 +00:00
|
|
|
#if MayFullScreen
|
|
|
|
short f_hOffset;
|
|
|
|
short f_vOffset;
|
2020-02-11 03:46:59 +00:00
|
|
|
uint16_t f_ViewHSize;
|
|
|
|
uint16_t f_ViewVSize;
|
|
|
|
uint16_t f_ViewHStart;
|
|
|
|
uint16_t f_ViewVStart;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
#if VarFullScreen
|
2020-02-11 05:34:32 +00:00
|
|
|
bool f_UseFullScreen;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
#if EnableMagnify
|
2020-02-11 05:34:32 +00:00
|
|
|
bool f_UseMagnify;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
};
|
2020-02-11 03:56:58 +00:00
|
|
|
typedef struct WState WState;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableRecreateW
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC GetWState(WState *r)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
r->f_main_wind = main_wind;
|
|
|
|
r->f_gc = gc;
|
2019-07-23 02:50:34 +00:00
|
|
|
#if MayFullScreen
|
|
|
|
r->f_hOffset = hOffset;
|
|
|
|
r->f_vOffset = vOffset;
|
|
|
|
r->f_ViewHSize = ViewHSize;
|
|
|
|
r->f_ViewVSize = ViewVSize;
|
|
|
|
r->f_ViewHStart = ViewHStart;
|
|
|
|
r->f_ViewVStart = ViewVStart;
|
|
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
|
|
r->f_UseFullScreen = UseFullScreen;
|
|
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
|
|
r->f_UseMagnify = UseMagnify;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableRecreateW
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC SetWState(WState *r)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
main_wind = r->f_main_wind;
|
|
|
|
gc = r->f_gc;
|
2019-07-23 02:50:34 +00:00
|
|
|
#if MayFullScreen
|
|
|
|
hOffset = r->f_hOffset;
|
|
|
|
vOffset = r->f_vOffset;
|
|
|
|
ViewHSize = r->f_ViewHSize;
|
|
|
|
ViewVSize = r->f_ViewVSize;
|
|
|
|
ViewHStart = r->f_ViewHStart;
|
|
|
|
ViewVStart = r->f_ViewVStart;
|
|
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
|
|
UseFullScreen = r->f_UseFullScreen;
|
|
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
|
|
UseMagnify = r->f_UseMagnify;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableRecreateW
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALVAR bool WantRestoreCursPos = false;
|
2020-02-11 03:46:59 +00:00
|
|
|
LOCALVAR uint16_t RestoreMouseH;
|
|
|
|
LOCALVAR uint16_t RestoreMouseV;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableRecreateW
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool ReCreateMainWindow(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
WState old_state;
|
|
|
|
WState new_state;
|
2019-07-23 02:50:34 +00:00
|
|
|
#if IncludeHostTextClipExchange
|
2020-02-11 05:34:32 +00:00
|
|
|
bool OwnClipboard = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (HaveCursorHidden) {
|
2020-02-11 05:34:32 +00:00
|
|
|
WantRestoreCursPos = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
RestoreMouseH = CurMouseH;
|
|
|
|
RestoreMouseV = CurMouseV;
|
|
|
|
}
|
|
|
|
|
|
|
|
ForceShowCursor(); /* hide/show cursor api is per window */
|
|
|
|
|
|
|
|
#if MayNotFullScreen
|
|
|
|
#if VarFullScreen
|
|
|
|
if (! UseFullScreen)
|
|
|
|
#endif
|
2020-02-11 05:34:32 +00:00
|
|
|
if (main_wind)
|
2019-07-23 02:50:34 +00:00
|
|
|
if (! NeedFinishOpen2)
|
|
|
|
{
|
|
|
|
/* save old position */
|
|
|
|
int xr;
|
|
|
|
int yr;
|
|
|
|
unsigned int dr;
|
|
|
|
unsigned int wr;
|
|
|
|
unsigned int hr;
|
|
|
|
unsigned int bwr;
|
|
|
|
Window rr;
|
|
|
|
Window rr2;
|
|
|
|
|
|
|
|
/* Get connection to X Server */
|
|
|
|
int screen = DefaultScreen(x_display);
|
|
|
|
|
|
|
|
Window rootwin = XRootWindow(x_display, screen);
|
|
|
|
|
|
|
|
XGetGeometry(x_display, rootwin,
|
|
|
|
&rr, &xr, &yr, &wr, &hr, &bwr, &dr);
|
|
|
|
|
|
|
|
/*
|
|
|
|
Couldn't reliably find out where window
|
|
|
|
is now, due to what seem to be some
|
|
|
|
broken X implementations, and so instead
|
|
|
|
track how far window has moved.
|
|
|
|
*/
|
|
|
|
XSync(x_display, 0);
|
2020-02-11 05:34:32 +00:00
|
|
|
if (XTranslateCoordinates(x_display, main_wind, rootwin,
|
2019-07-23 02:50:34 +00:00
|
|
|
0, 0, &xr, &yr, &rr2))
|
|
|
|
{
|
|
|
|
int newposh =
|
|
|
|
WinPositionWinsH[CurWinIndx] + (xr - SavedTransH);
|
|
|
|
int newposv =
|
|
|
|
WinPositionWinsV[CurWinIndx] + (yr - SavedTransV);
|
|
|
|
if ((newposv > 0) && (newposv < hr) && (newposh < wr)) {
|
|
|
|
WinPositionWinsH[CurWinIndx] = newposh;
|
|
|
|
WinPositionWinsV[CurWinIndx] = newposv;
|
|
|
|
SavedTransH = xr;
|
|
|
|
SavedTransV = yr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if MayFullScreen
|
|
|
|
if (GrabMachine) {
|
2020-02-11 05:34:32 +00:00
|
|
|
GrabMachine = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
UngrabMachine();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
GetWState(&old_state);
|
|
|
|
ZapWState();
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#if EnableMagnify
|
|
|
|
UseMagnify = WantMagnify;
|
|
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
|
|
UseFullScreen = WantFullScreen;
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
ColorTransValid = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if (! CreateMainWindow()) {
|
|
|
|
CloseMainWindow();
|
2020-02-11 03:56:58 +00:00
|
|
|
SetWState(&old_state);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
/* avoid retry */
|
|
|
|
#if VarFullScreen
|
|
|
|
WantFullScreen = UseFullScreen;
|
|
|
|
#endif
|
|
|
|
#if EnableMagnify
|
|
|
|
WantMagnify = UseMagnify;
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
2020-02-11 03:56:58 +00:00
|
|
|
GetWState(&new_state);
|
|
|
|
SetWState(&old_state);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#if IncludeHostTextClipExchange
|
2020-02-11 05:34:32 +00:00
|
|
|
if (main_wind) {
|
2020-02-11 03:56:58 +00:00
|
|
|
if (XGetSelectionOwner(x_display, XA_CLIPBOARD) ==
|
2020-02-11 05:34:32 +00:00
|
|
|
main_wind)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
OwnClipboard = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
CloseMainWindow();
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
SetWState(&new_state);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#if IncludeHostTextClipExchange
|
|
|
|
if (OwnClipboard) {
|
2020-02-11 03:56:58 +00:00
|
|
|
XSetSelectionOwner(x_display, XA_CLIPBOARD,
|
2020-02-11 05:34:32 +00:00
|
|
|
main_wind, CurrentTime);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if VarFullScreen && EnableMagnify
|
|
|
|
enum {
|
|
|
|
kWinStateWindowed,
|
|
|
|
#if EnableMagnify
|
|
|
|
kWinStateFullScreen,
|
|
|
|
#endif
|
|
|
|
kNumWinStates
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if VarFullScreen && EnableMagnify
|
|
|
|
LOCALVAR int WinMagStates[kNumWinStates];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
LOCALPROC ZapWinStateVars(void)
|
|
|
|
{
|
|
|
|
#if MayNotFullScreen
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < kNumMagStates; ++i) {
|
2020-02-11 05:34:32 +00:00
|
|
|
HavePositionWins[i] = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if VarFullScreen && EnableMagnify
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < kNumWinStates; ++i) {
|
|
|
|
WinMagStates[i] = kMagStateAuto;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
LOCALPROC ToggleWantFullScreen(void)
|
|
|
|
{
|
|
|
|
WantFullScreen = ! WantFullScreen;
|
|
|
|
|
|
|
|
#if EnableMagnify
|
|
|
|
{
|
|
|
|
int OldWinState =
|
|
|
|
UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
|
|
|
|
int OldMagState =
|
|
|
|
UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
|
|
|
|
int NewWinState =
|
|
|
|
WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
|
|
|
|
int NewMagState = WinMagStates[NewWinState];
|
|
|
|
|
|
|
|
WinMagStates[OldWinState] = OldMagState;
|
|
|
|
if (kMagStateAuto != NewMagState) {
|
|
|
|
WantMagnify = (kMagStateMagnifgy == NewMagState);
|
|
|
|
} else {
|
2020-02-11 05:34:32 +00:00
|
|
|
WantMagnify = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
if (WantFullScreen) {
|
|
|
|
Window rootwin;
|
|
|
|
int xr;
|
|
|
|
int yr;
|
|
|
|
unsigned int dr;
|
|
|
|
unsigned int wr;
|
|
|
|
unsigned int hr;
|
|
|
|
unsigned int bwr;
|
|
|
|
Window rr;
|
|
|
|
|
|
|
|
rootwin =
|
|
|
|
XRootWindow(x_display, DefaultScreen(x_display));
|
|
|
|
XGetGeometry(x_display, rootwin,
|
|
|
|
&rr, &xr, &yr, &wr, &hr, &bwr, &dr);
|
2020-02-11 03:56:58 +00:00
|
|
|
if ((wr >= vMacScreenWidth * WindowScale)
|
|
|
|
&& (hr >= vMacScreenHeight * WindowScale)
|
2019-07-23 02:50:34 +00:00
|
|
|
)
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
WantMagnify = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* --- SavedTasks --- */
|
|
|
|
|
|
|
|
LOCALPROC LeaveBackground(void)
|
|
|
|
{
|
|
|
|
ReconnectKeyCodes3();
|
|
|
|
DisableKeyRepeat();
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC EnterBackground(void)
|
|
|
|
{
|
|
|
|
RestoreKeyRepeat();
|
|
|
|
DisconnectKeyCodes3();
|
|
|
|
|
|
|
|
ForceShowCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC LeaveSpeedStopped(void)
|
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
#if SoundEnabled
|
|
|
|
Sound_Start();
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
StartUpTimeAdjust();
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC EnterSpeedStopped(void)
|
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
#if SoundEnabled
|
|
|
|
Sound_Stop();
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC CheckForSavedTasks(void)
|
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
if (EvtQNeedRecover) {
|
2020-02-11 05:34:32 +00:00
|
|
|
EvtQNeedRecover = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
/* attempt cleanup, EvtQNeedRecover may get set again */
|
|
|
|
EvtQTryRecoverFromFull();
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NeedFinishOpen2 && ! NeedFinishOpen1) {
|
2020-02-11 05:34:32 +00:00
|
|
|
NeedFinishOpen2 = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
#if VarFullScreen
|
|
|
|
if (UseFullScreen)
|
|
|
|
#endif
|
|
|
|
#if MayFullScreen
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
XSetInputFocus(x_display, main_wind,
|
2019-07-23 02:50:34 +00:00
|
|
|
RevertToPointerRoot, CurrentTime);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
#if MayNotFullScreen
|
|
|
|
{
|
|
|
|
Window rr;
|
|
|
|
int screen = DefaultScreen(x_display);
|
|
|
|
Window rootwin = XRootWindow(x_display, screen);
|
|
|
|
#if 0
|
|
|
|
/*
|
|
|
|
This doesn't work right in Red Hat 6, and may not
|
|
|
|
be needed anymore, now that using PPosition hint.
|
|
|
|
*/
|
2020-02-11 05:34:32 +00:00
|
|
|
XMoveWindow(x_display, main_wind,
|
2019-07-23 02:50:34 +00:00
|
|
|
leftPos, topPos);
|
|
|
|
/*
|
|
|
|
Needed after XMapRaised, because some window
|
|
|
|
managers will apparently ignore where the
|
|
|
|
window was asked to be put.
|
|
|
|
*/
|
|
|
|
#endif
|
|
|
|
|
|
|
|
XSync(x_display, 0);
|
|
|
|
/*
|
|
|
|
apparently, XTranslateCoordinates can be inaccurate
|
|
|
|
without this
|
|
|
|
*/
|
2020-02-11 05:34:32 +00:00
|
|
|
XTranslateCoordinates(x_display, main_wind, rootwin,
|
2019-07-23 02:50:34 +00:00
|
|
|
0, 0, &SavedTransH, &SavedTransV, &rr);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableRecreateW
|
|
|
|
if (WantRestoreCursPos) {
|
|
|
|
#if EnableFSMouseMotion
|
|
|
|
if (! HaveMouseMotion)
|
|
|
|
#endif
|
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
(void) MoveMouse(RestoreMouseH, RestoreMouseV);
|
2020-02-11 05:34:32 +00:00
|
|
|
WantCursorHidden = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
2020-02-11 05:34:32 +00:00
|
|
|
WantRestoreCursPos = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if EnableFSMouseMotion
|
|
|
|
if (HaveMouseMotion) {
|
2020-02-11 03:56:58 +00:00
|
|
|
MouseConstrain();
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (RequestMacOff) {
|
2020-02-11 05:34:32 +00:00
|
|
|
RequestMacOff = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
if (AnyDiskInserted()) {
|
|
|
|
MacMsgOverride(kStrQuitWarningTitle,
|
|
|
|
kStrQuitWarningMessage);
|
|
|
|
} else {
|
2020-02-11 05:34:32 +00:00
|
|
|
ForceMacOff = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ForceMacOff) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gTrueBackgroundFlag != gBackgroundFlag) {
|
|
|
|
gBackgroundFlag = gTrueBackgroundFlag;
|
|
|
|
if (gTrueBackgroundFlag) {
|
|
|
|
EnterBackground();
|
|
|
|
} else {
|
|
|
|
LeaveBackground();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CurSpeedStopped != (SpeedStopped ||
|
|
|
|
(gBackgroundFlag && ! RunInBackground
|
|
|
|
#if EnableAutoSlow && 0
|
|
|
|
&& (QuietSubTicks >= 4092)
|
|
|
|
#endif
|
|
|
|
)))
|
|
|
|
{
|
|
|
|
CurSpeedStopped = ! CurSpeedStopped;
|
|
|
|
if (CurSpeedStopped) {
|
|
|
|
EnterSpeedStopped();
|
|
|
|
} else {
|
|
|
|
LeaveSpeedStopped();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if MayFullScreen
|
|
|
|
if (gTrueBackgroundFlag
|
|
|
|
#if VarFullScreen
|
|
|
|
&& WantFullScreen
|
|
|
|
#endif
|
|
|
|
)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Since often get here on Ubuntu Linux 5.10
|
|
|
|
running on a slow machine (emulated) when
|
|
|
|
attempt to enter full screen, don't abort
|
|
|
|
full screen, but try to fix it.
|
|
|
|
*/
|
|
|
|
#if 0
|
|
|
|
ToggleWantFullScreen();
|
|
|
|
#else
|
2020-02-11 05:34:32 +00:00
|
|
|
XRaiseWindow(x_display, main_wind);
|
|
|
|
XSetInputFocus(x_display, main_wind,
|
2019-07-23 02:50:34 +00:00
|
|
|
RevertToPointerRoot, CurrentTime);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EnableRecreateW
|
|
|
|
if (0
|
|
|
|
#if EnableMagnify
|
|
|
|
|| (UseMagnify != WantMagnify)
|
|
|
|
#endif
|
|
|
|
#if VarFullScreen
|
|
|
|
|| (UseFullScreen != WantFullScreen)
|
|
|
|
#endif
|
|
|
|
)
|
|
|
|
{
|
|
|
|
(void) ReCreateMainWindow();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if MayFullScreen
|
|
|
|
if (GrabMachine != (
|
|
|
|
#if VarFullScreen
|
|
|
|
UseFullScreen &&
|
|
|
|
#endif
|
|
|
|
! (gTrueBackgroundFlag || CurSpeedStopped)))
|
|
|
|
{
|
|
|
|
GrabMachine = ! GrabMachine;
|
|
|
|
if (GrabMachine) {
|
|
|
|
GrabTheMachine();
|
|
|
|
} else {
|
|
|
|
UngrabMachine();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IncludeSonyNew
|
|
|
|
if (vSonyNewDiskWanted) {
|
|
|
|
#if IncludeSonyNameNew
|
|
|
|
if (vSonyNewDiskName != NotAPbuf) {
|
2020-02-11 05:34:32 +00:00
|
|
|
uint8_t * NewDiskNameDat;
|
|
|
|
if (MacRomanTextToNativePtr(vSonyNewDiskName, true,
|
2019-07-23 02:50:34 +00:00
|
|
|
&NewDiskNameDat))
|
|
|
|
{
|
|
|
|
MakeNewDisk(vSonyNewDiskSize, (char *)NewDiskNameDat);
|
|
|
|
free(NewDiskNameDat);
|
|
|
|
}
|
|
|
|
PbufDispose(vSonyNewDiskName);
|
|
|
|
vSonyNewDiskName = NotAPbuf;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
MakeNewDiskAtDefault(vSonyNewDiskSize);
|
|
|
|
}
|
2020-02-11 05:34:32 +00:00
|
|
|
vSonyNewDiskWanted = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
/* must be done after may have gotten disk */
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
|
|
|
|
MacMsgDisplayOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NeedWholeScreenDraw) {
|
2020-02-11 05:34:32 +00:00
|
|
|
NeedWholeScreenDraw = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
ScreenChangedAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
#if NeedRequestIthDisk
|
|
|
|
if (0 != RequestIthDisk) {
|
|
|
|
Sony_InsertIth(RequestIthDisk);
|
|
|
|
RequestIthDisk = 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (HaveCursorHidden != (WantCursorHidden
|
|
|
|
&& ! (gTrueBackgroundFlag || CurSpeedStopped)))
|
|
|
|
{
|
|
|
|
HaveCursorHidden = ! HaveCursorHidden;
|
|
|
|
if (HaveCursorHidden) {
|
2020-02-11 05:34:32 +00:00
|
|
|
XDefineCursor(x_display, main_wind, blankCursor);
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
2020-02-11 05:34:32 +00:00
|
|
|
XUndefineCursor(x_display, main_wind);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- command line parsing --- */
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool ScanCommandLine(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
char *pa;
|
|
|
|
int i = 1;
|
|
|
|
|
|
|
|
label_retry:
|
2020-02-11 05:34:32 +00:00
|
|
|
if (i < argc) {
|
|
|
|
pa = argv[i++];
|
2019-07-23 02:50:34 +00:00
|
|
|
if ('-' == pa[0]) {
|
|
|
|
if ((0 == strcmp(pa, "--display"))
|
|
|
|
|| (0 == strcmp(pa, "-display")))
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
if (i < argc) {
|
|
|
|
display_name = argv[i++];
|
2019-07-23 02:50:34 +00:00
|
|
|
goto label_retry;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if ((0 == strcmp(pa, "--rom"))
|
|
|
|
|| (0 == strcmp(pa, "-r")))
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
if (i < argc) {
|
|
|
|
rom_path = argv[i++];
|
2019-07-23 02:50:34 +00:00
|
|
|
goto label_retry;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if (0 == strcmp(pa, "-n"))
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
if (i < argc) {
|
|
|
|
n_arg = argv[i++];
|
2019-07-23 02:50:34 +00:00
|
|
|
goto label_retry;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if (0 == strcmp(pa, "-d"))
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
if (i < argc) {
|
|
|
|
d_arg = argv[i++];
|
2019-07-23 02:50:34 +00:00
|
|
|
goto label_retry;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
#ifndef UsingAlsa
|
|
|
|
#define UsingAlsa 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if UsingAlsa
|
|
|
|
if ((0 == strcmp(pa, "--alsadev"))
|
|
|
|
|| (0 == strcmp(pa, "-alsadev")))
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
if (i < argc) {
|
|
|
|
alsadev_name = argv[i++];
|
2019-07-23 02:50:34 +00:00
|
|
|
goto label_retry;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
#if 0
|
|
|
|
if (0 == strcmp(pa, "-l")) {
|
|
|
|
SpeedValue = 0;
|
|
|
|
goto label_retry;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
MacMsg(kStrBadArgTitle, kStrBadArgMessage, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
} else {
|
2020-02-11 05:34:32 +00:00
|
|
|
(void) Sony_Insert1(pa, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
goto label_retry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --- main program flow --- */
|
|
|
|
|
|
|
|
GLOBALOSGLUPROC DoneWithDrawingForTick(void)
|
|
|
|
{
|
|
|
|
#if EnableFSMouseMotion
|
|
|
|
if (HaveMouseMotion) {
|
|
|
|
AutoScrollScreen();
|
|
|
|
}
|
|
|
|
#endif
|
2020-02-11 03:56:58 +00:00
|
|
|
DrawChangesAndClear();
|
2019-07-23 02:50:34 +00:00
|
|
|
XFlush(x_display);
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
GLOBALOSGLUFUNC bool ExtraTimeNotOver(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
UpdateTrueEmulatedTime();
|
|
|
|
return TrueEmulatedTime == OnTrueTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC WaitForTheNextEvent(void)
|
|
|
|
{
|
|
|
|
XEvent event;
|
|
|
|
|
|
|
|
XNextEvent(x_display, &event);
|
|
|
|
HandleTheEvent(&event);
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC CheckForSystemEvents(void)
|
|
|
|
{
|
|
|
|
int i = 10;
|
|
|
|
|
|
|
|
while ((XEventsQueued(x_display, QueuedAfterReading) > 0)
|
|
|
|
&& (--i >= 0))
|
|
|
|
{
|
|
|
|
WaitForTheNextEvent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GLOBALOSGLUPROC WaitForNextTick(void)
|
|
|
|
{
|
|
|
|
label_retry:
|
|
|
|
CheckForSystemEvents();
|
|
|
|
CheckForSavedTasks();
|
|
|
|
if (ForceMacOff) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CurSpeedStopped) {
|
|
|
|
DoneWithDrawingForTick();
|
|
|
|
WaitForTheNextEvent();
|
|
|
|
goto label_retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ExtraTimeNotOver()) {
|
|
|
|
struct timespec rqt;
|
|
|
|
struct timespec rmt;
|
|
|
|
|
2020-02-11 03:46:59 +00:00
|
|
|
int32_t TimeDiff = GetTimeDiff();
|
2019-07-23 02:50:34 +00:00
|
|
|
if (TimeDiff < 0) {
|
|
|
|
rqt.tv_sec = 0;
|
|
|
|
rqt.tv_nsec = (- TimeDiff) * 1000;
|
|
|
|
(void) nanosleep(&rqt, &rmt);
|
|
|
|
}
|
|
|
|
goto label_retry;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CheckDateTime()) {
|
2020-02-11 03:56:58 +00:00
|
|
|
#if SoundEnabled
|
|
|
|
Sound_SecondNotify();
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((! gBackgroundFlag)
|
|
|
|
#if UseMotionEvents
|
|
|
|
&& (! CaughtMouse)
|
|
|
|
#endif
|
|
|
|
)
|
|
|
|
{
|
|
|
|
CheckMouseState();
|
|
|
|
}
|
|
|
|
|
|
|
|
OnTrueTime = TrueEmulatedTime;
|
|
|
|
|
|
|
|
#if dbglog_TimeStuff
|
|
|
|
dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- platform independent code can be thought of as going here --- */
|
|
|
|
|
|
|
|
#include "PROGMAIN.h"
|
|
|
|
|
|
|
|
LOCALPROC ZapOSGLUVars(void)
|
|
|
|
{
|
|
|
|
InitDrives();
|
|
|
|
ZapWinStateVars();
|
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC ReserveAllocAll(void)
|
|
|
|
{
|
|
|
|
#if dbglog_HAVE
|
|
|
|
dbglog_ReserveAlloc();
|
|
|
|
#endif
|
2020-02-11 05:34:32 +00:00
|
|
|
ReserveAllocOneBlock(&ROM, kROM_Size, 5, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
ReserveAllocOneBlock(&screencomparebuff,
|
2020-02-11 05:34:32 +00:00
|
|
|
vMacScreenNumBytes, 5, true);
|
2019-07-23 02:50:34 +00:00
|
|
|
#if UseControlKeys
|
|
|
|
ReserveAllocOneBlock(&CntrlDisplayBuff,
|
2020-02-11 05:34:32 +00:00
|
|
|
vMacScreenNumBytes, 5, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
#if WantScalingBuff
|
|
|
|
ReserveAllocOneBlock(&ScalingBuff,
|
2020-02-11 05:34:32 +00:00
|
|
|
ScalingBuffsz, 5, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
#if WantScalingTabl
|
|
|
|
ReserveAllocOneBlock(&ScalingTabl,
|
2020-02-11 05:34:32 +00:00
|
|
|
ScalingTablsz, 5, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
#if SoundEnabled
|
2020-02-11 05:34:32 +00:00
|
|
|
ReserveAllocOneBlock((uint8_t * *)&TheSoundBuffer,
|
|
|
|
dbhBufferSize, 5, false);
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
EmulationReserveAlloc();
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool AllocMemory(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
uimr n;
|
2020-02-11 05:34:32 +00:00
|
|
|
bool IsOk = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
ReserveAllocOffset = 0;
|
|
|
|
ReserveAllocBigBlock = nullpr;
|
|
|
|
ReserveAllocAll();
|
|
|
|
n = ReserveAllocOffset;
|
2020-02-11 05:34:32 +00:00
|
|
|
ReserveAllocBigBlock = (uint8_t *)calloc(1, n);
|
2019-07-23 02:50:34 +00:00
|
|
|
if (NULL == ReserveAllocBigBlock) {
|
2020-02-11 05:34:32 +00:00
|
|
|
MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, true);
|
2019-07-23 02:50:34 +00:00
|
|
|
} else {
|
|
|
|
ReserveAllocOffset = 0;
|
|
|
|
ReserveAllocAll();
|
|
|
|
if (n != ReserveAllocOffset) {
|
|
|
|
/* oops, program error */
|
|
|
|
} else {
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return IsOk;
|
|
|
|
}
|
|
|
|
|
2020-02-11 03:56:58 +00:00
|
|
|
LOCALPROC UnallocMemory(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
if (nullpr != ReserveAllocBigBlock) {
|
|
|
|
free((char *)ReserveAllocBigBlock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if HaveAppPathLink
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool ReadLink_Alloc(char *path, char **r)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
This should work to find size:
|
|
|
|
|
|
|
|
struct stat r;
|
|
|
|
|
|
|
|
if (lstat(path, &r) != -1) {
|
|
|
|
r = r.st_size;
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
But observed to return 0 in Ubuntu 10.04 x86-64
|
|
|
|
*/
|
|
|
|
|
|
|
|
char *s;
|
|
|
|
int sz;
|
|
|
|
char *p;
|
2020-02-11 05:34:32 +00:00
|
|
|
bool IsOk = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
size_t s_alloc = 256;
|
|
|
|
|
|
|
|
label_retry:
|
|
|
|
s = (char *)malloc(s_alloc);
|
|
|
|
if (NULL == s) {
|
|
|
|
fprintf(stderr, "malloc failed.\n");
|
|
|
|
} else {
|
|
|
|
sz = readlink(path, s, s_alloc);
|
|
|
|
if ((sz < 0) || (sz >= s_alloc)) {
|
|
|
|
free(s);
|
|
|
|
if (sz == s_alloc) {
|
|
|
|
s_alloc <<= 1;
|
|
|
|
goto label_retry;
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "readlink failed.\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* ok */
|
|
|
|
p = (char *)malloc(sz + 1);
|
|
|
|
if (NULL == p) {
|
|
|
|
fprintf(stderr, "malloc failed.\n");
|
|
|
|
} else {
|
|
|
|
(void) memcpy(p, s, sz);
|
|
|
|
p[sz] = 0;
|
|
|
|
*r = p;
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return IsOk;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if HaveSysctlPath
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool ReadKernProcPathname(char **r)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
size_t s_alloc;
|
|
|
|
char *s;
|
|
|
|
int mib[] = {
|
|
|
|
CTL_KERN,
|
|
|
|
KERN_PROC,
|
|
|
|
KERN_PROC_PATHNAME,
|
|
|
|
-1
|
|
|
|
};
|
2020-02-11 05:34:32 +00:00
|
|
|
bool IsOk = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
if (0 != sysctl(mib, sizeof(mib) / sizeof(int),
|
|
|
|
NULL, &s_alloc, NULL, 0))
|
|
|
|
{
|
|
|
|
fprintf(stderr, "sysctl failed.\n");
|
|
|
|
} else {
|
|
|
|
s = (char *)malloc(s_alloc);
|
|
|
|
if (NULL == s) {
|
|
|
|
fprintf(stderr, "malloc failed.\n");
|
|
|
|
} else {
|
|
|
|
if (0 != sysctl(mib, sizeof(mib) / sizeof(int),
|
|
|
|
s, &s_alloc, NULL, 0))
|
|
|
|
{
|
|
|
|
fprintf(stderr, "sysctl 2 failed.\n");
|
|
|
|
} else {
|
|
|
|
*r = s;
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
if (! IsOk) {
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return IsOk;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if CanGetAppPath
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool Path2ParentAndName(char *path,
|
2019-07-23 02:50:34 +00:00
|
|
|
char **parent, char **name)
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
bool IsOk = false;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
char *t = strrchr(path, '/');
|
|
|
|
if (NULL == t) {
|
|
|
|
fprintf(stderr, "no directory.\n");
|
|
|
|
} else {
|
|
|
|
int par_sz = t - path;
|
|
|
|
char *par = (char *)malloc(par_sz + 1);
|
|
|
|
if (NULL == par) {
|
|
|
|
fprintf(stderr, "malloc failed.\n");
|
|
|
|
} else {
|
|
|
|
(void) memcpy(par, path, par_sz);
|
|
|
|
par[par_sz] = 0;
|
|
|
|
{
|
|
|
|
int s_sz = strlen(path);
|
|
|
|
int child_sz = s_sz - par_sz - 1;
|
|
|
|
char *child = (char *)malloc(child_sz + 1);
|
|
|
|
if (NULL == child) {
|
|
|
|
fprintf(stderr, "malloc failed.\n");
|
|
|
|
} else {
|
|
|
|
(void) memcpy(child, t + 1, child_sz);
|
|
|
|
child[child_sz] = 0;
|
|
|
|
|
|
|
|
*name = child;
|
2020-02-11 05:34:32 +00:00
|
|
|
IsOk = true;
|
2019-07-23 02:50:34 +00:00
|
|
|
/* free(child); */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (! IsOk) {
|
|
|
|
free(par);
|
|
|
|
} else {
|
|
|
|
*parent = par;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return IsOk;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if CanGetAppPath
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool InitWhereAmI(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
if (!
|
|
|
|
#if HaveAppPathLink
|
|
|
|
ReadLink_Alloc(TheAppPathLink, &s)
|
|
|
|
#endif
|
|
|
|
#if HaveSysctlPath
|
|
|
|
ReadKernProcPathname(&s)
|
|
|
|
#endif
|
|
|
|
)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "InitWhereAmI fails.\n");
|
|
|
|
} else {
|
|
|
|
if (! Path2ParentAndName(s, &app_parent, &app_name)) {
|
|
|
|
fprintf(stderr, "Path2ParentAndName fails.\n");
|
|
|
|
} else {
|
|
|
|
/* ok */
|
|
|
|
/*
|
|
|
|
fprintf(stderr, "parent = %s.\n", app_parent);
|
|
|
|
fprintf(stderr, "name = %s.\n", app_name);
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
return true; /* keep going regardless */
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if CanGetAppPath
|
|
|
|
LOCALPROC UninitWhereAmI(void)
|
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
MayFree(app_parent);
|
|
|
|
MayFree(app_name);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
LOCALFUNC bool InitOSGLU(void)
|
2019-07-23 02:50:34 +00:00
|
|
|
{
|
2020-02-11 03:56:58 +00:00
|
|
|
if (AllocMemory())
|
2019-07-23 02:50:34 +00:00
|
|
|
#if CanGetAppPath
|
|
|
|
if (InitWhereAmI())
|
|
|
|
#endif
|
|
|
|
#if dbglog_HAVE
|
|
|
|
if (dbglog_open())
|
|
|
|
#endif
|
|
|
|
if (ScanCommandLine())
|
|
|
|
if (LoadMacRom())
|
|
|
|
if (LoadInitialImages())
|
|
|
|
if (InitLocationDat())
|
2020-02-11 03:56:58 +00:00
|
|
|
#if SoundEnabled
|
|
|
|
if (Sound_Init())
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
if (Screen_Init())
|
|
|
|
if (CreateMainWindow())
|
|
|
|
if (KC2MKCInit())
|
|
|
|
if (WaitForRom())
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
return true;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
2020-02-11 05:34:32 +00:00
|
|
|
return false;
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LOCALPROC UnInitOSGLU(void)
|
|
|
|
{
|
|
|
|
if (MacMsgDisplayed) {
|
|
|
|
MacMsgDisplayOff();
|
|
|
|
}
|
|
|
|
|
|
|
|
RestoreKeyRepeat();
|
|
|
|
#if MayFullScreen
|
|
|
|
UngrabMachine();
|
|
|
|
#endif
|
2020-02-11 03:56:58 +00:00
|
|
|
#if SoundEnabled
|
|
|
|
Sound_Stop();
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
2020-02-11 03:56:58 +00:00
|
|
|
#if SoundEnabled
|
|
|
|
Sound_UnInit();
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
#if IncludeHostTextClipExchange
|
2020-02-11 03:56:58 +00:00
|
|
|
FreeClipBuffer();
|
2019-07-23 02:50:34 +00:00
|
|
|
#endif
|
|
|
|
#if IncludePbufs
|
|
|
|
UnInitPbufs();
|
|
|
|
#endif
|
|
|
|
UnInitDrives();
|
|
|
|
|
|
|
|
ForceShowCursor();
|
|
|
|
if (blankCursor != None) {
|
|
|
|
XFreeCursor(x_display, blankCursor);
|
|
|
|
}
|
|
|
|
|
2020-02-11 05:34:32 +00:00
|
|
|
if (image != NULL) {
|
|
|
|
XDestroyImage(image);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#if EnableMagnify
|
2020-02-11 05:34:32 +00:00
|
|
|
if (Scaled_image != NULL) {
|
|
|
|
XDestroyImage(Scaled_image);
|
2019-07-23 02:50:34 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
CloseMainWindow();
|
|
|
|
if (x_display != NULL) {
|
|
|
|
XCloseDisplay(x_display);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if dbglog_HAVE
|
|
|
|
dbglog_close();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if CanGetAppPath
|
|
|
|
UninitWhereAmI();
|
|
|
|
#endif
|
2020-02-11 03:56:58 +00:00
|
|
|
UnallocMemory();
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
CheckSavedMacMsg();
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv)
|
|
|
|
{
|
2020-02-11 05:34:32 +00:00
|
|
|
argc = argc;
|
|
|
|
argv = argv;
|
2019-07-23 02:50:34 +00:00
|
|
|
|
|
|
|
ZapOSGLUVars();
|
|
|
|
if (InitOSGLU()) {
|
|
|
|
ProgramMain();
|
|
|
|
}
|
|
|
|
UnInitOSGLU();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|