#include "svg-main.h"
#include "shape.h"
#include "dbase.h"
#include "svg.h"

//======================================//
//		global variables
//======================================//
struct Header header;//メインファイルのヘッダー情報を持つ
struct IndexRecord* g_pIndexRecords=0;//インデックスレコード配列へのポインタ
INT g_iRecordNum;//インデックスレコード配列,シェイプの配列の数


//====================================//
//		global variables
//====================================//

struct SVGInfo SvgInfo;

//======================================//
//====functions of convert endaian======//
//======================================//

WORD convertLittleEndianWord(WORD val){
	#ifdef CPU_INTEL
		return val;
	#endif

	#ifdef CPU_SUN
		WORD reverse;
		int i;
		for(i=0 ; i< sizeof(val) ; i++){
			*((char*)&reverse +i)=*((char*)&val + (sizeof(val)-1) - i);
		}
		return reverse;
	#endif
}

WORD convertBigEndianWord(WORD val){
	#ifdef CPU_INTEL
		WORD reverse;
		int i;
		for(i=0 ; i< sizeof(val) ; i++){
			*((char*)&reverse +i)=*((char*)&val + (sizeof(val)-1) - i);
		}
		return reverse;
	#endif

	#ifdef CPU_SUN
		return val;
	#endif
}

INT convertLittleEndianInt(INT val){
	#ifdef CPU_INTEL
		return val;
	#endif

	#ifdef CPU_SUN
		INT reverse;
		INT i;
		for(i=0 ; i< sizeof(val) ; i++){
			*((char*)&reverse +i)=*((char*)&val + (sizeof(val)-1) - i);
		}
		return reverse;
	#endif
}

INT convertBigEndianInt(INT val){
	#ifdef CPU_INTEL
		INT reverse;
		INT i;
		for(i=0 ; i< sizeof(val) ; i++){
			*((char*)&reverse +i)=*((char*)&val + (sizeof(val)-1) - i);
		}
		return reverse;
	#endif

	#ifdef CPU_SUN
		return val;
	#endif
}

DOUBLE convertLittleEndianDouble(DOUBLE val){
	#ifdef CPU_INTEL
		return val;
	#endif
	#ifdef CPU_SUN
		DOUBLE reverse;
		INT i;
		for(i=0 ; i< sizeof(val) ; i++){
			*((char*)&reverse +i)=*((char*)&val + (sizeof(val)-1) - i);
		}
		return reverse;
	#endif


}

DOUBLE convertBigEndianDouble(DOUBLE val){
	#ifdef CPU_INTEL
		DOUBLE reverse;
		INT i;
		for(i=0 ; i< sizeof(val) ; i++){
			*((char*)&reverse +i)=*((char*)&val + (sizeof(val)-1) - i);
		}
		return reverse;
	#endif
	#ifdef CPU_SUN
		return val;
	#endif


}

void trim(char *str){
	int iLen;
	char *tmp;
	char *oldtmp;
	
	if(!str){
		return;
	}
	
	iLen=strlen(str);
	tmp=(char*)malloc(sizeof(char)*iLen+1);
	oldtmp=tmp;

	strcpy(tmp , str);

	while(*tmp == 0x20){
		tmp++;
	}

	iLen=strlen(tmp);
	while(*(tmp+iLen-1) == 0x20){
		*(tmp+iLen-1) = 0x00;
		iLen--;
	}
	iLen=strlen(tmp);
	strcpy(str , tmp);
	free(oldtmp);
}

//==========================================//
//		functions of SVG output
//==========================================//
// File pointer fin points the beggining of each format data.
 
int printPoint(FILE *fin , FILE *fout , int iID){
//////Point format////// 
//  Double X
//  Double Y
//////

	struct Point pt;
	struct Rect rc;
	fread(&pt , SIZEOF_POINT , 1 , fin);
	pt.X=convertLittleEndianDouble(pt.X);
	pt.Y=convertLittleEndianDouble(pt.Y);
	
	rc.Left=pt.X-(SvgInfo.StrokeWidth);
	rc.Right=pt.X+(SvgInfo.StrokeWidth);
	rc.Top=pt.Y-(SvgInfo.StrokeWidth);
	rc.Bottom=pt.Y+(SvgInfo.StrokeWidth);
	fprintf(fout , "<path id=\"%d\" fill=\"%s\" stroke=\"%s\" stroke-width=\"%f\" d=\"M %f %f L %f %f L %f %f L %f %f z\" />\n", 
						iID ,
						SvgInfo.Fill , SvgInfo.Stroke , SvgInfo.StrokeWidth,
						rc.Left , rc.Top,
						rc.Right , rc.Top,
						rc.Right , rc.Bottom,
						rc.Left , rc.Bottom );
	
	return 1;
}



