package jongs;

import java.util.Vector ;
import java.util.HashMap ;
import java.util.Stack ;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.IOException;


// 
// JONGS - Java Open Novels Game Script
// 
//    JongScripter.java 
//
//  Copyright 2007  DENZI TOMIZKA
//
//  ver 1.00 Create by DENZI TOMIZKA 2007.5.25
//  ver 1.01           DENZI TOMIZKA 2007.5.26
//  ver 1.02           DENZI TOMIZKA 2007.5.28
//  ver 1.03           DENZI TOMIZKA 2007.5.31
//  ver 1.04           DENZI TOMIZKA 2007.6.02
//
/*
 *-----------------------------------------------------------------------
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *----------------------------------------------------------------------
 */


public class JongScripter extends Thread {	
	//判断文処理系のコード
	public final static int LGK_and		= 1;
	public final static int LGK_or		= 2;

	//変数型のコード
	public final static int TYPE_int   =  100 ;
	public final static int TYPE_str   =  200 ;
	
	//基本処理系のコード
	public final static int CMD_if					= 1001;
	public final static int CMD_else					= 1002;
	public final static int CMD_while					= 1003;
	public final static int CMD_for					= 1004;
	public final static int CMD_goto					= 1005;
	public final static int CMD_gosub					= 1006;
	public final static int CMD_goScript				= 1007;
	public final static int CMD_return				= 1008;
	public final static int CMD_begin		   			= 1009;
	public final static int CMD_end					= 1010;
	public final static int CMD_set					= 1011;
	public final static int CMD_exit					= 1012;
	public final static int CMD_input					= 1013;
	public final static int CMD_switch				= 1014;
	public final static int CMD_case					= 1015;
	public final static int CMD_label					= 1016;
	public final static int CMD_break					= 1017;
	public final static int CMD_continue				= 1018;
	public final static int CMD_text					= 1019;
	public final static int CMD_WaitText				= 1020;
	public final static int CMD_print					= 1021;
	
	
	//一般処理系のコード
	public final static int CMD_setCellNumber			= 2001;
	public final static int CMD_setCellImage			= 2002;
	public final static int CMD_setCellPosition		= 2003;
	public final static int CMD_setCellSize			= 2004;
	public final static int CMD_setCellTransColor		= 2005;
	public final static int CMD_setCellFlag			= 2006;
	public final static int CMD_setCellCanvas			= 2007;
	public final static int CMD_setCellTextParam		= 2008;
	public final static int CMD_setCellText			= 2009;
	public final static int CMD_setShiftView			= 2010;
	public final static int CMD_setShiftHide			= 2011;
	public final static int CMD_viewDisplay			= 2012;
	public final static int CMD_transitionDisplay		= 2013;
	public final static int CMD_setDisplaySize		= 2014;
	public final static int CMD_wait					= 2015;
	public final static int CMD_setFontColor			= 2016;
	public final static int CMD_setFont				= 2017;
	public final static int CMD_setTextArea			= 2018;
	public final static int CMD_setTextInterval		= 2019;
	public final static int CMD_select				= 2020;
	public final static int CMD_setSelectArea			= 2021;
	public final static int CMD_setSelectColor		= 2022;
	public final static int CMD_midiPlay				= 2023;
	public final static int CMD_midiLoad				= 2024;
	public final static int CMD_midiStop				= 2025;
	public final static int CMD_audioPlay				= 2026;
	public final static int CMD_audioLoop				= 2027;
	public final static int CMD_audioStop				= 2028;
	public final static int CMD_clipLoop				= 2029;
	public final static int CMD_clipStop				= 2030;
	public final static int CMD_setWaitTime			= 2031;
	public final static int CMD_cellClick				= 2032;
	public final static int CMD_debug					= 2033;
	public final static int CMD_display				= 2034;
	public final static int CMD_save		 			= 2035;
	public final static int CMD_load		 			= 2036;
	public final static int CMD_random				= 2037;
	public final static int CMD_abs					= 2038;
			

	Vector < Vector<String> > scriptParams ;
	Vector <int[]> scriptCode ;
	int scriptPointer ;
	HashMap <String , int[] > typeMap , basicMap, cmdMap , labelMap  ;
	HashMap <String , Object > varIntMap ,varStrMap ;
	Stack <int[]> parStack , subroutineStack;

	
	int th_wtime ;
	int debug  ;
	String Text;

	//キー入力用
    BufferedReader bread ;
    //現在解析中の行
    String now_Line;
    	
    //画面及び画面管理
    jongsDisplayManagement dmng; 
    
    jongsSound sound ;
	
