// INIFile.cpp: implementation of the INIFile class.
//
//////////////////////////////////////////////////////////////////////

#include "INIFile.h"
#include <direct.h>


int  INIFile::m_iOutLen = BUFLEN;
//char INIFile::Text[ BUFLEN];
//int  INIFile::m_iCopy = 0;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
INIFile::INIFile()
{

  SECURITY_ATTRIBUTES sa = { sizeof( SECURITY_ATTRIBUTES),
                             NULL,
                             TRUE };

  //invalid semaphore handle
  m_hSemaphore = NULL;

  //build the buffers for keys and sections etc.
  Text = new char [299];
  m_cDefault = new char [m_iOutLen];
  m_cKey = new char [m_iOutLen];
  m_cSection = new char [m_iOutLen];

  //clear the section
  m_cSection[ 0] = '\0';
  m_cDefault[ 0] = '\0';

  m_iCopy = 1;

  //get a unnamed semaphore
  if ((m_hSemaphore = CreateSemaphore( &sa, 1, 1, NULL)) == NULL)
    return;
}

void INIFile::Create( char *FileName, char *Dir)
{

  char temp[ _MAX_PATH];


  //use the application name if there is no filename given
  if (FileName == NULL)
    strcpy( m_cFileName, AfxGetApp()->m_pszExeName);

  //save the filename
  if (Dir == NULL)
  {

    strcpy( temp, AfxGetApp()->m_pszHelpFilePath);
    temp[ strlen( temp) - 4 - strlen( AfxGetApp()->m_pszExeName)] = '\0';
    strcat( temp, m_cFileName);
    strcat(temp, ".ini");
    strcpy( Dir, temp);
  }
  else
    strcat( strcat( strcat( strcpy( m_cFileName, Dir), "\\"), FileName), ".ini");
}


//////////////////////////////////////////////////////////////////////
// Destruction
//////////////////////////////////////////////////////////////////////
INIFile::~INIFile()
{

  //reduce the count of copies, the last one will free our resources
  if (m_iCopy)
    if(--m_iCopy) return;

  //delete char buffers
  delete [] Text;
  delete [] m_cDefault;
  delete [] m_cKey;
  delete [] m_cSection;

  if (m_hSemaphore)
    CloseHandle( m_hSemaphore);
}

/////////////////////////////////////////////////////////////////////////////
// INIFile::INIFile(const INIFile &)
// 
// Copy constructor
/////////////////////////////////////////////////////////////////////////////
INIFile::INIFile(const INIFile &obj)
{

  //copy the values
  Text = obj.Text;
  m_cDefault = obj.m_cDefault;
  strcpy( m_cFileName, obj.m_cFileName);
  m_cKey = obj.m_cKey;
  m_cSection = obj.m_cSection;
  m_hSemaphore = obj.m_hSemaphore;
  m_iCopy++;
}

//////////////////////////////////////////////////////////////////////
// Get string from ini file
//////////////////////////////////////////////////////////////////////
const char *INIFile::GetString( const char *Key, const char *Section, const char *Default, int WriteDef)
{


  //clear the output text
  Text[ 0] = '\0';

  if ((Key == NULL) || !strlen(Key))
    return Text;

  //get the default string
  if (Default == NULL)
    m_cDefault[ 0] ='\0';
  else
    strcpy( m_cDefault, Default);

  //get the section name
  if (Section != NULL)
    strcpy( m_cSection, Section);

  //get the key
  strcpy( m_cKey, Key);

  //lock the file 
  Lock();

  //get the string
  GetPrivateProfileString( m_cSection, m_cKey, Text, Text, m_iOutLen, m_cFileName);

  //write the default string
  if (!strlen( Text) && WriteDef)
    WritePrivateProfileString(m_cSection, m_cKey, strcpy( Text, m_cDefault), m_cFileName);

  //release the file for other users
  UnLock();

  //return a pointer to the string
  return Text;
}


//////////////////////////////////////////////////////////////////////
// Put string in ini file
//////////////////////////////////////////////////////////////////////
void INIFile::PutString( char *Input, char *Key, char *Section)
{


  //get the section name
  if (Section != NULL)
    strcpy( m_cSection, Section);

  //get the key
  strcpy( m_cKey, Key);

  //lock the file 
  Lock();

  //write the string in the ini file
  WritePrivateProfileString(m_cSection, m_cKey, Input, m_cFileName);

  //release the file for other users
  UnLock();
}


//////////////////////////////////////////////////////////////////////
// Get integer from ini file
//////////////////////////////////////////////////////////////////////
int INIFile::GetInteger(const char *Key, const char *Section, int Default, int WriteDef)
{

  char temp[ BUFLEN];


  //make sure the default is integer
  strcpy( m_cDefault, _itoa( Default, temp, DECIMAL));

  //read first teh string
  GetString( Key, Section, m_cDefault, WriteDef);

  //convert string to int
  return atoi( Text);
}


//////////////////////////////////////////////////////////////////////
// Put string in ini file
//////////////////////////////////////////////////////////////////////
void INIFile::PutInteger(int Number, char *Key, char *Section)
{

  char temp[ BUFLEN];


  PutString( _itoa( Number, temp, DECIMAL), Key, Section);
}


//////////////////////////////////////////////////////////////////////
// Lock the INI file for exclusive use
//////////////////////////////////////////////////////////////////////
int INIFile::Lock()
{

  //check for valid semaphore
  if ((m_hSemaphore == NULL) || (m_hSemaphore == INVALID_HANDLE_VALUE))
    return FALSE;

  //wait untill port is released
  while (WaitForSingleObject( m_hSemaphore, INFINITE) != WAIT_OBJECT_0) ;

  return TRUE;
}


//////////////////////////////////////////////////////////////////////
// Unlock the INI file from exclusive use
//////////////////////////////////////////////////////////////////////
int INIFile::UnLock()
{

  //check for valid semaphore
  if ((m_hSemaphore == NULL) || (m_hSemaphore == INVALID_HANDLE_VALUE))
    return FALSE;

  //release the com port for internal use
  if (!ReleaseSemaphore( m_hSemaphore, 1, NULL))
    return FALSE;

  return TRUE;
}