int printPolyLine(FILE *fin , FILE *fout , int iID){

//////PolyLine format////
//	Double[4] Box //
//	Integer NumParts //
//	Integer NumPoints //
//	Integer[NumParts] Parts //
//	Point[NumPoints] Points //
//////

	INT iNumParts;
	INT iNumPoints;
	INT *pParts;
	struct Point* pPoints;
	int i;
	int j;
	int iLast;
	
	fseek(fin , sizeof(DOUBLE)*4 , SEEK_CUR); //this program doesent use Box
	
	//read iNumParts iNumPoints
	fread(&iNumParts , sizeof(iNumParts) , 1 , fin);
	fread(&iNumPoints , sizeof(iNumPoints) , 1 , fin);
	iNumParts=convertLittleEndianInt(iNumParts);
	iNumPoints=convertLittleEndianInt(iNumPoints);
	
	pParts=(INT*)malloc(sizeof(INT)*iNumParts);
	if(!pParts){
		fprintf(stderr , "malloc fault.\n");
		return 0;
	}
	
	//read Parts and convert endian
	for(i=0 ; i < iNumParts ; i++){
		fread(pParts+i , sizeof(INT) , 1 , fin);
		pParts[i]=convertLittleEndianInt(pParts[i]);
	}
	
	pPoints=(struct Point*)malloc(SIZEOF_POINT*iNumPoints);
	if(!pPoints){
		fprintf(stderr , "malloc fault.\n");
		free(pParts);
		return 0;
	}
	
	//read points and convert endian
	for(i=0 ; i<iNumPoints ; i++){
		fread(pPoints+i , SIZEOF_POINT , 1 , fin);
		pPoints[i].X=convertLittleEndianDouble(pPoints[i].X);
		pPoints[i].Y=convertLittleEndianDouble(pPoints[i].Y);
	}
	
	//output <path> elements
//	fprintf(fout , "<path id=\"%d\" fill=\"%s\" stroke=\"%s\" stroke-width=\"%f\" d=\"", iID , SvgInfo.Fill , SvgInfo.Stroke , SvgInfo.StrokeWidth);
	fprintf(fout , "<path id=\"%d\" fill=\"none\" stroke=\"%s\" stroke-width=\"%f\" d=\"", iID , SvgInfo.Stroke , SvgInfo.StrokeWidth);
	for(i=0 ; i<iNumParts ; i++){
		if(i == iNumParts-1){//if this part is last
			iLast=iNumPoints;
		}
		else{
			iLast=pParts[i+1];
		}
		
		fprintf(fout ,"M ");
		for(j=pParts[i] ; j<iLast ; j++){
			if(j != iLast-1){
				fprintf(fout , "%f %f L " , pPoints[j].X , pPoints[j].Y);
			}
			else{
				fprintf(fout , "%f %f " , pPoints[j].X , pPoints[j].Y);
			}
		}	
	}
	fprintf(fout , "\" />\n");
	
	free(pParts);
	free(pPoints);
	return 1;
}



int printPolygon(FILE *fin , FILE *fout , int iID){

//////Polygon format//////（
//	Double[4] Box //
//	Integer NumParts //
//	Integer NumPoints //
//	Integer[NumParts] Parts //
//	Point[NumPoints] Points //
//////

	INT iNumParts;
	INT iNumPoints;
	INT *pParts;
	struct Point* pPoints;
	int i;
	int j;
	int iLast;
	
	fseek(fin , sizeof(DOUBLE)*4 , SEEK_CUR); //this program doesent use Box
	
	//read iNumParts iNumPoints
	fread(&iNumParts , sizeof(iNumParts) , 1 , fin);
	fread(&iNumPoints , sizeof(iNumPoints) , 1 , fin);
	iNumParts=convertLittleEndianInt(iNumParts);
	iNumPoints=convertLittleEndianInt(iNumPoints);
	
	pParts=(INT*)malloc(sizeof(INT)*iNumParts);
	
	if(!pParts){
		fprintf(stderr , "malloc fault.\n");
		return 0;
	}

	//read parts and convert endian
	for(i=0 ; i < iNumParts ; i++){
		fread(pParts+i , sizeof(INT) , 1 , fin);
		pParts[i]=convertLittleEndianInt(pParts[i]);
	}
	
	pPoints=(struct Point*)malloc(sizeof(struct Point)*iNumPoints);
	if(!pPoints){
		fprintf(stderr , "malloc fault.\n");
		free(pParts);
		return 0;
	}
	
	//read points and convert endian
	for(i=0 ; i<iNumPoints ; i++){
		fread(pPoints+i , SIZEOF_POINT , 1 , fin);
		pPoints[i].X=convertLittleEndianDouble(pPoints[i].X);
		pPoints[i].Y=convertLittleEndianDouble(pPoints[i].Y);
	}
/*	
	//find clipping path
	for(i=0 ; i<iNumParts ; i++){
		int iPointsInPart;
		if(i == iNumParts-1){//if this part is last
			iPointsInPart=iNumPoints-pParts[i];
		}
		else{
			iPointsInPart=pParts[i+1]-pParts[i];
		}
		pClipPath[i]=IsClipPath(&pPoints[pParts[i]] , iPointsInPart);
		if(pClipPath[i]){
			int a=iID;
		}
	
	}

	//find path which is clipped by found clipping path.
//	for(i=0 ; i<iNumParts ; i++){
*/		
	//outpu <path> element
	fprintf(fout , "<path id=\"%d\" clip-rule=\"nonzero\" fill=\"%s\" stroke=\"%s\" stroke-width=\"%f\" d=\"", iID ,SvgInfo.Fill , SvgInfo.Stroke , SvgInfo.StrokeWidth);//<path ... d="
	for(i=0 ; i<iNumParts ; i++){
		if(i == iNumParts-1){//if this part is last
			iLast=iNumPoints;
		}
		else{
			iLast=pParts[i+1];
		}
		
		fprintf(fout ,"M ");
		for(j=pParts[i] ; j<iLast ; j++){
			if(j != iLast-1){
				fprintf(fout , "%f %f L " , pPoints[j].X , pPoints[j].Y);
			}
			else{
				fprintf(fout , "%f %f Z " , pPoints[j].X , pPoints[j].Y);
			}
		}	
	}
	fprintf(fout , "\" />\n");
	
	free(pParts);
	free(pPoints);
	return 1;
}



