/*************************************************************
*
* (c) 1999, 2000 Christoph Pinkel
* This is part of the VisKProg project.
*
* You may use it under the terms of the GPL licence.
* See COPYING for more details!
*
**************************************************************/

/* Please note: This file is pure c code: I took it from the form translator ! */

#include "infman.h"

struct subObjs vkfSubO;

void addSubProp( char *n, char *v )
{
int i;
	for( i = 0; vkfSubO.sprops[i][0][0] != 0L; i++ )
		if ( i == MAX_ENTRS-1 )
			fatal( "Too many properties in sub widget.\n" );

	strcat( vkfSubO.sprops[i][0], n );
	strcat( vkfSubO.sprops[i][1], v );
}


void clearSubO()
{
int i, ii;

	for( i = 0; i < EXPR_LEN; i++ )
	{
		vkfSubO.name[i] = 0L;
		vkfSubO.type[i] = 0L;

		for( ii = 0; ii < MAX_ENTRS; ii++ )
		{
			vkfSubO.sprops[ii][0][i] = 0L;
			vkfSubO.sprops[ii][1][i] = 0L;
		}
	}

}

int toInt( char *str )
{
int i, vm = 1;
int ret = 0;

	for( i = strlen(str)-1; i >= 0; i-- )
	{
		if ( !isdigit(str[i]) )
			fatal( "String contains trash (Can't convert to int).\n" );

		ret += (str[i]-48) *vm;

		vm = vm *10;
	}

	return ret;

}


int parseSubProp( int i, char *vkf )
{
int ii;
char expr1[EXPR_LEN], expr2[EXPR_LEN];

	while( vkf[i] != ')' )
	{
		ii = 0;

		while( vkf[i] != '=' )
		{
			if( !isalnum(vkf[i]) )
				fatal ( "Incorrect *.vk(t)f file: Wrong sub widget property.\n" );

			expr1[ii] = vkf[i];

			i++; ii++;

			if ( ii == EXPR_LEN )
				fatal( "Name of property of sub widget too long.\n" );
		}

		expr1[ii] = 0L;

		i++;

		if( vkf[i] != '"' )
			fatal ( "Incorrect *.vk(t)f file: '\"' expected #1.\n" );



		i++; ii = 0;

		while( vkf[i] != '"' )
		{

			if ( vkf[i] == 0L )
				fatal ( "Incorrect *.vk(t)f file: Unterminated string.\n" );


			expr2[ii] = vkf[i];

			i++; ii++;

			if ( ii == EXPR_LEN )
				fatal( "Value of property \"%s\" of sub widget \"%s\" too long.\n",
					expr2, vkfSubO.name );
		}

		expr2[ii] = 0L;

		addSubProp( expr1, expr2 );

		i++;


		if( vkf[i] != ';' )
			fatal ( "Incorrect *.vk(t)f file: ';' expected.\n" );

		i++;

	} //while

	return i;

}


void addByte( char *str, char nc )
{
int i;
	for( i = 0; str[i] != 0; i++ )
		if( i >= EXPR_LEN-1 )
			fatal ( "Expression too long ( > %d bytes ).\n", EXPR_LEN );


	str[i] = nc;
	str[i+1] = 0L;


}


