// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// Reporte :    FUNCIONES DE USO COMUN EN LAS FORMAS PREIMPRESAS               LibFormas.rpt 
//
// Sistema:     FORMAS PREIMPRESAS          Versión v1.0 Windows
//
// Descripcion::En este archivo se guardan todas las funciones de uso común para las formas
//             preimpresas, son funciones de edición, de busqueda y de cálculo que se agregan 
//             mediante un Incluye.
//             
// Creación  :  JUNIO/2001  , Félix B. de la Cruz Sandoval
//    
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
columnas 1;21


Objeto FormPrei = @CreaObjeto('FormPreiOleSvr.FuncLibrary')

DefFunc fFormateaFecha(aFecha; aFormato)
	FormPrei.FormateaFecha(aFecha; aFormato)
	Retorna FormPrei.Str_Resultado1
FinFunc

// ==========================================================================================
// fFormateaNumero
// Descripción:  convierte el numero a una cadena con el formato indicado por aMascarilla,y 
//        Con los decimales indicados por aDecimales.
//        0) -1234.00  1) (1234.00)  2) -1,234.00 3) (1,234.00)
// Regresa: Cadena que representa el número recibido    FBCS
// 10/12/2003 ND 2597 Se aplica redondeo al número recibido según valor antes de presentarlo
//		      con una mascarilla, el algoritmo fue copiado de AdminPAQ y adaptado al
//                    reporte. (EGV)
// 08/12/2004 ND 3038,3081 Antes de efectuar el redondeo se revisa si el número es cadena 
//            vacia para regresarse sin hacer nada. (DRdA)
// ==========================================================================================
DEFFUNC fFormateaNumero(aNumero;aMascarilla;aDecimales)
  Local lNumeroComoCadena,lPos, lCont, lCadenaTmp
  Local lImporteBase10             // Importe para la base 10.
  Local lImporte                   // Importe con la base aplicada.
  Local lEntero      // Parte entera del Importe.
  Local lFraccion    // Parte fraccionaria del importe.
  Local lEnteroTmp                 // Parte entera del importe de la fracción.
  Local lFraccionTmp // Parte fraccionara del importe de la fracción.
  Local lPotencia  // Para sacar la potencia en base 10 de acuerdo a los decimales.
  Local lCiclo, lBuffer, lLong
  
  // Se valida el dominio de la mascarilla
  Si (aMascarilla < 0 O aMascarilla > 3)
    aMascarilla = 2
  Finsi

  lNumeroComoCadena = @Str(aNumero;aDecimales)
  Si @Len(lNumeroComoCadena) = 0
     Retorna lNumeroComoCadena     
  FinSi

// lNumeroComoCadena debe quedar redondeado segun valor en este bloque de codigo//////////////

  // Valores usados para el ejemplo:
  // aImporte   = 10.0174
  // aDecimales = 3


  // Obtiene el importe de la base, 10X
  // Ejemplo: pow10(3) = 1000
  lImporteBase10 = 1
  lCiclo = 1
  Mientras lCiclo <= aDecimales
    lImporteBase10 = lImporteBase10 * 10
    lCiclo = lCiclo + 1
  FinMientras 

  // lImporte = aImporte * 10 * 10
  lImporte = aNumero
  lCiclo = 1
  Mientras lCiclo <= aDecimales
    lImporte = lImporte * 10
    lCiclo = lCiclo + 1 
  FinMientras

  // Obtiene la parte entera y la fracción del importe.
  // lFraccion = .4
  // lEntero   = 10017  
  lEntero = @int(lImporte)
  lBuffer = @val(lEntero)
  lFraccion = lImporte - lBuffer

  // Obtiene el valor de la fraccion como entero para saber si se incrementa
  // en 1 a la parte entera del importe.
  // Ejemplo: .4 * 10 = 4 
  lFraccionTmp = lFraccion * 10
  lEnteroTmp = @int(lFraccionTmp)
  
  // Si la fracción es mayor a 5 incrementa uno para que no haya pérdida
  // en la fracción o valor anterior
  Si @abs(lEnteroTmp) >= 5 
    lEntero = lEntero + @abs(lEnteroTmp) / lEnteroTmp // Considera el signo
  FinSi
  
  // Obtiene el nuevo importe redondeado
  // Ejemplo: 10017 / 1000 = 10.017 
  // Si hizo esta validación por la posible pérdida que genera el proceso y
  // esto se hace por que en los redondeos nunca el resultado final deber ser
  // menor al inicial
  lBuffer = lEntero / lImporteBase10
