//
//  RunViewController.m
//  X-BASIC'
//
//  Created by AIG-Soft(iMac) on 2012/10/21.
//  Copyright (c) 2012-15年 AIG-Soft. All rights reserved.
//

#import "RunViewController.h"
#import "main.h"
#import "click.h"
#import "mode.h"
#import "XB.h"
#import "ScreenCapture.h"
#import "Console+animation.h"
#import "UIActivityIndicatorView+show.h"
#import "UIView+waku.h"
#import "AppDelegate.h"
#import "Setup.h"

@interface RunViewController()
{
	UIActivityIndicatorView	*indicator;
}
@end

@implementation RunViewController

//-------------------------------------------------------------------
#if 0
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
	// runViewの読み込み時に呼び出される
	printSelf();
	nslog(@"fname=%@",nibNameOrNil);
	nslog(@"bundle=%@",nibBundleOrNil);
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
	//
	printSelfs(@"end",@"");
    return self;
}
#endif

-(instancetype)init
{
	nslog(@"RunVC init");
	self=[super init];
	if (self!=nil) {
		runView=self;	// XB外部関数のためにselfのアドレスを保存
//		tcons=tconsole;	// tconsoleはここではまだ未定なのでだめ
		debugTextMain=nil;
	}
	return self;
}

//---------------------------------------------------

-(void)setCLoseButton:(NSInteger)fdisp
{
	printSelf();
	if (fdisp) { // 表示する
		nslog(@"Close表示する");
		btnClose.tag=MODE_END;
		btnClose.tintColor=[UIColor blueColor]; // アイコンでも色は必要
		// アイコン化したので不要
//		[btnClose setTitle:NSLocalStr(@"CLOSE")];
		btnClose.enabled=YES;
	} else {
		nslog(@"Close表示しない");
		btnClose.tag=MODE_DISPLAY; // 何もしない印
		btnClose.tintColor=[UIColor clearColor]; // これでボタンが消える
		// アイコン化したので不要
//		[btnClose setTitle:@""];
		btnClose.enabled=NO;
	}
}

-(void)setBreakButton:(NSInteger)mode
{
	printSelfs(@"mode=%d",(int)mode);
	btnBreak.tag=mode;
	// stopとrunのサイズは同じ
	btnBreak.tintColor=[UIColor clearColor]; // これがないと画像の横から背景色が見えてしまう

	// .imageはUIBarItemのプロパティ
	switch (mode) {
		case MODE_DEBUG:
		case MODE_DISPLAY:
			nslog(@"MODE_DISPLAY");
			btnBreak.tintColor=[UIColor clearColor]; // これでボタンが消える
//			[btnBreak setTitle:@""];
			btnBreak.enabled=NO;
			return;
			
		case MODE_RUN:
			nslog(@"MODE_RUN");
			btnBreak.tintColor=[UIColor redColor];
			[btnBreak setImage:nil]; // これをしないと↓文字が有効にならない
			[btnBreak setTitle:@"Break"]; // ここはキーと同じ表記にするため英語のまま
			btnBreak.enabled=YES;
			break;
		
		case MODE_RERUN:
			nslog(@"MODE_RERUN");
			btnBreak.tintColor=[UIColor blueColor];
			[btnBreak setImage:[UIImage imageNamed:@"Run"]];
			[btnBreak setTitle:@""];
			btnBreak.enabled=YES;
			break;
	}
}

-(void)setDebugButton:(NSInteger)fdisp
{
	printSelf();
	btnDebug.tag=MODE_DEBUG;
	
	AppDelegate *app=getAppDelegate();
	Setup *setup=app.setup;
	if (!setup.fdisplayDebugButton) {
		// デバッグボタンを消す設定の時
		fdisp=NO;
	}
	
	if (fdisp) { // 表示する
		nslog(@"Debug表示する");
		btnDebug.tag=MODE_DEBUG;
		btnDebug.tintColor=[UIColor colorWithRed:(64.0/256.0) green:0 blue:(128.0/256.0) alpha:1.0]; // アイコンでも色は必要
		// アイコン化したので不要
//		[btnDebug setTitle:NSLocalStr(@"DEBUG")];
		btnDebug.enabled=YES;
	} else {
		nslog(@"Debug表示しない");
		btnDebug.tag=MODE_DISPLAY; // 何もしない印
		btnDebug.tintColor=[UIColor clearColor]; // これでボタンが消える
		// アイコン化したので不要
//		[btnDebug setTitle:@""];
		btnDebug.enabled=NO;
	}
}

