diff --git a/foxbin2prg.prg b/foxbin2prg.prg
index c2d2c0f..71c6a75 100644
--- a/foxbin2prg.prg
+++ b/foxbin2prg.prg
@@ -213,6 +213,7 @@
* 03/03/2018 FDBOZZO v1.19.50 Mejora: Permitir exportar a texto la información de DBFs cuya apertura está protegida por eventos del DBC
* 12/03/2018 FDBOZZO v1.19.50.1 Bug Fix: Cuando se usa la equivalencia "extension: pj2=pjm" se debe manejar el pjm como un pj2 y no como un pjm de SourceSafe (Darko Kezic)
* 15/03/2018 FDBOZZO v1.19.50.3 Bug Fix: Cuando se agregan archivos de texto no-VFP, como html,css,etc, en la sección de Text del proyecto, FoxBin2Prg no mantiene esta selección al regenerar el PJX, dejándolos en la sección Files (Darko Kezic)
+* 16/03/2018 FDBOZZO v1.19.51 Mejora: Agregado soporte para archivos de macros (.FKY)
*
*
*---------------------------------------------------------------------------------------------------
@@ -690,6 +691,8 @@ DEFINE CLASS c_foxbin2prg AS Session
+ [] ;
+ [] ;
+ [] ;
+ + [] ;
+ + [] ;
+ [] ;
+ [] ;
+ [] ;
@@ -751,7 +754,6 @@ DEFINE CLASS c_foxbin2prg AS Session
+ [] ;
+ [] ;
+ [] ;
- + [] ;
+ [] ;
+ [] ;
+ [] ;
@@ -871,12 +873,16 @@ DEFINE CLASS c_foxbin2prg AS Session
c_DB2 = 'DB2' && DBF
c_DC2 = 'DC2' && DBC
c_MN2 = 'MN2' && MNX
+ c_FK2 = 'FK2' && FKY
+ c_ME2 = 'ME2' && MEM
PJX_Conversion_Support = 2
VCX_Conversion_Support = 2
SCX_Conversion_Support = 2
FRX_Conversion_Support = 2
LBX_Conversion_Support = 2
MNX_Conversion_Support = 2
+ FKY_Conversion_Support = 2
+ MEM_Conversion_Support = 0
DBF_Conversion_Support = 1
DBC_Conversion_Support = 2
DBF_Conversion_Included = ''
@@ -1403,6 +1409,24 @@ DEFINE CLASS c_foxbin2prg AS Session
ENDPROC
+ PROCEDURE c_FK2_ACCESS
+ IF THIS.n_CFG_Actual = 0 OR ISNULL( THIS.o_Configuration( THIS.n_CFG_Actual ) )
+ RETURN THIS.c_FK2
+ ELSE
+ RETURN NVL( THIS.o_Configuration( THIS.n_CFG_Actual ).c_FK2, THIS.c_FK2 )
+ ENDIF
+ ENDPROC
+
+
+ PROCEDURE c_ME2_ACCESS
+ IF THIS.n_CFG_Actual = 0 OR ISNULL( THIS.o_Configuration( THIS.n_CFG_Actual ) )
+ RETURN THIS.c_ME2
+ ELSE
+ RETURN NVL( THIS.o_Configuration( THIS.n_CFG_Actual ).c_ME2, THIS.c_ME2 )
+ ENDIF
+ ENDPROC
+
+
PROCEDURE PJX_Conversion_Support_ACCESS
IF THIS.n_CFG_Actual = 0 OR ISNULL( THIS.o_Configuration( THIS.n_CFG_Actual ) )
RETURN THIS.PJX_Conversion_Support
@@ -1457,6 +1481,24 @@ DEFINE CLASS c_foxbin2prg AS Session
ENDPROC
+ PROCEDURE FKY_Conversion_Support_ACCESS
+ IF THIS.n_CFG_Actual = 0 OR ISNULL( THIS.o_Configuration( THIS.n_CFG_Actual ) )
+ RETURN THIS.FKY_Conversion_Support
+ ELSE
+ RETURN NVL( THIS.o_Configuration( THIS.n_CFG_Actual ).FKY_Conversion_Support, THIS.FKY_Conversion_Support )
+ ENDIF
+ ENDPROC
+
+
+ PROCEDURE MEM_Conversion_Support_ACCESS
+ IF THIS.n_CFG_Actual = 0 OR ISNULL( THIS.o_Configuration( THIS.n_CFG_Actual ) )
+ RETURN THIS.MEM_Conversion_Support
+ ELSE
+ RETURN NVL( THIS.o_Configuration( THIS.n_CFG_Actual ).MEM_Conversion_Support, THIS.MEM_Conversion_Support )
+ ENDIF
+ ENDPROC
+
+
PROCEDURE DBF_Conversion_Support_ACCESS
IF THIS.n_CFG_Actual = 0 OR ISNULL( THIS.o_Configuration( THIS.n_CFG_Actual ) )
RETURN THIS.DBF_Conversion_Support
@@ -1766,7 +1808,7 @@ DEFINE CLASS c_foxbin2prg AS Session
tcBakFile_1 = FORCEEXT(tcOutputFile, lcExt_1 + lcNext_Bak)
DO CASE
- CASE INLIST( lcExt_1, .c_PJ2, .c_VC2, .c_SC2, .c_FR2, .c_LB2, .c_DB2, .c_DC2, .c_MN2, 'PJM' )
+ CASE INLIST( lcExt_1, .c_PJ2, .c_VC2, .c_SC2, .c_FR2, .c_LB2, .c_DB2, .c_DC2, .c_MN2, .c_FK2, .c_ME2, 'PJM' )
*-- Extensiones TEXTO
CASE lcExt_1 = 'DBF'
@@ -1783,11 +1825,14 @@ DEFINE CLASS c_foxbin2prg AS Session
tcBakFile_2 = FORCEEXT(tcOutputFile, lcExt_2 + lcNext_Bak)
tcBakFile_3 = FORCEEXT(tcOutputFile, lcExt_3 + lcNext_Bak)
- OTHERWISE
+ CASE INLIST( lcExt_1, 'PJX', 'VCX', 'SCX', 'FRX', 'LBX', 'MNX' )
*-- PJX, VCX, SCX, FRX, LBX, MNX
lcExt_2 = LEFT(lcExt_1,2) + 'T'
tcBakFile_2 = FORCEEXT(tcOutputFile, lcExt_2 + lcNext_Bak)
+ OTHERWISE
+ *-- PKY, MEM
+
ENDCASE
IF NOT EMPTY(lcExt_1)
@@ -2636,6 +2681,8 @@ DEFINE CLASS c_foxbin2prg AS Session
, lcExt == 'FRX', .FRX_Conversion_Support > 0 ;
, lcExt == 'LBX', .LBX_Conversion_Support > 0 ;
, lcExt == 'MNX', .MNX_Conversion_Support > 0 ;
+ , lcExt == 'FKY', .FKY_Conversion_Support > 0 ;
+ , lcExt == 'MEM', .MEM_Conversion_Support > 0 ;
, lcExt == 'DBF', NOT ISNULL(loDBF_CFG) AND loDBF_CFG.DBF_Conversion_Support > 0 OR .DBF_Conversion_Support > 0 ;
, lcExt == 'DBC', .DBC_Conversion_Support > 0 ;
, .F. )
@@ -2676,6 +2723,8 @@ DEFINE CLASS c_foxbin2prg AS Session
, lcExt == .c_FR2, .FRX_Conversion_Support = 2 ;
, lcExt == .c_LB2, .LBX_Conversion_Support = 2 ;
, lcExt == .c_MN2, .MNX_Conversion_Support = 2 ;
+ , lcExt == .c_FK2, .FKY_Conversion_Support = 2 ;
+ , lcExt == .c_ME2, .MEM_Conversion_Support = 2 ;
, lcExt == .c_DB2, NOT ISNULL(loDBF_CFG) AND INLIST(loDBF_CFG.DBF_Conversion_Support, 2, 8) ;
OR (INLIST(.DBF_Conversion_Support, 2, 8) ;
AND (ISNULL(loDBF_CFG) OR NOT INLIST(loDBF_CFG.DBF_Conversion_Support, 1, 4))) ;
@@ -2720,6 +2769,8 @@ DEFINE CLASS c_foxbin2prg AS Session
, INLIST(lcExt, .c_FR2, 'FRX'), .FRX_Conversion_Support ;
, INLIST(lcExt, .c_LB2, 'LBX'), .LBX_Conversion_Support ;
, INLIST(lcExt, .c_MN2, 'MNX'), .MNX_Conversion_Support ;
+ , INLIST(lcExt, .c_FK2, 'FKY'), .FKY_Conversion_Support ;
+ , INLIST(lcExt, .c_ME2, 'MEM'), .MEM_Conversion_Support ;
, INLIST(lcExt, .c_DB2, 'DBF'), ICASE( ISNULL(loDBF_CFG) OR loDBF_CFG.DBF_Conversion_Support = 0, .DBF_Conversion_Support, loDBF_CFG.DBF_Conversion_Support ) ;
, INLIST(lcExt, .c_DC2, 'DBC'), .DBC_Conversion_Support ;
, 0 )
@@ -3242,7 +3293,6 @@ DEFINE CLASS c_foxbin2prg AS Session
ENDCASE
*-- UN ARCHIVO INDIVIDUAL O CONSULTA DE SOPORTE DE ARCHIVO
- *IF LEN(EVL(tc_InputFile,'')) = 1
IF lcInputFile_Type = C_FILETYPE_QUERYSUPPORT
*-- Consulta de soporte de conversión (compatibilidad con SourceSafe)
*-- SourceSafe consulta el tipo de soporte de cada archivo antes del Checkin/Checkout
@@ -3923,6 +3973,22 @@ DEFINE CLASS c_foxbin2prg AS Session
loConversor = CREATEOBJECT( 'c_conversor_mnx_a_prg' )
.changeFileAttribute( FORCEEXT( .c_InputFile, .c_MN2 ), lcForceAttribs )
+ CASE lcExtension = 'FKY'
+ IF NOT INLIST(.FKY_Conversion_Support, 1, 2)
+ ERROR (TEXTMERGE(loLang.C_FILE_NAME_IS_NOT_SUPPORTED_LOC))
+ ENDIF
+ .c_OutputFile = FORCEEXT( .c_InputFile, .c_FK2 )
+ loConversor = CREATEOBJECT( 'c_conversor_fky_a_prg' )
+ .changeFileAttribute( FORCEEXT( .c_InputFile, .c_FK2 ), lcForceAttribs )
+
+ CASE lcExtension = 'MEM'
+ IF NOT INLIST(.MEM_Conversion_Support, 1, 2)
+ ERROR (TEXTMERGE(loLang.C_FILE_NAME_IS_NOT_SUPPORTED_LOC))
+ ENDIF
+ .c_OutputFile = FORCEEXT( .c_InputFile, .c_ME2 )
+ loConversor = CREATEOBJECT( 'c_conversor_mem_a_prg' )
+ .changeFileAttribute( FORCEEXT( .c_InputFile, .c_ME2 ), lcForceAttribs )
+
CASE lcExtension = .c_VC2
IF .VCX_Conversion_Support <> 2
ERROR (TEXTMERGE(loLang.C_FILE_NAME_IS_NOT_SUPPORTED_LOC))
@@ -4005,6 +4071,22 @@ DEFINE CLASS c_foxbin2prg AS Session
.changeFileAttribute( FORCEEXT( .c_InputFile, 'MNX' ), lcForceAttribs )
.changeFileAttribute( FORCEEXT( .c_InputFile, 'MNT' ), lcForceAttribs )
+ CASE lcExtension = .c_FK2
+ IF .FKY_Conversion_Support <> 2
+ ERROR (TEXTMERGE(loLang.C_FILE_NAME_IS_NOT_SUPPORTED_LOC))
+ ENDIF
+ .c_OutputFile = FORCEEXT( .c_InputFile, 'FKY' )
+ loConversor = CREATEOBJECT( 'c_conversor_prg_a_fky' )
+ .changeFileAttribute( FORCEEXT( .c_InputFile, 'FKY' ), lcForceAttribs )
+
+ CASE lcExtension = .c_ME2
+ IF .MEM_Conversion_Support <> 2
+ ERROR (TEXTMERGE(loLang.C_FILE_NAME_IS_NOT_SUPPORTED_LOC))
+ ENDIF
+ .c_OutputFile = FORCEEXT( .c_InputFile, 'MEM' )
+ loConversor = CREATEOBJECT( 'c_conversor_prg_a_mem' )
+ .changeFileAttribute( FORCEEXT( .c_InputFile, 'MEM' ), lcForceAttribs )
+
OTHERWISE
*ERROR 'El archivo [' + .c_InputFile + '] no está soportado'
ERROR (TEXTMERGE(loLang.C_FILE_NAME_IS_NOT_SUPPORTED_LOC))
@@ -5208,6 +5290,36 @@ DEFINE CLASS c_foxbin2prg AS Session
ENDFUNC
+ FUNCTION FERROR_Message(tcFileName as String)
+ LOCAL lcMsg, lnError
+ tcFileName = EVL(tcFileName,'')
+ lnError = FERROR()
+
+ DO CASE
+ CASE lnError = 2
+ lcMsg = 'File not found'
+ CASE lnError = 4
+ lcMsg = 'Too many files open (out of file handles)'
+ CASE lnError = 5
+ lcMsg = 'Access denied'
+ CASE lnError = 6
+ lcMsg = 'Invalid file handle given'
+ CASE lnError = 8
+ lcMsg = 'Out of memory'
+ CASE lnError = 25
+ lcMsg = [Seek error (can't seek before the start of a file)]
+ CASE lnError = 29
+ lcMsg = 'Disk full'
+ CASE lnError = 31
+ lcMsg = 'Error opening file'
+ OTHERWISE
+ lcMsg = 'Unrecognized error trying to open the file ' + tcFileName
+ ENDCASE
+
+ RETURN lcMsg
+ ENDFUNC
+
+
ENDDEFINE
@@ -17713,6 +17825,102 @@ ENDDEFINE
+DEFINE CLASS c_conversor_fky_a_prg AS c_conversor_bin_a_prg
+ #IF .F.
+ LOCAL THIS AS c_conversor_fky_a_prg OF 'FOXBIN2PRG.PRG'
+ #ENDIF
+ c_Type = 'FKY'
+
+
+ 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 toMacro, toEx AS EXCEPTION, toFoxBin2Prg
+ DODEFAULT( @toMacro, @toEx, @toFoxBin2Prg )
+
+ #IF .F.
+ LOCAL toMacro AS CL_MACRO OF 'FOXBIN2PRG.PRG'
+ LOCAL toFoxBin2Prg AS c_foxbin2prg OF 'FOXBIN2PRG.PRG'
+ #ENDIF
+
+ LOCAL lnCodError, lnLen, lnHandle ;
+ , loLang as CL_LANG OF 'FOXBIN2PRG.PRG'
+
+ TRY
+ WITH THIS AS c_conversor_fky_a_prg OF 'FOXBIN2PRG.PRG'
+ lnHandle = -1
+
+ IF toFoxBin2Prg.l_ProcessFiles THEN
+ loLang = _SCREEN.o_FoxBin2Prg_Lang
+ STORE 0 TO lnCodError
+
+ .updateProgressbar( 'Analyzing FKY...', 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()
+
+ toMacro = CREATEOBJECT('CL_MACRO')
+ toMacro.get_DataFromMacroFKY(.c_InputFile, @toFoxBin2Prg)
+ C_FB2PRG_CODE = C_FB2PRG_CODE + toMacro.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_FK2 + '...', 2, 2, 1 )
+ ENDIF
+
+ IF .l_Test
+ toMacro = 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 ;
@@ -28000,6 +28208,8 @@ DEFINE CLASS CL_CFG AS CUSTOM
+ [] ;
+ [] ;
+ [] ;
+ + [] ;
+ + [] ;
+ [] ;
+ [] ;
+ [] ;
@@ -28023,6 +28233,8 @@ DEFINE CLASS CL_CFG AS CUSTOM
+ [] ;
+ [] ;
+ [] ;
+ + [] ;
+ + [] ;
+ [] ;
+ [] ;
+ [] ;
@@ -28066,12 +28278,16 @@ DEFINE CLASS CL_CFG AS CUSTOM
c_DB2 = NULL
c_DC2 = NULL
c_MN2 = NULL
+ c_FK2 = NULL
+ c_ME2 = NULL
PJX_Conversion_Support = NULL
VCX_Conversion_Support = NULL
SCX_Conversion_Support = NULL
FRX_Conversion_Support = NULL
LBX_Conversion_Support = NULL
MNX_Conversion_Support = NULL
+ FKY_Conversion_Support = NULL
+ MEM_Conversion_Support = NULL
DBF_Conversion_Support = NULL
DBF_Conversion_Included = NULL
DBF_Conversion_Excluded = NULL
@@ -28113,12 +28329,16 @@ DEFINE CLASS CL_CFG AS CUSTOM
.c_DB2 = toParentCFG.c_DB2
.c_DC2 = toParentCFG.c_DC2
.c_MN2 = toParentCFG.c_MN2
+ .c_FK2 = toParentCFG.c_FK2
+ .c_ME2 = toParentCFG.c_ME2
.PJX_Conversion_Support = toParentCFG.PJX_Conversion_Support
.VCX_Conversion_Support = toParentCFG.VCX_Conversion_Support
.SCX_Conversion_Support = toParentCFG.SCX_Conversion_Support
.FRX_Conversion_Support = toParentCFG.FRX_Conversion_Support
.LBX_Conversion_Support = toParentCFG.LBX_Conversion_Support
.MNX_Conversion_Support = toParentCFG.MNX_Conversion_Support
+ .FKY_Conversion_Support = toParentCFG.FKY_Conversion_Support
+ .MEM_Conversion_Support = toParentCFG.MEM_Conversion_Support
.DBF_Conversion_Support = toParentCFG.DBF_Conversion_Support
.DBF_Conversion_Included = toParentCFG.DBF_Conversion_Included
.DBF_Conversion_Excluded = toParentCFG.DBF_Conversion_Excluded
@@ -28938,3 +29158,856 @@ DEFINE CLASS CL_DBF_CFG AS CUSTOM
DBF_Conversion_Condition = ''
DBF_Conversion_Support = NULL
ENDDEFINE
+
+
+
+DEFINE CLASS CL_MACRO AS CL_COL_BASE
+ #IF .F.
+ LOCAL THIS AS CL_MACRO OF 'FOXBIN2PRG.PRG'
+ #ENDIF
+
+ _MEMBERDATA = [] ;
+ + [] ;
+ + [] ;
+ + [] ;
+ + [] ;
+ + [] ;
+ + [] ;
+ + []
+
+
+ c_InputFile = ''
+
+ *-- Macro Header
+ _Signature = ''
+ _Debug = .F.
+ _NumberOfMacros = ''
+ _Macros = NULL && Colección de macros
+
+
+
+ PROCEDURE INIT
+ DODEFAULT()
+ THIS._Macros = CREATEOBJECT("COLLECTION")
+ ENDPROC
+
+
+ PROCEDURE get_DataFromMacroFKY(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 ;
+ , loMRec as CL_MACRO_RECORD OF 'FOXBIN2PRG.PRG' ;
+ , loColl as Collection ;
+ , loEx as Exception
+
+ TRY
+ lnHandle = -1
+
+ WITH THIS AS CL_MACRO OF 'FOXBIN2PRG.PRG'
+ loColl = ._Macros
+ lnHandle = FOPEN(tcInputFile, 0)
+
+ IF lnHandle = -1
+ lcMsg = toFoxBin2Prg.FERROR_Message(tcInputFile)
+ ERROR (lcMsg)
+ ENDIF
+
+ lnFileLen = FSEEK(lnHandle, 0, 2)
+
+ IF lnFileLen < 17
+ ERROR 'Invalid FKY Macro File size'
+ ELSE
+ =FSEEK(lnHandle, 0, 0)
+ ENDIF
+
+ ._Signature = FREAD(lnHandle, 2)
+
+ IF ._Signature <> CHR(0xFF)+CHR(0x79)
+ ERROR 'Invalid FKY Macro signature'
+ ENDIF
+
+ =FSEEK(lnHandle, 14, 1) && Saltar bytes ignorados
+
+ ._NumberOfMacros = FREAD(lnHandle, 2)
+ lnNumberOfMacros = CTOBIN(._NumberOfMacros,'2RS')
+
+ 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
+
+ FOR I = 1 TO lnNumberOfMacros
+ loMRec = CREATEOBJECT("CL_MACRO_RECORD")
+
+ IF NOT loMRec.ReadNextMacro(lnHandle)
+ EXIT
+ ENDIF
+
+ loColl.Add( loMRec, loMRec.Macro_Name )
+ loMRec = NULL
+ ENDFOR
+
+ 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 decode_SpecialCodes_CR_LF
+ *---------------------------------------------------------------------------------------------------
+ * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
+ * tcText (!@ IN ) Decodifica los caracteres ASCII 10 y 13 de {nCode} a CHR(nCode)
+ *---------------------------------------------------------------------------------------------------
+ LPARAMETERS tcText
+ tcText = STRTRAN( STRTRAN( tcText, '{10}', CHR(10) ), '{13}', CHR(13) )
+ RETURN tcText
+ ENDPROC
+
+
+
+ PROCEDURE encode_SpecialCodes_CR_LF
+ *---------------------------------------------------------------------------------------------------
+ * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
+ * tcText (!@ IN ) Codifica los caracteres ASCII 10 y 13 de CHR(nCode) a {nCode}
+ *---------------------------------------------------------------------------------------------------
+ LPARAMETERS tcText
+ tcText = STRTRAN( STRTRAN( tcText, CHR(10), '{10}' ), CHR(13), '{13}' )
+ RETURN tcText
+ ENDPROC
+
+
+
+ PROCEDURE toText
+ *---------------------------------------------------------------------------------------------------
+ * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
+ *---------------------------------------------------------------------------------------------------
+ LOCAL lcText, loMRec AS CL_MACRO_RECORD OF 'FOXBIN2PRG.PRG'
+ lcText = ''
+
+ WITH THIS AS CL_MACRO OF 'FOXBIN2PRG.PRG'
+
+ *-- Macros
+ FOR EACH loMRec AS CL_MACRO_RECORD OF 'FOXBIN2PRG.PRG' IN ._Macros
+ lcText = lcText + CR_LF + loMRec.toText()
+ ENDFOR
+
+ ENDWITH
+
+ RETURN lcText
+ ENDPROC
+
+
+ENDDEFINE
+
+
+
+DEFINE CLASS CL_MACRO_RECORD AS CL_CUS_BASE
+ _MEMBERDATA = [] ;
+ + [] ;
+ + [] ;
+ + [] ;
+ + [] ;
+ + [] ;
+ + [] ;
+ + [] ;
+ + [] ;
+ + [] ;
+ + []
+
+ *--
+ Macro_Name = ''
+ Macro_Length = ''
+ Keystroke = ''
+ Macro_Keystrokes = ''
+
+
+ PROCEDURE ReadNextMacro(tnHandle as Integer)
+ *---------------------------------------------------------------------------------------------------
+ * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
+ * tnHandle (!v IN ) FKY file handle
+ *---------------------------------------------------------------------------------------------------
+ LOCAL lnMacro_Length
+
+ TRY
+ WITH THIS AS CL_MACRO_RECORD OF 'FOXBIN2PRG.PRG'
+ .Macro_Name = FREAD(tnHandle, 20)
+ .Macro_Length = FREAD(tnHandle, 2)
+ .Keystroke = FREAD(tnHandle, 2)
+ lnMacro_Length = CTOBIN(.Macro_Length, '2RS')
+ .Macro_Keystrokes = FREAD(tnHandle, lnMacro_Length * 2)
+ ENDWITH
+ ENDTRY
+
+ RETURN
+ ENDPROC
+
+
+ PROCEDURE toBin as String
+ *---------------------------------------------------------------------------------------------------
+ * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
+ *---------------------------------------------------------------------------------------------------
+ LOCAL lcText
+
+ WITH THIS AS CL_MACRO_RECORD OF 'FOXBIN2PRG.PRG'
+
+ ENDWITH
+
+ RETURN lcText
+ ENDPROC
+
+
+ PROCEDURE toText as String
+ *---------------------------------------------------------------------------------------------------
+ * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
+ *---------------------------------------------------------------------------------------------------
+ LOCAL lcText, loField AS CL_MACRO_RECORD OF 'FOXBIN2PRG.PRG'
+ lcText = ''
+
+ WITH THIS AS CL_MACRO_RECORD OF 'FOXBIN2PRG.PRG'
+ TEXT TO lcText ADDITIVE TEXTMERGE NOSHOW FLAGS 1+2 PRETEXT 1+2
+ <<>>
+ <<>> Macro_Name : <>
+ <<>> Keystroke : <<.get_Macro_Keystrokes(.Keystroke, .T.)>>
+ <<>> Macro_Keystrokes: <<.get_Macro_Keystrokes(.Macro_Keystrokes)>>
+ <<>>
+ ENDTEXT
+
+ ENDWITH
+
+ RETURN lcText
+ ENDPROC
+
+
+ FUNCTION get_Macro_Keystrokes(tcMacroStr, tlLiteralForCaption)
+ *---------------------------------------------------------------------------------------------------
+ * DEVLUELVE LOS LITERALES DE TODAS LAS TECLAS
+ *---------------------------------------------------------------------------------------------------
+ * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
+ *---------------------------------------------------------------------------------------------------
+ LOCAL lcKeystrokes, I
+
+ WITH THIS AS CL_MACRO_RECORD OF 'FOXBIN2PRG.PRG'
+ lcKeystrokes = ''
+
+ FOR I = 1 TO LEN(tcMacroStr) STEP 2
+ lcKeystrokes = lcKeystrokes + .get_KeyText(@tcMacroStr, @I, tlLiteralForCaption)
+ ENDFOR
+ ENDWITH
+
+ RETURN lcKeystrokes
+ ENDFUNC
+
+
+ FUNCTION get_KeyText(tcMacroStr as String, I as Integer, tlLiteralForCaption as Boolean) as String
+ *---------------------------------------------------------------------------------------------------
+ * DEVLUELVE EL LITERAL DE UNA TECLA
+ *---------------------------------------------------------------------------------------------------
+ * PARÁMETROS: (v=Pasar por valor | @=Pasar por referencia) (!=Obligatorio | ?=Opcional) (IN/OUT)
+ * tcMacroStr (!@ IN ) Cadena de teclas de la macro
+ * I (!@ IN ) Posición actualmente analizada de la cadena
+ * tlLiteralForCaption (?v IN ) Indica si algunos caracteres especiales se deben convertir a literal (ej: ";" => "SHIFT+SEMICOLON")
+ *---------------------------------------------------------------------------------------------------
+ LOCAL lcK1, lcK2, lcKeyName, lcKeyMod, lcTecla, lnKeyVal, lcKeyPair, lnCntMod ;
+ , llComplementar, llKeyCodeShift, llKeyCodeCtrl, llKeyCodeAlt, lnK1, lnK2
+
+ STORE '' TO lcTecla, lcKeyName, lcKeyMod, lcKey
+ lcKeyPair = SUBSTR(tcMacroStr,I,2)
+ lcK1 = LEFT(lcKeyPair,1)
+ lcK2 = RIGHT(lcKeyPair,1)
+ lnK1 = ASC(lcK1)
+ lnK2 = ASC(lcK2)
+ lnKeyVal = CTOBIN(lcKeyPair, '2RS')
+ lnCntMod = 0
+
+ * Tratamiento de modificadores
+ IF NOT lcKeyPair == CHR(0xFE)+CHR(0xFF)
+ IF BITAND(lnKeyVal, 0x1000) = 0x1000 && SHIFT
+ *lcKeyMod = lcKeyMod + IIF(EMPTY(lcKeyMod),'','+') + 'SHIFT'
+ llKeyCodeShift = .T.
+ lnCntMod = lnCntMod + 1
+ ENDIF
+ IF BITAND(lnKeyVal, 0x2000) = 0x2000 && CTRL
+ *lcKeyMod = lcKeyMod + IIF(EMPTY(lcKeyMod),'','+') + 'CTRL'
+ llKeyCodeCtrl = .T.
+ lnCntMod = lnCntMod + 1
+ ENDIF
+ IF BITAND(lnKeyVal, 0x4000) = 0x4000 && ALT
+ *lcKeyMod = lcKeyMod + IIF(EMPTY(lcKeyMod),'','+') + 'ALT'
+ llKeyCodeAlt = .T.
+ lnCntMod = lnCntMod + 1
+ ENDIF
+ IF BITAND(lnKeyVal, 0x8000) = 0x8000 && LITERAL
+ lcKeyMod = lcKeyMod + IIF(EMPTY(lcKeyMod),'','+') + 'LITERAL'
+ ENDIF
+ ENDIF
+
+ *llComplementar = NOT EMPTY(lcKeyMod)
+ llComplementar = llKeyCodeShift
+
+ * Tratamiento de teclas normales
+ * (Ordenar de mayor valor a menor: 0xFFF > 0x000)
+ DO CASE
+ CASE lcKeyPair == CHR(0xFE)+CHR(0xFF)
+ lcKeyName = 'PAUSE '
+ * Buscar el tiempo
+ I = I + 2
+ lcKeyPair = SUBSTR(tcMacroStr,I,2)
+
+ IF lcKeyPair == CHR(0xFF)+CHR(0xFF)
+ lcKeyName = lcKeyName + 'KEY'
+ ELSE
+ lnKeyVal = CTOBIN(lcKeyPair, '2RS')
+ lcKeyName = lcKeyName + LTRIM(STR(lnKeyVal/100,5,2))
+ ENDIF
+
+ CASE INLIST( lnK2, 0x00, 0x10, 0x80) OR lnCntMod > 1
+ *llComplementar = NOT EMPTY(lcKeyMod)
+
+ DO CASE
+ CASE BETWEEN(lnK1, 0x41, 0x7A) && A..z
+ lcKeyName = lcK1
+
+ CASE BETWEEN(lnK1, 0x21, 0x7E)
+ llKeyCodeShift = .F.
+ lcKeyName = lcK1
+
+ CASE lnK1 = 0x7F
+ lcKeyName = 'DEL'
+
+ CASE lnK1 = 0x1B
+ lcKeyName = 'ESCAPE'
+
+ CASE lnK1 = 0x0D
+ lcKeyName = 'ENTER'
+
+ CASE lnK1 = 0x09
+ lcKeyName = 'TAB'
+
+ CASE lnK1 = 0x08
+ lcKeyName = 'BACKSPACE'
+
+ OTHERWISE
+ llComplementar = .F.
+ lcKeyName = 'x' + RIGHT( TRANSFORM(lnKeyVal,'@0'), 4)
+
+ ENDCASE
+
+ OTHERWISE
+ llComplementar = .F.
+
+ DO CASE
+ CASE BITAND(lnKeyVal, 0x1A3) = 0x1A3
+ lcKeyName = 'ALT+DEL'
+
+ CASE BITAND(lnKeyVal, 0x1A2) = 0x1A2
+ lcKeyName = 'ALT+INS'
+
+ CASE BITAND(lnKeyVal, 0x1A1) = 0x1A1
+ lcKeyName = 'ALT+PGND'
+
+ CASE BITAND(lnKeyVal, 0x1A0) = 0x1A0
+ lcKeyName = 'ALT+DNARROW'
+
+ CASE BITAND(lnKeyVal, 0x19F) = 0x19F
+ lcKeyName = 'ALT+END'
+
+ CASE BITAND(lnKeyVal, 0x19D) = 0x19D
+ lcKeyName = 'ALT+RIGHTARROW'
+
+ CASE BITAND(lnKeyVal, 0x19B) = 0x19B
+ lcKeyName = 'ALT+LEFTARROW'
+
+ CASE BITAND(lnKeyVal, 0x199) = 0x199
+ lcKeyName = 'ALT+PGUP'
+
+ CASE BITAND(lnKeyVal, 0x198) = 0x198
+ lcKeyName = 'ALT+UPARROW'
+
+ CASE BITAND(lnKeyVal, 0x197) = 0x197
+ lcKeyName = 'ALT+HOME'
+
+ CASE BITAND(lnKeyVal, 0x194) = 0x194
+ lcKeyName = 'CTRL+TAB'
+
+ CASE BITAND(lnKeyVal, 0x193) = 0x193
+ lcKeyName = 'CTRL+DEL'
+
+ CASE BITAND(lnKeyVal, 0x192) = 0x192
+ lcKeyName = 'CTRL+INS'
+
+ CASE BITAND(lnKeyVal, 0x191) = 0x191
+ lcKeyName = 'CTRL+DNARROW'
+
+ CASE BITAND(lnKeyVal, 0x18D) = 0x18D
+ lcKeyName = 'CTRL+UPARROW'
+
+ CASE BITAND(lnKeyVal, 0x18C) = 0x18C
+ lcKeyName = 'ALT+F12'
+
+ CASE BITAND(lnKeyVal, 0x18B) = 0x18B
+ lcKeyName = 'ALT+F11'
+
+ CASE BITAND(lnKeyVal, 0x18A) = 0x18A
+ lcKeyName = 'CTRL+F12'
+
+ CASE BITAND(lnKeyVal, 0x189) = 0x189
+ lcKeyName = 'CTRL+F11'
+
+ CASE BITAND(lnKeyVal, 0x15F) = 0x188
+ lcKeyName = 'SHIFT+F12'
+
+ CASE BITAND(lnKeyVal, 0x15E) = 0x187
+ lcKeyName = 'SHIFT+F11'
+
+ CASE BITAND(lnKeyVal, 0x186) = 0x186
+ lcKeyName = 'F12'
+
+ CASE BITAND(lnKeyVal, 0x185) = 0x185
+ lcKeyName = 'F11'
+
+ CASE BITAND(lnKeyVal, 0x184) = 0x184
+ lcKeyName = 'CTRL+PGUP'
+
+ CASE BITAND(lnKeyVal, 0x181) = 0x181
+ lcKeyName = 'ALT+0'
+
+ CASE BITAND(lnKeyVal, 0x180) = 0x180
+ lcKeyName = 'ALT+9'
+
+ CASE BITAND(lnKeyVal, 0x17F) = 0x17F
+ lcKeyName = 'ALT+8'
+
+ CASE BITAND(lnKeyVal, 0x17E) = 0x17E
+ lcKeyName = 'ALT+7'
+
+ CASE BITAND(lnKeyVal, 0x17D) = 0x17D
+ lcKeyName = 'ALT+6'
+
+ CASE BITAND(lnKeyVal, 0x17C) = 0x17C
+ lcKeyName = 'ALT+5'
+
+ CASE BITAND(lnKeyVal, 0x17B) = 0x17B
+ lcKeyName = 'ALT+4'
+
+ CASE BITAND(lnKeyVal, 0x17A) = 0x17A
+ lcKeyName = 'ALT+3'
+
+ CASE BITAND(lnKeyVal, 0x179) = 0x179
+ lcKeyName = 'ALT+2'
+
+ CASE BITAND(lnKeyVal, 0x178) = 0x178
+ lcKeyName = 'ALT+1'
+
+ CASE BITAND(lnKeyVal, 0x177) = 0x177
+ lcKeyName = 'CTRL+HOME'
+
+ CASE BITAND(lnKeyVal, 0x176) = 0x176
+ lcKeyName = 'CTRL+PGDN'
+
+ CASE BITAND(lnKeyVal, 0x175) = 0x175
+ lcKeyName = 'CTRL+END'
+
+ CASE BITAND(lnKeyVal, 0x174) = 0x174
+ lcKeyName = 'CTRL+RIGHTARROW'
+
+ CASE BITAND(lnKeyVal, 0x173) = 0x173
+ lcKeyName = 'CTRL+LEFTARROW'
+
+ CASE BITAND(lnKeyVal, 0x171) = 0x171
+ lcKeyName = 'ALT+F10'
+
+ CASE BITAND(lnKeyVal, 0x170) = 0x170
+ lcKeyName = 'ALT+F9'
+
+ CASE BITAND(lnKeyVal, 0x16F) = 0x16F
+ lcKeyName = 'ALT+F8'
+
+ CASE BITAND(lnKeyVal, 0x16E) = 0x16E
+ lcKeyName = 'ALT+F7'
+
+ CASE BITAND(lnKeyVal, 0x16D) = 0x16D
+ lcKeyName = 'ALT+F6'
+
+ CASE BITAND(lnKeyVal, 0x16C) = 0x16C
+ lcKeyName = 'ALT+F5'
+
+ CASE BITAND(lnKeyVal, 0x16B) = 0x16B
+ lcKeyName = 'ALT+F4'
+
+ CASE BITAND(lnKeyVal, 0x16A) = 0x16A
+ lcKeyName = 'ALT+F3'
+
+ CASE BITAND(lnKeyVal, 0x169) = 0x169
+ lcKeyName = 'ALT+F2'
+
+ CASE BITAND(lnKeyVal, 0x168) = 0x168
+ lcKeyName = 'ALT+F1'
+
+ CASE BITAND(lnKeyVal, 0x167) = 0x167
+ lcKeyName = 'CTRL+F10'
+
+ CASE BITAND(lnKeyVal, 0x166) = 0x166
+ lcKeyName = 'CTRL+F9'
+
+ CASE BITAND(lnKeyVal, 0x165) = 0x165
+ lcKeyName = 'CTRL+F8'
+
+ CASE BITAND(lnKeyVal, 0x164) = 0x164
+ lcKeyName = 'CTRL+F7'
+
+ CASE BITAND(lnKeyVal, 0x163) = 0x163
+ lcKeyName = 'CTRL+F6'
+
+ CASE BITAND(lnKeyVal, 0x162) = 0x162
+ lcKeyName = 'CTRL+F5'
+
+ CASE BITAND(lnKeyVal, 0x161) = 0x161
+ lcKeyName = 'CTRL+F4'
+
+ CASE BITAND(lnKeyVal, 0x160) = 0x160
+ lcKeyName = 'CTRL+F3'
+
+ CASE BITAND(lnKeyVal, 0x15F) = 0x15F
+ lcKeyName = 'CTRL+F2'
+
+ CASE BITAND(lnKeyVal, 0x15E) = 0x15E
+ lcKeyName = 'CTRL+F1'
+
+ CASE BITAND(lnKeyVal, 0x15D) = 0x15D
+ lcKeyName = 'SHIFT+F10'
+
+ CASE BITAND(lnKeyVal, 0x15C) = 0x15C
+ lcKeyName = 'SHIFT+F9'
+
+ CASE BITAND(lnKeyVal, 0x15B) = 0x15B
+ lcKeyName = 'SHIFT+F8'
+
+ CASE BITAND(lnKeyVal, 0x15A) = 0x15A
+ lcKeyName = 'SHIFT+F7'
+
+ CASE BITAND(lnKeyVal, 0x159) = 0x159
+ lcKeyName = 'SHIFT+F6'
+
+ CASE BITAND(lnKeyVal, 0x158) = 0x158
+ lcKeyName = 'SHIFT+F5'
+
+ CASE BITAND(lnKeyVal, 0x157) = 0x157
+ lcKeyName = 'SHIFT+F4'
+
+ CASE BITAND(lnKeyVal, 0x156) = 0x156
+ lcKeyName = 'SHIFT+F3'
+
+ CASE BITAND(lnKeyVal, 0x155) = 0x155
+ lcKeyName = 'SHIFT+F2'
+
+ CASE BITAND(lnKeyVal, 0x154) = 0x154
+ lcKeyName = 'SHIFT+F1'
+
+ CASE BITAND(lnKeyVal, 0x153) = 0x153
+ lcKeyName = 'DEL'
+
+ CASE BITAND(lnKeyVal, 0x152) = 0x152
+ lcKeyName = 'INS'
+
+ CASE BITAND(lnKeyVal, 0x151) = 0x151
+ lcKeyName = 'PGDN'
+
+ CASE BITAND(lnKeyVal, 0x150) = 0x150
+ lcKeyName = 'DNARROW'
+
+ CASE BITAND(lnKeyVal, 0x14F) = 0x14F
+ lcKeyName = 'END'
+
+ CASE BITAND(lnKeyVal, 0x14D) = 0x14D
+ lcKeyName = 'RIGHTARROW'
+
+ CASE BITAND(lnKeyVal, 0x14B) = 0x14B
+ lcKeyName = 'LEFTARROW'
+
+ CASE BITAND(lnKeyVal, 0x149) = 0x149
+ lcKeyName = 'PGUP'
+
+ CASE BITAND(lnKeyVal, 0x148) = 0x148
+ lcKeyName = 'UPARROW'
+
+ CASE BITAND(lnKeyVal, 0x147) = 0x147
+ lcKeyName = 'HOME'
+
+ CASE BITAND(lnKeyVal, 0x144) = 0x144
+ lcKeyName = 'F10'
+
+ CASE BITAND(lnKeyVal, 0x143) = 0x143
+ lcKeyName = 'F9'
+
+ CASE BITAND(lnKeyVal, 0x142) = 0x142
+ lcKeyName = 'F8'
+
+ CASE BITAND(lnKeyVal, 0x141) = 0x141
+ lcKeyName = 'F7'
+
+ CASE BITAND(lnKeyVal, 0x140) = 0x140
+ lcKeyName = 'F6'
+
+ CASE BITAND(lnKeyVal, 0x13F) = 0x13F
+ lcKeyName = 'F5'
+
+ CASE BITAND(lnKeyVal, 0x13E) = 0x13E
+ lcKeyName = 'F4'
+
+ CASE BITAND(lnKeyVal, 0x13D) = 0x13D
+ lcKeyName = 'F3'
+
+ CASE BITAND(lnKeyVal, 0x13C) = 0x13C
+ lcKeyName = 'F2'
+
+ CASE BITAND(lnKeyVal, 0x13B) = 0x13B
+ lcKeyName = 'F1'
+
+ CASE BITAND(lnKeyVal, 0x132) = 0x132
+ lcKeyName = 'ALT+M'
+
+ CASE BITAND(lnKeyVal, 0x131) = 0x131
+ lcKeyName = 'ALT+N'
+
+ CASE BITAND(lnKeyVal, 0x130) = 0x130
+ lcKeyName = 'ALT+B'
+
+ CASE BITAND(lnKeyVal, 0x12F) = 0x12F
+ lcKeyName = 'ALT+V'
+
+ CASE BITAND(lnKeyVal, 0x12E) = 0x12E
+ lcKeyName = 'ALT+C'
+
+ CASE BITAND(lnKeyVal, 0x12D) = 0x12D
+ lcKeyName = 'ALT+X'
+
+ CASE BITAND(lnKeyVal, 0x12C) = 0x12C
+ lcKeyName = 'ALT+Z'
+
+ CASE BITAND(lnKeyVal, 0x126) = 0x126
+ lcKeyName = 'ALT+L'
+
+ CASE BITAND(lnKeyVal, 0x125) = 0x125
+ lcKeyName = 'ALT+K'
+
+ CASE BITAND(lnKeyVal, 0x124) = 0x124
+ lcKeyName = 'ALT+J'
+
+ CASE BITAND(lnKeyVal, 0x123) = 0x123
+ lcKeyName = 'ALT+H'
+
+ CASE BITAND(lnKeyVal, 0x122) = 0x122
+ lcKeyName = 'ALT+G'
+
+ CASE BITAND(lnKeyVal, 0x121) = 0x121
+ lcKeyName = 'ALT+F'
+
+ CASE BITAND(lnKeyVal, 0x120) = 0x120
+ lcKeyName = 'ALT+D'
+
+ CASE BITAND(lnKeyVal, 0x11F) = 0x11F
+ lcKeyName = 'ALT+S'
+
+ CASE BITAND(lnKeyVal, 0x11E) = 0x11E
+ lcKeyName = 'ALT+A'
+
+ CASE BITAND(lnKeyVal, 0x119) = 0x119
+ lcKeyName = 'ALT+P'
+
+ CASE BITAND(lnKeyVal, 0x118) = 0x118
+ lcKeyName = 'ALT+O'
+
+ CASE BITAND(lnKeyVal, 0x117) = 0x117
+ lcKeyName = 'ALT+I'
+
+ CASE BITAND(lnKeyVal, 0x116) = 0x116
+ lcKeyName = 'ALT+U'
+
+ CASE BITAND(lnKeyVal, 0x115) = 0x115
+ lcKeyName = 'ALT+Y'
+
+ CASE BITAND(lnKeyVal, 0x114) = 0x114
+ lcKeyName = 'ALT+T'
+
+ CASE BITAND(lnKeyVal, 0x113) = 0x113
+ lcKeyName = 'ALT+R'
+
+ CASE BITAND(lnKeyVal, 0x112) = 0x112
+ lcKeyName = 'ALT+E'
+
+ CASE BITAND(lnKeyVal, 0x111) = 0x111
+ lcKeyName = 'ALT+U'
+
+ CASE BITAND(lnKeyVal, 0x110) = 0x110
+ lcKeyName = 'ALT+Q'
+
+ CASE BITAND(lnKeyVal, 0x10F) = 0x10F
+ lcKeyName = 'BACKTAB'
+
+ CASE BITAND(lnKeyVal, 0x100) = 0x100
+ lcKeyName = 'LEFTMOUSE'
+
+ CASE BITAND(lnKeyVal, 0x020) = 0x020
+ lcKeyName = 'CTRL+SPACEBAR'
+
+ CASE BITAND(lnKeyVal, 0x01F) = 0x01F
+ lcKeyName = 'CTRL+HYPHEN'
+
+ CASE BITAND(lnKeyVal, 0x01E) = 0x01E
+ lcKeyName = 'CTRL+CARET'
+
+ CASE BITAND(lnKeyVal, 0x01D) = 0x01D
+ lcKeyName = 'CTRL+RBRACKET'
+
+ CASE BITAND(lnKeyVal, 0x01C) = 0x01C
+ lcKeyName = 'CTRL+BACKSLASH'
+
+ CASE BITAND(lnKeyVal, 0x01B) = 0x01B
+ lcKeyName = 'CTRL+LBRACKET'
+
+ CASE BITAND(lnKeyVal, 0x01A) = 0x01A
+ lcKeyName = 'CTRL+Z'
+
+ CASE BITAND(lnKeyVal, 0x019) = 0x019
+ lcKeyName = 'CTRL+Y'
+
+ CASE BITAND(lnKeyVal, 0x018) = 0x018
+ lcKeyName = 'CTRL+X'
+
+ CASE BITAND(lnKeyVal, 0x017) = 0x017
+ lcKeyName = 'CTRL+W'
+
+ CASE BITAND(lnKeyVal, 0x016) = 0x016
+ lcKeyName = 'CTRL+V'
+
+ CASE BITAND(lnKeyVal, 0x015) = 0x015
+ lcKeyName = 'CTRL+U'
+
+ CASE BITAND(lnKeyVal, 0x014) = 0x014
+ lcKeyName = 'CTRL+T'
+
+ CASE BITAND(lnKeyVal, 0x013) = 0x013
+ lcKeyName = 'CTRL+S'
+
+ CASE BITAND(lnKeyVal, 0x012) = 0x012
+ lcKeyName = 'CTRL+R'
+
+ CASE BITAND(lnKeyVal, 0x011) = 0x011
+ lcKeyName = 'CTRL+Q'
+
+ CASE BITAND(lnKeyVal, 0x010) = 0x010
+ lcKeyName = 'CTRL+P'
+
+ CASE BITAND(lnKeyVal, 0x00F) = 0x00F
+ lcKeyName = 'CTRL+O'
+
+ CASE BITAND(lnKeyVal, 0x00E) = 0x00E
+ lcKeyName = 'CTRL+N'
+
+ CASE BITAND(lnKeyVal, 0x00D) = 0x00D
+ lcKeyName = 'CTRL+M'
+
+ CASE BITAND(lnKeyVal, 0x00C) = 0x00C
+ lcKeyName = 'CTRL+L'
+
+ CASE BITAND(lnKeyVal, 0x00B) = 0x00B
+ lcKeyName = 'CTRL+K'
+
+ CASE BITAND(lnKeyVal, 0x00A) = 0x00A
+ lcKeyName = 'CTRL+ENTER'
+
+ CASE BITAND(lnKeyVal, 0x00A) = 0x00A
+ lcKeyName = 'CTRL+J'
+
+ CASE BITAND(lnKeyVal, 0x009) = 0x009
+ lcKeyName = 'CTRL+I'
+
+ CASE BITAND(lnKeyVal, 0x008) = 0x008
+ lcKeyName = 'CTRL+H'
+
+ CASE BITAND(lnKeyVal, 0x007) = 0x007
+ lcKeyName = 'CTRL+G'
+
+ CASE BITAND(lnKeyVal, 0x006) = 0x006
+ lcKeyName = 'CTRL+F'
+
+ CASE BITAND(lnKeyVal, 0x005) = 0x005
+ lcKeyName = 'CTRL+E'
+
+ CASE BITAND(lnKeyVal, 0x004) = 0x004
+ lcKeyName = 'CTRL+D'
+
+ CASE BITAND(lnKeyVal, 0x003) = 0x003
+ lcKeyName = 'CTRL+C'
+
+ CASE BITAND(lnKeyVal, 0x002) = 0x002
+ lcKeyName = 'CTRL+B'
+
+ CASE BITAND(lnKeyVal, 0x001) = 0x001
+ lcKeyName = 'CTRL+A'
+
+ OTHERWISE
+ lcKeyName = CHR(lnKeyVal)
+
+ ENDCASE
+ ENDCASE
+
+ * Tratamiento de modificadores
+ IF NOT lcKeyPair == CHR(0xFE)+CHR(0xFF)
+ IF llKeyCodeShift && SHIFT
+ lcKeyMod = lcKeyMod + IIF(EMPTY(lcKeyMod),'','+') + 'SHIFT'
+ ENDIF
+ IF llKeyCodeCtrl && CTRL
+ lcKeyMod = lcKeyMod + IIF(EMPTY(lcKeyMod),'','+') + 'CTRL'
+ ENDIF
+ IF llKeyCodeAlt && ALT
+ lcKeyMod = lcKeyMod + IIF(EMPTY(lcKeyMod),'','+') + 'ALT'
+ ENDIF
+ *IF BITAND(lnKeyVal, 0x8000) = 0x8000 && LITERAL
+ * lcKeyMod = lcKeyMod + IIF(EMPTY(lcKeyMod),'','+') + 'LITERAL'
+ *ENDIF
+ ENDIF
+
+ * Tratamiento de combinación final
+ DO CASE
+ CASE LEN(lcKeyName) > 1 AND NOT llComplementar
+ lcTecla = '{' + lcKeyName + '}'
+
+ CASE EMPTY(lcKeyMod)
+ lcTecla = lcKeyName
+
+ OTHERWISE
+ lcTecla = '{' + lcKeyMod + '+' + lcKeyName + '}'
+
+ ENDCASE
+
+ RETURN lcTecla
+ ENDFUNC
+
+
+ENDDEFINE
+
+
+