mirror of
https://github.com/InvisibleUp/uvmac.git
synced 2024-06-09 22:29:32 +00:00
be71368cf7
Non-windows systems are probably broken right now. Color display in general is probably broken. But, soon, you will be able to change the screen size and color depth without recompiling. That would be nice.
1758 lines
36 KiB
C
1758 lines
36 KiB
C
/*
|
|
OSGLUGTK.c
|
|
|
|
Copyright (C) 2009 Paul C. Pratt
|
|
|
|
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 GTK
|
|
|
|
All operating system dependent code for the
|
|
GIMP Toolkit should go here.
|
|
*/
|
|
|
|
#include "CNFGRAPI.h"
|
|
#include "SYSDEPNS.h"
|
|
#include "UTIL/ENDIANAC.h"
|
|
|
|
#include "UI/MYOSGLUE.h"
|
|
|
|
#include "STRCONST.h"
|
|
|
|
#include "UI/COMOSGLU.h"
|
|
|
|
/* --- some simple utilities --- */
|
|
|
|
GLOBALOSGLUPROC MoveBytes(anyp srcPtr, anyp destPtr, int32_t byteCount)
|
|
{
|
|
(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
|
|
}
|
|
|
|
/* --- control mode and internationalization --- */
|
|
|
|
#define NeedCell2PlainAsciiMap 1
|
|
|
|
#include "LANG/INTLCHAR.h"
|
|
|
|
#include "UI/CONTROLM.h"
|
|
|
|
/* --- sending debugging info to file --- */
|
|
|
|
#if dbglog_HAVE
|
|
|
|
#define dbglog_ToStdErr 0
|
|
|
|
#if ! dbglog_ToStdErr
|
|
LOCALVAR FILE *dbglog_File = NULL;
|
|
#endif
|
|
|
|
LOCALFUNC bool dbglog_open0(void)
|
|
{
|
|
#if dbglog_ToStdErr
|
|
return true;
|
|
#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 --- */
|
|
|
|
#define DbgEvents (dbglog_HAVE && 1)
|
|
|
|
#if ! dbglog_HAVE
|
|
#define WriteExtraErr(s)
|
|
#else
|
|
LOCALPROC WriteExtraErr(char *s)
|
|
{
|
|
dbglog_writeCStr("*** error: ");
|
|
dbglog_writeCStr(s);
|
|
dbglog_writeReturn();
|
|
}
|
|
#endif
|
|
|
|
/* --- text translation --- */
|
|
|
|
LOCALPROC NativeStrFromCStr(char *r, char *s, bool AddEllipsis)
|
|
{
|
|
uint8_t ps[ClStrMaxLength];
|
|
int i;
|
|
int L;
|
|
|
|
ClStrFromSubstCStr(&L, ps, s);
|
|
|
|
for (i = 0; i < L; ++i) {
|
|
r[i] = Cell2PlainAsciiMap[ps[i]];
|
|
}
|
|
|
|
if (AddEllipsis) {
|
|
r[L] = '.';
|
|
++L;
|
|
r[L] = '.';
|
|
++L;
|
|
r[L] = '.';
|
|
++L;
|
|
}
|
|
|
|
r[L] = 0;
|
|
}
|
|
|
|
/* --- drives --- */
|
|
|
|
#define NotAfileRef NULL
|
|
|
|
LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyTransfer(bool IsWrite, uint8_t * Buffer,
|
|
tDrive Drive_No, uint32_t Sony_Start, uint32_t Sony_Count,
|
|
uint32_t *Sony_ActCount)
|
|
{
|
|
uint32_t NewSony_Count = Sony_Count;
|
|
|
|
fseek(Drives[Drive_No], Sony_Start, SEEK_SET);
|
|
|
|
if (IsWrite) {
|
|
fwrite(Buffer, 1, NewSony_Count, Drives[Drive_No]);
|
|
} else {
|
|
fread(Buffer, 1, NewSony_Count, Drives[Drive_No]);
|
|
}
|
|
|
|
if (nullpr != Sony_ActCount) {
|
|
*Sony_ActCount = NewSony_Count;
|
|
}
|
|
|
|
return mnvm_noErr; /*& figure out what really to return &*/
|
|
}
|
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, uint32_t *Sony_Count)
|
|
{
|
|
fseek(Drives[Drive_No], 0, SEEK_END);
|
|
*Sony_Count = ftell(Drives[Drive_No]);
|
|
return mnvm_noErr; /*& figure out what really to return &*/
|
|
}
|
|
|
|
LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, bool deleteit)
|
|
{
|
|
DiskEjectedNotify(Drive_No);
|
|
|
|
fclose(Drives[Drive_No]);
|
|
Drives[Drive_No] = NotAfileRef; /* not really needed */
|
|
|
|
|
|
return mnvm_noErr;
|
|
}
|
|
|
|
GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
|
|
{
|
|
return vSonyEject0(Drive_No, false);
|
|
}
|
|
|
|
LOCALPROC UnInitDrives(void)
|
|
{
|
|
tDrive i;
|
|
|
|
for (i = 0; i < NumDrives; ++i) {
|
|
if (vSonyIsInserted(i)) {
|
|
(void) vSonyEject(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
LOCALFUNC bool Sony_Insert0(FILE *refnum, bool locked,
|
|
char *drivepath)
|
|
{
|
|
tDrive Drive_No;
|
|
|
|
if (! FirstFreeDisk(&Drive_No)) {
|
|
fclose(refnum);
|
|
MacMsg(kStrTooManyImagesTitle,
|
|
kStrTooManyImagesMessage, false);
|
|
return false;
|
|
} else {
|
|
/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
|
|
Drives[Drive_No] = refnum;
|
|
DiskInsertNotify(Drive_No, locked);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
LOCALFUNC bool Sony_Insert1(char *drivepath, bool silentfail)
|
|
{
|
|
bool locked = false;
|
|
/* printf("Sony_Insert1 %s\n", drivepath); */
|
|
FILE *refnum = fopen(drivepath, "rb+");
|
|
if (NULL == refnum) {
|
|
locked = true;
|
|
refnum = fopen(drivepath, "rb");
|
|
}
|
|
if (NULL == refnum) {
|
|
if (! silentfail) {
|
|
MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, false);
|
|
}
|
|
} else {
|
|
return Sony_Insert0(refnum, locked, drivepath);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
LOCALFUNC bool Sony_Insert1a(char *drivepath, bool silentfail)
|
|
{
|
|
bool v;
|
|
|
|
if (! ROM_loaded) {
|
|
v = (mnvm_noErr == LoadMacRomFrom(drivepath));
|
|
} else {
|
|
v = Sony_Insert1(drivepath, silentfail);
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
LOCALFUNC bool Sony_InsertIth(int i)
|
|
{
|
|
bool v;
|
|
|
|
if ((i > 9) || ! FirstFreeDisk(nullpr)) {
|
|
v = false;
|
|
} else {
|
|
char s[] = "disk?.dsk";
|
|
|
|
s[4] = '0' + i;
|
|
|
|
v = Sony_Insert1(s, true);
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
LOCALFUNC bool LoadInitialImages(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 1; Sony_InsertIth(i); ++i) {
|
|
/* stop on first error (including file not found) */
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* --- ROM --- */
|
|
|
|
LOCALVAR char *rom_path = NULL;
|
|
|
|
LOCALFUNC bool LoadMacRom(void)
|
|
{
|
|
tMacErr err;
|
|
|
|
if ((NULL == rom_path)
|
|
|| (mnvm_fnfErr == (err = LoadMacRomFrom(rom_path))))
|
|
if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName)))
|
|
{
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* --- video out --- */
|
|
|
|
static GtkWidget *drawing_area;
|
|
|
|
LOCALVAR bool gBackgroundFlag = false;
|
|
LOCALVAR bool gTrueBackgroundFlag = false;
|
|
LOCALVAR bool CurSpeedStopped = true;
|
|
|
|
LOCALPROC HaveChangedScreenBuff(int16_t top, int16_t left,
|
|
int16_t bottom, int16_t right)
|
|
{
|
|
guchar graybuf[vMacScreenWidth * vMacScreenHeight];
|
|
|
|
{
|
|
int i;
|
|
int j;
|
|
int k;
|
|
uint8_t *p1 = GetCurDrawBuff()
|
|
+ (uint32_t)vMacScreenWidth / 8 * top;
|
|
uint8_t *p2 = (uint8_t *)graybuf + (uint32_t)vMacScreenWidth * top;
|
|
uint32_t t0;
|
|
|
|
UnusedParam(left);
|
|
UnusedParam(right);
|
|
for (i = bottom - top; --i >= 0; ) {
|
|
for (j = vMacScreenWidth / 8; --j >= 0; ) {
|
|
t0 = *p1++;
|
|
for (k = 8; --k >= 0; ) {
|
|
*p2++ = ((t0 >> k) & 0x01) - 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
gdk_draw_gray_image(drawing_area->window,
|
|
drawing_area->style->fg_gc[GTK_WIDGET_STATE(drawing_area)],
|
|
left /* x */,
|
|
top /* y */,
|
|
right - left /* width */,
|
|
bottom - top /* height */,
|
|
GDK_RGB_DITHER_NONE,
|
|
graybuf + left + (uint32_t)vMacScreenWidth * top,
|
|
vMacScreenWidth);
|
|
}
|
|
|
|
LOCALPROC DrawChangesAndClear(void)
|
|
{
|
|
if (ScreenChangedBottom > ScreenChangedTop) {
|
|
HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
|
|
ScreenChangedBottom, ScreenChangedRight);
|
|
ScreenClearChanges();
|
|
}
|
|
}
|
|
|
|
GLOBALOSGLUPROC DoneWithDrawingForTick(void)
|
|
{
|
|
DrawChangesAndClear();
|
|
}
|
|
|
|
/* --- mouse --- */
|
|
|
|
LOCALVAR bool HaveCursorHidden = false;
|
|
LOCALVAR bool WantCursorHidden = false;
|
|
|
|
static GdkCursor *blank_cursor;
|
|
static GtkWidget *window = NULL;
|
|
|
|
LOCALPROC ForceShowCursor(void)
|
|
{
|
|
if (HaveCursorHidden) {
|
|
HaveCursorHidden = false;
|
|
|
|
if (window) {
|
|
gdk_window_set_cursor(window->window, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* cursor state */
|
|
|
|
LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
|
|
{
|
|
bool ShouldHaveCursorHidden = true;
|
|
|
|
{
|
|
if (NewMousePosh < 0) {
|
|
NewMousePosh = 0;
|
|
ShouldHaveCursorHidden = false;
|
|
} else if (NewMousePosh >= vMacScreenWidth) {
|
|
NewMousePosh = vMacScreenWidth - 1;
|
|
ShouldHaveCursorHidden = false;
|
|
}
|
|
if (NewMousePosv < 0) {
|
|
NewMousePosv = 0;
|
|
ShouldHaveCursorHidden = false;
|
|
} else if (NewMousePosv >= vMacScreenHeight) {
|
|
NewMousePosv = vMacScreenHeight - 1;
|
|
ShouldHaveCursorHidden = false;
|
|
}
|
|
|
|
|
|
/* if (ShouldHaveCursorHidden || CurMouseButton) */
|
|
/*
|
|
for a game like arkanoid, would like mouse to still
|
|
move even when outside window in one direction
|
|
*/
|
|
MousePositionSet(NewMousePosh, NewMousePosv);
|
|
}
|
|
|
|
WantCursorHidden = ShouldHaveCursorHidden;
|
|
}
|
|
|
|
LOCALPROC CheckMouseState(void)
|
|
{
|
|
#if 0
|
|
gint x;
|
|
gint y;
|
|
gint x0;
|
|
gint y0;
|
|
|
|
gdk_display_get_pointer(gdk_drawable_get_display(window),
|
|
NULL, &x, &y, NULL);
|
|
(void) gdk_window_get_origin(window, &x0, &y0);
|
|
MousePositionNotify(x - x0, y - y0);
|
|
#endif
|
|
gint x;
|
|
gint y;
|
|
|
|
gtk_widget_get_pointer(drawing_area, &x, &y);
|
|
/* (void) gdk_window_get_pointer(window, &x, &y, NULL); */
|
|
MousePositionNotify(x, y);
|
|
}
|
|
|
|
/* --- keyboard input --- */
|
|
|
|
#define MaxNumKeycode 256
|
|
#define KeyCodeMask (MaxNumKeycode - 1)
|
|
/*
|
|
assume keycodes >= 0 and < MaxNumKeycode, which
|
|
isn't promised by gtk documentation.
|
|
*/
|
|
|
|
|
|
LOCALVAR uint8_t KC2MKC[MaxNumKeycode];
|
|
|
|
LOCALPROC KC2MKCAssignOne(guint keyval, uint8_t key)
|
|
{
|
|
GdkKeymapKey *keys;
|
|
gint n_keys;
|
|
int i;
|
|
|
|
if (gdk_keymap_get_entries_for_keyval(NULL,
|
|
keyval, &keys, &n_keys))
|
|
{
|
|
for (i = 0; i < n_keys; i++) {
|
|
KC2MKC[keys[i].keycode & KeyCodeMask] = key;
|
|
}
|
|
g_free(keys);
|
|
}
|
|
#if 0
|
|
fprintf(stderr, "%d %d %d\n", (int)ks, key, (int)code);
|
|
#endif
|
|
}
|
|
|
|
LOCALFUNC bool KC2MKCInit(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 256; ++i) {
|
|
KC2MKC[i] = MKC_None;
|
|
}
|
|
|
|
#ifdef GDK_KP_Insert
|
|
KC2MKCAssignOne(GDK_KP_Insert, MKC_KP0);
|
|
#endif
|
|
#ifdef GDK_KP_End
|
|
KC2MKCAssignOne(GDK_KP_End, MKC_KP1);
|
|
#endif
|
|
#ifdef GDK_KP_Down
|
|
KC2MKCAssignOne(GDK_KP_Down, MKC_KP2);
|
|
#endif
|
|
#ifdef GDK_KP_Next
|
|
KC2MKCAssignOne(GDK_KP_Next, MKC_KP3);
|
|
#endif
|
|
#ifdef GDK_KP_Left
|
|
KC2MKCAssignOne(GDK_KP_Left, MKC_KP4);
|
|
#endif
|
|
#ifdef GDK_KP_Begin
|
|
KC2MKCAssignOne(GDK_KP_Begin, MKC_KP5);
|
|
#endif
|
|
#ifdef GDK_KP_Right
|
|
KC2MKCAssignOne(GDK_KP_Right, MKC_KP6);
|
|
#endif
|
|
#ifdef GDK_KP_Home
|
|
KC2MKCAssignOne(GDK_KP_Home, MKC_KP7);
|
|
#endif
|
|
#ifdef GDK_KP_Up
|
|
KC2MKCAssignOne(GDK_KP_Up, MKC_KP8);
|
|
#endif
|
|
#ifdef GDK_KP_Prior
|
|
KC2MKCAssignOne(GDK_KP_Prior, MKC_KP9);
|
|
#endif
|
|
#ifdef GDK_KP_Delete
|
|
KC2MKCAssignOne(GDK_KP_Delete, MKC_Decimal);
|
|
#endif
|
|
|
|
KC2MKCAssignOne(GDK_asciitilde, MKC_formac_Grave);
|
|
KC2MKCAssignOne(GDK_underscore, MKC_Minus);
|
|
KC2MKCAssignOne(GDK_plus, MKC_Equal);
|
|
KC2MKCAssignOne(GDK_braceleft, MKC_LeftBracket);
|
|
KC2MKCAssignOne(GDK_braceright, MKC_RightBracket);
|
|
KC2MKCAssignOne(GDK_bar, MKC_formac_BackSlash);
|
|
KC2MKCAssignOne(GDK_colon, MKC_SemiColon);
|
|
KC2MKCAssignOne(GDK_quotedbl, MKC_SingleQuote);
|
|
KC2MKCAssignOne(GDK_less, MKC_Comma);
|
|
KC2MKCAssignOne(GDK_greater, MKC_Period);
|
|
KC2MKCAssignOne(GDK_question, MKC_formac_Slash);
|
|
|
|
KC2MKCAssignOne(GDK_a, MKC_A);
|
|
KC2MKCAssignOne(GDK_b, MKC_B);
|
|
KC2MKCAssignOne(GDK_c, MKC_C);
|
|
KC2MKCAssignOne(GDK_d, MKC_D);
|
|
KC2MKCAssignOne(GDK_e, MKC_E);
|
|
KC2MKCAssignOne(GDK_f, MKC_F);
|
|
KC2MKCAssignOne(GDK_g, MKC_G);
|
|
KC2MKCAssignOne(GDK_h, MKC_H);
|
|
KC2MKCAssignOne(GDK_i, MKC_I);
|
|
KC2MKCAssignOne(GDK_j, MKC_J);
|
|
KC2MKCAssignOne(GDK_k, MKC_K);
|
|
KC2MKCAssignOne(GDK_l, MKC_L);
|
|
KC2MKCAssignOne(GDK_m, MKC_M);
|
|
KC2MKCAssignOne(GDK_n, MKC_N);
|
|
KC2MKCAssignOne(GDK_o, MKC_O);
|
|
KC2MKCAssignOne(GDK_p, MKC_P);
|
|
KC2MKCAssignOne(GDK_q, MKC_Q);
|
|
KC2MKCAssignOne(GDK_r, MKC_R);
|
|
KC2MKCAssignOne(GDK_s, MKC_S);
|
|
KC2MKCAssignOne(GDK_t, MKC_T);
|
|
KC2MKCAssignOne(GDK_u, MKC_U);
|
|
KC2MKCAssignOne(GDK_v, MKC_V);
|
|
KC2MKCAssignOne(GDK_w, MKC_W);
|
|
KC2MKCAssignOne(GDK_x, MKC_X);
|
|
KC2MKCAssignOne(GDK_y, MKC_Y);
|
|
KC2MKCAssignOne(GDK_z, MKC_Z);
|
|
|
|
/*
|
|
main mappings
|
|
*/
|
|
|
|
KC2MKCAssignOne(GDK_F1, MKC_formac_F1);
|
|
KC2MKCAssignOne(GDK_F2, MKC_formac_F2);
|
|
KC2MKCAssignOne(GDK_F3, MKC_formac_F3);
|
|
KC2MKCAssignOne(GDK_F4, MKC_formac_F4);
|
|
KC2MKCAssignOne(GDK_F5, MKC_formac_F5);
|
|
KC2MKCAssignOne(GDK_F6, MKC_F6);
|
|
KC2MKCAssignOne(GDK_F7, MKC_F7);
|
|
KC2MKCAssignOne(GDK_F8, MKC_F8);
|
|
KC2MKCAssignOne(GDK_F9, MKC_F9);
|
|
KC2MKCAssignOne(GDK_F10, MKC_F10);
|
|
KC2MKCAssignOne(GDK_F11, MKC_F11);
|
|
KC2MKCAssignOne(GDK_F12, MKC_F12);
|
|
|
|
#ifdef GDK_Delete
|
|
KC2MKCAssignOne(GDK_Delete, MKC_formac_ForwardDel);
|
|
#endif
|
|
#ifdef GDK_Insert
|
|
KC2MKCAssignOne(GDK_Insert, MKC_formac_Help);
|
|
#endif
|
|
#ifdef GDK_Help
|
|
KC2MKCAssignOne(GDK_Help, MKC_formac_Help);
|
|
#endif
|
|
#ifdef GDK_Home
|
|
KC2MKCAssignOne(GDK_Home, MKC_formac_Home);
|
|
#endif
|
|
#ifdef GDK_End
|
|
KC2MKCAssignOne(GDK_End, MKC_formac_End);
|
|
#endif
|
|
|
|
#ifdef GDK_Page_Up
|
|
KC2MKCAssignOne(GDK_Page_Up, MKC_formac_PageUp);
|
|
#else
|
|
#ifdef GDK_Prior
|
|
KC2MKCAssignOne(GDK_Prior, MKC_formac_PageUp);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef GDK_Page_Down
|
|
KC2MKCAssignOne(GDK_Page_Down, MKC_formac_PageDown);
|
|
#else
|
|
#ifdef GDK_Next
|
|
KC2MKCAssignOne(GDK_Next, MKC_formac_PageDown);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef GDK_Print
|
|
KC2MKCAssignOne(GDK_Print, MKC_Print);
|
|
#endif
|
|
#ifdef GDK_Scroll_Lock
|
|
KC2MKCAssignOne(GDK_Scroll_Lock, MKC_ScrollLock);
|
|
#endif
|
|
#ifdef GDK_Pause
|
|
KC2MKCAssignOne(GDK_Pause, MKC_Pause);
|
|
#endif
|
|
|
|
KC2MKCAssignOne(GDK_KP_Add, MKC_KPAdd);
|
|
KC2MKCAssignOne(GDK_KP_Subtract, MKC_KPSubtract);
|
|
KC2MKCAssignOne(GDK_KP_Multiply, MKC_KPMultiply);
|
|
KC2MKCAssignOne(GDK_KP_Divide, MKC_KPDevide);
|
|
KC2MKCAssignOne(GDK_KP_Enter, MKC_formac_Enter);
|
|
KC2MKCAssignOne(GDK_KP_Equal, MKC_KPEqual);
|
|
|
|
KC2MKCAssignOne(GDK_KP_0, MKC_KP0);
|
|
KC2MKCAssignOne(GDK_KP_1, MKC_KP1);
|
|
KC2MKCAssignOne(GDK_KP_2, MKC_KP2);
|
|
KC2MKCAssignOne(GDK_KP_3, MKC_KP3);
|
|
KC2MKCAssignOne(GDK_KP_4, MKC_KP4);
|
|
KC2MKCAssignOne(GDK_KP_5, MKC_KP5);
|
|
KC2MKCAssignOne(GDK_KP_6, MKC_KP6);
|
|
KC2MKCAssignOne(GDK_KP_7, MKC_KP7);
|
|
KC2MKCAssignOne(GDK_KP_8, MKC_KP8);
|
|
KC2MKCAssignOne(GDK_KP_9, MKC_KP9);
|
|
KC2MKCAssignOne(GDK_KP_Decimal, MKC_Decimal);
|
|
|
|
KC2MKCAssignOne(GDK_Left, MKC_Left);
|
|
KC2MKCAssignOne(GDK_Right, MKC_Right);
|
|
KC2MKCAssignOne(GDK_Up, MKC_Up);
|
|
KC2MKCAssignOne(GDK_Down, MKC_Down);
|
|
|
|
KC2MKCAssignOne(GDK_grave, MKC_formac_Grave);
|
|
KC2MKCAssignOne(GDK_minus, MKC_Minus);
|
|
KC2MKCAssignOne(GDK_equal, MKC_Equal);
|
|
KC2MKCAssignOne(GDK_bracketleft, MKC_LeftBracket);
|
|
KC2MKCAssignOne(GDK_bracketright, MKC_RightBracket);
|
|
KC2MKCAssignOne(GDK_backslash, MKC_formac_BackSlash);
|
|
KC2MKCAssignOne(GDK_semicolon, MKC_SemiColon);
|
|
KC2MKCAssignOne(GDK_apostrophe, MKC_SingleQuote);
|
|
KC2MKCAssignOne(GDK_comma, MKC_Comma);
|
|
KC2MKCAssignOne(GDK_period, MKC_Period);
|
|
KC2MKCAssignOne(GDK_slash, MKC_formac_Slash);
|
|
|
|
KC2MKCAssignOne(GDK_Escape, MKC_formac_Escape);
|
|
|
|
KC2MKCAssignOne(GDK_Tab, MKC_Tab);
|
|
KC2MKCAssignOne(GDK_Return, MKC_Return);
|
|
KC2MKCAssignOne(GDK_space, MKC_Space);
|
|
KC2MKCAssignOne(GDK_BackSpace, MKC_BackSpace);
|
|
|
|
KC2MKCAssignOne(GDK_Caps_Lock, MKC_formac_CapsLock);
|
|
KC2MKCAssignOne(GDK_Num_Lock, MKC_Clear);
|
|
|
|
KC2MKCAssignOne(GDK_Meta_L, MKC_formac_Command);
|
|
|
|
KC2MKCAssignOne(GDK_Meta_R, MKC_formac_RCommand);
|
|
|
|
KC2MKCAssignOne(GDK_Mode_switch, MKC_formac_Option);
|
|
KC2MKCAssignOne(GDK_Menu, MKC_formac_Option);
|
|
KC2MKCAssignOne(GDK_Super_L, MKC_formac_Option);
|
|
KC2MKCAssignOne(GDK_Super_R, MKC_formac_ROption);
|
|
KC2MKCAssignOne(GDK_Hyper_L, MKC_formac_Option);
|
|
KC2MKCAssignOne(GDK_Hyper_R, MKC_formac_ROption);
|
|
|
|
KC2MKCAssignOne(GDK_F13, MKC_formac_Option);
|
|
/*
|
|
seen being used in Mandrake Linux 9.2
|
|
for windows key
|
|
*/
|
|
|
|
KC2MKCAssignOne(GDK_Shift_L, MKC_formac_Shift);
|
|
KC2MKCAssignOne(GDK_Shift_R, MKC_formac_RShift);
|
|
|
|
KC2MKCAssignOne(GDK_Alt_L, MKC_formac_Command);
|
|
|
|
KC2MKCAssignOne(GDK_Alt_R, MKC_formac_RCommand);
|
|
|
|
KC2MKCAssignOne(GDK_Control_L, MKC_formac_Control);
|
|
|
|
KC2MKCAssignOne(GDK_Control_R, MKC_formac_RControl);
|
|
|
|
KC2MKCAssignOne(GDK_1, MKC_1);
|
|
KC2MKCAssignOne(GDK_2, MKC_2);
|
|
KC2MKCAssignOne(GDK_3, MKC_3);
|
|
KC2MKCAssignOne(GDK_4, MKC_4);
|
|
KC2MKCAssignOne(GDK_5, MKC_5);
|
|
KC2MKCAssignOne(GDK_6, MKC_6);
|
|
KC2MKCAssignOne(GDK_7, MKC_7);
|
|
KC2MKCAssignOne(GDK_8, MKC_8);
|
|
KC2MKCAssignOne(GDK_9, MKC_9);
|
|
KC2MKCAssignOne(GDK_0, MKC_0);
|
|
|
|
KC2MKCAssignOne(GDK_A, MKC_A);
|
|
KC2MKCAssignOne(GDK_B, MKC_B);
|
|
KC2MKCAssignOne(GDK_C, MKC_C);
|
|
KC2MKCAssignOne(GDK_D, MKC_D);
|
|
KC2MKCAssignOne(GDK_E, MKC_E);
|
|
KC2MKCAssignOne(GDK_F, MKC_F);
|
|
KC2MKCAssignOne(GDK_G, MKC_G);
|
|
KC2MKCAssignOne(GDK_H, MKC_H);
|
|
KC2MKCAssignOne(GDK_I, MKC_I);
|
|
KC2MKCAssignOne(GDK_J, MKC_J);
|
|
KC2MKCAssignOne(GDK_K, MKC_K);
|
|
KC2MKCAssignOne(GDK_L, MKC_L);
|
|
KC2MKCAssignOne(GDK_M, MKC_M);
|
|
KC2MKCAssignOne(GDK_N, MKC_N);
|
|
KC2MKCAssignOne(GDK_O, MKC_O);
|
|
KC2MKCAssignOne(GDK_P, MKC_P);
|
|
KC2MKCAssignOne(GDK_Q, MKC_Q);
|
|
KC2MKCAssignOne(GDK_R, MKC_R);
|
|
KC2MKCAssignOne(GDK_S, MKC_S);
|
|
KC2MKCAssignOne(GDK_T, MKC_T);
|
|
KC2MKCAssignOne(GDK_U, MKC_U);
|
|
KC2MKCAssignOne(GDK_V, MKC_V);
|
|
KC2MKCAssignOne(GDK_W, MKC_W);
|
|
KC2MKCAssignOne(GDK_X, MKC_X);
|
|
KC2MKCAssignOne(GDK_Y, MKC_Y);
|
|
KC2MKCAssignOne(GDK_Z, MKC_Z);
|
|
|
|
InitKeyCodes();
|
|
|
|
return true;
|
|
}
|
|
|
|
LOCALPROC CheckTheCapsLock(void)
|
|
{
|
|
GdkModifierType mask;
|
|
|
|
(void) gdk_window_get_pointer(window->window, NULL, NULL, &mask);
|
|
|
|
Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
|
|
(mask & GDK_LOCK_MASK) != 0);
|
|
}
|
|
|
|
LOCALPROC DoKeyCode(guint keycode, bool down)
|
|
{
|
|
if (GDK_Caps_Lock == keycode) {
|
|
CheckTheCapsLock();
|
|
} else {
|
|
uint8_t key = KC2MKC[keycode & KeyCodeMask];
|
|
|
|
if (MKC_None != key) {
|
|
Keyboard_UpdateKeyMap2(key, down);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* --- time, date, location --- */
|
|
|
|
LOCALVAR uint32_t TrueEmulatedTime = 0;
|
|
|
|
#include "UTIL/DATE2SEC.h"
|
|
|
|
#define TicksPerSecond 1000000
|
|
|
|
LOCALVAR bool HaveTimeDelta = false;
|
|
LOCALVAR uint32_t TimeDelta;
|
|
|
|
LOCALVAR uint32_t NewMacDateInSeconds;
|
|
|
|
LOCALVAR uint32_t LastTimeSec;
|
|
LOCALVAR uint32_t LastTimeUsec;
|
|
|
|
LOCALPROC GetCurrentTicks(void)
|
|
{
|
|
GTimeVal t;
|
|
|
|
g_get_current_time(&t);
|
|
if (! HaveTimeDelta) {
|
|
time_t Current_Time;
|
|
struct tm *s;
|
|
|
|
#if 0
|
|
GDate *date;
|
|
date = g_date_new();
|
|
g_date_set_time_val(date, &t);
|
|
g_date_free(date);
|
|
#endif
|
|
(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 ? */
|
|
CurMacDelta = ((uint32_t)(s->tm_gmtoff) & 0x00FFFFFF)
|
|
| ((s->tm_isdst ? 0x80 : 0) << 24);
|
|
#endif
|
|
HaveTimeDelta = true;
|
|
}
|
|
|
|
NewMacDateInSeconds = t.tv_sec + TimeDelta;
|
|
LastTimeSec = (uint32_t)t.tv_sec;
|
|
LastTimeUsec = (uint32_t)t.tv_usec;
|
|
}
|
|
|
|
#define InvTimeStep 16626 /* TicksPerSecond / 60.14742 */
|
|
|
|
LOCALVAR uint32_t NextTimeSec;
|
|
LOCALVAR uint32_t NextTimeUsec;
|
|
|
|
LOCALPROC IncrNextTime(void)
|
|
{
|
|
NextTimeUsec += InvTimeStep;
|
|
if (NextTimeUsec >= TicksPerSecond) {
|
|
NextTimeUsec -= TicksPerSecond;
|
|
NextTimeSec += 1;
|
|
}
|
|
}
|
|
|
|
LOCALPROC InitNextTime(void)
|
|
{
|
|
NextTimeSec = LastTimeSec;
|
|
NextTimeUsec = LastTimeUsec;
|
|
IncrNextTime();
|
|
}
|
|
|
|
LOCALPROC StartUpTimeAdjust(void)
|
|
{
|
|
GetCurrentTicks();
|
|
InitNextTime();
|
|
}
|
|
|
|
LOCALFUNC int32_t GetTimeDiff(void)
|
|
{
|
|
return ((int32_t)(LastTimeSec - NextTimeSec)) * TicksPerSecond
|
|
+ ((int32_t)(LastTimeUsec - NextTimeUsec));
|
|
}
|
|
|
|
LOCALPROC UpdateTrueEmulatedTime(void)
|
|
{
|
|
int32_t TimeDiff;
|
|
|
|
GetCurrentTicks();
|
|
|
|
TimeDiff = GetTimeDiff();
|
|
if (TimeDiff >= 0) {
|
|
if (TimeDiff > 4 * InvTimeStep) {
|
|
/* emulation interrupted, forget it */
|
|
++TrueEmulatedTime;
|
|
InitNextTime();
|
|
} else {
|
|
do {
|
|
++TrueEmulatedTime;
|
|
IncrNextTime();
|
|
TimeDiff -= TicksPerSecond;
|
|
} while (TimeDiff >= 0);
|
|
}
|
|
} else if (TimeDiff < - 2 * InvTimeStep) {
|
|
/* clock goofed if ever get here, reset */
|
|
InitNextTime();
|
|
}
|
|
}
|
|
|
|
LOCALFUNC bool CheckDateTime(void)
|
|
{
|
|
if (CurMacDateInSeconds != NewMacDateInSeconds) {
|
|
CurMacDateInSeconds = NewMacDateInSeconds;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
LOCALFUNC bool InitLocationDat(void)
|
|
{
|
|
GetCurrentTicks();
|
|
CurMacDateInSeconds = NewMacDateInSeconds;
|
|
|
|
return true;
|
|
}
|
|
|
|
/* --- basic dialogs --- */
|
|
|
|
LOCALPROC CheckSavedMacMsg(void)
|
|
{
|
|
if (nullpr != SavedBriefMsg) {
|
|
char briefMsg0[ClStrMaxLength + 1];
|
|
char longMsg0[ClStrMaxLength + 1];
|
|
|
|
NativeStrFromCStr(briefMsg0, SavedBriefMsg, false);
|
|
NativeStrFromCStr(longMsg0, SavedLongMsg, false);
|
|
|
|
fprintf(stderr, "%s\n", briefMsg0);
|
|
fprintf(stderr, "%s\n", longMsg0);
|
|
|
|
SavedBriefMsg = nullpr;
|
|
}
|
|
}
|
|
|
|
LOCALVAR bool CaughtMouse = false;
|
|
|
|
/* --- main window creation and disposal --- */
|
|
|
|
LOCALVAR int argc;
|
|
LOCALVAR char **argv;
|
|
|
|
/* Create a new backing pixmap of the appropriate size */
|
|
static gboolean configure_event(GtkWidget *widget,
|
|
GdkEventConfigure *event)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
/* Redraw the screen from the backing pixmap */
|
|
static gboolean expose_event(GtkWidget *widget,
|
|
GdkEventExpose *event,
|
|
gpointer user_data)
|
|
{
|
|
int x0 = event->area.x;
|
|
int y0 = event->area.y;
|
|
int x1 = x0 + event->area.width;
|
|
int y1 = y0 + event->area.height;
|
|
|
|
#if 0 && DbgEvents
|
|
fprintf(stderr, "- event - Expose\n");
|
|
#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);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean button_press_event(GtkWidget *widget,
|
|
GdkEventButton *event,
|
|
gpointer user_data)
|
|
{
|
|
MousePositionNotify(event->x, event->y);
|
|
MouseButtonSet(true);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean button_release_event(GtkWidget *widget,
|
|
GdkEventButton *event,
|
|
gpointer user_data)
|
|
{
|
|
MousePositionNotify(event->x, event->y);
|
|
MouseButtonSet(false);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean motion_notify_event(GtkWidget *widget,
|
|
GdkEventMotion *event,
|
|
gpointer user_data)
|
|
{
|
|
int x;
|
|
int y;
|
|
GdkModifierType state;
|
|
|
|
if (event->is_hint) {
|
|
gdk_window_get_pointer(event->window, &x, &y, &state);
|
|
} else {
|
|
x = event->x;
|
|
y = event->y;
|
|
state = event->state;
|
|
}
|
|
|
|
MousePositionNotify(x, y);
|
|
MouseButtonSet((state & GDK_BUTTON1_MASK) != 0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean enter_notify_event(GtkWidget *widget,
|
|
GdkEventCrossing *event,
|
|
gpointer user_data)
|
|
{
|
|
CaughtMouse = true;
|
|
|
|
MousePositionNotify(event->x, event->y);
|
|
MouseButtonSet((event->state & GDK_BUTTON1_MASK) != 0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean leave_notify_event(GtkWidget *widget,
|
|
GdkEventCrossing *event,
|
|
gpointer user_data)
|
|
{
|
|
MousePositionNotify(event->x, event->y);
|
|
MouseButtonSet((event->state & GDK_BUTTON1_MASK) != 0);
|
|
|
|
CaughtMouse = false;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean delete_event(GtkWidget *widget,
|
|
GdkEventMotion *event)
|
|
{
|
|
RequestMacOff = true;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LOCALPROC ReconnectKeyCodes3(void)
|
|
{
|
|
CheckTheCapsLock();
|
|
|
|
#if 0
|
|
if (WantCmdOptOnReconnect) {
|
|
WantCmdOptOnReconnect = false;
|
|
|
|
GetTheDownKeys();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC DisconnectKeyCodes3(void)
|
|
{
|
|
DisconnectKeyCodes2();
|
|
MouseButtonSet(false);
|
|
}
|
|
|
|
LOCALVAR bool ADialogIsUp = false;
|
|
|
|
LOCALPROC BeginDialog(void)
|
|
{
|
|
DisconnectKeyCodes3();
|
|
ADialogIsUp = true;
|
|
ForceShowCursor();
|
|
}
|
|
|
|
LOCALPROC EndDialog(void)
|
|
{
|
|
ADialogIsUp = false;
|
|
ReconnectKeyCodes3();
|
|
}
|
|
|
|
/* --- SavedTasks --- */
|
|
|
|
LOCALPROC LeaveBackground(void)
|
|
{
|
|
ReconnectKeyCodes3();
|
|
#if 0
|
|
DisableKeyRepeat();
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC EnterBackground(void)
|
|
{
|
|
#if 0
|
|
RestoreKeyRepeat();
|
|
#endif
|
|
DisconnectKeyCodes3();
|
|
|
|
ForceShowCursor();
|
|
}
|
|
|
|
LOCALPROC LeaveSpeedStopped(void)
|
|
{
|
|
StartUpTimeAdjust();
|
|
}
|
|
|
|
LOCALPROC EnterSpeedStopped(void)
|
|
{
|
|
}
|
|
|
|
static void InsertADisk0(void)
|
|
{
|
|
char ts[ClStrMaxLength + 1];
|
|
GtkWidget *dialog;
|
|
|
|
NativeStrFromCStr(ts, kStrMenuItemOpen, false);
|
|
|
|
BeginDialog();
|
|
dialog = gtk_file_chooser_dialog_new(ts,
|
|
GTK_WINDOW(window),
|
|
GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
|
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
|
NULL);
|
|
EndDialog();
|
|
|
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
|
char *filename;
|
|
|
|
filename =
|
|
gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
|
|
(void) Sony_Insert1a(filename, false);
|
|
g_free(filename);
|
|
}
|
|
|
|
gtk_widget_destroy(dialog);
|
|
}
|
|
|
|
LOCALPROC CheckForSavedTasks(void)
|
|
{
|
|
if (EvtQNeedRecover) {
|
|
EvtQNeedRecover = false;
|
|
|
|
/* attempt cleanup, EvtQNeedRecover may get set again */
|
|
EvtQTryRecoverFromFull();
|
|
}
|
|
|
|
if (RequestMacOff) {
|
|
RequestMacOff = false;
|
|
if (AnyDiskInserted()) {
|
|
MacMsgOverride(kStrQuitWarningTitle,
|
|
kStrQuitWarningMessage);
|
|
} else {
|
|
ForceMacOff = true;
|
|
}
|
|
}
|
|
|
|
if (ForceMacOff) {
|
|
return;
|
|
}
|
|
|
|
if (gTrueBackgroundFlag != gBackgroundFlag) {
|
|
gBackgroundFlag = gTrueBackgroundFlag;
|
|
if (gTrueBackgroundFlag) {
|
|
EnterBackground();
|
|
} else {
|
|
LeaveBackground();
|
|
}
|
|
}
|
|
|
|
if (CurSpeedStopped != (SpeedStopped ||
|
|
(gBackgroundFlag && ! RunInBackground)))
|
|
{
|
|
CurSpeedStopped = ! CurSpeedStopped;
|
|
if (CurSpeedStopped) {
|
|
EnterSpeedStopped();
|
|
} else {
|
|
LeaveSpeedStopped();
|
|
}
|
|
}
|
|
|
|
|
|
if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
|
|
MacMsgDisplayOn();
|
|
}
|
|
|
|
if (NeedWholeScreenDraw) {
|
|
NeedWholeScreenDraw = false;
|
|
ScreenChangedAll();
|
|
}
|
|
|
|
if (HaveCursorHidden != (WantCursorHidden && CaughtMouse
|
|
&& ! (gTrueBackgroundFlag || ADialogIsUp || CurSpeedStopped)))
|
|
{
|
|
HaveCursorHidden = ! HaveCursorHidden;
|
|
if (HaveCursorHidden) {
|
|
gdk_window_set_cursor(window->window, blank_cursor);
|
|
} else {
|
|
gdk_window_set_cursor(window->window, NULL);
|
|
}
|
|
}
|
|
|
|
if (gTrueBackgroundFlag || ADialogIsUp) {
|
|
} else {
|
|
if (RequestInsertDisk) {
|
|
RequestInsertDisk = false;
|
|
InsertADisk0();
|
|
}
|
|
}
|
|
|
|
#if NeedRequestIthDisk
|
|
if (0 != RequestIthDisk) {
|
|
Sony_InsertIth(RequestIthDisk);
|
|
RequestIthDisk = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* --- command line parsing --- */
|
|
|
|
LOCALFUNC bool ScanCommandLine(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 1; i < argc; ++i) {
|
|
if ('-' == argv[i][0]) {
|
|
#if 0
|
|
if ((0 == strcmp(argv[i], "--display")) ||
|
|
(0 == strcmp(argv[i], "-display")))
|
|
{
|
|
++i;
|
|
if (i < argc) {
|
|
display_name = argv[i];
|
|
}
|
|
} else
|
|
#endif
|
|
if ((0 == strcmp(argv[i], "--rom")) ||
|
|
(0 == strcmp(argv[i], "-r")))
|
|
{
|
|
++i;
|
|
if (i < argc) {
|
|
rom_path = argv[i];
|
|
}
|
|
} else
|
|
#if 0
|
|
if (0 == strcmp(argv[i], "-l")) {
|
|
SpeedValue = 0;
|
|
} else
|
|
#endif
|
|
{
|
|
MacMsg(kStrBadArgTitle, kStrBadArgMessage, false);
|
|
}
|
|
} else {
|
|
(void) Sony_Insert1(argv[i], false);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/* --- main program flow --- */
|
|
|
|
GLOBALOSGLUFUNC bool ExtraTimeNotOver(void)
|
|
{
|
|
UpdateTrueEmulatedTime();
|
|
return TrueEmulatedTime == OnTrueTime;
|
|
}
|
|
|
|
LOCALPROC WaitForTheNextEvent(void)
|
|
{
|
|
(void) gtk_main_iteration_do(TRUE);
|
|
}
|
|
|
|
LOCALPROC CheckForSystemEvents(void)
|
|
{
|
|
int i = 10;
|
|
|
|
while (gtk_events_pending() && (--i >= 0)) {
|
|
(void) gtk_main_iteration_do(FALSE);
|
|
}
|
|
#if 0
|
|
XFlush(x_display);
|
|
#endif
|
|
}
|
|
|
|
GLOBALOSGLUPROC WaitForNextTick(void)
|
|
{
|
|
label_retry:
|
|
CheckForSystemEvents();
|
|
CheckForSavedTasks();
|
|
if (ForceMacOff) {
|
|
return;
|
|
}
|
|
|
|
if (CurSpeedStopped) {
|
|
DoneWithDrawingForTick();
|
|
WaitForTheNextEvent();
|
|
goto label_retry;
|
|
}
|
|
|
|
if (ExtraTimeNotOver()) {
|
|
int32_t TimeDiff = GetTimeDiff();
|
|
if (TimeDiff < 0) {
|
|
g_usleep(- TimeDiff);
|
|
}
|
|
goto label_retry;
|
|
}
|
|
|
|
if (CheckDateTime()) {
|
|
}
|
|
|
|
if ((! gBackgroundFlag || ADialogIsUp)
|
|
&& (! CaughtMouse)
|
|
)
|
|
{
|
|
CheckMouseState();
|
|
}
|
|
|
|
OnTrueTime = TrueEmulatedTime;
|
|
}
|
|
|
|
#include "PROGMAIN.h"
|
|
|
|
static gboolean
|
|
MainEventLoop0(gpointer data)
|
|
{
|
|
(void) data;
|
|
fprintf(stderr, "hello from MainEventLoop0\n");
|
|
ProgramMain();
|
|
if (ForceMacOff) {
|
|
goto Label_01;
|
|
}
|
|
#if 0
|
|
while (! gtk_main_iteration_do(FALSE)) {
|
|
if (! gtk_events_pending()) {
|
|
fprintf(stderr, "sleep\n");
|
|
g_usleep(1000000);
|
|
}
|
|
}
|
|
#endif
|
|
Label_01:
|
|
fprintf(stderr, "leaving MainEventLoop0\n");
|
|
|
|
gtk_main_quit();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
focus_in_event(GtkWidget *widget, GdkEvent *event,
|
|
gpointer data)
|
|
{
|
|
gTrueBackgroundFlag = false;
|
|
|
|
CheckMouseState();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
focus_out_event(GtkWidget *widget, GdkEvent *event,
|
|
gpointer data)
|
|
{
|
|
gTrueBackgroundFlag = true;
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean key_press_event(GtkWidget *widget,
|
|
GdkEventKey *event,
|
|
gpointer user_data)
|
|
{
|
|
#if 0
|
|
fprintf(stderr, "hello from key_press_event\n");
|
|
fprintf(stderr, "keyval %d\n", event->keyval);
|
|
fprintf(stderr, "hardware_keycode %d\n", event->hardware_keycode);
|
|
#endif
|
|
#if 0
|
|
{
|
|
GdkKeymapKey *keys;
|
|
gint n_keys;
|
|
int i;
|
|
|
|
if (gdk_keymap_get_entries_for_keyval(NULL,
|
|
event->keyval, &keys, &n_keys))
|
|
{
|
|
for (i = 0; i < n_keys; i++) {
|
|
fprintf(stderr, "keycode %d\n", keys[i].keycode);
|
|
}
|
|
g_free(keys);
|
|
}
|
|
}
|
|
#endif
|
|
DoKeyCode(event->hardware_keycode, true);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean key_release_event(GtkWidget *widget,
|
|
GdkEventKey *event,
|
|
gpointer user_data)
|
|
{
|
|
#if 0
|
|
fprintf(stderr, "hello from key_release_event\n");
|
|
fprintf(stderr, "keyval %d\n", event->keyval);
|
|
fprintf(stderr, "hardware_keycode %d\n", event->hardware_keycode);
|
|
#endif
|
|
DoKeyCode(event->hardware_keycode, false);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void drag_data_received(GtkWidget *widget,
|
|
GdkDragContext *drag_context,
|
|
gint x,
|
|
gint y,
|
|
GtkSelectionData *data,
|
|
guint info,
|
|
guint time,
|
|
gpointer user_data)
|
|
{
|
|
char **uris;
|
|
char *file;
|
|
int i;
|
|
gboolean handled = FALSE;
|
|
|
|
uris = g_strsplit((char *)data->data, "\r\n", -1);
|
|
if (uris != NULL) {
|
|
for (i = 0; uris[i] != NULL; i++) {
|
|
file = g_filename_from_uri(uris[i], NULL, NULL);
|
|
/* file = gnome_vfs_get_local_path_from_uri(uris[i]); */
|
|
if (file != NULL) {
|
|
(void) Sony_Insert1a(file, false);
|
|
handled = TRUE;
|
|
g_free(file);
|
|
}
|
|
}
|
|
g_strfreev(uris);
|
|
}
|
|
gtk_drag_finish(drag_context, handled, FALSE, time);
|
|
if (handled) {
|
|
gtk_window_present_with_time(GTK_WINDOW(window), time);
|
|
}
|
|
}
|
|
|
|
static void do_more_commands_item(GtkAction *action, gpointer user_data)
|
|
{
|
|
DoMoreCommandsMsg();
|
|
}
|
|
|
|
static void do_about_item(GtkAction *action, gpointer user_data)
|
|
{
|
|
DoAboutMsg();
|
|
}
|
|
|
|
static void do_quit_item(GtkAction *action, gpointer user_data)
|
|
{
|
|
RequestMacOff = true;
|
|
}
|
|
|
|
static void do_open_item(GtkAction *action, gpointer user_data)
|
|
{
|
|
RequestInsertDisk = true;
|
|
}
|
|
|
|
LOCALPROC AppendConvertMenuItem(GtkWidget *the_menu,
|
|
GCallback c_handler, gpointer gobject, char *s, bool AddEllipsis)
|
|
{
|
|
char ts[ClStrMaxLength + 1];
|
|
GtkWidget *the_item;
|
|
|
|
NativeStrFromCStr(ts, s, AddEllipsis);
|
|
the_item = gtk_menu_item_new_with_label(ts);
|
|
g_signal_connect(G_OBJECT(the_item), "activate",
|
|
c_handler, gobject);
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(the_menu), the_item);
|
|
}
|
|
|
|
LOCALPROC AppendSubmenuConvertName(GtkWidget *menubar,
|
|
GtkWidget *the_menu, char *s)
|
|
{
|
|
char ts[ClStrMaxLength + 1];
|
|
GtkWidget *the_item;
|
|
|
|
NativeStrFromCStr(ts, s, false);
|
|
the_item = gtk_menu_item_new_with_label(ts);
|
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(the_item), the_menu);
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(menubar), the_item);
|
|
}
|
|
|
|
static GdkPixmap *blank_pixmap;
|
|
static GdkColor blank_color = {
|
|
0, 0, 0, 0
|
|
};
|
|
|
|
static gchar blank_cursor_bits[] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
static GtkTargetEntry dnd_target =
|
|
{
|
|
"text/uri-list", 0, 0
|
|
};
|
|
|
|
LOCALPROC ZapOSGLUVars(void)
|
|
{
|
|
InitDrives();
|
|
#if 0
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < kNumMagStates; ++i) {
|
|
HavePositionWins[i] = false;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
LOCALPROC ReserveAllocAll(void)
|
|
{
|
|
#if dbglog_HAVE
|
|
dbglog_ReserveAlloc();
|
|
#endif
|
|
ReserveAllocOneBlock(&ROM, kROM_Size, 5, false);
|
|
ReserveAllocOneBlock(&screencomparebuff,
|
|
vMacScreenNumBytes, 5, true);
|
|
#if UseControlKeys
|
|
ReserveAllocOneBlock(&CntrlDisplayBuff,
|
|
vMacScreenNumBytes, 5, false);
|
|
#endif
|
|
|
|
EmulationReserveAlloc();
|
|
}
|
|
|
|
LOCALFUNC bool AllocMemory(void)
|
|
{
|
|
uimr n;
|
|
bool IsOk = false;
|
|
|
|
ReserveAllocOffset = 0;
|
|
ReserveAllocBigBlock = nullpr;
|
|
ReserveAllocAll();
|
|
n = ReserveAllocOffset;
|
|
ReserveAllocBigBlock = (uint8_t *)calloc(1, n);
|
|
if (NULL == ReserveAllocBigBlock) {
|
|
MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, true);
|
|
} else {
|
|
ReserveAllocOffset = 0;
|
|
ReserveAllocAll();
|
|
if (n != ReserveAllocOffset) {
|
|
/* oops, program error */
|
|
} else {
|
|
IsOk = true;
|
|
}
|
|
}
|
|
|
|
return IsOk;
|
|
}
|
|
|
|
LOCALPROC UnallocMemory(void)
|
|
{
|
|
if (nullpr != ReserveAllocBigBlock) {
|
|
free((char *)ReserveAllocBigBlock);
|
|
}
|
|
}
|
|
|
|
LOCALFUNC bool InitOSGLU(void)
|
|
{
|
|
if (AllocMemory())
|
|
#if dbglog_HAVE
|
|
if (dbglog_open())
|
|
#endif
|
|
if (ScanCommandLine())
|
|
if (LoadMacRom())
|
|
if (LoadInitialImages())
|
|
if (InitLocationDat())
|
|
/* if (ReCreateMainWindow()) */
|
|
if (KC2MKCInit())
|
|
if (WaitForRom())
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
LOCALPROC UnInitOSGLU(void)
|
|
{
|
|
if (MacMsgDisplayed) {
|
|
MacMsgDisplayOff();
|
|
}
|
|
|
|
UnInitDrives();
|
|
|
|
ForceShowCursor();
|
|
|
|
#if dbglog_HAVE
|
|
dbglog_close();
|
|
#endif
|
|
|
|
UnallocMemory();
|
|
|
|
CheckSavedMacMsg();
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
GtkWidget *vbox;
|
|
|
|
#if 0
|
|
GtkWidget *button;
|
|
#endif
|
|
|
|
GtkWidget *menubar;
|
|
GtkWidget *the_menu;
|
|
GtkWidget *the_item;
|
|
|
|
gtk_init(&argc, &argv);
|
|
|
|
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
gtk_widget_set_name(window, "Test Input");
|
|
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
|
|
|
|
vbox = gtk_vbox_new(FALSE, 0);
|
|
gtk_container_add(GTK_CONTAINER(window), vbox);
|
|
gtk_widget_show(vbox);
|
|
|
|
g_signal_connect(G_OBJECT(window), "delete-event",
|
|
G_CALLBACK(delete_event), NULL);
|
|
g_signal_connect(G_OBJECT(window), "focus-out-event",
|
|
(GCallback)focus_out_event,
|
|
NULL);
|
|
g_signal_connect(G_OBJECT(window), "focus-in-event",
|
|
(GCallback)focus_in_event, NULL);
|
|
|
|
g_signal_connect(G_OBJECT(window), "key-press-event",
|
|
G_CALLBACK(key_press_event), NULL);
|
|
g_signal_connect(G_OBJECT(window), "key-release-event",
|
|
G_CALLBACK(key_release_event), NULL);
|
|
|
|
menubar = gtk_menu_bar_new();
|
|
|
|
the_menu = gtk_menu_new();
|
|
|
|
AppendConvertMenuItem(the_menu,
|
|
G_CALLBACK(do_open_item), NULL, kStrMenuItemOpen, true);
|
|
|
|
the_item = gtk_separator_menu_item_new();
|
|
gtk_menu_shell_append(GTK_MENU_SHELL(the_menu), the_item);
|
|
|
|
AppendConvertMenuItem(the_menu,
|
|
G_CALLBACK(do_quit_item), NULL, kStrMenuItemQuit, false);
|
|
|
|
AppendSubmenuConvertName(menubar, the_menu, kStrMenuFile);
|
|
|
|
the_menu = gtk_menu_new();
|
|
|
|
AppendConvertMenuItem(the_menu, G_CALLBACK(do_more_commands_item),
|
|
NULL, kStrMenuItemMore, true);
|
|
|
|
AppendSubmenuConvertName(menubar, the_menu, kStrMenuSpecial);
|
|
|
|
the_menu = gtk_menu_new();
|
|
|
|
AppendConvertMenuItem(the_menu,
|
|
G_CALLBACK(do_about_item), NULL, kStrMenuItemAbout, true);
|
|
|
|
AppendSubmenuConvertName(menubar, the_menu, kStrMenuHelp);
|
|
|
|
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show_all(menubar);
|
|
|
|
|
|
/* Create the drawing area */
|
|
|
|
drawing_area = gtk_drawing_area_new();
|
|
gtk_widget_set_size_request(GTK_WIDGET(drawing_area),
|
|
vMacScreenWidth, vMacScreenHeight);
|
|
gtk_box_pack_start(GTK_BOX(vbox), drawing_area, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show(drawing_area);
|
|
|
|
/* Signals used to handle backing pixmap */
|
|
|
|
g_signal_connect(G_OBJECT(drawing_area), "expose-event",
|
|
G_CALLBACK(expose_event), NULL);
|
|
g_signal_connect(G_OBJECT(drawing_area), "configure-event",
|
|
G_CALLBACK(configure_event), NULL);
|
|
|
|
/* Event signals */
|
|
|
|
g_signal_connect(G_OBJECT(drawing_area), "motion-notify-event",
|
|
G_CALLBACK(motion_notify_event), NULL);
|
|
g_signal_connect(G_OBJECT(drawing_area), "enter-notify-event",
|
|
G_CALLBACK(enter_notify_event), NULL);
|
|
g_signal_connect(G_OBJECT(drawing_area), "leave-notify-event",
|
|
G_CALLBACK(leave_notify_event), NULL);
|
|
|
|
g_signal_connect(G_OBJECT(drawing_area), "button-press-event",
|
|
G_CALLBACK(button_press_event), NULL);
|
|
g_signal_connect(G_OBJECT(drawing_area), "button-release-event",
|
|
G_CALLBACK(button_release_event), NULL);
|
|
|
|
gtk_widget_add_events(window,
|
|
GDK_KEY_PRESS_MASK
|
|
| GDK_KEY_RELEASE_MASK
|
|
);
|
|
|
|
gtk_widget_set_events(drawing_area, GDK_EXPOSURE_MASK
|
|
| GDK_LEAVE_NOTIFY_MASK
|
|
| GDK_BUTTON_PRESS_MASK
|
|
| GDK_BUTTON_RELEASE_MASK
|
|
| GDK_POINTER_MOTION_MASK
|
|
| GDK_ENTER_NOTIFY_MASK
|
|
| GDK_LEAVE_NOTIFY_MASK
|
|
| GDK_FOCUS_CHANGE_MASK
|
|
| GDK_KEY_PRESS_MASK
|
|
| GDK_KEY_RELEASE_MASK
|
|
/* | GDK_POINTER_MOTION_HINT_MASK */
|
|
);
|
|
|
|
#if 0
|
|
/* .. And a quit button */
|
|
button = gtk_button_new_with_label("Quit");
|
|
gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
|
|
|
|
g_signal_connect_swapped(G_OBJECT(button), "clicked",
|
|
G_CALLBACK(delete_event), NULL
|
|
/*
|
|
G_CALLBACK(gtk_widget_destroy),
|
|
G_OBJECT(window)
|
|
*/
|
|
);
|
|
gtk_widget_show(button);
|
|
#endif
|
|
|
|
gtk_drag_dest_set(drawing_area, GTK_DEST_DEFAULT_ALL,
|
|
&dnd_target, 1,
|
|
GDK_ACTION_COPY);
|
|
g_signal_connect(GTK_OBJECT(drawing_area), "drag-data-received",
|
|
G_CALLBACK(drag_data_received), NULL);
|
|
|
|
gtk_widget_show(window);
|
|
|
|
blank_pixmap = gdk_bitmap_create_from_data(NULL,
|
|
blank_cursor_bits, 16, 16);
|
|
blank_cursor = gdk_cursor_new_from_pixmap(blank_pixmap,
|
|
blank_pixmap, &blank_color, &blank_color, 8, 8);
|
|
gdk_pixmap_unref(blank_pixmap);
|
|
|
|
gdk_window_set_cursor(window->window, blank_cursor);
|
|
|
|
g_idle_add(MainEventLoop0, NULL);
|
|
|
|
argc = argc;
|
|
argv = argv;
|
|
|
|
ZapOSGLUVars();
|
|
if (InitOSGLU()) {
|
|
gtk_main ();
|
|
}
|
|
UnInitOSGLU();
|
|
|
|
return 0;
|
|
}
|