void readParse( struct inFile *inf, char *vkf, int makeWindow )
{
int i, ii = 0;
int strMode = 0;
char expr1[EXPR_LEN] = "", expr2[EXPR_LEN];

	for( i = 0; vkf[i] != 0L; i++ )
	{
		if( vkf[i] == '"' )
			strMode = !strMode;

		if( !strMode && isalpha(vkf[i]) )
		{
			vkf[i] = tolower( vkf[i] );
		}

		if ( strMode || ( vkf[i] != ' ' && vkf[i] != '\n' && vkf[i] != '\t' ) )
		{
			vkf[ii] = vkf[i];
			ii++;
		}

	}

	initInF( inf );

	vkf[i] = 0L;


	if ( makeWindow && strncmp(vkf, "window", 6) != 0 )
		fatal ( "Incorrect *.vk(t)f file: \"Window\" expected.\n" );
	else if ( !makeWindow && strncmp(vkf, "subwindow", 9) != 0 )
		fatal ( "Incorrect *.vk(t)f file: \"SubWindow\" expected.\n" );

	if ( makeWindow  )
		i = 6;
	else
		i = 9;

	for( ; vkf[i] != '('; i++ )
	{
		if( !isalnum(vkf[i]) )
			fatal ( "Incorrect *.vk(t)f file: Incorrect name.\n" );


		addByte( expr1, vkf[i] );
	}

	setInFName( inf, expr1 );

	i++;

	if ( strncmp(vkf+(i*sizeof(char)), "properties(", 11) != 0 )
		fatal ( "Incorrect *.vk(t)f file: \"Properties\" expected.\n" );


	i += 11;

	while( vkf[i] != ')' )
	{

		expr1[0] = 0L;
		expr2[0] = 0L;

		while( vkf[i] != '=' )
		{
			if( !isalnum(vkf[i]) )
				fatal ( "Incorrect *.vk(t)f file: Wrong property.\n" );


			addByte( expr1, vkf[i] );

			i++;
		}

		i++;

		if( vkf[i] != '"' )
			fatal ( "Incorrect *.vk(t)f file: '\"' expected #2.\n" );


		i++;

		while( vkf[i] != '"' )
		{

			if ( vkf[i] == 0L )
				fatal ( "Incorrect *.vk(t)f file: Unterminated string.\n" );

			addByte(expr2, vkf[i] );

			i++;
		}

		i++;


		if( vkf[i] != ';' )
			fatal ( "Incorrect *.vk(t)f file: ';' expected.\n" );

		i++;

		setInFProp( inf, expr1, expr2 );

	} //while


	i++;


	if ( strncmp(vkf+(i*sizeof(char)), "regional(", 9) != 0 )
		fatal ( "Incorrect *.vk(t)f file: \"Regional\" expected.\n" );

	i += 9;


	while( vkf[i] != ')' )
	{

		expr1[0] = 0L;
		expr2[0] = 0L;

		while( vkf[i] != '=' )
		{
			if( !isalnum(vkf[i]) && vkf[i] != '_' )
				fatal ( "Incorrect *.vk(t)f file: Wrong variable name.\n" );

			addByte( expr1, vkf[i] );

			i++;
		}

		i++;

		if( vkf[i] != '"' )
			fatal ( "Incorrect *.vk(t)f file: '\"' expected #3.\n" );


		i++;

		while( vkf[i] != '"' )
		{

			if ( vkf[i] == 0L )
				fatal ( "Incorrect *.vk(t)f file: Unterminated string.\n" );

			addByte( expr2, vkf[i] );

			i++;
		}

		i++;


		if( vkf[i] != ';' )
			fatal ( "Incorrect *.vk(t)f file: ';' expected.\n" );

		i++;

		setInFVar( inf, expr1, expr2 );

	} //while

	i++;



	if ( strncmp(vkf+(i*sizeof(char)), "regconst(", 9) != 0 )
		fatal ( "Incorrect *.vk(t)f file: \"RegConst\" expected.\n" );

	i += 9;


	while( vkf[i] != ')' )
	{
		expr1[0] = 0L;
		expr2[0] = 0L;

		while( vkf[i] != '=' )
		{
			if( !isalnum(vkf[i]) && vkf[i] != '_' )
				fatal ( "Incorrect *.vk(t)f file: Wrong const name.\n" );

			addByte( expr1, vkf[i] );

			i++;
		}

		i++;

		if( vkf[i] != '"' )
			fatal ( "Incorrect *.vk(t)f file: '\"' expected #4.\n" );


		i++;

		while( vkf[i] != '"' )
		{

			if ( vkf[i] == 0L )
				fatal ( "Incorrect *.vk(t)f file: Unterminated string.\n" );

			addByte( expr2, vkf[i] );

			i++;
		}

		i++;


		if( vkf[i] != ';' )
			fatal ( "Incorrect *.vk(t)f file: ';' expected.\n" );


		i++;

		setInFConst( inf, expr1, expr2 );

	} //while

	i++;


	if ( strncmp(vkf+(i*sizeof(char)), "functions(", 10) != 0 )
		fatal ( "Incorrect *.vk(t)f file: \"Functions\" expected.\n" );

	i += 10;


	while( vkf[i] != ')' )
	{
		expr1[0] = 0L;
		expr2[0] = 0L;

		while( vkf[i] != ':' )
		{
			if( !isalnum(vkf[i]) && vkf[i] != '_' )
				fatal ( "Incorrect *.vk(t)f file: Wrong function name.\n" );

			addByte( expr1, vkf[i] );

			i++;
		}

		i++;

		if ( !isdigit( vkf[i] ) )
			fatal ( "Incorrect *.vk(t)f file: Wrong function argument number.\n" );

		while( isdigit( vkf[i] ) )
		{
			addByte( expr2, vkf[i] );
			i++;
		}

		if( vkf[i] != ';' )
			fatal ( "Incorrect *.vk(t)f file: ';' expected.\n" );

		i++;

		setInFFunc( inf, expr1, toInt(expr2) );

	} //while

	i++;


	//Sub widgets:

	if ( strncmp(vkf+(i*sizeof(char)), "subwidgets(", 11) != 0 )
		fatal ( "Incorrect *.vk(t)f file: \"SubWidgets\" expected.\n" );

	i += 11;


	while( vkf[i] != ')' )
	{
		clearSubO();

		if ( strncmp(vkf+(i*sizeof(char)), "subwindow", 9) == 0 )
		{
			strcat( vkfSubO.type, "SubWindow" );
			i += 9;
		}
		else if ( strncmp(vkf+(i*sizeof(char)), "button", 6) == 0 )
		{
			strcat( vkfSubO.type, "Button" );
			i += 6;
		}
		else if ( strncmp(vkf+(i*sizeof(char)), "label", 5) == 0 )
		{
			strcat( vkfSubO.type, "Label" );
			i += 5;
		}
		else if ( strncmp(vkf+(i*sizeof(char)), "pixlabel", 5) == 0 )
		{
			strcat( vkfSubO.type, "PixLabel" );
			i += 8;
		}
		else if ( strncmp(vkf+(i*sizeof(char)), "lineedit", 8) == 0 )
		{
			strcat( vkfSubO.type, "LineEdit" );
			i += 8;
		}
		else if ( strncmp(vkf+(i*sizeof(char)), "listbox", 7) == 0 )
		{
			strcat( vkfSubO.type, "ListBox" );
			i += 7;
		}
		else if ( strncmp(vkf+(i*sizeof(char)), "checkbox", 8) == 0 )
		{
			strcat( vkfSubO.type, "CheckBox" );
			i += 8;
		}
		else if ( strncmp(vkf+(i*sizeof(char)), "optionbutton", 12) == 0 )
		{
			strcat( vkfSubO.type, "OptionButton" );
			i += 12;
		}
		else if ( strncmp(vkf+(i*sizeof(char)), "slider", 6) == 0 )
		{
			strcat( vkfSubO.type, "slider" );
			i += 6;
		}
		else if ( strncmp(vkf+(i*sizeof(char)), "procctrl", 8) == 0 )
		{
			strcat( vkfSubO.type, "procctrl" );
			i += 8;
		}
		else
			fatal ( "Incorrect *.vk(t)f file: Unknown widget type.\n%s\n",
				vkf+(i*sizeof(char)) );

		ii = 0;

		while( vkf[i] != '(' )
		{
			if( !isalnum(vkf[i]) )
				fatal ( "Incorrect *.vk(t)f file: Wrong sub object name name.\n" );

			vkfSubO.name[ii] = vkf[i];
			ii++;
			i++;

			if( ii == EXPR_LEN )
				fatal( "Name of sub widget is too long.\n" );

		}

		vkfSubO.name[ii] = 0L;

		i++;

		i = parseSubProp(i,vkf);

		setInFSub( inf, &vkfSubO );

		i++;

	} //while
	


} //readParse(...)