int printMultiPoint(FILE *fin , FILE *fout , int iID){

//////MultiPoint format//////
//	Double[4] Box //
//	Integer NumPoints //
//	Point[NumPoints] Points //
//////

	INT iNumPoints;
	struct Point pt;
	struct Rect rc;
	int i;
	
	fseek(fin , sizeof(DOUBLE)*4 , SEEK_CUR); //this program doesent use Box
	
	fread(&iNumPoints , sizeof(iNumPoints) , 1 , fin);
	iNumPoints=convertLittleEndianInt(iNumPoints);
	
	//read every points and output <path> element. This <path> draw rect whose center is the point.
	for(i=0 ; i<iNumPoints ; i++){
		fread(&pt , SIZEOF_POINT , 1 , fin);
		pt.X=convertLittleEndianDouble(pt.X);
		pt.Y=convertLittleEndianDouble(pt.Y);
		
		rc.Left=pt.X-(SvgInfo.StrokeWidth);
		rc.Right=pt.X+(SvgInfo.StrokeWidth);
		rc.Top=pt.Y-(SvgInfo.StrokeWidth);
		rc.Bottom=pt.Y+(SvgInfo.StrokeWidth);
		fprintf(fout , "<path id=\"%d\" fill=\"%s\" stroke=\"%s\" stroke-width=\"%f\" d=\"M %f %f L %f %f L %f %f L %f %f z\" />\n", 
						iID ,
						SvgInfo.Fill , SvgInfo.Stroke , SvgInfo.StrokeWidth,
						rc.Left , rc.Top,
						rc.Right , rc.Top,
						rc.Right , rc.Bottom,
						rc.Left , rc.Bottom );
	}

	
	return 1;
}



//================================================//
//		SVG output (Measure Data)
//================================================//
//＊＊＊this program doesnt use M data＊＊＊ //

int printPointM(FILE *fin , FILE *fout , int iID){

//////PointM format//////
//  Double X
//  Double Y
//	Double M
//////

	struct Point pt;
	struct Rect rc;
	DOUBLE M;//Not Used Now
	
	fread(&pt , SIZEOF_POINT , 1 , fin);
	pt.X=convertLittleEndianDouble(pt.X);
	pt.Y=convertLittleEndianDouble(pt.Y);
	
	rc.Left=pt.X-(SvgInfo.StrokeWidth);
	rc.Right=pt.X+(SvgInfo.StrokeWidth);
	rc.Top=pt.Y-(SvgInfo.StrokeWidth);
	rc.Bottom=pt.Y+(SvgInfo.StrokeWidth);
	fprintf(fout , "<path id=\"%d\" fill=\"%s\" stroke=\"%s\" stroke-width=\"%f\" d=\"M %f %f L %f %f L %f %f L %f %f z\" />\n", 
						iID,
						SvgInfo.Fill , SvgInfo.Stroke , SvgInfo.StrokeWidth,
						rc.Left , rc.Top,
						rc.Right , rc.Top,
						rc.Right , rc.Bottom,
						rc.Left , rc.Bottom );
	

	return 1;
}



