summaryrefslogtreecommitdiff
path: root/emu/MacOSX
diff options
context:
space:
mode:
Diffstat (limited to 'emu/MacOSX')
-rw-r--r--emu/MacOSX/keycodes.h189
-rw-r--r--emu/MacOSX/mkfile-a64
-rw-r--r--emu/MacOSX/win.c641
3 files changed, 894 insertions, 0 deletions
diff --git a/emu/MacOSX/keycodes.h b/emu/MacOSX/keycodes.h
new file mode 100644
index 00000000..52328ace
--- /dev/null
+++ b/emu/MacOSX/keycodes.h
@@ -0,0 +1,189 @@
+/* These are the Macintosh key scancode constants -- from Inside Macintosh */
+#define QZ_ESCAPE 0x35
+#define QZ_F1 0x7A
+#define QZ_F2 0x78
+#define QZ_F3 0x63
+#define QZ_F4 0x76
+#define QZ_F5 0x60
+#define QZ_F6 0x61
+#define QZ_F7 0x62
+#define QZ_F8 0x64
+#define QZ_F9 0x65
+#define QZ_F10 0x6D
+#define QZ_F11 0x67
+#define QZ_F12 0x6F
+#define QZ_PRINT 0x69
+#define QZ_SCROLLOCK 0x6B
+#define QZ_PAUSE 0x71
+#define QZ_POWER 0x7F
+#define QZ_BACKQUOTE 0x32
+#define QZ_1 0x12
+#define QZ_2 0x13
+#define QZ_3 0x14
+#define QZ_4 0x15
+#define QZ_5 0x17
+#define QZ_6 0x16
+#define QZ_7 0x1A
+#define QZ_8 0x1C
+#define QZ_9 0x19
+#define QZ_0 0x1D
+#define QZ_MINUS 0x1B
+#define QZ_EQUALS 0x18
+#define QZ_BACKSPACE 0x33
+#define QZ_INSERT 0x72
+#define QZ_HOME 0x73
+#define QZ_PAGEUP 0x74
+#define QZ_NUMLOCK 0x47
+#define QZ_KP_EQUALS 0x51
+#define QZ_KP_DIVIDE 0x4B
+#define QZ_KP_MULTIPLY 0x43
+#define QZ_TAB 0x30
+#define QZ_q 0x0C
+#define QZ_w 0x0D
+#define QZ_e 0x0E
+#define QZ_r 0x0F
+#define QZ_t 0x11
+#define QZ_y 0x10
+#define QZ_u 0x20
+#define QZ_i 0x22
+#define QZ_o 0x1F
+#define QZ_p 0x23
+#define QZ_LEFTBRACKET 0x21
+#define QZ_RIGHTBRACKET 0x1E
+#define QZ_BACKSLASH 0x2A
+#define QZ_DELETE 0x75
+#define QZ_END 0x77
+#define QZ_PAGEDOWN 0x79
+#define QZ_KP7 0x59
+#define QZ_KP8 0x5B
+#define QZ_KP9 0x5C
+#define QZ_KP_MINUS 0x4E
+#define QZ_CAPSLOCK 0x39
+#define QZ_a 0x00
+#define QZ_s 0x01
+#define QZ_d 0x02
+#define QZ_f 0x03
+#define QZ_g 0x05
+#define QZ_h 0x04
+#define QZ_j 0x26
+#define QZ_k 0x28
+#define QZ_l 0x25
+#define QZ_SEMICOLON 0x29
+#define QZ_QUOTE 0x27
+#define QZ_RETURN 0x24
+#define QZ_KP4 0x56
+#define QZ_KP5 0x57
+#define QZ_KP6 0x58
+#define QZ_KP_PLUS 0x45
+#define QZ_LSHIFT 0x38
+#define QZ_z 0x06
+#define QZ_x 0x07
+#define QZ_c 0x08
+#define QZ_v 0x09
+#define QZ_b 0x0B
+#define QZ_n 0x2D
+#define QZ_m 0x2E
+#define QZ_COMMA 0x2B
+#define QZ_PERIOD 0x2F
+#define QZ_SLASH 0x2C
+/* These are the same as the left versions - use left by default */
+#if 0
+#define QZ_RSHIFT 0x38
+#endif
+#define QZ_UP 0x7E
+#define QZ_KP1 0x53
+#define QZ_KP2 0x54
+#define QZ_KP3 0x55
+#define QZ_KP_ENTER 0x4C
+#define QZ_LCTRL 0x3B
+#define QZ_LALT 0x3A
+#define QZ_LMETA 0x37
+#define QZ_SPACE 0x31
+/* These are the same as the left versions - use left by default */
+#if 0
+#define QZ_RMETA 0x37
+#define QZ_RALT 0x3A
+#define QZ_RCTRL 0x3B
+#endif
+#define QZ_LEFT 0x7B
+#define QZ_DOWN 0x7D
+#define QZ_RIGHT 0x7C
+#define QZ_KP0 0x52
+#define QZ_KP_PERIOD 0x41
+
+/* Wierd, these keys are on my iBook under MacOS X */
+#define QZ_IBOOK_ENTER 0x34
+#define QZ_IBOOK_LEFT 0x3B
+#define QZ_IBOOK_RIGHT 0x3C
+#define QZ_IBOOK_DOWN 0x3D
+#define QZ_IBOOK_UP 0x3E
+#define KEY_ENTER 13
+#define KEY_TAB 9
+
+#define KEY_BASE 0x100
+
+/* Function keys */
+#define KEY_F (KEY_BASE+64)
+
+/* Control keys */
+#define KEY_CTRL (KEY_BASE)
+#define KEY_BACKSPACE (KEY_CTRL+0)
+#define KEY_DELETE (KEY_CTRL+1)
+#define KEY_INSERT (KEY_CTRL+2)
+#define KEY_HOME (KEY_CTRL+3)
+#define KEY_END (KEY_CTRL+4)
+#define KEY_PAGE_UP (KEY_CTRL+5)
+#define KEY_PAGE_DOWN (KEY_CTRL+6)
+#define KEY_ESC (KEY_CTRL+7)
+
+/* Control keys short name */
+#define KEY_BS KEY_BACKSPACE
+#define KEY_DEL KEY_DELETE
+#define KEY_INS KEY_INSERT
+#define KEY_PGUP KEY_PAGE_UP
+#define KEY_PGDOWN KEY_PAGE_DOWN
+#define KEY_PGDWN KEY_PAGE_DOWN
+
+/* Cursor movement */
+#define KEY_CRSR (KEY_BASE+16)
+#define KEY_RIGHT (KEY_CRSR+0)
+#define KEY_LEFT (KEY_CRSR+1)
+#define KEY_DOWN (KEY_CRSR+2)
+#define KEY_UP (KEY_CRSR+3)
+
+/* Multimedia keyboard/remote keys */
+#define KEY_MM_BASE (0x100+384)
+#define KEY_POWER (KEY_MM_BASE+0)
+#define KEY_MENU (KEY_MM_BASE+1)
+#define KEY_PLAY (KEY_MM_BASE+2)
+#define KEY_PAUSE (KEY_MM_BASE+3)
+#define KEY_PLAYPAUSE (KEY_MM_BASE+4)
+#define KEY_STOP (KEY_MM_BASE+5)
+#define KEY_FORWARD (KEY_MM_BASE+6)
+#define KEY_REWIND (KEY_MM_BASE+7)
+#define KEY_NEXT (KEY_MM_BASE+8)
+#define KEY_PREV (KEY_MM_BASE+9)
+#define KEY_VOLUME_UP (KEY_MM_BASE+10)
+#define KEY_VOLUME_DOWN (KEY_MM_BASE+11)
+#define KEY_MUTE (KEY_MM_BASE+12)
+
+/* Keypad keys */
+#define KEY_KEYPAD (KEY_BASE+32)
+#define KEY_KP0 (KEY_KEYPAD+0)
+#define KEY_KP1 (KEY_KEYPAD+1)
+#define KEY_KP2 (KEY_KEYPAD+2)
+#define KEY_KP3 (KEY_KEYPAD+3)
+#define KEY_KP4 (KEY_KEYPAD+4)
+#define KEY_KP5 (KEY_KEYPAD+5)
+#define KEY_KP6 (KEY_KEYPAD+6)
+#define KEY_KP7 (KEY_KEYPAD+7)
+#define KEY_KP8 (KEY_KEYPAD+8)
+#define KEY_KP9 (KEY_KEYPAD+9)
+#define KEY_KPDEC (KEY_KEYPAD+10)
+#define KEY_KPINS (KEY_KEYPAD+11)
+#define KEY_KPDEL (KEY_KEYPAD+12)
+#define KEY_KPENTER (KEY_KEYPAD+13)
+
+/* Special keys */
+#define KEY_INTERN (0x1000)
+#define KEY_CLOSE_WIN (KEY_INTERN+0)
diff --git a/emu/MacOSX/mkfile-a b/emu/MacOSX/mkfile-a
new file mode 100644
index 00000000..b077d95c
--- /dev/null
+++ b/emu/MacOSX/mkfile-a
@@ -0,0 +1,64 @@
+SYSTARG=MacOSX
+#OBJTYPE=power
+<../../mkconfig
+SYSTARG=MacOSX
+#OBJTYPE=power
+
+#Configurable parameters
+
+CONF=emu #default configuration
+CONFLIST=emu
+CLEANCONFLIST=
+
+INSTALLDIR=$ROOT/$SYSTARG/$OBJTYPE/bin #path of directory where kernel is installed
+
+#end configurable parameters
+
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE #set vars based on target system
+
+<| $SHELLNAME ../port/mkdevlist $CONF #sets $IP, $DEVS, $PORT, $LIBS
+
+OBJ=\
+ asm-$OBJTYPE.$O\
+ os.$O\
+ win.$O\
+ $CONF.root.$O\
+ lock.$O\
+ $DEVS\
+ $PORT\
+
+HFILES=\
+
+CFLAGS='-DROOT="'$ROOT'"'\
+ '-DOBJTYPE="'$OBJTYPE'"'\
+ -DEMU -I. -I../port\
+ -I$ROOT/$SYSTARG/$OBJTYPE/include\
+ -I$ROOT/include -I$ROOT/libinterp\
+ $CTHREADFLAGS $CFLAGS $EMUOPTIONS\
+
+KERNDATE=`{$NDATE}
+
+LDFLAGS=$LDFLAGS -L/usr/X11R6/lib
+
+SYSLIBS= \
+ -lm\
+ -framework Carbon -framework QuickTime\
+ -lpthread\
+ -framework CoreFoundation\
+ -framework IOKit\
+# -framework ApplicationServices\
+
+default:V: $O.$CONF
+
+
+$O.$CONF: $OBJ $CONF.c $CONF.root.h $LIBFILES
+ $CC $CFLAGS -DKERNDATE=$KERNDATE $CONF.c
+ $LD $LDFLAGS -o $target $OBJ $CONF.$O $LIBFILES $SYSLIBS
+
+install:V: $O.$CONF
+ cp $O.$CONF $INSTALLDIR/$CONF
+
+<../port/portmkfile
+
+ipif.c:N: ../FreeBSD/ipif.c
+devfs.c:N: ../port/devfs-posix.c
diff --git a/emu/MacOSX/win.c b/emu/MacOSX/win.c
new file mode 100644
index 00000000..da544014
--- /dev/null
+++ b/emu/MacOSX/win.c
@@ -0,0 +1,641 @@
+// in this file, _Rect is os x Rect,
+// _Point is os x Point
+#define Point _Point
+#define Rect _Rect
+
+#include <Carbon/Carbon.h>
+#include <QuickTime/QuickTime.h> // for full screen
+
+#undef Rect
+#undef Point
+
+#undef nil
+
+#include "dat.h"
+#include "fns.h"
+#undef log2
+#include <draw.h>
+#include <memdraw.h>
+#include "cursor.h"
+#include "keyboard.h"
+#include "keycodes.h"
+
+#define Kup Up
+#define Kleft Left
+#define Kdown Down
+#define Kright Right
+#define Kalt LAlt
+#define Kctl LCtrl
+#define Kshift LShift
+#define Kpgup Pgup
+#define Kpgdown Pgdown
+#define Khome Home
+#define Kins Ins
+#define Kend End
+
+#define rWindowResource 128
+
+extern void flushmemscreen(Rectangle);
+
+Memimage *gscreen;
+//Screeninfo screen;
+
+static int readybit;
+static Rendez rend;
+static int triedscreen;
+
+///
+// menu
+//
+static MenuRef windMenu;
+static MenuRef viewMenu;
+
+enum {
+ kQuitCmd = 1,
+ kFullScreenCmd = 2,
+};
+
+static WindowGroupRef winGroup = NULL;
+static WindowRef theWindow = NULL;
+static CGContextRef context;
+static CGDataProviderRef dataProviderRef;
+static CGImageRef fullScreenImage;
+static CGRect devRect;
+static CGRect bounds;
+static PasteboardRef appleclip;
+static _Rect winRect;
+
+
+static int
+isready(void*a)
+{
+ return readybit;
+}
+
+CGContextRef QuartzContext;
+
+void winproc(void *a);
+
+void
+screeninit(void)
+{
+ int fmt;
+ int dx, dy;
+ ProcessSerialNumber psn = { 0, kCurrentProcess };
+ TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+ SetFrontProcess(&psn);
+
+ fmt = XBGR32; //XRGB32;
+
+ devRect = CGDisplayBounds(CGMainDisplayID());
+// devRect.origin.x = 0;
+// devRect.origin.y = 0;
+// devRect.size.width = 1024;
+// devRect.size.height = 768;
+ dx = devRect.size.width;
+ dy = devRect.size.height;
+
+ if(1){ /* TO DO: new dev draw for changing screen size */
+ dx = Xsize;
+ dy = Ysize;
+ }
+
+ gscreen = allocmemimage(Rect(0,0,dx,dy), fmt);
+ dataProviderRef = CGDataProviderCreateWithData(0, gscreen->data->bdata,
+ dx * dy * 4, 0);
+ fullScreenImage = CGImageCreate(dx, dy, 8, 32, dx * 4,
+ CGColorSpaceCreateDeviceRGB(),
+ kCGImageAlphaNoneSkipLast,
+ dataProviderRef, 0, 0, kCGRenderingIntentDefault);
+
+ kproc("osxscreen", winproc, nil, 0);
+ Sleep(&rend, isready, nil);
+}
+
+static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
+static OSStatus MainWindowCommandHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
+
+void
+window_resized(void)
+{
+ GetWindowBounds(theWindow, kWindowContentRgn, &winRect );
+
+ bounds = CGRectMake(0, 0, winRect.right-winRect.left, winRect.bottom - winRect.top);
+}
+
+
+void
+winproc(void *a)
+{
+ MenuItemIndex index;
+ int dx, dy;
+
+ winRect.left = 30;
+ winRect.top = 60;
+ dx = devRect.size.width*0.75; /* devRect is full screen; take only most of it */
+ dy = devRect.size.height*0.75;
+ if(1){ /* TO DO */
+ dx = Xsize;
+ dy = Ysize;
+ }
+ winRect.bottom = winRect.top + dy;
+ winRect.right = winRect.left + dx;
+
+ ClearMenuBar();
+ InitCursor();
+
+ CreateStandardWindowMenu(0, &windMenu);
+ InsertMenu(windMenu, 0);
+
+ CreateNewMenu(1004, 0, &viewMenu);
+ SetMenuTitleWithCFString(viewMenu, CFSTR("View"));
+ AppendMenuItemTextWithCFString(viewMenu, CFSTR("Full Screen"), 0,
+ kFullScreenCmd, &index);
+ SetMenuItemCommandKey(viewMenu, index, 0, 'F');
+ AppendMenuItemTextWithCFString(viewMenu, CFSTR("ctrl-opt to return"),
+ kMenuItemAttrDisabled,
+ kFullScreenCmd, &index);
+ InsertMenu(viewMenu, GetMenuID(windMenu));
+
+ DrawMenuBar();
+ uint32_t windowAttrs = 0
+ | kWindowCloseBoxAttribute
+ | kWindowCollapseBoxAttribute
+// | kWindowResizableAttribute // TO DO
+ | kWindowStandardHandlerAttribute
+// | kWindowFullZoomAttribute // TO DO
+ ;
+
+ CreateNewWindow(kDocumentWindowClass, windowAttrs, &winRect, &theWindow);
+ CreateWindowGroup(0, &winGroup);
+ SetWindowGroup(theWindow, winGroup);
+
+ SetWindowTitleWithCFString(theWindow, CFSTR("Inferno"));
+
+ if(PasteboardCreate(kPasteboardClipboard, &appleclip) != noErr)
+ sysfatal("pasteboard create failed");
+
+ const EventTypeSpec commands[] = {
+ { kEventClassWindow, kEventWindowClosed },
+ { kEventClassWindow, kEventWindowBoundsChanged },
+ { kEventClassCommand, kEventCommandProcess }
+ };
+ const EventTypeSpec events[] = {
+ { kEventClassKeyboard, kEventRawKeyDown },
+ { kEventClassKeyboard, kEventRawKeyModifiersChanged },
+ { kEventClassKeyboard, kEventRawKeyRepeat },
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseUp },
+ { kEventClassMouse, kEventMouseMoved },
+ { kEventClassMouse, kEventMouseDragged },
+ { kEventClassMouse, kEventMouseWheelMoved },
+ };
+
+ InstallApplicationEventHandler (
+ NewEventHandlerUPP (MainWindowEventHandler),
+ GetEventTypeCount(events),
+ events,
+ NULL,
+ NULL);
+ InstallWindowEventHandler (
+ theWindow,
+ NewEventHandlerUPP (MainWindowCommandHandler),
+ GetEventTypeCount(commands),
+ commands,
+ theWindow,
+ NULL);
+
+ ShowWindow(theWindow);
+ ShowMenuBar();
+ window_resized();
+ SelectWindow(theWindow);
+// terminit();
+ // Run the event loop
+ readybit = 1;
+ Wakeup(&rend);
+ RunApplicationEventLoop();
+
+}
+
+static int
+convert_key(UInt32 key, UInt32 charcode)
+{
+ switch(key) {
+ case QZ_IBOOK_ENTER:
+ case QZ_RETURN: return '\n';
+ case QZ_ESCAPE: return 27;
+ case QZ_BACKSPACE: return '\b';
+ case QZ_LALT: return Kalt;
+ case QZ_LCTRL: return Kctl;
+ case QZ_LSHIFT: return Kshift;
+ case QZ_F1: return KF+1;
+ case QZ_F2: return KF+2;
+ case QZ_F3: return KF+3;
+ case QZ_F4: return KF+4;
+ case QZ_F5: return KF+5;
+ case QZ_F6: return KF+6;
+ case QZ_F7: return KF+7;
+ case QZ_F8: return KF+8;
+ case QZ_F9: return KF+9;
+ case QZ_F10: return KF+10;
+ case QZ_F11: return KF+11;
+ case QZ_F12: return KF+12;
+ case QZ_INSERT: return Kins;
+ case QZ_DELETE: return '0';
+ case QZ_HOME: return Khome;
+ case QZ_END: return Kend;
+ case QZ_KP_PLUS: return '+';
+ case QZ_KP_MINUS: return '-';
+ case QZ_TAB: return '\t';
+ case QZ_PAGEUP: return Kpgup;
+ case QZ_PAGEDOWN: return Kpgdown;
+ case QZ_UP: return Kup;
+ case QZ_DOWN: return Kdown;
+ case QZ_LEFT: return Kleft;
+ case QZ_RIGHT: return Kright;
+ case QZ_KP_MULTIPLY: return '*';
+ case QZ_KP_DIVIDE: return '/';
+ case QZ_KP_ENTER: return '\b';
+ case QZ_KP_PERIOD: return '.';
+ case QZ_KP0: return '0';
+ case QZ_KP1: return '1';
+ case QZ_KP2: return '2';
+ case QZ_KP3: return '3';
+ case QZ_KP4: return '4';
+ case QZ_KP5: return '5';
+ case QZ_KP6: return '6';
+ case QZ_KP7: return '7';
+ case QZ_KP8: return '8';
+ case QZ_KP9: return '9';
+ default: return charcode;
+ }
+}
+
+void
+sendbuttons(int b, int x, int y)
+{
+ /* TO DO: add special keyboard characters as mouse buttons */
+ mousetrack(b, x, y, 0);
+}
+
+static Ptr fullScreenRestore;
+static int amFullScreen = 0;
+static WindowRef oldWindow = NULL;
+
+static void
+leave_full_screen(void)
+{
+ if (0 && amFullScreen) {
+ EndFullScreen(fullScreenRestore, 0);
+ theWindow = oldWindow;
+ ShowWindow(theWindow);
+ amFullScreen = 0;
+ window_resized();
+ Rectangle rect = { { 0, 0 }, { bounds.size.width, bounds.size.height} };
+ drawqlock();
+ flushmemscreen(rect);
+ drawqunlock();
+ }
+}
+
+static void
+full_screen(void)
+{
+ if (0 && !amFullScreen) {
+ oldWindow = theWindow;
+ HideWindow(theWindow);
+ BeginFullScreen(&fullScreenRestore, 0, 0, 0, &theWindow, 0, 0);
+ amFullScreen = 1;
+ window_resized();
+ Rectangle rect = { { 0, 0 }, { bounds.size.width, bounds.size.height} };
+ drawqlock();
+ flushmemscreen(rect);
+ drawqunlock();
+ }
+}
+
+static OSStatus
+MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
+{
+ OSStatus result = noErr;
+ result = CallNextEventHandler(nextHandler, event);
+ UInt32 class = GetEventClass (event);
+ UInt32 kind = GetEventKind (event);
+ if(class == kEventClassKeyboard) {
+ char macCharCodes;
+ UInt32 macKeyCode;
+ UInt32 macKeyModifiers;
+
+ GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar,
+ NULL, sizeof(macCharCodes), NULL, &macCharCodes);
+ GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL,
+ sizeof(macKeyCode), NULL, &macKeyCode);
+ GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL,
+ sizeof(macKeyModifiers), NULL, &macKeyModifiers);
+ switch(kind) {
+ case kEventRawKeyModifiersChanged:
+ if ( macKeyModifiers == 0x1800 ) leave_full_screen();
+ break;
+ case kEventRawKeyDown:
+ case kEventRawKeyRepeat: {
+ if(macKeyModifiers != 256) {
+ if (kind == kEventRawKeyRepeat || kind == kEventRawKeyDown) {
+ int key = convert_key(macKeyCode, macCharCodes);
+ if(key != -1)
+ gkbdputc(gkbdq, key);
+if(0 && key != -1)fprint(2, "[%C]", key);
+ }
+ }
+ else
+ result = eventNotHandledErr;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else if(class == kEventClassMouse) {
+ _Point mousePos;
+
+ GetEventParameter(event, kEventParamMouseLocation, typeQDPoint,
+ 0, sizeof mousePos, 0, &mousePos);
+
+ static uint32_t mousebuttons = 0; // bitmask of buttons currently down
+
+ switch (kind) {
+ case kEventMouseWheelMoved: {
+ int32_t wheeldelta;
+ GetEventParameter(event,kEventParamMouseWheelDelta,typeLongInteger,
+ 0,sizeof(EventMouseButton), 0, &wheeldelta);
+ sendbuttons((int16_t)wheeldelta>0 ? 8 : 16,
+ mousePos.h - winRect.left,
+ mousePos.v - winRect.top);
+ break;
+ }
+ case kEventMouseUp:
+ case kEventMouseDown: {
+ uint32_t buttons;
+ GetEventParameter(event, kEventParamMouseChord,
+ typeUInt32, 0, sizeof buttons, 0, &buttons);
+ mousebuttons = (buttons & 1)
+ | ((buttons & 2)<<1)
+ | ((buttons & 4)>>1);
+ } /* Fallthrough */
+ case kEventMouseMoved:
+ case kEventMouseDragged: {
+ sendbuttons(mousebuttons,
+ mousePos.h - winRect.left,
+ mousePos.v - winRect.top);
+ }
+ break;
+
+ default:result = eventNotHandledErr;break;
+ }
+ }
+ return result;
+}
+
+//default window command handler (from menus)
+static OSStatus
+MainWindowCommandHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
+{
+ OSStatus result = noErr;
+ UInt32 class = GetEventClass (event);
+ UInt32 kind = GetEventKind (event);
+
+ result = CallNextEventHandler(nextHandler, event);
+
+ if(class == kEventClassCommand){
+ HICommand theHICommand;
+ GetEventParameter( event, kEventParamDirectObject, typeHICommand,
+ NULL, sizeof( HICommand ), NULL, &theHICommand );
+
+ switch ( theHICommand.commandID ){
+ case kHICommandQuit:
+ cleanexit(0);
+ break;
+
+ case kFullScreenCmd:
+ full_screen();
+ break;
+
+ default:
+ result = eventNotHandledErr;
+ break;
+ }
+ }
+ else if(class == kEventClassWindow){
+ WindowRef window;
+ _Rect rectPort = {0,0,0,0};
+
+ GetEventParameter(event, kEventParamDirectObject, typeWindowRef,
+ NULL, sizeof(WindowRef), NULL, &window);
+
+ if(window)
+ GetPortBounds(GetWindowPort(window), &rectPort);
+
+ switch (kind){
+ case kEventWindowClosed:
+ theWindow = NULL;
+ cleanexit(0); // only one window
+ break;
+
+ //resize window
+ case kEventWindowBoundsChanged:
+ window_resized();
+ Rectangle rect = { { 0, 0 },
+ { bounds.size.width,
+ bounds.size.height} };
+ drawqlock();
+ flushmemscreen(rect);
+ drawqunlock();
+ break;
+
+ default:
+ result = eventNotHandledErr;
+ break;
+ }
+ }
+
+ return result;
+}
+
+void
+flushmemscreen(Rectangle r)
+{
+ CGRect rbounds;
+
+ // sanity check. Trips from the initial "terminal"
+ if (r.max.x < r.min.x || r.max.y < r.min.y)
+ return;
+
+ rbounds.size.width = r.max.x - r.min.x;
+ rbounds.size.height = r.max.y - r.min.y;
+ rbounds.origin.x = r.min.x;
+ rbounds.origin.y = r.min.y;
+
+ if(rbounds.size.width <= 0 || rbounds.size.height <= 0)
+ return;
+
+ QDBeginCGContext( GetWindowPort(theWindow), &context);
+
+ // The sub-image is relative to our whole screen image.
+ CGImageRef subimg = CGImageCreateWithImageInRect(fullScreenImage, rbounds);
+
+ // Drawing the sub-image is relative to the window.
+ rbounds.origin.y = winRect.bottom - winRect.top - r.min.y - rbounds.size.height;
+ CGContextDrawImage(context, rbounds, subimg);
+ CGContextFlush(context);
+ CGImageRelease(subimg);
+ QDEndCGContext( GetWindowPort(theWindow), &context);
+}
+
+uchar*
+attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen)
+{
+ if(!triedscreen){
+ triedscreen = 1;
+ screeninit(); /* TO DO: call this elsewhere? */
+ }
+ *r = gscreen->r;
+ *chan = gscreen->chan;
+ *depth = gscreen->depth;
+ *width = gscreen->width;
+ *softscreen = 1;
+
+ return gscreen->data->bdata;
+}
+
+// PAL - no palette handling. Don't intend to either.
+void
+getcolor(ulong i, ulong *r, ulong *g, ulong *b)
+{
+
+// PAL: Certainly wrong to return a grayscale.
+ *r = i;
+ *g = i;
+ *b = i;
+}
+
+void
+setcolor(ulong index, ulong r, ulong g, ulong b)
+{
+ USED(index); USED(r); USED(g); USED(b);
+}
+
+enum{
+ SnarfSize= 100*1024
+};
+
+
+static char snarf[3*SnarfSize+1];
+static Rune rsnarf[SnarfSize+1];
+
+char*
+clipread(void)
+{
+ CFDataRef cfdata;
+ OSStatus err = noErr;
+ ItemCount nItems;
+ int i;
+ char *s;
+
+ // Wow. This is ridiculously complicated.
+ PasteboardSynchronize(appleclip);
+ if((err = PasteboardGetItemCount(appleclip, &nItems)) != noErr) {
+ fprint(2, "apple pasteboard GetItemCount failed - Error %d\n", err);
+ return 0;
+ }
+
+ // Yes, based at 1. Silly API.
+ for(i = 1; i <= nItems; i++) {
+ PasteboardItemID itemID;
+ CFArrayRef flavorTypeArray;
+ CFIndex flavorCount;
+
+ if((err = PasteboardGetItemIdentifier(appleclip, i, &itemID)) != noErr){
+ fprint(2, "Can't get pasteboard item identifier: %d\n", err);
+ return 0;
+ }
+
+ if((err = PasteboardCopyItemFlavors(appleclip, itemID, &flavorTypeArray))!=noErr){
+ fprint(2, "Can't copy pasteboard item flavors: %d\n", err);
+ return 0;
+ }
+
+ flavorCount = CFArrayGetCount(flavorTypeArray);
+ CFIndex flavorIndex;
+ for(flavorIndex = 0; flavorIndex < flavorCount; ++flavorIndex){
+ CFStringRef flavorType;
+ flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex);
+ if (UTTypeConformsTo(flavorType, CFSTR("public.utf16-plain-text"))){
+ if((err = PasteboardCopyItemFlavorData(appleclip, itemID,
+ CFSTR("public.utf16-plain-text"), &cfdata)) != noErr){
+ fprint(2, "apple pasteboard CopyItem failed - Error %d\n", err);
+ return 0;
+ }
+ CFIndex length = CFDataGetLength(cfdata);
+ if (length > sizeof rsnarf) length = sizeof rsnarf;
+ CFDataGetBytes(cfdata, CFRangeMake(0, length), (uint8_t *)rsnarf);
+ snprint(snarf, sizeof snarf, "%S", rsnarf);
+ for(s = snarf; *s; s++)
+ if(*s == '\r')
+ *s = '\n';
+ CFRelease(cfdata);
+ return strdup(snarf);
+ }
+ }
+ }
+ return 0;
+}
+
+// TO DO: check that the return value is correct
+int
+clipwrite(char *snarf)
+{
+ CFDataRef cfdata;
+ PasteboardSyncFlags flags;
+
+ runeseprint(rsnarf, rsnarf+nelem(rsnarf), "%s", snarf);
+ if(PasteboardClear(appleclip) != noErr){
+ fprint(2, "apple pasteboard clear failed\n");
+ return 0;
+ }
+ flags = PasteboardSynchronize(appleclip);
+ if((flags&kPasteboardModified) || !(flags&kPasteboardClientIsOwner)){
+ fprint(2, "apple pasteboard cannot assert ownership\n");
+ return 0;
+ }
+ cfdata = CFDataCreate(kCFAllocatorDefault, (uchar*)rsnarf, runestrlen(rsnarf)*2);
+ if(cfdata == nil){
+ fprint(2, "apple pasteboard cfdatacreate failed\n");
+ return 0;
+ }
+ if(PasteboardPutItemFlavor(appleclip, (PasteboardItemID)1,
+ CFSTR("public.utf16-plain-text"), cfdata, 0) != noErr){
+ fprint(2, "apple pasteboard putitem failed\n");
+ CFRelease(cfdata);
+ return 0;
+ }
+ CFRelease(cfdata);
+ return 1;
+}
+
+void
+setpointer(int x, int y)
+{
+ CGPoint pnt;
+
+ pnt.x = x + winRect.left;
+ pnt.y = y + winRect.top;
+ CGWarpMouseCursorPosition(pnt);
+}
+
+void
+drawcursor(Drawcursor* c)
+{
+ if(c->data == nil){
+ InitCursor();
+ return;
+ }
+}