//==============================================================================================================================
//	禁則処理
//
//
//==============================================================================================================================
#define	SW_MODULE_KINSOKU

#define		NAME_MAX		(16)

//------------------------------------------------------------------
//		スクリプトコマンドクラス
//------------------------------------------------------------------
class KINSOKU{
	
	BOOL		m_bInitialized;
	BOOL		m_bImplemented;
	BOOL		m_FullInit;
	
	void		Initialize(char *param,char *namelist);
	int			string_cmp(char *ptr,char *str);
	
	int			read_namelist(char *fname);
	int			check_kinsoku(char *ptr);
	
	char		crlf[5];
	int			width,hight;
	char		name[NAME_MAX][32];				//
	int			nlen_min[NAME_MAX];				//
	int			nlen_max[NAME_MAX];				//
	int			name_entry;
	
public:
	int			Func( CPARAMS cParams );
//	int			Func(char *path,char *param,char *namelist,char *outname);
	void		Quit( BOOL _bExit );
	
	void		kinsoku(char *mess);
	
	KINSOKU();
	~KINSOKU();
	
};

//	アプリケーション起動時
KINSOKU::KINSOKU(){
		m_FullInit = FALSE;
		m_bInitialized = FALSE;
		m_bImplemented = FALSE;
}
//	アプリケーション終了時
KINSOKU::~KINSOKU(){
}


//==============================================================================================================================================
//	初期化と開放
//		1ファイルに1つの処理でコンプリートするような場合は修正する必要ありません
//		注釈となっている Message_printf を有効にして sample.swb を実行すると動きがよく分かると思います。
//==============================================================================================================================================

//------------------------------------------------------------------
//		スクリプトコマンドの初期化
//			(特に必要ないなら変更の必要なし)
//------------------------------------------------------------------
void	KINSOKU::Initialize(char *param,char *namelist){
		int		i,j;
		
		
		if(m_bInitialized == TRUE)	return;
		m_bInitialized = TRUE;	//	初期済みフラグ
		
		width = 256;
		hight = 1;
		STRING_cpy(crlf,"\r\n");
		
		if(param[0] == '-'){
			i = 1;
			
			while(i < (int)strlen(param)){
				switch(param[i]){
					case '"':
						i++;
						j = 0;
						while(param[i]!='"'){
							if(param[i] == '\\'){
								i++;
								if(param[i] == 'r')			crlf[j++] = 0x0d;
								else if(param[i] == 'n')	crlf[j++] = 0x0a;
								i++;
							}else
								crlf[j++] = param[i++];
							if(j>=5)break;
						}
						i++;
						if(j >= 5){
							Message_error("改行コードが長すぎます");
							crlf[4] = 0;
						}else
							crlf[j] = 0;
						break;
					
					case '(':
						i++;
						width = 0;
						while(param[i] != ','){
							width *= 10;
							width += (param[i] - '0');
							i++;
						}
						i++;
						hight = 0;
						while(param[i] != ')'){
							hight *= 10;
							hight += (param[i] - '0');
							i++;
						}
						i++;
						break;
					
					default:
						i++;
				}
				
			}
			
		}
		
		
		if(namelist != NULL && namelist[0] != 0)
			read_namelist(namelist);
		
		
		Message_printf("改行コード:%s  幅高(%d,%d)",crlf,width,hight);
		
		if(m_FullInit == FALSE){
			m_FullInit = TRUE;
			//	全体を通して一度しか行わない初期化
			
			//Message_printf("全体の初期化");
			
			
		}
		
		//	初期化処理
		//	１つのバッチに同じスクリプトが２度指定されていたならここには２度来る
		//Message_printf("初期化");
		
		
}

//------------------------------------------------------------------
//		スクリプトコマンドの終了
//			(特に必要ないなら変更の必要なし)
//------------------------------------------------------------------
void	KINSOKU::Quit( BOOL _bExit )
{
		
		//	ここにはスクリプトを使っていなくても来るので注意
		
		if(m_bImplemented == FALSE)	return;		//	変換処理が実行されていないなら帰還
		m_bImplemented = FALSE;
		m_bInitialized = FALSE;
		
		//	終了処理
		//Message_printf("完了");
		
		if(et == 1){
			//	次のスクリプトは存在しない、完全な終了
			//	１つのバッチに同じスクリプトに別パラメータを渡しての処理で
			//	逐一結果を出さず、全体で統合して結果を出したい場合などはここで
			
			//Message_printf("終了");
			
		}
		
}