int printPolyLineM(FILE *fin , FILE *fout , int iID){

//////PolyLineM format//////
//	Double[4] Box //
//	Integer NumParts //
//	Integer NumPoints //
//	Integer[NumParts] Parts //
//	Point[NumPoints] Points //
//	Double[2] M Range //
//	Double[NumPoints] 
//////

	INT iNumParts;
	INT iNumPoints;
	INT *pParts;
	DOUBLE Mmin;//Not Used Now
	DOUBLE Mmax;//Not Used Now
	DOUBLE *Marray;//Not Used Now
	struct Point* pPoints;
	
	int i;
	int j;
	int iLast;
	
	fseek(fin , sizeof(DOUBLE)*4 , SEEK_CUR); //this program doesent use Box
	
	//read iNumParts iNumPoints
	fread(&iNumParts , sizeof(iNumParts) , 1 , fin);
	fread(&iNumPoints , sizeof(iNumPoints) , 1 , fin);
	iNumParts=convertLittleEndianInt(iNumParts);
	iNumPoints=convertLittleEndianInt(iNumPoints);
	
	pParts=(INT*)malloc(sizeof(INT)*iNumParts);
	if(!pParts){
		fprintf(stderr , "malloc fault.\n");
		return 0;
	}
	
	//read parts and convert endian
	for(i=0 ; i < iNumParts ; i++){
		fread(pParts+i , sizeof(INT) , 1 , fin);
		pParts[i]=convertLittleEndianInt(pParts[i]);
	}
	
	pPoints=(struct Point*)malloc(SIZEOF_POINT*iNumPoints);
	if(!pPoints){
		fprintf(stderr , "malloc fault.\n");
		free(pParts);
		return 0;
	}
	
	//read points and convert endian
	for(i=0 ; i<iNumPoints ; i++){
		fread(pPoints+i , SIZEOF_POINT , 1 , fin);
		pPoints[i].X=convertLittleEndianDouble(pPoints[i].X);
		pPoints[i].Y=convertLittleEndianDouble(pPoints[i].Y);
	}
	
	//output <path> element
//	fprintf(fout , "<path id=\"%d\" fill=\"%s\" stroke=\"%s\" stroke-width=\"%f\" d=\"", iID ,SvgInfo.Fill , SvgInfo.Stroke , SvgInfo.StrokeWidth);
	fprintf(fout , "<path id=\"%d\" fill=\"none\" stroke=\"%s\" stroke-width=\"%f\" d=\"", iID ,SvgInfo.Stroke , SvgInfo.StrokeWidth);
	for(i=0 ; i<iNumParts ; i++){
		if(i == iNumParts-1){//if this part is the last
			iLast=iNumPoints;
		}
		else{
			iLast=pParts[i+1];
		}
		
		fprintf(fout , "M ");
		for(j=pParts[i] ; j<iLast ; j++){
			if(j != iLast-1){
				fprintf(fout , "%f %f L " , pPoints[j].X , pPoints[j].Y);
			}
			else{
					fprintf(fout , "%f %f " , pPoints[j].X , pPoints[j].Y);
			}
		}	
	}
	fprintf(fout , "\" />\n");
	
	free(pParts);
	free(pPoints);
	return 1;
}



int printPolygonM(FILE *fin , FILE *fout , int iID){

//////PolygonM format//////
//	Double[4] Box //
//	Integer NumParts //
//	Integer NumPoints //
//	Integer[NumParts] Parts //
//	Point[NumPoints] Points //
//	Double[2] M Range //
//	Double[NumPoints] 
//////

	INT iNumParts;
	INT iNumPoints;
	INT *pParts;
	DOUBLE Mmin;//Not Used Now
	DOUBLE Mmax;//Not Used Now
	DOUBLE *Marray;//Not Used Now
	struct Point* pPoints;
	int i;
	int j;
	int iLast;
	
	fseek(fin , sizeof(DOUBLE)*4 , SEEK_CUR); //this program doesent use Box
	
	//read iNumParts and iNumPoints
	fread(&iNumParts , sizeof(iNumParts) , 1 , fin);
	fread(&iNumPoints , sizeof(iNumPoints) , 1 , fin);
	iNumParts=convertLittleEndianInt(iNumParts);
	iNumPoints=convertLittleEndianInt(iNumPoints);
	
	pParts=(INT*)malloc(sizeof(INT)*iNumParts);
	if(!pParts){
		fprintf(stderr , "malloc fault.\n");
		return 0;
	}
	
	//read parts and convert endian
	for(i=0 ; i < iNumParts ; i++){
		fread(pParts+i , sizeof(INT) , 1 , fin);
		pParts[i]=convertLittleEndianInt(pParts[i]);
	}
	
	pPoints=(struct Point*)malloc(sizeof(struct Point)*iNumPoints);
	if(!pPoints){
		fprintf(stderr , "malloc fault.\n");
		free(pParts);
		return 0;
	}
	
	//read points and convert endian
	for(i=0 ; i<iNumPoints ; i++){
		fread(pPoints+i , SIZEOF_POINT , 1 , fin);
		pPoints[i].X=convertLittleEndianDouble(pPoints[i].X);
		pPoints[i].Y=convertLittleEndianDouble(pPoints[i].Y);
	}
	
	//output <path> element
	fprintf(fout , "<path id=\"%d\" clip-rule=\"nonzero\" fill=\"%s\" stroke=\"%s\" stroke-width=\"%f\" d=\"", iID , SvgInfo.Fill , SvgInfo.Stroke , SvgInfo.StrokeWidth);
	for(i=0 ; i<iNumParts ; i++){
		if(i == iNumParts-1){//if this part is the last 
			iLast=iNumPoints;
		}
		else{//
			iLast=pParts[i+1];
		}
		
		fprintf(fout , "M ");
		for(j=pParts[i] ; j<iLast ; j++){
			if(j != iLast-1){
				fprintf(fout , "%f %f L " , pPoints[j].X , pPoints[j].Y);
			}
			else{
				fprintf(fout , "%f %f Z " , pPoints[j].X , pPoints[j].Y);
			}
		}	
	}
	fprintf(fout , "\" />\n");

	free(pParts);
	free(pPoints);
	
	
	return 1;
}



