/*
----------------------------------------------------------------
Filename.....: rmmIni.cc
ClassName....: rmmIni
Programmer...: Rick Miller.
Date.........: August 22, 2006.
Purpose......: Non-GUI Object to read/write ini/text files.
Notes........: See Notes below.
Written for..: dBASE 32 bit.
Rev. History.: August 25, 2008.
Added an optional <int> decimal parameter to
getFloat, getNumber, setFloat, setNumber methods.
Added a delete method to delete this.file.
Dependencies.: None.
Calls........: See x_InitializeExterns.
Called by....: Any.
Usage........: set procedure to rmmIni.cc additive
Example......: See Example 1, 2 below.
----------------------------------------------------------------
Properties:
----------------------------------------------------------------
file <char> set("directory") + "\" + login name + ".ini"
----------------------------------------------------------------
Example 1: standalone object.
----------------------------------------------------------------
oIni = new rmmIni()
Retreive a value from oIni.file.
cVar = oIni.get("section", "entryname")
Place a value into oIni.file.
lVar = oIni.set("section", "entryname", value)
oIni.release()
oIni := null
----------------------------------------------------------------
Example 2: child of a form.
----------------------------------------------------------------
form.ini = new rmmIni()
While the form is in scope:
Retreive a value from form.ini.file.
cVar = form.ini.get("section", "entryname")
Place a value into form.ini.file.
lVar = form.ini.set("section", "entryname", value)
In the form.canClose or form.onClose event.
form.ini.release()
form.ini := null
----------------------------------------------------------------
Methods:
----------------------------------------------------------------
delete() delete this.file.
return <logical>.
flush() flush writes to this.file in the cache.
return <logical>.
get(<char> section, <char> entry)
return <char>.
getFloat(<char> section, <char> entryname[, <int> decimals])
return <float>.
getInt(<char> section, <char> entryname)
return <int>.
getNumber(<char> section, <char> entryname[, <int> decimals])
return <number>.
release()
destroy object.
close procedure.
set(<char> section, <char> entryname, value)
return <logical>.
setFloat(<char> section, <char> entryname, value[, <int> decimals])
return <logical>.
setInt(<char> section, <char> entryname, value)
return <logical>.
setNumber(<char> section, <char> entryname, value[, <int> decimals])
return <logical>.
----------------------------------------------------------------
Notes:
----------------------------------------------------------------
1) the getFloat and getNumber methods call the same code.
2) the setFloat and setNumber methods call the same code.
3) when working with number values:
a) the set method will round based upon the
current set("decimals") value.
b) the getNumber, and setNumber methods will round
based upon the current set("decimals") value or
the decimals parameter when passed.
c) the getInt and setInt methods always drop all
decimals with no rounding.
d) when debugging using the ? command, the display is
always based upon the current set("decimals") value,
even when there are more decimals present.
----------------------------------------------------------------
*/
#define MAX_LINELENGTH 1024
#define MAX_USERNAME 256
#define ZEROS(n) replicate(chr(0), n)
#define RMMINI_PUBLISHER "Rick Miller"
#define RMMINI_VERSION "8.0825"
//---------------------------------------------------------------//
// constructor.
//---------------------------------------------------------------//
class rmmIni
// protected methods.
protect x_GetUserName, x_InitializeExterns
class::x_InitializeExterns()
this.className = "rmmIni"
// assign this.file a default filename.
this.file = set("directory") + "\" +;
class::x_GetUserName() + ".ini"
this.publisher = RMMINI_PUBLISHER
this.version = RMMINI_VERSION
//------------------------------------------------------------//
// end of constructor - methods below.
//------------------------------------------------------------//
// delete the file used with this object.
function delete
Local bRet, cFile, oFile
cFile = "" + this.file
oFile = new file()
if oFile.exists(cFile)
oFile.delete(cFile)
endif
bRet = iif(oFile.exists(cFile), false, true)
oFile := null
return iif(bRet, true, false)
//------------------------------------------------------------//
// flush file writes that are in the cache.
function flush
Local bRet, cFile, oFile
bRet = false
cFile = "" + this.file
oFile = new file()
if oFile.exists(cFile)
oFile.open(cFile, "W")
if not oFile.handle == -1
bRet := RMM_FlushFileBuffers(int(oFile.handle))
endif
oFile.close()
endif
release object oFile
oFile := null
return iif(bRet, true, false)
//------------------------------------------------------------//
// return a string value from this.file.
function get(section, entry)
Local cRet, nLen
cRet = space(MAX_LINELENGTH)
nLen = MAX_LINELENGTH
// returns number of characters copied to the buffer,
// not including the terminating null character.
nLen := RMM_GetIniString( ;
"" + section, "" + entry, "", cRet, nLen, this.file)
return left(cRet, nLen)
//------------------------------------------------------------//
// return a float value from this.file.
function getFloat(section, entry, nDecimals)
return this.getNumber(section, entry, nDecimals)
//------------------------------------------------------------//
// return an int value from this.file.
function getInt(section, entry)
return int(val(this.get(section, entry)))
//------------------------------------------------------------//
// return a numeric value from this.file.
function getNumber(section, entry, nDecimals)
Local nRet, nDeci, nValu
if ("" + nDecimals) == "false"
nRet = val(this.get(section, entry))
else
nValu = int(val("" + nDecimals))
if nValu > 18
nValu := 18
elseif nValu < 0
nValu := 0
endif
nDeci = set("decimals")
set decimals to (nValu)
nRet = val("" + this.get(section, entry))
set decimals to (nDeci)
endif
return nRet
//------------------------------------------------------------//
// display object in the inspector.
function inspect
inspect(this)
return
//------------------------------------------------------------//
// destroy this object. close procedure.
function release
try
release object this
close procedure (program(1))
catch(exception e)
endtry
return
//------------------------------------------------------------//
// write a char into this.file.
function set(section, entry, value)
return RMM_WriteIniString( ;
"" + section, "" + entry, "" + value, "" + this.file)
//------------------------------------------------------------//
// write a float into this.file.
function setFloat(section, entry, value, nDecimals)
return this.setNumber(section, entry, value, nDecimals)
//------------------------------------------------------------//
// write an int into this.file.
function setInt(section, entry, value)
return this.set(section, entry,;
ltrim(str(int(val("" + value)), 10, 0, "")))
//------------------------------------------------------------//
// write a number into this.file.
function setNumber(section, entry, value, nDecimals)
Local bRet, nDeci, nValu
nDeci = set("decimals")
if ("" + nDecimals) == "false"
bRet = this.set(section, entry,;
ltrim(str(val("" + value), 20, nDeci, "")))
else
nValu = int(val("" + nDecimals))
if nValu > 18
nValu := 18
elseif nValu < 0
nValu := 0
endif
set decimals to (nValu)
bRet = this.set(section, entry,;
ltrim(str(val("" + value), 20, nValu, "")))
set decimals to (nDeci)
endif
return iif(bRet, true, false)
//------------------------------------------------------------//
// get the user name logged into windows.
function x_GetUserName
Local cRet, sBuff, sLen
sBuff = ZEROS(MAX_USERNAME + 1)
cRet = "Default"
sLen = ZEROS(4)
// put the length value into a pointer.
sLen.setByte(0, bitand(MAX_USERNAME, 0xFF))
sLen.setByte(1, bitand(bitzrshift(MAX_USERNAME, 8), 0xFF))
sLen.setByte(2, bitand(bitzrshift(MAX_USERNAME, 16), 0xFF))
sLen.setByte(3, bitand(bitzrshift(MAX_USERNAME, 24), 0xFF))
if RMM_GetUserName(sBuff, sLen)
// the variable pointed to by sLen contains the number
// of characters copied to the buffer,
// including the terminating null character.
// ignore sLen and just find the first chr(0).
cRet := sBuff.left(sBuff.indexOf(chr(0)))
endif
return cRet
//------------------------------------------------------------//
// declare external functions.
function x_InitializeExterns
if not type("RMM_FlushFileBuffers") == "FP"
extern CLOGICAL RMM_FlushFileBuffers(CHANDLE) ;
kernel32 from "FlushFileBuffers"
endif
if not type("RMM_GetIniString") == "FP"
extern CULONG RMM_GetIniString( ;
CSTRING, CSTRING, CSTRING, CSTRING, CULONG, CSTRING) ;
kernel32 from "GetPrivateProfileStringA"
endif
if not type("RMM_GetUserName") == "FP"
extern CLOGICAL RMM_GetUserName(CSTRING, CPTR) ;
advapi32.dll from "GetUserNameA"
endif
if not type("RMM_WriteIniString") == "FP"
extern CLOGICAL RMM_WriteIniString( ;
CSTRING, CSTRING, CSTRING, CSTRING) ;
kernel32 from "WritePrivateProfileStringA"
endif
return
endclass
//---------------------------------------------------------------//
// end of rmmIni.
//---------------------------------------------------------------//