VERSION 1.0 CLASS BEGIN MultiUse = -1 'True Persistable = 0 'NotPersistable DataBindingBehavior = 0 'vbNone DataSourceBehavior = 0 'vbNone MTSTransactionMode = 0 'NotAnMTSObject END Attribute VB_Name = "VSComandos" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = True Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Option Explicit ' esta clase engloba los comandos del VisualSINTAC para aprovechar ' la facilidad del comando 'CallByName' ' va ligada al módulo 'Run' ya que es en ese dónde están ' las tablas de variables y ciertos procedimientos auxiliares ' NOTA: los nombre "reales" de los comandos son los de los métodos de estas clases ' pero sin el "VS_" inicial Private Par() As String ' para guardar los parámetros de la llamada a un comando ' separa los parámetros de un comando ' le pasamos la línea de llamada del comando y un número variable de argumentos ' que definen los parámetros que se espera, de la forma: ' ' n_param.,def_param1, def_param2, ... ' ' dónde: ' ' "num_param" es el nº de parámetros que se espera ' "def_param1", "def_param2",... las definiciones del tipo de parámetro de la forma "AB" ' dónde: ' ' "A" es "+" si tenemos que evaluarlo o "-" si no ' "B" es "N" si es númérico o "C" si es cadena ' ' devuelve False si hubo algún error ' Private Function Parametros(ByVal sLin As String, ParamArray Def()) As Boolean Dim ParTmp() As String Dim bHayPar As Boolean Dim i As Long, j As Long, lNumParam As Long, lPar As Long Dim s As String, sParam As String, sDefParam As String ReDim ParTmp(0) ParTmp(0) = "" bHayPar = False On Error Resume Next lNumParam = CLng(Def(0)) If Err.Number <> 0 Then Parametros = False Exit Function End If sParam = SeparaParametros(sLin) If sParam = Chr(0) Then Parametros = False Exit Function End If ' si no tiene parámetros y se le ha pasado alguno If lNumParam = 0 And sParam <> "" Then DescError "Demasiados parámetros" Parametros = False Exit Function End If ' comprobamos que el nº de parámetros sea correcto i = 1 Do While True If CogeParametro(sParam, i) = Chr(0) Then i = i - 1 Exit Do End If i = i + 1 Loop If lNumParam <> i Then DescError "Se esperaban " & CStr(lNumParam) & " parámetros" Parametros = False Exit Function End If For i = 1 To lNumParam sDefParam = UCase(Def(i)) If Len(sDefParam) <> 2 Then Parametros = False Exit Function End If ' cogemos el parámetro s = CogeParametro(sParam, i) If s = Chr(0) Then Parametros = False Exit Function End If ' si hay que evaluarlo If Left(sDefParam, 1) = "+" Then s = AnalizaExpresion(s) If s = Chr(0) Then Parametros = False Exit Function End If End If ' si se espera parámetro numérico lo intentamos convertir If Right(sDefParam, 1) = "N" Then lPar = CLng(s) If Err.Number <> 0 Then DescError "El parámetro " & CStr(i) & " debe ser numérico" Parametros = False Exit Function End If End If If Not bHayPar Then ParTmp(0) = s bHayPar = True Else j = UBound(ParTmp) + 1 ReDim Preserve ParTmp(j) ParTmp(j) = s End If Next ' copiamos los parámetros encontrados en una variable global If bHayPar Then ReDim Par(UBound(ParTmp)) For i = 0 To UBound(ParTmp) Par(i) = ParTmp(i) Next Else ReDim Par(0) Par(0) = "" End If Parametros = True End Function ' DEBUG(0/1) ' activa (1) o desactiva (0) el depurador Public Function VS_Debug(ByVal sLin As String) As String Dim lDeb As Long #If EsInterprete Then VS_Debug = "" #Else If Not Parametros(sLin, 1, "+N") Then VS_Debug = Chr(0) Exit Function End If lDeb = CLng(Par(0)) bDepurar = IIf(lDeb = 1, True, False) VentanaDepuracion VS_Debug = "" #End If End Function ' ERROR(0/1) ' activa (1) o desactiva (0) el control de errores, cuando está desactivado ' se puede consultar la variable global "Error" para ver si se ha producido alguno Public Function VS_Error(ByVal sLin As String) As String Dim lErr As Long ' cuando se ejecuta este comando no podemos ignorar los errores bIgnorarErrores = False If Not Parametros(sLin, 1, "+N") Then VS_Error = Chr(0) Exit Function End If lErr = CLng(Par(0)) bIgnorarErrores = IIf(lErr = 0, True, False) VS_Error = "" End Function ' CLEARERROR() ' limpia el último error producido cuando tenemos ERROR(0) Public Function VS_ClearError(ByVal sLin As String) As String Dim bTemp As Boolean ' cuando se ejecuta este comando no podemos ignorar los errores bTemp = bIgnorarErrores bIgnorarErrores = False If Not Parametros(sLin, 0) Then VS_ClearError = Chr(0) Exit Function End If sDescError = "" VS_ClearError = "" bIgnorarErrores = bTemp End Function ' DECLARE(var) ' declara una variable y, opcionalmente, le asigna un valor Public Function VS_Declare(ByVal sLin As String) As String Dim sVar As String Dim i As Long If Not Parametros(sLin, 1, "-C") Then VS_Declare = Chr(0) Exit Function End If ' comprueba que sea un nombre válido de variable sVar = UCase(Par(0)) If Not CompruebaNombreProcVar(sVar) Then DescError "Nombre de variable no válido: " & sVar VS_Declare = Chr(0) Exit Function End If If lProcActual = -1 Then CreaVariable sVar, "", VAR_GLOBAL, 0 Else CreaVariable sVar, "", lProcActual, Procedimientos(lProcActual).NumSerie End If VS_Declare = "" End Function ' PRINT([expr]) ' imprime una expresión, si no se le pasan parámetros imprime una línea en blanco Public Function VS_Print(ByVal sLin As String) As String Dim s As String, sParam As String, sResultado As String Dim lPantalla As Long sParam = SeparaParametros(sLin) If sParam = Chr(0) Then VS_Print = Chr(0) Exit Function End If ' si no hay parámetros, imprimimos una línea en blanco If sParam = "" Then frmVis.ImprimeTexto 0, "" VS_Print = "" Exit Function End If sResultado = AnalizaExpresion(sParam) If sResultado = Chr(0) Then VS_Print = Chr(0) Exit Function End If ' cogemos la "pantalla" activa On Error Resume Next s = ValorVariable(SCREEN_ACT) lPantalla = CLng(s) If Err.Number <> 0 Then VS_Print = Chr(0) Exit Function End If frmVis.ImprimeTexto lPantalla, sResultado VS_Print = "" End Function ' INPUT(prompt) ' queda a la espera de que el usuario introduzca una cadena por teclado y la devuelve ' presenta el mensaje que le pasemos como parámetro Public Function VS_Input(ByVal sLin As String) As String Dim s As String Dim lPantalla As Long If Not Parametros(sLin, 1, "+C") Then VS_Input = Chr(0) Exit Function End If ' cogemos la "pantalla" activa On Error Resume Next s = ValorVariable(SCREEN_ACT) lPantalla = CLng(s) If Err.Number <> 0 Then VS_Input = Chr(0) Exit Function End If s = frmVis.LeeInput(lPantalla, Par(0)) ' NOTA: debido a una limitación del evaluador de expresiones debemos sustituir ' las comillas dobles por simples s = Replace(s, COMILLAS, "'") VS_Input = s End Function ' PAUSE([expr]) ' hace una pausa en milisegundos, si no le pasamos ningún parámetro hace una ' pausa indefinida, hasta que se pulse una tecla ' devuelve el código de la tecla pulsada si se hizo pausa indefinida ' o cadena vacía si en otro caso Public Function VS_Pause(ByVal sLin As String) As String Dim i As Long, lMiliseg As Long, lFin As Long Dim sParam As String, sResultado As String, sRet As String sRet = "" sParam = SeparaParametros(sLin) If sParam = Chr(0) Then VS_Pause = Chr(0) Exit Function End If ' si no le hemos dado ningún parámetro If sParam = "" Then lMiliseg = 0 Else sResultado = AnalizaExpresion(sParam) If sResultado = Chr(0) Then VS_Pause = Chr(0) Exit Function End If On Error Resume Next lMiliseg = CLng(sResultado) If Err.Number <> 0 Then VS_Pause = Chr(0) Exit Function End If End If ' hace la pausa, si no dió parámetros o dió cero hace pausa indefinida If lMiliseg = 0 Then sRet = frmVis.LeeTecla Else ' NOTA: la función GetTickCount se resetea cada 49 días de ' estar el equipo encendido lFin = GetTickCount + lMiliseg Do i = GetTickCount DoEvents Loop While i < lFin End If VS_Pause = sRet End Function ' PARSE(expr) ' analiza una frase, actualiza las variables del sistema relacionadas y devuelve ' el fragmento que ha quedado sin analizar Public Function VS_Parse(ByVal sLin As String) As String Dim bVerbo As Boolean, bNombre1 As Boolean, bAdjetivo1 As Boolean, bNombre2 As Boolean, _ bAdjetivo2 As Boolean, bPrep As Boolean Dim c As String, sFrase As String, sCarSepar As String, _ sVerboAnt As String, sPal As String, sPal0 As String, sCarComill As String, _ sFraseComill As String, sNombreAnt As String, sAdjetivoAnt As String, _ sPrepa As String, sTerm As String Dim i As Long, j As Long, lSepar As Long, lPal As Long, lPal0 As Long, lComill As Long If Not Parametros(sLin, 1, "+C") Then VS_Parse = Chr(0) Exit Function End If sFrase = Par(0) ' caracteres no significativos y separadores sCarSepar = ValorVariable(PARSE_SEPAR) ' caracteres para entrecomillar frases sCarComill = ValorVariable(PARSE_COMILL) ' array con las terminaciones verbales sTerm = ValorVariable(PARSE_TERMVERB) ' vamos separando palabra por palabra esperando encontrar: ' ' Verbo [Nombre1] [Adjetivo1] [Preposición] [Nombre2] [Adjetivo2] [] ... ' ' las palabras estarán separadas por espacios ' el separador podrá ser también una conjunción ' si se encuentra una frase entrecomillada se devuelve ' ' dejaremos en variables del sistema la información del "parseado": ' ' VERBO verbo encontrado ' VERBOMOV si es o no verbo de movimiento ' NOMBRE1 nombre 1 encontrado ' ADJETIVO1 adjetivo 1 encontrado ' NOMBRE2 nombre 2 encontrado ' ADJETIVO2 adjetivo 2 encontrado ' PREPOSICION preposición encontrada ' PARSEFRASE frase entrecomillada ' guardamos el verbo, el nombre 1 y el adjetivo 1 sVerboAnt = ValorVariable(PARSE_VERBO) sNombreAnt = ValorVariable(PARSE_NOMBRE1) sAdjetivoAnt = ValorVariable(PARSE_ADJETIVO1) CreaVariable PARSE_VERBO, "", VAR_GLOBAL, 0 CreaVariable PARSE_VERBOMOV, EXPR_FALSE, VAR_GLOBAL, 0 CreaVariable PARSE_NOMBRE1, "", VAR_GLOBAL, 0 CreaVariable PARSE_ADJETIVO1, "", VAR_GLOBAL, 0 CreaVariable PARSE_NOMBRE2, "", VAR_GLOBAL, 0 CreaVariable PARSE_ADJETIVO2, "", VAR_GLOBAL, 0 CreaVariable PARSE_PREPOS, "", VAR_GLOBAL, 0 CreaVariable PARSE_FRASE, "", VAR_GLOBAL, 0 bVerbo = False bNombre1 = False bAdjetivo1 = False bNombre2 = False bAdjetivo2 = False bPrep = False Do ' salimos cuando se nos termine la frase If sFrase = "" Then Exit Do End If ' eliminamos espacios al principio sFrase = LTrim(sFrase) c = Left(sFrase, 1) ' si encontramos un separador, lo eliminamos y salimos If InStr(sCarSepar, c) > 0 Then i = Len(sFrase) - 1 If i > 0 Then sFrase = Right(sFrase, i) Else sFrase = "" End If Exit Do End If ' si encontramos inicio de frase entrecomillada If InStr(sCarComill, c) > 0 Then sFraseComill = "" For lComill = 1 To Len(sCarComill) ' buscamos las siguiente comillas y separamos la frase entrecomillada ' las primeras comillas las tenemos al inicio de la frase i = 1 j = InStr(i + 1, sFrase, Mid(sCarComill, lComill, 1)) If j > i + 1 Then ' separamos la frase entrecomillada sFraseComill = Mid(sFrase, i + 1, j - i - 1) If j < Len(sFrase) Then sFrase = Right(sFrase, Len(sFrase) - j) Else sFrase = "" End If Exit For End If Next ' si no hemos encontrado comillas de cierre, cogemos hasta el final If lComill > Len(sCarComill) Then If Len(sFrase) > 1 Then sFraseComill = Right(sFrase, Len(sFrase) - 1) Else sFraseComill = "" End If sFrase = "" End If CreaVariable PARSE_FRASE, sFraseComill, VAR_GLOBAL, 0 Else ' buscamos el siguiente separador o espacio lSepar = 0 For i = 1 To Len(sFrase) c = Mid(sFrase, i, 1) j = InStr(" " & sCarSepar, c) If j > 0 Then lSepar = i Exit For End If Next ' si no lo encontramos vamos hasta el final de la frase If lSepar = 0 Then lSepar = Len(sFrase) + 1 End If ' cogemos la palabra If lSepar > 1 Then sPal = Left(sFrase, lSepar - 1) Else sPal = "" End If ' eliminamos la palabra de la frase para la siguiente pasada i = Len(sFrase) - lSepar + 1 If i > 0 Then sFrase = Right(sFrase, i) Else sFrase = "" End If sPal = UCase(Trim(sPal)) lPal = EstaEnVoc(sPal, -1, 0) ' si no la hemos encontrado en el vocabulario If lPal = -1 Then ' comprobamos si es verbo con terminación si no hemos encontrado ya uno If Not bVerbo Then For i = 1 To ArrayLen(sTerm) c = UCase(ArrayItem(sTerm, i)) If Len(sPal) > Len(c) And Right(sPal, Len(c)) = c Then ' quitamos la terminación y comprobamos a ver si es un verbo sPal = Left(sPal, Len(sPal) - Len(c)) lPal = EstaEnVoc(sPal, -1, 0) If lPal <> -1 Then ' puede ser un sinónimo If Vocabulario(lPal).Tipo = VOC_SINONIMO Then sPal = Vocabulario(lPal).Sinonimo lPal = EstaEnVoc(sPal, -1, 0) End If ' por si acaso hemos fallado al encontrar el sinónimo If lPal <> -1 Then If Vocabulario(lPal).Tipo = VOC_VERBO Then CreaVariable PARSE_VERBO, sPal, VAR_GLOBAL, 0 CreaVariable PARSE_NOMBRE1, sNombreAnt, VAR_GLOBAL, 0 CreaVariable PARSE_ADJETIVO1, sAdjetivoAnt, VAR_GLOBAL, 0 bVerbo = True bNombre1 = True bAdjetivo1 = True End If End If End If Exit For End If Next End If ' si seguimos sin encontrar un verbo, cogemos el anterior '''If Not bVerbo Then ''' CreaVariable PARSE_VERBO, sVerboAnt, VAR_GLOBAL, 0 ''' bVerbo = True '''End If Else ' si es un sinónimo lo sustituimos por la palabra real Do While Vocabulario(lPal).Tipo = VOC_SINONIMO sPal0 = sPal lPal0 = lPal sPal = Vocabulario(lPal).Sinonimo lPal = EstaEnVoc(sPal, -1, 0) ' si es un verbo y ya tenemos uno, seguimos buscando If bVerbo And Vocabulario(lPal).Tipo = VOC_VERBO Then sPal = sPal0 lPal = EstaEnVoc(sPal, -1, lPal0 + 1) If lPal = -1 Then Exit Do End If End If Loop ' por si acaso al buscar el sinónimo no lo hemos encontrado (?) If lPal <> -1 Then Select Case Vocabulario(lPal).Tipo Case VOC_VERBO If Not bVerbo Then CreaVariable PARSE_VERBO, sPal, VAR_GLOBAL, 0 bVerbo = True End If Case VOC_CONJ Exit Do Case VOC_VERBOMOV If Not bVerbo Then CreaVariable PARSE_VERBO, sPal, VAR_GLOBAL, 0 CreaVariable PARSE_VERBOMOV, EXPR_TRUE, VAR_GLOBAL, 0 End If bVerbo = True Case VOC_NOMBRE If Not bNombre1 Then CreaVariable PARSE_NOMBRE1, sPal, VAR_GLOBAL, 0 bNombre1 = True ElseIf Not bNombre2 Then CreaVariable PARSE_NOMBRE2, sPal, VAR_GLOBAL, 0 bNombre2 = True End If Case VOC_ADJETIVO If Not bAdjetivo1 And Not bNombre2 Then CreaVariable PARSE_ADJETIVO1, sPal, VAR_GLOBAL, 0 bAdjetivo1 = True ElseIf Not bAdjetivo2 Then CreaVariable PARSE_ADJETIVO2, sPal, VAR_GLOBAL, 0 bAdjetivo2 = True End If Case VOC_PREPOS If Not bPrep And Not bNombre2 And Not bAdjetivo2 Then CreaVariable PARSE_PREPOS, sPal, VAR_GLOBAL, 0 bPrep = True End If End Select End If End If End If Loop While True ' si la frase no tenía verbo, usamos el anterior If Not bVerbo Then CreaVariable PARSE_VERBO, sVerboAnt, VAR_GLOBAL, 0 End If ' devolvemos el resto por si se quiere volver a hacer otra pasada VS_Parse = LTrim(sFrase) End Function ' CALL(procedimiento[,param1,param2,...]) ' ejecuta una llamada a un procedimiento y le pasa los parámetros ' devuelve el valor de retorno del procedimiento Public Function VS_Call(ByVal sLin As String) As String Dim sProc As String, sParam As String, sExpr As String Dim i As Long sParam = SeparaParametros(sLin) If sParam = Chr(0) Then VS_Call = Chr(0) Exit Function End If ' cogemos el nombre del procedimiento sExpr = CogeParametro(sParam, 1) sProc = UCase(AnalizaExpresion(sExpr)) If sProc = Chr(0) Then VS_Call = Chr(0) Exit Function End If ' eliminamos el primer parámetro (que corresponde al nombre del procedimiento) i = InStr(sParam, SEPAR_PARAM) If i > 0 Then sParam = Right(sParam, Len(sParam) - i) Else sParam = "" End If VS_Call = EjecutaProc(sProc, sParam) End Function ' LEN(expr) ' devuelve la longitud de una cadena Public Function VS_Len(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_Len = Chr(0) Exit Function End If VS_Len = CStr(Len(Par(0))) End Function ' LEFT(expr,longitud) ' devuelve una subcadena, de longitud determinada, por la izquierda de una cadena Public Function VS_Left(ByVal sLin As String) As String Dim sResultado As String If Not Parametros(sLin, 2, "+C", "+N") Then VS_Left = Chr(0) Exit Function End If On Error Resume Next sResultado = Left(Par(0), CLng(Par(1))) If Err.Number = 0 Then VS_Left = sResultado Else DescError "Error en parámetros" VS_Left = Chr(0) End If End Function ' RIGHT(expr,longitud) ' devuelve una subcadena, de longitud determinada, por la derecha de una cadena Public Function VS_Right(ByVal sLin As String) As String Dim sResultado As String If Not Parametros(sLin, 2, "+C", "+N") Then VS_Right = Chr(0) Exit Function End If On Error Resume Next sResultado = Right(Par(0), CLng(Par(1))) If Err.Number = 0 Then VS_Right = sResultado Else DescError "Error en parámetros" VS_Right = Chr(0) End If End Function ' MID(expr,inicio,longitud) ' devuelve una subcadena comenzando en "inicio", de longitud determinada, de una cadena Public Function VS_Mid(ByVal sLin As String) As String Dim sResultado As String If Not Parametros(sLin, 3, "+C", "+N", "+N") Then VS_Mid = Chr(0) Exit Function End If On Error Resume Next sResultado = Mid(Par(0), CLng(Par(1)), CLng(Par(2))) If Err.Number = 0 Then VS_Mid = sResultado Else DescError "Error en parámetros" VS_Mid = Chr(0) End If End Function ' UCASE(expr) ' devuelve una cadena convertida a mayúsculas Public Function VS_UCase(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_UCase = Chr(0) Exit Function End If VS_UCase = UCase(Par(0)) End Function ' LCASE(expr) ' devuelve una cadena convertida a minúsculas Public Function VS_LCase(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_LCase = Chr(0) Exit Function End If VS_LCase = LCase(Par(0)) End Function ' TRIM(expr) ' devuelve una cadena sin los espacios sobrantes por la izquierda y la derecha Public Function VS_Trim(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_Trim = Chr(0) Exit Function End If VS_Trim = Trim(Par(0)) End Function ' LTRIM(expr) ' devuelve una cadena sin los espacios sobrantes por la izquierda Public Function VS_LTrim(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_LTrim = Chr(0) Exit Function End If VS_LTrim = LTrim(Par(0)) End Function ' RTRIM(expr) ' devuelve una cadena sin los espacios sobrantes por la derecha Public Function VS_RTrim(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_RTrim = Chr(0) Exit Function End If VS_RTrim = RTrim(Par(0)) End Function ' IN(inicio,expr1,expr2) ' comprueba si 'expr2' está dentro de 'expr2' y devuelve su posición por la izquierda ' (empezando en 'inicio') o 0 si no se encontró Public Function VS_In(ByVal sLin As String) As String Dim i As Long If Not Parametros(sLin, 3, "+N", "+C", "+C") Then VS_In = Chr(0) Exit Function End If On Error Resume Next i = InStr(CLng(Par(0)), Par(1), Par(2)) If Err.Number = 0 Then VS_In = CStr(i) Else DescError "Error en parámetros" VS_In = Chr(0) End If End Function ' ARRAY(expr1,expr2,expr3,...) ' crea un array con los elementos que le pasemos como parámetros Public Function VS_Array(ByVal sLin As String) As String Dim sParam As String, sExpr As String, sArray As String Dim i As Long sParam = SeparaParametros(sLin) If sParam = Chr(0) Then VS_Array = Chr(0) Exit Function End If ' cogemos los parámetros y creamos el array sArray = "" i = 1 Do While True sExpr = CogeParametro(sParam, i) sExpr = AnalizaExpresion(sExpr) If sExpr = Chr(0) Then Exit Do End If ' encadenamos los elementos del array sArray = sArray & sExpr & Chr(SEPAR_ARRAY) i = i + 1 Loop VS_Array = sArray End Function ' ARRAYLEN(array) ' devuelve el nº de elementos de un array Public Function VS_ArrayLen(ByVal sLin As String) As String Dim i As Long, lNumElem As Long If Not Parametros(sLin, 1, "+C") Then VS_ArrayLen = Chr(0) Exit Function End If VS_ArrayLen = ArrayLen(Par(0)) End Function ' ARRAYITEM(array,n) ' devuelve el elemento n-ésimo de un array Public Function VS_ArrayItem(ByVal sLin As String) As String If Not Parametros(sLin, 2, "+C", "+N") Then VS_ArrayItem = Chr(0) Exit Function End If VS_ArrayItem = ArrayItem(Par(0), CLng(Par(1))) End Function ' INARRAY(array,elemento) ' comprueba si un elemento se encuentra dentro de un array y devuelve su posición ' devuelve 0 si no lo encontró ' NOTA: sólo se busca la 1ª coincidencia del elemento Public Function VS_InArray(ByVal sLin As String) As String If Not Parametros(sLin, 2, "+C", "+C") Then VS_InArray = Chr(0) Exit Function End If VS_InArray = CStr(InArray(Par(0), Par(1))) End Function ' SUBARRAY(array,inicio,longitud) ' devuelve un sub-array, empezando por "inicio", con un nº de elementos determinado ' por "longitud" Public Function VS_SubArray(ByVal sLin As String) As String Dim s As String, sSubArray As String Dim i As Long, lInicio As Long, lNumElem As Long If Not Parametros(sLin, 3, "+C", "+N", "+N") Then VS_SubArray = Chr(0) Exit Function End If sSubArray = "" lInicio = CLng(Par(1)) lNumElem = CLng(Par(2)) For i = lInicio To lInicio + lNumElem - 1 s = ArrayItem(Par(0), i) If s = Chr(0) Then DescError "Error al recuperar elemento " & CStr(i) & " del array" VS_SubArray = Chr(0) Exit Function Else sSubArray = sSubArray & s & Chr(SEPAR_ARRAY) End If Next If sSubArray = "" Then DescError "Sub-array vacío" VS_SubArray = Chr(0) Else VS_SubArray = sSubArray End If End Function ' ARRAYINSERT(array,posicion,elem) ' inserta un elemento en una posición de un array, si posición > longitud del array ' el elemento se inserta al final, y devuelve el array resultante Public Function VS_ArrayInsert(ByVal sLin As String) As String Dim lElem As Long If Not Parametros(sLin, 3, "+C", "+N", "+C") Then VS_ArrayInsert = Chr(0) Exit Function End If lElem = CLng(Par(1)) If lElem < 0 Then DescError "Elemento fuera del array" VS_ArrayInsert = Chr(0) End If VS_ArrayInsert = ArrayInsert(Par(0), lElem, Par(2)) End Function ' ARRAYLET(array,posicion,valor) ' cambia el valor de un elemento en una posición de un array ' y devuelve el array resultante Public Function VS_ArrayLet(ByVal sLin As String) As String Dim lElem As Long If Not Parametros(sLin, 3, "+C", "+N", "+C") Then VS_ArrayLet = Chr(0) Exit Function End If lElem = CLng(Par(1)) If lElem < 0 Or lElem > ArrayLen(Par(0)) Then DescError "Elemento fuera del array" VS_ArrayLet = Chr(0) End If VS_ArrayLet = ArrayLet(Par(0), lElem, Par(2)) End Function ' ARRAYFORMAT(array,separador,separador_final,punto_final,texto_vacio) ' formatea un array como una cadena de texto, separado cada elemento por 'separador' ' excepto los dos últimos que irán separador por 'separador_final' ' la cadena termina con 'punto_final' ' devuelve 'texto_vacio' si el array está vacio Public Function VS_ArrayFormat(ByVal sLin As String) As String Dim i As Long, lNumElem As Long Dim s As String, sElem As String, sUltElem As String If Not Parametros(sLin, 5, "+C", "+C", "+C", "+C", "+C") Then VS_ArrayFormat = Chr(0) Exit Function End If ' si no se ha dado separador final lo iguala al separador If Par(2) = "" Then Par(2) = Par(1) End If lNumElem = ArrayLen(Par(0)) If lNumElem = 0 Then VS_ArrayFormat = Par(4) Else s = "" sUltElem = "" For i = 1 To lNumElem sElem = ArrayItem(Par(0), i) ' ignoramos los elementos vacios If sElem <> "" Then If s = "" Then s = sElem Else s = s & Par(1) & sElem End If sUltElem = sElem End If Next ' comprobamos si al final todos los elementos del array estaban vacíos If s = "" Then s = Par(4) Else ' si hay más de un elemento, debemos unir los dos últimos con el separador ' final If s <> sUltElem Then s = Left(s, Len(s) - Len(sUltElem) - Len(Par(1))) s = s & Par(2) & sUltElem End If ' punto y final s = s & Par(3) End If VS_ArrayFormat = s End If End Function ' WINDOWPOS(x,y) ' define la posición de la ventana principal Public Function VS_WindowPos(ByVal sLin As String) As String If Not Parametros(sLin, 2, "+N", "+N") Then VS_WindowPos = Chr(0) Exit Function End If frmVis.PosVentana CLng(Par(0)), CLng(Par(1)) VS_WindowPos = "" End Function ' WINDOWSIZE(ancho,alto) ' define el tamaño (en pixels) de la ventana principal Public Function VS_WindowSize(ByVal sLin As String) As String If Not Parametros(sLin, 2, "+N", "+N") Then VS_WindowSize = Chr(0) Exit Function End If frmVis.TamVentana CLng(Par(0)), CLng(Par(1)) VS_WindowSize = "" End Function ' WINDOWBACKGROUND(fondo) ' define el fondo de la ventana principal, si damos una cadena de la forma "@rrggbb" ' lo pone del color correspondiente, si le damos una cadena de la forma "#nnnnn" se ' intenta cargar el gráfico desde el fichero de recursos Public Function VS_WindowBackground(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_WindowBackground = Chr(0) Exit Function End If frmVis.FondoVentana Par(0) VS_WindowBackground = "" End Function ' WINDOWSTYLE(estilo,titulo) ' define el estilo de la ventana (0=sin borde, 1=borde Windows) y el título (si estilo no es 0) Public Function VS_WindowStyle(ByVal sLin As String) As String If Not Parametros(sLin, 2, "+N", "+C") Then VS_WindowStyle = Chr(0) Exit Function End If frmVis.EstiloVentana CLng(Par(0)), Par(1) VS_WindowStyle = "" End Function ' CREATESCREEN() ' crea una "pantalla" dentro de la ventana principal y devuelve su nº Public Function VS_CreateScreen(ByVal sLin As String) As String Dim lPantalla As Long If Not Parametros(sLin, 0) Then VS_CreateScreen = Chr(0) Exit Function End If lPantalla = frmVis.CreaPantalla If lPantalla > 0 Then VS_CreateScreen = CStr(lPantalla) Else VS_CreateScreen = Chr(0) End If End Function ' DESTROYSCREEN(pantalla) ' elimina una "pantalla" (la 0 no se puede eliminar) ' NOTA: el nº de todas las pantallas que tengan uno superior a la eliminada ' se decrementa en 1 Public Function VS_DestroyScreen(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+N") Then VS_DestroyScreen = Chr(0) Exit Function End If frmVis.EliminaPantalla CLng(Par(0)) VS_DestroyScreen = "" End Function ' SCREENSCROLL(pantalla,scroll) ' cambia el modo de scroll de una pantalla ' el parámetro 'scroll' indica si la pantalla tiene scroll continuo (0) o ' se espera pulsación de tecla antes de hacer scroll (1) Public Function VS_ScreenScroll(ByVal sLin As String) As String If Not Parametros(sLin, 2, "+N", "+N") Then VS_ScreenScroll = Chr(0) Exit Function End If frmVis.ModoScrollPantalla CLng(Par(0)), CLng(Par(1)) VS_ScreenScroll = "" End Function ' SCREENPOS(pantalla,x,y) ' define la posición de una "pantalla" dentro de la ventana principal Public Function VS_ScreenPos(ByVal sLin As String) As String If Not Parametros(sLin, 3, "+N", "+N", "+N") Then VS_ScreenPos = Chr(0) Exit Function End If frmVis.PosPantalla CLng(Par(0)), CLng(Par(1)), CLng(Par(2)) VS_ScreenPos = "" End Function ' SCREENSIZE(pantalla,ancho,alto) ' define el tamaño (en pixels) de una "pantalla" Public Function VS_ScreenSize(ByVal sLin As String) As String If Not Parametros(sLin, 3, "+N", "+N", "+N") Then VS_ScreenSize = Chr(0) Exit Function End If frmVis.TamPantalla CLng(Par(0)), CLng(Par(1)), CLng(Par(2)) VS_ScreenSize = "" End Function ' SCREEN(pantalla) ' selecciona una "pantalla" como activa (a ella irán las entradas y salidas posteriores) ' se actualiza la variable del sistema SCREEN_ACT Public Function VS_Screen(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+N") Then VS_Screen = Chr(0) Exit Function End If CreaVariable SCREEN_ACT, Par(0), VAR_GLOBAL, 0 VS_Screen = "" End Function ' SCREENIMG(pantalla,imagen) ' pone una imagen como fondo de una "pantalla" activa, 'imagen' puede ser el ' nombre de un fichero o una cadena de la forma "#nnnnn" para indicar que es un ' recurso de imagen Public Function VS_ScreenImg(ByVal sLin As String) As String If Not Parametros(sLin, 2, "+N", "+C") Then VS_ScreenImg = Chr(0) Exit Function End If frmVis.FondoPantalla CLng(Par(0)), Par(1) VS_ScreenImg = "" End Function ' SCREENCLS(pantalla) ' limpia una "pantalla" Public Function VS_ScreenCls(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+N") Then VS_ScreenCls = Chr(0) Exit Function End If frmVis.LimpiaPantalla CLng(Par(0)) VS_ScreenCls = "" End Function ' SCREENAT(pantalla,x,y) ' fija la posición de impresión de una "pantalla" Public Function VS_ScreenAt(ByVal sLin As String) As String If Not Parametros(sLin, 3, "+N", "+N", "+N") Then VS_ScreenAt = Chr(0) Exit Function End If frmVis.PosImpPantalla CLng(Par(0)), CLng(Par(1)), CLng(Par(2)) VS_ScreenAt = "" End Function ' REMOVEAC(expr) ' convierte una cadena sustituyendo las vocales acentuadas por ' vocales si acentuar (es útil para no tener que definir en el vocabulario palabras ' acentuadas y sin acentuar) Public Function VS_RemoveAc(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_RemoveAc = Chr(0) Exit Function End If VS_RemoveAc = QuitaAcentos(Par(0)) End Function ' SAVE(fichero) ' guarda el estado actual en un fichero Public Function VS_Save(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_Save = Chr(0) Exit Function End If If Not GuardaEstado(Par(0)) Then VS_Save = EXPR_FALSE Else VS_Save = EXPR_TRUE End If End Function ' LOAD(fichero) ' carga el estado desde un fichero Public Function VS_Load(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_Load = Chr(0) Exit Function End If If Not RecuperaEstado(Par(0)) Then VS_Load = EXPR_FALSE Else VS_Load = EXPR_TRUE End If End Function ' NOT(expr) ' devuelve el valor negado de una expresión lógica (si no es un expresión lógica ' la devuelve sin ningún cambio) Public Function VS_Not(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_Not = Chr(0) Exit Function End If If Par(0) = EXPR_TRUE Then VS_Not = EXPR_FALSE ElseIf Par(0) = EXPR_FALSE Then VS_Not = EXPR_TRUE Else VS_Not = Par(0) End If End Function ' LOADSONG(modulo) ' carga un módulo de sonido y devuelve su identificador ' si 'modulo' es el nombre de un fichero lo carga desde el fichero ' si es de la forma "#nnnnn" busca el módulo en el fichero de recursos Public Function VS_LoadSong(ByVal sLin As String) As String Dim lIDMod As Long If Not Parametros(sLin, 1, "+C") Then VS_LoadSong = Chr(0) Exit Function End If lIDMod = CargarModulo(Par(0)) If lIDMod = 0 Then DescError "Error al cargar el módulo: " & Par(0) VS_LoadSong = Chr(0) Else VS_LoadSong = CStr(lIDMod) End If End Function ' PLAYSONG(IDmod) ' comienza la reproducción de un módulo de sonido Public Function VS_PlaySong(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+N") Then VS_PlaySong = Chr(0) Exit Function End If If Not TocarModulo(CLng(Par(0))) Then DescError "Error al reproducir módulo de sonido" VS_PlaySong = Chr(0) Else VS_PlaySong = "" End If End Function ' UNLOADSONG(IDmodulo) ' descarga de memoria un módulo de sonido Public Function VS_UnloadSong(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+N") Then VS_UnloadSong = Chr(0) Exit Function End If DescargarModulo CLng(Par(0)) VS_UnloadSong = "" End Function ' VOLUME(volumen) ' cambia el volumen de reproducción general ' el volumen se puede variar por porcentaje (50=mitad, 100=normal, 200=doble,...) Public Function VS_Volume(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+N") Then VS_Volume = Chr(0) Exit Function End If VolumenGeneral CLng(Par(0)) VS_Volume = "" End Function ' LOADWAV(wav) ' carga un WAv y devuelve su identificador ' si 'wav' es el nombre de un fichero lo carga desde el fichero ' si es de la forma "#nnnnn" busca el módulo en el fichero de recursos Public Function VS_LoadWav(ByVal sLin As String) As String Dim lIDWav As Long If Not Parametros(sLin, 1, "+C") Then VS_LoadWav = Chr(0) Exit Function End If lIDWav = CargarSample(Par(0)) If lIDWav = 0 Then DescError "Error al cargar WAV: " & Par(0) VS_LoadWav = Chr(0) Else VS_LoadWav = CStr(lIDWav) End If End Function ' PLAYWAV(IDwav,frecuencia,volumen) ' reproduce un WAV cargado con una frecuencia (Hz), un volumen Public Function VS_PlayWav(ByVal sLin As String) As String If Not Parametros(sLin, 3, "+N", "+N", "+N") Then VS_PlayWav = Chr(0) Exit Function End If If Not TocarSample(CLng(Par(0)), CLng(Par(1)), CLng(Par(2))) Then DescError "Error al reproducir WAV" VS_PlayWav = Chr(0) Else VS_PlayWav = "" End If End Function ' UNLOADWAV(IDwav) ' descarga un WAV de memoria Public Function VS_UnloadWav(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+N") Then VS_UnloadWav = Chr(0) Exit Function End If DescargarSample CLng(Par(0)) VS_UnloadWav = "" End Function ' RANDOM(min,max) ' genera un nº aleatorio comprendido entre 'min' y 'max' (ambos inclusive) Public Function VS_Random(ByVal sLin As String) As String Dim lRnd As Long, lLim1 As Long, lLim2 As Long If Not Parametros(sLin, 2, "+N", "+N") Then VS_Random = Chr(0) Exit Function End If lLim1 = CLng(Par(0)) lLim2 = CLng(Par(1)) lRnd = CLng((lLim2 - lLim1 + 1) * Rnd + lLim1) If lRnd < lLim1 Then lRnd = lLim1 End If If lRnd > lLim2 Then lRnd = lLim2 End If VS_Random = CStr(lRnd) End Function ' ONTIMER(tiempo,procedimiento) ' ejecuta un procedimiento a intervalos de tiempo definidos (en milisegundos) ' devuelve el ID del temporizador asignado Public Function VS_OnTimer(ByVal sLin As String) As String Dim lReloj As Long If Not Parametros(sLin, 2, "+N", "+S") Then VS_OnTimer = Chr(0) Exit Function End If lReloj = frmVis.CreaReloj(CLng(Par(0)), Par(1)) If lReloj = -1 Then VS_OnTimer = Chr(0) Else VS_OnTimer = CStr(lReloj) End If End Function ' STOPTIMER(t) ' para un temporizador Public Function VS_StopTimer(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+N") Then VS_StopTimer = Chr(0) Exit Function End If frmVis.ParaReloj CLng(Par(0)) VS_StopTimer = "" End Function ' STARTTIMER(t) ' arranca un temporizador Public Function VS_StartTimer(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+N") Then VS_StartTimer = Chr(0) Exit Function End If frmVis.ActivaReloj CLng(Par(0)) VS_StartTimer = "" End Function ' TYPEOF(nombre) ' devuelve el tipo de un objeto (0=ninguno, 1=localidad, 2=objeto, 3=PSI) Public Function VS_TypeOf(ByVal sLin As String) As String Dim sNombre As String, sAdjetivo As String Dim i As Long Dim iTipo As Integer If Not Parametros(sLin, 1, "+C") Then VS_TypeOf = Chr(0) Exit Function End If Par(0) = UCase(Par(0)) SeparaNombreAdj Par(0), sNombre, sAdjetivo i = DevuelveObjeto(sNombre, sAdjetivo, iTipo) VS_TypeOf = IIf(i = -1, "0", CStr(iTipo + 1)) End Function ' SEARCH(nombre,propiedades,donde) ' busca el objeto o PSI cuyo nombre se aproxime más al dado teniendo en cuenta ' una serie de reglas de acuerdo al parámetro 'donde': ' ' 0 : objetos presentes en la localidad del jugador o que este lleve encima ' 1 : objetos presentes en la localidad del jugador (pero no los que lleva encima) ' 2 : objetos que lleva encima el jugador ' 3 : PSIs presentes en la localidad del jugador ' 9 : todos los objetos que estén visibles ' ' devuelve un array con los objetos o PSIs encontrados o cadena vacía si no encontró ' ninguno, se puede usar '*' como nombre para buscar TODOS los objetos/PSIs Public Function VS_Search(ByVal sLin As String) As String Dim Propiedades() As String Dim bPropiedades As Boolean Dim sNombre As String, sAdjetivo As String, sLocJugador As String, _ sPSIJugador As String, sObj As String, sArray As String, _ sProp As String, sVal As String Dim i As Long, j As Long, k As Long, lPSIJugador As Long, lDonde As Long If Not Parametros(sLin, 3, "+C", "+C", "+N") Then VS_Search = Chr(0) Exit Function End If Par(0) = UCase(Par(0)) SeparaNombreAdj Par(0), sNombre, sAdjetivo ' separamos la cadena de propiedades "prop1=val1,prop2=val2,..." y la dejamos ' en un array donde cada elemento es una comparación a realizar (prop1=val1) Propiedades = Split(Par(1), ",") lDonde = CLng(Par(2)) lPSIJugador = NumPSIJugador sPSIJugador = JuntaNombreAdj(PSIs(lPSIJugador).Nombre, PSIs(lPSIJugador).Adjetivo) sLocJugador = PSIs(lPSIJugador).Localidad sArray = "" Select Case lDonde Case 0, 1, 2, 9 ' buscamos entre los objetos For i = 0 To UBound(Objetos) If (sNombre = "*" Or Objetos(i).Nombre = sNombre) And (sAdjetivo = "" Or Objetos(i).Adjetivo = sAdjetivo) _ And ( _ ((lDonde = 0 Or lDonde = 1) And Objetos(i).TipoContenedor = OBJ_CONTLOC And Objetos(i).Contenedor = sLocJugador) _ Or ((lDonde = 0 Or lDonde = 2) And Objetos(i).TipoContenedor = OBJ_CONTPSI And Objetos(i).Contenedor = sPSIJugador) _ Or (lDonde = 9) _ ) Then sObj = JuntaNombreAdj(Objetos(i).Nombre, Objetos(i).Adjetivo) ' comprobamos si es visible If PropiedadObj(sObj, OBJ_PROP_INVISIBLE, "") = EXPR_FALSE Then ' comprobamos las propiedades (si se expecificaron) If UBound(Propiedades) >= 0 Then bPropiedades = True For j = 0 To UBound(Propiedades) k = InStr(Propiedades(j), "=") If k > 1 And k < Len(Propiedades(j)) Then sProp = UCase(Left(Propiedades(j), k - 1)) sVal = UCase(Mid(Propiedades(j), k + 1)) If UCase(PropiedadObj(sObj, sProp, "")) <> sVal Then bPropiedades = False Exit For End If End If Next ' si se cumplen todas las comparaciones If bPropiedades Then sArray = ArrayInsert(sArray, ArrayLen(sArray) + 1, sObj) End If Else sArray = ArrayInsert(sArray, ArrayLen(sArray) + 1, sObj) End If End If End If Next Case 3 ' buscamos entre los PSIs For i = 0 To UBound(PSIs) If (sNombre = "*" Or PSIs(i).Nombre = sNombre) And (sAdjetivo = "" Or PSIs(i).Adjetivo = sAdjetivo) _ And PSIs(i).Localidad = sLocJugador Then sObj = JuntaNombreAdj(PSIs(i).Nombre, PSIs(i).Adjetivo) ' comprobamos si es visible If PropiedadPSI(sObj, PSI_PROP_INVISIBLE, "") = EXPR_FALSE Then ' comprobamos las propiedades (si se expecificaron) If UBound(Propiedades) >= 0 Then bPropiedades = True For j = 0 To UBound(Propiedades) k = InStr(Propiedades(j), "=") If k > 1 And k < Len(Propiedades(j)) Then sProp = UCase(Left(Propiedades(j), k - 1)) sVal = UCase(Mid(Propiedades(j), k + 1)) If UCase(PropiedadPSI(sObj, sProp, "")) <> sVal Then bPropiedades = False Exit For End If End If Next ' si se cumplen todas las comparaciones If bPropiedades Then sArray = ArrayInsert(sArray, ArrayLen(sArray) + 1, sObj) End If Else sArray = ArrayInsert(sArray, ArrayLen(sArray) + 1, sObj) End If End If End If Next End Select VS_Search = sArray End Function ' FONT(fuente) ' carga un fichero de tipo de letra, si se le da una cadena de la forma "#nnnnn" intenta ' cargarlo desde el fichero de recursos Public Function VS_Font(ByVal sLin As String) As String If Not Parametros(sLin, 1, "+C") Then VS_Font = Chr(0) Exit Function End If CargaResFuente sFichAventura & EXT_DLL, Par(0) VS_Font = "" End Function