summaryrefslogtreecommitdiff
path: root/plot/osx
diff options
context:
space:
mode:
Diffstat (limited to 'plot/osx')
-rw-r--r--plot/osx/Jamfile21
-rw-r--r--plot/osx/Readme.txt1
-rw-r--r--plot/osx/acoccoa.h402
-rw-r--r--plot/osx/helloc.c313
-rw-r--r--plot/osx/hellom.m181
5 files changed, 918 insertions, 0 deletions
diff --git a/plot/osx/Jamfile b/plot/osx/Jamfile
new file mode 100644
index 0000000..933d56d
--- /dev/null
+++ b/plot/osx/Jamfile
@@ -0,0 +1,21 @@
+
+# Jamfile for OS X window code development
+
+#PREF_CCFLAGS = $(CCOPTFLAG) ; # Turn optimisation on
+PREF_CCFLAGS = $(CCDEBUGFLAG) ; # Debugging flags
+#PREF_CCFLAGS += -x objective-c ;
+PREF_LINKFLAGS = $(LINKDEBUGFLAG) ;
+
+# Hello world
+#Main hello : hello.m ;
+
+# Hello world window in C
+Main helloc : helloc.c ;
+
+# Hello world window in Objective-C
+ObjectCcFlags hellom : -ObjC ;
+Main hellom : hellom.m ;
+
+#GuiBin tt ;
+#Main tt : tt.m ;
+
diff --git a/plot/osx/Readme.txt b/plot/osx/Readme.txt
new file mode 100644
index 0000000..44b083b
--- /dev/null
+++ b/plot/osx/Readme.txt
@@ -0,0 +1 @@
+Develop Cocoa based simple window code.
diff --git a/plot/osx/acoccoa.h b/plot/osx/acoccoa.h
new file mode 100644
index 0000000..ba88cd4
--- /dev/null
+++ b/plot/osx/acoccoa.h
@@ -0,0 +1,402 @@
+
+#ifndef ACOCCOA_H
+
+/* OS X Coccoa support code for Argyll. */
+/* In some places we really prefer not to have OS X code */
+/* in separate .m files, so we'll do it all from C. */
+
+#include <Carbon/Carbon.h>
+
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
+# include <objc/runtime.h>
+# include <objc/message.h>
+#else
+# include <objc/objc-runtime.h>
+
+/* Objective-C runtime compatibility functions for < 10.5 */
+
+/* Create a class definition, but don't register it */
+Class CreateClassDefinition(const char *name, const char *superclassName) {
+ struct objc_class *meta_class;
+ struct objc_class *super_class;
+ struct objc_class *new_class;
+ struct objc_class *root_class;
+
+ // Ensure that the superclass exists and that someone
+ // hasn't already implemented a class with the same name
+ //
+ super_class = (struct objc_class *)objc_lookUpClass(superclassName);
+ if (super_class == nil) {
+ printf("failed to lookup '%s'\n",superclassName);
+ return Nil;
+ }
+
+ if (objc_lookUpClass(name) != nil) {
+ return Nil;
+ }
+
+ // Find the root class
+ root_class = super_class;
+ while(root_class->super_class != nil)
+ root_class = root_class->super_class;
+
+ // Allocate space for the class and its metaclass
+ if ((new_class = calloc(2, sizeof(struct objc_class))) == NULL) {
+ return Nil;
+ }
+ meta_class = &new_class[1];
+
+ // setup class
+ new_class->isa = meta_class;
+ new_class->info = CLS_CLASS;
+ meta_class->info = CLS_META;
+
+ // Create a copy of the class name.
+ // For efficiency, we have the metaclass and the class itself
+ // to share this copy of the name, but this is not a requirement
+ // imposed by the runtime.
+ if ((new_class->name = strdup(name)) == NULL) {
+ free(new_class);
+ }
+ meta_class->name = new_class->name;
+
+ // Allocate empty method lists.
+ // We can add methods later.
+ if ((new_class->methodLists = calloc( 1, sizeof(struct objc_method_list *))) == NULL) {
+ free((void *)new_class->name);
+ free(new_class);
+ return Nil;
+ }
+ *new_class->methodLists = (struct objc_method_list *) -1;
+ if ((meta_class->methodLists = calloc(1, sizeof(struct objc_method_list *))) == NULL) {
+ free(new_class->methodLists);
+ free((void *)new_class->name);
+ free(new_class);
+ return Nil;
+ }
+ *meta_class->methodLists = (struct objc_method_list *) -1;
+
+ // Connect the class definition to the class hierarchy:
+ // Connect the class to the superclass.
+ // Connect the metaclass to the metaclass of the superclass.
+ // Connect the metaclass of the metaclass to the metaclass of the root class.
+ new_class->super_class = super_class;
+ meta_class->super_class = super_class->isa;
+ meta_class->isa = (void *)root_class->isa;
+
+ // Set the sizes of the class and the metaclass.
+ new_class->instance_size = super_class->instance_size;
+ meta_class->instance_size = meta_class->super_class->instance_size;
+
+ return new_class;
+}
+
+/* Add an array of methods. Null terminated by name array */
+/* We assume that the class is being created, and that there are */
+/* no existing methods. */
+BOOL registerDynamicMethods(Class cls, const char *mnames[], IMP mimps[], const char *mtypes[]) {
+ int i, nmeth;
+ struct objc_method_list *methodList;
+
+ /* Count the number of methods */
+ for (nmeth = 0; mnames[nmeth] != NULL && mnames[nmeth][0] != '\000'; nmeth++)
+ ;
+
+ /* Allocate an array */
+ methodList = malloc(sizeof(struct objc_method_list) + (nmeth-1) * sizeof(struct objc_method));
+
+ methodList->method_count = nmeth;
+ for (i = 0; i < nmeth; i++) {
+ // Get or register the selector for the method name
+ SEL methodSEL = SELUID(mnames[i]);
+
+ // Registering the method seems to register the selector
+ if (ISSELECTOR(methodSEL) == NO) {
+ methodSEL = sel_registerName(mnames[i]);
+ }
+
+ // Fill out the method list
+ methodList->method_list[i].method_name = methodSEL;
+ methodList->method_list[i].method_imp = mimps[i];
+ methodList->method_list[i].method_types = strdup(mtypes[i]);
+ }
+
+ // Register our methods
+ class_addMethods((Class)cls, methodList);
+
+ return YES;
+}
+
+/* Add an array of instance variables. Null terminated by name array */
+/* We assume that the class is being created, and that there are */
+/* no existing methods. */
+BOOL registerDynamicVariables(Class cls, const char *names[], size_t sizes[], const char *types[]) {
+ int i, nvar = 1;
+ int vsize;
+ struct objc_ivar *ivarp;
+
+ /* Count the number of variables */
+ for (nvar = 0; names[nvar] != NULL && names[nvar][0] != '\000'; nvar++)
+ ;
+
+ vsize = sizeof(struct objc_ivar_list) + (nvar - 1) * sizeof(struct objc_ivar);
+ cls->ivars = calloc(vsize, 1);
+ cls->ivars->ivar_count = nvar;
+
+ for (i = 0; i < nvar; i++) {
+ int abytes;
+ ivarp = &cls->ivars->ivar_list[i];
+
+ /* Set the variable information */
+ ivarp->ivar_name = strdup(names[i]);
+ ivarp->ivar_type = strdup(types[i]);
+
+ /* Align the offset for this variable to it's size, limiting to 64 bits */
+ if ((abytes = sizes[i]) > 8)
+ abytes = 8;
+ cls->instance_size = (cls->instance_size + abytes-1) & ~(abytes-1);
+ ivarp->ivar_offset = (int)cls->instance_size;
+ cls->instance_size += sizes[i];
+ }
+
+ return YES;
+}
+
+#endif /* __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 */
+
+extern id NSApp;
+
+/* Create a class */
+BOOL registerClass(
+const char *name, /* Name of class being created */
+const char *supername, /* Name of superclass */
+const char *methnames[], /* List of method names, empty string terminated */
+IMP methimps[], /* Method implementations */
+const char *methsigs[], /* Method signatures */
+const char *varnames[], /* List of variable names, empty string terminated */
+size_t varsizes[], /* Variable size in bytes */
+const char *varsigs[] /* Variable signatures */
+) {
+ int i;
+ Class nclass;
+
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
+ nclass = objc_allocateClassPair((Class)objc_getClass(supername), name, 0);
+ if (nclass == Nil) {
+ return NO;
+ }
+
+ for (i = 0; methnames[i] != NULL && methnames[i][0] != '\000'; i++) {
+ class_addMethod(nclass, sel_getUid(methnames[i]), methimps[i], methsigs[i]);
+ }
+
+ // Should check return value is YES
+ for (i = 0; varnames[i] != NULL && varnames[i][0] != '\000'; i++) {
+ int asize;
+ while( (1 << asize) < varsizes[i] && asize < 8)
+ asize++;
+ class_addIvar(nclass, varnames[i], varsizes[i], asize, varsigs[i]);
+ }
+
+ // Must be called after adding instance variable
+ objc_registerClassPair(nclass);
+#else
+ /* Use compat.h functions to do the dirty work */
+ // Should check the return value!
+ if ((nclass = CreateClassDefinition(name, supername)) == Nil) {
+ return NO;
+ }
+
+ registerDynamicMethods(nclass, methnames, methimps, methsigs);
+
+ registerDynamicVariables(nclass, varnames, varsizes, varsigs);
+
+ // Register the class with the runtime.
+ objc_addClass(nclass);
+#endif
+ return YES;
+}
+
+/* ------------------------------------------------ */
+/* One of the primary disadvantages of coding Coccoa in C */
+/* is the lack of compatible .h files. We have to make our own.. */
+
+/* ------------------------------------------------ */
+
+/* Foundation stuff */
+
+#ifndef __OBJC__
+
+#if !defined(FSTATIC_INLINE)
+# if defined (__GNUC__) && (__GNUC__ == 4)
+# define FSTATIC_INLINE static __inline__ __attribute__((always_inline))
+# else
+# define FSTATIC_INLINE static __inline__
+# endif
+#endif
+
+#ifdef __LP64__
+typedef double NSFloat;
+#else
+typedef float NSFloat;
+#endif
+
+typedef struct _NSPoint {
+ NSFloat x;
+ NSFloat y;
+} NSPoint;
+
+FSTATIC_INLINE NSPoint NSMakePoint(NSFloat x, NSFloat y) {
+ NSPoint r;
+ r.x = x;
+ r.y = y;
+ return r;
+}
+
+typedef struct _NSSize {
+ NSFloat width;
+ NSFloat height;
+} NSSize;
+
+FSTATIC_INLINE NSSize NSMakeSize(NSFloat w, NSFloat h) {
+ NSSize r;
+ r.width = w;
+ r.height = h;
+ return r;
+}
+
+
+typedef struct _NSRect {
+ NSPoint origin;
+ NSSize size;
+} NSRect;
+
+FSTATIC_INLINE NSRect NSMakeRect(NSFloat x, NSFloat y, NSFloat w, NSFloat h) {
+ NSRect r;
+ r.origin.x = x;
+ r.origin.y = y;
+ r.size.width = w;
+ r.size.height = h;
+ return r;
+}
+
+#endif /* !__OBJC__ */
+
+/* ------------------------------------------------ */
+/* Constats for NSString class */
+
+/* 10.4 and latter */
+typedef enum {
+ NSStringDrawingUsesLineFragmentOrigin = (1 << 0),
+ NSStringDrawingUsesFontLeading = (1 << 1),
+ NSStringDrawingDisableScreenFontSubstitution = (1 << 2),
+ NSStringDrawingUsesDeviceMetrics = (1 << 3),
+ NSStringDrawingOneShot = (1 << 4),
+ NSStringDrawingTruncatesLastVisibleLine = (1 << 5)
+} NSStringDrawingOptions;
+
+/* ------------------------------------------------ */
+/* Constats for NSApplication class */
+
+typedef enum {
+ NSApplicationPresentationDefault = 0,
+ NSApplicationPresentationAutoHideDock = (1 << 0),
+ NSApplicationPresentationHideDock = (1 << 1),
+ NSApplicationPresentationAutoHideMenuBar = (1 << 2),
+ NSApplicationPresentationHideMenuBar = (1 << 3),
+ NSApplicationPresentationDisableAppleMenu = (1 << 4),
+ NSApplicationPresentationDisableProcessSwitching = (1 << 5),
+ NSApplicationPresentationDisableForceQuit = (1 << 6),
+ NSApplicationPresentationDisableSessionTermination = (1 << 7),
+ NSApplicationPresentationDisableHideApplication = (1 << 8),
+ NSApplicationPresentationDisableMenuBarTransparency = (1 << 9),
+ NSApplicationPresentationFullScreen = (1 << 10),
+ NSApplicationPresentationAutoHideToolbar = (1 << 11)
+} NSApplicationPresentationOptions;
+
+typedef enum {
+ NSTerminateCancel = 0,
+ NSTerminateNow = 1,
+ NSTerminateLater = 2
+} NSApplicationTerminateReply;
+
+/* ------------------------------------------------ */
+/* Constats for NSWindow class */
+
+enum {
+ NSBorderlessWindowMask = 0,
+ NSTitledWindowMask = 1 << 0,
+ NSClosableWindowMask = 1 << 1,
+ NSMiniaturizableWindowMask = 1 << 2,
+ NSResizableWindowMask = 1 << 3,
+ NSTexturedBackgroundWindowMask = 1 << 8
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
+ ,NSUnscaledWindowMask = 1 << 11,
+ NSUnifiedTitleAndToolbarWindowMask = 1 << 12
+#endif
+};
+
+/* types of window backing store */
+typedef enum {
+ NSBackingStoreRetained = 0,
+ NSBackingStoreNonretained = 1,
+ NSBackingStoreBuffered = 2
+} NSBackingStoreType;
+
+
+/* ------------------------------------------------ */
+/* Convenience functions */
+
+/* Transform process to interact with descktop */
+void transProcess() {
+ OSStatus stat;
+ ProcessSerialNumber psn = { 0, 0 };
+
+ if (GetCurrentProcess(&psn) != noErr) {
+ /* Transform the process so that the desktop interacts with it properly. */
+ /* We don't need resources or a bundle if we do this. */
+ if (psn.lowLongOfPSN != 0 && (stat = TransformProcessType(&psn,
+ kProcessTransformToForegroundApplication)) != noErr)
+ fprintf(stderr,"TransformProcess failed with code %d\n",stat);
+ }
+}
+
+/* Send a message to the object */
+#define sendMsg(oid, msg, ...) objc_msgSend(oid, sel_getUid(msg), ##__VA_ARGS__)
+
+/* alloc and init a new object */
+id newObject(const char *cname) {
+ id rv;
+ rv = objc_msgSend(objc_getClass(cname), sel_getUid("alloc"));
+ rv = objc_msgSend(rv, sel_getUid("init"));
+ return rv;
+}
+/* release an object */
+void delObject(id oid) {
+ objc_msgSend(oid, sel_getUid("release"));
+}
+
+/* dealloc super */
+void delObjectSuper(id oid) {
+ struct objc_super ss;
+ ss.receiver = oid;
+#ifdef __OBJC__
+ ss.super_class = sendMsg(oid, "superclass");
+#else
+ ss.class = (Class)sendMsg(oid, "superclass");
+#endif
+ objc_msgSendSuper(&ss, sel_getUid("dealloc"));
+}
+
+/* Create an NSString from a C string */
+id newNSString(const char *cstr) {
+ id str;
+
+ str = objc_msgSend(objc_getClass("NSString"), sel_getUid("alloc"));
+ str = objc_msgSend(str, sel_getUid("initWithUTF8String:"), cstr);
+
+ return str;
+}
+
+#define ACOCCOA_H
+#endif /* ACOCCOA_H */
diff --git a/plot/osx/helloc.c b/plot/osx/helloc.c
new file mode 100644
index 0000000..9150989
--- /dev/null
+++ b/plot/osx/helloc.c
@@ -0,0 +1,313 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __OBJC__
+# include <Foundation/Foundation.h>
+# include <AppKit/AppKit.h>
+#endif
+
+#include "acocoa.h" /* Argyll Cocoa support functions and defines */
+
+/*
+- (void) someMethod:...
+{
+ va_list va;
+
+ va_start(va, _cmd);
+
+ // process all args with va_arg
+
+ va_end(va);
+}
+ */
+
+/* Our static instance variables for AppDelegate */
+typedef struct {
+ id window; /* NSWindow */
+ id view; /* NSView */
+} cntx_t;
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+void MyView_setCntx(id self, SEL _cmd, void *val) {
+ object_setInstanceVariable(self, "cntx", val);
+}
+
+void MyView_drawRect(id self, SEL _cmd, NSRect rect) {
+ double w = rect.size.width, h = rect.size.height;
+
+ id aPath = sendClassMsg("NSBezierPath", "bezierPath");
+ sendMsg(aPath, "setLineWidth:", 2.0);
+ sendMsg(aPath, "moveToPoint:", NSMakePoint(0.0, 0.0));
+ sendMsg(aPath, "lineToPoint:", NSMakePoint(0.9 * w, 0.9 * h));
+ sendMsg(aPath, "appendBezierPathWithRect:", NSMakeRect(0.5 * w, 0.5 * h,
+ 0.7 * w, 0.6 * h));
+ sendMsg(aPath, "stroke");
+
+ {
+ id att = newObject("NSDictionary");
+ id str = newNSString("String");
+ sendMsg(str, "drawAtPoint:withAttributes:", NSMakePoint(0.1 * w, 0.1 * h), att);
+ }
+}
+
+/* Clean up */
+void MyView_dealloc(id self, SEL _cmd) {
+ delObjectSuper(self);
+}
+
+// Create our custom NSView */
+void createMyView() {
+ method_info minfo[] = {
+ { "setCntx:", (IMP)MyView_setCntx, "v@:^v" },
+ { "drawRect:", (IMP)MyView_drawRect, "v@:@" },
+ { "dealloc", (IMP)MyView_dealloc, "v@:" },
+ { "" }
+ };
+
+ variable_info vinfo[] = {
+ { "cntx", sizeof(void *), "^v" },
+ { "" }
+ };
+
+ registerClass("MyView", "NSView", minfo, vinfo);
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+void MyWin_setCntx(id self, SEL _cmd, void *val) {
+ object_setInstanceVariable(self, "cntx", val);
+}
+
+void MyWin_keyDown(id self, SEL _cmd, id event) {
+ int etype;
+ id nresp;
+ id str;
+ const char *cstr;
+
+ etype = (int)sendMsg(event, "type");
+ str = sendMsg(event, "characters");
+ cstr = cNSString(str);
+ printf("Got Window KeyDown type %d, chars '%s'\n",etype, cstr);
+
+ if (cstr[0] == ' ')
+ sendMsg(NSApp, "terminate:", self);
+}
+
+/* Clean up */
+void MyWin_dealloc(id self, SEL _cmd) {
+ delObjectSuper(self);
+}
+
+// Create our custom NSWin */
+void createMyWin() {
+ method_info minfo[] = {
+ { "setCntx:", (IMP)MyWin_setCntx, "v@:^v", },
+ { "keyDown:", (IMP)MyWin_keyDown, "v@:@", },
+ { "dealloc", (IMP)MyWin_dealloc, "v@:" },
+ { "" }
+ };
+
+ variable_info vinfo[] = {
+ { "cntx", sizeof(void *), "^v" },
+ { "" }
+ };
+
+ registerClass("MyWin", "NSWindow", minfo, vinfo);
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+
+/* Create all the bits */
+void AppDel_willFinishLaunching(id self, SEL _cmd, id notification) {
+ cntx_t *cx;
+ id label; /* NSTextField */
+
+ cx = calloc(1, sizeof(cntx_t));
+
+ // Set cntx to to allocated structure
+ object_setInstanceVariable(self, "cntx", (void *)cx);
+
+ /* Create Window */
+ cx->window = sendClassMsg("MyWin", "alloc");
+ cx->window = sendMsg(cx->window,
+ "initWithContentRect:styleMask:backing:defer:",
+ NSMakeRect(300, 300, 200, 100),
+ NSTitledWindowMask
+ | NSClosableWindowMask
+ | NSMiniaturizableWindowMask
+ | NSResizableWindowMask,
+ NSBackingStoreBuffered,
+ YES);
+
+ /* Make the background white */
+ sendMsg(cx->window, "setBackgroundColor:", sendClassMsg("NSColor","whiteColor"));
+
+ /* Add title */
+ sendMsg(cx->window, "setTitle:", newNSString("Hello World"));
+
+#ifdef NEVER
+ /* Create Label */
+ label = sendClassMsg("NSTextField", "alloc");
+ label = sendMsg(label, "initWithFrame:", NSMakeRect(30, 30, 80, 30));
+
+ sendMsg(label, "setSelectable:", NO);
+ sendMsg(label, "setBezeled:", NO);
+ sendMsg(label, "setDrawsBackground:", NO);
+ sendMsg(label, "setStringValue:", newNSString("Hello World"));
+
+ /* Hmm. How does this work ? */
+ cx->view = sendMsg(cx->window, "contentView");
+ sendMsg(cx->view, "addSubview:", label);
+#else
+ /* Use our custom view to draw contents */
+ cx->view = newObject("MyView");
+
+ sendMsg(cx->view, "setCntx:", (void *)cx);
+ sendMsg(cx->window, "setContentView:", cx->view);
+
+// sendMsg(cx->window, "setInitialFirstResponder:", cx->view);
+#endif
+
+ // Window methods:
+
+ // sendEvent: gets messages.
+
+ // Set above the screen saver
+ // [aWindow setLevel:NSScreenSaverWindowLevel + 1];
+
+ // setCollectionBehavior: NSWindowCollectionBehaviorIgnoresCycle
+ // NSWindowCollectionBehaviorFullScreenPrimary
+ // NSWindowCollectionBehaviorStationary
+ // NSWindowCollectionBehaviorIgnoresCycle
+
+ // center
+ // mouseDownCanMoveWindow
+ // setMovable:
+ // setContentMinSize: and setContentMaxSize:
+ //
+ // NSRect frame = [myWindow frame];
+ // if (frame.size.width <= MIN_WIDTH_WITH_ADDITIONS)
+ // frame.size.width = MIN_WIDTH_WITH_ADDITIONS;
+ // frame.size.height += ADDITIONS_HEIGHT;
+ // frame.origin.y -= ADDITIONS_HEIGHT;
+ // [myWindow setFrame:frame display:YES animate:YES];
+ // objc_msgSend(label, "release"));
+ //
+ // setExcludedFromWindowsMenu:YES
+ //
+ // setBackgroundColor: and setAlphaValue:
+
+ // WindowImage object:
+ // setDepthLimit:
+
+ // Setting cursor:
+ // NSTrackingArea class, along with the cursorUpdate: method of the NSResponder class
+
+}
+
+/* Map the window */
+void AppDel_didFinishLaunching(id self, SEL _cmd, id notification) {
+ cntx_t *cx;
+
+ object_getInstanceVariable(self, "cntx", (void **)&cx);
+ sendMsg(cx->window, "makeKeyAndOrderFront:", self);
+
+#ifdef NEVER /* Test terminate */
+ sleep(5);
+ sendMsg(NSApp, "terminate:", self);
+#endif
+}
+
+/* Should the application terminate ? */
+NSApplicationTerminateReply AppDel_shouldTerminate(id self, SEL _cmd, id notification) {
+ return NSTerminateNow;
+}
+
+/* Clean up */
+void AppDel_dealloc(id self, SEL _cmd) {
+ cntx_t *cx;
+
+ object_getInstanceVariable(self, "cntx", (void **)&cx);
+ delObject(cx->window);
+ delObjectSuper(self);
+}
+
+// Create the delegate class that implements our window
+void createAppDelClass() {
+ method_info minfo[] = {
+ { "applicationWillFinishLaunching:", (IMP)AppDel_willFinishLaunching, "v@:@" },
+ { "applicationDidFinishLaunching:", (IMP)AppDel_didFinishLaunching, "v@:@" },
+ { "applicationShouldTerminate:", (IMP)AppDel_shouldTerminate, "i@:@" },
+ { "dealloc", (IMP)AppDel_dealloc, "v@:" },
+ { "" }
+ };
+
+ variable_info vinfo[] = {
+ { "cntx", sizeof(void *), "^v" },
+ { "" }
+ };
+
+ registerClass("AppDelegate", "NSObject", minfo, vinfo);
+}
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - */
+int main(int argc, char** argv) {
+ id pool;
+ id appDelObj;
+
+ /* Transform process so that it interacts with desktop properly */
+ transProcess();
+
+ /* Create an autorelease pool */
+ pool = newObject("NSAutoreleasePool");
+
+ // Create all the classes we override
+ createAppDelClass();
+ createMyWin();
+ createMyView();
+
+ // Get our shared NSApplication and start it
+ sendClassMsg("NSApplication", "sharedApplication");
+
+ if (NSApp == NULL) {
+ fprintf(stderr,"Failed to initialized NSApplication... terminating...\n");
+ return -1;
+ }
+
+ /* Set a delegate to create the window */
+ appDelObj = newObject("AppDelegate");
+ sendMsg(NSApp, "setDelegate:", appDelObj);
+
+// if running on 10.7:
+// sendMsg(NSApp, "disableRelaunchOnLogin"));
+
+ /* Call the run loop */
+ sendMsg(NSApp, "run");
+
+ // detachDrawingThread:toTarget:withObject:
+
+ /* To terminate:
+ sendMsg(NSApp, "terminate:", self);
+ */
+
+ /* We're done with the pool */
+ delObject(pool);
+
+ return EXIT_SUCCESS;
+}
+
+#ifdef NEVER
+
+- (void)drawRect:(NSRect)rect
+{
+ NSRect r = NSMakeRect(10, 10, 50, 60);
+ NSBezierPath *bp = [NSBezierPath bezierPathWithRect:r];
+ NSColor *color = [NSColor blueColor];
+ [color set];
+ [bp fill];
+}
+
+#endif
diff --git a/plot/osx/hellom.m b/plot/osx/hellom.m
new file mode 100644
index 0000000..b306878
--- /dev/null
+++ b/plot/osx/hellom.m
@@ -0,0 +1,181 @@
+
+#include <Foundation/Foundation.h>
+#include <AppKit/AppKit.h>
+
+#include <objc/objc-runtime.h> /* For diagnostics */
+
+typedef struct {
+ id window; /* NSWindow */
+ id view; /* NSTextField */
+} cntx_t;
+
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+@interface MyView : NSView {
+ void *cntx;
+}
+- (void)setCntx:(void *)cntx;
+@end
+
+@implementation MyView
+
+- (void)setCntx:(void *)val {
+ cntx = val;
+}
+
+- (void)drawRect:(NSRect)rect {
+// NSGraphicsContext* aContext = [NSGraphicsContext currentContext];
+
+ [[NSColor redColor] setStroke];
+
+ NSBezierPath* aPath = [NSBezierPath bezierPath];
+ [aPath setLineWidth:2.0];
+ [aPath moveToPoint:NSMakePoint(0.0, 0.0)];
+ [aPath lineToPoint:NSMakePoint(100.0, 100.0)];
+ [aPath appendBezierPathWithRect:NSMakeRect(20.0, 160.0, 80.0, 50.0)];
+
+ [aPath stroke];
+
+ NSDictionary *att = [NSDictionary new];
+
+ [ @"String" drawAtPoint: NSMakePoint(10.0, 10.0) withAttributes: att ];
+
+/*
+
+[@"Hello" drawInRect:r withAttributes:[NSDictionary
+dictionaryWithObjectsAndKeys:
+[NSColor redColor], NSForegroundColorAttributeName,
+[NSFont systemFontOfSize:24], NSFontAttributeName,
+nil]];
+
+*/
+}
+
+@end
+
+/* To trigger an update:
+
+Send a setNeedsDisplayInRect: or setNeedsDisplay: message to the
+view. Sending either of these messages marks part or all of the view as invalid
+
+ */
+
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+
+@interface MyWin : NSWindow {
+ void *cntx;
+}
+- (void)setCntx:(void *)cntx;
+@end
+
+@implementation MyWin
+
+- (void)setCntx:(void *)val {
+ cntx = val;
+}
+
+- (void)keyDown:(NSEvent *)event {
+ printf("Got Window KeyDown type %d char %s\n",[event type],
+ [[event characters] cStringUsingEncoding:NSASCIIStringEncoding]);
+}
+
+- (BOOL)windowShouldClose:(id)sender {
+ printf("Got Window windowShouldClose\n");
+ [NSApp terminate: nil];
+ return YES;
+}
+
+@end
+
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+
+@interface AppDelegate : NSObject {
+ void *cntx;
+}
+@end
+
+@implementation AppDelegate
+- (void) applicationWillFinishLaunching: (NSNotification *)not {
+ cntx_t *cx;
+
+ cx = calloc(1, sizeof(cntx_t));
+
+ cntx = (void *)cx;
+
+ /* Create Window */
+ cx->window = [[MyWin alloc] initWithContentRect: NSMakeRect(300, 300, 200, 100)
+ styleMask: (NSTitledWindowMask |
+ NSClosableWindowMask |
+ NSMiniaturizableWindowMask |
+ NSResizableWindowMask)
+ backing: NSBackingStoreBuffered
+ defer: YES];
+ [cx->window setTitle: @"Hello World"];
+
+#ifdef NEVER
+ /* Create Label */
+ cx->label = [[NSTextField alloc] initWithFrame: NSMakeRect(30, 30, 80, 30)];
+ [cx->label setSelectable: NO];
+ [cx->label setBezeled: NO];
+ [cx->label setDrawsBackground: NO];
+ [cx->label setStringValue: @"Hello World"];
+
+ [[cx->window contentView] addSubview: cx->label];
+
+ [cx->label release];
+
+#else
+ cx->view = [MyView new];
+ [cx->view setCntx:(void *)cx];
+ [cx->window setContentView: cx->view];
+#endif
+ // [window setContentView:customView]
+}
+
+- (void) applicationDidFinishLaunching: (NSNotification *) not {
+ cntx_t *cx = (cntx_t *)cntx;
+ [cx->window makeKeyAndOrderFront: self];
+}
+
+- (void) dealloc {
+ cntx_t *cx = (cntx_t *)cntx;
+ [cx->window release];
+ [super dealloc];
+}
+@end
+
+// - - - - - - - - - - - - - - - - - - - - - - - - -
+
+int main (int argc, const char **argv)
+{
+ NSAutoreleasePool *pool;
+ id appDelObj;
+
+ if (NSApp == nil) {
+ OSStatus stat;
+ ProcessSerialNumber psn = { 0, 0 };
+
+ if (GetCurrentProcess(&psn) == noErr) {
+ /* Transform the process so that the desktop interacts with it properly. */
+ /* We don't need resources or a bundle if we do this. */
+ if (psn.lowLongOfPSN != 0 && (stat = TransformProcessType(&psn,
+ kProcessTransformToForegroundApplication)) != noErr)
+ fprintf(stderr,"TransformProcess failed with code %d\n",stat);
+ }
+
+ pool = [NSAutoreleasePool new];
+
+ [NSApplication sharedApplication];
+ appDelObj = [AppDelegate new];
+ [NSApp setDelegate: appDelObj];
+
+ // Run the event loop until done
+ [NSApp run];
+
+ [pool release];
+ }
+
+ // To terminate:
+ // [NSApp terminate: nil];
+}
+
+