//---------------------------------------------------

- (void)viewDidLoad
// 何故かここは実表示の直前に呼び出される
{
	printSelf();

    [super viewDidLoad];
	//
	self.title=NSLocalStr(@"PROGRAM_NAME");
	[self setBreakButton:MODE_RUN];
	[self setCLoseButton:YES];
	btnClose.tag=MODE_END;
	
	// メイル
	self.mail=[[Mail alloc]initWithViewController:self];
	
	// コンソール表の構築(RunViewController内で使いまわす)
	consoles=@[self.kconsole,sconsole,tconsole,gconsole0,gconsole1,gconsole2,gconsole3];
	//
	// 背景の上に各コンソールを重ねて配置する
	// 初期化状態では表示はOFF
	int page=KCONSOLE;
	for (id console in consoles) {
		nslog(@"console初期化:%@",console);
		[console init2]; 		// 初期化も行う
		[console setTag:page];	// tagにページ番号を入れておく（現在は使って無いが念のため）
		
		if (![console isKindOfClass:[kConsole class]]) { // kconsole以外
			nslog(@"KVO設定1");
			[console setKVO:self forKeyPath:OBSERVE_IMAGE];
			if ([console isKindOfClass:[gConsole class]]
			 || [console isKindOfClass:[sConsole class]]
				) { // gConsole/sConsole
				// アニメーション通知
				[console setKVO:self forKeyPath:OBSERVE_ANIME];
			}
		}
		//
		// 初期設定の印(selfの上に各ビューは乗ってない状態)
		priority[page]=-1;
		page++;
	}
	// 表示優先順位を設定する(キーは常に最高優先順位なので設定なし)
	[self vpriority:SCONSOLE p1:TCONSOLE p2:GCONSOLE0 p3:GCONSOLE1 p4:GCONSOLE2 p5:GCONSOLE3];

	// ↑KVOにかかわるフラグはここより前に設定すること

	// Key-Value Observing
	nslog(@"KVO設定2");
	[tconsole setKVO:self forKeyPath:OBSERVE_WIDTHX options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld];
	[tconsole setKVO:self forKeyPath:OBSERVE_WIDTHY options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld];
	[tconsole setKVO:self forKeyPath:OBSERVE_FONTWY options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld];
	[tconsole setKVO:self forKeyPath:OBSERVE_FONTWX options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld];
	[tconsole setKVO:self forKeyPath:OBSERVE_FONT   options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld];
#if 0
	// KVOテスト
	nslog(@"KVOテスト");
	tconsole.widthx=tconsole.widthx;
	tconsole.widthy=tconsole.widthy;
	tconsole.fontWx=tconsole.fontWx;
	tconsole.fontWy=tconsole.fontWy;
#endif
	//
// ここでこれを設定してはいけない。何故か画面が消えてしまう。
//	self.modalTransitionStyle=UIModalTransitionStylePartialCurl;

	// ステータスバーを消す
	[self prefersStatusBarHidden];
	[self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];
	
	// v3.20
	[self initDebug];
	[self setDebugButton:YES];
}


// ステータスバーを消す場合に必要
- (BOOL)prefersStatusBarHidden
{
    return YES;
}

// 以下は、ActionSheetから呼び出しによって表示される際にも呼び出されることに注意

-(void)viewWillAppear:(BOOL)animated
{
	printSelf();
	[super viewWillAppear:animated];
}

-(void)viewDidAppear:(BOOL)animated
{
	printSelf();
	[super viewDidAppear:animated];
}

-(void)viewWillDisappear:(BOOL)animated
{
	printSelf();
	[super viewWillDisappear:animated];
}

-(void)viewDidDisappear:(BOOL)animated
{
	printSelf();
	[super viewDidDisappear:animated];
}

//---------------------------------------------------------------------------------------------
// 外部関数で参照するための処理

// consoleはクラスが混在しているのでidで返す
-(id)getConsole:(int)page
{
	printSelfs(@"%d",page);
	return consoles[page];
}

//---------------------------------------------------------------------------------------------

