|  | #define Point OSXPoint | 
|  | #define Rect OSXRect | 
|  | #define Cursor OSXCursor | 
|  | #import <Cocoa/Cocoa.h> | 
|  | #import <AppKit/AppKit.h> | 
|  | #undef Rect | 
|  | #undef Point | 
|  | #undef Cursor | 
|  | #undef offsetof | 
|  | #undef nil | 
|  |  | 
|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <draw.h> | 
|  | #include <memdraw.h> | 
|  | #include <keyboard.h> | 
|  | #include <mouse.h> | 
|  | #include <cursor.h> | 
|  | #include "osx-screen.h" | 
|  | #include "osx-keycodes.h" | 
|  | #include "devdraw.h" | 
|  | #include "glendapng.h" | 
|  |  | 
|  | AUTOFRAMEWORK(Cocoa) | 
|  |  | 
|  | #define panic sysfatal | 
|  |  | 
|  | extern Rectangle mouserect; | 
|  |  | 
|  | struct { | 
|  | char *label; | 
|  | char *winsize; | 
|  | QLock labellock; | 
|  |  | 
|  | Rectangle fullscreenr; | 
|  | Rectangle screenr; | 
|  | Memimage *screenimage; | 
|  | int isfullscreen; | 
|  | ulong fullscreentime; | 
|  |  | 
|  | Point xy; | 
|  | int buttons; | 
|  | int kbuttons; | 
|  |  | 
|  | CGDataProviderRef provider; | 
|  | NSWindow *window; | 
|  | CGImageRef image; | 
|  | CGContextRef windowctx; | 
|  |  | 
|  | int needflush; | 
|  | QLock flushlock; | 
|  | int active; | 
|  | int infullscreen; | 
|  | int kalting;		// last keystroke was Kalt | 
|  | } osx; | 
|  |  | 
|  | enum | 
|  | { | 
|  | WindowAttrs = NSClosableWindowMask | | 
|  | NSTitledWindowMask | | 
|  | NSMiniaturizableWindowMask | | 
|  | NSResizableWindowMask | 
|  | }; | 
|  |  | 
|  | static void screenproc(void*); | 
|  | void eresized(int); | 
|  | void fullscreen(int); | 
|  | void seticon(void); | 
|  | static void activated(int); | 
|  |  | 
|  | enum | 
|  | { | 
|  | CmdFullScreen = 1, | 
|  | }; | 
|  |  | 
|  | @interface P9View : NSView | 
|  | {} | 
|  | @end | 
|  |  | 
|  | @implementation P9View | 
|  | - (BOOL)acceptsFirstResponder | 
|  | { | 
|  | return YES; | 
|  | } | 
|  | @end | 
|  |  | 
|  | void screeninit(void); | 
|  | void _flushmemscreen(Rectangle r); | 
|  |  | 
|  | Memimage* | 
|  | attachscreen(char *label, char *winsize) | 
|  | { | 
|  | if(label == nil) | 
|  | label = "gnot a label"; | 
|  | osx.label = strdup(label); | 
|  | osx.winsize = winsize; | 
|  | if(osx.screenimage == nil){ | 
|  | screeninit(); | 
|  | if(osx.screenimage == nil) | 
|  | panic("cannot create OS X screen"); | 
|  | } | 
|  | return osx.screenimage; | 
|  | } | 
|  |  | 
|  | void | 
|  | _screeninit(void) | 
|  | { | 
|  | CGRect cgr; | 
|  | NSRect or; | 
|  | Rectangle r; | 
|  | int havemin; | 
|  |  | 
|  | memimageinit(); | 
|  |  | 
|  | cgr = CGDisplayBounds(CGMainDisplayID()); | 
|  | osx.fullscreenr = Rect(0, 0, cgr.size.width, cgr.size.height); | 
|  |  | 
|  | // Create the window. | 
|  | r = Rect(0, 0, Dx(osx.fullscreenr)*2/3, Dy(osx.fullscreenr)*2/3); | 
|  | havemin = 0; | 
|  | if(osx.winsize && osx.winsize[0]){ | 
|  | if(parsewinsize(osx.winsize, &r, &havemin) < 0) | 
|  | sysfatal("%r"); | 
|  | } | 
|  | if(!havemin) | 
|  | r = rectaddpt(r, Pt((Dx(osx.fullscreenr)-Dx(r))/2, (Dy(osx.fullscreenr)-Dy(r))/2)); | 
|  | or = NSMakeRect(r.min.x, r.min.y, r.max.x, r.max.y); | 
|  | osx.window = [[NSWindow alloc] initWithContentRect:or styleMask:WindowAttrs | 
|  | backing:NSBackingStoreBuffered defer:NO screen:[NSScreen mainScreen]]; | 
|  | [osx.window setDelegate:[NSApp delegate]]; | 
|  | [osx.window setAcceptsMouseMovedEvents:YES]; | 
|  |  | 
|  | P9View *view = [[P9View alloc] initWithFrame:or]; | 
|  | [osx.window setContentView:view]; | 
|  | [view release]; | 
|  |  | 
|  | setlabel(osx.label); | 
|  | seticon(); | 
|  |  | 
|  | // Finally, put the window on the screen. | 
|  | eresized(0); | 
|  | [osx.window makeKeyAndOrderFront:nil]; | 
|  |  | 
|  | [NSCursor unhide]; | 
|  | } | 
|  |  | 
|  | static Rendez scr; | 
|  | static QLock slock; | 
|  |  | 
|  | void | 
|  | screeninit(void) | 
|  | { | 
|  | scr.l = &slock; | 
|  | qlock(scr.l); | 
|  | //	proccreate(screenproc, nil, 256*1024); | 
|  | screenproc(NULL); | 
|  | while(osx.window == nil) | 
|  | rsleep(&scr); | 
|  | qunlock(scr.l); | 
|  | } | 
|  |  | 
|  | static void | 
|  | screenproc(void *v) | 
|  | { | 
|  | qlock(scr.l); | 
|  | _screeninit(); | 
|  | rwakeup(&scr); | 
|  | qunlock(scr.l); | 
|  | } | 
|  |  | 
|  | static ulong | 
|  | msec(void) | 
|  | { | 
|  | return nsec()/1000000; | 
|  | } | 
|  |  | 
|  | //static void | 
|  | void | 
|  | mouseevent(NSEvent *event) | 
|  | { | 
|  | int wheel; | 
|  | NSPoint op; | 
|  |  | 
|  | op = [event locationInWindow]; | 
|  |  | 
|  | osx.xy = subpt(Pt(op.x, op.y), osx.screenr.min); | 
|  | wheel = 0; | 
|  |  | 
|  | switch([event type]){ | 
|  | case NSScrollWheel:; | 
|  | CGFloat delta = [event deltaY]; | 
|  | if(delta > 0) | 
|  | wheel = 8; | 
|  | else | 
|  | wheel = 16; | 
|  | break; | 
|  |  | 
|  | case NSLeftMouseDown: | 
|  | case NSRightMouseDown: | 
|  | case NSOtherMouseDown: | 
|  | case NSLeftMouseUp: | 
|  | case NSRightMouseUp: | 
|  | case NSOtherMouseUp:; | 
|  | NSInteger but; | 
|  | NSUInteger  mod; | 
|  | but = [event buttonNumber]; | 
|  | mod = [event modifierFlags]; | 
|  |  | 
|  | // OS X swaps button 2 and 3 | 
|  | but = (but & ~6) | ((but & 4)>>1) | ((but&2)<<1); | 
|  | but = mouseswap(but); | 
|  |  | 
|  | // Apply keyboard modifiers and pretend it was a real mouse button. | 
|  | // (Modifiers typed while holding the button go into kbuttons, | 
|  | // but this one does not.) | 
|  | if(but == 1){ | 
|  | if(mod & NSAlternateKeyMask) { | 
|  | // Take the ALT away from the keyboard handler. | 
|  | if(osx.kalting) { | 
|  | osx.kalting = 0; | 
|  | keystroke(Kalt); | 
|  | } | 
|  | but = 2; | 
|  | } | 
|  | else if(mod & NSCommandKeyMask) | 
|  | but = 4; | 
|  | } | 
|  | osx.buttons = but; | 
|  | break; | 
|  |  | 
|  | case NSMouseMoved: | 
|  | case NSLeftMouseDragged: | 
|  | case NSRightMouseDragged: | 
|  | case NSOtherMouseDragged: | 
|  | break; | 
|  |  | 
|  | default: | 
|  | return; | 
|  | } | 
|  |  | 
|  | mousetrack(osx.xy.x, osx.xy.y, osx.buttons|osx.kbuttons|wheel, msec()); | 
|  | } | 
|  |  | 
|  | static int keycvt[] = | 
|  | { | 
|  | [QZ_IBOOK_ENTER] '\n', | 
|  | [QZ_RETURN] '\n', | 
|  | [QZ_ESCAPE] 27, | 
|  | [QZ_BACKSPACE] '\b', | 
|  | [QZ_LALT] Kalt, | 
|  | [QZ_LCTRL] Kctl, | 
|  | [QZ_LSHIFT] Kshift, | 
|  | [QZ_F1] KF+1, | 
|  | [QZ_F2] KF+2, | 
|  | [QZ_F3] KF+3, | 
|  | [QZ_F4] KF+4, | 
|  | [QZ_F5] KF+5, | 
|  | [QZ_F6] KF+6, | 
|  | [QZ_F7] KF+7, | 
|  | [QZ_F8] KF+8, | 
|  | [QZ_F9] KF+9, | 
|  | [QZ_F10] KF+10, | 
|  | [QZ_F11] KF+11, | 
|  | [QZ_F12] KF+12, | 
|  | [QZ_INSERT] Kins, | 
|  | [QZ_DELETE] 0x7F, | 
|  | [QZ_HOME] Khome, | 
|  | [QZ_END] Kend, | 
|  | [QZ_KP_PLUS] '+', | 
|  | [QZ_KP_MINUS] '-', | 
|  | [QZ_TAB] '\t', | 
|  | [QZ_PAGEUP] Kpgup, | 
|  | [QZ_PAGEDOWN] Kpgdown, | 
|  | [QZ_UP] Kup, | 
|  | [QZ_DOWN] Kdown, | 
|  | [QZ_LEFT] Kleft, | 
|  | [QZ_RIGHT] Kright, | 
|  | [QZ_KP_MULTIPLY] '*', | 
|  | [QZ_KP_DIVIDE] '/', | 
|  | [QZ_KP_ENTER] '\n', | 
|  | [QZ_KP_PERIOD] '.', | 
|  | [QZ_KP0] '0', | 
|  | [QZ_KP1] '1', | 
|  | [QZ_KP2] '2', | 
|  | [QZ_KP3] '3', | 
|  | [QZ_KP4] '4', | 
|  | [QZ_KP5] '5', | 
|  | [QZ_KP6] '6', | 
|  | [QZ_KP7] '7', | 
|  | [QZ_KP8] '8', | 
|  | [QZ_KP9] '9', | 
|  | }; | 
|  |  | 
|  | //static void | 
|  | void | 
|  | kbdevent(NSEvent *event) | 
|  | { | 
|  | char ch; | 
|  | UInt32 code; | 
|  | UInt32 mod; | 
|  | int k; | 
|  |  | 
|  | ch = [[event characters] characterAtIndex:0]; | 
|  | code = [event keyCode]; | 
|  | mod = [event modifierFlags]; | 
|  |  | 
|  | switch([event type]){ | 
|  | case NSKeyDown: | 
|  | osx.kalting = 0; | 
|  | if(mod == NSCommandKeyMask){ | 
|  | if(ch == 'F' || ch == 'f'){ | 
|  | if(osx.isfullscreen && msec() - osx.fullscreentime > 500) | 
|  | fullscreen(0); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Pass most Cmd keys through as Kcmd + ch. | 
|  | // OS X interprets a few no matter what we do, | 
|  | // so it is useless to pass them through as keystrokes too. | 
|  | switch(ch) { | 
|  | case 'm':	// minimize window | 
|  | case 'h':	// hide window | 
|  | case 'H':	// hide others | 
|  | case 'q':	// quit | 
|  | return; | 
|  | } | 
|  | if(' ' <= ch && ch <= '~') { | 
|  | keystroke(Kcmd + ch); | 
|  | return; | 
|  | } | 
|  | return; | 
|  | } | 
|  | k = ch; | 
|  | if(code < nelem(keycvt) && keycvt[code]) | 
|  | k = keycvt[code]; | 
|  | if(k >= 0) | 
|  | keystroke(k); | 
|  | else{ | 
|  | keystroke(ch); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case NSFlagsChanged: | 
|  | if(!osx.buttons && !osx.kbuttons){ | 
|  | if(mod == NSAlternateKeyMask) { | 
|  | osx.kalting = 1; | 
|  | keystroke(Kalt); | 
|  | } | 
|  | break; | 
|  | } | 
|  |  | 
|  | // If the mouse button is being held down, treat | 
|  | // changes in the keyboard modifiers as changes | 
|  | // in the mouse buttons. | 
|  | osx.kbuttons = 0; | 
|  | if(mod & NSAlternateKeyMask) | 
|  | osx.kbuttons |= 2; | 
|  | if(mod & NSCommandKeyMask) | 
|  | osx.kbuttons |= 4; | 
|  | mousetrack(osx.xy.x, osx.xy.y, osx.buttons|osx.kbuttons, msec()); | 
|  | break; | 
|  | } | 
|  | return; | 
|  | } | 
|  |  | 
|  | //static void | 
|  | void | 
|  | eresized(int new) | 
|  | { | 
|  | Memimage *m; | 
|  | NSRect or; | 
|  | ulong chan; | 
|  | Rectangle r; | 
|  | int bpl; | 
|  | CGDataProviderRef provider; | 
|  | CGImageRef image; | 
|  | CGColorSpaceRef cspace; | 
|  |  | 
|  | or = [[osx.window contentView] bounds]; | 
|  | r = Rect(or.origin.x, or.origin.y, or.size.width, or.size.height); | 
|  | if(Dx(r) == Dx(osx.screenr) && Dy(r) == Dy(osx.screenr)){ | 
|  | // No need to make new image. | 
|  | osx.screenr = r; | 
|  | return; | 
|  | } | 
|  |  | 
|  | chan = XBGR32; | 
|  | m = allocmemimage(Rect(0, 0, Dx(r), Dy(r)), chan); | 
|  | if(m == nil) | 
|  | panic("allocmemimage: %r"); | 
|  | if(m->data == nil) | 
|  | panic("m->data == nil"); | 
|  | bpl = bytesperline(r, 32); | 
|  | provider = CGDataProviderCreateWithData(0, | 
|  | m->data->bdata, Dy(r)*bpl, 0); | 
|  | //cspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); | 
|  | cspace = CGColorSpaceCreateDeviceRGB(); | 
|  | image = CGImageCreate(Dx(r), Dy(r), 8, 32, bpl, | 
|  | cspace, | 
|  | kCGImageAlphaNoneSkipLast, | 
|  | provider, 0, 0, kCGRenderingIntentDefault); | 
|  | CGColorSpaceRelease(cspace); | 
|  | CGDataProviderRelease(provider);	// CGImageCreate did incref | 
|  |  | 
|  | mouserect = m->r; | 
|  | if(new){ | 
|  | mouseresized = 1; | 
|  | mousetrack(osx.xy.x, osx.xy.y, osx.buttons|osx.kbuttons, msec()); | 
|  | } | 
|  | //	termreplacescreenimage(m); | 
|  | _drawreplacescreenimage(m);	// frees old osx.screenimage if any | 
|  | if(osx.image) | 
|  | CGImageRelease(osx.image); | 
|  | osx.image = image; | 
|  | osx.screenimage = m; | 
|  | osx.screenr = r; | 
|  | } | 
|  |  | 
|  | void | 
|  | flushproc(void *v) | 
|  | { | 
|  | for(;;){ | 
|  | if(osx.needflush && osx.windowctx && canqlock(&osx.flushlock)){ | 
|  | if(osx.windowctx){ | 
|  | CGContextFlush(osx.windowctx); | 
|  | osx.needflush = 0; | 
|  | } | 
|  | qunlock(&osx.flushlock); | 
|  | } | 
|  | usleep(33333); | 
|  | } | 
|  | } | 
|  |  | 
|  | void | 
|  | _flushmemscreen(Rectangle r) | 
|  | { | 
|  | CGRect cgr; | 
|  | CGImageRef subimg; | 
|  |  | 
|  | qlock(&osx.flushlock); | 
|  | if(osx.windowctx == nil){ | 
|  | osx.windowctx = [[osx.window graphicsContext] graphicsPort]; | 
|  | //		[osx.window flushWindow]; | 
|  | //		proccreate(flushproc, nil, 256*1024); | 
|  | } | 
|  |  | 
|  | cgr.origin.x = r.min.x; | 
|  | cgr.origin.y = r.min.y; | 
|  | cgr.size.width = Dx(r); | 
|  | cgr.size.height = Dy(r); | 
|  | subimg = CGImageCreateWithImageInRect(osx.image, cgr); | 
|  | cgr.origin.y = Dy(osx.screenr) - r.max.y; // XXX how does this make any sense? | 
|  | CGContextDrawImage(osx.windowctx, cgr, subimg); | 
|  | osx.needflush = 1; | 
|  | qunlock(&osx.flushlock); | 
|  | CGImageRelease(subimg); | 
|  | } | 
|  |  | 
|  | void | 
|  | activated(int active) | 
|  | { | 
|  | osx.active = active; | 
|  | } | 
|  |  | 
|  | void | 
|  | fullscreen(int wascmd) | 
|  | { | 
|  | NSView *view = [osx.window contentView]; | 
|  |  | 
|  | if(osx.isfullscreen){ | 
|  | [view exitFullScreenModeWithOptions:nil]; | 
|  | osx.isfullscreen = 0; | 
|  | }else{ | 
|  | [view enterFullScreenMode:[osx.window screen] withOptions:nil]; | 
|  | osx.isfullscreen = 1; | 
|  | osx.fullscreentime = msec(); | 
|  | } | 
|  | eresized(1); | 
|  | } | 
|  |  | 
|  | void | 
|  | setmouse(Point p) | 
|  | { | 
|  | CGPoint cgp; | 
|  |  | 
|  | cgp.x = p.x + osx.screenr.min.x; | 
|  | cgp.y = p.y + osx.screenr.min.y; | 
|  | CGWarpMouseCursorPosition(cgp); | 
|  | } | 
|  |  | 
|  | void | 
|  | setcursor(Cursor *c) | 
|  | { | 
|  | NSImage *image; | 
|  | NSBitmapImageRep *bitmap; | 
|  | NSCursor *nsc; | 
|  | unsigned char *planes[5]; | 
|  | int i; | 
|  |  | 
|  | if(c == nil){ | 
|  | [NSCursor pop]; | 
|  | return; | 
|  | } | 
|  |  | 
|  | image = [[NSImage alloc] initWithSize:NSMakeSize(16.0, 16.0)]; | 
|  | bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL | 
|  | pixelsWide:16 | 
|  | pixelsHigh:16 | 
|  | bitsPerSample:1 | 
|  | samplesPerPixel:2 | 
|  | hasAlpha:YES | 
|  | isPlanar:YES | 
|  | colorSpaceName:NSCalibratedWhiteColorSpace | 
|  | bytesPerRow:2 | 
|  | bitsPerPixel:1]; | 
|  |  | 
|  | [bitmap getBitmapDataPlanes:planes]; | 
|  |  | 
|  | for(i=0; i<16; i++){ | 
|  | planes[0][i] = ((ushort*)c->set)[i]; | 
|  | planes[1][i] = planes[0][i] | ((ushort*)c->clr)[i]; | 
|  | } | 
|  |  | 
|  | [image addRepresentation:bitmap]; | 
|  |  | 
|  | nsc = [[NSCursor alloc] initWithImage:image | 
|  | hotSpot:NSMakePoint(c->offset.x, c->offset.y)]; | 
|  | [nsc push]; | 
|  |  | 
|  | [image release]; | 
|  | [bitmap release]; | 
|  | [nsc release]; | 
|  | } | 
|  |  | 
|  | void | 
|  | getcolor(ulong i, ulong *r, ulong *g, ulong *b) | 
|  | { | 
|  | ulong v; | 
|  |  | 
|  | v = 0; | 
|  | *r = (v>>16)&0xFF; | 
|  | *g = (v>>8)&0xFF; | 
|  | *b = v&0xFF; | 
|  | } | 
|  |  | 
|  | int | 
|  | setcolor(ulong i, ulong r, ulong g, ulong b) | 
|  | { | 
|  | /* no-op */ | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | int | 
|  | hwdraw(Memdrawparam *p) | 
|  | { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | struct { | 
|  | QLock lk; | 
|  | char buf[SnarfSize]; | 
|  | Rune rbuf[SnarfSize]; | 
|  | NSPasteboard *apple; | 
|  | } clip; | 
|  |  | 
|  | char* | 
|  | getsnarf(void) | 
|  | { | 
|  | char *s, *t; | 
|  | NSArray *types; | 
|  | NSString *string; | 
|  | NSData * data; | 
|  | NSUInteger ndata; | 
|  |  | 
|  | /*	fprint(2, "applegetsnarf\n"); */ | 
|  | qlock(&clip.lk); | 
|  |  | 
|  | clip.apple = [NSPasteboard generalPasteboard]; | 
|  | types = [clip.apple types]; | 
|  |  | 
|  | string = [clip.apple stringForType:NSStringPboardType]; | 
|  | if(string == nil){ | 
|  | fprint(2, "apple pasteboard get item type failed\n"); | 
|  | qunlock(&clip.lk); | 
|  | return nil; | 
|  | } | 
|  |  | 
|  | data = [string dataUsingEncoding:NSUnicodeStringEncoding]; | 
|  | if(data != nil){ | 
|  | ndata = [data length]; | 
|  | qunlock(&clip.lk); | 
|  | s = smprint("%.*S", ndata/2, (Rune*)[data bytes]); | 
|  | for(t=s; *t; t++) | 
|  | if(*t == '\r') | 
|  | *t = '\n'; | 
|  | return s; | 
|  | } | 
|  |  | 
|  | qunlock(&clip.lk); | 
|  | return nil; | 
|  | } | 
|  |  | 
|  | void | 
|  | putsnarf(char *s) | 
|  | { | 
|  | NSArray *pboardTypes; | 
|  | NSString *string; | 
|  |  | 
|  | /*	fprint(2, "appleputsnarf\n"); */ | 
|  |  | 
|  | if(strlen(s) >= SnarfSize) | 
|  | return; | 
|  | qlock(&clip.lk); | 
|  | strcpy(clip.buf, s); | 
|  | runesnprint(clip.rbuf, nelem(clip.rbuf), "%s", s); | 
|  |  | 
|  | pboardTypes = [NSArray arrayWithObject:NSStringPboardType]; | 
|  |  | 
|  | clip.apple = [NSPasteboard generalPasteboard]; | 
|  | [clip.apple declareTypes:pboardTypes owner:nil]; | 
|  |  | 
|  | assert(sizeof(clip.rbuf[0]) == 2); | 
|  | string = [NSString stringWithCharacters:clip.rbuf length:runestrlen(clip.rbuf)*2]; | 
|  | if(string == nil){ | 
|  | fprint(2, "apple pasteboard data create failed\n"); | 
|  | qunlock(&clip.lk); | 
|  | return; | 
|  | } | 
|  | if(![clip.apple setString:string forType:NSStringPboardType]){ | 
|  | fprint(2, "apple pasteboard putitem failed\n"); | 
|  | qunlock(&clip.lk); | 
|  | return; | 
|  | } | 
|  | qunlock(&clip.lk); | 
|  | } | 
|  |  | 
|  | void | 
|  | setlabel(char *label) | 
|  | { | 
|  | CFStringRef cs; | 
|  | cs = CFStringCreateWithBytes(nil, (uchar*)label, strlen(osx.label), kCFStringEncodingUTF8, false); | 
|  | [osx.window setTitle:(NSString*)cs]; | 
|  | CFRelease(cs); | 
|  | } | 
|  |  | 
|  | void | 
|  | kicklabel(char *label) | 
|  | { | 
|  | char *p; | 
|  |  | 
|  | p = strdup(label); | 
|  | if(p == nil) | 
|  | return; | 
|  | qlock(&osx.labellock); | 
|  | free(osx.label); | 
|  | osx.label = p; | 
|  | qunlock(&osx.labellock); | 
|  |  | 
|  | setlabel(label); | 
|  | } | 
|  |  | 
|  | // static void | 
|  | void | 
|  | seticon(void) | 
|  | { | 
|  | NSImage *im; | 
|  | NSData *d; | 
|  |  | 
|  | d = [[NSData alloc] initWithBytes:glenda_png length:(sizeof glenda_png)]; | 
|  | im = [[NSImage alloc] initWithData:d]; | 
|  | if(im){ | 
|  | NSLog(@"here"); | 
|  | [NSApp setApplicationIconImage:im]; | 
|  | [[NSApp dockTile] setShowsApplicationBadge:YES]; | 
|  | [[NSApp dockTile] display]; | 
|  | } | 
|  | [d release]; | 
|  | [im release]; | 
|  | } |