	public JongScripter() {
		super("JONGS");
		//キー入力用バッファードリーダー作成
		this.bread = new BufferedReader(new InputStreamReader(System.in));
		//変数格納先をクリア
		varIntMap = new HashMap <String , Object >() ;
		varStrMap = new HashMap <String , Object >() ;
		//基本処理系の表を登録
		this.initBasicCode();
		//コマンドとコードの対比表登録
		this.initCommandCode();
		//最初のスクリプトを分解登録する
		//this.getScript(FIRST_script);
		th_wtime = 0;
		debug = 0 ;
		Text = "";
		
		//サウンド管理系を初期化
		sound = new jongsSound();
	}
	
	
	/**
	 *型・基本処理系予約語の登録 
	 */
	private void initBasicCode() {		
		//型名の登録
		typeMap = new HashMap <String , int[] >() ;	
		typeMap.put("int", this.getIntArray(TYPE_int) );
		typeMap.put("integer", this.getIntArray(TYPE_int) );
		typeMap.put("str", this.getIntArray(TYPE_str) );
		typeMap.put("string", this.getIntArray(TYPE_str) );

		//基本処理系予約語の登録
		basicMap = new HashMap <String , int[] >() ;
		basicMap.put("if", this.getIntArray(CMD_if) );
		basicMap.put("else", this.getIntArray(CMD_else) );
		basicMap.put("while", this.getIntArray(CMD_while) );
		basicMap.put("for", this.getIntArray(CMD_for) );
		basicMap.put("goto", this.getIntArray(CMD_goto) );
		basicMap.put("gosub", this.getIntArray(CMD_gosub) );
		basicMap.put("goscript", this.getIntArray(CMD_goScript) );
		basicMap.put("return", this.getIntArray(CMD_return) );
		basicMap.put("begin", this.getIntArray(CMD_begin) );
		basicMap.put("end", this.getIntArray(CMD_end) );
		basicMap.put("set", this.getIntArray(CMD_set) );
		basicMap.put("exit", this.getIntArray(CMD_exit) );
		basicMap.put("input", this.getIntArray(CMD_input) );
		basicMap.put("switch", this.getIntArray(CMD_switch) );
		basicMap.put("case", this.getIntArray(CMD_case) );
		basicMap.put("label", this.getIntArray(CMD_label) );
		basicMap.put("break", this.getIntArray(CMD_break) );
		basicMap.put("continue", this.getIntArray(CMD_continue) );
		basicMap.put("text", this.getIntArray(CMD_text) );
		basicMap.put("waittext", this.getIntArray(CMD_WaitText) );
		basicMap.put("print", this.getIntArray(CMD_print) );
		basicMap.put("printf", this.getIntArray(CMD_print) );
	}
	
	
	/**
	 *コマンドとコードの対比表を登録 
	 */
	private void initCommandCode(){
		cmdMap = new HashMap <String , int[]>();

		cmdMap.put("setcellnumber", this.getIntArray(CMD_setCellNumber) );
		cmdMap.put("setcellimage", this.getIntArray(CMD_setCellImage) );
		cmdMap.put("setcellposition", this.getIntArray(CMD_setCellPosition) );
		cmdMap.put("setcellsize", this.getIntArray(CMD_setCellSize) );
		cmdMap.put("setcelltranscolor", this.getIntArray(CMD_setCellTransColor) );
		cmdMap.put("setcellflag", this.getIntArray(CMD_setCellFlag) );
		cmdMap.put("setcellcanvas", this.getIntArray(CMD_setCellCanvas) );
		cmdMap.put("setcelltextparam", this.getIntArray(CMD_setCellTextParam) );
		cmdMap.put("setcelltext", this.getIntArray(CMD_setCellText) );
		cmdMap.put("setshiftview", this.getIntArray(CMD_setShiftView) );
		cmdMap.put("setshifthide", this.getIntArray(CMD_setShiftHide) );
		cmdMap.put("viewdisplay", this.getIntArray(CMD_viewDisplay) );
		cmdMap.put("transitiondisplay", this.getIntArray(CMD_transitionDisplay) );
		cmdMap.put("showimage", this.getIntArray(CMD_viewDisplay) );
		cmdMap.put("setdisplaysize", this.getIntArray(CMD_setDisplaySize) );
		cmdMap.put("wait", this.getIntArray(CMD_wait) );
		cmdMap.put("setfontcolor", this.getIntArray(CMD_setFontColor) );
		cmdMap.put("settextfont", this.getIntArray(CMD_setFont) );
		cmdMap.put("setfont", this.getIntArray(CMD_setFont) );
		cmdMap.put("settextarea", this.getIntArray(CMD_setTextArea) );
		cmdMap.put("settextinterval", this.getIntArray(CMD_setTextInterval) );
		cmdMap.put("select", this.getIntArray(CMD_select) );
		cmdMap.put("setselectarea", this.getIntArray(CMD_setSelectArea) );
		cmdMap.put("setselectcolor", this.getIntArray(CMD_setSelectColor) );
		cmdMap.put("midiload", this.getIntArray(CMD_midiLoad) );
		cmdMap.put("midiplay", this.getIntArray(CMD_midiPlay) );
		cmdMap.put("midistop", this.getIntArray(CMD_midiStop) );
		cmdMap.put("audioloop", this.getIntArray(CMD_audioLoop) );
		cmdMap.put("audioplay", this.getIntArray(CMD_audioPlay) );
		cmdMap.put("audiostop", this.getIntArray(CMD_audioStop) );
		cmdMap.put("soundloop", this.getIntArray(CMD_audioLoop) );
		cmdMap.put("soundplay", this.getIntArray(CMD_audioPlay) );
		cmdMap.put("soundstop", this.getIntArray(CMD_audioStop) );
		cmdMap.put("cliploop", this.getIntArray(CMD_clipLoop) );
		cmdMap.put("clipstop", this.getIntArray(CMD_clipStop) );
		cmdMap.put("setwaittime", this.getIntArray(CMD_setWaitTime) );
		cmdMap.put("cellclick", this.getIntArray(CMD_cellClick) );
		cmdMap.put("debug", this.getIntArray(CMD_debug) );
		cmdMap.put("display", this.getIntArray(CMD_display) );
		cmdMap.put("save", this.getIntArray(CMD_save) );
		cmdMap.put("load", this.getIntArray(CMD_load) );		
		cmdMap.put("random", this.getIntArray(CMD_random) );
		cmdMap.put("abs", this.getIntArray(CMD_abs) );
		
		
		/* コマンド定義ファイルを読み込む処理はとりあえずなし
		try {
			FileInputStream fis = new FileInputStream("./"+CMD_file);
			InputStreamReader isr = new InputStreamReader(fis , "MS932");
			BufferedReader br = new BufferedReader(isr);
			while ( (line= br.readLine()) != null ) {
				line = line.trim();
				if ( line.length() == 0 ) continue ;
				if ( line.charAt(0) == '#') continue ;
				if ( line.charAt(0) == '/' && line.charAt(1) == '/' ) continue ;
				st = new StringTokenizer(line ,",= :",false);
				cmd = st.nextToken().trim().toLowerCase();
				cmdMap.put(cmd , this.getIntArray(Integer.parseInt(st.nextToken() ,10)) );
				//System.err.println("Command:"+cmd+" / "+code[0]+"/"+cmdMap.get(cmd).toString());
			}
			isr.close();
			fis.close();
		} catch (Exception e) {
		}*/
		
		return ;
	}

	
	/**
	 * スクリプトを読み込み分解し、ラベルとコードとパラメータにする
	 * @param scfile
	 */
	public void getScript(String scfile,String txtcode) {
		String line  , label ;
		Vector <String> vct0 , vct1 , vct2;
		int code , pos , bpos , epos , funcpos , fcode;
		//スクリプト初期化
		scriptParams = new Vector < Vector<String> > () ;
		scriptCode = new Vector <int[]> () ;
		scriptPointer = 0 ;
		//ラベル初期化
		labelMap = new HashMap <String,int[]> () ;
		//Begin'{'End'{'スタック初期化
		parStack = new Stack <int[]> () ;
		//Gosub Returnスタック初期化
		subroutineStack = new Stack <int[]> () ;

		//スクリプトファイルを読む
		try {
			FileInputStream fis = new FileInputStream("./"+scfile);
			System.out.println("JONGS GetScript:"+"./"+scfile+":CODE:"+txtcode);
            InputStreamReader isr = new InputStreamReader(fis, txtcode);
			BufferedReader br = new BufferedReader(isr);
			while ( (line= br.readLine()) != null ) {
				line = line.trim();
				if ( line.length() == 0 ) continue ;
				//一行のスクリプトを分解し登録する
				this.setScriptOneLine(line) ;
			}
			isr.close();
			fis.close();
		} catch (Exception e) {
			Error(8,"スクリプトファイル["+scfile+"]を読み込めません");
		}

		//{ }のない if else for while に　{　}を付加する
		for (pos = 0 ; pos < this.scriptCode.size() ; pos++ ) {
			code = this.scriptCode.get(pos)[0];
			switch (code) {
			case CMD_if:
			case CMD_else:
			case CMD_while:
			case CMD_for:
				bpos = pos+1 ;
				if ( bpos == this.scriptCode.size() ) break ;
				code = this.scriptCode.get(bpos)[0];
				// if else for while　の次が {でない場合
				if (code != CMD_begin) {
					
					this.scriptCode.add(pos+2,this.getIntArray(CMD_end));
					vct0 = new Vector <String> ();
					vct0.add("end");
					this.scriptParams.add(pos+2,vct0);					

					this.scriptCode.add(pos+1,this.getIntArray(CMD_begin));
					vct0 = new Vector <String> ();
					vct0.add("begin");
					this.scriptParams.add(pos+1,vct0);					
				}
				
				break ;
			default :
				break ;
			}
		}
		
		//ラベルを登録する
		for (pos = 0 ; pos < this.scriptCode.size() ; pos++ ) {
			code = this.scriptCode.get(pos)[0];
			if ( code == CMD_label ){
				vct0 = this.scriptParams.get(pos);
				label = vct0.get(1);
				if ( label.length() > 0 ) {
					if ( this.labelMap.containsKey(label) ) 
						this.Error(8, "ラベル["+label+"]が重複しています。");	
					this.labelMap.put(label, this.getIntArray(pos));
				}
			}
		}
		

		//スクリプト全体の{(begin) }(end)の対応づけをする
		this.parStack.clear();
		for (pos = 0 ; pos < this.scriptCode.size() ; pos++ ) {
			code = this.scriptCode.get(pos)[0];
			if ( code == CMD_begin ) {
				this.parStack.push(this.getIntArray(pos));
			} else if ( code == CMD_end ) {
				//スクリプト内に{がないのに}が登場した
				if ( this.parStack.size() == 0) 
					this.Error(8, "スクリプトの｛｝の対応がとれていません、｝が多いようです");
				bpos = this.parStack.pop()[0];
				epos = pos ;
				funcpos = bpos - 1 ;
				
				//{}の処理機能を得る
				if ( funcpos < 0 ) 
					this.Error(8, "｛｝の記述位置が不正です");
				
				//{(begin)には }(end)を指させる
				vct1 = this.scriptParams.get(bpos);
				vct1.add( Integer.toString(epos) );
				
				//}(end)には {(begin)を指させる
				vct2 = this.scriptParams.get(epos);
				vct2.add( Integer.toString(bpos) );

				//(begin)(end)を統括する機能コマンドを複写
				vct0 = this.scriptParams.get(funcpos);
				fcode = this.scriptCode.get(funcpos)[0];
				//機能名
				vct1.add( vct0.get(0) ) ;
				vct2.add( vct0.get(0) ) ;
				if ( fcode == CMD_while ) {
					if ( vct0.size() < 2 )
						this.Error(8, "WHILE文の構文に誤りがあります。");
					vct2.add( vct0.get(1) ) ;
				} else if ( fcode == CMD_for ) {
					if ( vct0.size() < 4 )
						this.Error(8, "FOR文の構文に誤りがあります。");
					vct2.add( vct0.get(2) ) ;					
					vct2.add( vct0.get(3) ) ;										
				}
			}
		}
		//スクリプト内に}が不足
		if ( this.parStack.size() > 0) {
			this.scriptPointer = this.parStack.pop()[0];
			this.Error(8, "スクリプトの｛｝の対応がとれていません。}が不足です");
		}
				
		return ;		
	}

	
	/**
	 * 一行のスクリプトを分解し認識する
	 * @param ln
	 */
	private void setScriptOneLine(String ln) {
		int rpos , pos , pos1 , pos2  ;
		int [] bcode;
		String line , label , token1 , token2 , token3;
		Vector <String> vc;

		now_Line = line = ln.trim() ;
		if ( line.length() == 0 ) return ;		
		//一行中の注釈を削除する
		if ( ( rpos = line.indexOf("//") ) >= 0 ) {
			line = line.substring(0,rpos); 
			line = line.trim() ;
			if ( line.length() == 0 ) return ;
		}
		//一行中の注釈を削除する
		if ( ( rpos = line.indexOf(";") ) >= 0 ) {
			line = line.substring(0,rpos); 
			line = line.trim() ;
			if ( line.length() == 0 ) return ;
		}
		
		//ラベルとCASE文を登録する
		if ( ( pos = line.indexOf(':') ) > 0 ) {
			label = line.substring(0,pos).trim();			
			//CASE文か？
			pos2 = label.indexOf(' ');
			if ( pos2 < 0 ) pos2 = label.indexOf('\t');		
			if ( pos2 > 0  ){
				token1 = label.substring(0,pos2).toLowerCase();
				if ( basicMap.get(token1)[0] == CMD_case ) {
					token2 = label.substring(pos2).trim();
					this.scriptCode.add(basicMap.get(token1));
					this.scriptParams.add(this.getParams(token1+","+token2));
					line = line.substring(pos+1).trim();
					//CASE文の後ろに構文が存在すれば解析を継続する
					//if ( line.length() == 0 ) return ;
					if (line.length() > 0 ) setScriptOneLine(line);
					return ;
				} else {
					Error(16,"ラベルに空白やTABの含まれる文字を使用できません["+line+"]");
				}
			} else {
				//ラベルとして登録する（位置は未確定）
				token1 = "label";
				token2 = line.substring(0,pos).trim();
				this.checkLabelName(token2);
				this.scriptCode.add(basicMap.get(token1));
				this.scriptParams.add(this.getParams(token1+","+token2));
				line = line.substring(pos+1).trim();
				//ラベルの後ろに構文が存在すれば解析を継続する
				//if ( line.length() == 0 ) return ;
				if (line.length() > 0 ) setScriptOneLine(line);
				return ;				
			}
		}
		
		//{をbeginとする
		if ( line.charAt(0) == '{' ) {
			token1 = "begin" ;
			this.scriptCode.add(basicMap.get(token1));
			vc = new Vector <String> ();
			vc.add(token1);
			this.scriptParams.add(vc);
			line = line.substring(1).trim();
			if (line.length() > 0 ) setScriptOneLine(line);
			return ;
		}
		
		//}をendとする
		if ( line.charAt(0) == '}' ) {
			token1 = "end" ;
			this.scriptCode.add(basicMap.get(token1));
			vc = new Vector <String> ();
			vc.add(token1);
			this.scriptParams.add(vc);			
			line = line.substring(1).trim();
			if (line.length() > 0 ) setScriptOneLine(line);
			return ;
		}		
		
		//変数宣言文がないか調べる
		pos = line.indexOf(' ');
		if ( pos < 0 ) pos = line.indexOf('\t');
		pos2 = line.indexOf('(');
		//一行中に'('がなく半角空白もしくはTABがあれば宣言文ではないかとアタリをつける。
		if ( pos > 0 && ( pos2 < 0 || pos < pos2 ) ) {
			token1 = line.substring(0,pos).trim().toLowerCase();
			//先頭の文字列が変数型に存在するかどうかで宣言の有無を判断する。
			if (typeMap.containsKey(token1)) {
				//変数の登録
				token2 = line.substring(pos).trim();
				this.VarResist(token2,typeMap.get(token1)[0]);
				return ;
			} else if( basicMap.containsKey(token1) ) {
				//一つ目のトークンが基本処理系の予約語だった場合
				bcode = basicMap.get(token1);
				//elseの場合
				if ( bcode[0] == CMD_else ) {
					//行コードをスクリプトに登録する
					this.scriptCode.add(bcode);					
					this.scriptParams.add( this.getParams(token1) );
					token3 = line.substring(pos).trim();
					if (token3.length() > 0 ) setScriptOneLine(token3);
					return  ;
				}
			}
		}

		//一行中の解析
		//System.out.println("setScriptOneLine:"+line);
		pos1 = line.indexOf('(');
		if ( pos1 > 0 ) {
			//(の手前のコマンドを取り出す
			token1 = line.substring(0,pos1).trim().toLowerCase();
			pos2 = this.ParenthesesIndexOf(line, pos1 , '(', ')' );
			//パラメータを取り出す
			token2 = line.substring(pos1+1,pos2);
			if ( basicMap.containsKey(token1) ) {
				//一つ目のトークンが基本処理系の予約語だった場合
				//行コードをスクリプトに登録する
				this.scriptCode.add(basicMap.get(token1));
				this.scriptParams.add( this.getParams(token1+","+token2));
				//基本処理系の後は継続して次の行と見なす
				if ( pos2 > 0 && pos2 < line.length()) {
					token3 = line.substring(pos2+1).trim();
					if (token3.length() > 0 )
						setScriptOneLine(token3);	
				}	
				return  ;
			} else if ( cmdMap.containsKey(token1) ) {
				//一つ目のトークンがコマンドの予約語だった場合
				//その行コードをスクリプトに登録する
				this.scriptCode.add(cmdMap.get(token1));
				this.scriptParams.add( this.getParams(token1+","+token2) );
				return  ;
			}
		} else {
			pos1 = line.indexOf('{');
			if ( pos1 < 0 ) pos1 = line.length();
			token1 = line.substring(0,pos1).trim().toLowerCase();
			if ( basicMap.containsKey(token1) ) {
				//一つ目のトークンが基本処理系の予約語だった場合
				//行コードをスクリプトに登録する
				this.scriptCode.add(basicMap.get(token1));
				this.scriptParams.add( this.getParams(token1));
				//基本処理系の後は継続して次の行と見なす
				if ( pos1 > 0 && pos1 < line.length()) {
					token3 = line.substring(pos1).trim();
					if (token3.length() > 0 )
						setScriptOneLine(token3);	
				}	
				return  ;
			}			
		}
		
		if ( this.isSubstitution(line) ) {
			//代入処理の特徴が見出せるならば、基本コマンドの代入文として扱う
			token1 = "set";
			this.scriptCode.add(basicMap.get(token1));
			vc = new Vector <String> ();
			vc.add(token1);
			vc.add(line);
			this.scriptParams.add(vc);
		} else {
			//全てに引っかからなければスクリプトの台詞と解釈する
			token1 = "text";
			this.scriptCode.add(basicMap.get(token1));
			vc = new Vector <String> ();
			vc.add(token1);
			vc.add(line);			
			this.scriptParams.add(vc);
		}
		
		return  ;
	}

	
	/**
	 * 文字列がラベル名として適切か否か判断する
	 * @param lblstr
	 */
	private void checkLabelName (String lblstr) {
		String cannotUseChar = "!\"#$%&'()*+,-./:;<=>?[\\]^`{|}~";
		int n ;
		String lbl = lblstr.trim();
		if (this.labelMap.containsKey(lbl))
			Error(8,"ラベル["+lblstr+"]は重複しています。");
		if (this.basicMap.containsKey(lbl))
			Error(8,"ラベル["+lblstr+"]は予約語であり登録できません。");
		if (this.cmdMap.containsKey(lbl))
			Error(8,"ラベル["+lblstr+"]は予約語であり登録できません。");
		if (this.typeMap.containsKey(lbl))
			Error(8,"ラベル["+lblstr+"]は予約語であり登録できません。");
		for ( n = 0 ; n < lbl.length() ; n++ ) {
			if ( cannotUseChar.indexOf(lbl.charAt(n)) > -1 ) 
				Error(8,"ラベルに使用してはならない文字が使用されています。["+lblstr+"]");
		}
	}
	
