class library: Spawner - don't access PriorityQueue-array
[supercollider.git] / editors / scapp / CocoaBridgePrimitives.M
blob7c022e74dca69763f5fa323db6d55a31a8c66ae8
1 /*
2 * CocoaBridgePrimitives.M
3 * SC3lang
5 * Created by Jan Trutzschler 08/2005.
8 sc3 bridge to obj-c/cocoa
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #import <Cocoa/Cocoa.h>
28 #import <objc/objc-runtime.h>
29 #import <objc/Object.h>
30 #import <QTKit/QTTime.h>
31 #import <QTKit/QTTimeRange.h>
32 #import <Foundation/NSMethodSignature.h>
33 #import "SCBase.h"
34 #import "PyrSymbol.h"
35 #import "PyrPrimitive.h"
36 #import "PyrObject.h"
37 #import "PyrKernel.h"
38 #import "VMGlobals.h"
39 #import "MyDocument.h"
40 #import "GC.h"
41 #import "SCVirtualMachine.h"
43 #if (MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4)
44 #define class_getName(a) ((a)->name)
45 #endif
47 #define COCOABRIDGE_VERBOSITY 0
48 #define COCOABRIDGE_STORE_OBJECTS_IN_ARRAY 1 // Conditional for storing all created objects in an NSArray. For future test with special Pool.
49 #define COCOABRIDGE_AUTOCONVERT_NSSTRING 1 /* for backward compat. set to 0.
50 Used only for converting NSString to PyrString on INVOCATION RETURN.
51 PyrString are automatically converted to NSString when passed as arguments
53 #if COCOABRIDGE_VERBOSITY
54 #define COCOABRIDGE_OBJ_RETAIN_LOG(nsobj) NSLog(@"OBJ_RETA NSObject(%p), type(%@)", nsobj, [nsobj class]);
55 #define COCOABRIDGE_OBJ_RELEASE_LOG(nsobj) NSLog(@"OBJ_RELE NSObject(%p), type(%@)", nsobj, [nsobj class]);
56 #define COCOABRIDGE_POOL_ADD_LOG(nsobj) NSLog(@"POOL_ADD NSObject(%p), type(%@), POOL_OBJ_NUMBER: %i", nsobj, [nsobj class], [nsobjects count]);
57 #define COCOABRIDGE_POOL_REM_LOG(nsobj) NSLog(@"POOL_REM NSObject(%p), type(%@), POOL_OBJ_NUMBER: %i", nsobj, [nsobj class], [nsobjects count]-1);
58 #else
59 #define COCOABRIDGE_OBJ_RETAIN_LOG(nsobj) ;
60 #define COCOABRIDGE_OBJ_RELEASE_LOG(nsobj) ;
61 #define COCOABRIDGE_POOL_ADD_LOG(nsobj) ;
62 #define COCOABRIDGE_POOL_REM_LOG(nsobj) ;
63 #endif
65 #if COCOABRIDGE_STORE_OBJECTS_IN_ARRAY
66 # define COCOABRIDGE_POOL_ADD(nsobj) \
67 do { \
68 [nsobjects addObject: nsobj]; \
69 COCOABRIDGE_POOL_ADD_LOG(nsobj) \
70 } while(0);
72 # define COCOABRIDGE_POOL_REM(nsobj) \
73 do { \
74 COCOABRIDGE_POOL_REM_LOG(nsobj) \
75 [nsobjects removeObject: nsobj]; \
76 } while(0);
77 #else
78 # define COCOABRIDGE_POOL_ADD(nsobj)
79 # define COCOABRIDGE_POOL_REM(nsobj)
80 #endif
82 #define COCOABRIDGE_OBJ_RETAIN(nsobj) \
83 do { \
84 /*[nsobj retain];*/ \
85 /*COCOABRIDGE_OBJ_RETAIN_LOG(nsobj)*/ \
86 COCOABRIDGE_POOL_ADD(nsobj) \
87 }while(0)
89 #define COCOABRIDGE_OBJ_RELEASE(nsobj) \
90 do { \
91 /*COCOABRIDGE_OBJ_RELEASE_LOG(nsobj)*/ \
92 COCOABRIDGE_POOL_REM(nsobj) \
93 /*[nsobj release];*/ \
94 }while(0)
96 #define TryInvocation(anInvocation, receiver) \
97 @try { \
98 [anInvocation invoke]; \
99 }@catch(NSException* e){ \
100 post("ERROR: CocoaBridge exception caught: %s %s\n", [[e name]UTF8String], [[e reason]UTF8String]); \
101 SetNil(receiver); \
102 return errFailed; \
106 PyrSymbol *s_nsObject;
107 //NSAutoreleasePool *nsAutoReleasePool;
109 #if COCOABRIDGE_STORE_OBJECTS_IN_ARRAY
110 //NSMutableSet *nsobjects = nil;
111 NSMutableArray *nsobjects = nil;
112 #endif
115 inline NSString* nsStringFromPyrSlot(PyrSlot *slot)
117 if(IsSym(slot)) {
118 NSString* retval;
119 int len = strlen(slotRawSymbol(slot)->name);
120 char* symstr = (char*)malloc(len+1);
121 strcpy(symstr, slotRawSymbol(slot)->name);
122 #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
123 retval = [NSString stringWithCString:symstr length:len]; // Deprecated 10.4
124 #else
125 retval = [NSString stringWithCString:symstr encoding:NSASCIIStringEncoding];
126 #endif
127 free(symstr);
128 return retval;
130 else {
131 PyrString* pyrString = slotRawString(slot);
132 #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
133 return [NSString stringWithCString: pyrString->s length: pyrString->size]; // Deprecated 10.4
134 #else
135 char* symstr = (char*)malloc(pyrString->size + 1);
136 memcpy(symstr, pyrString->s, pyrString->size); symstr[pyrString->size] = 0;
137 NSString *retval = [NSString stringWithCString:symstr encoding:NSASCIIStringEncoding];
138 free(symstr);
139 return retval;
140 #endif
145 inline int ObjcTypeFillPyrSlot(PyrSlot* slot, const char* type, void* value, PyrObjectHdr** retPyrObject ) {
146 VMGlobals *g = gMainVMGlobals;
148 if(retPyrObject)
149 *retPyrObject = NULL;
151 if(*type == 'r') ++type;
152 switch(*type) {
153 case _C_ID:
155 id idval = *(id*)value;
156 if([idval isKindOfClass:[NSColor class]]) {
157 //NSLog(@"ObjcTypeFillPyrSlot [_NSCOLOR]");
158 NSColor* nscol = [idval colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
159 PyrObject *color = instantiateObject(g->gc, s_color->u.classobj, 0, false, true);
160 PyrSlot *slots = color->slots;
161 SetFloat(slots+0, [nscol redComponent]);
162 SetFloat(slots+1, [nscol greenComponent]);
163 SetFloat(slots+2, [nscol blueComponent]);
164 SetFloat(slots+3, [nscol alphaComponent]);
165 SetObject(slot, color);
166 if(retPyrObject)
167 *retPyrObject = color;
169 #if COCOABRIDGE_AUTOCONVERT_NSSTRING
170 else if([idval isKindOfClass:[NSString class]]) {
171 //NSLog(@"ObjcTypeFillPyrSlot [_NSSTRING]");
172 NSString* string = (NSString*)idval;
173 PyrString* pyrPathString = newPyrString(g->gc,[string UTF8String],0,true);
174 SetObject(slot, pyrPathString);
175 if(retPyrObject)
176 *retPyrObject = pyrPathString;
178 #endif
179 else {
180 //NSLog(@"ObjcTypeFillPyrSlot [_C_ID]");
181 if(idval) {
182 COCOABRIDGE_OBJ_RETAIN(idval);
183 SetPtr(slot, (id) idval);
184 }else
185 SetNil(slot);
188 break;
190 case _C_VOID:
191 case _C_UNDEF:
192 //NSLog(@"ObjcTypeFillPyrSlot [_C_VOID | _C_UNDEF]");
193 SetNil(slot);
194 break;
196 case _C_CHR:
197 case _C_UCHR:
198 //NSLog(@"ObjcTypeFillPyrSlot [_C_CHR | _C_UCHAR]");
199 //SetChar(slot, *(char*)value);
200 SetInt(slot, *(char*)value);
201 break;
204 case _C_LNG:
205 case _C_ULNG:
207 //NSLog(@"ObjcTypeFillPyrSlot [_C_LONG...]");
208 long sval = *(long*)value;
209 SetInt(slot, sval);
211 break;
213 case _C_SHT:
214 case _C_USHT:
216 //NSLog(@"ObjcTypeFillPyrSlot [_C_SHORT...]");
217 short sval = *(short*)value;
218 SetInt(slot, sval);
220 break;
222 case _C_INT:
223 case _C_UINT:
225 //NSLog(@"ObjcTypeFillPyrSlot [_C_INT...]");
226 SetInt(slot, *(int*)value);
228 break;
230 case _C_FLT:
232 float fval = *(float*)value;
233 SetFloat(slot, fval);
235 break;
237 case _C_DBL:
239 //NSLog(@"ObjcTypeFillPyrSlot [_C_FLT...]");
240 double dval = *(double*)value;
241 SetFloat(slot, dval);
243 break;
245 case 'B':
247 //NSLog(@"ObjcTypeFillPyrSlot [BOOLEAN...]");
248 bool b = *(bool*)value;
249 if(b)
250 SetTrue(slot);
251 else
252 SetFalse(slot);
254 break;
256 case _C_BFLD:
257 //NSLog(@"ObjcTypeFillPyrSlot [_C_BFLD BITFIELD...]");
258 SetNil(slot);
259 break;
261 case _C_PTR:
262 //NSLog(@"ObjcTypeFillPyrSlot [_C_CHR | _C_UCHAR]");
263 SetPtr(slot, *(void**)value);
264 break;
266 case _C_SEL:
268 //NSLog(@"ObjcTypeFillPyrSlot [_C_SEL]");
269 SEL sel = *(SEL*)value;
270 PyrString* pyrPathString = newPyrString(g->gc, sel_getName(sel), 0, true);
271 SetObject(slot, pyrPathString);
272 if(retPyrObject)
273 *retPyrObject = pyrPathString;
275 break;
277 case _C_CHARPTR:
279 //NSLog(@"ObjcTypeFillPyrSlot [_C_CHARPTR | r]");
280 char* str = *(char**)value;
281 PyrString* pyrPathString = newPyrString(g->gc, str,0,true);
282 SetObject(slot, pyrPathString);
283 if(retPyrObject)
284 *retPyrObject = pyrPathString;
286 break;
288 case _C_STRUCT_B:
291 support only for basic types.
292 TODO: plug some functions of the PyObjc to parse structure types.
295 if(strncmp(type+1, "_NSSize", 7) == 0) {
296 //NSLog(@"ObjcTypeFillPyrSlot [_NSSize]");
297 // return an array
298 PyrObject *array = ::instantiateObject(g->gc, s_array->u.classobj, 2, true, true);
299 if(!array) return errOutOfMemory;
300 NSSize s = *(NSSize*)value;
301 SetFloat(array->slots+0, s.width);
302 SetFloat(array->slots+1, s.height);
303 SetObject(slot, array);
304 if(retPyrObject)
305 *retPyrObject = array;
307 }else if(strncmp(type+1, "_NSRange", 8) == 0) {
308 //NSLog(@"ObjcTypeFillPyrSlot [_NSRange]");
309 // return an array
310 PyrObject *array = ::instantiateObject(g->gc, s_array->u.classobj, 2, true, true);
311 if(!array) return errOutOfMemory;
312 NSRange r = *(NSRange*)value;
313 SetInt(array->slots+0, r.location);
314 SetInt(array->slots+1, r.length);
315 SetObject(slot, array);
316 if(retPyrObject)
317 *retPyrObject = array;
318 }else if(strncmp(type+1, "_NSRect", 7) == 0) {
319 //NSLog(@"ObjcTypeFillPyrSlot [_NSRect]");
320 // return a SCRect
321 PyrSlot *slots;
322 PyrObject *rect = instantiateObject(g->gc, s_rect->u.classobj, 0, false, true);
323 NSRect r = *(NSRect*)value;
325 slots = rect->slots;
326 SetFloat(slots+0, r.origin.x);
327 SetFloat(slots+1, r.origin.y);
328 SetFloat(slots+2, r.size.width);
329 SetFloat(slots+3, r.size.height);
330 SetObject(slot, rect);
331 if(retPyrObject)
332 *retPyrObject = rect;
333 }else if(strncmp(type+1, "_NSPoint", 8) == 0) {
334 //NSLog(@"ObjcTypeFillPyrSlot [_NSPoint]");
335 // return a SCPoint
336 PyrSlot *slots;
337 PyrObject *point = instantiateObject(g->gc, s_point->u.classobj, 0, false, true);
338 NSPoint p = *(NSPoint*)value;
340 slots = point->slots;
341 SetFloat(slots+0, p.x);
342 SetFloat(slots+1, p.y);
343 SetObject(slot, point);
344 if(retPyrObject)
345 *retPyrObject = point;
346 }else if(strncmp(type, "{?=qll}", 7) == 0) { // QTTime
347 PyrObject *pyrarray = instantiateObject(g->gc, s_array->u.classobj, 3, true, true);
348 if(!pyrarray) return errOutOfMemory;
349 QTTime p = *(QTTime*)value;
350 SetInt(pyrarray->slots+0, (int)p.timeValue);
351 SetInt(pyrarray->slots+1, (int)p.timeScale);
352 SetInt(pyrarray->slots+2, (int)p.flags);
353 SetObject(slot, pyrarray);
354 if(retPyrObject)
355 *retPyrObject = pyrarray;
356 }else{
357 //NSLog(@"ObjcTypeFillPyrSlot [_C_STRUCT]");
358 SetNil(slot);
359 post("Warning: CocoaBridge objc structure type not supported.\n");
361 //cType[ptr-cType-1] = '=';
363 break;
365 case _C_ARY_E:
366 case _C_UNION_E:
367 case _C_STRUCT_E:
368 //NSLog(@"ObjcTypeFillPyrSlot [_C_STRUCT | _C_UNION | _C_ARY_E]");
369 return errNone;
371 // not handled
372 case _C_CLASS:
373 case _C_ARY_B:
374 case _C_UNION_B:
375 //case _C_STRUCT_B:
376 default:
377 SetNil(slot);
378 post("ERROR: ObjcType conversion not handled: %c!\n", *type);
379 return errWrongType;
382 return errNone;
386 //put this in a .h
387 @interface SCCocoaToLangAction : NSResponder
389 struct PyrObject *mSCObject;
390 NSMutableDictionary *mSelectorArray;
394 - (void)setSCObject: (struct PyrObject*)inObject;
395 - (struct PyrObject*)getSCObject;
396 - (void) doAction: (id) sender;
397 - (void) doFloatAction: (id) sender;
398 - (void) doIntAction: (id) sender;
399 - (void) doStateAction: (id) sender;
400 - (void) doFloatArrayAction: (id) sender;
401 - (void) doSCObjectAction: (id) sender;
403 - (void) keyUp: (NSEvent*) event;
404 - (void) keyDown: (NSEvent*) event;
405 - (void) mouseDown: (NSEvent*) event;
406 - (void)windowWillClose:(NSNotification *)aNotification;
407 - (void)notificationReceived:(NSNotification*)aNotification;
409 - (void)addSelector:(SEL)aSelector withObjcTypes:(const char*)cTypes;
410 - (void)removeSelector:(SEL)aSelector;
411 //- forward: (SEL)sel : (marg_list)args;
412 @end
415 extern bool compiledOK;
417 @implementation SCCocoaToLangAction
419 -(id)init {
420 if([super init]) {
421 mSelectorArray = [[NSMutableDictionary allocWithZone:[self zone]]initWithCapacity:16];
422 return self;
424 return nil;
426 - (void)setSCObject: (struct PyrObject*)inObject
428 mSCObject = inObject;
430 - (struct PyrObject*)getSCObject
432 return mSCObject;
434 - (void) doFloatAction: (id) sender
436 // post("doAction \n");
437 //need to sort out the event here ...
438 PyrObject * pobj = [self getSCObject];
439 if(compiledOK && pobj){
440 PyrSymbol *method = getsym("doAction");
441 VMGlobals *g = gMainVMGlobals;
442 g->canCallOS = true;
443 ++g->sp; SetObject(g->sp, pobj);
444 ++g->sp; SetFloat(g->sp, [sender floatValue]);
445 runInterpreter(g, method, 2);
446 g->canCallOS = false;
449 - (void) doAction: (id) sender
451 // post("doAction \n");
452 pthread_mutex_lock (&gLangMutex);
453 PyrObject * pobj = [self getSCObject];
454 if(compiledOK && pobj){
455 PyrSymbol *method = getsym("doAction");
456 VMGlobals *g = gMainVMGlobals;
457 g->canCallOS = true;
458 ++g->sp; SetObject(g->sp, pobj);
459 ++g->sp; SetInt(g->sp, 1);
460 runInterpreter(g, method, 2);
461 g->canCallOS = false;
463 pthread_mutex_unlock (&gLangMutex);
465 - (void) doStateAction: (id) sender
467 // post("doAction \n");
468 pthread_mutex_lock (&gLangMutex);
469 PyrObject * pobj = [self getSCObject];
470 if(compiledOK && pobj){
471 PyrSymbol *method = getsym("doAction");
472 VMGlobals *g = gMainVMGlobals;
473 g->canCallOS = true;
475 ++g->sp; SetObject(g->sp, pobj);
476 ++g->sp; SetInt(g->sp, [sender state]);
477 runInterpreter(g, method, 2);
478 g->canCallOS = false;
480 pthread_mutex_unlock (&gLangMutex);
483 - (void) doIntAction: (id) sender
485 pthread_mutex_lock (&gLangMutex);
486 PyrObject * pobj = [self getSCObject];
487 if(compiledOK && pobj){
488 PyrSymbol *method = getsym("doAction");
489 VMGlobals *g = gMainVMGlobals;
490 g->canCallOS = true;
491 ++g->sp; SetObject(g->sp, pobj);
492 ++g->sp; SetInt(g->sp, [sender intValue]);
493 runInterpreter(g, method, 2);
494 g->canCallOS = false;
496 pthread_mutex_unlock (&gLangMutex);
499 - (void) doArrayAction: (id) sender
501 pthread_mutex_lock (&gLangMutex);
502 PyrObject * pobj = [self getSCObject];
503 if(compiledOK && pobj){
504 PyrSymbol *method = getsym("doAction");
505 VMGlobals *g = gMainVMGlobals;
506 g->canCallOS = true;
507 ++g->sp; SetObject(g->sp, pobj);
508 //get Size
509 size_t size = (size_t) [sender arraySize];
510 float *src = (float*) [sender floatArray];
511 PyrDoubleArray* array = newPyrDoubleArray(g->gc, size, 0 , true);
512 for(int i=0; i<size; i++){
513 array->d[i] = src[i];
515 ++g->sp; SetObject(g->sp, array);
516 runInterpreter(g, method, 2);
517 g->canCallOS = false;
519 pthread_mutex_unlock (&gLangMutex);
523 /* experimental ! */
524 - (void) doFloatArrayAction: (id) sender
526 pthread_mutex_lock (&gLangMutex);
527 PyrObject * pobj = [self getSCObject];
528 if(compiledOK && pobj){
529 PyrSymbol *method = getsym("doAction");
530 VMGlobals *g = gMainVMGlobals;
531 g->canCallOS = true;
532 ++g->sp; SetObject(g->sp, pobj);
533 //get Size
534 size_t size = (size_t) [sender arraySize];
535 float *src = (float*) [sender floatArray];
536 PyrDoubleArray* array = newPyrDoubleArray(g->gc, size, 0 , true);
537 for(int i=0; i<size; i++){
538 array->d[i] = src[i];
540 ++g->sp; SetObject(g->sp, array);
541 runInterpreter(g, method, 2);
542 g->canCallOS = false;
544 pthread_mutex_unlock (&gLangMutex);
546 /* experimental ! */
547 - (void) doSCObjectAction: (id) sender
549 pthread_mutex_lock (&gLangMutex);
550 PyrObject * pobj = [self getSCObject];
551 if(compiledOK && pobj){
552 PyrSymbol *method = getsym("doAction");
553 VMGlobals *g = gMainVMGlobals;
554 g->canCallOS = true;
555 ++g->sp; SetObject(g->sp, pobj);
556 //push values from sender
557 PyrObject* reslut = (PyrObject*) [sender valueWith: self];
559 ++g->sp; SetObject(g->sp, reslut);
560 runInterpreter(g, method, 2);
561 g->canCallOS = false;
563 pthread_mutex_unlock (&gLangMutex);
566 - (void) keyUp: (NSEvent*) event
569 - (void) keyDown: (NSEvent*) event
571 post("keyDown in cocoaToLang \n");
573 - (void) mouseDown: (NSEvent*) event
575 post("doMouse \n");
579 - (void)dealloc {
580 mSCObject = NULL;
581 [mSelectorArray release];
582 [[NSNotificationCenter defaultCenter]removeObserver:self]; // in case
583 [super dealloc];
586 - (void)windowWillClose:(NSNotification *)aNotification
588 pthread_mutex_lock (&gLangMutex);
589 PyrObject * pobj = [self getSCObject];
590 if(compiledOK && pobj){
591 PyrSymbol *method = getsym("doAction");
592 VMGlobals *g = gMainVMGlobals;
593 g->canCallOS = true;
594 ++g->sp; SetObject(g->sp, pobj);
595 runInterpreter(g, method, 1);
596 g->canCallOS = false;
598 pthread_mutex_unlock (&gLangMutex);
602 //// added thelych
603 #pragma mark __SCCOCOATOLANG_FORWARD___
604 - (void)notificationReceived:(NSNotification*)aNotification
606 //post("notification received by delegate\n");
607 pthread_mutex_lock (&gLangMutex);
608 PyrObject * pobj = [self getSCObject];
609 if(compiledOK && pobj){
610 PyrSymbol *method = getsym("doNotificationAction");
611 VMGlobals *g = gMainVMGlobals;
613 g->canCallOS = true;
614 ++g->sp; SetObject(g->sp, pobj);
616 PyrString* pyrString = newPyrString(g->gc,[[aNotification name] cString],0,true);
617 ++g->sp; SetObject(g->sp, pyrString);
618 ++g->sp; SetPtr(g->sp, (void*)aNotification);
619 ++g->sp; SetPtr(g->sp, (void*)[aNotification object]);
621 runInterpreter(g, method, 4);
622 g->canCallOS = false;
624 pthread_mutex_unlock (&gLangMutex);
628 - (void*)forward: (SEL)sel : (marg_list)args {
629 NSLog(@"Forward invoked with Selector %s ", sel_getName(sel));
630 [super forward:sel :args];
634 -(NSMethodSignature*)methodSignatureForSelector:(SEL)aSel {
635 return (NSMethodSignature*)[mSelectorArray objectForKey:[NSNumber numberWithLong:(long)aSel]];
638 -(BOOL)respondsToSelector:(SEL)sel {
639 //post("trying %s ", sel_getName(sel));
640 NSEnumerator *e = [mSelectorArray keyEnumerator];
641 NSNumber* obj=nil;
642 while( (obj = (NSNumber*)[e nextObject]) ) {
643 SEL thesel = (SEL)[obj longValue];
644 if(sel == thesel) {
645 return YES;
648 return [super respondsToSelector:sel];
651 -(void)forwardInvocation:(NSInvocation*)inv {
653 SEL selector = [inv selector];
654 const char* retType = [[inv methodSignature]methodReturnType];
655 const char* csel = sel_getName(selector);
657 pthread_mutex_lock (&gLangMutex);
658 PyrObject * pobj = [self getSCObject];
659 if(compiledOK && pobj){
661 NSMethodSignature* nsSignature = [inv methodSignature];
662 int maxArgs = [nsSignature numberOfArguments];
664 PyrSymbol *method = getsym("doDelegateAction");
665 VMGlobals *g = gMainVMGlobals;
667 g->canCallOS = true;
668 ++g->sp; SetObject(g->sp, pobj);
670 PyrString* pyrString = newPyrString(g->gc, csel, 0, true);
671 ++g->sp; SetObject(g->sp, pyrString);
672 void* value;
674 //NSLog(@"NSInvocation Name: %s has %i number of arguments", csel, maxArgs);
676 ++g->sp;
677 if(maxArgs - 2 > 0) {
678 PyrObject* array;
679 PyrObjectHdr* pyrObject;
681 //array = newPyrArray(g->gc, 2, 0, true);
682 array = ::instantiateObject(g->gc, s_array->u.classobj, maxArgs-2, true, true);
683 SetObject(g->sp, array);
685 PyrSlot* slots = array->slots;
686 for(int i=2; i < maxArgs; ++i)
688 [inv getArgument:(void*)&value atIndex:i];
689 ObjcTypeFillPyrSlot(slots++, [nsSignature getArgumentTypeAtIndex:i], (void*)&value, &pyrObject);
690 if(pyrObject) {
691 g->gc->GCWrite(array, pyrObject);
695 else
696 SetNil(g->sp);
698 runInterpreter(g, method, 3);
700 g->canCallOS = false;
701 if(*retType != _C_VOID && *retType != _C_UNDEF) {
702 //NSLog(@"Setting NSInvocation Return Type");
703 //[inv retainArguments];
705 g = gMainVMGlobals;
706 PyrSlot* slot = &(g->result);
707 void * retbuffer=NULL;
709 if(*retType == 'r') ++retType;
710 switch(*retType) {
711 case _C_ID:
713 //NSLog(@"Setting [_C_ID]");
714 id retval = nil;
716 isKindOfSlot(slot, s_nsObject->u.classobj) ||
717 isKindOfSlot(slot, slotRawSymbol(&s_nsObject->u.classobj->superclass)->u.classobj)
719 //NSLog(@"Slot is a NSObject");
720 retval = (id)slotRawPtr(slotRawObject(slot)->slots);
722 else if(isKindOfSlot(slot, class_string) || IsSym(slot)) {
723 //NSLog(@"Slot is a string");
724 retval = (id)nsStringFromPyrSlot(slot);
726 else if(IsPtr(slot) ) {
727 //NSLog(@"Slot is a Pointer");
728 retval = (id)slotRawPtr(slot);
730 else if(IsFloat(slot)) {
731 //NSLog(@"Slot is a Float");
732 float f; NSNumber *n;
733 slotFloatVal(slot, &f);
734 n = [NSNumber numberWithFloat:f];
735 retval = (id)n;
737 else if(IsInt(slot)) {
738 //NSLog(@"Slot is an Int");
739 int i; NSNumber *n;
740 slotIntVal(slot, &i);
741 n = [NSNumber numberWithInt:i];
742 retval = (id)n;
744 else if(isKindOfSlot(slot, s_color->u.classobj)) {
745 //NSLog(@"Slot is a Color");
746 float r, g, b, a;
747 PyrSlot *slots = slotRawObject(slot)->slots;
748 slotFloatVal(slots+0, &r);
749 slotFloatVal(slots+1, &g);
750 slotFloatVal(slots+2, &b);
751 slotFloatVal(slots+3, &a);
752 NSColor *color = [NSColor colorWithCalibratedRed:r green:g blue:b alpha:a];
753 retval = (id)color;
755 else
756 post("ERROR: Cocoa Bridge wrong type. expected %c. Set to NIL\n", _C_ID);
757 retbuffer = (void*)&retval;
759 break;
761 case _C_UCHR:
762 case _C_CHR:
764 //NSLog(@"Setting [_C_CHR]");
765 char retval = 0;
766 if( IsChar(slot) )
767 retval = slotRawChar(slot);
768 else
769 post("ERROR: Cocoa Bridge wrong type. expected %c. Set to 0\n", _C_CHR);
770 retbuffer = (void*)&retval;
772 break;
774 case _C_SHT:
775 case _C_USHT: // same size PPC, PPC64, IA32...ect...
777 //NSLog(@"Setting [_C_SHT]");
778 int retval = 0; short shortval;
779 if( IsTrue(slot) )
780 retval = 1;
781 else if( IsFalse(slot) )
782 retval = 0;
783 else if(slotIntVal(slot, &retval) != errNone)
784 post("ERROR: Cocoa Bridge wrong type. expected %c\n", _C_SHT);
785 shortval = retval;
786 retbuffer = (void*)&shortval;
789 case _C_INT:
790 case _C_UINT: // same size PPC, PPC64, IA32...ect...
792 //NSLog(@"Setting [_C_INT]");
793 int retval = 0;
794 if( IsTrue(slot) )
795 retval = 1;
796 else if( IsFalse(slot) )
797 retval = 0;
798 else if(slotIntVal(slot, &retval) != errNone)
799 post("ERROR: Cocoa Bridge wrong type. expected %c\n", _C_INT);
800 retbuffer = (void*)&retval;
802 break;
804 case _C_LNG:
805 case _C_ULNG: // same size PPC, PPC64, IA32...ect...
807 //NSLog(@"Setting [_C_LNG]");
808 int retval = 0; long longval;
809 if( IsTrue(slot) )
810 retval = 1;
811 else if( IsFalse(slot) )
812 retval = 0;
813 else if(slotIntVal(slot, &retval) != errNone)
814 post("ERROR: Cocoa Bridge wrong type. expected %c\n", _C_LNG);
815 longval = (long)retval;
816 retbuffer = (void*)&longval;
818 break;
820 case _C_FLT:
822 //NSLog(@"Setting [_C_FLT]");
823 float retval = 0;
824 if(slotFloatVal(slot, &retval) != errNone)
825 post("ERROR: Cocoa Bridge wrong type. expected %c\n", _C_FLT);
826 retbuffer = (void*)&retval;
828 break;
830 case _C_DBL:
832 //NSLog(@"Setting [_C_DBL]");
833 double retval = 0;
834 if(slotDoubleVal(slot, &retval) != errNone)
835 post("ERROR: Cocoa Bridge wrong type. expected %c\n", _C_DBL);
836 retbuffer = (void*)&retval;
838 break;
840 case _C_PTR:
842 //NSLog(@"Setting [_C_PTR]");
843 void* ptr = 0;
844 if(IsPtr( slot )) {
845 ptr = slotRawPtr(slot);
846 retbuffer = &ptr;
848 else
849 post("ERROR: Cocoa Bridge wrong type. expected %c\n", _C_PTR);
851 break;
853 case _C_CHARPTR:
855 //NSLog(@"Setting [_C_CHARPTR | STRING]");
856 int size = 0;
857 char *retval = "";
859 if ( IsSym(slot) )
860 size = strlen(slotRawSymbol(slot)->name);
861 else if( isKindOfSlot(slot, class_string) ) {
862 size = ((PyrString*)slotRawObject(slot))->size;
864 else {
865 post("ERROR: Cocoa Bridge wrong type. expected %c. return ("")\n", _C_CHARPTR);
866 retbuffer = (void*)&retval;
867 break;
870 retval = (char*)malloc(sizeof(char) * (size+1));
871 slotStrVal(slot, retval, size);
872 retbuffer = (void*)&retval;
874 break;
876 case _C_STRUCT_B:
879 support only for basic types.
880 TODO: plug some functions of the PyObjc to parse structure types.
883 char * ptr, * cType;
884 cType = (char*)retType;
885 ptr = strchr(retType, '=') + 1;
886 cType[ptr-cType-1] = '\0';
888 if( (strcmp(cType+1, "_NSSize") == 0) && (
889 isKindOfSlot(slot, s_point->u.classobj) ||
890 isKindOfSlot(slot, class_array))
892 PyrSlot *slots = slotRawObject(slot)->slots;
893 NSSize s;
894 slotVal(slots+0, &s.width);
895 slotVal(slots+1, &s.height);
896 retbuffer = (void*)&s;
898 else if((strcmp(cType+1, "_NSRange") == 0) && (
899 isKindOfSlot(slot, s_point->u.classobj) ||
900 isKindOfSlot(slot, class_array))
902 PyrSlot *slots = slotRawObject(slot)->slots;
903 NSRange s;
904 slotIntVal(slots+0, (int*)&s.location);
905 slotIntVal(slots+1, (int*)&s.length);
906 retbuffer = (void*)&s;
908 else if((strcmp(cType+1, "_NSRect") == 0) && (
909 isKindOfSlot(slot, s_rect->u.classobj) ||
910 isKindOfSlot(slot, class_array))
912 PyrSlot *slots = slotRawObject(slot)->slots;
913 NSRect s;
914 slotVal(slots+0, &(s.origin.x));
915 slotVal(slots+1, &(s.origin.y));
916 slotVal(slots+2, &(s.size.width));
917 slotVal(slots+3, &(s.size.height));
918 retbuffer = (void*)&s;
920 else if((strcmp(cType+1, "_NSPoint") == 0) && (
921 isKindOfSlot(slot, s_point->u.classobj) ||
922 isKindOfSlot(slot, class_array))
924 PyrSlot *slots = slotRawObject(slot)->slots;
925 NSPoint s;
926 slotVal(slots+0, &s.x);
927 slotVal(slots+1, &s.y);
928 retbuffer = (void*)&s;
929 }else{
930 post("ERROR: Warning structure type not supported %c.\n", _C_STRUCT_B);
932 cType[ptr-cType-1] = '=';
934 break;
936 //// Not handled
937 case _C_BFLD:
938 case _C_CLASS:
939 case _C_SEL:
940 case _C_ARY_B:
941 case _C_UNION_B:
942 case _C_UNION_E:
943 case _C_ARY_E:
944 case _C_STRUCT_E:
945 default:
946 NSLog(@"ERROR: UNHANDLED RETURN TYPE OF INVOCATION: %c", *retType);
947 //post("return type not handled");
948 break;
951 //NSLog(@"Returning NSInvocation");
952 [inv setReturnValue:retbuffer];
953 } // End Of RetValue
954 } // End Of Compiled ok
955 pthread_mutex_unlock (&gLangMutex);
958 -(void)dummy{
959 NSLog(@"Dummy");
962 - (void)addSelector:(SEL)aSelector withObjcTypes:(const char*)cTypes
964 NSNumber* n = [NSNumber numberWithLong:(long)aSelector];
965 NSMethodSignature *signature;
967 if(cTypes && strlen(cTypes) > 0)
968 signature = [NSMethodSignature signatureWithObjCTypes:cTypes]; // defined in <Foundation/NSMethodSignature>
969 else
970 signature = [[self class] instanceMethodSignatureForSelector:@selector(dummy)];
972 if(!signature) {
973 post("ERROR: CocoaBridge Failed Creating valid signature for delegate !\n");
974 return;
977 [mSelectorArray setObject:signature forKey:n];
980 - (void)removeSelector:(SEL)aSelector
982 NSNumber* n = [NSNumber numberWithLong:(long)aSelector];
983 [mSelectorArray removeObjectForKey:n];
986 @end
989 these are a still experimental cocoa <-> sc bridge
990 an sc class: NSObjectHolder holds cocoa objects and lets you send and receive
991 messages.
993 prAllocInit { arg classname, initname,args;
994 _ObjC_allocinit;
995 ^this.primitiveFailed;
997 prDealloc {
998 _ObjC_dealloc;
1002 int slotGetNSRect(PyrSlot* a, NSRect *r);
1003 int slotGetPoint(PyrSlot* a, NSPoint *r);
1005 static int nsinvocationSetArguments(PyrSlot* args, NSInvocation *anInvocation)
1007 int len = slotRawObject(args)->size;
1008 for(int i =0; i<len; i++)
1010 PyrSlot * slot = slotRawObject(args)->slots+i;
1011 char *cType = (char *)[[anInvocation methodSignature] getArgumentTypeAtIndex: i+2];
1012 if(*cType == 'r') ++cType; // increment and go
1014 if(IsFloat(slot))
1016 float val;
1017 if(slotFloatVal(slot, &val) != noErr)
1018 return errFailed;
1020 if(*cType == _C_FLT) {
1021 [anInvocation setArgument: &val atIndex: i+2];
1023 else if(*cType == _C_DBL) {
1024 double dblval = (double)val;
1025 [anInvocation setArgument: &dblval atIndex: i+2];
1027 else if(*cType == _C_INT || *cType == _C_UINT){
1028 int ival = (int)val;
1029 [anInvocation setArgument: &ival atIndex: i+2];
1031 else if(*cType == _C_LNG || *cType == _C_ULNG) {
1032 long lval = (long)val;
1033 [anInvocation setArgument: &lval atIndex: i+2];
1035 else if(*cType == _C_SHT || *cType == _C_USHT) {
1036 short sval = (short)val;
1037 [anInvocation setArgument: &sval atIndex: i+2];
1039 else if(*cType == _C_CHR || *cType == _C_UCHR) {
1040 char cval = (char)val;
1041 [anInvocation setArgument: &cval atIndex: i+2];
1043 else if(*cType == _C_ID)
1045 double dval;
1046 if(slotDoubleVal(slot, &dval) != noErr)
1047 return errFailed;
1048 NSNumber* number = [NSNumber numberWithDouble:dval];
1049 [anInvocation setArgument: &number atIndex: i+2];
1051 else {
1052 post("wrong type (Float / Double) at arg: %i expected float\n", i);
1053 return errWrongType;
1057 else if(IsInt(slot))
1059 int val;
1060 if(slotIntVal(slot, &val) != noErr)
1061 return errFailed;
1063 if(*cType == _C_INT || *cType == _C_UINT) {
1064 [anInvocation setArgument: &val atIndex: i+2];
1066 else if(*cType == _C_LNG || *cType == _C_ULNG) {
1067 long lval = (long)val;
1068 [anInvocation setArgument: &lval atIndex: i+2];
1070 else if(*cType == _C_SHT || *cType == _C_USHT) {
1071 short sval = (short)val;
1072 [anInvocation setArgument: &sval atIndex: i+2];
1074 else if(*cType == _C_CHR || *cType == _C_UCHR) {
1075 char cval = (char)val;
1076 [anInvocation setArgument: &cval atIndex: i+2];
1078 else if(*cType == _C_FLT) {
1079 float fval;
1080 fval = (float)val;
1081 [anInvocation setArgument: &fval atIndex: i+2];
1082 }else if(*cType == _C_DBL) {
1083 double fval;
1084 fval = (double)val;
1085 [anInvocation setArgument: &fval atIndex: i+2];
1086 }else if(*cType == _C_ID){
1087 NSNumber* number = [NSNumber numberWithInt:val];
1088 [anInvocation setArgument: &number atIndex: i+2];
1089 }else{
1090 post("wrong type (Integer) at arg: %i expected %c \n", i, *cType); return errWrongType;
1093 else if(
1094 isKindOfSlot(slot, s_nsObject->u.classobj) ||
1095 isKindOfSlot(slot, slotRawSymbol(&s_nsObject->u.classobj->superclass)->u.classobj)
1098 if(*cType != _C_ID) {
1099 post("wrong type (SCNSObject) at arg: %i expected %c \n", i, *cType);
1100 return errWrongType;
1102 id val = (id) slotRawPtr(slotRawObject(slot)->slots);
1103 [anInvocation setArgument: &val atIndex: i+2];
1105 else if(IsFalse(slot)) {
1106 bool val = false;
1107 if(*cType == 'B') {
1108 [anInvocation setArgument: &val atIndex: i+2];
1110 else if(*cType == _C_INT || *cType == _C_UINT) {
1111 int ival = (int)val;
1112 [anInvocation setArgument: &ival atIndex: i+2];
1114 else if(*cType == _C_SHT || *cType == _C_USHT) {
1115 short sval = (short)val;
1116 [anInvocation setArgument: &sval atIndex: i+2];
1118 else if(*cType == _C_LNG || *cType == _C_ULNG) {
1119 short lval = (long)val;
1120 [anInvocation setArgument: &lval atIndex: i+2];
1122 else if(*cType == _C_CHR || *cType == _C_UCHR) {
1123 char cval = (char)val;
1124 [anInvocation setArgument: &cval atIndex: i+2];
1126 else if(*cType == _C_ID) {
1127 NSNumber* number = [NSNumber numberWithBool:NO];
1128 [anInvocation setArgument: &number atIndex: i+2];
1130 else{
1131 post("wrong type (Boolean False) at arg: %i expected %c \n", i, *cType); return errWrongType;
1134 else if(IsTrue(slot)) {
1135 bool val = true;
1136 if(*cType == 'B') {
1137 [anInvocation setArgument: &val atIndex: i+2];
1139 else if(*cType == _C_INT || *cType == _C_UINT) {
1140 int ival = (int)val;
1141 [anInvocation setArgument: &ival atIndex: i+2];
1143 else if(*cType == _C_SHT || *cType == _C_USHT) {
1144 short sval = (short)val;
1145 [anInvocation setArgument: &sval atIndex: i+2];
1147 else if(*cType == _C_LNG || *cType == _C_ULNG) {
1148 short lval = (long)val;
1149 [anInvocation setArgument: &lval atIndex: i+2];
1151 else if(*cType == _C_CHR || *cType == _C_UCHR) {
1152 char cval = (char)val;
1153 [anInvocation setArgument: &cval atIndex: i+2];
1155 else if(*cType == _C_ID) {
1156 NSNumber* number = [NSNumber numberWithBool:YES];
1157 [anInvocation setArgument: &number atIndex: i+2];
1159 else{
1160 post("wrong type (Boolean True) at arg: %i expected %c \n", i, *cType); return errWrongType;
1163 else if(IsNil(slot))
1165 if(*cType == _C_ID) {
1166 id idval = nil;
1167 [anInvocation setArgument: (void*)&idval atIndex: i+2];
1169 else if(*cType == _C_PTR) {
1170 void *ptr = NULL;
1171 [anInvocation setArgument: &ptr atIndex: i+2];
1172 }else{
1173 post("wrong type (Nil) at arg: %i expected %c \n", i, *cType); return errWrongType;
1176 else if (isKindOfSlot(slot, s_rect->u.classobj))
1178 if(*cType != _C_STRUCT_B) {
1179 post("wrong type (Rect) at arg: %i expected %c \n", i, *cType);
1180 return errWrongType;
1183 NSRect bounds;
1184 int err = slotGetNSRect(slot, &bounds);
1185 if (err) return err;
1186 [anInvocation setArgument: &bounds atIndex: i+2];
1188 else if (isKindOfSlot(slot, s_color->u.classobj))
1190 if(*cType != _C_ID) {
1191 post("wrong type (Color) at arg: %i expected %c \n", i, *cType);
1192 return errWrongType;
1195 PyrSlot *slots = slotRawObject(slot)->slots;
1196 int err;
1197 float r, g, b, a;
1198 NSColor * col;
1200 err = slotFloatVal(slots+0, &r);
1201 if (err) return err;
1202 err = slotFloatVal(slots+1, &g);
1203 if (err) return err;
1204 err = slotFloatVal(slots+2, &b);
1205 if (err) return err;
1206 err = slotFloatVal(slots+3, &a);
1207 if (err) return err;
1209 col = [NSColor colorWithCalibratedRed:r green:g blue:b alpha:a];
1210 [anInvocation setArgument: &col atIndex: i+2];
1212 else if (isKindOfSlot(slot, s_string->u.classobj))
1215 *cType == _C_CHARPTR ||
1216 *cType == _C_PTR
1218 char * ch = slotRawString(slot)->s;
1219 if(!ch) return errFailed;
1220 [anInvocation setArgument: (void*) &ch atIndex: i+2];
1222 else if(*cType == _C_ID) {
1223 NSString *s = nsStringFromPyrSlot(slot);
1224 if(!s) return errFailed;
1225 [anInvocation setArgument: (void*)&s atIndex: i+2];
1227 else if(*cType == _C_SEL) { // blackrain
1228 NSString *s = nsStringFromPyrSlot(slot);
1229 if(!s) return errFailed;
1230 SEL sel = NSSelectorFromString(s);
1231 [anInvocation setArgument: (void*)&sel atIndex: i+2];
1233 else {
1234 post("wrong type (String) at arg: %i expected %c \n", i, *cType);
1235 return errWrongType;
1238 else if (isKindOfSlot(slot, s_point->u.classobj))
1240 if(*cType != _C_STRUCT_B) return errWrongType;
1241 NSPoint point;
1242 int err = slotGetPoint(slot, &point);
1243 if (err) return err;
1244 [anInvocation setArgument: &point atIndex: i+2];
1246 else if (isKindOfSlot(slot, class_signal))
1248 float *slotvalues = (float*)(slotRawObject(slot)->slots) ;
1249 [anInvocation setArgument: &slotvalues atIndex: i+2];
1252 else if (isKindOfSlot(slot, s_int8array->u.classobj))
1254 if( *cType == _C_PTR ) {
1255 void* ptr = (void*)(((PyrInt8Array*)slotRawObject(slot))->b);
1256 if(!ptr) return errFailed;
1257 [anInvocation setArgument: &ptr atIndex: i+2];
1258 }else{
1259 post("wrong type (Int8Array) at arg: %i expected %c \n", i, *cType); return errWrongType;
1262 else if (isKindOfSlot(slot, s_int16array->u.classobj))
1264 if( *cType == _C_PTR ) {
1265 void* ptr = (void*)(((PyrInt16Array*)slotRawObject(slot))->i);
1266 if(!ptr) return errFailed;
1267 [anInvocation setArgument: &ptr atIndex: i+2];
1268 }else{
1269 post("wrong type (Int16Array) at arg: %i expected %c \n", i, *cType); return errWrongType;
1272 else if (isKindOfSlot(slot, s_int32array->u.classobj))
1274 if( *cType == _C_PTR ) {
1275 void* ptr = (void*)(((PyrInt32Array*)slotRawObject(slot))->i);
1276 if(!ptr) return errFailed;
1277 [anInvocation setArgument: &ptr atIndex: i+2];
1278 }else{
1279 post("wrong type (Int32Array) at arg: %i expected %c \n", i, *cType); return errWrongType;
1282 else if (isKindOfSlot(slot, s_doublearray->u.classobj))
1284 if( *cType == _C_PTR ) {
1285 void* ptr = (void*)(((PyrDoubleArray*)slotRawObject(slot))->d);
1286 if(!ptr) return errFailed;
1287 [anInvocation setArgument: &ptr atIndex: i+2];
1288 }else{
1289 post("wrong type (DoubleArray) at arg: %i expected %c \n", i, *cType); return errWrongType;
1292 else if (isKindOfSlot(slot, s_floatarray->u.classobj))
1294 if( *cType == _C_PTR ) {
1295 void* ptr = (void*)(((PyrFloatArray*)slotRawObject(slot))->f);
1296 if(!ptr) return errFailed;
1297 [anInvocation setArgument: &ptr atIndex: i+2];
1298 }else{
1299 post("wrong type (FloatArray) at arg: %i expected %c \n", i, *cType); return errWrongType;
1302 else if (isKindOfSlot(slot, s_arrayed_collection->u.classobj))
1304 if(strncmp(cType, "{_NSSize", 8) == 0) {
1305 NSSize size = (NSSize){0.f, 0.f};
1306 float value;
1307 if(slotRawObject(slot)->size > 0) {
1308 if(slotFloatVal(slotRawObject(slot)->slots+0, &value)) return errFailed;
1309 size.width = value;
1311 if(slotRawObject(slot)->size > 1) {
1312 if(slotFloatVal(slotRawObject(slot)->slots+1, &value)) return errFailed;
1313 size.height = value;
1315 [anInvocation setArgument: (void*)&size atIndex: i+2];
1317 else if(strncmp(cType, "{_NSRange", 9) == 0) {
1318 NSRange range = (NSRange){0, 0};
1319 int value;
1320 if(slotRawObject(slot)->size > 0) {
1321 if(slotIntVal(slotRawObject(slot)->slots+0, &value)) return errFailed;
1322 range.location = (unsigned int)value;
1324 if(slotRawObject(slot)->size > 1) {
1325 if(slotIntVal(slotRawObject(slot)->slots+1, &value)) return errFailed;
1326 range.length = (unsigned int)value;
1328 [anInvocation setArgument: (void*)&range atIndex: i+2];
1330 else if( strncmp(cType, "{?=qll}", 6) == 0 ) { // special QTTime structure
1332 QTTime time;
1333 PyrSlot* slots = slotRawObject(slot)->slots;
1335 if(slotRawObject(slot)->size < 2) {
1336 post("wrong number of elements in Array : 2 elements expected\n"); return errFailed;
1339 time = QTMakeTime(
1340 (long long)(IsInt(slots+0) ? slotRawInt(&slots[0]) : (IsFloat(slots+0) ? slotRawFloat(slots) : 0)),
1341 (long)(IsInt(slots+1) ? slotRawInt(&slots[1]) : (IsFloat(slots+1) ? slotRawFloat(&slots[1]) : 0))
1344 if( slotRawObject(slot)->size > 2 )
1345 time.flags = (long) (IsInt(slots+2) ? slotRawInt(&slots[2]) : (IsFloat(slots+2) ? slotRawFloat(&slots[2]) : 0));
1347 [anInvocation setArgument: (void*)&time atIndex: i+2];
1349 else if( strncmp(cType, "{?={?=qll}{?=qll}}", 18) == 0 ) { // special QTTimeRange structure
1351 QTTimeRange timeRange; QTTime* time;
1352 if(slotRawObject(slot)->size < 2) {
1353 post("wrong number of elements in Array: expected 2 elements\n"); return errFailed;
1356 PyrSlot* slots;
1357 for( int i=0; i < 2; ++i ) {
1358 if(slotRawObject(&slotRawObject(slot)->slots[i])->size < 2) {
1359 post("wrong number of elements in sub Array: expected 2 elements\n"); return errFailed;
1362 slots = slotRawObject(&slotRawObject(slot)->slots[i])->slots;
1363 time = (i == 0) ? &timeRange.time : &timeRange.duration;
1364 *time = QTMakeTime(
1365 (long long) (IsInt(slots+0) ? slotRawInt(&slots[0]) : (IsFloat(slots+0) ? slotRawFloat(slots) : 0)),
1366 (long) (IsInt(slots+1) ? slotRawInt(&slots[1]) : (IsFloat(slots+1) ? slotRawFloat(&slots[1]) : 0))
1368 if( slotRawObject(slot)->size > 2 )
1369 time->flags = (long) (IsInt(slots+2) ? slotRawInt(&slots[2]) : (IsFloat(slots+2) ? slotRawFloat(&slots[2]) : 0));
1374 else {
1375 //for now only arrays of SCNSObject
1376 id * nsObjects = (id*) malloc(slotRawObject(args)->size * sizeof(id));
1377 for(int j=0; j<slotRawObject(slot)->size; j++)
1379 PyrSlot * nsslot = slotRawObject(slot)->slots+j;
1380 nsObjects[j] = (id) slotRawPtr(slotRawObject(nsslot)->slots);
1382 if(!nsObjects) return errFailed;
1383 [anInvocation setArgument: &nsObjects atIndex: i+2];
1386 else {
1387 post("ERROR: bad argument type or Nil argument !\n");
1388 return errFailed;
1391 return errNone;
1394 int prObjcAllocInit(struct VMGlobals *g, int numArgsPushed);
1395 int prObjcAllocInit(struct VMGlobals *g, int numArgsPushed)
1397 PyrSlot *receiver = g->sp - 4;
1398 PyrSlot *classname = g->sp - 3;
1399 PyrSlot *initname = g->sp - 2;
1400 PyrSlot *args = g->sp-1;
1401 PyrSlot *defer = g->sp;
1404 bool hasArg = NotNil(args);
1405 bool isCollection = isKindOfSlot(args, class_array);
1406 NSString * nsclassname = nsStringFromPyrSlot(classname);
1407 if([nsclassname length] < 1){
1408 post("ERROR: CocoaBridge NSClass name invalid\n");
1409 SetNil(receiver);
1410 return errFailed;
1413 Class nsclass = [NSClassFromString( nsclassname ) class];
1414 if(!nsclass){
1415 post("ERROR: CocoaBridge Failed finding valid NSClass\n");
1416 SetNil(receiver);
1417 return errFailed;
1420 NSString * nsinitname = nsStringFromPyrSlot(initname);
1421 if([nsinitname length] < 1) {
1422 post("ERROR: CocoaBridge Failed converting method to NSString\n");
1423 SetNil(receiver);
1424 return errFailed;
1427 //post("Trying Class: %s selector: %s\n", [nsclassname UTF8String], [nsinitname UTF8String]);
1429 SEL sel = NSSelectorFromString(nsinitname);
1430 BOOL isInstanceMethod = [nsclass instancesRespondToSelector: sel];
1432 !isInstanceMethod &&
1433 ((isInstanceMethod = ![nsclass respondsToSelector: sel]) == YES)
1435 // not an instance method and not a class method
1436 SetNil(receiver);
1437 post("Warning: NSClass: %s does not respond to: %s \n", [nsclassname cString], [nsinitname cString]);
1438 return errNone;
1441 id newThing = NULL;
1442 NSMethodSignature *sig = isInstanceMethod ? [nsclass instanceMethodSignatureForSelector: sel] : [nsclass methodSignatureForSelector: sel];
1443 if(!sig) {
1444 post("ERROR: CocoaBridge NSMethodSignature not found\n");
1445 return errFailed;
1448 NSInvocation *anInvocation = [NSInvocation invocationWithMethodSignature: sig];
1449 if(!anInvocation) {
1450 post("ERROR: CocoaBridge Failed creating NSInvocation\n");
1451 return errFailed;
1454 SCVirtualMachine* scvm = [SCVirtualMachine sharedInstance];
1456 int numberOfArgs = (int) [sig numberOfArguments] - 2; //cocoa args start at 2
1458 if (hasArg && isCollection && numberOfArgs>0)
1460 int len = slotRawObject(args)->size;
1462 //should check for type [sig getArgumentTypeAtIndex: i];
1463 if(numberOfArgs != len)
1465 post("Warning: NSClass: %s numberOfArguments does not match: %i, provided: %i \n", [nsclassname cString],numberOfArgs, len);
1466 SetNil(receiver);
1467 return errFailed;
1469 int err = nsinvocationSetArguments(args, anInvocation);
1470 if(err){
1471 post("ERROR: CocoaBridge failed setting arguments for Invocation\n");
1472 SetNil(receiver);
1473 return err;
1475 } else if (numberOfArgs>0)
1477 post("Warning: CocoaBridge mismatching arguments \n");
1478 SetNil(receiver);
1479 return errFailed;
1482 [anInvocation setTarget: isInstanceMethod ? [nsclass alloc] : (id)nsclass];
1483 [anInvocation setSelector: sel];
1485 if(IsTrue(defer))
1486 [scvm defer: anInvocation];
1487 else
1489 PyrObjectHdr *convertedObject=NULL;
1490 PyrSlot retslot;
1491 const char *cType=NULL;
1492 unsigned int length;
1493 void *retval=NULL;
1495 TryInvocation(anInvocation, receiver);
1497 cType = [[anInvocation methodSignature]methodReturnType];
1498 length = [[anInvocation methodSignature] methodReturnLength];
1499 //NSLog(@"AllocInit type: %c length: %i", cType, length);
1501 SetNil(&retslot);
1503 if(length > 0) {
1504 retval = (void*)malloc(length);
1505 [anInvocation getReturnValue: (void*)retval];
1508 if(ObjcTypeFillPyrSlot(&retslot, cType, retval, &convertedObject) != noErr) {
1509 post("ERROR: CocoaBridge returned object type: %c is not-of-type _C_ID !\n", *cType);
1510 if(retval) free(retval);
1511 return errFailed;
1514 // If no suitable Cocoa<->SCLang conversion can be done for the object value
1515 if(*cType == _C_ID && !convertedObject) {
1517 if(IsNil(&retslot)) { // the returned object is Nil - might lead to EXC_BAD_ACCESS after
1518 SetNil(slotRawObject(receiver)->slots+0); // set the dataptr slot to nil
1519 SetNil(receiver); // return nil
1520 if(retval) free(retval);
1521 return errNone; // should returning nil be considered as an error ?
1524 slotCopy(&slotRawObject(receiver)->slots[0], &retslot);
1525 newThing = (id) slotRawPtr(slotRawObject(receiver)->slots);
1527 if([newThing isKindOfClass:[NSWindow class]])
1528 [newThing setReleasedWhenClosed:NO]; // prevent user crash for this specific UI
1530 NSString *classNameString = NSStringFromClass( [newThing class] );
1531 PyrString *pyrClassNameString = newPyrString(g->gc,[classNameString UTF8String],0,true);
1532 SetObject(slotRawObject(receiver)->slots + 1, pyrClassNameString);
1534 if(isInstanceMethod)
1535 [newThing release]; // retained and added already in ObjcTypeFillPyrSlot
1537 else
1538 slotCopy(receiver, &retslot);
1540 if(retval)
1541 free(retval);
1543 return errNone;
1546 int prObjcSetActionForControl(struct VMGlobals *g, int numArgsPushed);
1547 int prObjcSetActionForControl(struct VMGlobals *g, int numArgsPushed)
1549 PyrSlot *a = g->sp - 2;
1550 PyrSlot *b = g->sp - 1;
1551 PyrSlot *c = g->sp;
1552 id objc = (id) slotRawPtr(slotRawObject(a)->slots);
1553 if(!objc) return errFailed;
1554 NSString * actionname = nsStringFromPyrSlot(c);
1555 if([actionname length] < 1){ return errFailed; }
1556 SEL selAc = NSSelectorFromString(actionname);
1558 if(![[objc class] instancesRespondToSelector:@selector(setAction:)])
1560 post("Warning: %s does not respond to setAction:.\n", [[objc className] UTF8String]);
1561 SetNil(b);
1562 return errNone;
1564 SCCocoaToLangAction *action = [[SCCocoaToLangAction alloc] init];
1565 if(!action)
1566 return errFailed;
1568 COCOABRIDGE_OBJ_RETAIN(action);
1569 [action release]; // already retained
1571 [action setSCObject: slotRawObject(b)];
1573 [objc setAction: selAc];
1574 [objc setTarget: action];
1576 SetPtr(slotRawObject(b)->slots + 0, action);
1577 return errNone;
1581 //// Notification Test thelych
1582 int prObjcRegisterNotification(struct VMGlobals *g, int numArgsPushed);
1583 int prObjcRegisterNotification(struct VMGlobals *g, int numArgsPushed)
1585 PyrSlot *c = g->sp;
1586 PyrSlot *b = g->sp - 1;
1587 PyrSlot *a = g->sp - 2;
1588 id objc = (id) slotRawPtr(slotRawObject(a)->slots);
1589 id delegate = nil;
1590 if(!objc) return errFailed;
1592 if([[objc class] instancesRespondToSelector:@selector(delegate)])
1593 delegate = [objc delegate];
1595 if(!delegate) {
1596 //post("ERROR delegate does not exists\n"); // try to recover
1597 //return errFailed;
1599 IsNil(&(slotRawObject(a)->slots[3])) ||
1600 IsNil((slotRawObject(&slotRawObject(a)->slots[3]))->slots)
1602 printf("Error: Slot is nil\n");
1603 return errNone;
1605 else
1606 delegate = (id) slotRawPtr(slotRawObject(&slotRawObject(a)->slots[3])->slots); // some objects do not respond to
1607 // setDelegate but do post notifications...
1610 NSString *notificationName = nsStringFromPyrSlot(b);
1611 post([[NSString stringWithFormat:@"Registering Notification: %@\n", notificationName] UTF8String]);
1613 if (IsNil(c)) { // br
1614 objc = nil;
1615 post("Listening to Notifications from any Object.\n");
1616 } else
1617 objc = (id) slotRawPtr(slotRawObject(c)->slots);
1619 [[NSNotificationCenter defaultCenter] addObserver:delegate
1620 selector:@selector(notificationReceived:)
1621 name:notificationName object:objc // apply only to object
1624 return errNone;
1627 int prObjcSetDelegate(struct VMGlobals *g, int numArgsPushed);
1628 int prObjcSetDelegate(struct VMGlobals *g, int numArgsPushed)
1630 PyrSlot *a = g->sp - 1;
1631 PyrSlot *b = g->sp;
1632 id objc = (id) slotRawPtr(slotRawObject(a)->slots);
1633 if(!objc) {
1634 #pragma mark __TEST_CUSTOM_DELEGATE_
1635 SCCocoaToLangAction *action = [[SCCocoaToLangAction alloc] init];
1636 post("Warning: creating a special delegate %p\n", action);
1637 if(!action)
1638 return errFailed;
1639 COCOABRIDGE_OBJ_RETAIN(action);
1640 [action release]; // already retained
1642 [action setSCObject: slotRawObject(b)];
1643 SetPtr(slotRawObject(b)->slots + 0, action);
1644 return errNone;
1647 if(![[objc class] instancesRespondToSelector:@selector(setDelegate:)])
1649 // setting void action so it can register notifications
1650 SCCocoaToLangAction *action = [[SCCocoaToLangAction alloc] init];
1651 post("Warning: creating a void delegate\n");
1652 if(!action)
1653 return errFailed;
1655 COCOABRIDGE_OBJ_RETAIN(action);
1656 [action release]; // already retained
1657 [action setSCObject: slotRawObject(b)];
1658 SetPtr(slotRawObject(b)->slots + 0, action);
1659 return errNone;
1662 // do not create a delegate if a previous delegate exists already
1663 // default delegate can be SCVirtualMachine
1664 if(![objc delegate]) {
1665 SCCocoaToLangAction *action = [[SCCocoaToLangAction alloc] init];
1666 if(!action)
1667 return errFailed;
1669 COCOABRIDGE_OBJ_RETAIN(action);
1670 [action release]; // already retained
1671 [action setSCObject: slotRawObject(b)];
1672 [objc setDelegate: action];
1673 SetPtr(slotRawObject(b)->slots + 0, action);
1674 }else{
1675 post("Warning: There is already a delegate for this NSObject (%s).\n", [[objc delegate]className]);
1676 SetNil(slotRawObject(b)->slots + 0);
1678 post("delegate created successfully for object %p of class %s\n", objc, [[objc className]UTF8String]);
1679 return errNone;
1682 int prObjcGetClass(struct VMGlobals *g, int numArgsPushed);
1683 int prObjcGetClass(struct VMGlobals *g, int numArgsPushed)
1685 PyrSlot *receiver = g->sp - 1;
1686 PyrSlot *classname = g->sp ;
1688 id nsclass = [objc_getClass(slotRawString(classname)->s) class];
1690 [nsclass retain];
1691 SetPtr(slotRawObject(receiver)->slots + 0, nsclass);
1692 return errNone;
1695 int prObjcSendMessage(struct VMGlobals *g, int numArgsPushed);
1696 int prObjcSendMessage(struct VMGlobals *g, int numArgsPushed)
1698 PyrSlot *receiver = g->sp - 2;
1699 PyrSlot *msgname = g->sp - 1;
1700 PyrSlot *args = g->sp;
1701 // PyrSlot *defer = g->sp;
1704 // bool hasArg = NotNil(args);
1705 // bool isCollection = isKindOfSlot(args, class_array);
1707 id newThing = (id) slotRawPtr(slotRawObject(receiver)->slots);
1708 if (!newThing) return errFailed;
1710 NSString * nsinitname = nsStringFromPyrSlot(msgname);
1711 if([nsinitname length] < 1){ return errNone; }
1713 SEL sel = NSSelectorFromString(nsinitname);
1716 // int val;
1717 // slotIntVal(slotRawObject(args)->slots+0, &val);
1718 newThing = objc_msgSend(newThing, sel, args);
1719 // [newThing retain];
1720 if(newThing)
1721 SetPtr(slotRawObject(receiver)->slots + 0, newThing);
1722 else
1723 SetNil(slotRawObject(receiver)->slots + 0);
1725 return errNone;
1728 int prObjcAllocSend(struct VMGlobals *g, int numArgsPushed);
1729 int prObjcAllocSend(struct VMGlobals *g, int numArgsPushed)
1731 //under construction ...
1732 PyrSlot *receiver = g->sp - 3;
1733 PyrSlot *classname = g->sp - 2;
1734 PyrSlot *initname = g->sp - 1;
1735 // PyrSlot *args = g->sp;
1738 // bool hasArg = NotNil(args);
1739 // bool isCollection = isKindOfSlot(args, class_array);
1741 NSString * nsclassname = nsStringFromPyrSlot(classname);
1742 if([nsclassname length] < 1){ return errFailed; }
1743 NSString * nsinitname = nsStringFromPyrSlot(initname);
1744 if([nsinitname length] < 1){ return errNone; }
1746 SEL sel = NSSelectorFromString(nsinitname);
1748 // NSMethodSignature *sig = [[NSClassFromString( nsclassname ) class] instanceMethodSignatureForSelector: sel];
1749 #if 1
1750 id nsclass = objc_getClass(slotRawString(classname)->s);
1752 int val = 0;
1753 // slotIntVal(slotRawObject(args)->slots+0, &val);
1754 id newThing = objc_msgSend(nsclass, sel, val);
1755 [newThing retain];
1756 #else
1757 /// //for alloc
1758 int val = NULL;
1759 slotIntVal(slotRawObject(args)->slots+0, &val);
1761 id newThing = [[NSClassFromString( nsclassname ) class] sel val];
1762 [newThing retain];
1764 #endif
1765 SetPtr(slotRawObject(receiver)->slots + 0, newThing);
1766 // SetInt(slotRawObject(receiver)->slots + 0, 123);
1768 return errNone;
1771 int prObjcGetClassName(struct VMGlobals *g, int numArgsPushed);
1772 int prObjcGetClassName(struct VMGlobals *g, int numArgsPushed)
1774 PyrSlot *a = g->sp - 1;
1775 // PyrSlot *b = g->sp;
1776 id objc = (id) slotRawPtr(slotRawObject(a)->slots + 0);
1777 if(!objc) return errFailed;
1778 PyrString *pyrPathString = newPyrString(g->gc, [[objc className] UTF8String], 0, true);
1779 SetObject(a, pyrPathString);
1780 return errNone;
1783 int prObjcDeferInvocation(struct VMGlobals *g, int numArgsPushed);
1784 int prObjcDeferInvocation(struct VMGlobals *g, int numArgsPushed)
1786 PyrSlot *receiver = g->sp - 3;
1787 PyrSlot *initname = g->sp - 2;
1788 PyrSlot *args = g->sp - 1;
1789 PyrSlot *defer = g->sp;
1791 if (!g->canCallOS)
1792 return errCantCallOS; //moght be better to check this ?
1794 bool hasArg = NotNil(args) && isKindOfSlot(args, class_array);
1795 bool isCollection = isKindOfSlot(args, class_array);
1796 if(!isCollection) return errFailed;
1798 // must defer in case of large loads and gui
1799 id newThing = (id) slotRawPtr(slotRawObject(receiver)->slots);
1800 if (!newThing) {
1801 post("ERROR: no valid NSObject to defer Invocation to !\n");
1802 return errFailed;
1805 NSString * nsclassname = [newThing className];
1806 Class nsclass = [NSClassFromString( nsclassname ) class];
1807 NSString * nsinitname = nsStringFromPyrSlot(initname);
1809 if([nsinitname length] < 1){
1810 post("ERROR: Method argument is invalid !\n");
1811 return errFailed;
1814 SEL sel = NSSelectorFromString(nsinitname);
1815 if(![nsclass instancesRespondToSelector:sel])
1817 post("Warning: %s does not respond to: %s \n", [nsclassname cString], [nsinitname cString]);
1818 return errNone;
1821 NSMethodSignature *sig = [nsclass instanceMethodSignatureForSelector: sel];
1822 NSInvocation *anInvocation = [NSInvocation invocationWithMethodSignature: sig];
1823 SCVirtualMachine* scvm = [SCVirtualMachine sharedInstance];
1824 [anInvocation setTarget: newThing];
1825 [anInvocation setSelector: sel];
1827 int numberOfArgs = (int) [sig numberOfArguments] - 2; //cocoa args start at 2
1828 int len = slotRawObject(args)->size;
1830 if(len < numberOfArgs) return errFailed;
1831 if(len > numberOfArgs) len = numberOfArgs;
1833 if(hasArg)
1835 int err = nsinvocationSetArguments(args, anInvocation);
1836 if(err) return err;
1839 if(IsTrue(defer)){
1840 [anInvocation retainArguments];
1841 [scvm defer: anInvocation];
1843 else
1845 //?use void objc_msgSend_stret(void * stretAddr, id theReceiver, SEL theSelector, ...);
1846 PyrObjectHdr *convertedObject=NULL;
1847 unsigned int length = 0;
1848 char *cType = NULL;
1849 void *retval = NULL;
1851 TryInvocation(anInvocation, receiver);
1853 length = [[anInvocation methodSignature] methodReturnLength];
1854 cType = (char *)[[anInvocation methodSignature] methodReturnType];
1856 if(*cType != _C_VOID && *cType != _C_UNDEF && (length > 0)) {
1857 retval = (void*)malloc(length);
1858 [anInvocation getReturnValue: (void*)retval];
1860 if(ObjcTypeFillPyrSlot(receiver, cType, retval, &convertedObject) != noErr) {
1861 post("ERROR: CocoaBridge returned object type: %c is not-of-type _C_ID !\n", *cType);
1862 if(retval) free(retval);
1863 return errFailed;
1867 if(retval)
1868 free(retval);
1870 return errNone;
1873 int prObjcDealloc(struct VMGlobals *g, int numArgsPushed);
1874 int prObjcDealloc(struct VMGlobals *g, int numArgsPushed)
1876 //PyrSlot *receiver = g->sp - 1;
1877 PyrSlot *receiver = g->sp;
1878 //PyrSlot *dataptr = g->sp;
1880 // have to put them in a specific pool so they can be released on command
1881 //if(! IsInt(dataptr) )
1882 // return errWrongType;
1884 //id nsobj = (id)dataptr->ui;
1885 // check retain count and return in case
1886 id nsobj = (id)slotRawPtr(slotRawObject(receiver)->slots);
1887 if(nsobj) {
1888 COCOABRIDGE_OBJ_RELEASE(nsobj);
1889 SetPtr(slotRawObject(receiver)->slots, 0);
1890 }else
1891 post("SCNSObject object pointer is nil\n");
1893 return errNone;
1896 int prObjcLoadBundle(struct VMGlobals *g, int numArgsPushed);
1897 int prObjcLoadBundle(struct VMGlobals *g, int numArgsPushed)
1899 PyrSlot *a = g->sp - 1;
1900 PyrSlot *path = g->sp;
1901 //lazy load of a bundle and its principla class as desciped by apple
1902 NSString * bundlePath = nsStringFromPyrSlot(path);
1903 NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
1904 if(bundle)
1905 SetPtr(slotRawObject(a)->slots + 0, bundle);
1906 else
1907 SetNil(a);
1908 return errNone;
1911 int prObjcBundleAllocPrincipalClass(struct VMGlobals *g, int numArgsPushed);
1912 int prObjcBundleAllocPrincipalClass(struct VMGlobals *g, int numArgsPushed)
1915 PyrSlot *receiver = g->sp;
1917 // have to put them in a specific pool so they can be released on command
1918 id bundle = (id) slotRawPtr(slotRawObject(receiver)->slots);
1919 if (!bundle) return errFailed;
1920 Class principalClass = [bundle principalClass];
1921 NSObject * _bundleObject = NULL;
1923 if(principalClass)
1925 _bundleObject = [[principalClass alloc] init]; // 5
1927 if(_bundleObject)
1928 SetPtr(receiver, _bundleObject);
1929 else
1930 SetNil(receiver);
1931 return errNone;
1934 int prObjcBundleAllocClassNamed(struct VMGlobals *g, int numArgsPushed);
1935 int prObjcBundleAllocClassNamed(struct VMGlobals *g, int numArgsPushed)
1938 PyrSlot *receiver = g->sp - 4;
1939 PyrSlot *name = g->sp - 3;
1940 PyrSlot *initname = g->sp - 2;
1941 PyrSlot *args = g->sp-1;
1942 PyrSlot *defer = g->sp;
1944 bool hasArg = NotNil(args);
1945 bool isCollection = isKindOfSlot(args, class_array);
1947 //lazy load of a bundle and its principla class as desciped by apple
1948 NSString * nsclassname = nsStringFromPyrSlot(name);
1949 id bundle = (id) slotRawPtr(slotRawObject(receiver)->slots);
1950 if (!bundle) return errFailed;
1951 Class nsclass = NULL;
1952 NSObject * newThing = NULL;
1953 nsclass = [bundle classNamed:nsclassname];
1954 if(!nsclass){SetNil(receiver); post("class %s not found in bundle\n", [nsclassname cStringUsingEncoding: NSMacOSRomanStringEncoding]);return errFailed;}
1955 // sort out initMethod
1956 NSString * nsinitname = nsStringFromPyrSlot(initname);
1957 if([nsinitname length] < 1){ SetNil(receiver); return errFailed; }
1959 SEL sel = NSSelectorFromString(nsinitname);
1960 if(![nsclass instancesRespondToSelector:sel])
1962 SetNil(receiver);
1963 post("Warning: NSClass: %s does not respond to: %s \n", [nsclassname cString], [nsinitname cString]);
1964 return errNone;
1966 NSMethodSignature *sig = [nsclass instanceMethodSignatureForSelector: sel];
1967 NSInvocation *anInvocation = [NSInvocation invocationWithMethodSignature: sig];
1968 SCVirtualMachine* scvm = [SCVirtualMachine sharedInstance];
1970 int numberOfArgs = (int) [sig numberOfArguments] - 2; //cocoa args start at 2
1972 if (hasArg && isCollection && numberOfArgs>0)
1974 int len = slotRawObject(args)->size;
1976 //should check for type [sig getArgumentTypeAtIndex: i];
1977 if(numberOfArgs != len)
1979 post("Warning: NSClass: %s numberOfArguments does not match: %i, provided: %i \n", [nsclassname cString],numberOfArgs, len);
1980 SetNil(receiver);
1981 return errFailed;
1983 int err = nsinvocationSetArguments(args, anInvocation);
1984 if(err){ SetNil(receiver); return err;}
1987 } else if (numberOfArgs>0)
1989 post("Warning: mismatching arguments \n");
1990 SetNil(receiver);
1991 return errFailed;
1993 newThing = [nsclass alloc];
1994 [anInvocation setTarget: newThing];
1995 [anInvocation setSelector: sel];
1996 if(IsTrue(defer))
1998 [scvm defer: anInvocation];
2000 else
2002 id val;
2003 [anInvocation invoke];
2004 [anInvocation getReturnValue: (void*)&val];
2005 newThing = (id) val;
2006 [newThing retain];
2007 SetPtr(receiver, newThing);
2008 COCOABRIDGE_OBJ_RETAIN(newThing);
2011 return errNone;
2013 // if(_bundleObject)
2014 // SetPtr(receiver, _bundleObject);
2015 // else
2016 // SetNil(receiver);
2020 int prObjcNSStringToPyrString(struct VMGlobals *g, int numArgsPushed);
2021 int prObjcNSStringToPyrString(struct VMGlobals *g, int numArgsPushed)
2023 PyrSlot *a = g->sp; // the scns_object
2024 id nsstring = (id)slotRawPtr(slotRawObject(a)->slots);
2025 PyrString * pyrString;
2026 NSString* className = [nsstring className];
2028 [nsstring isKindOfClass:[NSString class]]
2030 pyrString = newPyrString(g->gc, [(NSString*)nsstring UTF8String], 0, true);
2031 else
2032 pyrString = newPyrString(g->gc, [className UTF8String], 0, true);
2034 SetObject(a, pyrString);
2035 return errNone;
2038 int prObjcIsSubclassOfNSClass(struct VMGlobals *g, int numArgsPushed);
2039 int prObjcIsSubclassOfNSClass(struct VMGlobals *g, int numArgsPushed)
2041 PyrSlot *a = g->sp - 1;
2042 PyrSlot *b = g->sp;
2045 NSString *nsstr = nsStringFromPyrSlot(b);
2046 if(!nsstr)
2047 return errFailed;
2049 Class objcclass = NSClassFromString(nsstr);
2050 if(objcclass != nil) {
2051 id obj = (id)slotRawPtr(slotRawObject(a)->slots);
2052 if([obj isKindOfClass:objcclass]) {
2053 SetTrue(a);
2054 return errNone;
2058 SetFalse(a);
2059 return errNone;
2062 int prObjcDelegateAddSelector(struct VMGlobals *g, int numArgsPushed);
2063 int prObjcDelegateAddSelector(struct VMGlobals *g, int numArgsPushed)
2065 PyrSlot *a = g->sp - 2;
2066 PyrSlot *b = g->sp - 1;
2067 PyrSlot *c = g->sp;
2068 //PyrObject* obj;
2069 char slotString[64];
2071 SCCocoaToLangAction* nsobj = (SCCocoaToLangAction*)slotRawPtr(slotRawObject(a)->slots);
2073 if(!isKindOfSlot(b, class_string) || !isKindOfSlot(c, class_string))
2074 return errWrongType;
2076 if(slotStrVal(b, slotString, 64) != noErr)
2077 return errWrongType;
2079 SEL selector = sel_getUid(slotString);
2080 if(!selector)
2081 return errFailed;
2083 if(slotStrVal(c, slotString, 64) != noErr)
2084 return errWrongType;
2086 [nsobj addSelector:selector withObjcTypes:slotString];
2088 return errNone;
2091 int prObjcDelegateRemoveSelector(struct VMGlobals *g, int numArgsPushed);
2092 int prObjcDelegateRemoveSelector(struct VMGlobals *g, int numArgsPushed)
2094 PyrSlot *a = g->sp - 1;
2095 PyrSlot *b = g->sp;
2096 SCCocoaToLangAction* nsobj = (SCCocoaToLangAction*)slotRawPtr(slotRawObject(a)->slots);
2098 if(!isKindOfSlot(b, class_string))
2099 return errWrongType;
2101 char slotString[64];
2102 if(slotStrVal(b, slotString, 64) != noErr)
2103 return errWrongType;
2105 SEL selector = sel_getUid(slotString);
2106 if(!selector)
2107 return errFailed;
2109 [nsobj removeSelector:selector];
2110 return errNone;
2113 int prObjcDumpPool(struct VMGlobals *g, int numArgsPushed);
2114 int prObjcDumpPool(struct VMGlobals *g, int numArgsPushed)
2116 #if COCOABRIDGE_STORE_OBJECTS_IN_ARRAY
2117 if(!nsobjects) {
2118 return errFailed;
2121 post("\n--- POOL DUMP %i ---\n", [nsobjects count]);
2122 NSEnumerator *e = [nsobjects objectEnumerator];
2123 id obj; int i=0;
2124 while((obj = [e nextObject])) {
2125 post("OBJECT (%p), CLASS (%s), IDX(%i)\n", obj, [NSStringFromClass([obj class]) UTF8String], i);
2126 ++i;
2128 post("--- END OF DUMP ---\n");
2129 #endif
2130 return errNone;
2133 int prObjcFreePool(struct VMGlobals *g, int numArgsPushed);
2134 int prObjcFreePool(struct VMGlobals *g, int numArgsPushed)
2136 #if COCOABRIDGE_STORE_OBJECTS_IN_ARRAY
2137 if(!nsobjects) {
2138 return errFailed;
2141 [nsobjects removeAllObjects];
2142 post("POOL FREED\n");
2143 #endif
2144 return errNone;
2147 int prObjcNSDataToPyrArray(struct VMGlobals *g, int numArgsPushed);
2148 int prObjcNSDataToPyrArray(struct VMGlobals *g, int numArgsPushed)
2150 PyrSlot *a = g->sp - 2; // the scns_object
2151 PyrSlot *b = g->sp - 1; // the array (or string)
2152 PyrSlot *c = g->sp; // length to retrieve
2154 PyrObject* pyrarray = slotRawObject(b);
2155 PyrClass* pyrclass = pyrarray->classptr;
2157 NSData* nsobject = (NSData*)slotRawPtr(slotRawObject(a)->slots);
2158 int size=0, nssize = [nsobject length]; // in bytes
2160 if(!IsInt(c) && !IsFloat(c))
2161 return errWrongType;
2163 size = IsFloat(c) ? (int)slotRawFloat(c) : (int)slotRawInt(c);
2164 if(size <= 0 || nssize <= 0) {
2165 SetNil(a);
2166 return errNone;
2169 if(pyrclass == class_int8array) {
2171 size = sc_min(nssize, size);
2172 memcpy(((PyrInt8Array*)pyrarray)->b, [nsobject bytes], size);
2174 } else if(pyrclass == class_int32array){
2176 size = sc_min(nssize, size/* >> 2*/);
2177 memcpy(((PyrInt32Array*)pyrarray)->i, [nsobject bytes], size);
2179 } else if(pyrclass == class_int16array) {
2181 size = sc_min(nssize, size/* >> 1*/);
2182 memcpy(((PyrInt32Array*)pyrarray)->i, [nsobject bytes], size);
2184 } else if(pyrclass == class_doublearray) {
2186 size = sc_min(nssize, size/* >> (sizeof(double)>>1)*/); // double size same for PPC32 - IA32 - IA64 according to Mac ABI
2187 memcpy(((PyrDoubleArray*)pyrarray)->d, [nsobject bytes], size);
2189 } else if(pyrclass == class_floatarray) {
2191 size = sc_min(nssize, size /*>> (sizeof(float)>>1)*/); // float size same for PPC32 - IA32 - IA64 according to Mac ABI
2192 memcpy(((PyrFloatArray*)pyrarray)->f, [nsobject bytes], size);
2194 } else if(pyrclass == class_string) {
2196 size = sc_min(nssize, size);
2197 memcpy(((PyrString*)pyrarray)->s, [nsobject bytes], size);
2199 } else
2200 return errWrongType;
2202 //pyrarray->size = size;
2203 SetObject(a, pyrarray);
2204 return errNone;
2207 void initCocoaBridgePrimitives()
2209 int base, index;
2211 base = nextPrimitiveIndex();
2212 index = 0;
2213 s_nsObject = getsym("SCNSObject");
2215 #if COCOABRIDGE_STORE_OBJECTS_IN_ARRAY
2216 if(nsobjects)
2218 #if COCOABRIDGE_VERBOSITY
2219 NSLog(@"----- POOL_MNG -----");
2220 NSLog(@"Number of objects: %i", [nsobjects count]);
2221 #endif
2222 id nsobj;
2223 NSEnumerator* e = [nsobjects objectEnumerator];
2224 while((nsobj = [e nextObject])) {
2225 if(strcmp(class_getName(nsobj->isa->isa), "FREED(id)") == 0) { // may happen so add verbosity
2226 NSLog(@"Already FREED NSObject in POOL -> will cause crash");
2227 continue;
2230 COCOABRIDGE_POOL_REM_LOG(nsobj)
2231 if([nsobj isKindOfClass:[NSWindow class]]) {
2232 // NSWindows are special since they are directly deallocated (freed - not just released)
2233 // by the windowing system - so we must take care that it won't crash by releasing an already freed reference
2234 // or we should disable this default behaviour
2235 NSWindow* wobj = (NSWindow*)nsobj;
2236 if([wobj isVisible]) {
2237 [wobj setReleasedWhenClosed:NO]; // otherwise might lead to a crash
2238 //[wobj close]; // close any windows instance
2242 [nsobjects release]; // will release all references
2243 nsobjects = nil;
2245 // nsobjects = [[NSMutableSet setWithCapacity: 8]retain];
2246 nsobjects = [[NSMutableArray arrayWithCapacity: 8]retain];
2247 #endif
2249 definePrimitive(base, index++, "_ObjC_AllocInit", prObjcAllocInit, 5, 0);
2250 definePrimitive(base, index++, "_ObjC_Dealloc", prObjcDealloc, 1, 0);
2251 definePrimitive(base, index++, "_ObjC_Invoke", prObjcDeferInvocation, 4, 0);
2252 definePrimitive(base, index++, "_ObjC_GetClassName", prObjcGetClassName, 2, 0);
2253 definePrimitive(base, index++, "_ObjC_SetActionForControl", prObjcSetActionForControl, 3, 0);
2254 definePrimitive(base, index++, "_ObjC_SetDelegate", prObjcSetDelegate, 2, 0);
2255 definePrimitive(base, index++, "_ObjC_AllocSend", prObjcAllocSend, 4, 0);
2256 definePrimitive(base, index++, "_ObjC_GetClass", prObjcGetClass, 2, 0);
2257 definePrimitive(base, index++, "_ObjC_SendMessage", prObjcSendMessage, 3, 0);
2258 definePrimitive(base, index++, "_ObjC_LoadBundle", prObjcLoadBundle, 2, 0);
2259 definePrimitive(base, index++, "_ObjcBundleAllocPrincipalClass", prObjcBundleAllocPrincipalClass, 1, 0);
2260 definePrimitive(base, index++, "_ObjcBundleAllocClassNamed", prObjcBundleAllocClassNamed, 5, 0);
2261 definePrimitive(base, index++, "_ObjC_RegisterNotification", prObjcRegisterNotification, 3, 0); // added cp
2262 definePrimitive(base, index++, "_ObjC_NSDataToSCArray", prObjcNSDataToPyrArray, 3, 0);
2263 definePrimitive(base, index++, "_ObjC_NSStringToPyrString", prObjcNSStringToPyrString, 1, 0);
2264 definePrimitive(base, index++, "_ObjC_IsSubclassOfNSClass", prObjcIsSubclassOfNSClass, 2, 0);
2265 definePrimitive(base, index++, "_ObjC_DelegateAddSelector", prObjcDelegateAddSelector, 3, 0);
2266 definePrimitive(base, index++, "_ObjC_DelegateRemoveSelector", prObjcDelegateRemoveSelector, 2, 0);
2267 definePrimitive(base, index++, "_ObjC_DumpPool", prObjcDumpPool, 1, 0);
2268 definePrimitive(base, index++, "_ObjC_FreePool", prObjcFreePool, 1, 0);
2269 // loadNibFile