//////////////////////////////////////////////////////////////////////////////////////////////

  lNumeroComoCadena = @Str(lBuffer;aDecimales)
  
  lLong = @Len(lNumeroComoCadena)

  // Guardo los decimales
  lDec = @SubStr(lNumeroComoCadena;lLong-aDecimales;aDecimales)
  // Recorto la cadena, se quitan los decimales y el punto, solo si hay decimales
  Si aDecimales > 0
    lLong = lLong - (aDecimales +1)
    lNumeroComoCadena = @SubStr(lNumeroComoCadena;0;lLong)
  Finsi
  // Se quita el signo - , en caso de negativo
  Si aNumero < 0
    lLong = lLong - 1
    lNumeroComoCadena = @SubStr(lNumeroComoCadena;1;lLong)
  Finsi
  
  // Ahora se insertan las comas en caso de ser tipo 2 o tipo 3
  Si aMascarilla = 2 O aMascarilla = 3
    lPos = lLong-1  // Se empieza apartir de la última pos. en la cadena
    lCont = 0
    lCadenaTmp = ''
    Si lLong > 3
      Mientras lPos >= 0 
        lCadenaTmp = @SubStr(lNumeroComoCadena;lPos;1) & lCadenaTmp
        
        lCont = lCont +1
        lPos = lPos - 1
        // se aplica el modulo tres para saber cuando agregar una coma, 
        // excepto si es el primer caracter de Izquierda a Derecha
        Si (lCont%3) = 0 y lPos >= 0
          lCadenaTmp = ',' & lCadenaTmp
        Finsi
      FinMientras
      lNumeroComoCadena = lCadenaTmp  
    Finsi
  Finsi
   
  // Se agregan los decimales, solo si hay decimales
  Si aDecimales > 0
    lNumeroComoCadena = lNumeroComoCadena & '.' & lDec
  Finsi
  // Se revisa que hacer en caso de negativo
  Si aNumero < 0
    // en caso 2,4 se agregan los parentesis en caso de negativo 
    Si aMascarilla = 1 O aMascarilla = 3 
      lNumeroComoCadena = '(' & lNumeroComoCadena &  ')'
    Sino //  se agregan el signo negativo al inicio
      lNumeroComoCadena = '-' & lNumeroComoCadena
    Finsi
  Finsi

  Retorna lNumeroComoCadena
FINFUNC

DefFunc fAjustaCampo(aCampo; aLongitud; aIniCadena; aJust)
	FormPrei.AjustaCampo(aCampo; aLongitud; aIniCadena; aJust)
	Retorna FormPrei.Str_Resultado1
FinFunc

DefFunc fUneCampo(aCadena; aCampo; aPos)
	FormPrei.UneCampo(aCadena; aCampo; aPos)
	Retorna FormPrei.Str_Resultado1
FinFunc

DefFunc fCantidadProtegida(aCantidad; aIdioma)
	FormPrei.CantidadProtegida(aCantidad; aIdioma; gNombreMonedaSing; gNombreMonedaPlu; gDescrProtegida)
	Retorna FormPrei.Str_Resultado1
FinFunc

Deffunc fEsComando(aSimbolo)
	FormPrei.EsComando(aSimbolo)
	Retorna FormPrei.Int_Resultado1