// KVOによる変更通知受信
// 通知は、通知元の動いているスレッド内で来る。
// したがって、元がメインでないスレッドの場合は描画処理はさせられない
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
	//nslog(@"observeValueForKeyPath:%@ from=%@",keyPath,object);
	tConsole *tc=(tConsole *)object;
	if ([keyPath isEqual:OBSERVE_WIDTHX]) {
		nslog(@"KVO.widthx");
		_kconsole.widthx=tc.widthx;
	}
	if ([keyPath isEqual:OBSERVE_WIDTHY]) {
		nslog(@"KVO.widthy");
		_kconsole.widthy=tc.widthy;
	}
	if ([keyPath isEqual:OBSERVE_FONTWY]) {
		nslog(@"KVO.fontWy");
		_kconsole.fontWy=tc.fontWy;
	}
	if ([keyPath isEqual:OBSERVE_FONTWX]) {
		nslog(@"KVO.fontWx");
		_kconsole.fontWx=tc.fontWx;
	}
	if ([keyPath isEqual:OBSERVE_FONT]) {
		nslog(@"KVO.font");
		_kconsole.font=tc.font;
	}
	// 画面描画通知;各console共通受付
	if ([keyPath isEqual:OBSERVE_IMAGE]) {
		nslog(@"KVO.fimage");
		if ([object isKindOfClass:[Console class]]) {
			// tConsole/gConsole/sConsoleの時
			Console *cons=(Console *)object;
			nslog(@"console=%@",object);
			// 終了待ちするかどうか
			BOOL fwait=(cons.fimage==DRAW_WAIT);
			[cons performSelectorOnMainThread:@selector(displayMainThread) withObject:nil waitUntilDone:fwait];
		}
	} // if

	if ([keyPath isEqual:OBSERVE_ANIME]) {
		nslog(@"KVO.fanime");
		// 発生設定でクラスを設定してあるので、ここでは判断する必要はない
		// gConsole/sConsoleのみ
		Console *g=(Console *)object;
		nslog(@"Console=%@",g);
		[g performSelectorOnMainThread:@selector(animeMainThread) withObject:nil waitUntilDone:NO];
	} // if
}

//---------------------------------------------------------------------------------------------
// 公開関数
//---------------------------------------------------------------------------------------------

// 画面回転を禁止する(onoff=YES)
-(void)disableRotate:(BOOL)onoff
{
	printSelfs(@"%d",onoff);
	fRotaionLock=onoff;
}

// frotate : ROTATE_*;console.h
-(void)setFrotate:(int)frotate
{
	printSelfs(@"%d",frotate);
	// 各ページヘ一括設定
	id console;
	for (console in consoles) {
		[console setFrotate:frotate];
	}
	self.view.contentMode=[console contentMode]; // これ自身にも同じ設定を入れる
	/*
	 gconsoleのFrotateを変更したときはself.contentModeも同じにする
	 1	RUN時に固定	RUN以降BREAK/ENDまで画面回転を無効にする
	 2	随時縦固定	いつでも回転し、縦横比を維持しながら縦を画面に収める(def.)
	 Aspect fit
	 ただし、横スタートと縦スタートで基本画面縦横比が変わる
	 0	随時幅合わせ	いつでも回転し、幅も合わせる；設定禁止
	 Scale to fit
	 */
}

// 各ページの表示ON/OFF
// page  : ?CONSOLE(1~)
// onoff : ON=表示
-(void)vpage:(int)page onoff:(BOOL)onoff
{
	printSelf();
	nslog(@"vpage%d=O%@",page,onoff? @"N":@"FF");
	id console=[self getConsole:page];
	nslog(@"console=%@",console);
	[console setHidden2:!onoff]; // hiddenはonoffの逆

#if 0
	// ここでこれを発行してしまうと、[console start]実行まで＝context確定前に[sconsole setFspriteBGDisp]が走ってしまうのでだめ
	if (page==SCONSOLE) {
		// スプライトの時は、この設定をスプライト関数にも渡す
		sConsole *sc=(sConsole *)console;
		sc.fspriteBGDisp=onoff;
	}
#endif
}

