- MEM file structure support

This commit is contained in:
fdbozzo
2018-03-25 23:48:49 +02:00
parent fa5bb1d4fe
commit 1f1c691573
9 changed files with 615 additions and 6 deletions

View File

@@ -26,6 +26,7 @@ Change History -------------------------------------------------------------
- Enhanced HELP dialog info when running FoxBin2Prg with double-click
- Feature: Added automatic default language recognition for the supported ones (FR,DE,ES,EN)
- Feature: FKY file structure support (MACRO exporting to text fk2)
- Feature: MEM file structure support (MEMORY exporting to text me2)
2018-03-15 v1.19.50.3
- Bug Fix: When adding some non-VFP text files like html,css,etc, in the text section of the project, FoxBin2Prg does not keep this selection when regenerating the PJX, leaving them in the files section (Darko Kezic)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -35,6 +35,8 @@
* FRX_Conversion_Support: 2 && 0=No support, 1=Generate TXT only (Diff), 2=Generate TXT and BIN (Merge)
* LBX_Conversion_Support: 2 && 0=No support, 1=Generate TXT only (Diff), 2=Generate TXT and BIN (Merge)
* MNX_Conversion_Support: 2 && 0=No support, 1=Generate TXT only (Diff), 2=Generate TXT and BIN (Merge)
* FKY_Conversion_Support: 1 && 0=No support, 1=Generate TXT only (Diff)
* MEM_Conversion_Support: 1 && 0=No support, 1=Generate TXT only (Diff)
* DBC_Conversion_Support: 2 && 0=No support, 1=Generate TXT only (Diff), 2=Generate TXT and BIN (Merge)
* DBF_Conversion_Support: 1 && 0=No support, 1=Generate TXT only (Diff), 2=Generate TXT and BIN (Merge/Only Structure!), 4=Generate TXT with DATA (Diff), 8=Export and Import DATA (Merge/Structure & Data)
* DBF_Conversion_Included: * && If DBF_Conversion_Support:4, you can specify multiple filemasks: www,fb2p_free.dbf

View File