	/**
	 * 文字列が変数名として適切か否か判断する
	 * @param lblstr
	 */
	private void checkVariableName (String vstr) {
		String cannotUseChar = "!\"#$%&'()*+,-./:;<=>?[\\]^`{|}~";
		int n ;
		String var = vstr.trim();
		if (this.varIntMap.containsKey(var))
			Error(8,"変数名["+var+"]は重複しています。");
		if (this.varStrMap.containsKey(var))
			Error(8,"変数名["+var+"]は重複しています。");
		if (this.basicMap.containsKey(var))
			Error(8,"変数名["+var+"]は予約語であり登録できません。");
		if (this.cmdMap.containsKey(var))
			Error(8,"変数名["+var+"]は予約語であり登録できません。");
		if (this.typeMap.containsKey(var))
			Error(8,"変数名["+var+"]は予約語であり登録できません。");
		if ( '0' <= var.charAt(0) && var.charAt(0) <= '9')
			Error(8,"変数名の先頭に半角数字が使用されています。["+var+"]");			
		for ( n = 0 ; n < var.length() ; n++ ) {
			if ( cannotUseChar.indexOf(var.charAt(n)) > -1 ) 
				Error(8,"変数名に使用してはならない文字が使用されています。["+var+"]");
		}
	}
	
	
	
	/**
	 * この行が代入文かどうか予想し判定する
	 * @param line
	 * @return
	 */
	private boolean isSubstitution(String line) {
		int pos0 , pos1 ;
		String token;
		
		//代入演算子の存在可能性を探る
		pos0 = line.indexOf('=');
		//System.out.println("isSubstitution:"+line+":"+pos0);
		/*
		if ( pos0 < 0 ) pos0 = line.indexOf("++");
		if ( pos0 < 0 ) pos0 = line.indexOf("--");
		if ( pos0 < 0 ) pos0 = line.indexOf("+=");
		if ( pos0 < 0 ) pos0 = line.indexOf("-=");
		if ( pos0 < 0 ) pos0 = line.indexOf("*=");
		if ( pos0 < 0 ) pos0 = line.indexOf("/=");
		if ( pos0 < 0 ) pos0 = line.indexOf("%=");
		*/
		
		//代入演算子がある
		if (pos0 > 0) {
			//配列変数かも
			pos1 = line.indexOf('[');
			if ( pos1 > 0 && pos1 < pos0 ) {
				pos0 = pos1 ;
			}
			
			//代入されているのが宣言された変数かどうか判定する
			token = line.substring(0,pos0).trim();
			if ( this.varIntMap.containsKey(token) ) return true ;
			if ( this.varStrMap.containsKey(token) ) return true ;	
		}
		
		return false ;
	}
	
	
	/**
	 * 変数を登録する
	 * @param line
	 * @param varkind
	 */
	private void VarResist(String line , int varkind) {
		int n , pos , epos ;
		int vmat ;
		String varName , var  , vl ;
		Vector <String> vc = this.getParams(line);
		
		for (n = 0 ; n < vc.size() ; n++) {
			var = vc.get(n);
			varName = var ;
			vmat = 0 ;
			if ( var.indexOf('[') > 0 ) {
				pos = var.indexOf('[');
				varName = var.substring(0,pos).trim();
				//[]のペアをとる
				epos = this.ParenthesesIndexOf(var, pos , '[', ']');
				vl = var.substring(pos+1,epos);
				//[]の数値を得る
				vmat = this.Calc(vl) ;
			}
			
			//変数として宣言できない変数名の場合はエラーとする
			this.checkVariableName(varName);
			
			//型毎の処理
			switch ( varkind ) {
			case TYPE_int:								
				switch (vmat) {
				
				case 0:
					int [] intVar0 = new int[1];
					this.varIntMap.put(varName, intVar0);
					break ;
				
				default :
					int [] intVar1 = new int[vmat];
					this.varIntMap.put(varName, intVar1);				
					break ;
				
				}
				break ;
			
			case TYPE_str:				
				switch (vmat) {
				case 0:
					String [] strVar0 = new String[1];
					varStrMap.put(varName, strVar0);				
					break ;
				
				default :
					String [] strVar1 = new String[vmat];
					varStrMap.put(varName, strVar1);				
					break ;
				
				}
				break ;
			
			}
		}		
	}
	
	
	/**
	 * []で区切られた文字列を分解しVectorにして返す
	 * @param var
	 * @return
	 */
	public Vector <String> getArrayMatrixParams(String var) {
		Vector <String> vc = new Vector <String>() ;
		String token ;
		int pos , pos1  ;
		pos = var.indexOf('[');
		
		//[]で区切られた要素はない
		if ( pos < 0 ) {
			vc.add(var.trim());
			return vc ;
		}

		//第一要素をVectorに格納する
		token = var.substring(0,pos).trim();
		vc.add(token);
		
		while ( pos > 0 ) {
			//'['に対応する']'の位置を見つける
			pos1 = this.ParenthesesIndexOf(var, pos, '[', ']');
			if (pos1 == -1 ) this.Error(8, "[]の対応がとれていません["+var+"]");
			token = var.substring(pos+1,pos1);
			vc.add(token);
			pos = var.indexOf('[',pos1);
		}
		
		return vc ;
	}

	
	/**
	 * ,で区切られたパラメータ文字列を分解しVectorにして返す
	 * @param pline
	 * @return
	 */
	private Vector <String> getParams(String pline) {
		StringTokenizer st ;
		Vector <String>params = new Vector <String>();
		st = new StringTokenizer(pline ,",",false);
		while (st.countTokens() > 0) 
			params.add( st.nextToken().trim() ) ;
		return params;
	}
	