int printMultiPointM(FILE *fin , FILE *fout , int iID){

//////MultiPointM format//////
//	Double[4] Box //
//	Integer NumPoints //
//	Point[NumPoints] Points //
//	Double[2] M Range //
//	Double[NumPoints] 
//////

	INT iNumPoints;
	DOUBLE Mmin;//Not Used Now
	DOUBLE Mmax;//Not Used Now
	DOUBLE *Marray;//Not Used Now
	
	struct Point pt;
	struct Rect rc;
	
	int i;
	
	fseek(fin , sizeof(DOUBLE)*4 , SEEK_CUR); //this program doesent use Box
	
	fread(&iNumPoints , sizeof(iNumPoints) , 1 , fin);
	iNumPoints=convertLittleEndianInt(iNumPoints);
	
	//	//read every points and output <path> element. This <path> draw rect whose center is the point.
	for(i=0 ; i<iNumPoints ; i++){
		fread(&pt , SIZEOF_POINT , 1 , fin);
		pt.X=convertLittleEndianDouble(pt.X);
		pt.Y=convertLittleEndianDouble(pt.Y);
		
		rc.Left=pt.X-(SvgInfo.StrokeWidth);
		rc.Right=pt.X+(SvgInfo.StrokeWidth);
		rc.Top=pt.Y-(SvgInfo.StrokeWidth);
		rc.Bottom=pt.Y+(SvgInfo.StrokeWidth);
		fprintf(fout , "<path id=\"%d\" fill=\"%s\" stroke=\"%s\" stroke-width=\"%f\" d=\"M %f %f L %f %f L %f %f L %f %f z\" />\n", 
						iID ,
						SvgInfo.Fill , SvgInfo.Stroke , SvgInfo.StrokeWidth,
						rc.Left , rc.Top,
						rc.Right , rc.Top,
						rc.Right , rc.Bottom,
						rc.Left , rc.Bottom );
		
	}

	
	return 1;
}

//=========================================//
//		functions for .dbf file
//=========================================//

//functions which output field type and the data.
int printCharField(char *pData , FILE *fout){
	fprintf(fout , "type=\"text\">%s" , pData);
	return 1;
}

int printDateField(char *pData , FILE *fout){
	char year[5];
	char month[3];
	char day[3];
	strncpy(year , pData , 4);
	strncpy(month , pData+4 , 2);
	strncpy(day , pData+6 , 2);
	fprintf(fout , "type=\"date\">%s-%s-%s" , year , month , day);
	return 1;
}

int printFloatField(char *pData ,FILE *fout){
	fprintf(fout , "type=\"float\">%s" , pData );
	return 1;
}

int printDecimalField(char *pData , FILE *fout){
	fprintf(fout , "type=\"decimal\">%s" , pData);
	return 1;
}

int printLogicalField(char *pData , FILE *fout){
	fprintf(fout , "type=\"logical\">%s" , pData);
	return 1;
}

int printMemoField(char *pData , FILE *fout){
	fprintf(fout , "type=\"Memo\">");
	return 1;
}


