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 + + +