void initInF( struct inFile *inf )
{
int i, ii, iii;


	for( i = 0; i < MAX_ENTRS; i++ )
	{
		for( ii = 0; ii < EXPR_LEN; ii++ )
		{
			inf->props[i][0][ii] = 0L;
			inf->props[i][1][ii] = 0L;

			inf->vars[i][0][ii] = 0L;
			inf->vars[i][1][ii] = 0L;

			inf->consts[i][0][ii] = 0L;
			inf->consts[i][1][ii] = 0L;

			inf->funcs[i][ii] = 0L;

			inf->sobjs[i].name[ii] = 0L;
			inf->sobjs[i].type[ii] = 0L;

			for( iii = 0; iii < MAX_ENTRS; iii++ )
			{
				inf->sobjs[i].sprops[iii][0][ii] = 0L;
				inf->sobjs[i].sprops[iii][1][ii] = 0L;
			}

		}

		inf->funcarg[i] = -1;

	} //for

	for( i = 0; i < EXPR_LEN; i++ )
		inf->name[i] = 0L;

}


void setInFName( struct inFile *inf, char *newName )
{
int i;

	for( i = 0; newName[i] != 0L; i++ )
	{
		if( i >= EXPR_LEN )
			fatal( "Data check error.\n" );

		inf->name[i] = newName[i];
	}

	inf->name[i] = 0L;
}