//output <information>...</information>
#define MAX_FIELD_NAME 12
int printDBInformation(const char *filename , FILE *fout){
	struct DBaseHeader dbaseheader;
	struct DBaseField* pFields;
	char dbasefile[256];
	char pFieldName[MAX_FIELD_NAME];
	FILE *fp;
	int iFieldNum;
	int i;
	int j;
	char Del;
	char *pData;

	strcpy(dbasefile , filename);
	strcat(dbasefile , DBASE_EXT);
	
	fp=fopen(dbasefile , "rb");
	if(!fp){
		printf("Can't open DatabaseFile:%s. Can't output informations.\n", dbasefile);
		return 0;
	}

	fread(&dbaseheader.Info , sizeof(BYTE) , 1 , fp);
	fread(dbaseheader.LastModified , sizeof(BYTE) , 3 , fp);
	fread(&dbaseheader.RecordNum , sizeof(INT) , 1 , fp);
	fread(&dbaseheader.HeaderLength , sizeof(WORD) , 1 , fp);
	fread(&dbaseheader.RecordLength , sizeof(WORD) , 1 , fp);
	fread(dbaseheader.NoUse1 , sizeof(BYTE) , 2 , fp);
	fread(&dbaseheader.TFlag , sizeof(BYTE) , 1 , fp);
	fread(&dbaseheader.CFlag , sizeof(BYTE) , 1 , fp);
	fread(dbaseheader.NoUse2 , sizeof(BYTE) , 12 , fp);
	fread(&dbaseheader.Mdx , sizeof(BYTE) , 1 , fp);
	fread(&dbaseheader.DriverID , sizeof(BYTE) , 1 , fp);
	fread(dbaseheader.NoUse3 , sizeof(BYTE) , 2 , fp);
	
	//convert endian
	dbaseheader.RecordNum=convertLittleEndianInt(dbaseheader.RecordNum);
	dbaseheader.HeaderLength=convertLittleEndianWord(dbaseheader.HeaderLength);
	dbaseheader.RecordLength=convertLittleEndianWord(dbaseheader.RecordLength);
	
	if(g_iRecordNum != dbaseheader.RecordNum){
		fprintf(stderr , "warning : Number of records in ShapeFile and DatabaseFile are not equal.\n");
	}

	//calc Number of fields
	iFieldNum=(dbaseheader.HeaderLength-SIZEOF_DBASEHEADER-1)/SIZEOF_DBASEFIELD;
	
	pFields=(struct DBaseField*)malloc(sizeof(struct DBaseField)*iFieldNum);
	if(!pFields){
		fprintf(stderr , "malloc fault. Can't output informations.\n");
		return 0;
	}
	
	for(i=0 ; i<iFieldNum  ; i++){
		fread(pFields[i].FieldName , sizeof(char) , 11 , fp);
		fread(&pFields[i].FieldType , sizeof(char) , 1 , fp);
		fread(pFields[i].NoUse1 , sizeof(BYTE) , 4 , fp);
		fread(&pFields[i].FieldLength , sizeof(BYTE) , 1 , fp);
		fread(&pFields[i].DecimalLength , sizeof(BYTE) , 1 , fp);
		fread(pFields[i].NoUse2 , sizeof(BYTE) , 2 , fp);
		fread(&pFields[i].WorkSpaceID , sizeof(BYTE) , 1 , fp);
		fread(pFields[i].NoUse3 , sizeof(BYTE) , 10 , fp);
		fread(&pFields[i].Mdx , sizeof(BYTE) , 1 , fp);
	}
	
	fseek(fp , 1 , SEEK_CUR);

	
	for(i=0 ; i<dbaseheader.RecordNum ; i++){
		fread(&Del , sizeof(char) , 1 , fp);
		if(Del == 0x20 ){//if this record is not deleted
			fprintf(fout , "<information name=\"%d\">\n" , i+1);
			fprintf(fout , "<record>\n");//<record> element
			for(j=0 ; j<iFieldNum ; j++){
				//output <field> element
				strncpy(pFieldName , pFields[j].FieldName , MAX_FIELD_NAME);
				trim(pFieldName);
				fprintf(fout ,"\t<%s " , pFieldName); //
				//read data
				pData=(char *)malloc(pFields[j].FieldLength+1);//
				fread(pData , pFields[j].FieldLength , 1 , fp);
				pData[pFields[j].FieldLength]=0x00;//add NULL
				trim(pData);
				switch(pFields[j].FieldType){
					case TYPE_CHAR:
						printCharField(pData , fout);
						break;
					case TYPE_DATE:
						printDateField(pData , fout);
						break;
					case TYPE_FLOAT:
						printFloatField(pData ,fout);
						break;
					case TYPE_DECIMAL:
						printDecimalField(pData , fout);
						break;
					case TYPE_LOGICAL:
						printLogicalField(pData , fout);
						break;
					case TYPE_MEMO:
						printMemoField(pData , fout);
						break;
				}
				fprintf(fout , "</%s>\n" , pFieldName);
				free(pData);
			}
			fprintf(fout , "</record>\n</information>\n");
		}
	}

	free(pFields);
	return 1;
}

int printSVG(char *filename , int iOut){
	char mainfile[256];
	char outfile[256];
	FILE *fin;
	FILE *fout;
	int i;
	INT iShapeType;
	
	strcpy(mainfile , filename);
	strcat(mainfile , MAIN_EXT);
	fin=fopen(mainfile , "rb");
	if(!fin){
		fprintf(stderr , "File Open Error. Can't open %s.\n", mainfile);
		return 0;
	}
	
	strcpy(outfile , filename);
	strcat(outfile , SVG_EXT);
	if(iOut ==1){
		fout=stdout;
	}
	else{
		fout=fopen(outfile , "w");
		if(!fout){
			fprintf(stderr , "File Open Error\n Can't open %s\n", outfile);
			return 0;
		}
	}
	
	//output xml,svg header
	//fprintf(fout , "<?xml version=\"1.0\" ?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n");
	fprintf(fout , "<?xml version=\"1.0\" ?>\n");
	fprintf(fout , "<svg viewBox=\"%f %f %f %f\">\n" , header.Xmin , header.Ymin , header.Xmax-header.Xmin , header.Ymax-header.Ymin);
	
	//read each record from mainfile(.shp). and call functions by each format.
	for(i=0 ; i<g_iRecordNum ; i++){
		fseek(fin , g_pIndexRecords[i].Offset+SIZEOF_RECORDHEADER , SEEK_SET);
		fread(&iShapeType , sizeof(INT) , 1 , fin);
		iShapeType=convertLittleEndianInt(iShapeType);
		switch(iShapeType){
			case NULL_SHAPE:
				break;
			case POINT:
				printPoint(fin , fout , i+1);
				break;
			case POLYLINE:
				printPolyLine(fin , fout , i+1);
				break;
			case POLYGON:
				printPolygon(fin , fout , i+1);
				break;
			case MULTIPOINT:
				printMultiPoint(fin , fout , i+1);
				break;
			case POINTM:
				printPointM(fin , fout , i+1);
				break;
			case POLYLINEM:
				printPolyLineM(fin , fout , i+1);
				break;
			case POLYGONM:
				printPolygonM(fin , fout , i+1);
				break;
			case MULTIPOINTM:
				printMultiPointM(fin , fout , i+1);
				break;
		}
	}
	
	fprintf(fout , "</svg>\n");

	printDBInformation(filename , fout);//print <information>...</information>
	fclose(fout);
	fclose(fin);
	return 1;
}





