// // AppDelegate.m // UpTeXeditor // // Created by 小川弘和 on 2015/08/02. // Copyright (c) 2015年 小川弘和. All rights reserved. // #import "AppDelegate.h" #import "Document.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender { return NO; } //起動時の処理 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { //初期設定ファイルからエディタのフォントを設定 NSUserDefaults *ud; ud = [NSUserDefaults standardUserDefaults]; if ([ud floatForKey:@"fontSize"]) {} else [ud setInteger:18 forKey:@"fontSize"]; if ([ud valueForKey:@"fontName"]) {} else [ud setObject:@"HiraMinProN-W3" forKey:@"fontName"]; if ([ud valueForKey:@"sizeDisplay"]) {} else {NSString* size = @"18"; [ud setObject: size forKey:@"sizeDisplay"];} if ([ud valueForKey:@"nameDisplay"]) {} else {NSString* name = @"ヒラギノ明朝 ProN W3"; [ud setObject: name forKey:@"nameDisplay"];} [ud synchronize]; //初起動時の処理 1.~/Library/Pereferencesに初期設定ファイルがなかったらアプリ内からコピーする NSArray* libraryPaths; libraryPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); NSString* prefPath = [libraryPaths[0] stringByAppendingPathComponent:@"Preferences/com.dokuroryokan.UpTeX.command.plist"]; NSFileManager* fileMgr; fileMgr = [NSFileManager defaultManager]; if (![fileMgr fileExistsAtPath:prefPath]) { NSString* myPath= [ NSBundle mainBundle ].bundlePath ; NSString* plistPath = [myPath stringByAppendingString:@"/Contents/Resources/command.plist"]; [fileMgr copyItemAtPath:plistPath toPath:prefPath error:nil]; } //初起動時の処理 2.texmf-local内にフォントのシンボリックリンクを生成する NSString* myPath; myPath= [ NSBundle mainBundle ].bundlePath ; NSString* fontPath; fontPath = [myPath stringByAppendingString:@"/Contents/Resources/TEX/texmf-local/fonts/opentype/cjk-gs-integrate"]; NSFileManager* fileMgr2; fileMgr2 = [NSFileManager defaultManager]; if (![fileMgr2 fileExistsAtPath:fontPath]) { [self cjkgsIntegrate]; } else //初起動でなく、チェックボックスがオンならtlmgr update --self --allを実行する { if (_launchUp.state == NSOnState) { [self texUpdate]; } } //コンソールウィンドウのスタイルを初期設定に応じて設定 BOOL tc = [ud boolForKey:@"tc"]; if (tc == YES) { //レトロ風 _logWindow.alphaValue = 0.85; [_logView setTextColor:[NSColor greenColor]]; [_logView setBackgroundColor:[NSColor blackColor]]; } else { //通常 _logWindow.alphaValue = 1; [_logView setTextColor:[NSColor blackColor]]; [_logView setBackgroundColor:[NSColor whiteColor]]; } } //アプリ終了時の処理:特に何もしない - (void)applicationWillTerminate:(NSNotification *)aNotification { // Insert code here to tear down your application } //フォントパネルの表示メソッド - (IBAction)showFontPanel:(id)sender { [[NSFontPanel sharedFontPanel] makeKeyAndOrderFront:self]; [NSFontManager sharedFontManager].delegate = self; } //エディタのフォント変更のメソッド - (void)changeFont:(id)sender { NSFont* oldFont = [NSFont fontWithName:@"Times" size:14]; NSFont* newFont; newFont = [sender convertFont:oldFont]; NSString* newFontFamilyName; newFontFamilyName = newFont.familyName; NSString* newFontDisplayName; newFontDisplayName = newFont.displayName; NSString* newFontName; newFontName = newFont.fontName; NSInteger fontSize= newFont.pointSize; NSUserDefaults *ud; ud = [NSUserDefaults standardUserDefaults]; [ud setInteger:fontSize forKey:@"fontSize"]; [ud setObject:newFontName forKey:@"fontName"]; [ud setObject:newFontDisplayName forKey:@"nameDisplay"]; NSString* sizeDisplay; sizeDisplay = [NSString stringWithFormat:@"%.0f", newFont.pointSize]; [ud setObject:sizeDisplay forKey:@"sizeDisplay"]; [ud synchronize]; } //プルダウンメニューでの選択を受け取って、リポジトリを変更するメソッド - (IBAction)selectedRPopUp:(id)sender { NSString* rep; if (Rpop.selectedTag ==0) {rep = @"http://ftp.jaist.ac.jp/pub/CTAN/systems/texlive/tlnet/";} if (Rpop.selectedTag ==1) {rep = @"ftp://ftp.jaist.ac.jp/pub/CTAN/systems/texlive/tlnet/";} if (Rpop.selectedTag ==2) {rep = @"http://ftp.kddilabs.jp/pub/ctan/systems/texlive/tlnet/";} if (Rpop.selectedTag ==3) {rep = @"ftp://ftp.u-aizu.ac.jp/pub/tex/CTAN/systems/texlive/tlnet/";} if (Rpop.selectedTag ==4) {rep = @"ftp://ftp.tug.org/texlive/tlnet/";} if (Rpop.selectedTag ==5) {rep = @"http://mirror.ctan.org/systems/texlive/tlnet";} NSString* _arg; _arg = [@"echo \"リポジトリを変更しています。\n\"; cd ~/; CC=: tlmgr option repository " stringByAppendingString:rep]; _arg = [_arg stringByAppendingString:@"; tlmgr repository add http://contrib.texlive.info/current tlcontrib; tlmgr pinning add tlcontrib '*'; echo \"リポジトリ変更が完了しました。\n\""]; [_logView setString:@""]; [self startProcess:_arg]; } //プルダウンメニューでの選択を受け取って、dvipdfmx用のフォントを切り替えるメソッド - (IBAction)selectedPopUp:(id)sender { NSString* pdffont; if (PDFpop.selectedTag ==0) {pdffont = @"--jis2004 hiragino-highsierra-pron";} if (PDFpop.selectedTag ==1) {pdffont = @"--jis2004 hiragino-highsierra";} if (PDFpop.selectedTag ==2) {pdffont = @"--jis2004 toppanbunkyu-highsierra";} if (PDFpop.selectedTag ==3) {pdffont = @"--jis2004 toppanbunkyu-sierra";} if (PDFpop.selectedTag ==4) {pdffont = @"--jis2004 hiragino-elcapitan-pron";} if (PDFpop.selectedTag ==5) {pdffont = @"--jis2004 hiragino-elcapitan";} if (PDFpop.selectedTag ==6) {pdffont = @"--jis2004 hiragino-pron";} if (PDFpop.selectedTag ==7) {pdffont = @"--jis2004 hiragino";} if (PDFpop.selectedTag ==8) {pdffont = @"--jis2004 yu-osx";} if (PDFpop.selectedTag ==9) {pdffont = @"ipaex";} if (PDFpop.selectedTag ==10) {pdffont = @"ipa";} if (PDFpop.selectedTag ==11) {pdffont = @"--jis2004 kozuka-pr6n";} if (PDFpop.selectedTag ==12) {pdffont = @"--jis2004 kozuka-pr6";} if (PDFpop.selectedTag ==13) {pdffont = @"--jis2004 noEmbed";} NSString* _arg; _arg = @"echo \"dvipdfmxのフォントを変更しています。\n\"; mktexlsr;kanji-config-updmap-sys "; _arg = [_arg stringByAppendingString:pdffont]; _arg = [_arg stringByAppendingString:@"; echo \"\n\"; echo \"dvipdfmxのフォント変更が完了しました。\n\""]; [_logView setString:@""]; [self startProcess:_arg]; } //プッシュボタンからtlmgr update --self --allするためのメソッド - (IBAction)pushFUPButton:(id)sender { NSString *_op; if (_forceUp.state == NSOnState) { _op=@"--reinstall-forcibly-removed "; }else{ _op=@""; } NSString* _arg; _arg = @"echo \"TeXコンポーネントをアップデートしています。\n\"; cd ~/; CC=: tlmgr update --self; CC=: tlmgr update "; _arg = [_arg stringByAppendingString:_op]; _arg = [_arg stringByAppendingString:@"--all; echo \"\nTeXコンポーネントのアップデートが完了しました。\n\""]; [_logView setString:@""]; //NSLog(@"%@", _arg); [self startProcess:_arg]; } //ボタンプッシュでtexbinのパスを生成・クリップボードに格納するメソッド - (IBAction)pushPButton:(id)sender { NSString* myPath; myPath= [ NSBundle mainBundle ].bundlePath ; NSString* stringToWrite; stringToWrite = [myPath stringByAppendingString:@"/Contents/Resources/TEX/texbin"]; NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; [pasteboard declareTypes:@[NSStringPboardType] owner:nil]; [pasteboard setString:stringToWrite forType:NSStringPboardType]; } //ボタンプッシュでシンボリックリンク作成メソッドに渡すメソッド - (IBAction)pushFSButton:(id)sender { [self cjkgsIntegrate]; } //フォントのシンボリックリンクを作成するためのメソッド - (void)cjkgsIntegrate { NSString* myPath; myPath= [ NSBundle mainBundle ].bundlePath ; NSFileManager *tmpFile = [ NSFileManager defaultManager]; [tmpFile changeCurrentDirectoryPath:[myPath stringByAppendingString:@"/Contents/Resources/"]]; NSString* _arg; _arg = @"echo \"フォントをスキャンしてシンボリックリンクを作成しています。\n\";cjk-gs-integrate --output=test --link-texmf --cleanup;cjk-gs-integrate-macos --output=test --link-texmf; rm -rf "; _arg = [_arg stringByAppendingString:myPath]; _arg = [_arg stringByAppendingString:@"/Contents/Resources/test; echo \"\nシンボリックリンクの作成が完了しました。\""]; [_logView setString:@""]; [self startProcess:_arg]; } // tlmgr update --self --allを実行するメソッド - (void)texUpdate { NSString* arg; arg = @"echo \"TeXコンポーネントをアップデートしています。\n\"; cd ~/; CC=: tlmgr update --self --all; echo \"\n\"; echo \"TeXコンポーネントのアップデートが完了しました。\n\""; [_logView setString:@""]; [self startProcess:arg]; } //ログの表示をクリアするメソッド。他のクラスからの指示のため。 - (void)cleanLogveiw { [_logView setString:@""]; } //ボタンプッシュでパッケージ管理ウィンドウを開き処理をはじめるメソッド - (IBAction)pushPacButton:(id)sender { [NSApp activateIgnoringOtherApps:YES]; [_pacWindow makeKeyAndOrderFront:self]; [self listGet]; } //パッケージ管理ウィンドウのリストを取得するメソッド。tlmgr -listで得たテキストをパースしNSArrayControllerに格納・NSTableViewに表示している。 //パッケージ管理ウィンドウ表示メソッドに組み込んでもよかったが、別に呼び出すこともできるようにしてある。 - (void)listGet { listCnt.content = nil; //tlmgr info --data name,category,installed,shortdesc,longdescをcmdResultメソッドに投げて実行して、返り値=標準出力をパースする。結果はCSVで得られるが、shortdescやlongdescの文中に","がある場合があるので、それらは出現パターンに応じて別の文字列に置換。そのうえで","も"@@@"に置換。そこまでやってから","を含んでいたため別文字列に置換したものを、もとの文字列に再置換している。 NSString *result; result = [self cmdResult:@"cd ~/; CC=: tlmgr info --data name,category,installed,shortdesc,longdesc"]; result = [result stringByReplacingOccurrencesOfString:@", " withString:@"***"]; result = [result stringByReplacingOccurrencesOfString:@",." withString:@"$$$"]; result = [result stringByReplacingOccurrencesOfString:@".," withString:@"%%%"]; result = [result stringByReplacingOccurrencesOfString:@"," withString:@"@@@"]; result = [result stringByReplacingOccurrencesOfString:@"***" withString:@", "]; result = [result stringByReplacingOccurrencesOfString:@"$$$" withString:@",."]; result = [result stringByReplacingOccurrencesOfString:@"%%%" withString:@".,"]; result = [result stringByReplacingOccurrencesOfString:@"\"" withString:@""]; //まず、改行コードで分割してパッケージごとのレコードに分解しMutableArrayに格納する。 NSMutableArray *lines = [NSMutableArray array]; [result enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) { [lines addObject:line]; }]; //パッケージのレコードごとに"@@@"で分割してname,category,installed,shortdesc,longdescのデータを得て、NSDictionaryに格納。NSArrayControllerにセットしてNSTableViewでリスト表示するためのループ処理。 NSString* install; NSString* sts; for (NSString *row in lines) { NSArray *items = [row componentsSeparatedByString:@"@@@"]; //installedについては、済・未を表す1/0をYES/NOに置換して表示。またYESならリストの先頭(NSArrayControllerの先頭レコード)に“旗”を立てる。 if ([items[2] isEqualToString:@"1"]) { install = @"YES"; sts = @"🚩"; } if ([items[2] isEqualToString:@"0"]) { install = @"NO"; sts = @""; } NSDictionary *tmpData = @{@"sts":sts,@"name" :items[0],@"category" : items[1],@"install" : install,@"shortdesc" : items[3], @"longdesc" : items[4]}; [listCnt addObject:tmpData]; } //リストのトップを選択状態にして処理を完了する。 [listCnt setSelectionIndex:0]; } //パッケージをインストール/アンインストールするメソッド - (IBAction)pushInstButton:(id)sender { [NSApp activateIgnoringOtherApps:YES]; [_logWindow makeKeyAndOrderFront:self]; [_logView setString:@""]; inst = _status.stringValue; paName = _name.stringValue; NSString *_arg; NSString *_mes; //インストール済か否かでコマンドを決定 if ([inst isEqualToString:@"NO"]) { _mes = [paName stringByAppendingString:@"をインストールします。\n"]; _arg = @"cd ~/; CC=: tlmgr install "; } if ([inst isEqualToString:@"YES"]) { _mes = [paName stringByAppendingString:@"をアンインストールします。\n"]; _arg = @"cd ~/; CC=: tlmgr uninstall "; } NSString *logtxt; [_logView setString:_mes]; //cmdResultメソッドにコマンドを投げて実行。同期実行にしているのは、実行中の思わぬ操作で選択パッケージが変更されてしまって、以降の処理で不整合が起きないようにするため。 _arg=[_arg stringByAppendingString:paName]; NSString* result = [self cmdResult: _arg]; //コンソールウィンドウにcmdResultの返り値=実行ログを表示 logtxt = [_logView string]; [_logView setString:[logtxt stringByAppendingString:result]]; [_logView scrollRangeToVisible:NSMakeRange( [_logView string ].length , 0 ) ]; //cmdResultでtlmgr info パッケージ名を実行。後で結果をパースしてインストール済か否かを取得するため。 result = [self cmdResult: [@"tlmgr info " stringByAppendingString:paName]]; //選択中のパッケージのデータをNSArrayControllerから取得。 NSUInteger tmpIndex = listCnt.selectionIndex; NSDictionary *tmpData = listCnt.arrangedObjects[tmpIndex]; NSString *tmpName = tmpData[@"name"]; NSString *tmpCategory = tmpData[@"category"]; NSString *tmpShortdesc = tmpData[@"shortdesc"]; NSString *tmpLongdesc = tmpData[@"longdesc"]; //cmdResultの返り値をパースしてインストール済か否かを取得。それに応じてリスト更新用のパッケージのデータを設定 NSString* instRes; NSString* stsRes; NSString *search = @"installed: Yes"; NSRange range = [result rangeOfString:search]; if (range.location != NSNotFound) { instRes = @"YES"; stsRes = @"🚩"; } search = @"installed: No"; range = [result rangeOfString:search]; if (range.location != NSNotFound) { instRes = @"NO"; stsRes = @""; } //NSArrayControllerからパッケージの現在情報を削除。更新情報に置き換えた新しいデータを用意して、もとの位置に挿入し、NSTableViewの表示も更新する。 [listCnt removeObjectAtArrangedObjectIndex: tmpIndex]; NSDictionary* newData = @{@"sts":stsRes,@"name" :tmpName,@"category" :tmpCategory,@"install" : instRes,@"shortdesc" : tmpShortdesc, @"longdesc" :tmpLongdesc}; [listCnt insertObject:newData atArrangedObjectIndex: tmpIndex]; // [listCnt setSelectionIndex:tmpIndex]; [_table scrollRowToVisible:_table.selectedRow]; //取得したインストール済・未情報を更新実行前と比較。不一致なら処理成功・一致なら処理失敗と判断して、結果をコンソールウィンドウに表示する。 logtxt = [_logView string]; NSString* ending; if ([inst isEqualToString:instRes]) {ending=[paName stringByAppendingString:@"の処理に失敗しました。"];} else {ending=[paName stringByAppendingString:@"の処理に成功しました。"];} [_logView setString:[logtxt stringByAppendingString:ending]]; [_logView scrollRangeToVisible:NSMakeRange( [_logView string ].length , 0 ) ]; } //バックアップを残すか否かのチェックボックスのメソッド - (IBAction)checkBuBox:(id)sender { [_logView setString:@""]; NSString *_arg; if (_chekcBu.state == NSOnState) { //NSLog(@"はチェックあり。\n"); _arg=@"echo \"バックアップを保存するよう設定します。\"; cd ~/; CC=: tlmgr option -- autobackup 1; echo \"\n設定が終わりました。\""; [self startProcess:_arg]; }else{ //NSLog(@"はチェックなし。\n"); _arg=@"echo \"バックアップを保存しないよう設定します。\"; cd ~/; CC=: tlmgr option -- autobackup 0; echo \"\n設定が終わりました。\""; [self startProcess:_arg]; } } //バックアップをクリアするメソッド - (IBAction)pushCleanBuButton:(id)sender { NSString *_arg; [_logView setString:@""]; if (_chekcBu.state == NSOnState) { _arg=@"echo \"「バックアップを残す」設定では、バックアップを削除できません。\""; } else { _arg=@"echo \"バックアップをクリアします。\"; cd ~/; CC=: tlmgr backup --clean --all; echo \"\nバックアップのクリアが終わりました。\""; } [self startProcess:_arg]; } //個別にバックアップからレストアするメソッド - (IBAction)pushBuButton:(id)sender { [_logView setString:@""]; NSString* paName; paName = _name.stringValue; //まずtlmgr resutore パッケージ名をcmdResultメソッドで実行して結果を得る。バックアップが残っていればAvailable backups for hoge: 39105 (2016-02-02 15:45)のようになるので、")"の有無でバックアップの有無を判定。バックアップがなければ処理を終了する。 NSString *_arg; _arg = [@"tlmgr restore " stringByAppendingString:paName]; NSString *result = [self cmdResult:_arg]; NSRange range = [result rangeOfString:@")"]; if (range.location == NSNotFound) { _arg=@"echo \"バックアップはありません。処理を終了します。\n\""; [self startProcess:_arg]; } //バックアップがあればcmdResultの返り値を":"と" ("で分割してバックアップのNo.を取得し、それとパッケージ名とからコマンドを生成して、startProcessメソッドに投げて実行する。 else { NSArray *arr = [result componentsSeparatedByString:@":"]; result = arr [1]; arr = [result componentsSeparatedByString:@" ("]; result = arr [0]; _arg=[@"echo \"" stringByAppendingString:paName]; //tlmgr restoreは途中でYES/NOの確認のために標準入力へのy/nの入力を要求する。が、そのメッセージがコンソールウィンドウにしかるべき段階で表示されないので、以下のメッセージを表示して選択を促す。 _arg=[_arg stringByAppendingString:@"をバックアップからレストアします。続行するならy, キャンセルするならnを入力してください。\n\"; cd ~/; CC=: tlmgr restore "]; _arg=[_arg stringByAppendingString:paName]; _arg=[_arg stringByAppendingString:@" "]; _arg=[_arg stringByAppendingString:result]; _arg=[_arg stringByAppendingString:@"; echo \"レストアが完了しました。\""]; // NSLog(@"%@", _arg); [self startProcess:_arg]; } } //すべてをレストアするメソッド。 - (IBAction)pushABuButton:(id)sender { NSString *_arg; //tlmgr restoreは途中でYES/NOの確認のために標準入力へのy/nの入力を要求する。が、そのメッセージがコンソールウィンドウにしかるべき段階で表示されないので、以下のメッセージを表示して選択を促す。 _arg=@"echo \"バックアップからフルレストアします。続行するならy, キャンセルするならnを入力してください。\n\"; cd ~/; CC=: tlmgr restore -all; echo \"フルレストアが完了しました。\""; [_logView setString:@""]; [self startProcess:_arg]; } //platex, uplatexのfmtを再作成するメソッド。 - (IBAction)pushFButton:(id)sender { NSString *_arg; _arg=@"echo \"platex, uplatexのfmtファイルを再作成します。。\n\"; fmtutil-sys --byfmt platex; fmtutil-sys --byfmt uplatex; echo \"fmtファイルの作成が完了しました。\""; [_logView setString:@""]; [self startProcess:_arg]; } //コマンドの同期実行メソッド。標準出力を返り値として返すことで、結果のパースなどをできるようにしてある。 //bash -c "export PATH="hoge/texbin:$PATH";<引数として受け取った、実行するべきコマンド>"の定型で、texbinにパスを通すようにしている。 //大概、実行ディレクトリも移動せねばならず、現状では引数のなかに"cd hoge;本来実行したいコマンド"とすることで処理しているが、メソッド自身が二つめの引数として移動すべきディレクトリを受け取る用にした方がよいかもしれない。 - (NSString *)cmdResult:(NSString *)argString { NSString* myPath; myPath= [ NSBundle mainBundle ].bundlePath ; NSString* binPath; binPath = [myPath stringByAppendingString:@"/Contents/Resources/TEX/texbin"]; NSString* _arg; _arg = [@"export PATH=\"" stringByAppendingString:binPath]; _arg = [_arg stringByAppendingString:@":$PATH\"; "]; _arg = [_arg stringByAppendingString:argString]; NSTask *tmpTask = [[NSTask alloc] init]; tmpTask.launchPath = @"/bin/bash"; tmpTask.arguments = @[@"-c",_arg]; NSPipe *pipe = [NSPipe pipe]; tmpTask.standardOutput = pipe; [tmpTask launch]; NSData *data = [pipe.fileHandleForReading readDataToEndOfFile]; if (data != nil && data.length) { NSString *_out; _out = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; return _out; } else return nil; } /*以下のコマンドの実行と標準出力の逐次表示は https://qiita.com/denjin-m/items/e859953aa83c93cddd2b から戴いたものをアレンジした。*/ //親プロセスから実行コマンドを受け取って実行するメソッド //bash -c "export PATH="hoge/texbin:$PATH";<引数として受け取った、実行するべきコマンド>"の定型で、texbinにパスを通すようにしている。 //大概、実行ディレクトリも移動せねばならず、現状では引数のなかに"cd hoge;本来実行したいコマンド"とすることで処理しているが、メソッド自身が二つめの引数として移動すべきディレクトリを受け取る用にした方がよいかもしれない。そのヴァージョンも作ったが、直しの見落としがあると嫌なので、こちらのままにしてある。 - (void)startProcess:(NSString*)argString { NSString* myPath; myPath= [ NSBundle mainBundle ].bundlePath ; NSString* binPath; binPath = [myPath stringByAppendingString:@"/Contents/Resources/TEX/texbin"]; NSString* _arg; _arg = [@"export PATH=\"" stringByAppendingString:binPath]; _arg = [_arg stringByAppendingString:@":$PATH\"; "]; _arg = [_arg stringByAppendingString:argString]; _task = [[NSTask alloc] init]; _task.launchPath = @"/bin/bash"; _task.arguments = @[@"-c",_arg]; NSPipe *pipe = [NSPipe pipe]; inpipe = [NSPipe pipe]; _task.standardOutput = pipe; _task.standardError = pipe; _task.standardInput = inpipe; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getData:) name:NSFileHandleReadCompletionNotification object:pipe.fileHandleForReading]; [pipe.fileHandleForReading readInBackgroundAndNotify]; writeHandle=inpipe.fileHandleForWriting; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskExited:) name:NSTaskDidTerminateNotification object: _task]; [NSApp activateIgnoringOtherApps:YES]; [_logWindow makeKeyAndOrderFront:self]; [_task launch]; } //Notification - (void)getData:(NSNotification *)aNotification { NSData *data = aNotification.userInfo[NSFileHandleNotificationDataItem]; NSString *strOut; NSString *logtxt; if (data != nil && data.length) { //ログを表示。platexの日本語ファイル名処理のために、ログの文字コードを判別するようにしてあるが、実質的にはASCIIとUTF-8だけを扱えばよいかもしれない。 strOut = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; NSString* tryStr; tryStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; if (tryStr != nil) { strOut = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; } else { tryStr = [[NSString alloc] initWithData:data encoding:NSShiftJISStringEncoding]; if (tryStr != nil) { strOut = [[NSString alloc] initWithData:data encoding:NSShiftJISStringEncoding]; } else { tryStr = [[NSString alloc] initWithData:data encoding:NSJapaneseEUCStringEncoding]; if (tryStr != nil) { strOut = [[NSString alloc] initWithData:data encoding:NSJapaneseEUCStringEncoding]; } else tryStr = [[NSString alloc] initWithData:data encoding:NSISO2022JPStringEncoding]; if (tryStr != nil) { strOut = [[NSString alloc] initWithData:data encoding:NSISO2022JPStringEncoding]; } } } logtxt = [_logView string]; [_logView setString:[logtxt stringByAppendingString:strOut]]; [_logView scrollRangeToVisible:NSMakeRange( [_logView string ].length , 0 ) ]; // we need to schedule the file handle go read more data in the background again. [aNotification.object readInBackgroundAndNotify]; } else { [[NSNotificationCenter defaultCenter] removeObserver:self name:NSFileHandleReadCompletionNotification object:[_task.standardOutput fileHandleForReading]]; [_task waitUntilExit]; [[NSNotificationCenter defaultCenter] postNotificationName:@"pdfopen" object:nil]; } } //TexfFieldから標準出力を受け取るメソッド - (IBAction)pushRButton:(id)sender{ if ((_task.running)&&(inpipe)) { NSString* command; command = [[_input stringValue] stringByAppendingString:@"\n"]; NSData* myData; myData = [command dataUsingEncoding:NSUTF8StringEncoding]; [writeHandle writeData: myData]; NSString *logtxt; logtxt = [_logView string]; [_logView setString:[logtxt stringByAppendingString:command]]; [_logView scrollRangeToVisible:NSMakeRange( [_logView string ].length , 0 ) ]; } [_input setStringValue: @""]; } //ボタンプッシュでタスクを停止するメソッド - (IBAction)stopProcess:(id)sender { // Notificationの削除 [[NSNotificationCenter defaultCenter] removeObserver:self name:NSFileHandleReadCompletionNotification object:[_task.standardOutput fileHandleForReading]]; // タスクの停止 // 停止の完了を待たずに、すぐに処理が戻ってくる。 [_task terminate]; NSString *logtxt; logtxt = [_logView string]; [_logView setString:[logtxt stringByAppendingString:@"\n処理を強制終了しました。"]]; [_logView scrollRangeToVisible:NSMakeRange( [_logView string ].length , 0 ) ]; } //タスク完了後の処理のメソッド - (void)taskExited:(NSNotification *)aNotification { [[NSNotificationCenter defaultCenter] removeObserver:self name:NSTaskDidTerminateNotification object:_task]; _task = nil; } //ヘルプメニューの「UpTeX ReadMe」からReadMe.pdfを表示するメソッド。できれば、直接にHelpを置き換えた方がよい。今後の課題。 - (IBAction)showUptexHelp:(id)sender { BOOL openResult; NSString* myPath; myPath = [ NSBundle mainBundle ].bundlePath ; NSString* helpDoc =[myPath stringByAppendingString:@"/Contents/Resources/ReadMe.pdf"]; openResult = [[NSWorkspace sharedWorkspace] openFile:helpDoc withApplication:myPath]; } @end