// cStringArray.cpp: implementation of the cStringArray class.
//
//////////////////////////////////////////////////////////////////////

#include "cStringArray.h"
#include "TOOLMemory.h"
#include <algorithm>

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

cStringArray::cStringArray(){
	Strings = NULL;
	Indices = NULL;
}

cStringArray::~cStringArray(){
	Destroy();
}

bool cStringArray::Create(int _charCount, int _LineCount){
	int i;

	charCount = _charCount;
	LineCount = _LineCount;

	if(charCount < 2) charCount = 3;

	// 문자열 포인터를 준비
	Strings = new char *[LineCount];
	if(!Strings) return false;
	ZeroMemory(Strings, sizeof(char *) * LineCount);

	for(i = 0; i < LineCount; i ++){
		Strings[i] = new char [charCount + 1];
		if(!Strings[i]){
			Destroy();
			return false;
		}
		ZeroMemory(Strings[i], sizeof(char) * charCount + 1);
	}
	// 스트링을 교환을 빠르게 하기 위한 테이블을 준비한다.
	Indices = new char *[LineCount];
	if(!Indices){
		Destroy();
		return false;
	}
	for(i = 0; i < LineCount; i ++){
		Indices[i] = Strings[i];
	}
	return true;
}

void cStringArray::Destroy(){
	int i;
	if(Strings){
		for(i = 0; i < LineCount; i ++)
			Free(Strings[i]);
		Free(Strings);
	}
	Free(Indices);
}

bool cStringArray::AddString(char *String, int Index){
// printf와 동일한 문자열 출력을 제공한다.
	int x, y, i, Len;

	if(Index < 0 || Index > LineCount) Index = LineCount - 1;
//	if(Index > 0) ScrollUp(0, Index);
	x = strlen(Indices[Index]);
	y = Index;
	Len = strlen(String);
	for(i = 0; i < Len && String[i]; i ++){
		if((BYTE)String[i] & 0x80){ // 문자가 한글인 경우
			if(x < charCount - 1){ // 출력 하기에 충분한 공간이 있을 경우
				(Indices[y])[x] = String[i];
				x ++; i ++;
				(Indices[y])[x] = String[i];
				x ++;
			}else{
				x = charCount;
				i --;
			}
		}else{
			switch(String[i]){
			case '\n':
				(Indices[y])[x] = '\0';
				x = charCount;
				break;
			default:
				(Indices[y])[x] = String[i];
				x ++; 
				break;
			}
		}
		if(x >= charCount){
			(Indices[y])[x] = '\0';
			x = 0;
			y ++;
			if(y >= LineCount){
				y = LineCount - 1;
				ScrollUp(0, y);
			}
		}
	}
	(Indices[y])[x] = '\0';
	return true;
}

char *cStringArray::GetString(int Index){
	if(Index < 0 || Index >= LineCount) return NULL;
	return Indices[Index];
}


void cStringArray::ScrollUp(int BeginLine, int EndLine){
// 문자열 배열을 한 줄위로 스크롤 한다.
// 새로 생겨나는 줄은 비어있다.
// 물론 처리속도의 증대를 위해 인덱스 배열만을 변경한다.
	int i;
	char *tmp;

	if(!Strings) return;
	if(BeginLine < 0) BeginLine = 0;
	if(EndLine < 0) EndLine = LineCount - 1;
	if(BeginLine > EndLine) std::swap<int>(BeginLine, EndLine);
	if(BeginLine < 0) BeginLine = 0;
	if(EndLine >= LineCount) EndLine = LineCount - 1;
	(Indices[BeginLine])[0] = '\0';
	tmp = Indices[BeginLine];
	for(i = 0; i < EndLine; i ++){
		Indices[i] = Indices[i + 1];
	}
	Indices[EndLine] = tmp;
}

bool cStringArray::Printf(char *Format, ...){
	char buff[512];
	va_list vaList;

	va_start(vaList, Format);

	if(vsprintf(buff, Format, vaList) <= 0)
		return false;
	AddString(buff);
	return true;
}

bool cStringArray::Printfv(char *format, va_list VaList){
	char buff[512];

	if(vsprintf(buff, format, VaList) <= 0)
		return false;
	AddString(buff);
	return true;
}