	private Vector <String> stringToVector(String pline , String pt) {
		Vector <String> vct = new Vector <String>();
		int pb , pe , ptlen ;
		
		ptlen = pt.length();
		pb = 0 ;
		
		while ( ( pe = pline.indexOf(pt,pb) ) >= 0) {
			vct.add(pline.substring(pb,pe));
			pb = pe + ptlen  ;
		}
		vct.add(pline.substring(pb) );
		
		return vct;
	}
	
	
	/**
	 * 	現在のスクリプトの状態を表示(デバッグ用)
	 *
	 */
	public void outScriptState() {
		Object [] keys;
		
		System.err.println("----------------------------");
		System.err.println("----- JONG Script State-----");
		System.err.println("----------------------------");
		
		System.err.println("★基本型★");
		keys = this.typeMap.keySet().toArray();
		for ( int n = 0 ; n < keys.length ; n ++  ) {
			System.err.print("KEY:"+keys[n]);
			System.err.println(" CODE:"+this.typeMap.get(keys[n])[0]);
		}		
		System.err.println();
		
		System.err.println("★基本コマンド★");
		keys = this.basicMap.keySet().toArray();
		for ( int n = 0 ; n < keys.length ; n ++  ) {
			System.err.print("KEY:"+keys[n]);
			System.err.println(" CODE:"+this.basicMap.get(keys[n])[0]);
		}		
		System.err.println();
		
		System.err.println("★登録コマンド★");
		keys = this.cmdMap.keySet().toArray();
		for ( int n = 0 ; n < keys.length ; n ++  ) {
			System.err.print("KEY:"+keys[n]);
			System.err.println(" CODE:"+this.cmdMap.get(keys[n])[0]);
		}		
		System.err.println();
		
		System.err.println("★ラベル★");
		keys = this.labelMap.keySet().toArray();
		for ( int n = 0 ; n < keys.length ; n ++  ) {
			System.err.print("KEY:"+keys[n]);
			System.err.println(" CODE:"+this.labelMap.get(keys[n])[0]);
		}		
		System.err.println();

		System.err.println("★スクリプト★");
		for ( int n = 0 ; n < this.scriptCode.size() ; n ++  ) {
			int [] code  = this.scriptCode.get(n);
			Vector vct = this.scriptParams.get(n);
			String cs = "0000"+code[0] ;
			String ln = "000"+n ;
			System.err.print(ln.substring(ln.length()-3));
			System.err.print(" Cmd:"+cs.substring(cs.length()-4));
			System.err.println(" Param["+vct.size()+"]"+vct.toString());
		}	
	}
	
	
	/**
	 * 	代入演算子の左辺に右辺を代入する
	 * @param line
	 */
	private void setVariable(String line) {
		int pos0 ;
		String varName , param ;
		//代入演算子の位置を得る
		pos0 = line.indexOf('=');
		
		varName = line.substring(0,pos0);
		param = line.substring(pos0+1).trim();
		if ( this.isIntVar(varName) ) {
			this.setVarIntValue(varName, this.Calc(param));			
		} else if ( this.isStrVar(varName) ) {
			this.setVarStrValue(varName, this.getStrValue(param));						
		}
	}

	/**
	 * 文字列で表現される１項目だけの数値を返却する
	 * @param intstr
	 * @return
	 */
	private int getIntValue(String intstr) {
		int value ;
		String str = intstr.trim();
		if ( this.isIntVar(str) ) {
			//変数ならば値を返す
			return getVarIntValue(str);
		} else {
			//そうでなければ数値として返す
			value = strToInt(str) ;
			if ( value != 0 ) return value ;
			if ( str.charAt(0) != '0') {
				this.Error(8,"["+str+"]という数値型の変数は存在しません");
			}
			return 0;		
		}
	}
		
	/**
	 * スクリプト文字列で表現される文字列を返却
	 * @param scrtext
	 * @return
	 */
	private String getStrValue(String scrtext) {
		String str = scrtext.trim();
		char tc = str.charAt(0);
		if ( tc == '+' ) str = str.substring(1);
		
		if ( this.isStrVar(str) )
			str = this.getVarStrValue(str);
		else if ( this.isIntVar(str) )
			str = ""+ this.getVarIntValue(str) ;
		else if ( str.indexOf('+') >= 0 ) 
			str = this.strToStr(str);
		else {
			if ( str.charAt(0) == '\"' && str.charAt(str.length()-1)== '\"') 
				str = str.substring(1,str.length()-1);  
		}
		
		if ( tc == '+' ) str = "+" + str;

		return str;
	}

	
	/**
	 * 文字列の+結合処理を行い返却
	 * @param str
	 * @return
	 */
	private String strToStr(String str) {
		String text , token;
		StringTokenizer st ;
		st = new StringTokenizer(str ,"\"+",false);
		text = "";
		while ( st.hasMoreTokens() ) {
			token = st.nextToken();
			if ( this.isIntVar(token) ) {
				text = text + this.getIntValue(token);
			} else if ( this.isStrVar(token) ) { 
				text = text + this.getVarStrValue(token);
			} else {
				text = text + token ;
			}
		}
		return text;
	}
	
	/**
	 * １６進数の文字列なら１６進数を返す。
	 * １０進の文字列なら１０進数を返す。
	 * そうでなければ0を返す
	 * @param str
	 * @return
	 */
	private int strToInt (String str) {
		int DataVAL = 0 ;
		String DataStr ;
		if ( str.length() == 0 ) return 0;
		if ( str.charAt(0) == '-' ||  str.charAt(0) == '+' )
			DataStr = str.substring(1);
		else 
			DataStr = str ;
		try {
			if ( DataStr.length() > 2 && DataStr.charAt(0)=='0' &&  DataStr.charAt(1)=='x' ){
				DataVAL =Integer.parseInt( DataStr.substring(2) ,16);
			} else if ( DataStr.charAt(0) >= '0' &&  DataStr.charAt(0) <= '9' ){
				DataVAL =Integer.parseInt( DataStr , 10 );
				//System.out.print("strToInt:"+DataStr+"="+ DataVAL);
			} else DataVAL = 0 ;
		} catch(NumberFormatException murle) {
			return 0;
		}
		
		if ( str.charAt(0) == '-') DataVAL = -DataVAL ;	
		return DataVAL ;
	}

	/**
	 * 数値型変数の値を返す
	 * @param str
	 * @return
	 */
	private int getVarIntValue(String str) {
		int [] varMat ;
		int m ;
		Vector <String> vc = this.getArrayMatrixParams(str);
		varMat = (int []) this.varIntMap.get(vc.get(0).trim());
		if (varMat == null) this.Error(8, "変数"+vc.get(0).trim()+"は存在しません。");
		//配列でない変数
		if ( vc.size() == 1 ) return varMat[0];
	
		//1次元配列の変数
		m = this.Calc( vc.get(1) );				
		return varMat[m];
	}

	/**
	 * 文字列型変数の値を返す
	 * @param str
	 * @return
	 */
	private String getVarStrValue(String str) {
		String [] varMat ;
		int m ;
		Vector <String> vc = this.getArrayMatrixParams(str);
		varMat = (String []) this.varStrMap.get( vc.get(0).trim() ) ;
		if (varMat == null) this.Error(8, "変数"+vc.get(0).trim()+"は存在しません。");
		//配列でない変数
		if ( vc.size() == 1 ) return varMat[0];
	
		//1次元配列の変数
		m = this.getIntValue( vc.get(1) );				
		return varMat[m];
	}


	/**
	 * 数値型変数に値をセットする
	 * @param str
	 * @param val
	 */
	private void setVarIntValue(String str , int val) {
		int [] varMat ;
		int m ;
		Vector <String> vc = this.getArrayMatrixParams(str);
		varMat = (int []) this.varIntMap.get(vc.get(0).trim());
		//System.out.print("setVarIntName"+vc.get(0)+":"+varMat[0]);
		//配列でない変数
		if ( vc.size() == 1 ) {
			varMat[0] = val ;
		} else {
			//1次元配列の変数
			m = this.Calc( vc.get(1) );
			if ( m < varMat.length )
				varMat[m] = val;
			else 
				this.Error(8, "変数"+str+"の配列添字をオーバー"+m+"しました");
		}
		return ;
	}
	
	/**
	 * 文字列型変数に値をセットする
	 * @param str
	 * @param val
	 */
	private void setVarStrValue(String str , String val) {
		String [] varMat ;
		int m ;
		Vector <String> vc = this.getArrayMatrixParams(str);
		varMat = (String[]) this.varStrMap.get(vc.get(0).trim());
		//配列でない変数
		if ( vc.size() == 1 ) {
			varMat[0] = val ;
		} else {
			//1次元配列の変数
			m = this.Calc( vc.get(1) );
			if ( m < varMat.length )
				varMat[m] = val;
			else 
				this.Error(8, "変数"+str+"の配列添字をオーバー"+m+"しました");
		}
		return ;
	}

	
	/**
	 * 文字列が数値型変数として存在すればtrue
	 * そうでなければfalseを返す
	 * @param str
	 * @return
	 */
	private boolean isIntVar(String str) {
		String varName ;
		int pos ;
		if ( str.length() == 0 ) return false ;
		pos = str.indexOf('[');
		if ( pos > 0 ) varName = str.substring(0,pos).trim() ;
		else varName = str.trim() ;
		return  this.varIntMap.containsKey(varName);
	}

	/**
	 * 文字列が文字型変数として存在すればtrue
	 * そうでなければfalseを返す
	 * @param str
	 * @return
	 */
	private boolean isStrVar(String str) {
		String varName ;
		int pos ;
		if ( str.length() == 0 ) return false ;
		pos = str.indexOf('[');
		if ( pos > 0 ) varName = str.substring(0,pos).trim() ;
		else varName = str.trim() ;
		//System.out.println("\nisStrVar:"+varName);
		return  this.varStrMap.containsKey(varName);
	}

	/**
	 * 文字列を計算式として認識し、計算結果を返す
	 * @param calcStr
	 * @return
	 */
	public int Calc ( String calcStr ){
		int ans = 0;
		if ( calcStr.indexOf('(') < 0 ) {
			//System.out.print("Calc:" +calcStr);
			ans = singleCalc(calcStr) ;
		} else {
			ans = parenthesesCalc(calcStr);
		}
		return ans;
	}
	
	
	/**
	 * 文字列を()でくくられた要素のある計算式として認識し、計算結果を返す
	 * @param str
	 * @return
	 */
	public int parenthesesCalc( String str ) {
		int ans = 0;
		int pos0 , pos1 , n , val0 ;
		Vector <String> cObj  ;
		Vector <int[]> valObj  ;
		String opeObj , objStr ;
		String calcStr = str.trim();
		char c ;
		
		String operator = "+-*/%";
		if ( calcStr.charAt(0) == '-' ) 
			calcStr = "0"+str.trim() ;
				
		cObj = new Vector <String> () ;
		opeObj = "";
		pos0 = pos1 = 0 ;
		
		while (  pos1 < calcStr.length()  ) {
			c = calcStr.charAt(pos1);
			if ( operator.indexOf(c) >= 0) {
				objStr = calcStr.substring(pos0,pos1).trim() ;
				if ( objStr.charAt(0) == '(' ) {
					objStr = objStr.substring(1,objStr.length()-1).trim();
				}
				cObj.add( objStr );
				pos0 = pos1 + 1;
				opeObj = opeObj + calcStr.substring(pos1,pos0) ;
			} else if ( c == '(' ) {
				//()内文字列はとばす
				pos1 = this.ParenthesesIndexOf(calcStr, pos1 , '(', ')');
			} else if ( c == '[' ) {
				//配列変数の[]内文字列はとばす
				pos1 = this.ParenthesesIndexOf(calcStr, pos1 , '[', ']');
			} 
			pos1 ++ ;
		}
		cObj.add(calcStr.substring(pos0,pos1).trim() );		

		valObj = new Vector <int[]> () ;
		for ( n = 0 ; n < cObj.size() ; n++ ) {
			val0 = Calc( cObj.get(n) );
			valObj.add(this.getIntArray(val0));
		}

		ans = this.vectorCalc(valObj, opeObj);
		
		return ans;
		
	}
	
