/******************************************************************/
/* アニメーション初期化 */
/******************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <time.h>
#include "defines.h"
#include "amacro.h"
#include "abuff.h"
#include "aigtext.h"

#define	DEBUG	0

/******************************************************************/
/* 定数・変数・構造体定義 */

#define LMAX	128		/* スケジュールファイル１行最大長さ */
#define PMAX	12288		/* １パターン最大サイズ：１／４画面 */

/******************************************************************/

static int getxy(int *x,int *y,unchar *line,int point)
/* lineからx,y座標を読みとる */
{
unchar token[LMAX+1];
int i,xy;
	for (i=0;i<2;i++) {
		if (get_token(line,point+i,token)==0) {
			#if DEBUG
			prints(i==0? "ｘ":"ｙ");
			printsn("\a座標がありません：",line);
			#endif
			return(1+i);
		}
		xy=atoi(token);
		if (i==0) *x=xy; else *y=xy;
	}
	return(0);
}

/******************************************************************/
/* スケジュールファイル構造
	１行目	制御行：利用プログラムによって意味が異なる
		AnimeGetch()のとき
			アニメーションが始まるまでの秒数
				と
			アニメーションが終わるまでの秒数
			  ０なら無限
			  ＜０なら開始秒からの相対経過時間（*-1した秒数）
		Anime()のとき
			アニメーション繰り返し回数
				と
			繰り返し前のウエイト秒数
	
	２行目	アニメーションパターンのグラフィックエリア座標（退避される）
		実際に退避されるのはテキスト座標系になる
		?? ?? 0 0 のときは退避されない
	
	３行目以降
		fname x y clr time
		fname	パターン名＝ファイル名＋拡張子
			パス名は入れてはいけない
			.I_Gファイルの時は内部で反転する（自動判別）
		clr	クリアフラグ
			1=前のパターンを消してから次の表示をする
			0=前のパターンは消さずに次の表示をする
		time	そのパターンの表示時間
*/
/******************************************************************/

int AnimeOpen(unchar *scfname,int (*getchs)(),int (*kbhits)(),ANIME *an)
/* Animation initialize */
/* scfname : スケジュールファイル名 */
{
FILE *fp;
unchar line[LMAX+1],token[LMAX+1];
unchar *buff;
int x,y,ret,i;
	fp=fopen(scfname,"rt");
	if (fp==NULL) {
		#if DEBUG
		printsn("\aスケジュールファイルが見つかりません：",fname);
		#endif
		return(1);
	}
	
	ret=an->ptrns=i=0;
	while (read1line0(fp,line,token,LMAX)==0) {
		i++;
		if (i==1) { /* 最初の行はアニメーションの開始／終了秒数 */
		    an->stim=atoi(token);
		    if (an->stim==0) {
			#if DEBUG
			printsn("\a開始秒数が異常です：",line);
			#endif
			ret=12;
			break;
		    }
		    if (get_token(line,2,token)==0) an->etim=0;
		    else an->etim=atoi(token);
		    if (an->etim<an->stim) an->etim=0;
		    if (an->etim<0) an->etim=an->stim-an->etim; /* 相対時間指定 */
		    continue;
		}
		if (i==2) { /* ２行目は退避されるエリア座標 */
		    ret=getxy(&x,&y,line,1);
		    if (ret) return(12+ret);
		    an->sx=x;
		    an->sy=y;
		    ret=getxy(&x,&y,line,3);
		    if (ret) return(14+ret);
		    an->ex=x;
		    an->ey=y;
		    if (x==0||y==0) an->under=NULL;
		    else {
			an->under=newmalloc(calc_text_size(an->sx/8,an->sy/16,x/8,y/16));
			if (an->under==NULL) {
			    #if DEBUG
			    prints("\a画面退避メモリーが確保できません\n");
			    #endif
			    ret=17;
			    break;
			}
		    }
		    continue;
		}
		/* パターンファイル名 */
		/* 登録ずみのパターンの時はアドレスをコピーしパターンの重複読み込みはしない */
		for (x=0;x<an->ptrns && strcmpi(an->sc[x].name,token);x++);
		if (x>=an->ptrns) { /* 新ファイル名 */
		    if ((ret=load_ptrn(token,&buff,PMAX))) break;
		    an->sc[an->ptrns].buff=buff;
		} else { /* すでにある時はそのアドレスをコピーしておく */
		    an->sc[an->ptrns].buff=an->sc[x].buff;
		}
		strcpy(an->sc[an->ptrns].name,token);
		
		/* ｘ座標 */
		ret=getxy(&x,&y,line,2);
		if (ret) return(9+ret);
		an->sc[an->ptrns].x=x;
		an->sc[an->ptrns].y=y;
		
		/* クリアフラグ：省略するとクリアしないになる */
		if (get_token(line,4,token)==0) an->sc[an->ptrns].clr=0;
		else an->sc[an->ptrns].clr=atoi(token);
		
		/* 表示時間：省略すると25/100秒 */
		if (get_token(line,5,token)==0) an->sc[an->ptrns].tm=25;
		else an->sc[an->ptrns].tm=atoi(token);
		
		/* 次へ */
		if ((++an->ptrns)>=ANIME_MAX) break;
	}
	if (ret==0 && an->ptrns==0) { /* パターンがない */
		#if DEBUG
		prints("\aパターン指定がありません\n");
		#endif
		ret=100;
	}
	fclose(fp);
	/* キー入力関数登録 */
	an->kbhits=kbhits;
	an->getchs=getchs;
	if (ret) AnimeClose(an); /* エラーの時は終了してしまう */
	return(ret);
}

/******************************************************************/

int AnimeClose(ANIME *an)
/* Animation end */
{
int i,j;
	/* パターンバッファークリア */
	for (i=0;i<an->ptrns;i++) {
		if (an->sc[i].buff==NULL) continue; /* すでに解放済み */
		/* このバッファーを解放 */
		free(an->sc[i].buff);
		/* 重複バッファーをクリア */
		for (j=i+1;j<an->ptrns;j++) {
			if (an->sc[j].buff==an->sc[i].buff) an->sc[j].buff=NULL;
		}
	}
	if (an->under!=NULL) free(an->under);
	return(0);
}

/******************************************************************/
