/*	Renegade Scripts.dll
	INI Functions
	Copyright 2006 xuyifeng

	This file is part of the Renegade scripts.dll
	The Renegade scripts.dll is free software; you can redistribute it and/or modify it under
	the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2, or (at your option) any later
	version. See the file COPYING for more details.
	In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence.
	Only the source code to the module(s) containing the licenced code has to be released.
*/
//----------------------------------------------------------------------------
// MS Windows Style .ini File Interface for C++
// This is the first version.
// Programed by xuyifeng, 1995.10, china
//----------------------------------------------------------------------------
// Test history:
//		 Compiler			  OS						  TEST
//		 ---------------------------------------------------------------
//		 Watcom  C++ 10.0a	 Rational System DOS4GW	  100% tested
//		 Borland C++ 3.1	   DOS						 100% tested
//----------------------------------------------------------------------------
#pragma warning (disable: 4100)
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef WIN32
#define strnicmp strncasecmp
#define stricmp strcasecmp
#include "linux_comp.h"
#endif
#include "profile.h"

//------------------------------------------------------------------------------
// titlePos: get a section title position & length in a string.
//------------------------------------------------------------------------------
bool isEntry( char sLine[256] )
{
	if ( sLine[0] == '[' )
		return false;
	if ( sLine[strlen(sLine)-2] == ']' )
		return false;
	if ( strcmp( "=", sLine ) == 0 )
		return false;
	unsigned int icount = 0;
	unsigned int x = strlen(sLine);
	for (unsigned int i = 0; i < x; i++ )
	{
		if ( sLine[i] == '=' )
			icount++;
	}
	if ( icount != 1 )
		return false;
	return true;
}

void lTrim(char *buf)
{
	char * p1 = buf;
	char * p2 = buf;
	while (p2[0])
	{
		if (p2[0] > 0x20)
		{ break; }
		p2++;
	}
	while (p2[0])
	{
		p1[0] = p2[0];
		p1++;
		p2++;
	}
	p1[0] = 0x0;
}

bool getEntry( char sLine[256], char *psKey, char *psValue )
{
	if ( !isEntry( sLine ) )
		return false;

	int iPos = -1;
	unsigned int x = strlen(sLine);
	for (unsigned int i = 0; i < x; i++ )
	{
		if ( sLine[i] == '=' )
		{
			iPos = i;
			break;
		}
	}
	// remove leading spaces
	strcpy( psKey, sLine );
	psKey[ iPos ] = '\0';
	strcpy( psValue, sLine + iPos + 1 );
	psValue[ strlen(psValue) - 1 ] = '\0';
	return true;
}

void writeEntry( const char *psKey, const char *psValue, FILE *FP )
{
	char newentry[256];
	strcpy( newentry, psKey );
	strcat( newentry, "=" );
	strcat( newentry, psValue );
	strcat( newentry, "\n" );
	fputs( newentry, FP );
}

bool isSection( char sLine[256] )
{
	if ( sLine[0] != '[' )
		return false;
	if ( sLine[strlen(sLine)-2] != ']' )
		return false;
	return true;
}

void writeSection( const char *psName, FILE *FP )
{
	char newsection[256];
	strcpy( newsection, "[" );
	strcat( newsection, psName );
	strcat( newsection, "]\n" );
	fputs( newsection, FP );
}

bool getSection( char sLine[256], char *psSection )
{
	if ( !isSection( sLine ) )
		return false;   
	strcpy( psSection, sLine + 1 );
	psSection[ strlen(psSection) - 2 ] = '\0';
	return true;
}

static void stripQuotationChar( char *buf )
{
	char *p;
	char *q;
	p = buf;
	while( *p && isspace(*p) ) p++;
	if( !(*p == '\"' || *p == '\'') )
		return;
	q = p+strlen(p);
	while( *q != *p && q > p ) q--;
	if( q == p )
		return;
	int len = int(q - p - 1);
	memmove( buf, p+1, len );
	buf[len] = 0;
}

static char *pathmv = "/bin/mv";

int getProfileString( const char *section,
					 const char *entry,
					 const char *defaultString,
					 char *buffer,
					 int   bufLen,
					 const char *fileName )
{
	// Open sourceFile
	FILE *FP;
	if ( (FP = fopen( fileName, "r" )) == NULL )
	{
		strcpy( buffer, defaultString );
		return strlen(buffer);
	}
	char sLine[256];
	bool bFoundSection = false;
	bool bFoundEntry = false;
	char curSection[256];
	char curKey[256];
	char curValue[256];
	while ( fgets( sLine, 256, FP ) )
	{
		if ( getSection( sLine, curSection ) )
		{
			if ( strcmp( curSection, section ) == 0 )

				bFoundSection = true;
			else
				bFoundSection = false;
		}
		else if ( getEntry( sLine, curKey, curValue ) )
		{
			int i;
			int x = strlen(curKey);
			for (i = x-1; i >=  0; i--)
			{
				if (curKey[i] == ' ') curKey[i] = 0;
				else
					break;
			}	   
			if ( bFoundSection && (strcmp(curKey,entry) == 0) )
			{
				bFoundEntry = true;
				break;
			}
		}
	}
	fclose( FP );
	if ( bFoundEntry ) 
		strcpy( buffer, curValue );
	else 
		strcpy( buffer, defaultString );
	lTrim(buffer);
	stripQuotationChar( buffer );
	if (sLine[0] == ' ')
	{
		char tmp[256];
		strcpy(tmp, sLine);
	}
	return strlen(buffer);
}