//		名前リストを取得
int		KINSOKU::read_namelist(char *fname){
		char	*mem = NULL;
		int		i,j,len;
		
		
		len = MEM_TargetRead(&mem,fname);
		if(len == 0)	return FALSE;
		
		name_entry = 0;
		i = 0;
		while(i < len){
			if(*(mem+i) == '\t' || *(mem+i) == '\r' || *(mem+i) == '\n'){
				while(*(mem+i) == '\t' && i<len)	i++;
				while(*(mem+i) == '\r' && i<len)	i+=2;
				while(*(mem+i) == '\n' && i<len)	i++;
				continue;
			}
			
			j = 0;
			while(*(mem+i) != '\t' && i<len)	name[name_entry][j++] = *(mem+i++);
			name[name_entry][j] = 0;
			
			while(*(mem+i) == '\t' && i<len)	i++;
			
			j = 0;
			while(*(mem+i) != '-' && i<len){
				j *= 10;
				j += *(mem+i++) - '0';
			}
			if(*(mem+i) == '-' && i<len)	i++;
			nlen_min[name_entry] = j;
			
			j = 0;
			while(*(mem+i) > ' ' && i<len){
				j *= 10;
				j += *(mem+i++) - '0';
			}
			nlen_max[name_entry] = j;
			
			if(++name_entry >= NAME_MAX){
				Message_error("名前が多すぎます");
				return FALSE;
			}
		}
		
	//	for(i=0 ; i<name_entry ; i++)	_printf("%s %d %d\n",name[i],nlen_min[i],nlen_max[i]);
		
		mem_del(mem);
		
		return TRUE;
}



//==============================================================================================================================================
//	変換処理部分
//==============================================================================================================================================

#define	KINSOKU_OUTAREA		2	//	変換後の容量は仮に元の倍取っている　内容によって変更して下さい
#define	KINSOKU_RANGE				//	このdefineを有効にすると範囲限定機能が有効になる

//------------------------------------------------------------------
//	変換フィルターサンプル　機能:無変換(ファイルコピー)
//			変換せず調査だけなら out に関する部分は不要
//------------------------------------------------------------------
int		KINSOKU::Func( CPARAMS cParams ){
		LPCTSTR	sPath;
		LPCTSTR	sParam;
		LPCTSTR	sNameList;
		LPCTSTR	sOutName;
		TCHAR	drive[_MAX_DRIVE],dir[_MAX_DIR],name[_MAX_FNAME],ext[_MAX_EXT],temp[1024/*MAXPATH*/];
		char	*mem=NULL;
		char	*out=NULL;
		int		i,j,ll,len;
		
		sPath     = cParams.GetPath();		///< ターゲットファイル (GetFilePath(0)としても同じ).
		sParam    = cParams.GetString(1);
		sNameList = cParams.GetString(2);
		sOutName  = cParams.GetString(3);
		
		
		Initialize( sParam, sNameList );
		
		len = MEM_TargetRead(&mem,sPath );
		if(len == 0)	return FALSE;		//	ファイルがない
		
		m_bImplemented = TRUE;	//	実行済みフラグ
		
		//	変換後のデータバッファを確保
		mem_alloc(char,out, len*KINSOKU_OUTAREA );
		
		
		i = 0;
		#ifdef	KINSOKU_RANGE
		cRange.Init(mem,len);						//範囲限定機能を有効にするにはこの初期化と
		while(cRange.Is(mem,i,len))	i++;		//　初回スキップ、下の[スキップ判定]が必要。スキップが必要な間trueが返りループしている
		#endif
		
		j = 0;
		while(i < len){
			#ifdef	KINSOKU_RANGE
			while(cRange.Is(mem,i,len))	i++;	//	スキップ判定
			#endif
			
			while((*(mem+i) == '\t' || *(mem+i) == '\r' || *(mem+i) == '\n') && i<len)	*(out+j++) = *(mem+i++);
			
			if(_ismbblead(*(mem+i)) == 0 && *(mem+i) != '\\' && *(mem+i) != crlf[0]){	//全角でない
				while(*(mem+i) != '\n' && i<len)	*(out+j++) = *(mem+i++);
				if(*(mem+i) == '\n')	*(out+j++) = *(mem+i++);
			}else{
				ll=0;
				{
	loop:
					while(*(mem+i) != '\n' && i<len){
						temp[ll++] = (*(mem+i++));
					}
					temp[ll++] = (*(mem+i++));
					if(temp[ll-1] == '\n')	ll--;
					if(temp[ll-1] == '\r')	ll--;
					
					while(*(mem+i) == '\t' && i<len)	i++;
					
					if(_ismbblead(*(mem+i)) != 0 || *(mem+i)=='\\'){	//全角
						if(crlf[0] == '\r' && crlf[1] == '\n')	{temp[ll++] = '\r';	temp[ll++] = '\n';}
						if(crlf[0] == '\n')						{temp[ll++] = '\n';}
						goto	loop;
					}
				}
				temp[ll] = 0;
				
				
				kinsoku(temp);
			/*	if(STRING_len(temp) > width){
					_printf(temp);
					_printf("\r\n");
				}
			*/	
				STRING_cpy(out+j,temp);
				j += STRING_len(temp);
				STRING_cpy(out+j,"\r\n");
				j += STRING_len("\r\n");
				
			}
			
		}
		
		//	変換された out を出力　　出力ファイル名はバッチで指定、特に指定されていなければ元と同じファイル名
		
		if( !sOutName )	STRING_cpy(temp,sPath );	//	出力パスが指定されていない時、元のパス
		else			STRING_cpy(temp,sOutName );	//	出力パスが指定されている
		
		FILE_split( temp,drive,dir,name,ext);
		FILE_merge( temp,drive,dir,name,ext);	//ここでは分解した物をそのまま連結、拡張子等を変えたい時はここで
	//	FILE_merge( temp,drive,dir,name,".txt");	//拡張子を".txt"に変えるサンプル
		
		//	ファイル出力(同名が存在する時はバックアップが作成される)
		file_targetwrite(temp,out,j);
		
		
		//	メモリを開放
		mem_del(mem);
		mem_del(out);
		
		return TRUE;
}