@@ -882,7 +882,7 @@ DEFINE CLASS c_foxbin2prg AS Session
LBX_Conversion_Support = 2
MNX_Conversion_Support = 2
FKY_Conversion_Support = 1
MEM_Conversion_Support = 0
MEM_Conversion_Support = 1
DBF_Conversion_Support = 1
DBC_Conversion_Support = 2
DBF_Conversion_Included = ''
@@ -959,11 +959,11 @@ DEFINE CLASS c_foxbin2prg AS Session
THIS.writeLog( REPLICATE( '*', 100 ) )
THIS.writeLog( 'FoxBin2Prg: [' + THIS.c_Foxbin2prg_FullPath + '] (EXE Version: ' + THIS.c_FB2PRG_EXE_Version + ', FoxPro Version: ' + VERSION(4) + ')' )
THIS.writeLog( TEXTMERGE( '- Internal CFG: <<SYS(2019,2)>> / External CFG: <<SYS(2019,1)>> / CodePage Used: <<CPCURRENT()>>)' ) )
* Get default language info
* ISO 639-2 Language Codes: https://www.loc.gov/standards/iso639-2/php/code_list.php
lcLang = THIS.getLocaleInfo(0x00000067) && ie: spa
DO CASE
CASE lcLang = 'spa'
lcLang = 'ES'
@@ -974,7 +974,7 @@ DEFINE CLASS c_foxbin2prg AS Session
OTHERWISE && Default: EN
lcLang = 'EN'
ENDCASE
THIS.changeLanguage(lcLang)
THIS.o_FSO = CREATEOBJECT("Scripting.FileSystemObject")
@@ -2317,6 +2317,20 @@ DEFINE CLASS c_foxbin2prg AS Session
.writeLog( C_TAB + JUSTFNAME(lcConfigFile) + ' > MNX_Conversion_Support: ' + TRANSFORM(lo_CFG.MNX_Conversion_Support) )
ENDIF
CASE LEFT( laConfig(m.I), 23 ) == LOWER('FKY_Conversion_Support:')
lcValue = ALLTRIM( SUBSTR( laConfig(m.I), 24 ) )
IF INLIST( lcValue, '0', '1' ) THEN
lo_CFG.FKY_Conversion_Support = INT( VAL( lcValue ) )
.writeLog( C_TAB + JUSTFNAME(lcConfigFile) + ' > FKY_Conversion_Support: ' + TRANSFORM(lo_CFG.FKY_Conversion_Support) )
ENDIF
CASE LEFT( laConfig(m.I), 23 ) == LOWER('MEM_Conversion_Support:')
lcValue = ALLTRIM( SUBSTR( laConfig(m.I), 24 ) )
IF INLIST( lcValue, '0', '1' ) THEN
lo_CFG.MEM_Conversion_Support = INT( VAL( lcValue ) )
.writeLog( C_TAB + JUSTFNAME(lcConfigFile) + ' > MEM_Conversion_Support: ' + TRANSFORM(lo_CFG.MEM_Conversion_Support) )
ENDIF
CASE LEFT( laConfig(m.I), 23 ) == LOWER('DBF_Conversion_Support:')
lcValue = ALLTRIM( SUBSTR( laConfig(m.I), 24 ) )
IF INLIST( lcValue, '0', '1', '2', '4', '8' ) THEN
@@ -5337,7 +5351,7 @@ DEFINE CLASS c_foxbin2prg AS Session
ENDFUNC
FUNCTION GetLocaleInfo
FUNCTION getLocaleInfo
LPARAMETERS tnSetting, tcLocale
#DEFINE C_NULL CHR(0)
LOCAL lcLocale, lnLen, lcBuffer, lnReturn, lcReturn
@@ -5347,7 +5361,7 @@ DEFINE CLASS c_foxbin2prg AS Session
ELSE
lcLocale = .NULL.
ENDIF
DECLARE INTEGER GetLocaleInfoEx in Win32API ;
string locale, long type, string @buffer, integer len
lnLen = 255
@@ -17959,6 +17973,105 @@ ENDDEFINE
DEFINE CLASS c_conversor_mem_a_prg AS c_conversor_bin_a_prg
#IF .F.
LOCAL THIS AS c_conversor_mem_a_prg OF 'FOXBIN2PRG.PRG'
#ENDIF
c_Type = 'MEM'
PROCEDURE convert
*---------------------------------------------------------------------------------------------------
* PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
* toMacro (!@ OUT) Objeto generado de clase CL_MACRO con la información leida del texto
* toEx (!@ OUT) Objeto con información del error
* toFoxBin2Prg (v! IN ) Referencia al objeto principal
*---------------------------------------------------------------------------------------------------
LPARAMETERS toMemVar, toEx AS EXCEPTION, toFoxBin2Prg
DODEFAULT( @toMemVar, @toEx, @toFoxBin2Prg )
#IF .F.
LOCAL toMemVar AS CL_MEMVAR OF 'FOXBIN2PRG.PRG'
LOCAL toFoxBin2Prg AS c_foxbin2prg OF 'FOXBIN2PRG.PRG'
#ENDIF
LOCAL lnCodError, lnLen, lnHandle ;
, loLang as CL_LANG OF 'FOXBIN2PRG.PRG'
PRIVATE pnCols, pnRows, pnElement
STORE 0 TO pnCols, pnRows, pnElement
TRY
WITH THIS AS c_conversor_mem_a_prg OF 'FOXBIN2PRG.PRG'
lnHandle = -1
IF toFoxBin2Prg.l_ProcessFiles THEN
loLang = _SCREEN.o_FoxBin2Prg_Lang
STORE 0 TO lnCodError
.updateProgressbar( 'Analyzing MEM...', 1, 2, 1 )
*-- Verificación de archivo de macros válido
*IF FCOUNT() < 25 OR EMPTY(FIELD("RESNAME")) OR EMPTY(FIELD("SYSRES"))
* *ERROR 'Menu [' + (.c_InputFile) + '] is NOT VFP 9 Format! - Please convert to VFP 9 with MODIFY MENU ' + JUSTFNAME((.c_InputFile))
* ERROR (TEXTMERGE(loLang.C_MENU_NOT_IN_VFP9_FORMAT_LOC))
*ENDIF
*-- Header
C_FB2PRG_CODE = C_FB2PRG_CODE + toFoxBin2Prg.get_PROGRAM_HEADER()
toMemVar = CREATEOBJECT('CL_MEMVAR')
toMemVar.get_DataFromMEM(.c_InputFile, @toFoxBin2Prg)
C_FB2PRG_CODE = C_FB2PRG_CODE + toMemVar.toText()
ENDIF
DO CASE
CASE toFoxBin2Prg.c_SimulateError = 'SIMERR_I1'
ERROR 'InputFile Error Simulation'
CASE toFoxBin2Prg.c_SimulateError = 'SIMERR_I0'
.writeErrorLog( '*** SIMULATED ERROR' )
ENDCASE
IF .l_Error
.writeLog( '*** ERRORS found - Generation Cancelled' )
EXIT
ENDIF
toFoxBin2Prg.updateProcessedFile()
*-- Genero el FK2
IF toFoxBin2Prg.l_ProcessFiles THEN
.updateProgressbar( 'Writing ' + toFoxBin2Prg.c_ME2 + '...', 2, 2, 1 )
ENDIF
IF .l_Test
toMemVar = C_FB2PRG_CODE
ELSE
.write_OutputFile( (C_FB2PRG_CODE), .c_OutputFile, @toFoxBin2Prg )
ENDIF
ENDWITH && THIS
CATCH TO toEx
THIS.set_UserValue(@toEx)
IF THIS.n_Debug > 0 AND _VFP.STARTMODE = 0
SET STEP ON
ENDIF
THROW
FINALLY
*
ENDTRY
RETURN
ENDPROC
ENDDEFINE
DEFINE CLASS CL_CUS_BASE AS CUSTOM
*-- Propiedades (Se preservan: CONTROLCOUNT, CONTROLS, OBJECTS, PARENT, CLASS)
HIDDEN BASECLASS, TOP, WIDTH, CLASSLIB, CLASSLIBRARY, COMMENT ;
@@ -30061,3 +30174,496 @@ ENDDEFINE
DEFINE CLASS CL_MEMVAR AS CL_COL_BASE
* .MEM FILE STRUCTURE (Based on observation and testing) - Fernando D. Bozzo. 2018/03/24
* Complementary documentation: https://www.clicketyclick.dk/databases/xbase/format/mem.html#MEM_STRUCT
* STRUCTURE OF VARIABLES
* Byte Offset Description
* ----------- -------------------------------------------------------------------------------------------------
* 0 - 10 NULL terminated VarName. If VarName is empty, then VarName starts at offset 32
* 11 VarType (A,C,N,Y,B,F,I,Q,D,T,L,0). If VarType is lowercase, then next VarName
* begins with 2 bytes for VarName length.
* 12 - 15 Reserved
* 16 Value length
* 17 Decimal count
* 18 - 24 Reserved
* 25 0x00 if it is an array element, 0x03 if it isn't an array element
* 26 - 31 Reserved
* 32 - n If VarName (offset 0-10) is NULL then goto TABLE 1, If VarType=A then continue in TABLE 2,
* if VarType=0 then continue in TABLE 3, else continue in TABLE 4
* ...
* eof Last character is EOF (0x1A) character
* ----------- -------------------------------------------------------------------------------------------------
* TABLE 1 - ARRAY STRUCTURE (VarType=A)
* Byte Offset Description
* ----------- -------------------------------------------------------------------------------------------------
* 32 - 33 VarName length
* 34 - n VarName
* n + 1 Next TABLE: If VarType=A then continue in TABLE 2, if VarType=0 then continue in TABLE 3,
* else continue in TABLE 4
* ----------- -------------------------------------------------------------------------------------------------
* TABLE 2 - ARRAY STRUCTURE (VarType=A)
* Byte Offset Description
* ----------- -------------------------------------------------------------------------------------------------
* n - n+1 Array rows
* n+2 - n+3 Array cols
* n+4 - x Next Variable structure, or EOF (0x1A)
* ----------- -------------------------------------------------------------------------------------------------
* TABLE 3 - NULL VALUE STRUCTURE (VarType=0)
* Byte Offset Description
* ----------- -------------------------------------------------------------------------------------------------
* n VarType.
* n+1 - x Next Variable structure, or EOF (0x1A)
* ----------- -------------------------------------------------------------------------------------------------
* TABLE 4 - NORMAL VALUE STRUCTURE
* Byte Offset Description
* ----------- -------------------------------------------------------------------------------------------------
* n - x Value of length "value length". If ValTye is a Char type then Value length is the value's width,
* else the width is 8 for numbers and dates
* x Next Variable structure, or EOF (0x1A)
* ----------- -------------------------------------------------------------------------------------------------
#IF .F.
LOCAL THIS AS CL_MEMVAR OF 'FOXBIN2PRG.PRG'
#ENDIF
_MEMBERDATA = [<VFPData>] ;
+ [<memberdata name="c_inputfile" display="c_InputFile"/>] ;
+ [<memberdata name="_debug" display="_Debug"/>] ;
+ [<memberdata name="get_datafrommem" display="get_DataFromMEM"/>] ;
+ [<memberdata name="_memvars" display="_MemVars"/>] ;
+ [</VFPData>]
c_InputFile = ''
_Debug = .F.
_MemVars = NULL && Colección de variables de memoria
PROCEDURE INIT
DODEFAULT()
THIS._MemVars = CREATEOBJECT("COLLECTION")
ENDPROC
PROCEDURE get_DataFromMEM(tcInputFile as String, toFoxBin2Prg)
*---------------------------------------------------------------------------------------------------
* PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
* tcInputFile (!v IN ) Archivo de entrada
* toFoxBin2Prg (!@ IN ) Referencia al objeto principal
*---------------------------------------------------------------------------------------------------
#IF .F.
LOCAL toFoxBin2Prg AS c_foxbin2prg OF 'FOXBIN2PRG.PRG'
#ENDIF
LOCAL lnHandle, lnFileLen, lcMsg, lcStr, lnNumberOfMacros ;
, loMVRec as CL_MEMVAR_RECORD OF 'FOXBIN2PRG.PRG' ;
, loColl as Collection ;
, loEx as Exception
TRY
lnHandle = -1
WITH THIS AS CL_MEMVAR OF 'FOXBIN2PRG.PRG'
loColl = ._MemVars
lnHandle = FOPEN(tcInputFile, 0)
IF lnHandle = -1
lcMsg = toFoxBin2Prg.FERROR_Message(tcInputFile)
ERROR (lcMsg)
ENDIF
lnFileLen = FSEEK(lnHandle, 0, 2)
IF lnFileLen < 1
ERROR 'Invalid MEM File size'
ELSE
=FSEEK(lnHandle, 0, 0)
ENDIF
*IF lnFileLen < 17 + 25 * lnNumberOfMacros
* * 25 caracteres es el tamaño mínimo de una macro sin teclas guardadas (solo la estructura)
* ERROR 'Invalid FKY Macro File size'
*ENDIF
IF lnFileLen > 1
DO WHILE NOT FEOF(lnHandle) AND FSEEK(lnHandle, 0, 1) < (lnFileLen - 1)
loMVRec = CREATEOBJECT("CL_MEMVAR_RECORD")
IF NOT loMVRec.ReadNextMemVar(lnHandle)
EXIT
ENDIF
loColl.Add( loMVRec, loMVRec.getName() + PADL(pnElement, 5, '0') )
loMVRec = NULL
ENDDO
* Ordenar alfabéticamente por nombre de variable
loColl.KeySort = 2
ENDIF
ENDWITH
CATCH TO loEx
*loEx.UserValue = loEx.UserValue + 'lcAsignacion = [' + TRANSFORM(lcAsignacion) + ']' + CR_LF
IF THIS.n_Debug > 0 AND _VFP.STARTMODE = 0
SET STEP ON
ENDIF
THROW
FINALLY
IF lnHandle <> -1
=FCLOSE(lnHandle)
ENDIF
ENDTRY
RETURN
ENDPROC
PROCEDURE toText
*---------------------------------------------------------------------------------------------------
* PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
*---------------------------------------------------------------------------------------------------
LOCAL lcText, loMVRec AS CL_MEMVAR_RECORD OF 'FOXBIN2PRG.PRG'
lcText = ''
WITH THIS AS CL_MEMVAR OF 'FOXBIN2PRG.PRG'
*-- Macros
FOR EACH loMVRec IN ._MemVars &&FOXOBJECT
lcText = lcText + CR_LF + loMVRec.toText()
ENDFOR
ENDWITH
RETURN lcText
ENDPROC
ENDDEFINE
DEFINE CLASS CL_MEMVAR_RECORD AS CL_CUS_BASE
_MEMBERDATA = [<VFPData>] ;
+ [<memberdata name="memvar_name" display="MemVar_Name"/>] ;
+ [<memberdata name="memvar_namelength" display="MemVar_NameLength"/>] ;
+ [<memberdata name="memvar_type" display="MemVar_Type"/>] ;
+ [<memberdata name="memvar_rows" display="MemVar_Rows"/>] ;
+ [<memberdata name="memvar_cols" display="MemVar_Cols"/>] ;
+ [<memberdata name="memvar_length" display="MemVar_Length"/>] ;
+ [<memberdata name="memvar_dec" display="MemVar_Dec"/>] ;
+ [<memberdata name="memvar_value" display="MemVar_Value"/>] ;
+ [<memberdata name="memvar_elemtype" display="MemVar_ElemType"/>] ;
+ [<memberdata name="readnextmemvar" display="ReadNextMemVar"/>] ;
+ [<memberdata name="totext" display="toText"/>] ;
+ [<memberdata name="get_memvardata" display="get_MemVarData"/>] ;
+ [<memberdata name="getrows" display="getRows"/>] ;
+ [<memberdata name="getcols" display="getCols"/>] ;
+ [<memberdata name="getlength" display="getLength"/>] ;
+ [<memberdata name="getdec" display="getDec"/>] ;
+ [<memberdata name="getvalue" display="getValue"/>] ;
+ [<memberdata name="getname" display="getName"/>] ;
+ [<memberdata name="juliantodatetime" display="julianToDateTime"/>] ;
+ [<memberdata name="isarrayelement" display="isArrayElement"/>] ;
+ [</VFPData>]
*--
MemVar_Name = ''
MemVar_NameLength = ''
MemVar_Type = ''
MemVar_Rows = ''
MemVar_Cols = ''
MemVar_Length = ''
MemVar_Dec = ''
MemVar_Value = ''
MemVar_ElemType = ''
PROCEDURE ReadNextMemVar(tnHandle as Integer)
*---------------------------------------------------------------------------------------------------
* PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
* tnHandle (!v IN ) FKY file handle
*---------------------------------------------------------------------------------------------------
LOCAL lnVarLength, lnVarDec, lnVarNameLength, lcVarNameLength, llVarTypeIsChar
TRY
WITH THIS AS CL_MEMVAR_RECORD OF 'FOXBIN2PRG.PRG'
.MemVar_Name = FREAD(tnHandle, 11)
.MemVar_Type = FREAD(tnHandle, 1)
=FSEEK(tnHandle, 4, 1) && Skip 4 bytes
.MemVar_Length = FREAD(tnHandle, 1)
.MemVar_Dec = FREAD(tnHandle, 1)
DO CASE
CASE INLIST( UPPER(.MemVar_Type), 'C', 'Q', 'L')
llVarTypeIsChar = .T.
lnVarLength = .getLength()
CASE UPPER(.MemVar_Type) = 'A'
* Array
OTHERWISE && Numeric
lnVarLength = 8
lnVarDec = .getDec()
ENDCASE
=FSEEK(tnHandle, 7, 1) && Skip 7 bytes
.MemVar_ElemType = FREAD(tnHandle, 1) && 0x00 if it is an array element, else 0x03
=FSEEK(tnHandle, 6, 1) && Skip 6 bytes
IF .isArrayElement()
* Mantiene el contador de elemento
pnElement = pnElement + 1
ELSE
* Reinicia el conteo de filas, columnas y elemento actual
STORE 0 TO pnCols, pnRows, pnElement
ENDIF
IF EMPTY( RTRIM(.MemVar_Name, 0, CHR(0)) )
* Long VarName
lcVarNameLength = FREAD(tnHandle, 2)
lnVarNameLength = CTOBIN(lcVarNameLength, '2RS')
.MemVar_Name = FREAD(tnHandle, lnVarNameLength)
ENDIF
DO CASE
CASE INLIST(.MemVar_Type, 'A', 'a')
* ARRAY
* Rows/Cols
.MemVar_Rows = FREAD(tnHandle, 2)
.MemVar_Cols = FREAD(tnHandle, 2)
pnCols = .getCols()
pnRows = .getRows()
CASE .MemVar_Type = '0'
* NULL
* VarType
.MemVar_Type = FREAD(tnHandle, 1)
.MemVar_Value = NULL
OTHERWISE
* NORMAL VALUE
* Value
.MemVar_Value = FREAD(tnHandle, lnVarLength)
ENDCASE
ENDWITH
ENDTRY
RETURN
ENDPROC
FUNCTION isArrayElement
#IF .F.
LOCAL THIS AS CL_MEMVAR_RECORD OF 'FOXBIN2PRG.PRG'
#ENDIF
RETURN ASC(THIS.MemVar_ElemType) = 0
ENDFUNC
FUNCTION getRows
#IF .F.
LOCAL THIS AS CL_MEMVAR_RECORD OF 'FOXBIN2PRG.PRG'
#ENDIF
RETURN CTOBIN(THIS.MemVar_Rows, '2RS')
ENDFUNC
FUNCTION getCols
#IF .F.
LOCAL THIS AS CL_MEMVAR_RECORD OF 'FOXBIN2PRG.PRG'
#ENDIF
RETURN CTOBIN(THIS.MemVar_Cols, '2RS')
ENDFUNC
FUNCTION getLength
#IF .F.
LOCAL THIS AS CL_MEMVAR_RECORD OF 'FOXBIN2PRG.PRG'
#ENDIF
RETURN ASC(THIS.MemVar_Length)
ENDFUNC
FUNCTION getDec
#IF .F.
LOCAL THIS AS CL_MEMVAR_RECORD OF 'FOXBIN2PRG.PRG'
#ENDIF
RETURN ASC(THIS.MemVar_Dec)
ENDFUNC
FUNCTION getName
#IF .F.
LOCAL THIS AS CL_MEMVAR_RECORD OF 'FOXBIN2PRG.PRG'
#ENDIF
RETURN RTRIM(THIS.MemVar_Name, 0, CHR(0))
ENDFUNC
FUNCTION getValue
WITH THIS AS CL_MEMVAR_RECORD OF 'FOXBIN2PRG.PRG'
LOCAL lxValue
DO CASE
CASE ISNULL(.MemVar_Value)
lxValue = NULL
CASE UPPER(.MemVar_Type) = 'L'
lxValue = ( ASC(.MemVar_Value) = 1 )
CASE INLIST( UPPER(.MemVar_Type), 'C', 'M')
lxValue = ["] + RTRIM(.MemVar_Value, 0, CHR(0)) + ["]
CASE INLIST( UPPER(.MemVar_Type), 'Q')
lxValue = '0h' + STRCONV(.MemVar_Value,15)
CASE UPPER(.MemVar_Type) = 'D'
lxValue = SYS(10, CTOBIN(.MemVar_Value, '8S'))
CASE UPPER(.MemVar_Type) = 'T'
lxValue =.julianToDateTime( CTOBIN(.MemVar_Value, '8S') )
CASE UPPER(.MemVar_Type) = 'Y'
lxValue = CTOBIN(.MemVar_Value, '8YRS')
CASE UPPER(.MemVar_Type) = 'B'
lxValue = CTOBIN(.MemVar_Value, '8BRS')
OTHERWISE && 'N'
lxValue = CTOBIN(.MemVar_Value, '8S')
*IF .getDec() = 0
* lxValue = ROUND(lxValue,0)
*ENDIF
ENDCASE
ENDWITH
RETURN lxValue
ENDFUNC
FUNCTION julianToDateTime(tnJulian as Double)
LOCAL lnInt, lnDec, ltValue, ldDate, lcTime ;
, lnSecs, lnMins, lnHours
ltValue = {/:}
lnInt = INT(tnJulian)
lnDec = tnJulian - lnInt
ldDate = EVALUATE( '{^' + SYS(10, lnInt) + '}' )
lnSecs = 24 * 60 * 60 * lnDec
lnHours = INT(lnSecs / 3600)
lnSecs = lnSecs - lnHours * 3600
lnMins = INT(lnSecs / 60)
lnSecs = lnSecs - lnMins * 60
ltValue = DATETIME( YEAR(ldDate), MONTH(ldDate), DAY(ldDate), lnHours, lnMins, lnSecs)
RETURN ltValue
ENDFUNC
PROCEDURE toText as String
*---------------------------------------------------------------------------------------------------
* PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
*---------------------------------------------------------------------------------------------------
LOCAL lcText, lcVarName, lcVarType, lnVarLen, lnVarDec, lcPrecision, lnLenName ;
, loField AS CL_MACRO_RECORD OF 'FOXBIN2PRG.PRG'
lnLenName = 16
lcText = ''
lcPrecision = ''
lcVarName = ''
WITH THIS AS CL_MEMVAR_RECORD OF 'FOXBIN2PRG.PRG'
lcVarType = UPPER(.MemVar_Type)
lnVarLen = .getLength()
lnVarDec = .getDec()
lcVarName = .getName()
IF LEN(lcVarName) < lnLenName
lcVarName = PADR(lcVarName, lnLenName)
ENDIF
IF lcVarType = 'N'
IF lnVarDec > 0
lcPrecision = TEXTMERGE( '(<<lnVarLen>>,<<lnVarDec>>)' )
ELSE
lcPrecision = TEXTMERGE( '(<<lnVarLen>>)' )
ENDIF
ENDIF
lcPrecision = PADR(lcPrecision, 10)
IF lcVarType = 'A'
pnCols = .getCols()
pnRows = .getRows()
pnElement = 0
IF CTOBIN(.MemVar_Cols, '2RS') = 0
* Array Unidimensional
TEXT TO lcText ADDITIVE TEXTMERGE NOSHOW FLAGS 1 PRETEXT 1+2
<<lcVarName>> <<lcVarType>>(<<.getRows()>>)
ENDTEXT
ELSE
* Array Bidimensional
TEXT TO lcText ADDITIVE TEXTMERGE NOSHOW FLAGS 1 PRETEXT 1+2
<<lcVarName>> <<lcVarType>>(<<.getRows()>>,<<.getCols()>>)
ENDTEXT
ENDIF
ELSE
IF .isArrayElement()
* Elemento de array
pnElement = pnElement + 1
IF pnCols = 0
* Elemento de Array Unidimensional
TEXT TO lcText ADDITIVE TEXTMERGE NOSHOW FLAGS 1 PRETEXT 1+2
<<>> (<<STR(pnElement,5)>>) <<lcVarType>><<lcPrecision>> <<.getValue()>>
ENDTEXT
ELSE
* Elemento de Array Bidimensional
TEXT TO lcText ADDITIVE TEXTMERGE NOSHOW FLAGS 1 PRETEXT 1+2
<<>> (<<STR(CEILING(pnElement/pnCols),5)>>,<<STR(EVL( MOD(pnElement,pnCols), pnCols),5)>>) <<lcVarType>><<lcPrecision>> <<.getValue()>>
ENDTEXT
ENDIF
ELSE
* Variable normal
TEXT TO lcText ADDITIVE TEXTMERGE NOSHOW FLAGS 1 PRETEXT 1+2
<<lcVarName>> <<lcVarType>><<lcPrecision>> <<.getValue()>>
ENDTEXT
ENDIF
ENDIF
ENDWITH
RETURN lcText
ENDPROC
ENDDEFINE