-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathmain.m
192 lines (165 loc) · 7.25 KB
/
main.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*
* R.app : a Cocoa front end to: "R A Computer Language for Statistical Data Analysis"
*
* R.app Copyright notes:
* Copyright (C) 2004-5 The R Foundation
* written by Stefano M. Iacus and Simon Urbanek
*
*
* R Copyright notes:
* Copyright (C) 1995-1996 Robert Gentleman and Ross Ihaka
* Copyright (C) 1998-2001 The R Development Core Team
* Copyright (C) 2002-2004 The R Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* A copy of the GNU General Public License is available via WWW at
* http://www.gnu.org/copyleft/gpl.html. You can also obtain it by
* writing to the Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA.
*
* Created by Stefano Iacus on 7/26/04.
* $Id: main.m 7917 2021-01-25 03:37:15Z urbaneks $
*/
#import <Cocoa/Cocoa.h>
#import "RGUI.h"
#import "REngine/REngine.h"
#import "Preferences.h"
#import "PreferenceKeys.h"
#import "RController.h"
#import "Rversion.h"
#import <ExceptionHandling/NSExceptionHandler.h>
#import "Tools/GlobalExHandler.h"
#include <string.h>
#include <stdlib.h>
#include <sys/utsname.h> /* for uname */
/* we need the following two to implement RappQuit and register it with R */
#include "R_ext/Rdynload.h"
#include "R_ext/RStartup.h"
/* those are exported in RGUI.h */
NSString *Rapp_R_version_short;
NSString *Rapp_R_version;
double os_version;
char *os_version_string;
/* this is called by the R.app q/quit function */
static SEXP RappQuit(SEXP save, SEXP status, SEXP runLast) {
int sc, rl, save_flag = -1, cancel = 0; /* 1=yes, 0=no, -1=ask */
const char *sv;
if (!isString(save) || LENGTH(save) != 1) Rf_error("'save' must be a character vector of length one.");
sc = asInteger(status);
rl = asInteger(runLast);
sv = CHAR(STRING_ELT(save, 0));
if (!strcmp(sv, "yes")) save_flag = 1;
else if (!strcmp(sv, "no")) save_flag = 0;
else if (!strcmp(sv, "ask")) save_flag = -1;
else if (strcmp(sv, "default"))
Rf_error("unrecognized value of 'save'");
if ([RController sharedController])
cancel = [[RController sharedController] quitRequest: save_flag withCode: sc last: rl];
// FIXME: this is never executed - we should re-visit the shutdown procedure ...
// R_CleanUp is note exported so better not use it
#if 0
if (!cancel) /* no cancel and we're still here -> run the internal version */
R_CleanUp((save_flag == 0) ? SA_NOSAVE : ((save_flag == -1) ? SA_SAVEASK : SA_SAVE), sc, rl);
#endif
Rf_error("cancelled by user");
return R_NilValue;
}
/* this is called by the R.app prompt() function in interactive mode */
static SEXP RappPrompt(SEXP filename, SEXP isTempFile) {
BOOL isTemp = (asInteger(isTempFile) == 1) ? YES : NO;
const char *fp;
NSString *filepath = nil;
if (TYPEOF(filename) == STRSXP && LENGTH(filename) > 0) {
if (LENGTH(filename) > 1)
Rf_warning("`filename' has more than one element, using only the first one.");
fp = Rf_translateCharUTF8(STRING_ELT(filename, 0));
if (fp)
filepath = [NSString stringWithCString:fp encoding:NSUTF8StringEncoding];
}
if(filepath && [filepath length])
[[RController sharedController] handlePromptRdFileAtPath:[filepath stringByExpandingTildeInPath] isTempFile:isTemp];
else
Rf_error("in interactive mode the argument 'filename' has to be either a valid path or NULL or NA");
return R_NilValue;
}
SEXP pkgbrowser(SEXP rpkgs, SEXP rvers, SEXP ivers, SEXP wwwhere,
SEXP install_dflt);
SEXP hsbrowser(SEXP h_topic, SEXP h_pkg, SEXP h_desc, SEXP h_wtitle,
SEXP h_url);
SEXP pkgmanager(SEXP pkgstatus, SEXP pkgname, SEXP pkgdesc, SEXP pkgurl);
SEXP datamanager(SEXP dsets, SEXP dpkg, SEXP ddesc, SEXP durl);
SEXP customprint(SEXP objType, SEXP obj);
SEXP wsbrowser(SEXP ids, SEXP isroot, SEXP iscont, SEXP numofit,
SEXP parid, SEXP name, SEXP type, SEXP objsize);
static R_CallMethodDef mainCallMethods[] = {
{"RappQuit", (DL_FUNC) &RappQuit, 3},
{"RappPrompt", (DL_FUNC) &RappPrompt, 2},
{"pkgbrowser", (DL_FUNC) &pkgbrowser, 5},
{"hsbrowser", (DL_FUNC) &hsbrowser, 5},
{"pkgmanager", (DL_FUNC) &pkgmanager, 4},
{"datamanager", (DL_FUNC) &datamanager, 4},
{"aqua.custom.print", (DL_FUNC) &customprint, 2},
{"wsbrowser", (DL_FUNC) &wsbrowser, 8},
{NULL, NULL, 0}
};
static struct utsname os_uname;
int main(int argc, const char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
uname(&os_uname);
os_version_string = strdup(os_uname.release);
os_version = atof(os_uname.release);
if ([Preferences flagForKey:@"Debug all exceptions"] == YES) {
// add an independent exception handler
[[GlobalExHandler alloc] init]; // the init method also registers the handler
[[NSExceptionHandler defaultExceptionHandler] setExceptionHandlingMask: 1023]; // hang+log+handle all
}
Rapp_R_version_short = [[NSString alloc] initWithFormat:@"%d.%d", (R_VERSION >> 16), (R_VERSION >> 8)&255];
Rapp_R_version = [[NSString alloc] initWithFormat:@"%s.%s", R_MAJOR, R_MINOR];
[NSApplication sharedApplication];
[NSBundle loadNibNamed:@"MainMenu" owner:NSApp];
SLog(@" - initalizing R");
if (![[REngine mainEngine] activate]) {
NSRunAlertPanel(NLS(@"Cannot start R"),[NSString stringWithFormat:NLS(@"Unable to start R: %@"), [[REngine mainEngine] lastError]],NLS(@"OK"),nil,nil);
exit(-1);
}
SLog(@" - load R code for R.app");
R_registerRoutines(R_getEmbeddingDllInfo(), 0, mainCallMethods, 0, 0);
NSString *codePath = [[NSBundle mainBundle] pathForResource:@"GUI-tools.R" ofType:@""];
SLog(@" - loading code from '%@'", codePath);
[[REngine mainEngine] executeString: [NSString stringWithFormat:@"try(local(source(\"%@\",local=TRUE,echo=FALSE,verbose=FALSE,encoding='UTF-8',keep.source=FALSE)))", codePath]];
SLog(@" - set R options");
// force html-help, because that's the only format we can handle ATM
[[REngine mainEngine] executeString: @"options(help_type='html')"];
SLog(@" - set default CRAN mirror");
{
NSString *url = [Preferences stringForKey:defaultCRANmirrorURLKey withDefault:@""];
if (![url isEqualToString:@""])
[[REngine mainEngine] executeString:[NSString stringWithFormat:@"try(local({ r <- getOption('repos'); r['CRAN']<-gsub('/$', '', \"%@\"); options(repos = r) }),silent=TRUE)", url]];
}
SLog(@" - loading secondary NIBs");
if (![NSBundle loadNibNamed:@"Vignettes" owner:NSApp]) {
SLog(@" * unable to load Vignettes.nib!");
}
SLog(@"main: finish launching");
[NSApp finishLaunching];
// torture
[pool release];
pool = [[NSAutoreleasePool alloc] init];
// ready to rock
SLog(@"main: entering REPL");
[[REngine mainEngine] runREPL];
SLog(@"main: returned from REPL");
[pool release];
SLog(@"main: exiting with status 0");
return 0;
}