//======================================//
//		functions of parse files
//======================================//

int parseHeader(const char * filename){
	char mainfile[256];
	FILE *fp;

	strcpy(mainfile , filename);
	strcat(mainfile , MAIN_EXT);
	
	fp=fopen(mainfile , "rb");
	if(!fp){
		fprintf(stderr , "File open error. Can't open %s.\n", mainfile);
		return 0;
	}
	
	//read file header struct
	fread(&header.FileCode , sizeof(INT) , 1 , fp);
	fread(header.NoUse , sizeof(INT) , 5 , fp);
	fread(&header.FileLength , sizeof(INT) , 1 , fp);
	fread(&header.Version , sizeof(INT), 1 , fp);
	fread(&header.ShapeType , sizeof(INT) , 1 , fp);
	fread(&header.Xmin , sizeof(DOUBLE) , 1 , fp);
	fread(&header.Ymin , sizeof(DOUBLE) , 1 , fp);
	fread(&header.Xmax , sizeof(DOUBLE) , 1 , fp);
	fread(&header.Ymax , sizeof(DOUBLE) , 1 , fp);
	fread(&header.Zmin , sizeof(DOUBLE) , 1 , fp);
	fread(&header.Zmax , sizeof(DOUBLE) , 1 , fp);
	fread(&header.Mmin , sizeof(DOUBLE) , 1 , fp);
	fread(&header.Mmax , sizeof(DOUBLE) , 1 , fp);

	//Convert endian
	header.FileCode=convertBigEndianInt(header.FileCode);
	header.FileLength=convertBigEndianInt(header.FileLength);
	header.Version=convertLittleEndianInt(header.Version);
	header.ShapeType=convertLittleEndianInt(header.ShapeType);
	header.Xmin=convertLittleEndianDouble(header.Xmin);
	header.Ymin=convertLittleEndianDouble(header.Ymin);
	header.Xmax=convertLittleEndianDouble(header.Xmax);
	header.Ymax=convertLittleEndianDouble(header.Ymax);
	header.Zmin=convertLittleEndianDouble(header.Zmin);
	header.Zmax=convertLittleEndianDouble(header.Zmax);
	header.Mmin=convertLittleEndianDouble(header.Mmin);
	header.Mmax=convertLittleEndianDouble(header.Mmax);

	//convert from unit WORD to unit BYTE
	header.FileLength*=2;
	
	if(header.FileCode != SHAPE_FILE_CODE){
		fprintf(stderr ,"The format of %s is not Shapefile format.\n" , mainfile);
		fclose(fp);
		return 0;
	}

	//This software doesnt support these shape types.
	if(header.ShapeType == 11 ||
		 header.ShapeType == 13 ||
		 header.ShapeType == 15 ||
		 header.ShapeType == 18 ||
		 header.ShapeType == 31 )
	{
		 fprintf(stderr , "%s : This shapefile includes ShapeType which this software doesn't support. \n" , mainfile);
		 fclose(fp);
		 return 0;
	}
	
	return -1;
}