// vpriority s,t,g0,g1,g2,g3 1〜5 優先順位番号小さいほど上。デフォルトは1,2,3,4,5,6
// 画面間優先順位の設定
// p?=0〜5:?CONSOLE=ページ番号
// リターン値 : YES=正常終了 , NO=重複有り
-(BOOL)vpriority:(int)p0 p1:(int)p1 p2:(int)p2 p3:(int)p3 p4:(int)p4 p5:(int)p5
{
	printSelf();
	nslog(@"vpriority:%d,%d,%d,%d,%d,%d",p0,p1,p2,p3,p4,p5);
	// [優先順位]=page
	// 配列に代入
	int pp[MAX_CONSOLES]={KCONSOLE,p0,p1,p2,p3,p4,p5}; // kConsoleは常に最高優先順位
	
	// 指定チェック
	int i,j;
	for (i=0;i<MAX_CONSOLES;i++) {
		for (j=0;j<MAX_CONSOLES;j++) {
			if (i==j) continue;
			if (pp[i]==pp[j]) return (NO); // 重複有り
		}
	}
	// layer.zPositionは数値が大きいほど前に出てくる
	// 優先順位の低いものから数値を入れる
	// *10で入れているのは、間を調整できるようにするため
	// ここで優先順位を設定するので、RunViewController上で設定された優先順位は無効になる
	j=0;
	for (i=MAX_CONSOLES-1;i>=0;i--) {
		id console=[self getConsole:pp[i]];
		//
		if ([console isKindOfClass:[kConsole class]]) {
			nslog(@"kconsole=%d",j);
			_kconsole.layer.zPosition=j;
			[_kconsole update];
		} else {
			Console *cons=(Console *)console;
			cons.layer.zPosition=j;
			nslog(@"console=%d:%@",j,cons);
			[cons update];
		}
		j+=10;
		nslog(@"(%d)pp=%d:%@",i,pp[i],console);
		priority[i]=pp[i];
	}
	nslog(@"capturedImageView.layer.zPosition");
	// 常にこれを最高優先順位にする(現在はcapturedImageView=キー画面であり、それ最高優先順位なので)
	// そうでないと、終了時にキー画面をキャプチャーしたcapturedImageViewが消えてしまう
	_capturedImageView.layer.zPosition=j;
	//
#if 0 // 不要
	if (![NSThread isMainThread]) {
		// これはメインスレッド(実行直前)からも実行中(サブスレッド)からも呼ばれることがあり、メインにいるときは更新処理は必要ない
		nslog(@"vpriority update(in sub thread");
		[self update];
	}
#endif
	//
	return (YES);
}

//---------------------------------------------------------------------------------------------

#if 0
-(void)update
{
	printSelf();
	[self performSelectorOnMainThread:@selector(update_)
						   withObject:nil
						waitUntilDone:NO];
}

- (void)update_
{
	@autoreleasepool { // 別スレッドのお約束
	printSelf();
	[self.view.layer display]; // これだけで良い
	[self.view setNeedsDisplay];
	}
}
#endif

//---------------------------------------------------------------------------------------------
// UI制御
//---------------------------------------------------------------------------------------------

// ボタン操作
// 現在はtoolbarだけど従来はnaviだったのでその名前のまま
-(IBAction)naviButtonAction:(id)sender
{
	UIBarButtonItem *btn=(UIBarButtonItem *)sender;
	printSelfs(@":UIBarButtonItem=%d",(int)btn.tag);
	if (btn.tag!=MODE_DISPLAY) {
		clickSound();
	}
	switch (btn.tag) {
		case MODE_DEBUG: // デバッグ画面表示 v3.20
			nslog(@"Debug");
			if (varDumpView.hidden==YES) {
				// 消えている時は表示
				[self displayDebug:MODE_DEBUG_RUN];
			} else {
				// 表示しているときは消す
				[self hideDebugScreen];
			}
			break;
		case MODE_RUN: // RUN時のBREAK
			nslog(@"Run→Break");
			// RUN中のBREAK=実行停止
			_fBreak=YES;
			break;
		case MODE_END: // 実行画面/デバッグ画面表示閉じ
			nslog(@"MODE_END");
			// 消すのは自分自身
			_rootView.editorView.frunAfter=YES;
			[self dismissViewControllerAnimated:YES completion:NULL];
			[self hideDebugScreen]; // デバッグ画面が開いていた時は消す(これをしないと、次回表示時に一瞬見えてしまう)
			break;
		case MODE_RERUN:// RUN後のRERUN
			// ここに1回来ているということはコンパイルエラーはないということ
			nslog(@"Break→ReRun");
			xb_compile();
			[self run];
		case MODE_DISPLAY:
			// 何もしない
			break;
	}
}