int getProfileInt( const char *section,
				  const char *entry,
				  int defaultInt,
				  const char *fileName )
{
	char buf[256];
	char iBuf[34];   //"34" is max space "itoa" required under 32 bit C++
	sprintf(iBuf, "%d", defaultInt);
	getProfileString( section, entry, iBuf, buf, 256, fileName );
	return atoi( buf );
}

float getProfileFloat( const char *section,
					  const char *entry,
					  float defaultInt,
					  const char *fileName )
{
	char buf[256];
	char iBuf[68];   //"34" is max space "itoa" required under 32 bit C++
	sprintf(iBuf, "%f", defaultInt);
	getProfileString( section, entry, iBuf, buf, 256, fileName );
	return (float)atof( buf );
}

int writeProfileString( const char *section,
					   const char *entry,
					   const char *string,
					   const char *fileName )
{
	char tmpfileName[256];
	// work better on network!
	strcpy( tmpfileName, tmpnam(0) );
	// Open tmpFile
	FILE *FPtmp;
	if ( (FPtmp = fopen( tmpfileName, "w")) == NULL )
		return 0;
	// Open sourceFile
	FILE *FPsource;
	if ( (FPsource = fopen( fileName, "r" )) == NULL )
	{
		FPsource = fopen( fileName, "w" );
		if ( FPsource == NULL )
			return 0;
		fclose( FPsource );
		FPsource = fopen( fileName, "r" );
		if ( FPsource == NULL )
		{
			unlink( fileName );
			return 0;
		}
	}
	// Write Source to Tmp
	char sLine[256];
	char curSection[256];
	char curKey[256];
	char curValue[256];
	bool bDone = false;
	bool bInSection = false;
	while ( fgets( sLine, 256, FPsource ) )
	{
		if ( getSection( sLine, curSection ) )
		{
			if ( strcmp( curSection, section ) == 0 )
			{
				bInSection = true;
			}
			else
			{
				if ( bInSection )
				{
					bInSection = false;

					if ( !bDone )
					{
						bDone = true;
						writeEntry( entry, string, FPtmp );
					}
				}
			}
			writeSection( curSection, FPtmp );
		}
		else if ( getEntry( sLine, curKey, curValue ) )
		{
			if ( bInSection && (strcmp( curKey, entry ) == 0) )
			{
				bDone = true;
				writeEntry( curKey, string, FPtmp );
			}
			else 
				writeEntry( curKey, curValue, FPtmp );
		}
	}
	if ( !bDone )
	{
		bDone = true;
		if ( !bInSection )
			writeSection( section, FPtmp );
		writeEntry( entry, string, FPtmp );
	}
	fclose( FPsource );
	fclose( FPtmp );
	// Copy Tmp to Source
	if ( unlink( fileName ) == -1 )
	{
		unlink( tmpfileName );
		return 0;
	}
#ifndef WIN32
	char execstr[256];
	sprintf( execstr, "%s %s %s", pathmv, tmpfileName, fileName );
	if ( system( execstr ) == -1 )
		return 0;
#else
	int result;
	result= rename( tmpfileName , fileName );
	if (result != 0 )
		perror( "Error renaming file" );
#endif
	// All successfully done
	return strlen( string );
}

int deleteProfileString( const char *section,
						const char *entry,
						const char *string,
						const char *fileName )
{
	char tmpfileName[256];
	// work better on network!
	strcpy( tmpfileName, tmpnam(0) );
	// Open tmpFile
	FILE *FPtmp;
	if ( (FPtmp = fopen( tmpfileName, "w")) == NULL )
	{
		return 0;
	}
	// Open sourceFile
	FILE *FPsource;
	if ( (FPsource = fopen( fileName, "r" )) == NULL )
	{
		FPsource = fopen( fileName, "w" );
		if ( FPsource == NULL )
			return 0;
		fclose( FPsource );
		FPsource = fopen( fileName, "r" );
		if ( FPsource == NULL )
		{
			unlink( fileName );
			return 0;
		}
	}
	// Write Source to Tmp
	char sLine[256];
	char curSection[256];
	char curKey[256];
	char curValue[256];
	bool bDone = false;
	bool bInSection = false;
	while ( fgets( sLine, 256, FPsource ) )
	{
		if ( getSection( sLine, curSection ) )
		{
			if ( strcmp( curSection, section ) == 0 )
			{
				bInSection = true;
			}
			else
			{
				if ( bInSection )
				{
					bInSection = false;
					if ( !bDone )
					{
						bDone = true;
						writeEntry( entry, string, FPtmp );
					}
				}
			}
			writeSection( curSection, FPtmp );
		}
		else if ( getEntry( sLine, curKey, curValue ) )
		{
			if ( bInSection && (strcmp( curKey, entry ) == 0) )
			{
				bDone = true;

				if ( (strcmp(curKey, entry) == 0) && (strcmp(curValue, string) == 0) )
				{
				} 
				else
				{
					writeEntry( curKey, string, FPtmp );
				}
			}
			else 
			{
				if ( (strcmp(curKey, entry) == 0) && (strcmp(curValue, string) == 0) )
				{
				} else
				{
					writeEntry( curKey, curValue, FPtmp );
				}
			}
		}
	}
	fclose( FPsource );
	fclose( FPtmp );
	// Copy Tmp to Source
	if ( unlink( fileName ) == -1 )
	{
		unlink( tmpfileName );
		return 0;
	}
#ifndef WIN32
	char execstr[256];
	sprintf( execstr, "%s %s %s", pathmv, tmpfileName, fileName );
	if ( system( execstr ) == -1 )
		return 0;
#else
	int result;
	result= rename( tmpfileName , fileName );
	if (result != 0 )
		perror( "Error renaming file" );
#endif
	// All successfully done
	return strlen( string );
}
