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