//---------------------------------------------------------------------------------------------
// 実行＆表示
//---------------------------------------------------------------------------------------------

static BOOL _fBreak=NO;
// BREAKボタンが押された印 → XBに渡すため関数にしている
int checkBreakIniOS(void)
{
	return (_fBreak);
}

// 実行
// ここはメインスレッド
-(void)run
{
	printSelf();
	[self stopIndicator];
	//
	[self setCLoseButton:NO];
	[self setBreakButton:MODE_RUN];
	_capturedImageView.hidden=YES; // 外部でキャプチャーされる画面はここでは非表示
	
	// X-BASIC実行
	nslog(@"runBasic→バックグラウンドへ");
	[self performSelectorInBackground:@selector(runBasic) withObject:nil];
}

// 実行(バックグラウンド)
-(void)runBasic
{
	printSelf();
	@autoreleasepool { // 不要かもしれないけど、別スレッド実行のでのお約束
//		runView=self;	// XB外部関数のためにselfのアドレスを保存	-> initで代入
		tcons=tconsole;
		_fBreak=NO;		// Breakはなしから開始
		[self setLogoAlert:nil message:@""]; // ロゴボタンによる表示は標準設定に戻す

		Setup *setup=getAppDelegate().setup;
		operationStatus.programName=nsStringTocString(setup.basicFileOnly); // これはアドレス参照なので、グローバルには有効ではないので注意；コンパイル前に代入しているのにここでも入れているのはそのせい
		nslog(@"プログラム名=%@",@(operationStatus.programName));

		nslog(@"xb_interpreter");
		xb_interpreter(); // サブタスクはこの中を回り続けている
		// end/stop/BREAK/エラーで返ってくる
		
		nslog(@"xb_end");
		[self startIndicator];
		//
		// xb_end()の中で画面が確定することもあるので、ここで画面キャプチャーしてもダメ
		//
		xb_end(NO); // 終了処理
		//
		[self updateDebugScreen]; // debug画面更新
		//
		[self stopIndicator];
	}

	// 実行回数+1
	_runCount++;

	if (errorCnt>0) {
		nslog(@"実行時エラーがあった:%d個",errorCnt);
		// RootViewに戻す または alertViewを表示するには必ずメインスレッドでなければならない
		[self performSelectorOnMainThread:@selector(displayError) withObject:nil waitUntilDone:NO];
	}
#if 1	// v2.5
	// 画面更新はメインスレッドで実行しなければいけないようなので、一旦メインスレッドに渡す
	[self performSelectorOnMainThread:@selector(redispDisplayRun)
						   withObject:nil
						waitUntilDone:YES];	// 命令終了を待つ
#else
	// 実行後画面表示にする
	nslog(@"実行後画面");
	[self displayRun:MODE_RERUN];
#endif
}

// メインスレッドで表示するエラー
-(void)displayError
{
	@autoreleasepool { // 別スレッドのお約束
		[self dismissViewControllerAnimated:YES completion:NULL];
		// rootView内のエラー表示処理を呼び出す
		[_rootView performSelector:@selector(displayError) withObject:nil];
	}
}

//---------------------------------------------------------------------------------------------

// 実行画面表示(mode付き)
-(void)displayRun:(int)mode
{
	printSelf();
//	printSelfs(@"%d",mode);
	[self stopIndicator];
	[self setCLoseButton:YES];
	[self setBreakButton:mode];
	_capturedImageView.hidden=NO; // 外部でキャプチャーされた画面を表示
}

// 実行画面表示;ActionSheetから
-(void)displayRun
{
	printSelf();
	[self hideDebugScreen]; // デバッグ画面も表示できるようにする
	[self displayRun:MODE_DISPLAY];
}

// 実行後画面表示にする
-(void)redispDisplayRun
{
	@autoreleasepool { // 別スレッドのお約束
		printSelf();
		[self displayRun:MODE_RERUN];
	}
}

//-------------------------------------------------------------------
// 印刷処理
//-------------------------------------------------------------------

-(void)printClose
{
	printSelf();
	[airPrint close];
}