void setInFProp( struct inFile *inf, char *nn, char *nv )
{
int i;

	for( i = 0; inf->props[i][0][0] != 0L; i++ )
		if( i == MAX_ENTRS-1 )
		{
			warning( "Data check error.\n" );
			abort();
		}

	if ( strlen(nn) >= EXPR_LEN || strlen(nv) >= EXPR_LEN )
	{
		warning( "Expression too long.\n" );
		abort();
	}

	strcat( inf->props[i][0], nn );
	strcat( inf->props[i][1], nv );
}


void setInFVar( struct inFile *inf, char *nn, char *nv )
{
int i;

	for( i = 0; inf->vars[i][0][0] != 0L; i++ )
		if( i == MAX_ENTRS-1 )
		{
			warning( "Data check error.\n" );
			abort();
		}

	if ( strlen(nn) >= EXPR_LEN || strlen(nv) >= EXPR_LEN )
	{
		warning( "Expression too long.\n" );
		abort();
	}


	strcat( inf->vars[i][0], nn );
	strcat( inf->vars[i][1], nv );
}


void setInFConst( struct inFile *inf, char *nn, char *nv )
{
int i;

	for( i = 0; inf->consts[i][0][0] != 0L; i++ )
		if( i == MAX_ENTRS-1 )
		{
			warning( "Data check error.\n" );
			abort();
		}

	if ( strlen(nn) >= EXPR_LEN || strlen(nv) >= EXPR_LEN )
	{
		warning( "Expression too long.\n" );
		abort();
	}


	strcat( inf->consts[i][0], nn );
	strcat( inf->consts[i][1], nv );
}


void setInFFunc( struct inFile *inf, char *nn, int args )
{
int i;

	for( i = 0; inf->funcs[i][0] != 0L; i++ )
		if( i == MAX_ENTRS-1 )
		{
			warning( "Data check error.\n" );
			abort();
		}

	if ( strlen(nn) >= EXPR_LEN )
	{
		warning( "Expression too long.\n" );
		abort();
	}


	strcat( inf->funcs[i], nn );
	inf->funcarg[i] = args;
}


void setInFSub( struct inFile *inf, struct subObjs *sob )
{
int i, ii, iii;

	for( i = 0; inf->sobjs[i].name[0] != 0L; i++ )
		if( i == MAX_ENTRS-1 )
		{
			warning( "Data check error.\n" );
			abort();
		}


	for( ii = 0; ii < MAX_ENTRS; ii++ )
	{
		for( iii = 0; iii < EXPR_LEN; iii++ )
		{
			inf->sobjs[i].sprops[ii][0][iii] = sob->sprops[ii][0][iii];
			inf->sobjs[i].sprops[ii][1][iii] = sob->sprops[ii][1][iii];
		}

		inf->sobjs[i].name[ii] = sob->name[ii];
		inf->sobjs[i].type[ii] = sob->type[ii];
	}

}


void getInFName( struct inFile *inf, char *name )
{
	strcpy( name, inf->name );
}


void getInPropN( struct inFile *inf, int ix, char *ret )
{
int i;

	if ( ix >= MAX_ENTRS )
	{
		ret[0] = 0L;
		return;
	}

	for( i = 0; inf->props[ix][0][i] != 0L; i++ )
	{
		if ( i == EXPR_LEN )
		{
			warning( "Invalid expression in file data.\n" );
			abort();
		}

		ret[i] = inf->props[ix][0][i];

	}

	ret[i] = 0L;
}


void getInPropV( struct inFile *inf, int ix, char *ret )
{
int i;

	if ( ix >= MAX_ENTRS )
	{
		ret[0] = 0L;
		return;
	}

	for( i = 0; inf->props[ix][1][i] != 0L; i++ )
	{
		if ( i == EXPR_LEN )
		{
			warning( "Invalid expression in file data.\n" );
			abort();
		}

		ret[i] = inf->props[ix][1][i];

	}


	ret[i] = 0L;
}


void getInVarN( struct inFile *inf, int ix, char *ret )
{
int i;

	if ( ix >= MAX_ENTRS )
	{
		ret[0] = 0L;
		return;
	}

	for( i = 0; inf->vars[ix][0][i] != 0L; i++ )
	{
		if ( i == EXPR_LEN )
		{
			warning( "Invalid expression in file data.\n" );
			abort();
		}

		ret[i] = inf->vars[ix][0][i];

	}

	ret[i] = 0L;
}


