From c50e30b59e81227198b3188183e55ae143498d71 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 9 Jan 2007 22:17:21 +0000 Subject: [PATCH] Updates for 386 OS X, add native OS X graphics from Paul Lalonde --- Make.osx | 7 +- Make.osx-x11 | 21 ++ gui-osx/Makefile | 19 ++ gui-osx/alloc.c | 23 ++ gui-osx/cload.c | 10 + gui-osx/draw.c | 22 ++ gui-osx/keycodes.h | 189 ++++++++++++ gui-osx/load.c | 10 + gui-osx/screen.c | 666 ++++++++++++++++++++++++++++++++++++++++ gui-osx/wstrtoutf.c | 35 +++ gui-x11/alloc.c | 2 + include/lib.h | 4 + libc/Makefile | 3 + posix-386/Makefile | 6 +- posix-386/md5block.spp | 8 +- posix-386/sha1block.spp | 6 +- 16 files changed, 1020 insertions(+), 11 deletions(-) create mode 100644 Make.osx-x11 create mode 100644 gui-osx/Makefile create mode 100644 gui-osx/alloc.c create mode 100644 gui-osx/cload.c create mode 100644 gui-osx/draw.c create mode 100644 gui-osx/keycodes.h create mode 100644 gui-osx/load.c create mode 100644 gui-osx/screen.c create mode 100644 gui-osx/wstrtoutf.c diff --git a/Make.osx b/Make.osx index 10f94b1..d0f26a4 100644 --- a/Make.osx +++ b/Make.osx @@ -3,13 +3,12 @@ PTHREAD= # for Mac AR=ar AS=as RANLIB=ranlib -X11=/usr/X11R6 CC=gcc -CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 +CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -D_THREAD_SAFE $(PTHREAD) -O2 O=o OS=posix -GUI=x11 -LDADD=-L$(X11)/lib -lX11 -ggdb +GUI=osx +LDADD=-ggdb -framework Carbon -framework QuickTime LDFLAGS=$(PTHREAD) TARG=drawterm AUDIO=none diff --git a/Make.osx-x11 b/Make.osx-x11 new file mode 100644 index 0000000..10f94b1 --- /dev/null +++ b/Make.osx-x11 @@ -0,0 +1,21 @@ +# Mac OS X +PTHREAD= # for Mac +AR=ar +AS=as +RANLIB=ranlib +X11=/usr/X11R6 +CC=gcc +CFLAGS=-Wall -Wno-missing-braces -ggdb -I$(ROOT) -I$(ROOT)/include -I$(ROOT)/kern -c -I$(X11)/include -D_THREAD_SAFE $(PTHREAD) -O2 +O=o +OS=posix +GUI=x11 +LDADD=-L$(X11)/lib -lX11 -ggdb +LDFLAGS=$(PTHREAD) +TARG=drawterm +AUDIO=none + +all: default + +libmachdep.a: + arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/'`; \ + (cd posix-$$arch && make) diff --git a/gui-osx/Makefile b/gui-osx/Makefile new file mode 100644 index 0000000..1054760 --- /dev/null +++ b/gui-osx/Makefile @@ -0,0 +1,19 @@ +ROOT=.. +include ../Make.config +LIB=libgui.a + +OFILES=\ + alloc.$O\ + cload.$O\ + draw.$O\ + load.$O\ + screen.$O + +default: $(LIB) +$(LIB): $(OFILES) + $(AR) r $(LIB) $(OFILES) + $(RANLIB) $(LIB) + +%.$O: %.c + $(CC) $(CFLAGS) $*.c + diff --git a/gui-osx/alloc.c b/gui-osx/alloc.c new file mode 100644 index 0000000..cc7e977 --- /dev/null +++ b/gui-osx/alloc.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include + +Memimage* +allocmemimage(Rectangle r, ulong chan) +{ + return _allocmemimage(r, chan); +} + +void +freememimage(Memimage *i) +{ + _freememimage(i); +} + +void +memfillcolor(Memimage *i, ulong val) +{ + _memfillcolor(i, val); +} + diff --git a/gui-osx/cload.c b/gui-osx/cload.c new file mode 100644 index 0000000..9d658ef --- /dev/null +++ b/gui-osx/cload.c @@ -0,0 +1,10 @@ +#include +#include +#include +#include + +int +cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) +{ + return _cloadmemimage(i, r, data, ndata); +} diff --git a/gui-osx/draw.c b/gui-osx/draw.c new file mode 100644 index 0000000..eaac6d5 --- /dev/null +++ b/gui-osx/draw.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +void +memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, Memimage *mask, Point mp, int op) +{ + _memimagedraw(_memimagedrawsetup(dst, r, src, sp, mask, mp, op)); +} + +ulong +pixelbits(Memimage *m, Point p) +{ + return _pixelbits(m, p); +} + +void +memimageinit(void) +{ + _memimageinit(); +} diff --git a/gui-osx/keycodes.h b/gui-osx/keycodes.h new file mode 100644 index 0000000..52328ac --- /dev/null +++ b/gui-osx/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/gui-osx/load.c b/gui-osx/load.c new file mode 100644 index 0000000..7cca3a6 --- /dev/null +++ b/gui-osx/load.c @@ -0,0 +1,10 @@ +#include +#include +#include +#include + +int +loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) +{ + return _loadmemimage(i, r, data, ndata); +} diff --git a/gui-osx/screen.c b/gui-osx/screen.c new file mode 100644 index 0000000..92c9e39 --- /dev/null +++ b/gui-osx/screen.c @@ -0,0 +1,666 @@ +// in this file, _Rect is os x Rect, +// _Point is os x Point +#undef Point +#define Point _Point +#undef Rect +#define Rect _Rect + +#include +#include // for full screen + +#undef Rect +#undef Point + +#undef nil + + +#include "u.h" +#include "lib.h" +#include "kern/dat.h" +#include "kern/fns.h" +#include "error.h" +#include "user.h" +#include +#include +#include "screen.h" +#include "keyboard.h" +#include "keycodes.h" + +#define rWindowResource 128 + +#define topLeft(r) (((Point *) &(r))[0]) +#define botRight(r) (((Point *) &(r))[1]) + +extern int mousequeue; +static int depth; +Boolean gDone; +RgnHandle gCursorRegionHdl; + +Memimage *gscreen; +Screeninfo screen; + +static int readybit; +static Rendez rend; + +/// +// 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); + + memimageinit(); + depth = 32; // That's all this code deals with for now + screen.depth = 32; + 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; + + 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, 0); + ksleep(&rend, isready, 0); +} + +static OSStatus MainWindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData); +static OSStatus MainWindowCommandHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData); + +void +window_resized() +{ + GetWindowBounds(theWindow, kWindowContentRgn, &winRect ); + + bounds = CGRectMake(0, 0, winRect.right-winRect.left, winRect.bottom - winRect.top); +} + + +void winproc(void *a) +{ + winRect.left = 30; + winRect.top = 60; + winRect.bottom = (devRect.size.height * 0.75) + winRect.top; + winRect.right = (devRect.size.width * 0.75) + winRect.left; + + ClearMenuBar(); + InitCursor(); + + CreateStandardWindowMenu(0, &windMenu); + InsertMenu(windMenu, 0); + + MenuItemIndex index; + 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 + | kWindowStandardHandlerAttribute + | kWindowFullZoomAttribute + ; + + CreateNewWindow(kDocumentWindowClass, windowAttrs, &winRect, &theWindow); + CreateWindowGroup(0, &winGroup); + SetWindowGroup(theWindow, winGroup); + + SetWindowTitleWithCFString(theWindow, CFSTR("Drawterm")); + + 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 inline 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) +{ + int i; + lock(&mouse.lk); + i = mouse.wi; + if(mousequeue) { + if(i == mouse.ri || mouse.lastb != b || mouse.trans) { + mouse.wi = (i+1)%Mousequeue; + if(mouse.wi == mouse.ri) + mouse.ri = (mouse.ri+1)%Mousequeue; + mouse.trans = mouse.lastb != b; + } else { + i = (i-1+Mousequeue)%Mousequeue; + } + } else { + mouse.wi = (i+1)%Mousequeue; + mouse.ri = i; + } + mouse.queue[i].xy.x = x; + mouse.queue[i].xy.y = y; + mouse.queue[i].buttons = b; + mouse.queue[i].msec = ticks(); + mouse.lastb = b; + unlock(&mouse.lk); + wakeup(&mouse.r); +} + +static Ptr fullScreenRestore; +static int amFullScreen = 0; +static WindowRef oldWindow = NULL; + +static void +leave_full_screen() +{ + if (amFullScreen) { + EndFullScreen(fullScreenRestore, 0); + theWindow = oldWindow; + ShowWindow(theWindow); + amFullScreen = 0; + window_resized(); + Rectangle rect = { { 0, 0 }, + { bounds.size.width, + bounds.size.height} }; + flushmemscreen(rect); + } +} + +static void +full_screen() +{ + if (!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} }; + flushmemscreen(rect); + } +} + +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) kbdputc(kbdq, 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,typeSInt32, + 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: + exit(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; + exit(0); // only one window + break; + + //resize window + case kEventWindowBoundsChanged: + window_resized(); + Rectangle rect = { { 0, 0 }, + { bounds.size.width, + bounds.size.height} }; + flushmemscreen(rect); + break; + + default: + result = eventNotHandledErr; + break; + } + } + + return result; +} + +void +flushmemscreen(Rectangle r) +{ + // sanity check. Trips from the initial "terminal" + if (r.max.x < r.min.x || r.max.y < r.min.y) return; + + screenload(r, gscreen->depth, byteaddr(gscreen, ZP), ZP, + gscreen->width*sizeof(ulong)); +} + +uchar* +attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen, void **X) +{ + *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 red, ulong green, ulong blue) +{ + assert(0); +} + + +static char snarf[3*SnarfSize+1]; +static Rune rsnarf[SnarfSize+1]; + +char* +clipread(void) +{ + CFDataRef cfdata; + OSStatus err = noErr; + ItemCount nItems; + + // 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; + } + + uint32_t i; + // 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); + char *s = snarf; + while (*s) { + if (*s == '\r') *s = '\n'; + s++; + } + CFRelease(cfdata); + return strdup(snarf); + } + } + } + return 0; +} + +int +clipwrite(char *snarf) +{ + CFDataRef cfdata; + PasteboardSyncFlags flags; + + runesnprint(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 +mouseset(Point xy) +{ + CGPoint pnt; + pnt.x = xy.x + winRect.left; + pnt.y = xy.y + winRect.top; + CGWarpMouseCursorPosition(pnt); +} + +void +screenload(Rectangle r, int depth, uchar *p, Point pt, int step) +{ + CGRect rbounds; + 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(depth != gscreen->depth) + panic("screenload: bad ldepth"); + + 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); + +} + +// PAL: these don't work. +// SetCursor and InitCursor are marked as deprecated in 10.4, and I can't for the +// life of me find out what has replaced them. +void +setcursor(void) +{ + Cursor crsr; + int i; + + for(i=0; i<16; i++){ + crsr.data[i] = ((ushort*)cursor.set)[i]; + crsr.mask[i] = crsr.data[i] | ((ushort*)cursor.clr)[i]; + } + crsr.hotSpot.h = -cursor.offset.x; + crsr.hotSpot.v = -cursor.offset.y; + SetCursor(&crsr); +} + +void +cursorarrow(void) +{ + InitCursor(); +} diff --git a/gui-osx/wstrtoutf.c b/gui-osx/wstrtoutf.c new file mode 100644 index 0000000..2cdc7fd --- /dev/null +++ b/gui-osx/wstrtoutf.c @@ -0,0 +1,35 @@ +#include +#include + +int +wstrutflen(Rune *s) +{ + int n; + + for(n=0; *s; n+=runelen(*s),s++) + ; + return n; +} + +int +wstrtoutf(char *s, Rune *t, int n) +{ + int i; + char *s0; + + s0 = s; + if(n <= 0) + return wstrutflen(t)+1; + while(*t) { + if(n < UTFmax+1 && n < runelen(*t)+1) { + *s = 0; + return i+wstrutflen(t)+1; + } + i = runetochar(s, t); + s += i; + n -= i; + t++; + } + *s = 0; + return s-s0; +} diff --git a/gui-x11/alloc.c b/gui-x11/alloc.c index 8053c44..ea6ca10 100644 --- a/gui-x11/alloc.c +++ b/gui-x11/alloc.c @@ -17,6 +17,8 @@ xallocmemimage(Rectangle r, ulong chan, int pmid) int d; m = _allocmemimage(r, chan); + if(m == nil) + return nil; if(chan != GREY1 && chan != xscreenchan) return m; diff --git a/include/lib.h b/include/lib.h index 8e72575..448309f 100644 --- a/include/lib.h +++ b/include/lib.h @@ -223,6 +223,10 @@ extern Rune* runevseprint(Rune*, Rune*, char*, va_list); extern Rune* runesmprint(char*, ...); extern Rune* runevsmprint(char*, va_list); +extern Rune* runestrchr(Rune*, Rune); +extern long runestrlen(Rune*); +extern Rune* runestrstr(Rune*, Rune*); + extern int fmtfdinit(Fmt*, int, char*, int); extern int fmtfdflush(Fmt*); extern int fmtstrinit(Fmt*); diff --git a/libc/Makefile b/libc/Makefile index a6c4f48..d17530b 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -49,6 +49,9 @@ OFILES=\ runesmprint.$O\ runesnprint.$O\ runesprint.$O\ + runestrchr.$O\ + runestrlen.$O\ + runestrstr.$O\ runetype.$O\ runevseprint.$O\ runevsmprint.$O\ diff --git a/posix-386/Makefile b/posix-386/Makefile index 3df36dd..062e3e0 100644 --- a/posix-386/Makefile +++ b/posix-386/Makefile @@ -20,10 +20,8 @@ $(LIB): $(OFILES) $(AS) -o $*.$O $*.s md5block.s: md5block.spp - cpp md5block.spp >md5block.s + gcc -E md5block.spp >md5block.s sha1block.s: sha1block.spp - cpp sha1block.spp >sha1block.s - - + gcc -E sha1block.spp >sha1block.s diff --git a/posix-386/md5block.spp b/posix-386/md5block.spp index 213a923..feebf61 100644 --- a/posix-386/md5block.spp +++ b/posix-386/md5block.spp @@ -43,7 +43,7 @@ #define S43 15 #define S44 21 -#define PAYME(x) $ ## x +#define PAYME(x) $##x /* * SI is data @@ -116,9 +116,13 @@ .text .p2align 2,0x90 +#ifdef __Darwin__ + .globl __md5block + __md5block: +#else .globl _md5block - .type _md5block, @function _md5block: +#endif /* Prelude */ pushl %ebp diff --git a/posix-386/sha1block.spp b/posix-386/sha1block.spp index 2c7ba77..d568e4f 100644 --- a/posix-386/sha1block.spp +++ b/posix-386/sha1block.spp @@ -1,9 +1,13 @@ .text .p2align 2,0x90 +#ifdef __Darwin__ +.globl __sha1block +__sha1block: +#else .globl _sha1block - .type _sha1block, @function _sha1block: +#endif /* x = (wp[off-f] ^ wp[off-8] ^ wp[off-14] ^ wp[off-16]) <<< 1; * wp[off] = x;