#ifdef DEBUG
// 印刷設定画面が表示された後に呼び出される
- (void)printInteractionControllerDidPresentPrinterOptions:(UIPrintInteractionController *)printInteractionController
{
	printSelf();
}
#endif

// 印刷設定画面が、印刷開始で消えるときに呼び出される
// closeでは呼び出されないので注意
- (void)printInteractionControllerDidDismissPrinterOptions:(UIPrintInteractionController *)printInteractionController
{
	printSelf();
}

// 印刷開始時に呼び出される
- (void)printInteractionControllerWillStartJob:(UIPrintInteractionController *)printInteractionController
{
	printSelf();
	// 設定画面はこの時点で自動的に閉じるので、通常閉じ処理は必要ない
}

// 印刷終了時に呼び出される
// プリンタースプーラーに処理が渡ればすぐに呼び出される（＝実印刷終了を待つわけではない）
// 印刷設定画面がcloseで消された時も呼び出される(重要）
- (void)printInteractionControllerDidFinishJob:(UIPrintInteractionController *)printInteractionController
{
	printSelf();
}

// imageハードコピーのメインスレッド実行部
-(void)printImage_:(UIImage *)image
{
	printSelf();

	@autoreleasepool { // 不要かもしれないけど、別スレッド実行のでのお約束
		airPrint=[[AirPrint alloc]init];
		[airPrint initPrintInView:self.view]; // 渡しているのは、プリンターコントロールを表示するビュー（位置）のみ
		airPrint.delegate=self;
		[airPrint setItem:(id)image jobName:@""]; // 面倒なのでタイトルはなし
	// setItemは画面表示するとすぐに戻ってきてここに来るので、ここではprintCloseで画面を閉じてはいけない

//	finputDone=NO;	// 入力中;KVOを発生させないためself.にしない
	}
}

// imageハードコピー
-(void)printImage:(UIImage *)image
{
	printSelf();
	[self performSelectorOnMainThread:@selector(printImage_:)
					   withObject:image
					waitUntilDone:YES];	// 命令終了を待つ
}

//---------------------------------------------------------------------------------------------
// 他処理
//---------------------------------------------------------------------------------------------

-(void)startIndicator
{
	printSelfs(@"cnt=%d",cntActivityIndicator);
	if (cntActivityIndicator++==0) {// 多重処理対応
		indicator=[UIActivityIndicatorView show:self.view style:UIActivityIndicatorViewStyleWhiteLarge fbackground:YES];
	} // 多重処理対応
}

-(void)stopIndicator
{
	printSelfs(@"%d",cntActivityIndicator);
	if (cntActivityIndicator>0) {
		if (--cntActivityIndicator==0) {
			[indicator dismiss];
		} // 多重処理対応
	}
}

//----------------------------------------------------------------------------------------------
// アラート表示	v3.20
//----------------------------------------------------------------------------------------------
// V3.2でNaviではなくToolbarに変更したのでタイトルが表示されなくなった。
// そのためタイトルロゴをボタンで表示するようにしたので、それを押した時の処理

-(IBAction)logoButton:(id)sender
{
	if (_logoAlertTitle!=nil && _logoAlertMessage!=nil) {
		UIAlertView *aview=[[UIAlertView alloc]initWithTitle:_logoAlertTitle
													 message:_logoAlertMessage
													delegate:self
										   cancelButtonTitle:NSLocalStr(@"CLOSE")
										   otherButtonTitles:nil,nil];
		setAlertViewResize(aview); // リサイズ設定
		[aview show]; // 表示したらすぐ帰ってくる
	}
}