FinFunc

DefFunc fMascarilla(aCodigoSinMascarilla;aMascarilla)
	FormPrei.Mascarilla(aCodigoSinMascarilla; aMascarilla)
	Retorna FormPrei.Str_Resultado1
FinFunc

DefFunc fCabenLetrasEnCampo(aTamCharMin;aTamCharMay;aTexto;aLongitudCampo)
	FormPrei.CabenLetrasEnCampo(aTamCharMin; aTamCharMay; aTexto; aLongitudCampo)
	Retorna FormPrei.Int_Resultado1
FinFunc

DefFunc fCabenLetrasEnCFD(aTamCharMin;aTamCharMay;aTexto;aPxXCm)
	FormPrei.CabenLetrasEnCFD(aTamCharMin; aTamCharMay; aTexto; (gAnchoHoja-2.60)*aPxXCm )
	Retorna FormPrei.Int_Resultado1
FinFunc

DefFunc fFormateaEmail1(aEmail)
	FormPrei.FormateaEmail(aEmail)
	Retorna FormPrei.Str_Resultado1
FinFunc
DefFunc fFormateaEmail2(aEmail)
	FormPrei.FormateaEmail(aEmail)
	Retorna FormPrei.Str_Resultado1
FinFunc
DefFunc fFormateaEmail3(aEmail)
	FormPrei.FormateaEmail(aEmail)
	Retorna FormPrei.Str_Resultado1
FinFunc
DefFunc fFormateaEmail4(aEmail)
	FormPrei.FormateaEmail(aEmail)
	Retorna FormPrei.Str_Resultado1
FinFunc
DefFunc fFormateaEmail5(aEmail)
	FormPrei.FormateaEmail(aEmail)
	Retorna FormPrei.Str_Resultado1
FinFunc
DefFunc fFormateaEmail6(aEmail)
	FormPrei.FormateaEmail(aEmail)
	Retorna FormPrei.Str_Resultado1
FinFunc

// ############################################################################################
// Variables Globales para la función de fContieneUnEnter

gIniCadenaMemo = 0      // Este renglón es para mantener el valor de inicio para imprimir un 
                        // substring de un campo memo.  
gLongitudMemo = 0       // Este renglón es para mantener el valor de la longutud para imprimir
                        // un substring de un campo memo.                                         
gEnter = 0              // Sirve coma bandera si se detecta un enter en un substring de un campo
                        // memo.
// ############################################################################################
// ============================================================================================
// fContieneUnEnter()
// Descripcion :
// revisa si tiene un enter la cadena solicitada
//
//   1.- aNuevoCampo:Es el campo que se agregará
//   2.- aPosicion:  Posicion en la que se debe colocar el campo(expresada en num. de caracteres)
//   3.- aLong :Es la longituda que debe tener el campo, expresada en caracteres, se debe completar
//              con espacios en caso de ser necesario.
// Salida : El valor que regresa es verdadero o falso si encuentra un enter
//      **LEPC **
// ============================================================================================
DefFunc fContieneUnEnter(aNuevoCampo;aIniCadena;aLongitud)
  local lCont,lRes

  lRes = False
  gEnter = 0 
  gIniCadenaMemo = aIniCadena
  gLongitudMemo = aLongitud

  lCont =aIniCadena-1[c0]
  Mientras  (@col(lCont;0) < @len(aNuevoCampo))
    Si @substr(aNuevoCampo;@col(lCont;0);1) = @chr(10) o  @substr(aNuevoCampo;@col(lCont;0);1) = @chr(13) 
      gIniCadenaMemo = aIniCadena
      gLongitudMemo = @col(lCont;0)-(aIniCadena-1)
      gEnter = 2 
      lRes = True
     
      finCiclo
    Finsi
    lCont =  @col(lCont;0) + 1[c0]
  FinMientras 
  Si gLongitudMemo > aLongitud
    gLongitudMemo = aLongitud
    gEnter = 0 
  Finsi 

  Retorna lRes
