@ -6,11 +6,59 @@
# include "IRC.h"
# include "IWin/IWinStatus.h"
# include "MdiManager.h"
# include "IniFile.h"
# include "config.h"
# include <QInputDialog>
# include <QMessageBox>
# include <QDateTime>
# include <random>
# include <unordered_map>
# include <fstream>
# include <fmt/format.h>
namespace {
std : : unordered_map < int , IniFile > iniFiles ;
int iniFileHandleCount { 1 } ;
IniFile & getIniHandle ( const std : : string & callingFunctionName , int handle )
{
try {
return iniFiles . at ( handle ) ;
}
catch ( const std : : out_of_range & ) {
Builtin : : Error : : throwUnrecognizedIniHandle ( callingFunctionName , handle ) ;
}
}
bool createFileIfNotExists ( const std : : string & path )
{
/*
* Opening a file in ostream will create it if it doesn ' t exist .
* Tested with GNU stdlib ( Linux ) and Microsoft ' s stdlib ( Windows ) .
*/
std : : ofstream fs ( path , std : : fstream : : app ) ;
auto ok = fs . is_open ( ) ;
fs . close ( ) ;
return ok ;
}
std : : string setRelativePath ( const std : : string & path )
{
if ( path . empty ( ) )
return std : : string { } ;
# if defined(Q_OS_LINUX)
if ( path [ 0 ] ! = ' / ' ) {
# elif defined(Q_OS_WIN32) | defined(Q_OS_WIN64)
if ( path [ 1 ] ! = ' : ' ) {
# else
# error Update ScriptGeneralUtils.cpp setRelativePath to work with the target.
# endif
return fmt : : format ( " {}/{} " , LOCAL_PATH . toStdString ( ) , path ) ;
}
else {
return path ;
}
}
}
using namespace Builtin : : Error ;
@ -211,4 +259,279 @@ ValueHolder subwinname(Script&, std::vector<ValueHolder>& args)
return cwin - > getButtonText ( ) . toStdString ( ) ;
}
ValueHolder openini ( Script & , std : : vector < ValueHolder > & args )
{
if ( args . empty ( ) )
throwInsufficientParameters ( " openini " , args . size ( ) , 1 ) ;
if ( args [ 0 ] . getType ( ) ! = ValueHolder : : Type : : String )
throwNotAString ( " openini " , 1 ) ;
const std : : string fname = setRelativePath ( ValueExtract ( args [ 0 ] ) . toString ( ) ) ;
if ( ! createFileIfNotExists ( fname ) ) {
throw ScriptException ( " openini: Unable to open INI file: " + fname ) ;
}
+ + iniFileHandleCount ;
iniFiles . emplace ( iniFileHandleCount , IniFile ( fname ) ) ;
const auto & ini = iniFiles . at ( iniFileHandleCount ) ;
if ( ini . error ( ) ! = IniFile : : Error : : NoError ) {
iniFiles . erase ( iniFileHandleCount ) ;
throw ScriptException ( " openini: Unable to open INI file: " + fname ) ;
}
else
return iniFileHandleCount ;
}
ValueHolder closeini ( Script & , std : : vector < ValueHolder > & args )
{
if ( args . empty ( ) )
throwInsufficientParameters ( " closeini " , args . size ( ) , 1 ) ;
if ( args [ 0 ] . getType ( ) ! = ValueHolder : : Type : : Integer )
throwNotAnIniHandle ( " closeini " , 1 ) ;
int hndl = ValueExtract ( args [ 0 ] ) . toInt ( ) ;
auto & ini = getIniHandle ( " readiniitem " , ValueExtract ( args [ 0 ] ) . toInt ( ) ) ;
ini . flush ( ) ;
iniFiles . erase ( hndl ) ;
return { } ;
}
ValueHolder readini ( Script & , std : : vector < ValueHolder > & args )
{
if ( args . size ( ) ! = 3 & & args . size ( ) ! = 4 )
throwInsufficientParameters ( " readini " , args . size ( ) , 3 , 4 ) ;
if ( args [ 0 ] . getType ( ) ! = ValueHolder : : Type : : Integer )
throwNotAnIniHandle ( " readini " , 1 ) ;
int sectN = - 1 ;
int itemN = - 1 ;
std : : string sectS ;
std : : string itemS ;
std : : string defaultValue ;
/* Section parameter */
if ( args [ 1 ] . getType ( ) = = ValueHolder : : Type : : String )
sectS = ValueExtract ( args [ 1 ] ) . toString ( ) ;
else if ( args [ 1 ] . getType ( ) = = ValueHolder : : Type : : Integer )
sectN = ValueExtract ( args [ 1 ] ) . toInt ( ) ;
else
throwNotAStringOrWholeNumber ( " readini " , 2 ) ;
/* Item parameter */
if ( args [ 2 ] . getType ( ) = = ValueHolder : : Type : : String )
itemS = ValueExtract ( args [ 2 ] ) . toString ( ) ;
else if ( args [ 2 ] . getType ( ) = = ValueHolder : : Type : : Integer )
itemN = ValueExtract ( args [ 2 ] ) . toInt ( ) ;
else
throwNotAStringOrWholeNumber ( " readini " , 2 ) ;
/* Default value parameter */
if ( args . size ( ) = = 4 )
defaultValue = args [ 3 ] . toStdString ( ) ;
auto & ini = getIniHandle ( " readini " , ValueExtract ( args [ 0 ] ) . toInt ( ) ) ;
/* Section and Item by key */
if ( sectN = = - 1 & & itemN = = - 1 ) {
return ini . read ( sectS , itemS , defaultValue ) ;
}
/* Section by key, item by position */
else if ( sectN = = - 1 & & itemN > - 1 ) {
return ini . read ( sectS , itemN , defaultValue ) ;
}
/* Section by position, item by key */
else if ( sectN > - 1 & & itemN = = - 1 ) {
return ini . read ( sectN , itemS , defaultValue ) ;
}
/* Section and item by position */
else {
return ini . read ( sectN , itemN , defaultValue ) ;
}
}
ValueHolder readiniitem ( Script & , std : : vector < ValueHolder > & args )
{
if ( args . size ( ) ! = 3 )
throwInsufficientParameters ( " readiniitem " , args . size ( ) , 3 ) ;
if ( args [ 0 ] . getType ( ) ! = ValueHolder : : Type : : Integer )
throwNotAnIniHandle ( " readiniitem " , 1 ) ;
int sectN = - 1 ;
int itemN = - 1 ;
std : : string sectS ;
/* Section parameter */
if ( args [ 1 ] . getType ( ) = = ValueHolder : : Type : : String )
sectS = ValueExtract ( args [ 1 ] ) . toString ( ) ;
else if ( args [ 1 ] . getType ( ) = = ValueHolder : : Type : : Integer )
sectN = ValueExtract ( args [ 1 ] ) . toInt ( ) ;
else
throwNotAStringOrWholeNumber ( " readiniitem " , 2 ) ;
/* Item parameter */
if ( args [ 2 ] . getType ( ) = = ValueHolder : : Type : : Integer )
itemN = ValueExtract ( args [ 2 ] ) . toInt ( ) ;
else
throwNotAWholeNumber ( " readiniitem " , 2 ) ;
auto & ini = getIniHandle ( " readiniitem " , ValueExtract ( args [ 0 ] ) . toInt ( ) ) ;
/* Section by key, item by position */
if ( sectN = = - 1 & & itemN > - 1 ) {
return ini . item ( sectS , itemN ) ;
}
/* Section by position, item by position */
else {
return ini . item ( sectN , itemN ) ;
}
}
ValueHolder readinisection ( Script & , std : : vector < ValueHolder > & args )
{
if ( args . size ( ) ! = 2 )
throwInsufficientParameters ( " readinisection " , args . size ( ) , 2 ) ;
if ( args [ 0 ] . getType ( ) ! = ValueHolder : : Type : : Integer )
throwNotAnIniHandle ( " readinisection " , 1 ) ;
int sectN = - 1 ;
/* Section parameter */
if ( args [ 1 ] . getType ( ) = = ValueHolder : : Type : : Integer )
sectN = ValueExtract ( args [ 1 ] ) . toInt ( ) ;
else
throwNotAWholeNumber ( " readinisection " , 2 ) ;
auto & ini = getIniHandle ( " readinisection " , ValueExtract ( args [ 0 ] ) . toInt ( ) ) ;
return ini . section ( sectN ) ;
}
ValueHolder countini ( Script & , std : : vector < ValueHolder > & args )
{
/* Return amount of sections */
if ( args . size ( ) = = 1 ) {
if ( args [ 0 ] . getType ( ) ! = ValueHolder : : Type : : Integer )
throwNotAnIniHandle ( " countini " , 1 ) ;
auto & ini = getIniHandle ( " countini " , ValueExtract ( args [ 0 ] ) . toInt ( ) ) ;
return static_cast < int > ( ini . count ( ) ) ;
}
/* Return amount of items in section */
else if ( args . size ( ) = = 2 ) {
if ( args [ 0 ] . getType ( ) ! = ValueHolder : : Type : : Integer )
throwNotAnIniHandle ( " countini " , 1 ) ;
auto & ini = getIniHandle ( " countini " , ValueExtract ( args [ 0 ] ) . toInt ( ) ) ;
const auto & section = ValueExtract ( args [ 1 ] ) . toString ( ) ;
return static_cast < int > ( ini . count ( section ) ) ;
}
else {
throwInsufficientParameters ( " countini " , args . size ( ) , 0 , 1 ) ;
}
}
ValueHolder writeini ( Script & , std : : vector < ValueHolder > & args )
{
if ( args . size ( ) < 4 )
throwInsufficientParameters ( " writeini " , args . size ( ) , 4 ) ;
if ( args [ 0 ] . getType ( ) ! = ValueHolder : : Type : : Integer )
throwNotAnIniHandle ( " writeini " , 1 ) ;
if ( args [ 1 ] . getType ( ) ! = ValueHolder : : Type : : String )
throwNotAString ( " writeini " , 2 ) ;
if ( args [ 2 ] . getType ( ) ! = ValueHolder : : Type : : String )
throwNotAString ( " writeini " , 3 ) ;
const auto section = ValueExtract ( args [ 1 ] ) . toString ( ) ;
const auto item = ValueExtract ( args [ 2 ] ) . toString ( ) ;
const auto value = args [ 3 ] . toStdString ( ) ;
auto & ini = getIniHandle ( " writeini " , ValueExtract ( args [ 0 ] ) . toInt ( ) ) ;
ini . write ( section , item , value ) ;
return { } ;
}
ValueHolder sreadini ( Script & , std : : vector < ValueHolder > & args )
{
if ( args . size ( ) < 3 )
throwInsufficientParameters ( " sreadini " , args . size ( ) , 0 ) ;
if ( args [ 0 ] . getType ( ) ! = ValueHolder : : Type : : String )
throwNotAString ( " sreadini " , 1 ) ;
if ( args [ 1 ] . getType ( ) ! = ValueHolder : : Type : : String )
throwNotAString ( " sreadini " , 2 ) ;
if ( args [ 2 ] . getType ( ) ! = ValueHolder : : Type : : String )
throwNotAString ( " sreadini " , 3 ) ;
const auto filename = setRelativePath ( ValueExtract ( args [ 0 ] ) . toString ( ) ) ;
const auto section = ValueExtract ( args [ 1 ] ) . toString ( ) ;
const auto item = ValueExtract ( args [ 2 ] ) . toString ( ) ;
IniFile f ( filename ) ;
if ( f . error ( ) ! = IniFile : : Error : : NoError ) {
// Could be that the file didn't exist.
// For "simple readini" we will return an empty value as if it isn't an error.
return std : : string { } ;
}
return f . read ( section , item ) ;
}
ValueHolder swriteini ( Script & , std : : vector < ValueHolder > & args )
{
if ( args . size ( ) < 4 )
throwInsufficientParameters ( " swriteini " , args . size ( ) , 0 ) ;
if ( args [ 0 ] . getType ( ) ! = ValueHolder : : Type : : String )
throwNotAString ( " swriteini " , 1 ) ;
if ( args [ 1 ] . getType ( ) ! = ValueHolder : : Type : : String )
throwNotAString ( " swriteini " , 2 ) ;
if ( args [ 2 ] . getType ( ) ! = ValueHolder : : Type : : String )
throwNotAString ( " swriteini " , 3 ) ;
const auto filename = setRelativePath ( ValueExtract ( args [ 0 ] ) . toString ( ) ) ;
const auto section = ValueExtract ( args [ 1 ] ) . toString ( ) ;
const auto item = ValueExtract ( args [ 2 ] ) . toString ( ) ;
const auto value = args [ 3 ] . toStdString ( ) ;
if ( ! createFileIfNotExists ( filename ) ) {
throw ScriptException ( " swriteini: Unable to open INI file: " + filename ) ;
}
IniFile f ( filename ) ;
if ( f . error ( ) ! = IniFile : : Error : : NoError ) {
throw ScriptException ( " swriteini: Unable to open INI file: " + filename ) ;
}
f . write ( section , item , value ) ;
f . flush ( ) ;
return { } ;
}
}