	/**
	 * 文字列を複数要素のある計算式として認識し、計算結果を返す
	 * @param str
	 * @return
	 */
	private int singleCalc( String str ) {
		int ans = 0;
		int pos0 , pos1 , n , val0 ;
		Vector <String> cObj  ;
		Vector <int[]> valObj  ;
		String opeObj ;
		String calcStr = str.trim();
		char c ;
		
		String operator = "+-*/%";
		
		if ( calcStr.charAt(0) == '-' ) calcStr = "0"+str.trim() ;
				
		cObj = new Vector <String> () ;
		opeObj = "";
		pos0 = pos1 = 0 ;
		
		while (  pos1 < calcStr.length()  ) {
			c = calcStr.charAt(pos1);
			if ( operator.indexOf(c) >= 0) {
				cObj.add(new String( calcStr.substring(pos0,pos1) ) );
				pos0 = pos1 + 1;
				opeObj = opeObj + calcStr.substring(pos1,pos0) ; ;
			} else if ( c == '[' ) {
				//配列変数の[]内文字列は無視する
				pos1 = this.ParenthesesIndexOf(calcStr, pos1 , '[', ']');
			}
			pos1 ++ ;
		}
		cObj.add(new String( calcStr.substring(pos0,pos1).trim() ) );
				
		valObj = new Vector <int[]> () ;
		for ( n = 0 ; n < cObj.size() ; n++ ) {
			val0 = this.getIntValue(cObj.get(n));
			valObj.add(this.getIntArray(val0));
		}
		ans = this.vectorCalc(valObj, opeObj);
		return ans;	
	}

	
	/**
	 * 四則演算を行う
	 * @param valObj 計算上の数値要素
	 * @param opeObj 計算上の演算子
	 * @return
	 */
	private int vectorCalc(Vector <int[]> valObj ,String opeObj) {
		int n , val0 , val1 , ans , ans0 ;
		char [] oplst ;
		char c;
		
		oplst = opeObj.toCharArray();
		// * / % 
		for ( n = 0 ; n < oplst.length ; n++ ) {
			c = oplst[n];
			switch (c) {
			case '*':
				val0 = valObj.get(n)[0];
				val1 = valObj.get(n+1)[0];
				ans0 = val0 * val1 ;
				valObj.get(n)[0] = valObj.get(n+1)[0] = ans0 ;
				oplst[n] = ' ';
				break ;
			case '/':
				val0 = valObj.get(n)[0];
				val1 = valObj.get(n+1)[0];
				ans0 = val0 / val1 ;
				valObj.get(n)[0] = valObj.get(n+1)[0] = ans0 ;
				oplst[n] = ' ';
				break ;
			case '%':
				val0 = valObj.get(n)[0];
				val1 = valObj.get(n+1)[0];
				ans0 = val0 % val1 ;
				valObj.get(n)[0] = valObj.get(n+1)[0] = ans0 ;
				oplst[n] = ' ';
				break ;
			}
		}
		for ( n = oplst.length-1 ; n >= 0 ; n-- ) { 
			if (oplst[n] == ' ') {
				valObj.get(n)[0] = valObj.get(n+1)[0] ;
			}
		}
	
		for ( n = 0 ; n < oplst.length ; n++ ) {
			c = oplst[n];
			switch (c) {
			case '+':
				val0 = valObj.get(n)[0];
				val1 = valObj.get(n+1)[0];
				ans0 = val0 + val1 ;
				valObj.get(n)[0] = valObj.get(n+1)[0] = ans0 ;
				oplst[n] = ' ';
				break ;
			case '-':
				val0 = valObj.get(n)[0];
				val1 = valObj.get(n+1)[0];
				ans0 = val0 - val1 ;
				valObj.get(n)[0] = valObj.get(n+1)[0] = ans0 ;
				oplst[n] = ' ';
				break ;
			case ' ':
				valObj.get(n+1)[0] = valObj.get(n)[0];
				break ;
			}
		}
		ans = valObj.get(valObj.size()-1)[0];		
		return ans;	
	}

	
	
	
	/**
	 * 文字列表現を比較式として判断し、判断結果を返す
	 * @param judgeStr
	 * @return
	 */
	private boolean judge ( String judgeStr ){
		boolean rjudge = false ;
		if (judgeStr.indexOf("&&") > 0 || judgeStr.indexOf("||") > 0 ) {
			rjudge = someJudge(judgeStr);			
		} else {
			rjudge = singleJudge(judgeStr);
		}
		return rjudge;
	}
	
	
	
	/**
	 * 複数の比較式による判断結果を返す
	 * @param str
	 * @return
	 */
	private boolean someJudge ( String str ){
		Vector<String> vct = new Vector<String>();
		String token ;
		StringBuffer opeObj ;
		int pos0 , pos1 , n ;
		char [] opeArray;
		boolean [] logicArray ;
		boolean rjudge , flg0;
	
		opeObj = new StringBuffer();

		//&&もしくは||で区切られた文字列を分解し、Vector化
		for ( pos0 = pos1 = 0 ; pos1 < str.length() ; pos1++ ) {
			switch ( str.charAt(pos1)) {
			case '(' :
				pos1 = this.ParenthesesIndexOf(str, pos1, '(' ,')');
				break ;
			case '[' :
				pos1 = this.ParenthesesIndexOf(str, pos1, '[' ,']');
				break ;
			case '"' :
				pos1 = this.ParenthesesIndexOf(str, pos1, '"' ,'"');
				break ;
			case '&' :
				if ( str.charAt(pos1+1) == '&' ) {
					token = str.substring(pos0,pos1).trim();
					if ( token.length() > 2 && token.charAt(0) == '(' && token.charAt(token.length()-1) == ')') {
						token = token.substring(1,token.length()-1).trim();
					}
					if ( token.length() > 0 ) {
						vct.add(token);
						pos0 = pos1 = pos1 + 2;					
					}
				}
				opeObj.append('&');
				break ;
				
			case '|' :
				if ( str.charAt(pos1+1) == '|' ) {
					token = str.substring(pos0,pos1).trim();
					if ( token.length() > 2 && token.charAt(0) == '(' && token.charAt(token.length()-1) == ')') {
						token = token.substring(1,token.length()-1).trim();
					}
					if ( token.length() > 0 ) {
						vct.add(token);
						pos0 = pos1 = pos1 + 2;					
					}
				}
				opeObj.append('|');
				break ;
				
			}
		}
		//最後の要素を登録する
		token = str.substring(pos0,pos1).trim();
		if ( token.length() > 2 && token.charAt(0) == '(' && token.charAt(token.length()-1) == ')') {
			token = token.substring(1,token.length()-1).trim();
		}
		if ( token.length() > 0 ) {
			vct.add(token);
			pos0 = pos1 = pos1 + 2;					
		}
				
		opeArray = opeObj.toString().toCharArray();
		logicArray = new boolean[vct.size()];
		
		//Vectorの全要素のロジックを取り出す
		for ( n = 0 ; n < vct.size() ; n ++ ) {
			logicArray[n] = this.judge(vct.get(n));
		}
				
		for ( n = 0 ; n < opeArray.length ; n ++ ) {
			if ( opeArray[n] == '&') {
				flg0 = logicArray[n] && logicArray[n+1];
				logicArray[n] = logicArray[n+1] = flg0 ;
			} else if ( opeArray[n] == '|') {
				flg0 = logicArray[n] && logicArray[n+1];
				logicArray[n] = logicArray[n+1] = flg0 ;
			}
		}
		
		rjudge =  logicArray[opeArray.length];
		
		return rjudge ;
	}
	
	
	
	/**
	 * 単一の比較式による結果を返す
	 * @param judgeStr
	 * @return
	 */
	private boolean singleJudge( String judgeStr ) {
		int w , pos , type ;
		String left , right ;
		int lintval , rintval ;
		String lstrval , rstrval ;
		boolean judge = false ;
		String jstr ;
		
		if ( judgeStr.trim().charAt(0) == '!' ) 
			jstr = judgeStr.substring(1).trim();
		else 
			jstr = judgeStr.trim();
		
		w = 2; pos= jstr.indexOf("=="); type = 0; 
		if ( pos < 0 ) { w = 2;pos = jstr.indexOf("!=");type = 1;}
		if ( pos < 0 ) { w = 2;pos = jstr.indexOf("=!");type = 2;}
		if ( pos < 0 ) { w = 2;pos = jstr.indexOf("<=");type = 3;}
		if ( pos < 0 ) { w = 2;pos = jstr.indexOf("=<");type = 4;}
		if ( pos < 0 ) { w = 2;pos = jstr.indexOf(">=");type = 5;}
		if ( pos < 0 ) { w = 2;pos = jstr.indexOf("=>");type = 6;}
		if ( pos < 0 ) { w = 1;pos = jstr.indexOf("<");type = 7;}
		if ( pos < 0 ) { w = 1;pos = jstr.indexOf(">");type = 8;}
		
		if ( pos < 0 ) {
			this.Error(8,"比較の記述に誤りがあります。");
		}
		
		left = jstr.substring(0,pos).trim();
		right = jstr.substring(pos+w).trim();
				
		if ( this.isStrVar(left) || this.isStrVar(right) ) {
			//文字列の比較
			lstrval = this.getStrValue(left);
			rstrval = this.getStrValue(right);
			if ( type == 0 ) judge = lstrval.equals(rstrval);
			else judge = ! lstrval.equals(rstrval);			
		} else {
			//数値の比較
			lintval = this.Calc(left);
			rintval = this.Calc(right);
			
			switch (type) {
			case 0:
				judge = ( lintval == rintval );
				break ;
			case 1:
			case 2:
				judge = ( lintval != rintval );
				break ;
			case 3:
			case 4:
				judge = ( lintval <= rintval );
				break ;
			case 5:
			case 6:
				judge = ( lintval >= rintval );
				break ;
			case 7:
				judge = ( lintval < rintval );
				break ;
			case 8:
				judge = ( lintval > rintval );
				break ;
			}
		}	

		if ( judgeStr.trim().charAt(0) == '!' )
			judge = !judge ;
		
		return judge ;
		
	}

	

		
	/**
	 * 	intをint[1]の形式にし、オブジェクトとして扱えるようにする
	 * @param cd
	 * @return
	 */
	private int[] getIntArray (int cd) {
		int [] code = new int[1];
		code[0] = cd ;
		return code ;
	}
	