FinFunc
// ============================================================================================
// fAgregaCampoAlRenglon()
// Descripcion :
//      1.- Esta función agrega el campo que recibe (aNuevoCampo),a la variable 
//         (aMiRenglon) que recibe como parametro. 
//      2.- El campo queda colocado en la cadena apartir del caracter indicado por la posición 
//         que recibe (aPosicion).
//      3.- Si la cadena es menor a la posición que recibe, entonces se debe crecer hasta lograr 
//         la longitud (posicion-1) y de esa manera poder concatenar el campo.
//      4.-El campo se edita y se justifica antes de ser concatenado.
//
// Entradas: aMiRenglon :Es la variable renglon a la que se le pega el nuevo campo.
//   1.- aMiRenglon: Es la variable renglon a la que se le pega el nuevo campo.
//   2.- aNuevoCampo:Es el campo que se agregará
//   3.- aPosicion:  Posicion en la que se debe colocar el campo(expresada en num. de caracteres)
//   4.- aLong :Es la longituda que debe tener el campo, expresada en caracteres, se debe completar
//              con espacios en caso de ser necesario.
//   5.- aIniCadena : Es la posición de inicio apartir de la cual se deben recuperar aLong caracteres
//            en el caso de que el campo sea más corto, se deben ajustar con espacios.
//   6.- aMascarilla:Es el numero de la mascarilla que debe aplicar
//   7.- aTipoCampo:Indica si es cantidad, importe, fecha, u otro
//   8.- aDecimales: Indica cuantos decimales se deben aplicar, en el caso en que sea igual a -1, se 
//            se debe tomar el número de decimales que corresponda según el sistema. 
//   9.- aJustificado: Como se distribuye el campo dentro de su longitud.
// Salida : El valor que regresa es un renglon el cual es formado por aMiRenglon + aNuevoCampo,
//          pero la cadena contenida en el renglon de regreso ya mide en caracteres igual   
//          aPosicion + aLong, considerando que si hubo necesidad fue ajustada con espacios en 
//          blanco, hasta lograr la longitud aPosicion-1 
//      **FBCS **

