Annotation of OpenXM/src/cfep/MyDocument.m, Revision 1.7
1.1 takayama 1: //
2: // MyDocument.m
3: // cfep
4: //
5: // Created by Nobuki Takayama
6: // Copyright (c) 2006 OpenXM.org
7: //
8:
9: // [self setDefaultPeer BASH] or [self setDefaultPeer OX_TEXMACS]
10:
11: #include <signal.h>
12: #import "MyDocument.h"
13: #import "MyOutputWindowController.h"
14: #import "MyOpenGLController.h"
15:
16: int myDebug=0;
17: static int myDocumentSaidTheMessageAboutX = 0;
18:
19:
20: @implementation MyDocument
1.4 takayama 21: static int NoEngine = 0; // experimental.
22: static NSMenuItem *menuItemNoEngine = nil; // NoEngine
1.3 takayama 23: // For OnState or OffState in the execution menu
24: static NSMenuItem *menuItemNotebookMode = nil;
25: static NSMenuItem *menuItemBasicMode = nil;
26: static NSMenuItem *menuItemRisaAsir = nil;
27: static NSMenuItem *menuItemKanSm1 = nil;
28: static NSMenuItem *menuItemOutputDebugMessages = nil; //cf. debugMyTunnel;
29: static NSMenuItem *menuItemPrettyPrint = nil; // prettyPrint.
30:
1.1 takayama 31:
32: - (void)dealloc {
33: MyOutputWindowController *mowc;
34: if (myDebug) NSLog(@"dealloc of MyDocument.\n");
35: if (myDebug) NSLog(@"retainCount of task=%d\n",[task retainCount]); // why is it 2?
36: [self closeMyModel];
37: // [task dealloc]; //BUG. if we do this, error happens.
38: mowc = [MyOutputWindowController sharedMyOutputWindowController: self];
39: if (mowc != nil) [mowc closeMyOutputWindow: self];
40: if (errorLines) { [errorLines autorelease]; errorLines = nil; }
41:
42: [myDecoder dealloc];
43:
44: [dataFromFile release];
45: [rtfDataFromFile release];
46: [textDataFromFile release];
47: if (myDebug) NSLog(@"Done: dealloc of MyDocument.\n");
48: [super dealloc];
49: }
50:
51: // The name of the nib file to load for this document.
52: - (NSString *)windowNibName
53: {
54: return @"MyDocument";
55: }
56:
57: // Loads up the data when the nib file is loaded.
58: - (void)windowControllerDidLoadNib:(NSWindowController *)aController {
59: [super windowControllerDidLoadNib:aController];
60:
61: if (dataFromFile) {
62: [self loadtextViewWithData:dataFromFile];
63: [dataFromFile release];
64: dataFromFile = nil;
65: } else if (rtfDataFromFile) {
66: [self loadtextViewWithRTFData: rtfDataFromFile];
67: [rtfDataFromFile release];
68: rtfDataFromFile = nil;
69: } else if (textDataFromFile) {
70: [self loadtextViewWithTextData: textDataFromFile];
71: [textDataFromFile release];
72: textDataFromFile = nil;
73: }
74: [self addMenuExec]; // adding the execution menu.
75: [textViewIn setAllowsUndo:YES];
1.2 takayama 76: if ([textViewIn isContinuousSpellCheckingEnabled]) [textViewIn toggleContinuousSpellChecking: self]; // Turn off the spell checking.
1.1 takayama 77: [self sayTheMessageAboutX];
78: [self initAux];
79: }
80:
81: // Load the view with data given an NSData.
82: - (void)loadtextViewWithData:(NSData *)data {
83: [textViewIn replaceCharactersInRange:NSMakeRange(0, [[textViewIn string] length]) withRTFD:data];
84: }
85: - (void)loadtextViewWithRTFData:(NSData *)data {
86: [textViewIn replaceCharactersInRange:NSMakeRange(0, [[textViewIn string] length]) withRTF:data];
87: }
88: -(void) loadtextViewWithTextData:(NSData *)data {
89: [textViewIn replaceCharactersInRange: NSMakeRange(0,[[textViewIn string] length])
90: withString:[NSString stringWithCString: [data bytes] encoding:NSUTF8StringEncoding]];
91: }
92:
93: // Return an NSData representation of our document's view.
94: - (NSData *)dataRepresentationOfType:(NSString *)aType {
95: if ([@"RTFWithGraphics" compare: aType] == NSOrderedSame) {
96: return [textViewIn RTFDFromRange:NSMakeRange(0, [[textViewIn string] length])];
97: }else if ([@"RTF" compare: aType] == NSOrderedSame) {
98: return [textViewIn RTFFromRange:NSMakeRange(0, [[textViewIn string] length])];
99: }else {
100: return [[textViewIn string] dataUsingEncoding: NSUTF8StringEncoding];
101: }
102: }
103:
104: // If we're loading from a file just retain the data and it will be
105: // loaded when windowControllerDidLoadNib is invoked. If not, go
106: // ahead and load the view with the data.
107: // These paths are separate in order to support Revert where the
108: // data is reloaded but the nib is not.
109: - (BOOL)loadDataRepresentation:(NSData *)data ofType:(NSString *)aType {
110: if ([@"RTFWithGraphics" compare: aType] == NSOrderedSame) {
111: if (textViewIn)
112: [self loadtextViewWithData:data];
113: else
114: dataFromFile = [data retain];
115: }else if ([@"RTF" compare: aType] == NSOrderedSame) {
116: if (textViewIn)
117: [self loadtextViewWithRTFData:data];
118: else
119: rtfDataFromFile = [data retain];
120: }else{
121: if (textViewIn)
122: [self loadtextViewWithTextData: data];
123: else
124: textDataFromFile = [data retain];
125: }
126:
127: return YES;
128: }
129:
130: // =======================================================================
131:
132: -(void) initAux {
133: static int serial;
134: MyEnvironment *myEnvironment;
135: myDocumentKey = [@"myDocumentNo" stringByAppendingString: [NSString stringWithFormat: @"%d",(++serial)]];
136: [myDocumentKey retain];
137:
138: onlySelectedArea = 0;
139: notebookMode = 0; // or = 1; // experimental.
140: oxEngine = 0; // experimental. For select engine menu.
141: errorLines = [NSMutableArray arrayWithCapacity: 10]; [errorLines retain];
142: debugMyTunnel = 0;
143: task = nil;
144: myEnvironment = [[MyEnvironment alloc] init]; [myEnvironment retain];
145:
146: myDefaultTypingAttributes = [myEnvironment getMyDefaultTypingAttributes];
147: [myDefaultTypingAttributes retain];
148: [textViewIn setTypingAttributes: myDefaultTypingAttributes];
149:
150: myDecoder = [[MyDecoder alloc] init]; [myDecoder retain];
151:
152: [self openMyModel: myEnvironment ];
1.3 takayama 153: [MyOpenGLController initMyOpenGLController]; // For the second execution, it will do nothing.
1.1 takayama 154: }
155: -(int) getMyDocumentKey { return myDocumentKey; }
156:
157: -(id) openMyModel: (MyEnvironment *) myEnvironment {
158: [myEnvironment showForDebug]; // for debug.
159: OpenXM_HOME= [myEnvironment getOpenXM_HOME];
160: [OpenXM_HOME retain]; // without these SIGSEGV
161: inputCounter = outputCounter = 0;
162: redirectPrint = 0;
163: peer = [myEnvironment getPeer];
164: peerStartupString = [myEnvironment getPeerStartupString];
165: [peerStartupString retain];
166: peerEndEvaluteMark = [myEnvironment getPeerEndEvaluateMark];
167: [peerEndEvaluteMark retain];
168:
169: [self stopIndicator];
1.4 takayama 170: if (NoEngine && (!restartMode)) { task = nil; return; }
171:
1.1 takayama 172: // Initialization to call /bin/bash
173: outboundPipe = [NSPipe pipe]; // since autorelease is called in pipe.
174: inboundPipe = [NSPipe pipe];
175: errPipe = [NSPipe pipe];
176: [outboundPipe retain]; [inboundPipe retain]; [errPipe retain];
177: outboundFileHandle = [outboundPipe fileHandleForWriting];
178: inboundFileHandle = [inboundPipe fileHandleForReading];
179: errFileHandle = [errPipe fileHandleForReading];
180:
181: NSLog(@"Starting /bin/bash\n");
182: task = [[NSTask alloc] init];
183: [task setStandardInput: outboundPipe];
184: [task setStandardOutput: inboundPipe];
185: [task setStandardError: errPipe];
186: [task setEnvironment: [myEnvironment getMyUnixEnvironment]];
187: //[task setArguments: [NSArray arrayWithObject: @"http://www.google.com"]];
188: //[task setLaunchPath: @"/usr/bin/open"];
189: //[task setLaunchPath: @"/Users/NobukiTakayama/OX4/OpenXM/bin/asir"];
190: //[task setLaunchPath: @"/bin/date"];
191: [task setLaunchPath: @"/bin/bash"];
192: // launch will be done after nib is loaded.
193: @try { // version >= 10.3, add option in info
194: [task launch];
195: } @catch (NSException *exception) {
196: NSLog(@"init task launch Caught %@: %@", [exception name], [exception reason]);
197: } @finally {
198: NSLog(@"/bin/bash is started.\n");
199: // fprintf(stderr,"pid = %d\n",[task processIdentifier]);
200: signal(SIGPIPE,SIG_IGN); //BUG. non-cocoa way.
201: [self oxEvaluateString: peerStartupString withMark: FALSE];
202: }
203:
204: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(readInboundData:)
205: name:NSFileHandleDataAvailableNotification object: inboundFileHandle];
206: [inboundFileHandle waitForDataInBackgroundAndNotify];
207: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(readErrData:)
208: name:NSFileHandleDataAvailableNotification object: errFileHandle];
209: [errFileHandle waitForDataInBackgroundAndNotify];
210:
211: return self;
212: }
213:
214: - (void) closeMyModel {
215: [self stopIndicator];
216: if (task == nil) {
217: NSLog(@"closeMyModel. Task is not running.\n"); return ;
218: }
219: [[NSNotificationCenter defaultCenter] removeObserver:self
220: name:NSFileHandleDataAvailableNotification object: inboundFileHandle];
221: [[NSNotificationCenter defaultCenter] removeObserver:self
222: name:NSFileHandleDataAvailableNotification object: errFileHandle];
223:
224: [inboundFileHandle closeFile];
225: [outboundFileHandle closeFile];
226: [errFileHandle closeFile];
227: [task terminate];
228: task = nil; //BUG. memory leak?
229: NSLog(@"Terminated the child process.\n");
230: }
231:
232: -(id) restartMyModel: (enum peer_type) peerType {
233: MyEnvironment *myEnvironment;
1.4 takayama 234: restartMode = 1;
1.1 takayama 235: [self closeMyModel];
236: myEnvironment = [[MyEnvironment alloc] initFor: peerType]; //BUG. leak memory?
237: [myEnvironment retain];
238: [myEnvironment showForDebug]; // for debug.
239: [self openMyModel: myEnvironment ];
240: return self;
241: }
242:
243: // messenges
244: -(void) sayTheMessageAboutX {
245: NSLog(@"myDocumentSaidTheMessageAboutX=%d\n",myDocumentSaidTheMessageAboutX);
246: if (!myDocumentSaidTheMessageAboutX) {
247: if ([MyEnvironment checkX] != 1)
1.5 takayama 248: // [self messageDialog:
249: // NSLocalizedString(@"A few commands (plot, ...) cannot be used, because X11 is not running.",nil) with: 0];
250: [self changeOutputCounterFieldWithString:
251: [NSLocalizedString(@"Output mini-view: ",nil) stringByAppendingString:
252: NSLocalizedString(@"A few commands (plot, ...) cannot be used, because X11 is not running.",nil)]];
1.1 takayama 253: myDocumentSaidTheMessageAboutX = 1;
254: }
255: }
256:
257: - (IBAction) oxEvaluate:(id) sender {
258: NSString* cmd0;
259: NSMutableString *cmd;
260: NSRange r;
261:
1.4 takayama 262: if (!task) return;
1.1 takayama 263: if (inEvaluation) {
264: NSLog(@"In evaluatioin. ");
265: [self messageDialog: NSLocalizedString(@"Evaluating...",nil) with: 0];
266: return;
267: }
268: if (notebookMode) doInsertNewInputCell=0;
269: else [[MyOutputWindowController sharedMyOutputWindowController: self] showUp];
270: ox_texmacs_level=0;
271: [self clearLines];
272:
273: [textViewIn setTypingAttributes: myDefaultTypingAttributes];
274:
275: if (notebookMode) {
276: cmd0 = [self getContentsOfInputCell];
277: [self prepareOutputCell];
278: }else if (onlySelectedArea) {
279: r = [textViewIn selectedRange];
280: // NSLog(@"r=(%d,%d)\n",r.location,r.length);
281: cmd0 = [textViewIn string];
282: if (r.length != 0) {
283: cmd0= [cmd0 substringWithRange: r];
284: }else{
285: int pos;
286: r = [cmd0 lineRangeForRange: r];
287: pos = r.location+r.length;
288: [textViewIn setSelectedRange: r]; // select the range containing the insertion point.
289: if (pos < [cmd0 length]) {
290: [textViewIn replaceCharactersInRange: NSMakeRange(pos+1,0) withString: @""];
291: }else{
292: [textViewIn replaceCharactersInRange: NSMakeRange(pos,0) withString: @"\n"];
293: }
294: cmd0 = [cmd0 substringWithRange:r ];
1.6 takayama 295: }
296: [self outputBorderLine: [NSColor magentaColor]];
297: [self outputString: cmd0];
298: if ([cmd0 length] > 0) {
299: if ([cmd0 characterAtIndex: ([cmd0 length]-1)] != 0xa) [self outputString: @"\n"];
300: }
301: [self outputBorderLine: [NSColor yellowColor]];
1.1 takayama 302: }else{
303: cmd0 = [textViewIn string];
304: MyOutputWindowController *mc;
305: mc = [MyOutputWindowController sharedMyOutputWindowController: self];
306: [mc clearOutputWindow];
307: }
308: cmd = [NSMutableString stringWithString: cmd0 ];
309:
310: [self changeInputCounterField: 1];
311: if (peer == OX_TEXMACS) [self startIndicator];
312: [self oxEvaluateString: cmd withMark: TRUE];
313: [self changeOutputCounterField: 1];
314: }
315:
316: - (IBAction) oxInterrupt:(id) sender {
317:
318: NSAlert *alert = [[NSAlert alloc] init];
319: [alert addButtonWithTitle: NSLocalizedString(@"OK",nil)];
320: [alert addButtonWithTitle: NSLocalizedString(@"Cancel",nil)];
321: [alert setMessageText: NSLocalizedString(@"Interrupt the ox server?",nil)];
322: [alert setInformativeText:NSLocalizedString(@"The OX-RFC-100 interruption protocol is used.",nil)];
323: [alert setAlertStyle:NSWarningAlertStyle];
324: if ([alert runModal] != NSAlertFirstButtonReturn) {
325: // Cancel clicked, return.
326: return;
327: }
328: [alert release];
329:
330: fprintf(stderr,"Trying to interrupt.\n");
1.4 takayama 331: if (task) [task interrupt];
1.1 takayama 332: inputCounter = outputCounter = 0;
333: [self stopIndicator];
334: [myDecoder reset];
335: }
336: -(IBAction) oxRenderOutput: (id) sender {
337: [self messageDialog: @"oxRenderOutput has not been implemented." with: 0];
338: }
339:
340: -(IBAction) oxEvaluateSelected: (id) sender {
341: // try or test something here
342: // end of try or test.
343: // fprintf(stderr,"OnlySelectedArea\n");
344: if (notebookMode && (onlySelectedArea == 0)) {
345: [self messageDialog: NSLocalizedString(@"Selection will be ignored in the notebook style.",nil) with: 0];
346: }
347: if (onlySelectedArea) onlySelectedArea = 0; else onlySelectedArea = 1;
348: }
349:
350: -(IBAction) oxEvaluateRegisteredString: (id) sender {
351: int ans;
352: NSAlert *alert = [[NSAlert alloc] init];
353: [alert addButtonWithTitle: NSLocalizedString(@"Cancel",nil)];
354: [alert addButtonWithTitle: NSLocalizedString(@"unix shell",nil)];
355: [alert addButtonWithTitle: NSLocalizedString(@"Risa/Asir",nil)];
356: [alert setMessageText: NSLocalizedString(@"Restart the computation server?",nil)];
357: //[alert setInformativeText:NSLocalizedString(@"",nil)];
358: [alert setAlertStyle:NSWarningAlertStyle];
359: ans = [alert runModal];
360: [alert release];
361: if (ans == NSAlertFirstButtonReturn) {
362: // Cancel clicked, return.
363: return ;
364: } else if (ans == NSAlertSecondButtonReturn) {
365: [self restartMyModel: BASH];
366: inputCounter = outputCounter = 0;
367: return ;
368: }else{
369: [self restartMyModel: OX_TEXMACS];
370: inputCounter = outputCounter = 0;
371: [myDecoder reset];
372: return;
373: }
374: }
375:
376: -(IBAction) checkSelectedArea: (id) sender {
377: int ans;
378: ans = [self selectIllegalCharacter];
379: if (ans) return;
380: [self selectBlockForward];
381: }
382:
383: -(int) oxEvaluateString: (NSString *) cmd withMark: (BOOL) yes {
384: NSData* cmdInData;
385: NSLog(@"Evaluating... ");
386: NSLog(@"%@",cmd);
387: // Evaluation is here.
1.4 takayama 388: if (!task) return -1;
1.1 takayama 389: cmdInData = [cmd dataUsingEncoding: NSUTF8StringEncoding];
390: @try {
391: //todo if (yes) [outboundFileHandle writeData: peerStartEvaluateMark];
392: [outboundFileHandle writeData: cmdInData];
393: if (yes) [outboundFileHandle writeData: peerEndEvaluteMark];
394: } @catch (NSException *exception) {
395: NSLog(@"oxEvalluateString Caught %@: %@", [exception name], [exception reason]);
396: [self messageDialog: NSLocalizedString(@"Error: Engine is not responding.",nil) with: 0];
397: return -1;
398: } @finally {
399: NSLog(@"writeData suceeded.\n");
400: }
401: // [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 10.0]];
402: NSLog(@"\nDone.\n");
403: return 0;
404: }
405:
406: - (void) outputString: (NSString *) amt {
407: NSRange myRange = NSMakeRange([[textViewOut textStorage] length],0);
408: if (myDebug) NSLog(@"Get in outputString\n");
409: [textViewOut replaceCharactersInRange: myRange withString: amt];
410: [textViewOut scrollRangeToVisible: NSMakeRange([[textViewOut textStorage] length],0)];
411: //[textViewOut replaceCharactersInRange: NSMakeRange(0,NSMakeRange(0,[textViewOut length])) withString: amt];
412: if (notebookMode) [self outputStringInNotebookMode: amt];
413: else {
414: MyOutputWindowController *mc;
415: mc = [MyOutputWindowController sharedMyOutputWindowController: self];
1.3 takayama 416: if (prettyPrint) [mc outputStringToOutputWindow: amt withColor: [NSColor blueColor]];
417: else [mc outputStringToOutputWindow: amt];
1.1 takayama 418: }
419: }
1.5 takayama 420: -(void)outputBorderLine: (NSColor *)color {
421: MyOutputWindowController *mc;
422: mc = [MyOutputWindowController sharedMyOutputWindowController: self];
423: [mc outputStringToOutputWindow: @"----------------------------------------\n" withColor: color];
424: }
1.1 takayama 425: - (void) outputErrorString: (NSString *) amt {
426: int oldEnd;
427: int newEnd;
428: oldEnd = [[textViewOut textStorage] length];
429: NSRange myRange = NSMakeRange(oldEnd,0);
430: [textViewOut replaceCharactersInRange: myRange withString: amt];
431: newEnd = [[textViewOut textStorage] length];
432: [textViewOut setTextColor: [NSColor orangeColor] range: NSMakeRange(oldEnd,newEnd-oldEnd)];
433: [textViewOut scrollRangeToVisible: NSMakeRange(newEnd,0)];
434: }
435:
436: - (void) printErrorMessage: (NSString *) amt {
437: MyOutputWindowController *mc;
438: if (notebookMode) [self outputErrorStringInNotebookMode: amt];
439: else {
440: mc = [MyOutputWindowController sharedMyOutputWindowController: self];
441: [mc printErrorMessageToOutputWindow: amt];
442: }
443: }
444: -(void)outputStringInNotebookMode: (NSString *)msg {
445: [self outputStringInNotebookMode: msg withColor: [NSColor blueColor]];
446: }
447: -(void)outputErrorStringInNotebookMode: (NSString *)msg {
448: [self outputStringInNotebookMode: msg withColor: [NSColor redColor]];
449: }
450: -(void)outputStringInNotebookMode: (NSString *)msg withColor: (NSColor *)color{
451: NSRange range;
452: int insertPos;
453: range=[textViewIn selectedRange];
454: insertPos = range.location+range.length;
455: range = NSMakeRange(insertPos,0);
456: [textViewIn replaceCharactersInRange: range withString: msg];
457: range = NSMakeRange(insertPos,[msg length]);
458: [textViewIn setTextColor: color range: range];
459: range=NSMakeRange(range.location+range.length,0);
460: [textViewIn scrollRangeToVisible: range];
461: [textViewIn setSelectedRange: range];
462: @synchronized(self) {
463: if (doInsertNewInputCell) {
464: if (![self getOutOfOutputCell]) [self insertInputCell];
465: doInsertNewInputCell = 0;
466: }
467: }
468: }
469:
470: -(IBAction) clearTextViewOut: (id) sender {
471: NSRange myRange = NSMakeRange(0,[[textViewOut textStorage] length]);
472: [textViewOut replaceCharactersInRange: myRange withString: @""];
473: [textViewOut replaceCharactersInRange: NSMakeRange(0,0) withString: @" \n \n \n"];
474: [textViewOut scrollRangeToVisible: NSMakeRange(0,[[textViewOut textStorage] length])];
475: }
476:
477: - (void) messageDialog: (NSString *)msg with: (int) no {
478: char s[256];
479: NSAlert *alert = [[NSAlert alloc] init];
480: sprintf(s,"%d",no);
481: [alert addButtonWithTitle: @"OK"];
482: [alert setMessageText: msg] ;
483: if (no) [alert setInformativeText: [NSString stringWithCString: (const char *) s]];
484: [alert setAlertStyle:NSWarningAlertStyle];
485: [alert runModal];
486: [alert release];
487: }
488:
489: -(void) printDocument: (id) sender {
490: int status;
491: NSAlert *alert = [[NSAlert alloc] init];
492: [alert addButtonWithTitle:NSLocalizedString(@"Cancel",nil)];
493: [alert addButtonWithTitle:NSLocalizedString(@"Print output view",nil)];
494: [alert addButtonWithTitle:NSLocalizedString(@"Print input view",nil)];
495: [alert setMessageText:NSLocalizedString(@"Which view will you print?",nil)];
496: [alert setAlertStyle:NSWarningAlertStyle];
497: status = [alert runModal];
498: switch(status) {
499: case NSAlertThirdButtonReturn:
500: [textViewIn print: sender]; break;
501: case NSAlertSecondButtonReturn:
502: [textViewOut print: sender]; break;
503: default:
504: // Cancel clicked, return.
505: return;
506: }
507: [alert release];
508: }
509:
510: -(void) showHelp: (id)sender {
511: BOOL ans;
512: NSString *path=nil;
513: //bug. temporary.
514: path = [OpenXM_HOME stringByAppendingString: @"/doc/cfep/intro-ja.html"];
515:
1.2 takayama 516: ans = [[NSWorkspace sharedWorkspace] openFile:path withApplication: @"Safari"]; //We do not use Help Viewer
1.1 takayama 517: if (ans != YES) {
518: [self messageDialog: NSLocalizedString(@"Help file is not found at cfep.app/OpenXM/doc/cfep",nil) with: 0];
519: }
520: }
521:
522: -(void) changeInputCounterField: (int) inc {
523: NSString *ss;
524: ss = [NSString stringWithFormat: NSLocalizedString(@"Input%d",nil), inputCounter];
525: [inputCounterField setStringValue: ss];
526: inputCounter += inc;
527: return;
528: }
529: -(void) changeOutputCounterField: (int) inc {
530: NSString *ss;
531: ss = [NSString stringWithFormat: NSLocalizedString(@"Out%d",nil),outputCounter];
532: [outputCounterField setStringValue: ss];
533: outputCounter += inc;
534: return;
535: }
536: -(void) changeOutputCounterFieldWithString: (NSString *) ss {
537: [outputCounterField setStringValue: ss];
538: return;
539: }
540:
541: -(void) startIndicator {
542: if (inEvaluation) return ;
543: inEvaluation = 1;
544: [myIndicator startAnimation: self];
545: }
546: -(void) stopIndicator {
547: if (inEvaluation == 0) return ;
548: inEvaluation = 0;
549: [myIndicator stopAnimation: self];
550: }
551:
552:
553: int debugInbound = 0;
554: - (void)readInboundData:(NSNotification*)aNotification
555: {
556: static int state=0;
557: static int u0 = 0;
558: static int u1 = 0;
559: static int u2 = 0;
560: int n,i,j,k;
561: unsigned char *d;
562: unsigned char *d2;
563: int c;
564: NSMutableString* inboundString;
565: NSData* data;
566: NSMutableData* data2;
567: NSString *act;
568: int channel;
569: @synchronized (self) {
570: if (debugInbound) NSLog(@"Reading inboudData\n");
571: data=[ inboundFileHandle availableData ];
572: n = [data length]; d = (unsigned char *)[data bytes];
573: if (debugInbound) NSLog(@"n=%d\n",n);
574: // if (n < 30) { for (k=0; k<n; k++) printf("%2x ",d[k]); printf("\n"); }
575: if (n == 0) { NSLog(@"Broken pipe?\n"); [self messageDialog: @"Error: Engine is not responding." with: 0]; return ; }
576: data2 = [NSMutableData dataWithCapacity: (n+4)];
577: d2 = (unsigned char *)[data2 mutableBytes];
578: i = 0; d2[i] = 0;
579: for (j = 0; j< n; j++) {
580: c = d[j];
581: if (c == END_OF_EVALUATION_OF_OX_TEXMACS) {
582: [self stopIndicator];
583: ox_texmacs_level--;
584: if (ox_texmacs_level <= 0) doInsertNewInputCell = 1;
585: } else if (c == START_OF_RESULT_OF_OX_TEXMACS) {
586: ox_texmacs_level++;
587: }
588: switch(state) {
589: case 1:
590: u1 = d[j];
591: d2[i] = u0; i++; d2[i] = u1; i++; d2[i] = 0;
592: state = 0; break;
593: case 2:
594: u1 = d[j]; state = 3; break;
595: case 3:
596: u2 = d[j];
597: d2[i] = u0; i++; d2[i] = u1; i++; d2[i] = u2; i++ ; d2[i] = 0;
598: state = 0; break;
599: case 4: // MYDECODER
600: u1 = d[j]; state = 5; break;
601: case 5:
602: u2 = d[j];
603: c = ((u0 & 0x3) << 6) | (((u1 & 0x7) << 3) & 0x38) | (u2 & 0x7);
604: // NSLog(@"|%2x| ",c); // send it to myDecoder
605: act = [myDecoder myDecoder: c from: self];
606: if (act != nil) {
607: if (debugMyTunnel) [self outputErrorString: act]; // for debug.
608: channel = [myDecoder getChannel];
609: if (channel == 0) [self errorActionFor: act];
1.2 takayama 610: // cf. MyDecode.h for the list of channel numbers.
1.1 takayama 611: else if (channel == 1) [self openGLActionFor: act];
612: else if (channel == 2) [self openGLInitActionFor: act];
1.2 takayama 613: else if (channel == 10) [self pngActionFor: act];
1.1 takayama 614: }
615: state = 0; break;
616: default:
617: c=d[j];
618: if ((c >> 5) == UTF8_2) { u0=c ; state=1; }
619: else if ((c >> 4) == UTF8_3) { u0 =c ; state = 2; }
620: else if ((c >> 2) == MYDECODER) { u0=c; state = 4; }
621: else if ( c & 0x80) {
622: state = 0; NSLog(@"err|%2x| ",c);
623: }else {
624: if (c > 5) {
625: d2[i] = c; i++; d2[i] = 0; state = 0;
626: }
627: }
628: }
629: }
630: }
631: if (i) {
632: inboundString = [NSString stringWithCString: d2 encoding: NSUTF8StringEncoding];
633: [self outputString: inboundString]; // do this out of the synchronized session.
634: }
635:
636: if (n) [[aNotification object] waitForDataInBackgroundAndNotify];
637: }
638:
639:
640: - (void)readErrData:(NSNotification*)aNotification
641: {
642: int n,i,j;
643: #define MD_SIZE 5000
644: unsigned char *d;
645: int c;
646: NSMutableString* inboundString;
647: NSData* inboundData ;
648: @synchronized (self) {
649: inboundString = [NSMutableString stringWithCapacity: (MD_SIZE+2)];
650:
651: // NSLog(@"(err) Reading inboudData\n");
652: inboundData=[ errFileHandle availableData ];
653: n = [inboundData length]; d = (unsigned char *)[inboundData bytes];
654: i = 0;
655: while (i < n ) {
656: for (j = 0; j<MD_SIZE ; j++ ) {
657: c = d[i]; // putchar(c);
658: [inboundString appendString: [NSString stringWithFormat: @"%c", (c & 0x7f)] ];
659: i++; if (i >= n) { j++; break;}
660: }
661: // NSLog( [NSString stringWithFormat: @"i=%d, j=%d\n", i, j] );
662: j++;
663: // NSLog(@"%@", inboundString );
664: [self outputErrorString: inboundString];
665: inboundString = [NSMutableString stringWithCapacity: (MD_SIZE+2)] ;
666: }
667: }
668: if (n) [[aNotification object] waitForDataInBackgroundAndNotify];
669:
670: }
671:
672: -(int) specialCharacterInNotebookMode: (int) c {
673: if (!notebookMode) return 0;
674: if (c == BEGIN_INPUT_CELL) return 1;
675: else if (c==BEGIN_OUTPUT_CELL) return 1;
676: else if (c==END_INPUT_CELL) return 1;
677: else if (c==END_OUTPUT_CELL) return 1;
678: return 0;
679: }
680: -(int) selectIllegalCharacter {
681: NSRange r;
682: NSString *in;
683: int i, n;
684: int state,offset;
685: int c,c2;
686: // 1: in /*
687: // 2: in //
688: // 3: in "
689: // 4: in '
690: in = [textViewIn string];
691: r = [textViewIn selectedRange];
692: //NSLog(@"%d, %d\n",r.location, r.length);
693: if (r.length < 1) {
694: offset = 0;
695: n = [in length];
696: }else{
697: offset = r.location;
698: n = offset + r.length;
699: }
700: state = 0;
701: for (i=offset; i<n; i++) {
702: c = [in characterAtIndex: i]; // NSLog(@"|%04x| ",c);
703: if (i != n-1) c2 = [in characterAtIndex: (i+1)];
704: else c2 = 0;
705: switch (state) {
706: case 0:
707: if ((c == 0x1b)) {
708: [textViewIn setSelectedRange: NSMakeRange(i,1)];
709: [self outputErrorString:
710: NSLocalizedString(@"Error: Illegal control character.\n",nil)];
711: return 1;
712: }
713: if ((c > 0x7e) && (![self specialCharacterInNotebookMode: c])) {
714: [textViewIn setSelectedRange: NSMakeRange(i,1)];
715: [self outputErrorString:
716: NSLocalizedString(@"Error: Program part must be written only by ascii characters.\n",nil)];
717: return 1;
718: }
719: if (((c == '/') && (c2 == '*')) || (notebookMode && (c == BEGIN_OUTPUT_CELL))) {
720: i++; state = 1;
721: }else if ((c == '/') && (c2 == '/')) {
722: i++; state = 2;
723: }else if (c == '"') {
724: state = 3;
725: }else if (c == '\'') {
726: state = 4;
727: }else state=0;
728: break;
729: case 1:
730: if (((c == '*') && (c2 == '/')) || (notebookMode && (c2 == END_OUTPUT_CELL))) {
731: i++; state = 0;
732: }
733: break;
734: case 2:
735: if (c == '\n') state = 0;
736: break;
737: case 3:
738: if (c == '"') state = 0;
739: else if (c == '\\') {
740: i++; //BUG. skip only one letter.
741: }
742: break;
743: case 4:
744: if (c == '\'') state = 0;
745: else if (c == '\\') {
746: i++; //BUG. skip only one letter.
747: }
748: break;
749: }
750: }
751: // [self outputErrorString: @"No illegal character.\n"];
752: return 0;
753: }
754:
755: -(NSRange) selectBlockForward {
756: NSRange r;
757: NSRange ans;
758: NSString *in;
759: int i, n;
760: int first, last,offset, state;
761: int c,c2;
762: static int prevStart = -1;
763:
764: first = last = 0;
765: ans = NSMakeRange(0,0);
766:
767: // 1: in /*
768: // 2: in //
769: // 3: in "
770: // 4: in '
771: in = [textViewIn string];
772: r = [textViewIn selectedRange];
773: if (r.length < 1) {
774: offset = 0;
775: } else {
776: offset = r.location;
777: }
778: if (offset == prevStart) {
779: offset = offset+1;
780: }
781: n = [in length];
782: if (offset >= n) offset = 0;
783: state = 0;
784: for (i=offset; i<n; i++) {
785: c = [in characterAtIndex: i];
786: if (i != n-1) c2 = [in characterAtIndex: (i+1)];
787: else c2 = 0;
788: switch (state) {
789: case 0:
790: if (c == '{') {
791: ans=[self selectBlockForwardFrom: i with: c and: '}'];
792: if (prevStart != ans.location) { prevStart = ans.location; }
793: return ans;
794: }else if (c == '(') {
795: ans=[self selectBlockForwardFrom: i with: c and: ')'];
796: if (prevStart != ans.location) { prevStart = ans.location; }
797: return ans;
798: }else if (c == '[') {
799: ans=[self selectBlockForwardFrom: i with: c and: ']'];
800: if (prevStart != ans.location) { prevStart = ans.location; }
801: return ans;
802: }
803: if ((c == '/') && (c2 == '*')) {
804: i++; state = 1;
805: }else if ((c == '/') && (c2 == '/')) {
806: i++; state = 2;
807: }else if (c == '"') {
808: state = 3;
809: }else if (c == '\'') {
810: state = 4;
811: }else state=0;
812: break;
813: case 1:
814: if ((c == '*') && (c2 == '/')) {
815: i++; state = 0;
816: }
817: break;
818: case 2:
819: if (c == '\n') state = 0;
820: break;
821: case 3:
822: if (c == '"') state = 0;
823: else if (c == '\\') {
824: i++; //BUG. skip only one letter.
825: }
826: break;
827: case 4:
828: if (c == '\'') state = 0;
829: else if (c == '\\') {
830: i++; //BUG. skip only one letter.
831: }
832: break;
833: }
834: }
835: return ans;
836: }
837: -(NSRange) selectBlockForwardFrom: (int) offset with: (int) first and: (int) last {
838: NSRange r;
839: NSRange ans;
840: NSString *in;
841: int i, n;
842: int state;
843: int c,c2;
844: int level;
845: int startpos;
846:
847: level = 0;
848: ans = NSMakeRange(0,0);
849:
850: // 1: in /*
851: // 2: in //
852: // 3: in "
853: // 4: in '
854: in = [textViewIn string];
855: r = [textViewIn selectedRange];
856: n = [in length];
857: state = 0;
858: for (i=offset; i<n; i++) {
859: c = [in characterAtIndex: i];
860: if (i != n-1) c2 = [in characterAtIndex: (i+1)];
861: else c2 = 0;
862: switch (state) {
863: case 0:
864: if (level == 0) {
865: if (c == first) {
866: level = 1; startpos = i;
867: }
868: } else if (level > 0) {
869: if (c == first) level++;
870: else if (c == last) level--;
871: else ;
872: if (level == 0) {
873: ans = NSMakeRange(startpos, i+1-startpos);
874: [textViewIn setSelectedRange: ans];
875: [textViewIn scrollRangeToVisible: NSMakeRange(startpos,0)];
876: return ans;
877: }
878: }
879:
880: if ((c == '/') && (c2 == '*')) {
881: i++; state = 1;
882: }else if ((c == '/') && (c2 == '/')) {
883: i++; state = 2;
884: }else if (c == '"') {
885: state = 3;
886: }else if (c == '\'') {
887: state = 4;
888: }else state=0;
889: break;
890: case 1:
891: if ((c == '*') && (c2 == '/')) {
892: i++; state = 0;
893: }
894: break;
895: case 2:
896: if (c == '\n') state = 0;
897: break;
898: case 3:
899: if (c == '"') state = 0;
900: else if (c == '\\') {
901: i++; //BUG. skip only one letter.
902: }
903: break;
904: case 4:
905: if (c == '\'') state = 0;
906: else if (c == '\\') {
907: i++; //BUG. skip only one letter.
908: }
909: break;
910: }
911: }
912: if (level > 0) {
913: [self outputErrorString: NSLocalizedString(@"Error: No right parenthesis.\n",nil)] ;
914: [textViewIn setSelectedRange: NSMakeRange(startpos,n-startpos)];
915: ans = NSMakeRange(startpos,-1);
916: return ans;
917: }
918: return ans;
919: }
920:
921: -(void) errorActionFor: (NSString *)cmd
922: {
923: NSArray *a;
924: NSRange r;
925: static NSRange r2;
926: static NSRange r3;
927: static int r2IsSet;
928: static int r3IsSet;
929: NSString *s;
930: int line,i, currentLine;
931: // NSLog(@"cmd=%@\n",cmd);
932: if ([cmd hasPrefix: @"Begin"] == YES) {
933: r3IsSet = 0; r2IsSet = 0;
934: }else if ([cmd hasPrefix: @"End"] == YES) {
935: if (r2IsSet) {
936: [textViewIn setSelectedRange: r2];
937: [textViewIn scrollRangeToVisible: r2];
938: r2IsSet = 0;
939: }
940: if (r3IsSet) { //gotoLine, xyz is stronger than findAndSelect.
941: [textViewIn setSelectedRange: r3];
942: [textViewIn scrollRangeToVisible: r3];
943: r3IsSet = 0;
944: }
945: }else if ([cmd hasPrefix: @"findAndSelect"] == YES) {
946: a = [cmd componentsSeparatedByString: @", "];
947: if ([a count] > 1) {
948: a = [[a objectAtIndex: 1] componentsSeparatedByString: @"\n"];
949: s = [a objectAtIndex: 0];
950: r2 = [[textViewIn string] rangeOfString: s];
951: r2IsSet = 1;
952: // selection will be done in End.
953: [self printErrorMessage: [NSLocalizedString(@"Error in executing ",nil) stringByAppendingString: s]];
954: [self printErrorMessage: @"\n"];
955: }
956: }else if ([cmd hasPrefix: @"findAndShow"] == YES) {
957: a = [cmd componentsSeparatedByString: @", "];
958: if ([a count] > 1) {
959: a = [[a objectAtIndex: 1] componentsSeparatedByString: @"\n"];
960: s = [a objectAtIndex: 0];
961: [self printErrorMessage: [NSLocalizedString(@"Error in executing ",nil) stringByAppendingString: s]];
962: [self printErrorMessage: @"\n"];
963: }
964: }else if ([cmd hasPrefix: @"printErrorMessage"] == YES) {
965: a = [cmd componentsSeparatedByString: @"ErrorMessage, "];
966: if ([a count] > 1) {
967: s = [a objectAtIndex: 1];
968: [self printErrorMessage: [NSLocalizedString(@"Error: ",nil) stringByAppendingString: s]];
969: [self printErrorMessage: @"\n"];
970: }
971: }else if ([cmd hasPrefix: @"gotoLine"] == YES) {
972: a = [cmd componentsSeparatedByString: @"Line, "];
973: if ([a count] > 1) {
974: s = [a objectAtIndex: 1];
975: [self printErrorMessage: [NSLocalizedString(@"Error at ",nil) stringByAppendingString: s]];
976: [self printErrorMessage: @"\n"];
977: line = [s intValue];
978: [self addLine: line];
979: // move the selection to the line.
980: i = [self gotoLine: line];
981: if (i >= 0) {
982: r3 = NSMakeRange(i,0); // NSLog(@"Goto the location=%d\n",i);
983: r3IsSet = 1;
984: }
985: }
986: }
987: }
988:
989: -(void) clearLines {
990: [errorLines removeAllObjects];
991: [self nextLine: -1];
992: }
993: -(void) addLine: (int) n {
994: [errorLines addObject: [NSNumber numberWithInt: n]];
995: }
996: -(int) nextLine: (int) n {
997: static int p = 0;
998: int v;
999: if (n < 0) { p = 0; return -1; }
1000: if (p < [errorLines count]) ; else { p = 0; return -1;}
1001: v = [[errorLines objectAtIndex: p] intValue];
1002: p++;
1003: return v;
1004: }
1005: -(int) gotoLine: (int) line {
1006: NSString *s;
1007: NSRange r;
1008: NSRange r3;
1009: int currentLine,i;
1.3 takayama 1010: [self outputErrorString: NSLocalizedString(@"Move to the line ",nil)];
1011: [self outputErrorString: [NSString stringWithFormat: @"%d\n",line]];
1.1 takayama 1012: // move the selection to the line line.
1013: s = [textViewIn string];
1014: if (onlySelectedArea || notebookMode) r = [textViewIn selectedRange];
1015: else r = NSMakeRange(0,[s length]);
1016: // NSLog(@"r.location=%d",r.location);
1017: currentLine = 1;
1018: for (i=r.location; i< r.location+r.length; i++) {
1019: if (currentLine == line) {
1020: r3 = NSMakeRange(i,0); // NSLog(@"Goto the location=%d\n",i);
1021: [textViewIn setSelectedRange: r3 ];
1022: [textViewIn scrollRangeToVisible: r3];
1023: return i; // set r3IsSet
1024: break;
1025: }
1026: if ([s characterAtIndex: i] == '\n') ++currentLine;
1027: }
1028: return -1;
1029: }
1030: -(int) gotoNextError: (id) sender{
1031: int n;
1.3 takayama 1032: if (onlySelectedArea || notebookMode)
1033: [self outputErrorString: NSLocalizedString(@"The next error action will not work properly in this mode.\n",nil)];
1.1 takayama 1034: n = [self nextLine: 0];
1035: if (n >= 0) { [self gotoLine: n]; return n;}
1036: else return -1;
1037: }
1038:
1039: /* act= 0;[glRectf,-0.5, ...] */
1040: -(int) openGLActionFor: (NSString *)act {
1041: NSArray *a;
1042: int gid;
1043: a=[act componentsSeparatedByString: @";"];
1044: if ([a count] < 2) {
1045: [self printErrorMessage: @"Invalid format in openGLActionFor. gid and command must be separated by ;\n"];
1046: return -1;
1047: }
1048: gid = [[a objectAtIndex: 0] intValue];
1.3 takayama 1049: if ([[a objectAtIndex: 1] hasPrefix: @"meta"]) {[self openGLMeta: [a objectAtIndex: 1] to: gid]; return; }
1.1 takayama 1050: [MyOpenGLController addOglComm: [a objectAtIndex: 1] to: gid from: self];
1051: return 0;
1052: }
1053: -(int) openGLInitActionFor: (NSString *) act {
1054: NSArray *a;
1055: int gid;
1056: a=[act componentsSeparatedByString: @";"];
1057: if ([a count] < 2) {
1058: [self printErrorMessage: @"Invalid format in openGLInitActionFor. gid and command must be separated by ;\n"];
1059: return -1;
1060: }
1061: gid = [[a objectAtIndex: 0] intValue];
1062: [MyOpenGLController addOglInitComm: [a objectAtIndex: 1] to: gid from: self];
1063: return 0;
1064: }
1.3 takayama 1065: -(void)openGLMeta: (NSString *) cmd to: (int) gid{
1066: MyOpenGLController *oglc;
1067: oglc = [MyOpenGLController getOglWindow: gid];
1.5 takayama 1068: if (!oglc) {[self printErrorMessage:
1069: [NSString stringWithFormat: @"Invalid gid %d in openGLMeta command %@\n",gid,cmd]]; return; }
1.3 takayama 1070: if ([cmd hasPrefix: @"meta_showListOfOglComm"]) {
1071: [self showListOfOglComm: gid]; return ;
1.4 takayama 1072: }else if ([cmd hasPrefix: @"meta_removeAllInit"]) { // longer command must come first, because we use prefix.
1073: [oglc removeAllOfOglInitComm];
1074: }else if ([cmd hasPrefix: @"meta_removeLastInit"]) {
1075: [oglc removeLastOfOglInitComm];
1.3 takayama 1076: }else if ([cmd hasPrefix: @"meta_removeAll"]) {
1077: [oglc removeAllOfOglComm];
1078: }else if ([cmd hasPrefix: @"meta_removeLast"]) {
1079: [oglc removeLastOfOglComm];
1080: }else{
1.5 takayama 1081: [self printErrorMessage: [NSString stringWithFormat: @"Unknown OpenGL meta command %@\n",cmd]];
1.3 takayama 1082: }
1083: }
1084: -(void) showListOfOglComm: (int) gid {
1085: MyDocument *md;
1086: MyOpenGLController *oglc;
1087: NSMutableArray *comm;
1088: int i,n;
1089: md = self;
1090: oglc = [MyOpenGLController getOglWindow: gid];
1091: if (!oglc) {[self outputErrorString: @"Invalid gid in showListOfOglComm\n"]; return; }
1092: comm = [oglc getListOfOglInitComm];
1093: n = [comm count];
1094: [md outputString: NSLocalizedString(@"OpenGL init commands\n",nil)];
1095: for (i=0; i<n; i++) {
1096: [md outputString: [NSString stringWithFormat: @"%04d: ",i]];
1097: [md outputString: [[comm objectAtIndex: i] toString]];
1098: [md outputString: @"\n"];
1099: }
1100: comm = [oglc getListOfOglComm];
1101: n = [comm count];
1102: [md outputString: NSLocalizedString(@"OpenGL redraw commands\n",nil)];
1103: for (i=0; i<n; i++) {
1104: [md outputString: [NSString stringWithFormat: @"%04d: ",i]];
1105: [md outputString: [[comm objectAtIndex: i] toString]];
1106: [md outputString: @"\n"];
1107: }
1108: }
1109:
1.1 takayama 1110:
1.2 takayama 1111: -(void) pngActionFor: (NSString *)act {
1112: NSArray *a;
1113: id typesetExpression;
1114: MyOutputWindowController *mowc;
1115: NSString *path;
1116: int n;
1117: a=[act componentsSeparatedByString: @","];
1118: n = [a count];
1119: if (n < 1) {
1120: [self printErrorMessage: @"Invalid format in pngActionFor: \n"];
1121: return;
1122: }
1123: // NSLog(@"%@",a);
1124: if ([[a objectAtIndex: 0] hasPrefix: @"notAvailable"]) {
1125: [self messageDialog:
1.7 ! takayama 1126: NSLocalizedString(@"Typeset the output by TeX is not available. latex and dvipng must be installed.",nil) with: 0];
1.2 takayama 1127: prettyPrint = 1; [self setPrettyPrint: nil];
1128: return;
1129: } else if ([[a objectAtIndex: 0] compare: @"showFile"] == NSOrderedSame) {
1130: if (n < 2) [self printErrorMessage: @"showFile,filename filename is missing.\n"];
1131: path = [MyUtil pruneThings: [a objectAtIndex: 1]]; // for buggy componentsSeparatedByString
1132: typesetExpression = [MyUtil attributedStringWithPath: path];
1133: if (typesetExpression) {
1134: if (notebookMode) [textViewIn insertText: typesetExpression];
1135: else {
1136: mowc = [MyOutputWindowController sharedMyOutputWindowController: self];
1137: [mowc insertText: typesetExpression];
1138: }
1139: }
1140: return;
1141: } else {
1142: NSLog(@"pngActionFor: %@\n",act);
1143: [self printErrorMessage: @"Unknown command for pngActionFor:\n"];
1144: }
1145: }
1146:
1.1 takayama 1147: -(void) setBasicStyle: (id) sender {
1148: notebookMode = 0;
1149: [self updateInterfaceStyleMenu];
1150: }
1151: -(void) setNotebookStyle: (id) sender {
1152: notebookMode = 1;
1153: [self updateInterfaceStyleMenu];
1154: [self insertInputCell];
1155: }
1156: -(void) updateInterfaceStyleMenu {
1157: if (!menuItemNotebookMode) return;
1158: if (!menuItemBasicMode) return;
1159: if (notebookMode) {
1160: [menuItemNotebookMode setState: NSOnState];
1161: [menuItemBasicMode setState: NSOffState];
1162: }else {
1163: [menuItemNotebookMode setState: NSOffState];
1164: [menuItemBasicMode setState: NSOnState];
1165: }
1166: }
1167: -(void) setEngineRisaAsir: (id) sender {
1168: oxEngine = 0;
1169: [self updateSelectEngineMenu];
1170: [self oxEvaluateString: @"!asir;" withMark: TRUE];
1171: }
1172: -(void) setEngineKanSm1: (id) sender {
1173: oxEngine = 1;
1174: [self updateSelectEngineMenu];
1175: [self oxEvaluateString: @"!sm1;" withMark: TRUE];
1176: }
1.3 takayama 1177: // BUG: update* must be called when the focus is changed to "setState:"
1.1 takayama 1178: -(void) updateSelectEngineMenu {
1179: if (!menuItemRisaAsir) return;
1180: if (!menuItemKanSm1) return;
1181: if (oxEngine == 0) {
1182: [menuItemRisaAsir setState: NSOnState];
1183: [menuItemKanSm1 setState: NSOffState];
1184: }else if (oxEngine == 1) {
1185: [menuItemRisaAsir setState: NSOffState];
1186: [menuItemKanSm1 setState: NSOnState];
1187: }
1188: }
1189: -(void) setDebugMyTunnel: (id) sender {
1190: if (debugMyTunnel) {
1191: debugMyTunnel = 0;
1192: if (menuItemOutputDebugMessages) [menuItemOutputDebugMessages setState: NSOffState];
1193: } else {
1194: debugMyTunnel = 1;
1195: if (menuItemOutputDebugMessages) [menuItemOutputDebugMessages setState: NSOnState];
1196: }
1197: [MyUtil setDebugMyUtil];
1198: }
1.3 takayama 1199:
1200: //BUG: [self setPrettyPrint: nil] or update must be called when focus is changed to "setState:"
1.2 takayama 1201: -(void) setPrettyPrint: (id) sender {
1202: if (prettyPrint) {
1203: prettyPrint = 0;
1204: [self oxEvaluateString: @"!verbatim;" withMark: TRUE];
1205: if (menuItemPrettyPrint) [menuItemPrettyPrint setState: NSOffState];
1206: } else {
1207: prettyPrint = 1;
1208: if (!asir_contrib) [self loadAsirContrib: nil];
1209: [self oxEvaluateString: @"!cfep_png;" withMark: TRUE];
1210: if (menuItemPrettyPrint) [menuItemPrettyPrint setState: NSOnState];
1211: }
1212: }
1.4 takayama 1213: -(void) setNoEngine: (id) sender {
1214: if (NoEngine) {
1215: NoEngine = 0;
1216: if (menuItemNoEngine) [menuItemNoEngine setState: NSOffState];
1217: } else {
1218: NoEngine = 1;
1219: if (menuItemNoEngine) [menuItemNoEngine setState: NSOnState];
1220: }
1221: }
1.2 takayama 1222:
1223: -(void) loadAsirContrib: (id) sender {
1224: NSString *com;
1225: if (inEvaluation) {
1226: [self messageDialog: NSLocalizedString(@"Evaluating...",nil) with: 0];
1227: return;
1228: }
1229: asir_contrib = 1;
1230: com = [@"load(\"" stringByAppendingString: OpenXM_HOME];
1231: com = [com stringByAppendingString: @"/rc/asirrc\")$"];
1232: if (notebookMode) { doInsertNewInputCell=0; [self getContentsOfInputCell]; [self prepareOutputCell];}
1233: [self oxEvaluateString: com withMark: TRUE];
1234: }
1.1 takayama 1235: -(void) mytest: (id) sender {
1.2 takayama 1236: // Add any code here for testing.
1237: id typesetExpression;
1238: typesetExpression = [MyUtil attributedStringWithPath: @"/Users/nobuki/OpenXM_tmp/1/work1.png"];
1239: if (typesetExpression) [textViewIn insertText: typesetExpression];
1240: else NSLog(@"typesetExpression is nil.\n");
1241: }
1242:
1243: -(NSMenuItem *) menuItemLoadLibrary: (int) oxengine {
1244: NSMenuItem *menuItemAsirContrib;
1245: NSMenuItem *menuItemCohom;
1246: NSMenu *submenuLoadLibrary = [[[NSMenu alloc] init] autorelease];
1247: switch(oxengine) {
1248: case 0: /* asir */
1249: menuItemAsirContrib = [[[NSMenuItem alloc] init] autorelease];
1250: [menuItemAsirContrib setTitle: NSLocalizedString(@"Load asir-contrib",nil)];
1251: [menuItemAsirContrib setAction: @selector(loadAsirContrib:)];
1252: [menuItemAsirContrib setTarget: [[NSApp mainWindow] document]];
1253: [submenuLoadLibrary addItem: menuItemAsirContrib];
1254: break;
1255: case 1: /* sm1 */
1256: menuItemCohom = [[[NSMenuItem alloc] init] autorelease];
1257: [menuItemCohom setTitle: NSLocalizedString(@"Load cohom.sm1",nil)];
1258: [menuItemCohom setAction: @selector(loadCohom:)];
1259: [menuItemCohom setTarget: [[NSApp mainWindow] document]];
1260: [submenuLoadLibrary addItem: menuItemCohom];
1261: break;
1262: default:
1263: break;
1264: }
1265:
1266: NSMenuItem *menuItemLoadLibrary = [[[NSMenuItem alloc] init] autorelease];
1267: [menuItemLoadLibrary setTitle: NSLocalizedString(@"Load library",nil)];
1268: [menuItemLoadLibrary setSubmenu: submenuLoadLibrary];
1269: return menuItemLoadLibrary;
1.1 takayama 1270: }
1271: -(void) addMenuExec {
1272: static int done=0;
1273: NSMenu *menuItem;
1274: NSMenu *menuExec;
1275: NSMenuItem *menuItemEvaluate;
1276: NSMenuItem *menuItemInterrupt;
1277: NSMenuItem *menuItemInterfaceStyle;
1278: NSMenuItem *menuItemSelectEngine;
1279: NSMenuItem *menuItemGotoNextError;
1280: NSMenuItem *menuItemForTest;
1.2 takayama 1281: NSMenuItem *menuItemLoadLibrary;
1.1 takayama 1282: if (done) return;
1283: done = 1;
1284: // oxEvalute
1285: menuExec = [[[NSMenu alloc] init] autorelease];
1286: [menuExec setTitle: NSLocalizedString(@"Execution",nil)];
1287: menuItemEvaluate = [[[NSMenuItem alloc] init] autorelease];
1288: [menuItemEvaluate setTitle: NSLocalizedString(@"Evaluate",nil)];
1289: [menuItemEvaluate setAction: @selector(oxEvaluate:)];
1290: [menuItemEvaluate setTarget: [[NSApp mainWindow] document]];
1291: [menuItemEvaluate setKeyEquivalentModifierMask: NSCommandKeyMask];
1292: [menuItemEvaluate setKeyEquivalent: @"\n"];
1293: [menuExec addItem: menuItemEvaluate];
1294: // oxInterrupt
1295: menuItemInterrupt = [[[NSMenuItem alloc] init] autorelease];
1296: [menuItemInterrupt setTitle: NSLocalizedString(@"Interrupt",nil)];
1297: [menuItemInterrupt setAction: @selector(oxInterrupt:)];
1298: [menuItemInterrupt setTarget: [[NSApp mainWindow] document]]; // do not use self.
1299: [menuExec addItem: menuItemInterrupt];
1300:
1301: // gotoNextError
1302: menuItemGotoNextError = [[[NSMenuItem alloc] init] autorelease];
1303: [menuItemGotoNextError setTitle: NSLocalizedString(@"Next error line",nil)];
1304: [menuItemGotoNextError setAction: @selector(gotoNextError:)];
1305: [menuItemGotoNextError setTarget: [[NSApp mainWindow] document]];
1306: [menuExec addItem: menuItemGotoNextError];
1307:
1.2 takayama 1308: // pretty print
1.3 takayama 1309: menuItemPrettyPrint = [[[NSMenuItem alloc] init] autorelease]; [menuItemPrettyPrint retain]; // it is the static variable.
1.2 takayama 1310: [menuItemPrettyPrint setTitle: NSLocalizedString(@"Typeset the output by TeX",nil)];
1311: [menuItemPrettyPrint setAction: @selector(setPrettyPrint:)];
1312: [menuItemPrettyPrint setTarget: [[NSApp mainWindow] document]];
1313: [menuExec addItem: menuItemPrettyPrint];
1314:
1315: // loadLibrary
1316: [menuExec addItem: [self menuItemLoadLibrary: oxEngine]]; //bug. dynamic change.
1317:
1.1 takayama 1318: // interface style
1319: NSMenu *submenuInterfaceItem = [[[NSMenu alloc] init] autorelease];
1320: // basic-like
1321: NSMenuItem *menuItemBasicLike = [[[NSMenuItem alloc] init] autorelease];
1322: [menuItemBasicLike setTitle: NSLocalizedString(@"BASIC-like",nil)];
1323: [menuItemBasicLike setAction: @selector(setBasicStyle:)];
1324: [menuItemBasicLike setTarget: [[NSApp mainWindow] document]];
1.3 takayama 1325: menuItemBasicMode = menuItemBasicLike; [menuItemBasicMode retain];
1.1 takayama 1326: [submenuInterfaceItem addItem: menuItemBasicLike];
1327: // notebook-like
1328: NSMenuItem *menuItemNotebookLike = [[[NSMenuItem alloc] init] autorelease];
1329: [menuItemNotebookLike setTitle: NSLocalizedString(@"Notebook-like",nil)];
1330: [menuItemNotebookLike setAction: @selector(setNotebookStyle:)];
1331: [menuItemNotebookLike setTarget: [[NSApp mainWindow] document]];
1.3 takayama 1332: menuItemNotebookMode = menuItemNotebookLike; [menuItemNotebookMode retain];
1.1 takayama 1333: [submenuInterfaceItem addItem: menuItemNotebookLike];
1334:
1335: menuItemInterfaceStyle = [[[NSMenuItem alloc] init] autorelease];
1336: [menuItemInterfaceStyle setTitle: NSLocalizedString(@"Interface style",nil)];
1337: [menuItemInterfaceStyle setSubmenu: submenuInterfaceItem];
1338: [menuExec addItem: menuItemInterfaceStyle];
1339: [self updateInterfaceStyleMenu];
1340:
1341: // select engine
1342: NSMenu *submenuSelectEngineItem = [[[NSMenu alloc] init] autorelease];
1343: // asir
1.3 takayama 1344: menuItemRisaAsir = [[[NSMenuItem alloc] init] autorelease]; [menuItemRisaAsir retain];
1.1 takayama 1345: [menuItemRisaAsir setTitle: NSLocalizedString(@"Risa/Asir",nil)];
1346: [menuItemRisaAsir setAction: @selector(setEngineRisaAsir:)];
1347: [menuItemRisaAsir setTarget: [[NSApp mainWindow] document]];
1348: [submenuSelectEngineItem addItem: menuItemRisaAsir];
1349: // notebook-like
1.3 takayama 1350: menuItemKanSm1 = [[[NSMenuItem alloc] init] autorelease]; [menuItemKanSm1 retain];
1.1 takayama 1351: [menuItemKanSm1 setTitle: NSLocalizedString(@"Kan/sm1",nil)];
1352: [menuItemKanSm1 setAction: @selector(setEngineKanSm1:)];
1353: [menuItemKanSm1 setTarget: [[NSApp mainWindow] document]];
1354: [submenuSelectEngineItem addItem: menuItemKanSm1];
1355:
1356: menuItemSelectEngine = [[[NSMenuItem alloc] init] autorelease];
1357: [menuItemSelectEngine setTitle: NSLocalizedString(@"Select engine",nil)];
1358: [menuItemSelectEngine setSubmenu: submenuSelectEngineItem];
1359: [menuExec addItem: menuItemSelectEngine];
1360: [self updateSelectEngineMenu];
1361:
1.4 takayama 1362: // outputDebugMessage
1363: menuItemOutputDebugMessages = [[[NSMenuItem alloc] init] autorelease]; [menuItemOutputDebugMessages retain];
1364: [menuItemOutputDebugMessages setTitle: NSLocalizedString(@"Output debug messages",nil)];
1365: [menuItemOutputDebugMessages setAction: @selector(setDebugMyTunnel:)];
1366: [menuItemOutputDebugMessages setTarget: [[NSApp mainWindow] document]];
1367: [menuExec addItem: menuItemOutputDebugMessages];
1368:
1369: // NoEngine
1370: menuItemNoEngine = [[[NSMenuItem alloc] init] autorelease]; [menuItemNoEngine retain]; // it is the static variable.
1371: [menuItemNoEngine setTitle: NSLocalizedString(@"Do not start engine at startup",nil)];
1372: [menuItemNoEngine setAction: @selector(setNoEngine:)];
1373: [menuItemNoEngine setTarget: [[NSApp mainWindow] document]];
1374: [menuExec addItem: menuItemNoEngine];
1.1 takayama 1375:
1376: // test
1377: menuItemForTest = [[[NSMenuItem alloc] init] autorelease];
1378: [menuItemForTest setTitle: NSLocalizedString(@"For test",nil)];
1379: [menuItemForTest setAction: @selector(mytest:)];
1380: [menuItemForTest setTarget: [[NSApp mainWindow] document]];
1381: [menuExec addItem: menuItemForTest];
1382:
1383: menuItem = [[[NSMenuItem alloc] init] autorelease];
1384: [[NSApp mainMenu] insertItem: menuItem atIndex: 4];
1385: [menuItem setSubmenu: menuExec];
1386: }
1387:
1388: -(void) insertInputCell {
1389: NSRange r;
1390: NSString *ic;
1391: unichar uu[2];
1392: uu[0] = BEGIN_INPUT_CELL; uu[1] = END_INPUT_CELL;
1393: r = [textViewIn selectedRange]; r.length=0;
1394: ic = [NSString stringWithCharacters: uu length: 2];
1395: // NSLog(@"insertInputCell: r.location=%d, r.length=%d, %@\n",r.location,r.length,ic);
1396: [textViewIn replaceCharactersInRange: r withString: ic];
1397: r.location = r.location+1; r.length = 0;
1398: [textViewIn setSelectedRange: r ];
1399: r.location = r.location-1; r.length = 2;
1400: [textViewIn setTextColor: [NSColor blackColor] range: r];
1401: }
1402: -(NSString *) getContentsOfInputCell {
1403: int start,end,i,n;
1404: NSString *cmd0;
1405: NSRange r;
1406: cmd0 = [textViewIn string];
1407: start=0; end = n = [cmd0 length]; if (end > 0) end--;
1408: r = [textViewIn selectedRange];
1409: if (r.location < n) i = r.location; else i = n-1;
1410: if (i < 0) i=0;
1411: for (; i>=0; i--) {
1412: if ([cmd0 characterAtIndex: i] == BEGIN_INPUT_CELL) {
1413: start = i+1; break;
1414: }
1415: }
1416: for (i=start; i<n; i++) {
1417: if ([cmd0 characterAtIndex: i] == END_INPUT_CELL) {
1418: end = i-1; break;
1419: }
1420: }
1421: // NSLog(@"start=%d, end=%d\n",start,end);
1422: r.location = start; r.length = end-start+1;
1423: if (r.length > 0) {
1424: cmd0= [cmd0 substringWithRange: r];
1425: }else{
1426: cmd0 = @"";
1427: }
1428: if (end+2 <= n) r.location=end+2;
1429: r.length = 0;
1430: [textViewIn setSelectedRange: r];
1431: return cmd0;
1432: }
1433: // return 1 if there is the next inputCell
1434: -(int) getOutOfOutputCell {
1435: int start,end,i,n;
1436: NSString *cmd0;
1437: NSRange r;
1438: cmd0 = [textViewIn string];
1439: n = [cmd0 length];
1440: r = [textViewIn selectedRange];
1441: start = r.location;
1442: // NSLog(@"r.location=%d, r.length=%d\n",r.location,r.length);
1443: if (r.location < n) i = r.location; else i = n-1;
1444: if (i>0) i--;
1445: for (; i<n; i++) {
1446: if ([cmd0 characterAtIndex: i] == END_OUTPUT_CELL) {
1447: start = i+1; break;
1448: }else if ([cmd0 characterAtIndex: i] == BEGIN_INPUT_CELL) {
1449: r.location = i+1; r.length=0;
1450: [textViewIn setSelectedRange: r]; [textViewIn scrollRangeToVisible: r];
1451: return 1;
1452: }else if ([cmd0 characterAtIndex: i] == END_INPUT_CELL) {
1453: r.location = i-1; r.length=0;
1454: [textViewIn setSelectedRange: r]; [textViewIn scrollRangeToVisible: r];
1455: return 1;
1456: }
1457: }
1458: r.location = start; r.length = 0;
1459: [textViewIn setSelectedRange: r];
1460:
1461: for (i = start; i<n; i++) {
1462: // Try to find the next input cell.
1463: if ([cmd0 characterAtIndex: i] == BEGIN_INPUT_CELL) {
1464: r.location = i+1; r.length = 0;
1465: [textViewIn setSelectedRange: r]; [textViewIn scrollRangeToVisible: r];
1466: return 1;
1467: }else if ([cmd0 characterAtIndex: i] == END_INPUT_CELL) {
1468: // We are inside an input cell.
1469: r.location = i-1; r.length = 0;
1470: [textViewIn setSelectedRange: r]; [textViewIn scrollRangeToVisible: r];
1471: return 1;
1472: }
1473: }
1474: return 0;
1475: }
1476: -(void) prepareOutputCell {
1477: int start,end,i,j,n,m;
1478: NSString *cmd0;
1479: NSString *ic;
1480: unichar uu[7];
1481: NSRange r;
1482: start = -1; end = -1;
1483: cmd0 = [textViewIn string];
1484: n = [cmd0 length];
1485: r = [textViewIn selectedRange];
1486: i = r.location;
1487: if (i < 0) i = 0;
1488: if (i >= n) i = n-1;
1489: for (; i<n; i++) {
1490: if ([cmd0 characterAtIndex: i] == BEGIN_OUTPUT_CELL) {
1491: start = i;
1492: for (j=i; j>=0; j--) {
1493: if ([cmd0 characterAtIndex: j] <= ' ') {
1494: start = j;
1495: } else {
1496: if (start>0) start--;
1497: break;
1498: }
1499: }
1500: break;
1501: }else if ([cmd0 characterAtIndex: i] == BEGIN_INPUT_CELL) {
1502: start = i-1;
1503: if (start < 0) start = 0;
1504: end = -2;
1505: break;
1506: }
1507: }
1508: if (end == -2) {
1509: r.location = start; r.length=0;
1510: }else{
1511: end = start;
1512: i = start; if (i < 0) i = 0;
1513: for (; i<n; i++) {
1514: if ([cmd0 characterAtIndex: i] == END_OUTPUT_CELL) {
1515: end = i; break;
1516: }
1517: }
1518: if ((start == -1) || (end == -1)) {
1519: r.location = n; r.length=0;
1520: }else{
1521: r.location = start; r.length = end-start+1;
1522: }
1523: }
1524: [textViewIn replaceCharactersInRange: r withString: @""];
1525:
1526: uu[0] = '\n';
1527: uu[1] = BEGIN_OUTPUT_CELL; uu[2] = END_OUTPUT_CELL;
1528: m = 3;
1529: // If there is no next input cell, add a new one.
1530: for (i=r.location; i<n; i++) {
1531: if ([cmd0 characterAtIndex:i] == BEGIN_INPUT_CELL) {
1532: break;
1533: }
1534: }
1535: if ((i == n) || (r.location >= n)) {
1536: uu[3] = '\n'; uu[4] = BEGIN_INPUT_CELL; uu[5] = END_INPUT_CELL; m=6;
1537: }
1538: // NSLog(@"prepareOutputCell start=%d, length=%d, m=%d\n",start,r.length,m);
1539: r.length = 0;
1540: ic = [NSString stringWithCharacters: uu length: m];
1541: [textViewIn replaceCharactersInRange: r withString: ic];
1542: r.location = r.location+2; r.length = 0;
1543: [textViewIn setSelectedRange: r ];
1544: }
1545: @end
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>