	/**
	 * 文字列中のかっこのペアの対応をとる。
	 * @param S 文字列
	 * @param n 文字列開始位置
	 * @param begin 括弧の始まり文字
	 * @param end 括弧の終了文字
	 * @return
	 */
	private int ParenthesesIndexOf(String S, int n , char begin , char end)
	{
		int n0 ,n1 ,len ;
		len = S.length();
		for ( n0 = 0,  n1 = n; n1 < len ; n1++ )
		{	
			if ( S.charAt(n1) == begin ) n0++ ;
			else if ( S.charAt(n1) == end )
			{
				n0-- ;
				if ( n0 == 0 ) return n1 ;
			}
		}
		this.Error(8,"括弧の対応がとれていません。("+S+")"); 
		return -1;
	}

	
	public String loadText(String file , String code ) {
		FileInputStream fis;
		InputStreamReader isr;
		BufferedReader br;
		String line;
		StringBuffer sb = new StringBuffer();		
		try {
			fis = new FileInputStream("./"+file);
			isr = new InputStreamReader(fis, code);
			br = new BufferedReader(isr);
			
			sb = new StringBuffer();
			while ( (line= br.readLine()) != null ) {
				line = line.trim();
				sb.append(line);
			}
			isr.close();
			fis.close();
		} catch (Exception e) {
			Error(8,"ファイル["+file+"]を読み込めません");
		}
		return sb.toString();
	}

	
	public void saveText(String file , String text , String code){
		FileOutputStream fos ;
		OutputStreamWriter osw ;
		BufferedWriter bw;
		try {
			fos = new FileOutputStream("./"+file);
			osw = new OutputStreamWriter(fos ,code);
			bw = new BufferedWriter(osw);
			bw.write(text);
			bw.close();
			osw.close();
			fos.close();
		} catch (Exception e) {
			Error(8,"ファイル["+file+"]を書き込めません");
		}
	}
	

	/**
	 * 指定された変数群の内容をファイルに保存する
	 * @param vct
	 */
	public void saveVariable( Vector vct ) {
		int n , i ,  num , pb , pe , vn ,ival[];
		StringBuffer sb = new StringBuffer();
		String file , vwk , var , vns , sval[];
		file = this.getStrValue((String) vct.get(1));
		num = vct.size() - 2;
		for ( n = 0 ; n < num ; n++ ) {
			vwk = (String) vct.get(n+2);
			//System.out.println("saveVariable:"+vwk);
			if ( ( pb = vwk.indexOf('[') ) > 0 ) {
				pe = this.ParenthesesIndexOf(vwk, pb,'[',']');
				vns = vwk.substring(pb+1, pe).trim();
				vn = this.Calc(vns);
				var = vwk.substring(0,pb);
			} else {
				vn = -1 ;
				var = vwk.trim();
			}
						
			if ( this.isIntVar(var) ) {
				ival = (int []) this.varIntMap.get(var);
				if ( vn >= 0)  {
					sb.append(ival[vn]);
					sb.append("\t");					
				} else {
					for ( i = 0 ; i < ival.length ; i++ ) {
						sb.append(ival[i]);
						sb.append('\t');					
					}
				}
			} else if (this.isStrVar(var)) {
				sval = (String []) this.varStrMap.get(var);
				if ( vn >= 0)  {
					sb.append(sval[vn]);
					sb.append('\t');					
				} else {
					for ( i = 0 ; i < sval.length ; i++ ) {
						sb.append(sval[i]);
						sb.append('\t');					
					}
				}
			} else 
				Error(8,var+"という変数は存在しません。");
			sb.deleteCharAt(sb.length()-1);
			sb.append("\n");
		}
		this.saveText(file, sb.toString() , "EUC_JP");
	}
	
	
	/**
	 * 指定された変数群にファイルから読み込んだ値をセットする
	 * @param vct
	 */
	public void loadVariable( Vector vct  ) {
		FileInputStream fis;
		InputStreamReader isr;
		BufferedReader br;
		String line , file , vname[] , vwk , var , vns , sval[];
		int n , m  , vnum[] , pb , pe , vn , ival[];
		Vector <String> vc;
		
		file = this.getStrValue((String) vct.get(1));
		vname = new String[vct.size() - 2];
		vnum = new int[vct.size() - 2];
		
		for ( n = 0 ; n < vname.length ; n++ ) {
			vwk = (String) vct.get(n+2);
			if ( ( pb = vwk.indexOf('[') ) > 0 ) {
				pe = this.ParenthesesIndexOf(vwk, pb,'[',']');
				vns = vwk.substring(pb+1, pe).trim();
				vnum[n] = this.Calc(vns);
				vname[n] = vwk.substring(0,pb);
			} else {
				vnum[n] = -1 ;
				vname[n] = vwk.trim();
			}			
			//System.out.println("loadVariable:"+vname[n]+"/"+vnum[n]);
		}
				
		try {
			fis = new FileInputStream("./"+file);
			isr = new InputStreamReader(fis, "EUC_JP");
			br = new BufferedReader(isr);
			n = 0;
			while ( (line= br.readLine()) != null && n < vname.length ) {				
				vc = this.stringToVector(line, "\t");
				//System.out.println("loadVariable:"+vc.toString());
				var = vname[n];
				vn = vnum[n];
				
				if ( this.isIntVar(vname[n]) ) {
					ival = (int []) this.varIntMap.get(var);
					if ( vn == -1 ) {
						for ( m = 0 ; m < ival.length && m < vc.size() ; m ++ ) 
							ival[m] = Integer.parseInt(vc.get(m));
					} else {
						ival[vn] = Integer.parseInt(vc.get(0));
					}
				} else if ( this.isStrVar(vname[n]) ) {
					sval = (String []) this.varStrMap.get(var);
					if ( vn == -1 ) {
						for ( m = 0 ; m < sval.length && m < vc.size() ; m ++ ) 
							sval[m] = vc.get(m);						
					} else {
						sval[vn] = vc.get(0);						
					}
				} else 
					Error(8,var+"という変数は存在しません。");
				
				n++ ;
			}
			isr.close();
			fis.close();
		} catch (Exception e) {
			Error(8,"ファイル["+file+"]を読み込めません");
		}
	}
	
	
	//
	//　スクリプトの実行
	//

	
	/**
	 * 	コンソールより文字列を入力する
	 * @param txt
	 */
	private void inputValue (String str) {
        String val = "";
		try {
	          val = bread.readLine();
		}catch(IOException e){
			this.Error(8, "キー入力に失敗");
		}
		if ( this.isStrVar(str) ) {
			this.setVarStrValue(str, val);
		} else if ( this.isIntVar(str) ) {
			this.setVarIntValue(str, this.strToInt(val));			
		}
	}
	

	/**
	 * 	ボタンで選択する
	 * @param vct 
	 */
	private void buttonSelect(Vector<String> vct ) {
		String rvect , tkn , val ;
		Vector <String> vect ;
		int n ;
		
		vect = new Vector <String>() ;
		rvect = new String( vct.get(1) );
		
		//パラメータを文字列に変換する
		for ( n = 2 ; n < vct.size() ; n++ ) {
			tkn = vct.get(n);
			val = this.strToStr(tkn);
			//System.out.println("buttonSelect:"+tkn+":"+val);
			vect.add(val);
		}
		
		dmng.setSelectParam(vect);
		//値が帰ってくるのを待つ
		this.waitDisplayExec();	
		//変数に値をセットする
		if ( this.isIntVar(rvect))
			this.setVarIntValue(rvect,dmng.getSelectButton());
		else if ( this.isStrVar(rvect))
			this.setVarStrValue(rvect,dmng.getSelectText());
	}

	/**
	 * 	ボタンで選択する
	 * @param vct 
	 */
	private void arrayButtonSelect(Vector<String> vct ) {
		String rvect ;
		rvect = new String( vct.get(1) );
		dmng.setSelectParam(vct);
		//値が帰ってくるのを待つ
		this.waitDisplayExec();	
		//変数に値をセットする
		if ( this.isIntVar(rvect))
			this.setVarIntValue(rvect,dmng.getSelectButton());
		else if ( this.isStrVar(rvect))
			this.setVarStrValue(rvect,dmng.getSelectText());
	}

	
	/**
	 * 	入力を待ちクリックしたセル番号を得て変数に格納
	 * @param vct 
	 */
	private void cellClick(Vector<String> vct ) {
		int  cellvalue  ;
		String rvect ;
		rvect = vct.get(1);
		if ( dmng.visibleCellNum() == 0 ) {
			//全セルが不可視なら変数に格納されるのは-1
			this.setVarIntValue(rvect,-1);
			return ;
		}	
		
		//画面にクリックイベントの要求をする
		//dmng.commandCode == CMD_cellclick
		dmng.cellClick();
		//どこかのセルがクリックされるまでループする
		cellvalue = -1 ;
		while (cellvalue == -1 ) {
			//イベントが帰ってくるのを待つ
			this.waitDisplayExec();
			cellvalue = dmng.getSelectCell();
		}
		//変数にセルの値をセットする
		this.setVarIntValue(rvect,cellvalue);
	}
	

	/**
	 * 画面側の処理終了を待つ
	 *
	 */
	private void waitDisplayExec() {
		while ( dmng.diaplayBusy() ) 
			this.waitMiliSec(100);
	}	

	/**
	 * スレッドを停止して時間待ち
	 * @param w
	 */
	public void waitMiliSec(int w) {
		long wait ;
		wait = (long) w;
		try { sleep(wait);} 
		catch  ( InterruptedException ie) {}
	}
	
	
	/**
	 * 	文字列を画面もしくはコンソールに出す
	 * @param txt
	 */
	private void drawText(String txt, boolean wait , int wtime) {
		String text = txt.trim();		
		if (dmng == null) {
			if ( text.charAt(0) == '+') 
				Text = text + text.substring(1);
			else
				Text = text ;
			//画面がない場合文字列をコンソールに出す
			System.out.println(Text);
		} else {
			if ( wait ) {
				//画面への出力をする。
				dmng.drawText(text);
				//dmng.commandCode = CMD_text
				//マウスクリックがあるまで待つ
				this.waitDisplayExec();				
			} else {
				//画面への出力をする
				dmng.drawWaitText(text,wtime);				
			}
		}
	}

	
	