// ロゴボタンを押した時アラートで表示する文字列を設定する
-(void)setLogoAlert:(NSString *)title message:(NSString *)message
{
	if (title==nil) {
		// title設定がない
		// title=nil && message!=nil で標準設定 , title=nil && message=nilで表示禁止
		if (message!=nil) {
			// 標準に戻す
			_logoAlertTitle=@"-- X-BASIC' --";
			_logoAlertMessage=[NSString stringWithFormat:
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
							   @"%@ : %s\n"
								,
							   NSLocalStr(@"VERSION_CORE")			,VERSION_CORE,
							   NSLocalStr(@"VERSION_IOS_INTERFACE")	,VERSION_IOS_INTERFACE,
							   NSLocalStr(@"VERSION_XBFUNC")		,VERSION_XBFUNC,
							   NSLocalStr(@"VERSION_XBFUNC2")		,VERSION_XBFUNC2,
							   NSLocalStr(@"VERSION_XBFILEFUNC")	,VERSION_XBFILEFUNC,
							   NSLocalStr(@"VERSION_XBIOSFUNCT")	,VERSION_XBIOSFUNCT,
							   NSLocalStr(@"VERSION_XBIOSFUNCG")	,VERSION_XBIOSFUNCG,
							   NSLocalStr(@"VERSION_XBIOSFUNCK")	,VERSION_XBIOSFUNCK,
							   NSLocalStr(@"VERSION_XBIOSFUNCS")	,VERSION_XBIOSFUNCS,
							   NSLocalStr(@"VERSION_XBIOSFUNCM")	,VERSION_XBIOSFUNCM,
							   NSLocalStr(@"VERSION_XBIOSFUNCA")	,VERSION_XBIOSFUNCA,
							   NSLocalStr(@"VERSION_XBIOSFUNCSP")	,VERSION_XBIOSFUNCSP,
							   NSLocalStr(@"VERSION_XBIOSFUNCX68")	,VERSION_XBIOSFUNCX68,
							   NSLocalStr(@"VERSION_XBIOSFUNCCARD")	,VERSION_XBIOSFUNCCARD,
							   NSLocalStr(@"VERSION_XBIOSFUNCMUSIC"),VERSION_XBIOSFUNCMUSIC
							   ];
							   ;
			return;
		}
	} else {
		// title設定がある
		if (message==nil) {
			message=@"";
		}
	}
	_logoAlertTitle=title;
	_logoAlertMessage=message;
}

-(void)setAlert:(NSString *)title message:(NSString *)message 
{
	if (title==nil) title=@"";
	if (message==nil) message=@"";
	UIAlertView *aview=[[UIAlertView alloc]initWithTitle:title
												 message:message
												delegate:self
									   cancelButtonTitle:NSLocalStr(@"CLOSE")
									   otherButtonTitles:nil,nil];
	setAlertViewResize(aview); // リサイズ設定
	[aview show]; // 表示したらすぐ帰ってくる
}


//----------------------------------------------------------------------------------------------
// varDump関連 v3.20
//----------------------------------------------------------------------------------------------

// 初期化
-(void)initDebug
{
	printSelf();
	// デバッグ画面を消す
	varDumpView.hidden=YES;
	//
	[varDumpCtrlView setWaku:[UIColor redColor] width:1.0];
	
	// ここのほうがdebugTextへのアクセスはviewDidLoadより前にもあるので、ここでクリアしてはいけない
//	// クリア
//	self.debugText=@"";
}

// 変数デバッグ画面表示
// mode=MODE_DEBUG_*
-(void)displayDebug:(NSInteger)mode
{
	printSelf();
	
	switch (mode) {
		case MODE_DEBUG_RUN:
			varDumpStepper.value=
			varDumpTextView.alpha=0.7;
			btnVarDumpClear.hidden=NO;
			break;
			
		case MODE_DEBUG_ACTIONSHEET:
			[self stopIndicator];
			[self setDebugButton:NO];
			[self setCLoseButton:YES];
			[self setBreakButton:MODE_DEBUG];
			varDumpTextView.alpha=0.9; // わざわざデバッグ画面を見るのだから濃く
			// クリアボタンは消す
			btnVarDumpClear.hidden=YES;
			break;
	}
	// デバッグ画面表示
	varDumpView.hidden=NO;
	varDumpTextView.text=debugTextMain; // この時内容を入れる
	nslog(@"debufg=%@",self.debugText);
}

-(void)hideDebugScreen
{
	printSelf();
	// 表示しているときは消す
	varDumpView.hidden=YES;
	[self setDebugButton:YES];
}

// getter
-(NSString *)debugText
{
	printSelf();
	return (NSString *)debugTextMain;
}

// setter
// 文字列置き換え
-(void)setDebugText:(NSString *)debugText
{
	printSelf();
	if (debugText==nil) {
		// 何故かnilで来ることがあるので対策
		nslog(@"debugText=nil");
		// 表示しない
		return;
	}
	if (debugTextMain!=nil) {
		// 前のがあるときは前のを開放
		debugTextMain=nil;
	} else {
		// =nil
		nslog(@"初回代入");
	}
	debugTextMain=[[NSMutableString alloc]initWithString:debugText];
	nslog(@"debugText=%@",debugTextMain);
	// デバッグ画面を開いたまま再実行した時のため更新処理を入れる
	[self updateDebugScreen];
}

