//**************************************************************************************************
//                                          Config.cpp                                             *
//                                         ------------                                            *
// Started     : 2016-09-25                                                                        *
// Last Update : 2017-05-28                                                                        *
// Copyright   : (C) 2016-2017 MSWaters                                                            *
//**************************************************************************************************

//**************************************************************************************************
//                                                                                                 *
//      This program 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 3 of the License, or (at your option) any later version.                    *
//                                                                                                 *
//**************************************************************************************************

#include "Config.hpp"

//**************************************************************************************************
// Allocate storage for static data members.

wxConfig * Config::m_poCfg = NULL;

//**************************************************************************************************
// Constructor.

Config::Config( void )
{
}

//**************************************************************************************************
// Destructor.

Config::~Config( )
{
}

//**************************************************************************************************
// Generic set functions for writing a value into the configuration object.
//
// Argument List :
//   rosGroup - The group name
//   rosKey   - The key (parameter) name
//   *Value   - The value to set
//
// Return Values :
//   Success - true
//   Failure - false

bool  Config::bSet( const wxString & rosGroup, const wxString & rosKey, int iValue )
{
  // The configuration object must be closed
  if( ! bIsOpen( ) ) return( false );

  m_poCfg->SetPath( rosGroup );
  m_poCfg->Write( rosKey, iValue );

  return( true );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSet( const wxString & rosGroup, const wxString & rosKey, bool bValue )
{
  // The configuration object must be closed
  if( ! bIsOpen( ) ) return( false );

  m_poCfg->SetPath( rosGroup );
  m_poCfg->Write( rosKey, bValue );

  return( true );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSet( const wxString & rosGroup, const wxString & rosKey, const wxString & rosValue )
{
  // The configuration object must be closed
  if( ! bIsOpen( ) ) return( false );

  m_poCfg->SetPath( rosGroup );
  m_poCfg->Write( rosKey, rosValue );

  return( true );
}

//**************************************************************************************************
// Generic get functions for reading a value from the configuration object.
//
// Argument List :
//   rosGroup - The group name
//   rosKey   - The key (parameter) name
//   *Default - The default value
//
// Return Values :
//   Success - The configuration value
//   Failure - The default       value

int  Config::iGet( const wxString & rosGroup, const wxString & rosKey, int iDefault )
{
  long  li1;

  if( bIsOpen( ) )
  {
    m_poCfg->SetPath( rosGroup );
    m_poCfg->Read( rosKey, &li1, long( iDefault ) );
  }
  else li1 = long( iDefault );

  return( int( li1 ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bGet( const wxString & rosGroup, const wxString & rosKey, bool bDefault )
{
  bool  b1;

  if( bIsOpen( ) )
  {
    m_poCfg->SetPath( rosGroup );
    m_poCfg->Read( rosKey, &b1, bDefault );
  }
  else b1 = bDefault;

  return( b1 );
}

//--------------------------------------------------------------------------------------------------

const wxString & Config::rosGet( const wxString & rosGroup, const wxString & rosKey,
                                 const wxString & rosDefault )
{
  static  wxString  os1;

  if( bIsOpen( ) )
  {
    m_poCfg->SetPath( rosGroup );
    m_poCfg->Read( rosKey, &os1, rosDefault );
  }
  else os1 = rosDefault;

  return( os1 );
}

//**************************************************************************************************
// Open a configuration file.
//
// Argument List :
//   rosFileName - A string containing the configuration file name, if empty use m_oFileName
//
// Return Values :
//   Success - true
//   Failure - false

bool  Config::bOpen( const wxString & rosFileName )
{
  wxConfig  * poCfg;
  wxFileName  ofn1;

  // A configuration file must be open
  if( bIsOpen( ) )                      return( false );

  // Set the RC file name
  if( ! rosFileName.IsEmpty( ) )
    if( ! bSetFileName( rosFileName ) ) return( false );

  // Configure and create the global configuration object
  m_poCfg = new wxConfig( wxEmptyString, wxEmptyString, m_oFileName.GetFullPath( ) );
  poCfg = (wxConfig *) wxConfig::Set( m_poCfg );
  if( poCfg != NULL ) delete poCfg;  // Delete the old wxConfig object if one exists

  // Record a default to the config file whenever attempting to read a value which is not present
  m_poCfg->SetRecordDefaults( true );

  return( true );
}

//**************************************************************************************************
// Close the configuration file.
//
// Return Values:
//   Success - true
//   Failure - false

bool  Config::bClose( void )
{
  // A configuration file must be open
  if( ! bIsOpen( ) ) return( true );

  // Delete the global configuration object
  delete wxConfig::Set( (wxConfig *) NULL );
  m_poCfg = NULL;

  return( true );
}

//**************************************************************************************************
// Permanently writes all changes to the configuration on disk.
//
// Return Values:
//   Success - true
//   Failure - false

bool  Config::bFlush( void )
{
  // A configuration file must be open
  if( ! bIsOpen( ) ) return( false );

  m_poCfg->Flush( );

  return( true );
}

//**************************************************************************************************
// Clean / rebuild the configuration file.
//
// Over time configuration options change, new ones are introduced, configuration groups change,
// names changes and old configuration options are dropped. Consequently a configuration file can
// become cluttered with outdated information. This function cleans out all this out-moded data.
//
// Return Values:
//   Success - true
//   Failure - false

bool  Config::bClean( void )
{
  bool  bRtn=true;

  // A configuration file must be open
  if( ! bIsOpen( ) ) return( false );

  // Create temporary storage for all configuration parameters
  uint             uiFrmLayout;    // MAIN       group
  eTypeTmpFileMgt  eTmpFileMgt;
  uint             uiPrecision;
  uint             uiNbkMaxLns;
  uint             uiSpnPeriod;
  bool             bToolTips;
  uint             uiToolTipDly;
  bool             bKeepNetLst;
  int              iMainPosnX;
  int              iMainPosnY;
  int              iMainSizeW;
  int              iMainSizeH;
  wxString         osNetLstFile;   // FILES      group
  wxString         osSchemFiles;
  wxString         osRecentFiles;
  wxString         osDirLastAcc;
  int              iHelpPosnX;     // HELP       group
  int              iHelpPosnY;
  int              iHelpSizeW;
  int              iHelpSizeH;
  bool             bVerboseMode;   // GNETLIST   group
  wxString         osGuileProc;
  bool             bIncludeMode;
  bool             bEmbedMode;
  bool             bNoMungeMode;
  eTypeSimEng      eSimEng;        // SIMULATOR  group
  eTypeCmd         eAnalysis;
  bool             bSyncSigSrcs;
  bool             bSyncTemps;
  bool             bAutoRegen;
  eTypeUnits       ePhaseUnits;
  wxString         osEdaSuite;     // EDA_SUITE  group
  eTypeViewer      eDataViewer;    // DATAVIEWER group

  // Get all configuration parameter values
  uiFrmLayout   = uiGetFrmLayout   ( );  // MAIN       group
  eTmpFileMgt   = eGetTmpFileMgt   ( );
  uiPrecision   = uiGetPrecision   ( );
  uiNbkMaxLns   = uiGetNbkMaxLns   ( );
  uiSpnPeriod   = uiGetSpnPeriod   ( );
  bToolTips     = bGetToolTips     ( );
  uiToolTipDly  = uiGetToolTipDly  ( );
  bKeepNetLst   = bGetKeepNetLst   ( );
  iMainPosnX    = iGetMainPosnX    ( );
  iMainPosnY    = iGetMainPosnY    ( );
  iMainSizeW    = iGetMainSizeW    ( );
  iMainSizeH    = iGetMainSizeH    ( );
  osNetLstFile  = rosGetNetLstFile ( );  // FILES      group
  osSchemFiles  = rosGetSchemFiles ( );
  osRecentFiles = rosGetRecentFiles( );
  osDirLastAcc  = rosGetDirLastAcc ( );
  iHelpPosnX    = iGetHelpPosnX    ( );  // HELP       group
  iHelpPosnY    = iGetHelpPosnY    ( );
  iHelpSizeW    = iGetHelpSizeW    ( );
  iHelpSizeH    = iGetHelpSizeH    ( );
  bVerboseMode  = bGetVerboseMode  ( );  // GNETLIST   group
  osGuileProc   = rosGetGuileProc  ( );
  bIncludeMode  = bGetIncludeMode  ( );
  bEmbedMode    = bGetEmbedMode    ( );
  bNoMungeMode  = bGetNoMungeMode  ( );
  eSimEng       = eGetSimEng       ( );  // SIMULATOR  group
  eAnalysis     = eGetAnalysis     ( );
  ePhaseUnits   = eGetPhaseUnits   ( );
  bSyncSigSrcs  = bGetSyncSigSrcs  ( );
  bSyncTemps    = bGetSyncTemps    ( );
  bAutoRegen    = bGetAutoRegen    ( );
  osEdaSuite    = rosGetEdaSuite   ( );  // EDA_SUITE  group
  eDataViewer   = eGetDataViewer   ( );  // DATAVIEWER group

  // Delete the whole underlying object (disk file, registry key, ...)
  m_poCfg->DeleteAll( );

  // Close this configuration object
  if( ! bClose( ) )                        bRtn = false;

  // Re-open this configuration object
  if( ! bOpen( ) )                         bRtn = false;

  // Re-build the configuration object
  if( ! bSetFrmLayout  ( uiFrmLayout   ) ) bRtn = false;  // MAIN       group
  if( ! bSetTmpFileMgt ( eTmpFileMgt   ) ) bRtn = false;
  if( ! bSetPrecision  ( uiPrecision   ) ) bRtn = false;
  if( ! bSetNbkMaxLns  ( uiNbkMaxLns   ) ) bRtn = false;
  if( ! bSetSpnPeriod  ( uiSpnPeriod   ) ) bRtn = false;
  if( ! bSetToolTips   ( bToolTips     ) ) bRtn = false;
  if( ! bSetToolTipDly ( uiToolTipDly  ) ) bRtn = false;
  if( ! bSetKeepNetLst ( bKeepNetLst   ) ) bRtn = false;
  if( ! bSetMainPosnX  ( iMainPosnX    ) ) bRtn = false;
  if( ! bSetMainPosnY  ( iMainPosnY    ) ) bRtn = false;
  if( ! bSetMainSizeW  ( iMainSizeW    ) ) bRtn = false;
  if( ! bSetMainSizeH  ( iMainSizeH    ) ) bRtn = false;
  if( ! bSetNetLstFile ( osNetLstFile  ) ) bRtn = false;  // FILES      group
  if( ! bSetSchemFiles ( osSchemFiles  ) ) bRtn = false;
  if( ! bSetRecentFiles( osRecentFiles ) ) bRtn = false;
  if( ! bSetDirLastAcc ( osDirLastAcc  ) ) bRtn = false;
  if( ! bSetHelpPosnX  ( iHelpPosnX    ) ) bRtn = false;  // HELP       group
  if( ! bSetHelpPosnY  ( iHelpPosnY    ) ) bRtn = false;
  if( ! bSetHelpSizeW  ( iHelpSizeW    ) ) bRtn = false;
  if( ! bSetHelpSizeH  ( iHelpSizeH    ) ) bRtn = false;
  if( ! bSetVerboseMode( bVerboseMode  ) ) bRtn = false;  // GNETLIST   group
  if( ! bSetGuileProc  ( osGuileProc   ) ) bRtn = false;
  if( ! bSetIncludeMode( bIncludeMode  ) ) bRtn = false;
  if( ! bSetEmbedMode  ( bEmbedMode    ) ) bRtn = false;
  if( ! bSetNoMungeMode( bNoMungeMode  ) ) bRtn = false;
  if( ! bSetSimEng     ( eSimEng       ) ) bRtn = false;  // SIMULATOR  group
  if( ! bSetAnalysis   ( eAnalysis     ) ) bRtn = false;
  if( ! bSetPhaseUnits ( ePhaseUnits   ) ) bRtn = false;
  if( ! bSetSyncSigSrcs( bSyncSigSrcs  ) ) bRtn = false;
  if( ! bSetSyncTemps  ( bSyncTemps    ) ) bRtn = false;
  if( ! bSetAutoRegen  ( bAutoRegen    ) ) bRtn = false;
  if( ! bSetEdaSuite   ( osEdaSuite    ) ) bRtn = false;  // EDA_SUITE  group
  if( ! bSetDataViewer ( eDataViewer   ) ) bRtn = false;  // DATAVIEWER group

  // Permanently writes all changes to the configuration on disk
  if( ! bFlush( ) )                        bRtn = false;

  return( bRtn );
}

//**************************************************************************************************
// Set the configuration file name.
//
// Note : if no path is specified the users home directory is assumed
//
// Argument List :
//   rosFileName - A string containing the configuration file name
//
// Return Values:
//   Success - true
//   Failure - false

bool  Config::bSetFileName( const wxString & rosFileName )
{
  wxFileName  ofn1;

  // The configuration object must be closed
  if( bIsOpen( ) )              return( false );

  // Check that the RC file name argument is valid (if no path is specified assume users home dir.)
  ofn1 = rosFileName;
#ifndef __WXMSW__
  if( ofn1.GetPath( ).IsEmpty( ) ) ofn1.SetPath( wxGetenv( wxT("HOME") ) );
#else
  if( ofn1.GetPath( ).IsEmpty( ) ) ofn1.SetPath( wxGetenv( wxT("USERPROFILE") ) );
#endif
  if( ! ofn1.IsDirWritable( ) ) return( false );

  // Check that the file name attribute it valid
  if( ! ofn1.IsOk( ) )          return( false );

  // Set the object attribute
  m_oFileName = ofn1;

  return( true );
}

//**************************************************************************************************
// Get the configuration file name as a string.
//
// Return Values:
//   The configuration file name or an empty string

const wxString & Config::rosGetFileName( void )
{
  static  wxString  osFileName;

  osFileName = m_oFileName.GetFullPath( );

  return( osFileName );
}

//**************************************************************************************************
// Set configuration parameter value functions.
//
// Argument List :
//   The configuration parameter value to be updated
//
// Return Values:
//   Success - true
//   Failure - false

bool  Config::bSetFrmLayout( uint uiLayout )
{
  return( bSet( wxT("/MAIN"), wxT("FrmLayout"), int( uiLayout ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetTmpFileMgt( eTypeTmpFileMgt eTmpFileMgt )
{
  return( bSet( wxT("/MAIN"), wxT("TmpFileMgt"), int( eTmpFileMgt ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetPrecision( uint uiFltRes )
{
  return( bSet( wxT("/MAIN"), wxT("Precision"), int( uiFltRes ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetNbkMaxLns( uint uiLnCnt )
{
  return( bSet( wxT("/MAIN"), wxT("NbkMaxLns"), int( uiLnCnt ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetSpnPeriod( uint ui_mSec )
{
  return( bSet( wxT("/MAIN"), wxT("SpnPeriod"), int( ui_mSec ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetToolTips( bool bEnable )
{
  return( bSet( wxT("/MAIN"), wxT("ToolTips"), bEnable ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetToolTipDly( uint ui_mSec )
{
  return( bSet( wxT("/MAIN"), wxT("ToolTipDly"), int( ui_mSec ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetKeepNetLst( bool bEnable )
{
  return( bSet( wxT("/MAIN"), wxT("KeepNetLst"), bEnable ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetMainPosnX( int iPosnX )
{
  return( bSet( wxT("/MAIN"), wxT("PosnX"), iPosnX ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetMainPosnY( int iPosnY )
{
  return( bSet( wxT("/MAIN"), wxT("PosnY"), iPosnY ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetMainSizeW( int iSizeW )
{
  return( bSet( wxT("/MAIN"), wxT("SizeW"), iSizeW ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetMainSizeH( int iSizeH )
{
  return( bSet( wxT("/MAIN"), wxT("SizeH"), iSizeH ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetHelpPosnX( int iPosnX )
{
  return( bSet( wxT("/HELP"), wxT("PosnX"), iPosnX ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetHelpPosnY( int iPosnY )
{
  return( bSet( wxT("/HELP"), wxT("PosnY"), iPosnY ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetHelpSizeW( int iSizeW )
{
  return( bSet( wxT("/HELP"), wxT("SizeW"), iSizeW ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetHelpSizeH( int iSizeH )
{
  return( bSet( wxT("/HELP"), wxT("SizeH"), iSizeH ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetNetLstFile( const wxString & rosFile )
{
  return( bSet( wxT("/FILES"), wxT("NetList"), rosFile ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetSchemFiles( const wxString & rosFiles )
{
  return( bSetSchemFiles( roasStrToArr( rosFiles ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetSchemFiles( const wxArrayString & roasFiles )
{
  return( bSet( wxT("/FILES"), wxT("Schematics"), rosArrToStr( roasFiles ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetRecentFiles( const wxString & rosFiles )
{
  return( bSetRecentFiles( roasStrToArr( rosFiles ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetRecentFiles( const wxArrayString & roasFiles )
{
  return( bSet( wxT("/FILES"), wxT("Recent"), rosArrToStr( roasFiles ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetDirLastAcc( const wxString & rosFile )
{
  return( bSet( wxT("/FILES"), wxT("DirLastAcc"), rosFile ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetVerboseMode( bool bEnable )
{
  return( bSet( wxT("/GNETLIST"), wxT("VerboseMode"), bEnable ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetGuileProc( const wxString & rosGuileProc )
{
  return( bSet( wxT("/GNETLIST"), wxT("GuileProc"), rosGuileProc ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetIncludeMode( bool bEnable )
{
  return( bSet( wxT("/GNETLIST"), wxT("IncludeMode"), bEnable ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetEmbedMode( bool bEnable )
{
  return( bSet( wxT("/GNETLIST"), wxT("EmbedMode"), bEnable ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetNoMungeMode( bool bEnable )
{
  return( bSet( wxT("/GNETLIST"), wxT("NoMungeMode"), bEnable ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetSimEng( const wxString & rosSimEng )
{
  // Check that the viewer name is valid
  if( eStrToEnumEng( rosSimEng ) == eSIMR_NONE ) return( false );

  return( bSet( wxT("/SIMULATOR"), wxT("Engine"), rosSimEng ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetSimEng( eTypeSimEng eSimEng )
{
  return( bSetSimEng( rosEnumEngToStr( eSimEng ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetAnalysis( eTypeCmd eAnalysis )
{
  return( bSet( wxT("/SIMULATOR"), wxT("Analysis"), rosEnumCmdToStr( eAnalysis ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetPhaseUnits( eTypeUnits eUnits )
{
  return( bSet( wxT("/SIMULATOR"), wxT("PhaseUnits"), int( eUnits ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetSyncSigSrcs( bool bEnable )
{
  return( bSet( wxT("/SIMULATOR"), wxT("SyncSigSrcs"), bEnable ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetSyncTemps( bool bEnable )
{
  return( bSet( wxT("/SIMULATOR"), wxT("SyncTemps"), bEnable ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetAutoRegen( bool bEnable )
{
  return( bSet( wxT("/SIMULATOR"), wxT("AutoRegen"), bEnable ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetEdaSuite( const wxString & rosEdaSuite )
{
  return( bSet( wxT("/EDA_SUITE"), wxT("Project"), rosEdaSuite ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetEdaSuite( eTypeEDA eEDA )
{
  return( bSetEdaSuite( rosEnumEdaToStr( eEDA ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetDataViewer( const wxString & rosDataViewer )
{
  // Check that the viewer name is valid
  if( eStrToEnumVwr( rosDataViewer ) == eVIEW_NONE ) return( false );

  return( bSet( wxT("/DATAVIEWER"), wxT("Utility"), rosDataViewer ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bSetDataViewer( eTypeViewer eDataViewer )
{
  return( bSetDataViewer( rosEnumVwrToStr( eDataViewer ) ) );
}

//**************************************************************************************************
// Get configuration parameter value functions.
//
// Return Values:
//   Success - The value stored in the configuration file
//   Failure - The default value

uint  Config::uiGetFrmLayout( void )
{
  return( iGet( wxT("/MAIN"), wxT("FrmLayout"), CFG_DEF_FRMLAYOUT ) );
}

//--------------------------------------------------------------------------------------------------

eTypeTmpFileMgt  Config::eGetTmpFileMgt( void )
{
  return( (eTypeTmpFileMgt) iGet( wxT("/MAIN"), wxT("TmpFileMgt"), CFG_DEF_TMPFILEMGT ) );
}

//--------------------------------------------------------------------------------------------------

uint  Config::uiGetPrecision( void )
{
  return( uint( iGet( wxT("/MAIN"), wxT("Precision"), CFG_DEF_PRECISION ) ) );
}

//--------------------------------------------------------------------------------------------------

uint  Config::uiGetNbkMaxLns( void )
{
  return( uint( iGet( wxT("/MAIN"), wxT("NbkMaxLns"), CFG_DEF_NBKMAXLNS ) ) );
}

//--------------------------------------------------------------------------------------------------

uint  Config::uiGetSpnPeriod( void )
{
  return( uint( iGet( wxT("/MAIN"), wxT("SpnPeriod"), CFG_DEF_SPNPERIOD ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bGetToolTips( void )
{
  return( bGet( wxT("/MAIN"), wxT("ToolTips"), CFG_DEF_TOOLTIPS ) );
}

//--------------------------------------------------------------------------------------------------

uint  Config::uiGetToolTipDly( void )
{
  return( uint( iGet( wxT("/MAIN"), wxT("ToolTipDly"), CFG_DEF_TOOLTIPDLY ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bGetKeepNetLst( void )
{
  return( bGet( wxT("/MAIN"), wxT("KeepNetLst"), CFG_DEF_KEEPNETLST ) );
}

//--------------------------------------------------------------------------------------------------

int  Config::iGetMainPosnX( void )
{
  return( iGet( wxT("/MAIN"), wxT("PosnX"), CFG_DEF_MAINPOSNX ) );
}

//--------------------------------------------------------------------------------------------------

int  Config::iGetMainPosnY( void )
{
  return( iGet( wxT("/MAIN"), wxT("PosnY"), CFG_DEF_MAINPOSNY ) );
}

//--------------------------------------------------------------------------------------------------

int  Config::iGetMainSizeW( void )
{
  return( iGet( wxT("/MAIN"), wxT("SizeW"), CFG_DEF_MAINSIZEW ) );
}

//--------------------------------------------------------------------------------------------------

int  Config::iGetMainSizeH( void )
{
  return( iGet( wxT("/MAIN"), wxT("SizeH"), CFG_DEF_MAINSIZEH ) );
}

//--------------------------------------------------------------------------------------------------

int  Config::iGetHelpPosnX( void )
{
  return( iGet( wxT("/HELP"), wxT("PosnX"), CFG_DEF_HELPPOSNX ) );
}

//--------------------------------------------------------------------------------------------------

int  Config::iGetHelpPosnY( void )
{
  return( iGet( wxT("/HELP"), wxT("PosnY"), CFG_DEF_HELPPOSNY ) );
}

//--------------------------------------------------------------------------------------------------

int  Config::iGetHelpSizeW( void )
{
  return( iGet( wxT("/HELP"), wxT("SizeW"), CFG_DEF_HELPSIZEW ) );
}

//--------------------------------------------------------------------------------------------------

int  Config::iGetHelpSizeH( void )
{
  return( iGet( wxT("/HELP"), wxT("SizeH"), CFG_DEF_HELPSIZEH ) );
}

//--------------------------------------------------------------------------------------------------

const wxString & Config::rosGetNetLstFile( void )
{
  return( rosGet( wxT("/FILES"), wxT("NetList"), wxEmptyString ) );
}

//--------------------------------------------------------------------------------------------------

const wxString & Config::rosGetSchemFiles( void )
{
  return( rosArrToStr( roasGetSchemFiles( ) ) );
}

//--------------------------------------------------------------------------------------------------

const wxArrayString & Config::roasGetSchemFiles( void )
{
  return( roasStrToArr( rosGet( wxT("/FILES"), wxT("Schematics"), wxEmptyString ) ) );
}

//--------------------------------------------------------------------------------------------------

const wxString & Config::rosGetRecentFiles( void )
{
  return( rosArrToStr( roasGetRecentFiles( ) ) );
}

//--------------------------------------------------------------------------------------------------

const wxArrayString & Config::roasGetRecentFiles( void )
{
  return( roasStrToArr( rosGet( wxT("/FILES"), wxT("Recent"), wxEmptyString ) ) );
}

//--------------------------------------------------------------------------------------------------

const wxString & Config::rosGetDirLastAcc( void )
{
  return( rosGet( wxT("/FILES"), wxT("DirLastAcc"), wxGetHomeDir( ) ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bGetVerboseMode( void )
{
  return( bGet( wxT("/GNETLIST"), wxT("VerboseMode"), CFG_DEF_VERBOSEMODE ) );
}

//--------------------------------------------------------------------------------------------------

const wxString & Config::rosGetGuileProc( void )
{
  return( rosGet( wxT("/GNETLIST"), wxT("GuileProc"), CFG_DEF_GUILEPROC ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bGetIncludeMode( void )
{
  return( bGet( wxT("/GNETLIST"), wxT("IncludeMode"), CFG_DEF_INCLUDEMODE ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bGetEmbedMode( void )
{
  return( bGet( wxT("/GNETLIST"), wxT("EmbedMode"), CFG_DEF_EMBEDMODE ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bGetNoMungeMode( void )
{
  return( bGet( wxT("/GNETLIST"), wxT("NoMungeMode"), CFG_DEF_NOMUNGEMODE ) );
}

//--------------------------------------------------------------------------------------------------

const wxString & Config::rosGetSimEng( void )
{
  return( rosGet( wxT("/SIMULATOR"), wxT("Engine"), CFG_DEF_SIMENG ) );
}

//--------------------------------------------------------------------------------------------------

eTypeSimEng  Config::eGetSimEng( void )
{
  return( eStrToEnumEng( rosGetSimEng( ) ) );
}

//--------------------------------------------------------------------------------------------------

eTypeCmd  Config::eGetAnalysis( void )
{
  return( eStrToEnumCmd( rosGet( wxT("/SIMULATOR"), wxT("Analysis"), CFG_DEF_ANALYSIS ) ) );
}

//--------------------------------------------------------------------------------------------------

eTypeUnits  Config::eGetPhaseUnits( void )
{
  return( (eTypeUnits) iGet( wxT("/SIMULATOR"), wxT("PhaseUnits"), CFG_DEF_PHASEUNITS ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bGetSyncSigSrcs( void )
{
  return( bGet( wxT("/SIMULATOR"), wxT("SyncSigSrcs"), CFG_DEF_SYNCSIGSRCS ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bGetSyncTemps( void )
{
  return( bGet( wxT("/SIMULATOR"), wxT("SyncTemps"), CFG_DEF_SYNCTEMPS ) );
}

//--------------------------------------------------------------------------------------------------

bool  Config::bGetAutoRegen( void )
{
  return( bGet( wxT("/SIMULATOR"), wxT("AutoRegen"), CFG_DEF_AUTOREGEN ) );
}

//--------------------------------------------------------------------------------------------------

const wxString & Config::rosGetEdaSuite( void )
{
  return( rosGet( wxT("/EDA_SUITE"), wxT("Project"), CFG_DEF_EDASUITE ) );
}

//--------------------------------------------------------------------------------------------------

eTypeEDA  Config::eGetEdaSuite( void )
{
  return( eStrToEnumEda( rosGetEdaSuite( ) ) );
}

//--------------------------------------------------------------------------------------------------

const wxString & Config::rosGetDataViewer( void )
{
  return( rosGet( wxT("/DATAVIEWER"), wxT("Utility"), CFG_DEF_DATAVIEWER ) );
}

//--------------------------------------------------------------------------------------------------

eTypeViewer  Config::eGetDataViewer( void )
{
  return( eStrToEnumVwr( rosGetDataViewer( ) ) );
}

//**************************************************************************************************
// Print the object attributes.
//
// Argument List :
//   rosPrefix - A prefix to every line displayed (usually just spaces)

void  Config::Print( const wxString & rosPrefix )
{
  wxString  osPrefix;

  osPrefix = rosPrefix + wxT( "Config::" );

  std::cout << osPrefix.mb_str( ) << "rosGetFileName( )    : " << rosGetFileName( ).mb_str( ) << '\n';
  std::cout << '\n';

  // MAIN group
  std::cout << osPrefix.mb_str( ) << "eGetTmpFileMgt( )    : " << eGetTmpFileMgt( )         << '\n';
  std::cout << osPrefix.mb_str( ) << "uiGetFrmLayout( )    : " << uiGetFrmLayout( )         << '\n';
  std::cout << osPrefix.mb_str( ) << "uiGetPrecision( )    : " << uiGetPrecision( )         << '\n';
  std::cout << osPrefix.mb_str( ) << "uiGetNbkMaxLns( )    : " << uiGetNbkMaxLns( )         << '\n';
  std::cout << osPrefix.mb_str( ) << "uiGetSpnPeriod( )    : " << uiGetSpnPeriod( )         << '\n';
  std::cout << osPrefix.mb_str( ) << "bGetToolTips( )      : " << (bGetToolTips()?"true":"false") << '\n';
  std::cout << osPrefix.mb_str( ) << "iGetMainPosnX( )     : " << iGetMainPosnX( )          << '\n';
  std::cout << osPrefix.mb_str( ) << "iGetMainPosnY( )     : " << iGetMainPosnY( )          << '\n';
  std::cout << osPrefix.mb_str( ) << "iGetMainSizeW( )     : " << iGetMainSizeW( )          << '\n';
  std::cout << osPrefix.mb_str( ) << "iGetMainSizeH( )     : " << iGetMainSizeH( )          << '\n';
  std::cout << '\n';

  // HELP group
  std::cout << osPrefix.mb_str( ) << "iGetHelpPosnX( )     : " << iGetHelpPosnX( )          << '\n';
  std::cout << osPrefix.mb_str( ) << "iGetHelpPosnY( )     : " << iGetHelpPosnY( )          << '\n';
  std::cout << osPrefix.mb_str( ) << "iGetHelpSizeW( )     : " << iGetHelpSizeW( )          << '\n';
  std::cout << osPrefix.mb_str( ) << "iGetHelpSizeH( )     : " << iGetHelpSizeH( )          << '\n';
  std::cout << '\n';

  // FILES group
  std::cout << osPrefix.mb_str( ) << "rosGetNetLstFile( )  : " << rosGetNetLstFile( ) .mb_str( ) << '\n';
  std::cout << osPrefix.mb_str( ) << "rosGetSchemFiles( )  : " << rosGetSchemFiles( ) .mb_str( ) << '\n';
  std::cout << osPrefix.mb_str( ) << "rosGetRecentFiles( ) : " << rosGetRecentFiles( ).mb_str( ) << '\n';
  std::cout << osPrefix.mb_str( ) << "rosGetDirLastAcc( )  : " << rosGetDirLastAcc( ) .mb_str( ) << '\n';
  std::cout << '\n';

  // GNETLIST group
  std::cout << osPrefix.mb_str( ) << "rosGetGuileProc( )   : " << rosGetGuileProc( ).mb_str( ) << '\n';
  std::cout << '\n';

  // SIMULATOR group
  std::cout << osPrefix.mb_str( ) << "rosGetSimEng( )      : " << rosGetSimEng( ).mb_str( ) << '\n';
  std::cout << osPrefix.mb_str( ) << "eGetPhaseUnits( )    : " << eGetPhaseUnits( )         << '\n';
  std::cout << osPrefix.mb_str( ) << "bGetSyncSigSrcs( )   : " << (bGetSyncSigSrcs()?"true":"false") << '\n';
  std::cout << '\n';

  // SCHEMEDIT group
  std::cout << osPrefix.mb_str( ) << "rosGetEdaSuite( )    : " << rosGetEdaSuite( ).mb_str( ) << '\n';

  // DATAVIEWER group
  std::cout << osPrefix.mb_str( ) << "rosGetDataViewer( )  : " << rosGetDataViewer( ).mb_str( ) << '\n';
}

//**************************************************************************************************
//                                          Test Utility                                           *
//**************************************************************************************************

#ifdef TEST_CONFIG

using  namespace  std;

// wxWidgets Includes

#include <wx/cmdline.h>

// Function prototypes

void  Usage( char * psAppName );

// Declare a structure defining the command line syntax
static  const  wxCmdLineEntryDesc  tCmdLnDesc[] =
{
#if wxCHECK_VERSION( 3,0,0 )
  { wxCMD_LINE_SWITCH, "h", "", "", wxCMD_LINE_VAL_NONE  , wxCMD_LINE_OPTION_HELP      },
  { wxCMD_LINE_SWITCH, "c", "", "", wxCMD_LINE_VAL_NONE                                },
  { wxCMD_LINE_SWITCH, "p", "", "", wxCMD_LINE_VAL_NONE                                },
  { wxCMD_LINE_OPTION, "r", "", "", wxCMD_LINE_VAL_STRING, wxCMD_LINE_OPTION_MANDATORY },
#else
  { wxCMD_LINE_SWITCH, wxT("h"), wxT(""), wxT(""), wxCMD_LINE_VAL_NONE  , wxCMD_LINE_OPTION_HELP      },
  { wxCMD_LINE_SWITCH, wxT("c"), wxT(""), wxT(""), wxCMD_LINE_VAL_NONE                                },
  { wxCMD_LINE_SWITCH, wxT("p"), wxT(""), wxT(""), wxCMD_LINE_VAL_NONE                                },
  { wxCMD_LINE_OPTION, wxT("r"), wxT(""), wxT(""), wxCMD_LINE_VAL_STRING, wxCMD_LINE_OPTION_MANDATORY },
#endif
  { wxCMD_LINE_NONE }
};

//**************************************************************************************************

int  main( int argc, char * argv[ ] )
{
  // This function is used in wxBase only and only if an wxApp object isn't created at all. In this
  // case wxInitialize( ) must be called in main( ) before calling any other wxWidgets functions.
  if( ! wxInitialize( ) ) exit( EXIT_FAILURE );

  wxCmdLineParser  oCmdLn;
  wxFileName       oFName;
  wxString         osFName;

  // Setup the command line parser object and process the command line
  oCmdLn.SetDesc( tCmdLnDesc );
  oCmdLn.SetCmdLine( argc, argv );
  if( oCmdLn.Parse( false ) != 0 ) { Usage( argv[0] ); exit( EXIT_FAILURE ); }
  if( oCmdLn.Found( wxT("h") ) )   { Usage( argv[0] ); exit( EXIT_SUCCESS ); }
  oCmdLn.Found( wxT("r"), &osFName );
  oFName = osFName;
  if( oFName.GetPath( ).IsEmpty( ) ) oFName.SetPath( wxGetenv( wxT("PWD") ) );

  // Create the Config object
  Config  oConfig;

  // Display the utility banner
  std::cout << "\n  Config Class Test Utility"
            << "\n  Version 0.65 (2016-10-10)\n";

  // Configure and create the global configuration object
  if( ! oConfig.bOpen( oFName.GetFullPath( ) ) )
  {
    std::cout << "\nCouldn't open file : " << oFName.GetFullPath( ).mb_str( ) << "\n\n";
    exit( EXIT_FAILURE );
  }

  if( oCmdLn.Found( wxT("c") ) )
  {
    std::cout << "\nClean / rebuild the configuration file : "
              << ( oConfig.bClean( ) ? "Success" : "Failure" ) << "\n\n";
  }
  if( oCmdLn.Found( wxT("p") ) )
  {
    std::cout << "\nPrint oConfig attributes :\n\n";
    oConfig.Print( );
    cout << "\n";
  }

  // This function must be called for each successful call to wxInitialize( ). Clean up; the library
  // can't be used any more.
  wxUninitialize( );

  exit( EXIT_SUCCESS );
}

//**************************************************************************************************

void  Usage( char * psAppName )
{
  std::cout << "\nUsage   : " << psAppName << " [-OPTIONS] [FILE]"
            << "\nOptions : -h        : Print usage (this message)"
            << "\n          -r RCFILE : Specify a configuration file"
            << "\n          -c        : Rebuild/clean the configuration file"
            << "\n          -p        : Print configuration object attributes"
            << "\n\n";
}

#endif // TEST_CONFIG

//**************************************************************************************************