void getInVarV( struct inFile *inf, int ix, char *ret )
{
int i;

	if ( ix >= MAX_ENTRS )
	{
		ret[0] = 0L;
		return;
	}

	for( i = 0; inf->vars[ix][1][i] != 0L; i++ )
	{
		if ( i == EXPR_LEN )
		{
			warning( "Invalid expression in file data.\n" );
			abort();
		}

		ret[i] = inf->vars[ix][1][i];

	}

	ret[i] = 0L;
}


void getInConstN( struct inFile *inf, int ix, char *ret )
{
int i;

	if ( ix >= MAX_ENTRS )
	{
		ret[0] = 0L;
		return;
	}

	for( i = 0; inf->consts[ix][0][i] != 0L; i++ )
	{
		if ( i == EXPR_LEN )
		{
			warning( "Invalid expression in file data.\n" );
			abort();
		}

		ret[i] = inf->consts[ix][0][i];

	}

	ret[i] = 0L;
}


void getInConstV( struct inFile *inf, int ix, char *ret )
{
int i;

	if ( ix >= MAX_ENTRS )
	{
		ret[0] = 0L;
		return;
	}

	for( i = 0; inf->consts[ix][1][i] != 0L; i++ )
	{
		if ( i == EXPR_LEN )
		{
			warning( "Invalid expression in file data.\n" );
			abort();
		}

		ret[i] = inf->consts[ix][1][i];

	}

	ret[i] = 0L;
}


void getInFuncN( struct inFile *inf, int ix, char *ret )
{
int i;

	if ( ix >= MAX_ENTRS )
	{
		ret[0] = 0L;
		return;
	}

	for( i = 0; inf->funcs[ix][i] != 0; i++ )
	{
		if ( i == EXPR_LEN )
		{
			warning( "Invalid expression in file data.\n" );
			abort();
		}

		ret[i] = inf->funcs[ix][i];

	}

	ret[i] = 0L;
}


int getInFuncA( struct inFile *inf, int ix )
{
int ret = 0;

	if ( ix >= MAX_ENTRS )
		ret = -1;

	ret = inf->funcarg[ix];

	return ret;
}


void getInSubN( struct inFile *inf, int ix, char *ret )
{
int i;

	if ( ix >= MAX_ENTRS )
	{
		ret[0] = 0L;
		return;
	}

	for( i = 0; inf->sobjs[ix].name[i] != 0L; i++ )
	{
		if ( i == EXPR_LEN )
		{
			warning( "Invalid expression in file data.\n" );
			abort();
		}

		ret[i] = inf->sobjs[ix].name[i];

	}

	ret[i] = 0L;
}


void getInSubT( struct inFile *inf, int ix, char *ret )
{
int i;

	if ( ix >= MAX_ENTRS )
	{
		ret[0] = 0L;
		return;
	}

	for( i = 0; inf->sobjs[ix].type[i] != 0L; i++ )
	{
		if ( i == EXPR_LEN )
		{
			warning( "Invalid expression in file data.\n" );
			abort();
		}

		ret[i] = inf->sobjs[ix].type[i];

	}

	ret[i] = 0L;
}


void getInSubPropN( struct inFile *inf, int ix, int indx, char *ret )
{
int i;

	if ( ix >= MAX_ENTRS || indx >= MAX_ENTRS )
	{
		ret[0] = 0L;
		return;
	}

	for( i = 0; inf->sobjs[ix].sprops[indx][0][i] != 0L; i++ )
	{
		if ( i == EXPR_LEN )
		{
			warning( "Invalid expression in file data.\n" );
			abort();
		}

		ret[i] = inf->sobjs[ix].sprops[indx][0][i];

	}

	ret[i] = 0L;
}


void getInSubPropV( struct inFile *inf, int ix, int indx, char *ret )
{
int i;

	if ( ix >= MAX_ENTRS || indx >= MAX_ENTRS )
	{
		ret[0] = 0L;
		return;
	}

	for( i = 0; inf->sobjs[ix].sprops[indx][1][i] != 0L; i++ )
	{
		if ( i == EXPR_LEN )
		{
			warning( "Invalid expression in file data.\n" );
			abort();
		}

		ret[i] = inf->sobjs[ix].sprops[indx][1][i];

	}

	ret[i] = 0L;
}