// デバッグ情報追加
-(void)addDebugText:(NSString *)text
{
	printSelf();
	[debugTextMain appendString:text];
	nslog(@"debugText=%@",debugTextMain);
	// デバッグ画面を開いたまま再実行した時のため更新処理を入れる
	[self updateDebugScreen];
}

// クリアボタン押下
-(IBAction)varClearBtn:(UIButton *)btn
{
	printSelf();
	self.debugText=@"";
}

// デバッグ画面更新
-(void)updateDebugScreen
{
	printSelf();
	@autoreleasepool {
		if (varDumpCtrlView.hidden==NO) { // デバッグ画面表示中の時
			// メインスレッドで更新しなければらならないので
			[self performSelectorOnMainThread:@selector(updateDebugScreen_) withObject:nil waitUntilDone:NO];
		}
	}
}

-(void)updateDebugScreen_
{
	varDumpTextView.text=self.debugText; // この時内容を入れる
}

// 透明度変更
-(IBAction)updateStepper:(UIStepper *)stepper
{
	printSelf();
	varDumpTextView.alpha=stepper.value;
}

//---------------------------------------------------------------------------------------------
// 外部から呼び出される関数
//---------------------------------------------------------------------------------------------
// 必要な場所でプロトタイプ宣言して使うこと
// xb.mの中に置きたいが、ヘッダーがエラーを出すのでこちらに置く

// 以下関数
static	RunViewController	*runView;	// =selfはrunBasicで行われている
static	tConsole			*tcons;

// selfアドレスを返す
RunViewController *xb_getRunView(void)
{
	return (runView); // 関数なのでselfは使えない
}

// strは外部でUTF8に変換しておくこと
// ここで変換したほうが集約できるが、すでに外部で行われているので今はとりあえずそのまま
BOOL printus(UByte *str)
{
	printFunc();
	nslog(@"\x22%@\x22(len=%ld)\n",@((char *)str),bstrlen(str)); // @()は日本語対応のため
	@autoreleasepool { // これを外すとCFStringが増え続ける(Leak);極めて重要
		BOOL ret=[tcons print:uCstringToNSString(str)];
		return (ret);
	}
}

//---------------------------------------------------------------------------------------------
// 画面回転
//---------------------------------------------------------------------------------------------

// 回転検出：回転前
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
	printSelfs(@"%d",(int)interfaceOrientation);
	understandOrientation(interfaceOrientation); // 画面方向を記録
	// interfaceOrientationは新しい方向
	switch (interfaceOrientation) {
		default:
		case UIInterfaceOrientationPortrait:
		case UIInterfaceOrientationPortraitUpsideDown:
			nslog(@"縦方向");
			break;
		case UIInterfaceOrientationLandscapeLeft:
		case UIInterfaceOrientationLandscapeRight:
			nslog(@"横方向");
			break;
	}
}

// 画面を回転して良いかどうか
-(BOOL)shouldAutorotate
{
	printSelf();
	return shouldAutorotateByMain();
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
	printSelf();
	return (supportedInterfaceOrientationsByMain());
}

//---------------------------------------------------

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)dealloc
{
	printSelf();

	// key-value通知解除
	[self removeObserver:tconsole forKeyPath:OBSERVE_WIDTHX];
	[self removeObserver:tconsole forKeyPath:OBSERVE_WIDTHY];
	[self removeObserver:tconsole forKeyPath:OBSERVE_FONTWY];
	[self removeObserver:tconsole forKeyPath:OBSERVE_FONTWX];
	[self removeObserver:tconsole forKeyPath:OBSERVE_FONT];
	//
	for (id console in consoles) {
		[self removeObserver:console forKeyPath:OBSERVE_IMAGE];
		if ([console isKindOfClass:[gConsole class]]
		 || [console isKindOfClass:[sConsole class]]
		) { // gConsole/sConsole
			[self removeObserver:console forKeyPath:OBSERVE_ANIME];
		}
		 // オブジェクトも解放
	}
	//
}

//----------------------------------------------------------------------------------------------

@end