int parseIndex(const char *filename){
	struct Header indexHeader;
	char indexfile[256];
	FILE *fp;
	int i;
	
	strcpy(indexfile , filename);
	strcat(indexfile , INDEX_EXT);
	
	fp=fopen(indexfile , "rb");
	if(!fp){
		fprintf(stderr , "File open error. Can't open %s.\n" , indexfile);
		return 0;
	}
	
	//read Index file header(only FileCode and FileLength are used in this function)
	fread(&indexHeader.FileCode , sizeof(INT) , 1 , fp);
	fread(indexHeader.NoUse , sizeof(INT) , 5 , fp);
	fread(&indexHeader.FileLength , sizeof(INT) , 1 , fp);
	fread(&indexHeader.Version , sizeof(INT), 1 , fp);
	fread(&indexHeader.ShapeType , sizeof(INT) , 1 , fp);
	fread(&indexHeader.Xmin , sizeof(DOUBLE) , 1 , fp);
	fread(&indexHeader.Ymin , sizeof(DOUBLE) , 1 , fp);
	fread(&indexHeader.Xmax , sizeof(DOUBLE) , 1 , fp);
	fread(&indexHeader.Ymax , sizeof(DOUBLE) , 1 , fp);
	fread(&indexHeader.Zmin , sizeof(DOUBLE) , 1 , fp);
	fread(&indexHeader.Zmax , sizeof(DOUBLE) , 1 , fp);
	fread(&indexHeader.Mmin , sizeof(DOUBLE) , 1 , fp);
	fread(&indexHeader.Mmax , sizeof(DOUBLE) , 1 , fp);

	//convert endian
	indexHeader.FileCode=convertBigEndianInt(indexHeader.FileCode);
	if(header.FileCode != SHAPE_FILE_CODE){
		fprintf(stderr , "The format of %s is not Shapefile format.\n" , indexfile);
		fclose(fp);
		return 0;
	}
	indexHeader.FileLength=convertBigEndianInt(indexHeader.FileLength);
	//convert from unit WORD to unit BYTE
	indexHeader.FileLength*=2;
	
	
	//calc number of records
	g_iRecordNum= (indexHeader.FileLength-SIZEOF_HEADER)/SIZEOF_INDEXRECORD;
	
	g_pIndexRecords=(struct IndexRecord*)(malloc(sizeof(struct IndexRecord)*g_iRecordNum));
	if(!g_pIndexRecords){
		fprintf(stderr , "malloc fault.\n" , indexfile);
		fclose(fp);
		return 0;
	}



	//read IndexRecords and convert endian and unit
	for(i=0 ; i<g_iRecordNum ; i++){
		fread(&g_pIndexRecords[i].Offset , sizeof(INT) , 1 , fp);
		fread(&g_pIndexRecords[i].ContentLength , sizeof(INT) , 1 , fp);
		g_pIndexRecords[i].Offset=convertBigEndianInt(g_pIndexRecords[i].Offset);
		g_pIndexRecords[i].ContentLength=convertBigEndianInt(g_pIndexRecords[i].ContentLength);
		//convert unit WORD to unit BYTE
		g_pIndexRecords[i].Offset*=2;
		g_pIndexRecords[i].ContentLength*=2;
	}

	return 1;
}

void freeIndexRecords(){
	if(g_pIndexRecords){
		free(g_pIndexRecords);
		g_pIndexRecords=0;
	}

}


//===========================================//
//		
int setSvgInfo(){
	SvgInfo.StrokeWidth=(header.Xmax-header.Xmin)/5000;
	sprintf(SvgInfo.Stroke , "black");
	sprintf(SvgInfo.Fill , "#cccccc");
	return 1;
}
//==========================================//
//		function 
//==========================================//
/*
bool IsClipPath(struct Point * pSubPoints, INT iNumPoints){
	//get the sum of external angles of this polygon
	//if the sum is + , that is clipping path , else that is path.
	int i;
	double t1=0;
	double t2=0;
	double t=0;
	struct Point* pPoints;
	if(iNumPoints < 3 || !pSubPoints){
		return 0;
	}
	if(pSubPoints[0].X != pSubPoints[iNumPoints-1].X || pSubPoints[0].Y != pSubPoints[iNumPoints-1].Y){
		return 0;
	}
	pPoints=(struct Point*)malloc(sizeof(struct Point)*(iNumPoints)*2);
	memcpy(pPoints , pSubPoints , sizeof(struct Point)*iNumPoints);
	memcpy(pPoints+iNumPoints , pSubPoints , sizeof(struct Point)*iNumPoints);

	for(i=0 ; i<iNumPoints-1 ; i++){
		double tmp;
		struct Point baseVec=pPoints[i];
		struct Point vec1;
		struct Point vec2;
		vec1.X=pPoints[i+1].X-baseVec.X;
		vec1.Y=pPoints[i+1].Y-baseVec.Y;
		if(vec1.X == 0 && vec1.Y == 0)//when vec1 is zero vector
			continue;
		
		while(1){
			vec2.X=pPoints[i+2].X-pPoints[i+1].X;
			vec2.Y=pPoints[i+2].Y-pPoints[i+1].Y;
			if(vec2.X == 0 && vec2.Y==0){//when vec2 is zero vector
				i++;
			}
			else{
				break;
			}
		}
		t1=atan2(vec1.Y , vec1.X);
		t2=atan2(vec2.Y , vec2.X);
		tmp=t2-t1;
		//-PI <= tmp => PI
		if(tmp > PI)
			tmp-=2*PI;
		if(tmp < -PI)
			tmp+=2*PI;

		t+=tmp;
	}
	if(t>0){
		int a=0;
	}
	return t>0?1:0;//if this path is clippath , return true;

}
*/






int main(int argc, char* argv[]) {
	int i;
	int iOut=0;// 0:output .svg file. 1:output stdout.
	int iFileNum=0;
	
	//check args
	for(i=1 ; i<argc ; i++){
		if(argv[i][0] != '-'){
			iFileNum++;
		}
		else if(!strcmp(argv[i] , "-s")){
			iOut=1;
		}
	}
	
	if(iFileNum < 1){
		fprintf(stderr , "No Filename\n");
		return EXIT_FAILURE;
	}

	//parse files and outpu .svg file
	for(i=1 ; i<argc ; i++){
		if(argv[i][0] != '-'){
			parseHeader(argv[i]) &&	parseIndex(argv[i]) &&	setSvgInfo() && printSVG(argv[i] , iOut);
			freeIndexRecords();
		}
	}

	return EXIT_SUCCESS;
}
