From 4d466cbef5236867c8f332588e388cf7909798ca Mon Sep 17 00:00:00 2001 From: Byron Ellis Date: Tue, 10 Jul 2007 13:14:21 -0700 Subject: [PATCH] Many changes! Snapshots now working properly. Programmatic environment interface. Support for Workspace. Other miscellaneous changes --- DeviceView.m | 5 + DeviceWindowController.m | 6 + RApplicationDelegate.m | 4 +- RCGImageDevice.m | 6 +- RDataPortManager.h | 14 + RDataPortManager.m | 19 + RDevice.h | 7 +- RDevice.m | 40 +- RDeviceImpl.c | 36 +- RDeviceImpl.h | 14 +- REnvironment.h | 18 + REnvironment.m | 65 ++ RExecServer.xcodeproj/bcellis.pbxuser | 1088 ++++++++++++++++++++------------- RExecServer.xcodeproj/project.pbxproj | 68 ++- RFunction.h | 18 + RFunction.m | 39 ++ RInterpreter.h | 8 +- RInterpreter.m | 30 +- RObject.h | 25 + RObject.m | 90 +++ RServerConnection.h | 14 + RServerConnection.m | 37 ++ TerminalDelegate.h | 1 + TerminalDelegate.m | 2 + main.m | 1 + 25 files changed, 1162 insertions(+), 493 deletions(-) create mode 100644 RDataPortManager.h create mode 100644 RDataPortManager.m create mode 100644 REnvironment.h create mode 100644 REnvironment.m create mode 100644 RFunction.h create mode 100644 RFunction.m create mode 100644 RObject.h create mode 100644 RObject.m create mode 100644 RServerConnection.h create mode 100644 RServerConnection.m diff --git a/DeviceView.m b/DeviceView.m index d8d742b..14c0715 100644 --- a/DeviceView.m +++ b/DeviceView.m @@ -65,4 +65,9 @@ - (void)willCloseDevice:(RDevice*)aDevice { } +- (void)didEndPageForDevice:(RDevice*)aDevice { +} +- (void)willBeginPageForDevice:(RDevice*)aDevice { +} + @end diff --git a/DeviceWindowController.m b/DeviceWindowController.m index dcb2195..424701c 100644 --- a/DeviceWindowController.m +++ b/DeviceWindowController.m @@ -51,4 +51,10 @@ } } +- (void)didEndPageForDevice:(RDevice*)aDevice { +} + +- (void)willBeginPageForDevice:(RDevice*)aDevice { +} + @end diff --git a/RApplicationDelegate.m b/RApplicationDelegate.m index f49bdbd..e4896d4 100644 --- a/RApplicationDelegate.m +++ b/RApplicationDelegate.m @@ -20,8 +20,8 @@ - (void)applicationWillFinishLaunching:(NSNotification*)aNotification { RInterpreter *ri = [RInterpreter sharedInterpreter]; - if((NULL != getenv("EMACS") && strncmp(getenv("EMACS"),"t",1)==0) || - (NULL != getenv("TERM"))) + if(!(NULL != getenv("RNOTERM") && strncmp(getenv("RNOTERM"),"t",1)==0) && + ((NULL != getenv("EMACS") && strncmp(getenv("EMACS"),"t",1)==0) || (NULL != getenv("TERM")))) [ri setAllowTerminal:YES]; if(NULL != getenv("RNOVEND")) [ri setVend:NO]; diff --git a/RCGImageDevice.m b/RCGImageDevice.m index d26084e..9c88893 100644 --- a/RCGImageDevice.m +++ b/RCGImageDevice.m @@ -65,11 +65,11 @@ - (NSData*)deviceRepresentationOfType:(NSString*)aType { if((nil == aType || [aType isEqual:@""])) { - NSString *display = [self display]; + NSString *aDisplay = [self display]; //If we don't have a display just return the raw bitmap - if(nil == display || [display isEqual:@""]) + if(nil == aDisplay || [aDisplay isEqual:@""]) return [[[NSData alloc] initWithBytes:bitmap length:bitmapSize] autorelease]; - else aType = display; + else aType = aDisplay; } if([aType isEqual:@"tiff"] || [aType isEqual:NSTIFFPboardType]) { } diff --git a/RDataPortManager.h b/RDataPortManager.h new file mode 100644 index 0000000..a1147da --- /dev/null +++ b/RDataPortManager.h @@ -0,0 +1,14 @@ +#import +#import "RObject.h" + +@interface RDataPortManager : NSObject { + NSString *portName; + NSMutableArray *subscribers; +} +- (void)setName:(NSString*)aName; +- (void)addSubscriber:(id)subs; +- (void)removeSubscriber:(id)subs; + +- (void)setValue:(id)value; + +@end diff --git a/RDataPortManager.m b/RDataPortManager.m new file mode 100644 index 0000000..6cdc377 --- /dev/null +++ b/RDataPortManager.m @@ -0,0 +1,19 @@ +// +// RDataPortManager.m +// RExecServer +// +// Created by Byron Ellis on 7/5/07. +// Copyright 2007 __MyCompanyName__. All rights reserved. +// + +#import "RDataPortManager.h" + + +@implementation RDataPortManager + + + +- (void)setValue:(id)value { +} + +@end diff --git a/RDevice.h b/RDevice.h index 671243d..11b7767 100644 --- a/RDevice.h +++ b/RDevice.h @@ -13,6 +13,9 @@ - (void)willCloseDevice:(RDevice*)aDevice; +- (void)willBeginPageForDevice:(RDevice*)aDevice; +- (void)didEndPageForDevice:(RDevice*)aDevice; + @end @interface RDevice : NSObject { @@ -27,7 +30,7 @@ - (id)delegate; - (void)setDelegate:(id)delegate; -- (id)initWithDevice:(NewDevDesc*)dd size:(NSSize)size pointSize:(double)ps display:(NSString*)aDisplay target:(NSString*)aTarget +- (id)initWithDevice:(void*)dd size:(NSSize)size pointSize:(double)ps display:(NSString*)aDisplay target:(NSString*)aTarget background:(int)bg antialias:(BOOL)antialias; - (BOOL)canResize; - (BOOL)canLocate; @@ -47,5 +50,7 @@ - (NSString*)display; - (void)close; +- (bycopy NSData*)snapshot; +- (void)setSnapshot:(NSData*)aData; @end diff --git a/RDevice.m b/RDevice.m index 09f62ea..c03d362 100644 --- a/RDevice.m +++ b/RDevice.m @@ -1,5 +1,5 @@ #import "RDevice.h" - +#import "NSData+RSerialize.h" CGContextRef RDevice_GetCGContext(QuartzDesc_t,void*); int RDevice_LocatePoint(QuartzDesc_t,void*,double*,double*); @@ -23,8 +23,9 @@ static NSMutableDictionary *deviceDict = nil; } - (double)defaultScale { return 1.0; } -- (id)initWithDevice:(NewDevDesc*)dd size:(NSSize)size pointSize:(double)ps display:(NSString*)aDisplay target:(NSString*)aTarget +- (id)initWithDevice:(void*)dd size:(NSSize)size pointSize:(double)ps display:(NSString*)aDisplay target:(NSString*)aTarget background:(int)bg antialias:(BOOL)antialias { + if(nil == [super init]) return nil; desc = RDevice_Create(dd,[self defaultScale],ps,size.width,size.height,bg,antialias, RDevice_GetCGContext, @@ -55,11 +56,19 @@ static NSMutableDictionary *deviceDict = nil; - (CGContextRef)context { return NULL; } - (BOOL)locatePointAtX:(double*)x y:(double*)y { *x = *y = 0.0;return NO; } - (void)close { - if(nil != delegate) [delegate willCloseDevice:self]; + if(nil != delegate) { + [delegate didEndPageForDevice:self]; + [delegate willCloseDevice:self]; + } desc = NULL; [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"RDeviceClosed" object:self]]; } -- (void)newPage { } +- (void)newPage { + if(nil != delegate) { + [delegate didEndPageForDevice:self]; + [delegate willBeginPageForDevice:self]; + } +} - (void)activate:(int)devNum { if(nil != delegate) [delegate didActivateDevice:self withNumber:devNum]; } @@ -76,9 +85,11 @@ static NSMutableDictionary *deviceDict = nil; - (void)setSize:(NSSize)newSize { double sc = 72.0*RDevice_GetScale(desc); - RDevice_SetWidth(desc,newSize.width/sc); - RDevice_SetHeight(desc,newSize.height/sc); - [self didResize]; + if(abs(newSize.width/sc - RDevice_GetWidth(desc)) > .0001 || abs(newSize.height/sc - RDevice_GetHeight(desc)) > .0001) { + RDevice_SetWidth(desc,newSize.width/sc); + RDevice_SetHeight(desc,newSize.height/sc); + [self didResize]; + } } - (id)delegate { return delegate; } @@ -103,18 +114,25 @@ static NSMutableDictionary *deviceDict = nil; } } -- (void)redraw { RDevice_ReplayDisplayList(desc); } +- (void)redraw { RDevice_ReplayDisplayList(desc);[delegate didUpdateDevice:self]; } - (NSData*)deviceRepresentationOfType:(NSString*)aType { return nil; } -- (NSData*)displayList { +- (bycopy NSData*)snapshot { + return [NSData dataWithSEXP:RDevice_GetSnapshot(desc)]; + } - -- (void)setDisplayList:(NSData*)displayList { +- (void)setSnapshot:(NSData*)aData { + NSLog(@"Got snapshot data with length:%d",[aData length]); + RDevice_RestoreSnapshot(desc, [aData unserialize]); + if(nil != delegate) + [delegate didUpdateDevice:self]; } + + @end CGContextRef RDevice_GetCGContext(QuartzDesc_t desc,void*ui) { diff --git a/RDeviceImpl.c b/RDeviceImpl.c index b4edbb1..4c27a48 100644 --- a/RDeviceImpl.c +++ b/RDeviceImpl.c @@ -1,8 +1,14 @@ #include "RDeviceImpl.h" +#include +#include +#include + +#include +#include typedef struct { double ps,scale,width,height,tscale; - int dirty,bg,gstate,antialias; + int dirty,bg,gstate,antialias,redraw; CGRect clipRect; NewDevDesc *dev; //Circular reference. void* userInfo; @@ -57,7 +63,24 @@ void RDevice_Update(QuartzDesc_t desc) { void RDevice_ReplayDisplayList(QuartzDesc_t desc) { QuartzDesc *qd = (QuartzDesc*)desc; - GEplayDisplayList((GEDevDesc*)GetDevice(devNumber((DevDesc*)qd->dev))); + qd->redraw = 1; + if(qd->dev->displayList != R_NilValue) + GEplayDisplayList((GEDevDesc*)GetDevice(devNumber((DevDesc*)qd->dev))); + qd->redraw = 0; +} + +void* RDevice_GetSnapshot(QuartzDesc_t desc) { + QuartzDesc *qd = (QuartzDesc*)desc; + return qd->dev->savedSnapshot; +} + +void RDevice_RestoreSnapshot(QuartzDesc_t desc,void* snap) { + QuartzDesc *qd = (QuartzDesc*)desc; + PROTECT((SEXP)snap); + qd->redraw = 1; + GEplaySnapshot((SEXP)snap,(GEDevDesc*)GetDevice(devNumber((DevDesc*)qd->dev))); + qd->redraw = 0; + UNPROTECT(1); } #pragma mark Function Prototypes @@ -83,7 +106,7 @@ static void RQuartz_MetricInfo(int,R_GE_gcontext *,double*,double*,double*,N void* RDevice_Create( - NewDevDesc *dev,double scale,double ps,double width,double height,int bg,int aa, + void *_dev,double scale,double ps,double width,double height,int bg,int aa, CGContextRef (*getCGContext)(QuartzDesc_t dev,void*userInfo), //Get the context for this device int (*locatePoint)(QuartzDesc_t dev,void*userInfo,double*x,double*y), void (*close)(QuartzDesc_t dev,void*userInfo), @@ -91,7 +114,7 @@ void* RDevice_Create( void (*activate)(QuartzDesc_t dev,void*userInfo,int devNum), void (*deactivate)(QuartzDesc_t dev,void*userInfo,int devNum), void*userInfo) { - + NewDevDesc *dev = (NewDevDesc*)_dev; dev->displayList = R_NilValue; dev->startfill = R_RGB(255,255,255); @@ -134,6 +157,7 @@ void* RDevice_Create( dev->canResizePlot = TRUE; dev->canChangeFont = TRUE; dev->canRotateText = TRUE; + dev->canResizeText = TRUE; dev->canClip = TRUE; dev->canHAdj = 2; dev->canChangeGamma= TRUE; @@ -167,7 +191,7 @@ void* RDevice_Create( qd->clipRect = CGRectMake(0,0,dev->right,dev->bottom); qd->dirty = 0; - + qd->redraw= 0; return (QuartzDesc_t)qd; } @@ -325,7 +349,7 @@ static void RQuartz_Size(double*left,double*right,double*bottom,double*top,DEVDE static void RQuartz_NewPage(CTXDESC) { DRAWSPEC; //Should have new page event - if(NULL != xd->newPage) xd->newPage(xd,xd->userInfo); + if(0 == xd->redraw && NULL != xd->newPage) xd->newPage(xd,xd->userInfo); SET(RQUARTZ_FILL); CGRect bounds = CGRectMake(0,0,RDevice_ScaledWidth(xd),RDevice_ScaledHeight(xd)); if(R_ALPHA(xd->bg) == 255 && R_ALPHA(gc->fill) == 255) diff --git a/RDeviceImpl.h b/RDeviceImpl.h index 10b1600..502955b 100644 --- a/RDeviceImpl.h +++ b/RDeviceImpl.h @@ -1,19 +1,13 @@ #ifndef _H_RDEVICEIMPL_ #define _H_RDEVICEIMPL_ -#include -#include -#include - -#include -#include - #include + typedef void* QuartzDesc_t; QuartzDesc_t RDevice_Create( - NewDevDesc *dd,double scale,double ps,double width,double height,int bg,int aa, + void*dd,double scale,double ps,double width,double height,int bg,int aa, CGContextRef (*getCGContext)(QuartzDesc_t dev,void*userInfo), //Get the context for this device int (*locatePoint)(QuartzDesc_t dev,void*userInfo,double*x,double*y), void (*close)(QuartzDesc_t dev,void*userInfo), @@ -41,7 +35,9 @@ double RDevice_GetPointSize(QuartzDesc_t desc); int RDevice_GetDirty(QuartzDesc_t desc); void RDevice_SetDirty(QuartzDesc_t desc,int dirty); -void RDevice_ReplayDisplayList(QuartzDesc_t desc); +void RDevice_ReplayDisplayList(QuartzDesc_t desc); +void* RDevice_GetSnapshot(QuartzDesc_t desc); +void RDevice_RestoreSnapshot(QuartzDesc_t desc,void* snapshot); int RDevice_GetGDepth(QuartzDesc_t desc); void RDevice_ResetGDepth(QuartzDesc_t desc); diff --git a/REnvironment.h b/REnvironment.h new file mode 100644 index 0000000..16d7597 --- /dev/null +++ b/REnvironment.h @@ -0,0 +1,18 @@ +#import +#import "RObject.h" +#import "RServerConnection.h" +#import "NSData+RSerialize.h" + +@interface REnvironment : RObject { +} ++ (REnvironment*)globalEnv; + +- (RServerConnection*)connectToServer:(NSString*)aServer host:(NSString*)aHost; + +- (NSArray*)names; +- (RObject*)objectWithName:(NSString*)aName; +- (NSArray*)objectDescriptions; + +- (BOOL)unserializeObject:(NSData*)obj toName:(NSString*)aName overwrite:(BOOL)shouldOverwrite; + +@end diff --git a/REnvironment.m b/REnvironment.m new file mode 100644 index 0000000..a727c0a --- /dev/null +++ b/REnvironment.m @@ -0,0 +1,65 @@ +#import "REnvironment.h" +#include +#include + +#undef error + +@implementation REnvironment ++ (REnvironment*)globalEnv { + static REnvironment *globalEnv = nil; + if(nil == R_GlobalEnv) return nil; + if(nil == globalEnv) globalEnv = [[self objectWithSEXP:R_GlobalEnv preserve:NO] retain]; + return globalEnv; +} + +- (NSArray*)names { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + SEXP ls; + PROTECT(ls = lang2(install("ls"),(SEXP)obj_ptr)); + SET_TAG(CDR(ls),install("envir")); + int err; + SEXP res; + PROTECT(res = R_tryEval(ls,R_GlobalEnv,&err)); + if(err == 0 && res != R_NilValue) { + int i; + for(i=0;i +#import "RObject.h" + +@interface RFunction : RObject { + +} + ++ (RFunction*)functionWithName:(NSString*)aFun; + +@end diff --git a/RFunction.m b/RFunction.m new file mode 100644 index 0000000..3f262e1 --- /dev/null +++ b/RFunction.m @@ -0,0 +1,39 @@ +// +// RFunction.m +// RExecServer +// +// Created by Byron Ellis on 7/6/07. +// Copyright 2007 __MyCompanyName__. All rights reserved. +// + +#import "RFunction.h" +#include + +@implementation RFunction + ++ (RFunction*)functionWithName:(NSString*)aFun { + +} + +- (SEXP)_formals { + SEXP e,ret; + int err; + PROTECT(e = lang2(install("formals"),(SEXP)obj_ptr)); + ret = R_tryEval(e,R_GlobalEnv,&err); + if(err == 0) { + UNPROTECT(1); + return ret; + } else { + UNPROTECT(1); + return R_NilValue; + } +} + +- (NSArray*)arguments { +} + +- (NSDictionary*)defaults { +} + + +@end diff --git a/RInterpreter.h b/RInterpreter.h index 3f5364d..246af92 100644 --- a/RInterpreter.h +++ b/RInterpreter.h @@ -1,5 +1,6 @@ #import - +#import "RDevice.h" +#import "REnvironment.h" @interface RInterpreter : NSObject { @@ -60,8 +61,7 @@ #pragma mark Moving Data Between Servers -- (NSData*)serializeObjectWithName:(NSString*)anName error:(NSError**)anError; -- (BOOL)deserializeObject:(NSData*)anObject withName:(NSString*)aName replace:(BOOL)shouldReplace error:(NSError**)error; -- (void)copyObjectWithName:(NSString*)anObject toServer:(NSString*)aServer error:(NSError**)anError; + +- (REnvironment*)environment; @end diff --git a/RInterpreter.m b/RInterpreter.m index 432bfda..55eb902 100644 --- a/RInterpreter.m +++ b/RInterpreter.m @@ -67,10 +67,15 @@ //Set some environment variables to their defaults if they are not presently set. setenv("R_HOME",[[[NSBundle bundleWithIdentifier:@"org.r-project.R-framework"] resourcePath] UTF8String],0); setenv("LANG",[[NSString stringWithFormat:@"%@.UTF-8",[[NSLocale currentLocale] localeIdentifier]] UTF8String],0); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(closeInterpreter:) name:NSApplicationWillTerminateNotification object:nil]; + return self; } - +- (void)closeInterpreter:(NSNotification*)aNotify { + if(nil != delegate) [delegate didCloseInterpreter:self]; +} - (BOOL)isConfigured { return configured; } @@ -118,6 +123,7 @@ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if(NULL != getenv("RVENDNAME")) { vendName = [[NSString alloc] initWithUTF8String:getenv("RVENDNAME")]; + NSLog(@"Vending with specified name: %@",vendName); NSConnection *conn = [NSConnection defaultConnection]; [conn setRootObject:self]; if(NO == [conn registerName:vendName]) { @@ -136,7 +142,7 @@ } else [vendName release]; } - if(vend_num == 11) { + if(vend_num == 17) { NSLog(@"Unable to register server. Presently, a maximum of 16 local execution servers are allowed per machine"); vendName = nil; } @@ -152,9 +158,7 @@ [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"RExecServerStartedVending" object:vendName]; [NSApp run]; [pool release]; - } else - NSLog(@"Finished vending with delegate %@",[delegate description]); - + } waiting = NO; [self _run]; } @@ -186,6 +190,7 @@ - (NSArray*)devices { return deviceList; } - (NSString*)serverName { return vendName; } +- (REnvironment*)environment { return [REnvironment globalEnv]; } - (NSData*)serializeObjectWithName:(NSString*)anName error:(NSError**)anError { const char *name = [anName UTF8String]; @@ -227,6 +232,11 @@ [theProxy release]; } +- (RDevice*)deviceCopyOfType:(NSString*)aType withTarget:(NSString*)aTarget { + return nil; +} + + @end @@ -309,12 +319,13 @@ extern void Rstd_WriteConsole(char*,int); Rf_initialize_R(argc,argv); //R_GUIType = "RExecServer"; //We are NOT the Aqua GUI, but not being the aqua gui is even more annoying. if(YES == allowTerminal) { - NSLog(@"Installing terminal delegate"); + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; TerminalDelegate *tempDel = [[TerminalDelegate alloc] init]; [tempDel setReaderFunction:ptr_R_ReadConsole]; [tempDel setWriterFunction:Rstd_WriteConsole]; [tempDel setFlushFunction:ptr_R_FlushConsole]; [self setDelegate:tempDel]; + [pool release]; } R_Outputfile = NULL; R_Consolefile = NULL; @@ -534,7 +545,12 @@ void RInterp_WriteConsole(char*buffer,int length) { } void RInterp_ClearerrConsole() { [[RInterpreter sharedInterpreter] clearErrorConsole]; } void RInterp_Busy() { [[RInterpreter sharedInterpreter] busy]; } -void RInterp_CleanUp(SA_TYPE type,int a,int b) { } +void RInterp_CleanUp(SA_TYPE type,int a,int b) { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + [[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:NSApplicationWillTerminateNotification object:nil]]; + [[RInterpreter sharedInterpreter] closeInterpreter:nil]; + [pool release]; +} int RInterp_ShowFiles(int a,char**b,char**c,char*d,Rboolean e,char*f) { return [[RInterpreter sharedInterpreter] showFiles:a file:b headers:c wtitle:d del:e pager:f]; } diff --git a/RObject.h b/RObject.h new file mode 100644 index 0000000..0f230bf --- /dev/null +++ b/RObject.h @@ -0,0 +1,25 @@ +#import + + +@interface RObject : NSObject { + void* obj_ptr; + BOOL preserved; +} ++ (id)objectWithSEXP:(void*)aSexp preserve:(BOOL)shouldPreserve; ++ (id)objectWithSEXP:(void*)aSexp; + +- (id)initWithSEXP:(void*)aSexp preserve:(BOOL)shouldPreserve; +- (id)initWithSEXP:(void*)aSexp; + +- (int)length; +- (NSArray*)classList; +- (BOOL)isMatrix; +- (NSArray*)dimensions; + +- (NSData*)serialize; +- (id)coerce; + +- (NSDictionary*)describeWithName:(NSString*)aName; +- (NSDictionary*)descibe; + +@end diff --git a/RObject.m b/RObject.m new file mode 100644 index 0000000..a04b2ab --- /dev/null +++ b/RObject.m @@ -0,0 +1,90 @@ +#import "RObject.h" +#import "NSData+RSerialize.h" + +#include +#undef error +#undef length + +@implementation RObject ++ (id)objectWithSEXP:(void*)aSexp preserve:(BOOL)shouldPreserve { return [[[self alloc] initWithSEXP:aSexp preserve:shouldPreserve] autorelease]; } ++ (id)objectWithSEXP:(void*)aSexp { return [[[self alloc] initWithSEXP:aSexp] autorelease]; } + +- (id)initWithSEXP:(void*)aSexp preserve:(BOOL)shouldPreserve { + if(nil == [super init]) return nil; + if(YES == shouldPreserve) R_PreserveObject((SEXP)aSexp); + obj_ptr = aSexp; + preserved = shouldPreserve; + return self; +} +- (id)initWithSEXP:(void*)aSexp { return [self initWithSEXP:aSexp preserve:YES]; } + +- (id)initWithData:(NSData*)data { + return [self initWithSEXP:[data unserialize]]; +} + +- (void)dealloc { + if(obj_ptr != NULL && YES == preserved) R_ReleaseObject((SEXP)obj_ptr); + [super dealloc]; +} + + +- (NSData*)serialize { return [NSData dataWithSEXP:(SEXP)obj_ptr]; } + + +- (id)coerce { + return nil; +} + +- (int)length { return Rf_length((SEXP)obj_ptr); } + +- (NSArray*)dimensions { + NSMutableArray *arr = [[NSMutableArray alloc] init]; + SEXP e,dims; + PROTECT(e = lang2(install("dim"),(SEXP)obj_ptr)); + int err,i; + PROTECT(dims = R_tryEval(e,R_GlobalEnv,&err)); + if(!err && R_NilValue != dims) { + for(i=0;i + +@class REnvironment; + +@interface RServerConnection : NSObject { + REnvironment *env; + id server; +} ++ (RServerConnection*)serverConnectionToServer:(NSString*)aServer host:(NSString*)hostName environment:(REnvironment*)anEnv; +- (id)initWithConnectionToServer:(NSString*)aServer host:(NSString*)hostName environment:(REnvironment*)aEnv; +- (BOOL)synchronizePackages; +- (BOOL)copyObject:(NSString*)aFrom toName:(NSString*)aTo; + +@end diff --git a/RServerConnection.m b/RServerConnection.m new file mode 100644 index 0000000..2b9a78d --- /dev/null +++ b/RServerConnection.m @@ -0,0 +1,37 @@ +// +// RServerConnection.m +// RExecServer +// +// Created by Byron Ellis on 7/9/07. +// Copyright 2007 __MyCompanyName__. All rights reserved. +// + +#import "RServerConnection.h" +#import "REnvironment.h" + +@implementation RServerConnection ++ (RServerConnection*)serverConnectionToServer:(NSString*)aServer host:(NSString*)hostName environment:(REnvironment*)anEnv { + return [[[self alloc] initWithConnectionToServer:aServer host:hostName environment:anEnv] autorelease]; +} +- (id)initWithConnectionToServer:(NSString*)aServer host:(NSString*)hostName environment:(REnvironment*)aEnv { + if(nil == [super init]) return nil; + server = [NSConnection rootProxyForConnectionWithRegisteredName:aServer host:hostName]; + if(nil == server) { + [self release]; + return nil; + } + env = [aEnv retain]; + return self; +} +- (void)dealloc { + if(nil != env) [env release]; + [super dealloc]; +} + +- (BOOL)synchronizePackages { return NO; } +- (BOOL)copyObject:(NSString*)aFrom toName:(NSString*)aTo { + NSData *data = [[(REnvironment*)[server environment] objectWithName:aFrom] serialize]; + return [env unserializeObject:data toName:aTo overwrite:YES]; +} + +@end diff --git a/TerminalDelegate.h b/TerminalDelegate.h index f96fa31..d2e60ce 100644 --- a/TerminalDelegate.h +++ b/TerminalDelegate.h @@ -31,6 +31,7 @@ typedef void (*R_FLUSH_FN)(); - (void)didBeginEvaluationForInterpreter:(id)anInterpreter; - (void)didBeginWaitingForInputWithMaximumLength:(int)bufferLength addToHistory:(BOOL)shouldAdd forInterpreter:(id)anInterpreter; - (void)didGetInputForInterpreter:(id)anInterpreter; +- (void)didCloseInterpreter:(id)anInterpreter; - (BOOL)shouldBufferOutputForInterpreter:(id)anInterpreter; - (void)appendString:(NSString*)outputString ofType:(int)aType forInterpreter:(id)anInterpreter; diff --git a/TerminalDelegate.m b/TerminalDelegate.m index 4f6bcbb..d43a034 100644 --- a/TerminalDelegate.m +++ b/TerminalDelegate.m @@ -87,5 +87,7 @@ void Terminal_ProcessEvents(void) { } - (void)flushOutputForInterpreter:(id)anInterpreter { } +- (void)didCloseInterpreter:(id)anInterpreter { +} @end diff --git a/main.m b/main.m index 605eb06..50da9ff 100644 --- a/main.m +++ b/main.m @@ -24,5 +24,6 @@ int main(int argc, char *argv[]) [pool release]; //Turn primary control over to the R event loop. [[RInterpreter sharedInterpreter] run]; + //If we get here then we should shut down the application. return 0; } -- 2.11.4.GIT