// DEBE CONSIDERARSE QUE LOS CAMPOS PUEDEN VENIR EN DESORDEN, LO QUE IMPLICA QUE SE INSERTEN 
// AL INICIO Y LUEGO AL FINAL, LUEGO EN MEDIO ETC.
// ============================================================================================
Deffunc fAgregaCampoAlRenglon(aMiRenglon;aNuevoCampo;aPosicion;aLongitud;aIniCadena;aMascarilla;aTipoCampo;aDecimales;aJustificado)
Local lRenglonRegreso,lCampoEditado, lEditable, lIniCadena, LLongitud

  lEditable = 0

  // todos los campos de algun tipo de entero o real, son tratados como campos Numéricos
  Si aTipoCampo = 'N' O aTipoCampo = '$' O aTipoCampo = 'S' O aTipoCampo = 'I' O aTipoCampo = '+' O aTipoCampo = 'Y'
    aTipoCampo = 'N' 
    lEditable = 1    
  Finsi
  // los campos Alfanumérico, Memo o Etiquetas son tratados como Alfanuméricos
  Si aTipoCampo = 'A' O aTipoCampo = 'M' O aTipoCampo = 'E'

    //lepc
    //se pregunta por los campos memo hasta ahora solo esta el campo obsevaciones 
    Si aTipoCampo = 'M'
      //se posiciona en el enter mas cercano
     
      //si esta posicionado en el primer renglón del campo memo se inicilalizan la longitud y el inicio cadena del campo memo
      //nota : no se puede imprimir dos campos memo en los mismos renglones debido a estas variables globales.
      Si aIniCadena = 1
        gLongitudMemo = 0
        gIniCadenaMemo = 0
      Sino
        aIniCadena = gLongitudMemo + gIniCadenaMemo +gEnter
      Finsi
      Si fContieneUnEnter(aNuevoCampo;aIniCadena;aLongitud)
        //se actualiza
        aIniCadena = gIniCadenaMemo 
        aLongitud = gLongitudMemo
      sino

      finsi

    finsi
    aTipoCampo = 'A'
    lEditable = 1
  Finsi
  // Un campo tipo DAte o tipo TimeStamp son tratados como tipo fecha
  Si aTipoCampo = 'D' O aTipoCampo = '@'
    aTipoCampo = 'F'
    lEditable = 1    
  Finsi

  // si se trata de un campo no editable se pone un espacio para que se ajuste con blancos y no se
  // se pierda la estructura del renglón de impresión.
  Si lEditable = 0
    lCampoEditado = ' ' // 
  Sino
    //Aplica la mascarilla apropiada y le agrega los decimales en el caso que aplique.
    Escoge aTipoCampo
      Caso  'N' // se trata de un importe Numérico,se convierte a cadena y se agregan los decimales
        lCampoEditado = fFormateaNumero(aNuevoCampo;aMascarilla;aDecimales)      
      FinCaso
      Caso  'A' // se trata de una cadena Alfanumérica, en este caso nada se formatea
        lCampoEditado = aNuevoCampo
      FinCaso
      Caso  'F' // se trata de una fecha 
        lCampoEditado = fFormateaFecha(aNuevoCampo;aMascarilla)     
      FinCaso
    FinEscoge
  Finsi

  SI gImpresionGrafica = 0
     //Ajusta el campo y lo justifica 
     lCampoEditado = fAjustaCampo(lCampoEditado;aLongitud;aIniCadena;aJustificado)

     //Une el campo a la cadena donde se esta armando el renglon
     lRenglonRegreso = fUneCampo(aMiRenglon;lCampoEditado;aPosicion)
  SINO
     lRenglonRegreso = lCampoEditado
  FINSI

  Si !gMGRenglonNoVacio
    Si @Len(@Trim(3;lRenglonRegreso)) > 0
      gMGRenglonNoVacio = TRUE
    FinSi
  FinSi

  Retorna lRenglonRegreso
Finfunc

// ############################################################################################
// Variables Globales para la función de fImprimeRenglon y control del salto y número de hoja
gRenglonAImprimir = 1   // Este renglón siempre tiene el numero de renglón donde se imprimirá el
                        // siguiente renglón.(Solo se modifica desde la función fImprimeRenglon)
gNumeroDeHoja = 1       // Esta variable siempre debe tener el numero de hoja que se está 
                        // imprimiendo. (Solo se modifica en fCambiaPagina,fControlPostDetalle)
gNumeroDeEncabezados = 0// Esta variable siempre tiene el número de encabezados que han sido 
                        // impresos (Solo se modifica en fImprimeEncabezado)
// ############################################################################################

