/*	
 *	cliplogb.c
 *
 *	ログバッファ
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2014 Naoyuki Sawa
 *
 *	* Mon Dec 16 17:34:52 JST 2013 Naoyuki Sawa
 *	- 1st リリース。
 *	* Wed Sep 17 00:00:00 JST 2014 Naoyuki Sawa
 *	- 文字列描画関数を、呼出し側が提供するようにしました。
 *	  これまではrender_reduced_string()を使っていましたが、読み易さのためにrender_string()でフォント2を使いたいことがあったからです。
 *	  日本語ログを表示する場合は、これまでどおりrender_reduced_string()を使いたい事も考えられるので、可変にするのが良いと思いました。
 *	  以上の理由により、文字列描画関数を呼出し側が提供するようにしました。
 */
#include "clip.h"

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

//{{2014/09/17変更:文字列描画関数を、呼出し側が提供するようにしました。
//ST_LogBuf* LogBuf_Init(int LineNum) {
//↓2014/09/17変更:文字列描画関数を、呼出し側が提供するようにしました。
ST_LogBuf* LogBuf_Init(int LineNum, int (*fnDraw)(int x, int y, const char* Str)) {
//}}2014/09/17変更:文字列描画関数を、呼出し側が提供するようにしました。
	ST_LogBuf* Me;
	/* 行数は1行以上でなくてはなりません。 */
	if(LineNum < 1) { DIE(); }
	/* ST_LogBuf構造体と行バッファをまとめて確保します。 */
	Me = calloc(sizeof(ST_LogBuf) + (sizeof(char*) * LineNum), 1);
	if(!Me) { DIE(); }
//{{2014/09/17追加:文字列描画関数を、呼出し側が提供するようにしました。
	/* 文字列描画関数を格納します。 */
	Me->fnDraw = fnDraw;
//}}2014/09/17追加:文字列描画関数を、呼出し側が提供するようにしました。
	/* 最大行(=行数-1)を格納します。 */
	Me->LineMax = LineNum - 1;
	/* ST_LogBuf構造体を返します。 */
	return Me;
}

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

void LogBuf_Free(ST_LogBuf* Me) {
	/* 行バッファに格納した文字列を開放します。 */
	LogBuf_Clear(Me);
	/* ST_LogBuf構造体と行バッファをまとめて開放します。 */
	free(Me);
}

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

void LogBuf_Clear(ST_LogBuf* Me) {
	int i;
	/* 行位置をリセットします。 */
	Me->LinePos = 0;
	/* 行バッファに格納した文字列を開放します。 */
	for(i = 0; i <= Me->LineMax; i++) {
		free(Me->LineMem[i]); /* (free(NULL)も可) */
		     Me->LineMem[i] = NULL;
	}
}
/****************************************************************************
 *	
 ****************************************************************************/

void LogBuf_Print(ST_LogBuf* Me, const char* Str) {
	int Len;
	char* Mem;
	do {
		/* 終端又は改行の直前までの文字の長さを求めます。 */
		Len = strcspn(Str, "\n");
		/* 情報量を増やすため、空行は飛ばすことにします。 */
		if(!Len) { continue; }
		/* 終端又は改行の直前までの文字列をコピーします。 */
		Mem = calloc(Len + 1, 1);
		if(!Mem) { DIE(); }
		memcpy(Mem, Str, Len);
		/* 文字列ポインタを終端又は改行の位置へ進めます。 */
		Str += Len;
		/* 既存の行の文字列を開放します。(free(NULL)も可) */
		free(Me->LineMem[Me->LinePos]);
		/* 新しい行の文字列を格納します。 */
		Me->LineMem[Me->LinePos] = Mem;
		/* 行位置を進め、最大行を越えたら先頭に戻します。 */
		if(++Me->LinePos > Me->LineMax) { Me->LinePos = 0; }
		/* 終端ならば終了し、改行ならば処理を継続します。 */
	} while(*Str++);
}

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

/* 文字列展開バッファとして_def_vbuff[]を利用しています。 */
void LogBuf_Printf(ST_LogBuf* Me, const char* Fmt, ...) {
	va_list ap;
	va_start(ap, Fmt);
	vsprintf(_def_vbuff, Fmt, ap);
	va_end(ap);
	LogBuf_Print(Me, _def_vbuff);
}

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

//{{2014/09/17変更:文字列描画関数を、呼出し側が提供するようにしました。
//void LogBuf_Draw(ST_LogBuf* Me, RENDER* r, int x, int y, int c) {
//↓2014/09/17変更:文字列描画関数を、呼出し側が提供するようにしました。
void LogBuf_Draw(ST_LogBuf* Me, int x, int y) {
//}}2014/09/17変更:文字列描画関数を、呼出し側が提供するようにしました。
	char* Str;
	/* 最後に格納した行位置の次の行から… */
	int i = Me->LinePos;
	for(;;) {
		/* 未格納でなければ、描画します。 */
		Str = Me->LineMem[i++];
		if(Str) {
//{{2014/09/17変更:文字列描画関数を、呼出し側が提供するようにしました。
//			render_reduced_string(r, x, y, Str, c);
//			y += 10; /* 描画した場合のみ描画位置を進める。最初の一画面を上詰めで描画するために、未格納ならば描画位置も進めない。 */
//↓2014/09/17変更:文字列描画関数を、呼出し側が提供するようにしました。
			y += (*Me->fnDraw)(x, y, Str); /* 描画した場合のみ描画位置を進める。最初の一画面を上詰めで描画するために、未格納ならば描画位置も進めない。 */
//}}2014/09/17変更:文字列描画関数を、呼出し側が提供するようにしました。
		}
		/* ラップアラウンド判定。 */
		if(i >  Me->LineMax) { i = 0; }
		/* 一画面分描画完了判定。 */
		if(i == Me->LinePos) { break; }
	}
}