	/**
	 * 一行のみ実行する
	 *
	 */
	private void oneLineExec () {
		int code = this.scriptCode.get(scriptPointer)[0];
		Vector <String> params = this.scriptParams.get(scriptPointer);
		Vector <String> vcs ;
		int   iwk0 , iwk1  , iwk2 , iwk3 , iwk4 , iwk5 , iwk6 , iwk7 ;
		String swk0 , swk1  ;
		boolean bwk0 ;
		
		//System.err.println(this.getName()+ ":"+ scriptPointer+ " "+ params.toString());
		
		//コマンドコード毎の分岐
		switch (code) {
		case CMD_display:
			if (params.size() == 3) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				//画面を出す
				dmng = new jongsDisplayManagement(iwk0, iwk1);
			} else {
				dmng = new jongsDisplayManagement();
			}
			scriptPointer ++ ;
			break ;
		
		
		case CMD_goto:
			if (params.size() != 2) this.Error(8,"パラメータ数が誤っています");
			//Goto文の第一パラメーターがラベルに登録されていればそこに飛ぶ
			if ( this.labelMap.containsKey(this.getStrValue(params.get(1))) ) 
				scriptPointer =  this.labelMap.get(params.get(1))[0];
			else 
				this.Error(8, this.getStrValue(params.get(1))+"というラベルはスクリプト内に存在しません。");			
			break ;
			
		case CMD_gosub:
			if (params.size() != 2) this.Error(8,"パラメータ数が誤っています");
			//Gusub文の第一パラメーターがラベルに登録されていればそこに飛ぶ
			if ( this.labelMap.containsKey(this.getStrValue(params.get(1))) ) {
				this.subroutineStack.add(this.getIntArray(scriptPointer));
				scriptPointer =  this.labelMap.get(params.get(1))[0];
			} else 
				this.Error(8, this.getStrValue(params.get(1))+"というラベルはスクリプト内に存在しません。");			
			break ;
			
		case CMD_return:
			//呼び出されたGusubの戻り先に戻る
			if ( this.subroutineStack.empty() ) 
				this.Error(8, "return文の戻り先がありません");			
			scriptPointer = this.subroutineStack.pop()[0] + 1;
			break ;
			
		case CMD_goScript:
			if (params.size() == 2) {
				swk0 = this.getStrValue(params.get(1));
				this.getScript(swk0,"EUC_JP");
			} else if (params.size() == 3) {
				swk0 = this.getStrValue(params.get(1));
				swk1 = this.getStrValue(params.get(2));
				this.getScript(swk0,swk1);
			} else {
				this.Error(8,"パラメータ数が誤っています");
			}
			scriptPointer = 0;
			break ;
			
		case CMD_text:
			if (params.size() != 2) this.Error(8,"パラメータ数が誤っています");
			swk0 = this.strToStr(params.get(1));//結合処理をする
			this.drawText(swk0,true,0); //待ちフラグＯＮで呼ぶ
			scriptPointer ++ ;
			break ;

		case CMD_print:
			if (params.size() != 2) this.Error(8,"パラメータ数が誤っています");
			swk0 = this.strToStr(params.get(1));
			System.out.println(swk0); //System.outに出す
			scriptPointer ++ ;
			break ;

		case CMD_WaitText:
			if ( params.size() == 2 ) {
				swk0 = this.getStrValue(params.get(1));
				this.drawText(swk0,false,2000);//待ちフラグＯＦＦで呼ぶ				
			} else if ( params.size() == 3 ) {
				swk0 = this.getStrValue(params.get(1));
				iwk0 = this.Calc(params.get(2));
				this.drawText(swk0,false,iwk0);//待ちフラグＯＦＦで呼ぶ
			} else {
				if (params.size() != 2) this.Error(8,"パラメータ数が誤っています");				
			}
			
			scriptPointer ++ ;
			break ;
			
			
		case CMD_input:
			if (params.size() != 2) this.Error(8,"パラメータ数が誤っています");
			this.inputValue(params.get(1));
			scriptPointer ++ ;			
			break ;

		case CMD_set:	
			this.setVariable(params.get(1));
			scriptPointer ++ ;
			break ;
			
		case CMD_if:		
			if (params.size() != 2) this.Error(8,"パラメータ数が誤っています");
			if ( judge(params.get(1)) ) {
				//式の評価結果がtrueなら{の処理だけ飛ばす
				scriptPointer ++;					
			} else {
				//式の評価結果がfalseの場合｝の次の行まで飛ばす
				vcs = this.scriptParams.get(scriptPointer+1);
				scriptPointer = Integer.parseInt(vcs.get(1)) ;
			}
			scriptPointer ++;
			break ;
		
		case CMD_while:
			if (params.size() != 2) this.Error(8,"パラメータ数が誤っています");
			if ( judge(params.get(1)) ) {
				//式の評価結果がtrueだった場合{だけ飛ばす
				scriptPointer ++;
			} else {
				//式の評価結果がfalseだった場合｝の次の行まで飛ばす
				vcs = this.scriptParams.get(scriptPointer+1);
				scriptPointer = Integer.parseInt(vcs.get(1)) ;
			}
			scriptPointer ++ ;
			break ;


		case CMD_for:
			if (params.size() != 4) this.Error(8,"パラメータ数が誤っています");
			this.setVariable(params.get(1));
			if ( judge(params.get(2)) ) {
				//論理式の評価結果がtrueだった場合 {の処理だけ飛ばす
				scriptPointer ++;
			} else {
				//論理式の評価結果がfalseだった場合｝の次の行まで飛ばす
				vcs = this.scriptParams.get(scriptPointer+1);
				scriptPointer = Integer.parseInt(vcs.get(1)) ;
			}
			scriptPointer ++ ;
			break ;

		
		case CMD_end:
			//この｝と対をなす｛の位置を得る
			iwk1 = Integer.parseInt(params.get(1));
			//この｝の所属するコードを得る
			iwk0 = this.basicMap.get(params.get(2))[0] ;
			
			switch ( iwk0 ) {
			case CMD_while :
				if ( judge(params.get(3)) ) scriptPointer = iwk1+1 ;
				else scriptPointer ++ ;				
				break ;
				
			case CMD_for :
				this.setVariable(params.get(4));
				if ( judge(params.get(3)) ) scriptPointer = iwk1+1 ;
				else scriptPointer ++ ;				
				break ;
				
			case CMD_if :
				if ( this.scriptCode.get(scriptPointer+1)[0] == CMD_else ) {
					vcs = this.scriptParams.get(scriptPointer+2);
					scriptPointer = Integer.parseInt(vcs.get(1))+1 ;
				} else {
					scriptPointer ++ ;					
				}
				break ;
				
			default :
				scriptPointer ++ ;				
			}
			
			break ;
			
		case CMD_debug:		
			if (debug == 0) debug =1 ;
			else debug = 0;
			scriptPointer ++ ;
			break ;
		
		case CMD_wait:
			if (params.size() != 2) this.Error(8,"パラメータ数が誤っています");
			iwk0 = this.Calc(params.get(1));
			if (dmng == null) this.waitMiliSec(iwk0);
			else dmng.waitMiliSec(iwk0);
			scriptPointer ++ ;			
			break ;			

			
		case CMD_random:
			if ( params.size() != 3 ) this.Error(8,"パラメータ数が誤っています");
			swk0 = params.get(1);
			if ( ! this.isIntVar(swk0) ) this.Error(8, swk0+"は整数型の変数ではありません");
			iwk0 = this.Calc(params.get(2));
			iwk2 = (int) ( Math.random() * (double ) iwk0 );
			this.setVarIntValue(swk0, iwk2);
			scriptPointer ++ ;
			break ;				
						
		case CMD_abs:
			if ( params.size() != 3 ) this.Error(8,"パラメータ数が誤っています");
			swk0 = params.get(1);
			if ( ! this.isIntVar(swk0) ) this.Error(8, swk0+"は整数型の変数ではありません");
			iwk0 = this.Calc(swk0);
			iwk2 = Math.abs(iwk0);
			this.setVarIntValue(swk0, iwk2);
			scriptPointer ++ ;
			break ;				

		case CMD_save:
			if ( params.size() < 3 ) this.Error(8,"パラメータ数が誤っています");
			this.saveVariable(params);
			scriptPointer ++ ;
			break ;							
			
		case CMD_load:
			if ( params.size() < 3 ) this.Error(8,"パラメータ数が誤っています");
			this.loadVariable(params);
			scriptPointer ++ ;
			break ;							
			
		case CMD_setCellNumber:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if (params.size() != 2) this.Error(8,"パラメータ数が誤っています");
			iwk0 = this.Calc(params.get(1));
			dmng.setCellNumber(iwk0);
			scriptPointer ++ ;				
			break ;
			
		case CMD_setCellFlag:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if (params.size() == 2) {
				swk0 = this.getStrValue(params.get(1));
				dmng.setCellView(swk0);
			} else if (params.size() == 3) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				dmng.setCellView(iwk0,iwk1);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;				
			break ;
			
		case CMD_setCellPosition:
			if (params.size() == 4) {
				iwk0 = this.Calc(params.get(1));
				swk0 = params.get(2).trim();
				//予約語 _LEFT _RIGHT _CENTERの値を得る
				iwk1 = dmng.getPositionCode(swk0);
				if ( iwk1 == 0 ) iwk1 = this.Calc(params.get(2));
				swk0 = params.get(3).trim();
				//予約語 _UPPER _LOWER _MIDDLEの値を得る
				iwk2 = dmng.getPositionCode(swk0);
				if ( iwk2 == 0 ) iwk2 = this.Calc(params.get(3));				
				dmng.setCellPosition(iwk0, iwk1, iwk2);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;				
			break ;
			
		case CMD_setCellSize:
			if (params.size() == 4) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				iwk2 = this.Calc(params.get(3));
				dmng.setCellSize(iwk0, iwk1, iwk2);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;				
			break ;
			
		case CMD_setCellImage:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 3) {
				iwk0 = this.Calc(params.get(1));
				swk0 = this.getStrValue(params.get(2));
				bwk0 = dmng.setCellImage(iwk0, swk0);
				if ( bwk0 == false ) {
					this.Error(8,"画像ファイル" + swk0 + "が読み込めません");									
				}
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;				
			break ;
				
		case CMD_setCellCanvas:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 5) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				iwk2 = this.Calc(params.get(3));
				iwk3 = this.Calc(params.get(4));
				this.dmng.setCellCanvas(iwk0, iwk1, iwk2, iwk3);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;				
			break ;

		case CMD_setCellTextParam:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 6) {
				iwk0 = this.Calc(params.get(1));
				swk0 = this.getStrValue(params.get(2));
				swk1 = this.getStrValue(params.get(3));
				iwk1 = this.Calc(params.get(4));
				iwk2 = this.Calc(params.get(5));
				this.dmng.setCellTextParameter(iwk0, swk0, swk1, iwk1, iwk2 );
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;				
			break ;
			
			
		case CMD_setCellText:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 3) {
				iwk0 = this.Calc(params.get(1));
				swk0 = this.getStrValue(params.get(2));
				this.dmng.setCellText(iwk0, swk0);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;				
			break ;
			
		case CMD_setShiftView:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 2) {
				iwk0 = this.Calc(params.get(1));
				this.dmng.setShiftView(iwk0);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;				
			break ;
			
		case CMD_setShiftHide:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 2) {
				iwk0 = this.Calc(params.get(1));
				this.dmng.setShiftHide(iwk0);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;				
			break ;
			
			
		case CMD_viewDisplay:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if (params.size() == 1) {
				dmng.viewDisplay();
			} else if ( params.size() == 2 ) {
				swk0 = this.getStrValue(params.get(1));
				dmng.viewDisplay(swk0);
			} else if ( params.size() == 3 ) {
				swk0 = this.getStrValue(params.get(1));
				swk1 = this.getStrValue(params.get(2));
				dmng.transitionDisplay(swk0,swk1);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			this.waitDisplayExec();
			scriptPointer ++ ;				
			break ;	
			
		case CMD_transitionDisplay:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if (params.size() == 2) {
				swk0 = this.getStrValue(params.get(1));
				dmng.transitionDisplay(swk0);
			} else if ( params.size() == 3 ) {
				swk0 = this.getStrValue(params.get(1));
				swk1 = this.getStrValue(params.get(2));
				dmng.transitionDisplay(swk0,swk1);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			this.waitDisplayExec();
			scriptPointer ++ ;				
			break ;	
			
		case CMD_setCellTransColor:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 3 ) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				dmng.setTransColor(iwk0, iwk1);				
			} else if ( params.size() == 4 ) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				iwk2 = this.Calc(params.get(3));
				dmng.setTransColor(iwk0, iwk1, iwk2);				
			} else if ( params.size() == 5 ) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				iwk2 = this.Calc(params.get(3));
				iwk3 = this.Calc(params.get(4));
				dmng.setTransColor(iwk0, iwk1, iwk2, iwk3);				
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;
			break ;	