// ============================================================================================
// fImprimeRenglon
//  Esta función Imprime la cadena (aCadenaRenglon) que recibe, en el renglon  (aEnElRenglon),
//  Si es necesario realiza los ajustes (imprime renglones en blanco) para que el renglon se 
//  imprima en donde debe ser. -FBCS-
//
//  aEnElRenglon : Es el numero de renglon donde se imprimira la cadena que recibe
//  aCadenaRenglon : es la cadena de caracteres que se imprimirán (Se pasa por referencia)       
// ============================================================================================ 
Deffunc fImprimeRenglon(aEnElRenglon; aCadenaRenglon;aSeccion)
  LOCAL lTamCadena, lIndCar, lBandImp

  // se imprimirá sobre el renglon mayor entre aEnElRenglon y el gRenglonAImprimir
  Si gRenglonAImprimir > aEnElRenglon
    aEnElRenglon = gRenglonAImprimir
  Sino
    // Se ajusta para que el siguiente renglon a imprimir sea el aEnElRenglon
    Mientras gRenglonAImprimir < aEnElRenglon
      Si gImpresionGrafica = 0
         Texto ' '
         Imprime
      SiNo
         SALTALIN
      FinSi
      gRenglonAImprimir = gRenglonAImprimir +1
    FinMientras
  Finsi  

  // Hasta este punto, El renglon global (gRenglonAImprimir) y el parametro (aEnElRenglon) estan 
  // iguales y ya se imprimieron gRenglonAImprimir -1 renglones 

  // Imprime el renglon, se utiliza la instrucción texto porque con la instrucción - Imprime aCadenaRenglon-
  // se desconfigura el tipo de letra si el campo a imprimir es vacio o solo tiene espacios en blanco
  // Evita imprimir una cadena vacia, para que no se desfase la impresión en impresoras de matriz
  Si @Len(aCadenaRenglon) <= 0
    aCadenaRenglon = ' '
		SI gTieneDetalle = 1			
			SI gSiInserto = 0
				gRenglonAImprimir = gRenglonAImprimir-1			
				gLineasDetSDet = gLineasDetSDet-1
			fINSI
//lista 'Entra'
		FINSI
  Finsi

  // Bandera que decide la impresión del renglon
  lBandImp = True

  // Verifica si la cadena del renglon a imprimir esta en blanco para no imprimir
  // en el caso de que gNoImpRenBlanco = 1
  Si gNoImpRenBlanco Y gDetalleDinamico Y gImpresionGrafica = 0
     lBandImp = False
     lTamCadena = @LEN(aCadenaRenglon)
     Mientras[ lIndCar = 0; lIndCar < lTamCadena; lIndCar = lIndCar + 1 ]
       Si @SUBSTR(aCadenaRenglon;lIndCar;1) != ' '
          lBandImp = True
          FinCiclo
       FinSi
     FinMientras 
  FinSi

  Si gNoImpRenBlanco Y gDetalleDinamico Y !gMGRenglonNoVacio
    lBandImp = False
  FinSi

  // Se imprime renglón
  Si lBandImp
     SI gImpresionGrafica = 0
        Texto aCadenaRenglon
     FINSI
     Imprime
  FinSi

  gMGRenglonNoVacio = False

  // actualiza el renglon actual	
  gRenglonAImprimir = gRenglonAImprimir + 1  // Se queda en el sig. renglón a imprimir.

  aCadenaRenglon = ''  // se inicializa, para el siguiente,por eso es recibido por referencia

  gNoImpRenBlanco = False // se inicializa
FinFunc

// ============================================================================================ 
// fAlcanzaFinalHoja()
//  logra el final de la hoja antes de cambiar de hoja. -FBCS-
// ============================================================================================ 
Deffunc fAlcanzaFinalHoja(aRenglonesHoja)
  Mientras  gRenglonAImprimir <= aRenglonesHoja Y gDetalleDinamico != 1
    Texto '    '
    Imprime
    gRenglonAImprimir = gRenglonAImprimir +1
  FinMientras
FinFunc


// ============================================================================================
// fFechaHoy-FBCS-
// ============================================================================================
Deffunc fFechaHoy()
  Local  lRegresa

  lRegresa = fFormateaFecha(@Hoy();3)

  Retorna lRegresa
FinFunc

// ============================================================================================
// fHoraActual
// ============================================================================================
Deffunc fHoraActual()
  local lRegresa

  lRegresa = @SubStr(@Hora();0;8)

  Retorna lRegresa
FinFunc

// ============================================================================================
// fFechaHora -FBCS-
// ============================================================================================
Deffunc fFechaHora()
  Local lRegresa

  lRegresa = fFormateaFecha(@Hoy();3)
  lRegresa = lRegresa & ' ' &@SubStr(@Hora();0;8)

  Retorna lRegresa
FinFunc