//		
void	KINSOKU::kinsoku(char *mess){
		char	temp[1024];
		int		i,j,k,top_i,top_j,x,y,gosa,f,renew;
		
		#define	next_line()		{top_i=i;top_j=j;gosa=x=0;y++;}
		
		
		STRING_cpy(temp,mess);
		
		i = j = 0;
		top_i = top_j = 0;
		x = gosa = 0;
		
		renew = 0;
		y = 0;
		while(i < STRING_len(temp)){
			
			//	既に打ってある改行コードはそのままコピー(行カウントはする)
			if(string_cmp(temp+i,crlf)==1){
				next_line();
			}else{	//	改行コードに指定されていない通常改行はスキップ(普通はここに来るまでに削除されるが)
				if(*(temp+i) == '\r')	i++;
				if(*(temp+i) == '\n')	i++;
			}
			
			f=0;
			for(k=0 ; k<name_entry ; k++){
				if(string_cmp(temp+i,name[k])==1){
					gosa += (nlen_max[k] - nlen_min[k]);
					
					x += nlen_min[k];
					if(x+gosa >= width){		//	名前部分で横幅オーバー
						
						//	改行記号を追記
						renew |= 1;
						STRING_cpy(mess+j,crlf);
						j += STRING_len(crlf);
						next_line();
					}
					
					i += STRING_len(name[k]);
					STRING_cpy(mess+j,name[k]);
					j += STRING_len(name[k]);
					
					f = 1;
				}
			}
			if(f)continue;
			
			if(_ismbblead(*(temp+i)) != 0){	//全角
				mess[j++] = temp[i++];
				x++;
			}
			mess[j++] = temp[i++];
			x++;
			
			if(x+gosa >= width){				//	横幅オーバー
				
			//		mess[j++] = '\r';	//	実改行を入れる
			//		mess[j++] = '\n';
				if(gosa > 0){	//可変文字が間にある
					
				}
				
				next_line();
				
				if(check_kinsoku(temp+i)){
					Message_printf("\r\n禁則発生\r\n%s",mess);
					
					x += 2;	//プログラム対処　シミュレート(特殊)
					
				}
				
			}
			
		}
		
		
		if(y >= hight)
			Message_printf("行数をオーバー:%s",mess);
		
		mess[j] = 0;
		
		
		if(renew == 1){
		//	STRING_cat(mess,"\r\n;▲改行");
			Message_printf("\r\n名前直前で改行\r\n%s",mess);
			
		}
		
}


//		
int		KINSOKU::string_cmp(char *ptr,char *str){
		
		for(int i=0 ; i<STRING_len(str) ; i++){
			if(*(ptr+i) != *(str+i))	return 0;
		}
		
		return 1;
}


//		ポインタで指定されている部分が禁則対象なら TRUE を返す
int		KINSOKU::check_kinsoku(char *ptr){
		char	kinsoku_moji[] = "っゃゅょぁぃぅぇぉ、。！？」）ー〜";
		int		i;
		
		
		if(_ismbblead(*ptr) == 0)	//全角でない
			return FALSE;
		
		for(i=0; i<(int)STRING_len(kinsoku_moji) ; i+=2){
			if(
				*(kinsoku_moji+i) == *(ptr) && 
				*(kinsoku_moji+i+1) == *(ptr+1)
			){
				return TRUE;
			}
		}
		
		return FALSE;
}


KINSOKU	*pC_kinsoku = NULL;