		case CMD_cellClick :
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() != 2 ) this.Error(8,"パラメータ数が誤っています");
			this.cellClick(params);
			scriptPointer ++ ;
			break ;				

			
		case CMD_setDisplaySize:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 3 ) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				dmng.createDisplay(iwk0, iwk1);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;
			break ;	
			
		case CMD_setFontColor:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 2 ) {
				iwk0 = this.Calc(params.get(1));
				dmng.setFontColor(iwk0, this.anotherColor(iwk0) );
			} else if ( params.size() == 3 ) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				dmng.setFontColor(iwk0, iwk1);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			//this.waitDisplayExec();
			scriptPointer ++ ;
			break ;	
		
		case CMD_setFont:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 4 ) {
				swk0 = this.getStrValue(params.get(1));
				swk1 = this.getStrValue(params.get(2));
				iwk1 = this.Calc(params.get(3));
				dmng.setTextFont(swk0, swk1,iwk1);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			//this.waitDisplayExec();
			scriptPointer ++ ;
			break ;	

			
		case CMD_setTextInterval:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 3 ) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				dmng.setTextInterval(iwk0, iwk1);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;
			break ;	

		case CMD_setTextArea:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 5 ) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				iwk2 = this.Calc(params.get(3));
				iwk3 = this.Calc(params.get(4));
				dmng.setTextArea(iwk0, iwk1,iwk2,iwk3);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			scriptPointer ++ ;
			break ;	

			
		case CMD_setSelectArea:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 5 ) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				iwk2 = this.Calc(params.get(3));
				iwk3 = this.Calc(params.get(4));
				dmng.setSelectArea(iwk0, iwk1,iwk2,iwk3);
			} else if ( params.size() == 7 ) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				iwk2 = this.Calc(params.get(3));
				iwk3 = this.Calc(params.get(4));
				iwk4 = this.Calc(params.get(5));
				iwk5 = this.Calc(params.get(6));
				dmng.setSelectArea(iwk0,iwk1,iwk2,iwk3,iwk4,iwk5);
			} else if ( params.size() == 9 ) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				iwk2 = this.Calc(params.get(3));
				iwk3 = this.Calc(params.get(4));
				iwk4 = this.Calc(params.get(5));
				iwk5 = this.Calc(params.get(6));
				iwk6 = this.Calc(params.get(7));
				iwk7 = this.Calc(params.get(8));
				dmng.setSelectArea(iwk0,iwk1,iwk2,iwk3,iwk4,iwk5,iwk6,iwk7);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			//this.waitDisplayExec();
			scriptPointer ++ ;
			break ;	

		case CMD_setSelectColor:
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() == 5 ) {
				iwk0 = this.Calc(params.get(1));
				iwk1 = this.Calc(params.get(2));
				iwk2 = this.Calc(params.get(3));
				iwk3 = this.Calc(params.get(4));
				dmng.setSelectColor(iwk0, iwk1,iwk2,iwk3);
			} else {
				this.Error(8,"パラメータ数が誤っています");				
			}
			//this.waitDisplayExec();
			scriptPointer ++ ;
			break ;	

			
		case CMD_select :
			if ( dmng == null ) this.Error(8,"画面が存在しないので、画面系の処理はできません");
			if ( params.size() < 3 ) this.Error(8,"パラメータ数が誤っています");
			this.buttonSelect(params);
			scriptPointer ++ ;
			break ;	
			
		case CMD_midiLoad :
			if ( params.size() < 2 ) this.Error(8,"パラメータ数が誤っています");
			swk0 = this.getStrValue(params.get(1));
			iwk0 = sound.MIDIload(swk0);
			if ( iwk0 > 0 )
				Error(8,"このMIDI ["+swk0+"] を開くことができません。("+iwk0+")");
			scriptPointer ++ ;
			break ;	

		case CMD_midiPlay :
			iwk0 = sound.Midiplay();
			if ( iwk0 > 0 )
				Error(8,"このMIDIを演奏できません。");
			this.th_wtime = 30;//Midiのためにスレッドを停止する時間msを設定
			scriptPointer ++ ;
			break ;	

		case CMD_midiStop :
			sound.MIDIstop();
			this.th_wtime = 0;//Midiのためにスレッドを停止する時間を解除
			scriptPointer ++ ;
			break ;	

		case CMD_audioLoop :
			if ( params.size() < 2 ) this.Error(8,"パラメータ数が誤っています");
			swk0 = this.getStrValue(params.get(1));
			iwk0 = sound.AUDIOLoop(swk0);
			if ( iwk0 > 0 )
				Error(8,"このオーディオファイル ["+swk0+"] を演奏できません。("+iwk0+")");
			scriptPointer ++ ;
			break ;	

		case CMD_audioPlay :
			if ( params.size() < 2 ) this.Error(8,"パラメータ数が誤っています");
			swk0 = this.getStrValue(params.get(1));
			iwk0 = sound.AUDIOPlay(swk0);
			if ( iwk0 > 0 )
				Error(8,"このオーディオファイル ["+swk0+"] を演奏できません。("+iwk0+")");
			scriptPointer ++ ;
			break ;	


		case CMD_audioStop :
			if ( params.size() < 2 ) this.Error(8,"パラメータ数が誤っています");
			swk0 = this.getStrValue(params.get(1));
			sound.AUDIOStop(swk0);
			scriptPointer ++ ;
			break ;	
	
		case CMD_clipLoop :
			if ( params.size() < 2 ) this.Error(8,"パラメータ数が誤っています");
			swk0 = this.getStrValue(params.get(1));
			iwk0 = sound.CLIPLoop(swk0);
			if ( iwk0 > 0 )
				Error(8,"このオーディオファイル ["+swk0+"] を演奏できません。("+iwk0+")");
			scriptPointer ++ ;
			break ;	


		case CMD_clipStop :
			if ( params.size() < 2 ) this.Error(8,"パラメータ数が誤っています");
			swk0 = this.getStrValue(params.get(1));
			sound.CLIPStop(swk0);
			scriptPointer ++ ;
			break ;	
	
			
		case CMD_setWaitTime :
			if ( params.size() < 2 ) this.Error(8,"パラメータ数が誤っています");
			this.th_wtime = this.Calc(params.get(1));
			scriptPointer ++ ;
			break ;	
			

		default :
			scriptPointer ++ ;
		}
	}

	private int anotherColor(int col ) {
		int r = ( col >> 16 ) & 0x0000ff ; 
		int g = ( col >> 8 ) & 0x0000ff ; 
		int b = col & 0x0000ff ; 
		
		if ( r > 127 ) r = r / 2;
		else r = (r+127) / 2;
		if ( g > 127 ) g = g / 2;
		else g = (g+127) / 2;
		if ( b > 127 ) b = b / 2;
		else b = (b+127) / 2;
		
		int color = 0xff000000 | (r << 16) | (g << 8) | b ;
		return color ;
	}
	
	
	
	/**
	 * エラー処理を行いレベルが８以上の場合は強制終了する
	 * @param level
	 * @param t0
	 */
	private void Error(int level, String t0 ){
		if (this.scriptPointer == 0 || this.scriptParams == null )
			System.err.print("JONGS-Error:"+t0);
		else 
			System.err.print("JONGS-Error:"+t0+":"+this.scriptParams.get(this.scriptPointer));
		//MIDIを停止
		switch (level) {
		case 0:
			break ;
		case 4:
			break ;
		case 8:
			sound.MIDIclose();
			if ( dmng != null ) dmng.dispose();
			System.exit(level);
			break ;
		default :
			sound.MIDIclose();
			if ( dmng != null ) dmng.dispose();
			System.exit(level);
		}
		return ;
	}


	/**
	 * 全体実行部
	 */
	public void run() {
		//スクリプトが終了するまで繰り返す
		while (scriptPointer < scriptCode.size()) {
			//一行だけ実行
			if ( debug > 0 ) {
				System.out.println("JONGS Line:"+scriptParams.get(this.scriptPointer).toString());				
			}
			this.oneLineExec();
			
			//スレッド停止(MIDIが途切れぬよう)
			if ( this.th_wtime > 0 ) waitMiliSec(th_wtime);
		}
		sound.MIDIclose();
		if ( dmng != null ) {
			dmng.dispose();
		}
	}
	
	
	
	public static void main(String[] args) {
		JongScripter js = new JongScripter() ;
		if ( args.length > 0 ) {
			if ( args.length >= 2) {
				js.getScript(args[0],args[1]);				
			} else {
				js.getScript(args[0],"EUC_JP");								
			}
			//js.outScriptState();
			js.start();
		}
	}
}