// ============================================================================================
// fPromedio
//    Regresa el valor promedio entre las dos variables que recibe-FBCS-
// ============================================================================================
Deffunc fPromedio(aVar1;aVar2)
  Local lRegresa  

  lRegresa = (aVar1 + aVar2) / 2

  Retorna lRegresa
FinFunc

// ============================================================================================
// fNumeroPagina
//      Regresa el número de página que se está imprimiendo-FBCS-
// ============================================================================================
Deffunc fNumeroPagina()
  Local lRegresa

  lRegresa = gNumeroDeHoja

  Retorna lRegresa
FinFunc




//=============================================================================================
// fExtraeTextoAlRenglon 
// Descripción: Regresa el substring según el número de caracteres que caben en el renglon
//              ó dependiendo si es fin de texto o si tiene algún enter
// Entrada:   aTexto (La cadena completa que va a cortar); aCaracteres (El número de caracteres
//            Que caben en el renglon)
// Regresa:   Una nueva cadena   
//=============================================================================================
DEFFUNC fExtraeTextoAlRenglon(aTexto; aCaracteres)
  LOCAL lI, lTieneEnters, lRetorno, lJ, lIni

  lI=0
  lTieneEnters = 0

//Valida si tiene Enters
  lJ = 0
  lIni = 0
  MIENTRAS lJ < aCaracteres        
    SI @ASC(@SUBSTR(@str(@TRIM(3;aTexto);0);lI;1)) = 13
      SI lJ = 0        
        lJ=lJ-1
        lIni=lIni+1        
      SINO
        lTieneEnters=1      
        FINCICLO
      FINSI
    FINSI
    //SI @ASC(@SUBSTR(@str(@TRIM(3;aTexto);0);lI;1)) = 255
    //  SI lJ = 0
    //    lJ=lJ-1
    //    lIni=lIni+1 
    //  FINSI
    //FINSI    
    SI @ASC(@SUBSTR(@str(@TRIM(3;aTexto);0);lI;1)) = 10
      SI lJ = 0
        lJ=lJ-1
        lIni=lIni+1 
      FINSI
    FINSI    
    lJ=lJ+1
    lI=lI+1
  FINMIENTRAS

  gCharFaltan = lI-lJ

  SI lTieneEnters = 1
    lRetorno = @substr(@str(aTexto;0);@INT(lIni);lJ)
  SINO
    lRetorno = @substr(@str(aTexto;0);@INT(lIni);aCaracteres)
  FINSI

  RETORNA lRetorno
FINFUNC

//=============================================================================================
//=============================================================================================

DEFFUNC fLlenaDetalleVacio(aNoRenLlenos)
  LOCAL lRenglon, lNumRenglon, lRenglonesDetalle

	lRenglonesDetalle = (gRenglonesEncabezado + gRenglonesDetalle) - gRenglonAImprimir

	lRenglon = ''
	MIENTRAS  lRenglonesDetalle > 0
	  COLUMNAS 1;gAnchoHoja,0
	  lNumRenglon = gRenglonAImprimir
		SI gTipoImpresoraTE = 2
	  	TEXTO C0;'@F{' & @STR(gMaxFontDet;0) & '}@S{' & @STR(gMaxSizeDet;0) & '}@TC{251,251,251}´' 
		SINO
			TEXTO C0;'@F{' & @STR(gMaxFontDet;0) & '}@S{' & @STR(gMaxSizeDet;0) & '}@TC{251,251,251} ' 
		FINSI
		//TEXTO C0;'@F{' & @STR(gMaxFontDet;0) & '}@S{' & @STR(gMaxSizeDet;0) & '}@TC{0,0,0}'
	  fImprimeRenglon(&lNumRenglon;&lRenglon;'P')
		lRenglonesDetalle = lRenglonesDetalle-1
	FINMIENTRAS
  
FiNFUNC


// FIN FUNCIONES

