//  CAFE2011.EXE is licensed under the terms of the CC-LGPL.
//  (CC-LGPL Version 3, 29 junio 2007 y CAFE2011 version 2011)
//  El objetivo es el libre uso comercial y no comercial del software.
//  Una copia de dicho documento se incluye en esta distribucion.
//  CWSDPMI.EXE, STREAMCO.PAS, el procedimiento TextOut
//  se tomaron de la distribucion FreePascal 2.4.2. con patente similar.
//        StreamCo.PAS es una contraccion conveniente a ocho letras del
//        nombre StreamColl.PAS en la distribucion FreePascal
  {$MODE                OBJFPC          }
  {$INCLUDEPATH         ..\INCLUDE      }
  {$INCLUDE             CAFE_INC.INC    }
  {$DEFINE              SILENCIAR       }
  {$INTERFACES          CORBA           }
{
  ADVERTENCIA   :
        Esta unidad NO FUNTIONA...
        Existe como estructura a futuro para permitir
        la comunicacion con programas externos
        El problema actual (Noviembre 2011)
        es algunas dificultades en la ejecucion
        de las unidades
        Timer, Process y Pipes
        que confiamos se arreglaran proximamente, o
        bien se sustituiran con alguna herramienta adecuada
}

UNIT CAFE_Tu1;

INTERFACE

USES
  SysUtils, Types   , Classes , CustApp , IOStream,
  StreamCo,
{
  StreamCo is almost identical to StreamColl
  of FPC distribution, problem: name file very large...
  for Command.com of Windows98.  Sorry...
}

  StreamIO, DateUtils         , Variants, Math    , CAFE_Ej1, CAFE_Ej3;

TYPE
  TFPTimerMultiSistema          = TDateTime;
{
  TFPTimerMultiSistema          :
        La idea es sustituirlo por TFPTimer en el futuro,
        en la version actual no reconoce fpTimer 2.4.2. modo GO32v2
}

CONST
  CAFE_PrecisionNumeroRenglon   : Byte  = 6;
{
  CAFE_PrecisionNumeroRenglon   : Indica la precision a escribir
        los numeros de pipa, si la precision tiende a agotarse
        Se supone que deberia generarse un WaitOnCompleted
        o bien un Reset y existe riezgo de inconsistencia
        de numeracion.
        CUIDADO: El codigo deberia ser independiente de este valor
}

  CAFE_MaximoNumeroRenglon      : LongInt       = 900000;
{
  CAFE_MaximoNumeroRenglon      :
        A partir de aqui se retorna la numeracion a uno.
        Numeros posteriores se reservan para procesos en paralelo.
}

  CAFE_PrecisionRepeticionRenglon       : Byte  = 6;
{
  CAFE_PrecisionRepeticionRenglon       : Indica la precision a escribir
        los numeros de repeticion de renglon,
        Podria funciona un numero bajo, pero en operaciones
        como load, multimedia o de calculos complejos podria
        crecer el numero en forma dificil de predecir.
        De agotarse la numeracion probablemente vuelva a cero,
        y mande una se¤al inofensiva de Alerta
        CUIDADO: El codigo deberia ser independiente de este valor
}

  CAFE_MinimaPrecisionNumeroPipe                = 2;
{
  CAFE_MinimaPrecisionNumeroPipe        : Minimo valor admisible
        de precision de numero de renglon o similar
}

  CAFE_NameValueSeparator       = '=';
{
  CAFE_NameValueSeparator       : Char utilizado por CAFE_TStringList
        para separar Nombres de valures en listas de String,
        simplemente utilizo el mismo que fpc.exe
}

CONST
  CAFE_GUIDInterfaceBasico      =  '{01000000-0000-0000-DEFA-BACA000000A0}';
{
  CAFE_GUIDInterfaceBasico      : GUID como ShortString
                        para CAFE_InterfaceBasico
}

  CAFE_GUIDInterfacePipe        =  '{02000000-0000-0000-DEFA-BACA000000A0}';
{
  CAFE_GUIDInterfacePipe        : GUID como ShortString
                        para CAFE_InterfacePipe
}

  CAFE_GUIDInterfaceTraductora  =  '{03000000-0000-0000-DEFA-BACA000000A0}';
{
  CAFE_GUIDInterfacePipe        : GUID como ShortString
                        para CAFE_InterfacePipe
}

TYPE
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
  {$INTERFACES  CORBA           }
  CAFE_InterfaceBasico          = INTERFACE  [CAFE_GUIDInterfaceBasico]
{
  CAFE_InterfaceBasico          : Interface primitiva que sirva
        para el pase general de parametro Interface en Ejes.EXE
        La idea es que algun descendiente, sea lo que reciba
        el programador que utilice el grupo CAFE_EJX, como
        clave Manejador.  Y el programador utilice PROCEDURE y FUNCTION
        corriente con Manejador tipo Interface de parametro.
        NOTA : Se declara experimental pues se cree que cambiara
        la logica en el futuro, hasta es probable
        que no sea interface.
}

FUNCTION  Leer_Actual           : TStreamCollectionItem;
{
  FUNCTION Leer_Actual
        Property Actual requiere el READ declarado
        para el buen funcionamiento y debe ser metodo.
  FUNCTION Leer_Actual          : devuelve el Self de la Clase implementada
}

PROCEDURE   SetDisplayNameI
  (       MyName                : String                                );
{
  PROCEDURE SetDisplayNameI
        Property DisplayNombre requiere el WRITE declarado
        para el buen funcionamiento y debe ser metodo.
}

FUNCTION    GetDisplayNameI                                     : String;
{
  FUNCTION GetDisplayNameI
        Property DisplayNombre requiere el READ declarado
        para el buen funcionamiento y debe ser metodo
}

  Property
    DisplayNombre               :  String
                                   READ  GetDisplayNameI
                                   WRITE SetDisplayNameI;
{
  DisplayNombre                 : Sustituye a
        TStreanCollectionItem.DisplayName en EJES.EXE, se le cambio
        el nombre para evitar interferencia en algoritmos previos
        de FreePascal.
        Aqui seria el nombre de usuario de la Hoja de Calculo
        o similar
}

  Property
    Actual                      : TStreamCollectionItem READ Leer_Actual;
{
  Actual                        : Sirve como Self de la clase que
        implemente la Interface.  Probablemente requiera AS.
}

  END experimental;  { INTERFACE CAFE_InterfaceBasico }
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }

  CAFE_Manejador0               = CLASS
                                  ( TStreamCollectionItem,
                                    CAFE_InterfaceBasico )
{
  CAFE_Manejador0               : Clase fundamental inutil para los
        manejadores, se crea aqui para darle sentido
        a CAFE_InterfaceBasico.Actual
}

  Strict Private
    DisplayNameI                : ShortString;

  Public
CONSTRUCTOR Create
  (       ACollection           : TCollection                   ); override;
{
  Herencias de TStreamCollectionItem nunca deberian crearse en forma
  independiente (ver Manual Classes)
}

  Public
DESTRUCTOR  Destroy; override;
{
  Unica forma para remover Items desde una TStreamCollection, deje que
  ella se encargue
}

  Protected
PROCEDURE   SetDisplayNameI
  (       MyName                : String                                );
{
  PROCEDURE SetDisplayNameI
        Se guarda un nombre de manejador asociado con la propiedad
        DisplayNombre
  MyName                        : Nombre a asociar
}

  Private
FUNCTION    GetDisplayNameI                                     : String;

  Private
FUNCTION    Leer_Actual         : TStreamCollectionItem;

  Public
  Property
    Actual                      : TStreamCollectionItem READ Leer_Actual;
{
  Actual                        : Sirve como Self de la clase que
        implemente la Interface.  Probablemente requiera AS.
}

  Public
  Property
    DisplayNombre               :  String
                                   READ  GetDisplayNameI
                                   WRITE SetDisplayNameI;
{
  DisplayNombre                 : Sustituye a
        TStreamCollectionItem.DisplayName en EJES.EXE, se le cambio
        el nombre para evitar interferencia en algoritmos previos
        de FreePascal
        Aqui seria el nombre de usuario de la Hoja de Calculo
        o similar
}

                                  END;  { CLASS CAFE_Manejador0 }

TYPE
  CAFE_EstiloCadenaInicial      =
        ( NoReconocidoRECI      , NumeralRECI                   ,
          CasillaRECI           , InexistenteRECI               );
{
  CAFE_EstiloCadenaInicial      :
        Tipo enumerado para distinguir univocamente el estilo
        de CadenaInicial en mensajes de pipa
        $$$$$$ERROR!!!!!!=CadenaInicial 'Msg1' 'Msg2' 'TYPE'
  NoReconocidoRECI              : Se refiere a un formato no reconocido
  NumeralRECI                   : Se trata de un formato de tipo
        $$$$$$ERROR!!!!!!=#0%%%%%% 'Msg1' 'Msg2' 'TYPE'
        CadenaInicial seria #0%%%%%%
        Indica un numero en alguna lista compartida de Strings
  CasillaRECI                   : Se trata de una referencia de casilla
        $$$$$$ERROR!!!!!!=#C(F,C,TV,NI) 'Msg1' 'Msg2' 'TYPE'
        CadenaInicial seria #C(F,C,TV,NI)
        para describir casillas en arreglos bidimensionales
  InexistenteRECI               : Se trata de una referencia de casilla vacia
        $$$$$$ERROR!!!!!!='Msg1' 'Msg2' 'TYPE'
        que podria no tener ningun mensaje tambien
}

TYPE
  CAFE_RespuestaEstiloPipe      =
        ( BeginREPO             , EndREPO                       ,
          ResultREPO            , AccionREPO                    ,
          EchoREPO              , RemREPO                       ,
          DatoREPO              , ExitoREPO                     ,
          EsperoREPO            , ParcialREPO                   ,
          SuspendidoREPO        , BeginLoadREPO                 ,
          EndLoadREPO           , AceptadoLoadREPO              ,
          BeginSaveREPO         , EndSaveREPO                   ,
          BeginTXTREPO          , EndTXTREPO                    ,
          PerfectoTXTREPO       , BeginMultimediaREPO           ,
          DatoMultimediaREPO    , PeticionMultimediaREPO        ,
          EndMultimediaREPO     , NombreREPO                    ,
          NumeroIDREPO          , ArchivoREPO                   ,
          SystemREPO            , StreamREPO                    ,
          PeticionREPO          , NoteREPO                      ,
          DerechoREPO           , TipREPO                       ,
          PublicidadREPO        , WaitREPO                      ,
          LibreWaitREPO         , BeginStdErrREPO               ,
          EndStdErrREPO         , FracasoREPO                   ,
          HaltREPO              , ErrorREPO                     ,
          MensajeTXTREPO        , ErrorTXTREPO                  ,
          DescartadoTXTREPO     , MensajeLoadREPO               ,
          ErrorLoadREPO         , DescartadoLoadREPO            ,
          ErrorMultimediaREPO   , MensajeMultimediaREPO         ,
          SuspendidoMultimediaREPO                              ,
          CanceladoMultimediaREPO                               ,
          MensajeREPO           , AlertaREPO                    ,
          CanceladoREPO         , LlaveREPO                     ,
          FatalREPO             , FinUsuarioREPO                ,
          ReinicioREPO          , HintREPO                      ,
          VaganciaREPO          , RetrasoREPO                   ,
          SaturadoREPO          , IncompletoREPO                ,
          FreeDOSREPO           , DOSREPO                       ,
          WindowsREPO           , LinuxREPO                     ,
          NullREPO              );
{
  REGLAMENTO GENERAL DE MENSAJES DE ERROR EN Pipes metodo directo
      $$$$$$ERROR!!!!!!=#?CADENAINICIAL 'Msg1' 'Msg2' 'TYPE'
      $$$$$$    : Numero de renglon como 000025
      !!!!!!    : Numero de tipo de mensaje por renglon como 000002
      #         : Obligatorio para este tipo de clave
      ?         : Char que permite variaciones en CadenaInicial
      CadenaInicial     : no tiene comillas, identifica
                  el error de forma diversa segun ?
      'Msg1'    : Mensaje de error entrecomillado principal en idioma nativo
                  del programador o de algun otro pais,
                  Probablemente pueda traducirse
                  con las claves en CadenaInicial
      'Msg2'    : Identifica Msg1 como una categoria y lo ubica
                  no es obligarorio
                  Se recomienda usar 'NULL' entrecomillado para mensaje vacio.
                  Para indicar que existe mas cadenas.
                  i.e Msg2 : 'ErrorSintactico(C:A23)'
                      Msg1 : 'Operador COSIN() no reconocido'
                      Type : '..\TEMPORAL\COSIN.HTML'
      'TYPE'    : Permite agregar un archivo, pero el tipo
                  Deberia ser correcto para facilitar las cosas
                  Se supone que puede sustituir completamente
                  Msg1 y Msg2. No es obligatorio.
                  Se recomienda usar 'NULL' entrecomillado para mensaje vacio.
      ALTERNATIVAS para ?
      0         : Mensajes de error simple
        CADENAINICIAL   : Es un numero entero corriente
                  que permite encontrar el error en alguna lista
                  Probablemente no exista ni 'Msg2' y 'TYPE'
                  La ubicacion se realice probablemente con $$$$$$
      C         : Ubica una casilla en alguna matriz
        CadenaInicial   : (Fila,Columna[[,TipoDeError],IdentificadorError])
        i.e.
        #C(12,0,1,25) 'Operador COSIN() no reconocido'
        En los mensajes de error en listas se utiliza el %S para indicarle
        al usuario alguna sustitucion, ademas deberia
        tener espacios en blancos antes y despues
        Por ejemplo, en la lista de errores podria aparecer
        'Operador %S no reconocido'
        %S      : deberia ser alguna sustitucion sin espacios
                  en blanco, para que pueda ser facilmente traducido
}

{
  Explicacion de las constantes
    BeginREPO                   :
        Su objetivo es marcar el inicio de proceso.
        Mientras no aparezca se supone que CAFE no ha hecho nada
        al respecto
    EndREPO                     :
        Su objetivo es marcar el final de proceso de pipa
        Si aparece es el final de proceso del renglon.
        El usuario queda 'autorizado' a destruir la secuencia
        de Strings correspondientes al renglon.
    ResultREPO                  :
        Su objetivo es devolver resultados, por ejemplo
        un calculo como CALCULAR( A1*SUM( A2:A4 ) )
    AccionREPO                  :
        Para informar que el programa hizo algo, probablemente
        no ordenado.  Pero que podria afectar al usuario.
        i.e. Descomprimir un archivo muy grande sin pedir permiso
        y guardarlo en disco
    NullREPO                    :
        Para informar que un renglon de pipa es vacio o equivalente
    EchoREPO                    :
        Su objetivo es repetir las ordenes recibidas, puede
        activarse o desactivarse
    RemREPO                     :
        Pasar mensajes REM al estilo DOS.
        Probable respuesta a una orden REM de usuario o TXT.
    DatoREPO                    :
        Para enviar datos.  Por ejemplo, un bloque
        de hoja de calculo
    ExitoREPO                   :
        Algunas ordenes de usuario, enviaran un mensaje de EXITO.
        Por ejemplo, para indicar una operacion UNDO exitosa.
    EsperoREPO                  :
        Para solicitar actos o informacion por parte del programa
        de Aplicacion;  que probablemente generen un
        temporal estado pasivo.
    ParcialREPO                 :
        Similar a CAFE_PipeExito, pero para subetapas de un proceso
        mayor.  Por ejemplo, un proceso parcial de interpretacion
        y el proceso total fuera ejecucion.
    SuspendidoREPO              :
        Para indicar que CAFE.EXE se encuentra suspendido.
        FreePascal puede suspender procesos externos sin problemas,
        pero probablemente convenga mandar una llamada
        previa a la pipa que lo permita.
    BeginLoadREPO               :
        Para indicar inicio de un proceso de Load,
        probablemente desde archivo.
        Aunque tambien podria aplicarse para algun tipo de ClipBoard,
        si se define.  Los procesos LOAD generan por ejemplo,
        cuando no se detienen al primer error
        listas de errores.
        La generacion o ausencia de estos errores se
        detecta facilmente con AceptadoLoad
    EndLoadREPO                 :
        Para indicar final de un proceso de Load.  Ya no deberian
        recibirse mas mensajes por el acto load concreto.
    AceptadoLoadREPO            :
        Para indicar un proceso Load sin objeciones detectadas
    SaveREPO                    :
        Para indicar el inicio de un proceso Save.  Probablemente
        alguno particularmente extenso.
    EndSaveREPO                 :
        Para indicar el final de un proceso Save.
        Ya no deberian recibirse mas mensajes
        por este motivo.
    BeginTXTREPO                :
        Para indicar el inicio de un proceso estilo TXT, o sea
        una lectura de archivo TXT de ordenes
    EndTXTREPO                  :
        Para indicar el fin de un proceso estilo TXT, o sea
        una lectura de archivo TXT de ordenes
    PerfectoTXTREPO             :
        Para indicar un proceso Load sin objeciones detectadas
    BeginMultimediaREPO         :
        Para indicar el inicio de un proceso estilo Multimedia, o sea
        archivos grandes que requieren tiempo sincronizado con el usuario
        y aplicaciones similares
    DatoMultimediaREPO          :
        Para indicar una transferencia de dato estilo Multimedia
        compatible con el formato ReadLn WriteLn.
        Tambien podria servir de antecedente para
        una orden WAIT para transferencia de binarios.
    PeticionMultimediaREPO      :
        Para peticiones de parte de CAFE al usuario, relacionados
        con ejecucion tipo Multimedia
    EndMultimediaREPO           :
        Para indicar el final de un proceso estilo Multimedia, o sea
        archivos grandes que requieren tiempo sincronizado con el usuario
        y aplicaciones similares
    NombreREPO                  :
        Para transferencia de datos importantes de algunas ordenes.
        Que convenca identificar con un Nombre o Identificador importante.
        Si se trata de un nombre de archivo, talvez convenga utilizar
    NumeroIDREPO                :
        Para transferencia de numeros "Handle", o claves
        de acceso para ordenes y similar.  Probable sustituto
        de un NOMBRE
    ArchivoREPO                 :
        Para transmitir informacion relevante de archivo,
        como el nombre en disco de algun dato
    SystemREPO                  :
        Para transmitir informacion relevante para el Sistema Operativo
        de una forma que resulte bastante independiente del
        sistema particular.  Se admiten algunas transferencia
        particulares como el estilo de nombre de directorio
    StreamREPO                  :
        Para transmitir informacion relevante de Stream
        Por ejemplo INPUT, OUTPUT y StdErr en Process se
        manejan como TStream
    PeticionREPO                :
        Para transmitir "peticiones" al programa controlador de pipa.
        Como mas informacion o similar.
    NoteREPO                    :
        Pasar mensajes NOTE al estilo FreePascal
        Probable alguna advertencia o curiosidad de importancia
        secundaria
    DerechoREPO                 :
        Asociado con asuntos de autoria y derechos intelectuales.
        Aparte de informacion de derechos de uso como FreeWare o Patente
    TipREPO                     :
        Pasar mensajes TIP, es decir.  Sugerencias para el usuario
        que se supone recibira con agrado, para mejorar en el uso
        del programa
    PublididadREPO              :
        Asociado con asuntos de publicidad.
        Por ejemplo, para sugerir la compra de camisetas FreePascal
    WaitREPO                    :
        Para transferencia de datos binarios, es decir de formato libre,
        utilizando la pipa de StdOut.
    LibreWaitREPO               :
        Para indicar al usuario, que esta listo el dato WAIT, y
        puede proceder a su lectura.  O bien simplemente
        para finalizar el estado WAIT
    BeginStdErrREPO             :
        Para indicar el inicio de una secuencia de mensajes en
        StdErr.  La idea es que si no aparece esta orden,
        no se detectan errores en el renglon de pipa respectivo.
        Sin embargo, no todo reporte es un error verdadero;
        pues HINTS y MENSAJES tambien se envian aqui.
    EndStdErrREPO               :
        Para finalizar una secuencia de errores, la idea es
        que esto autoriza al 'usuario' a olvidarse del asunto
        iniciado con BEGINSTDERR
    FracasoREPO                 :
        Para indicar la interrupcion, fracaso o fallo de
        un proceso.
    HaltREPO                    :
        Informa al usuario que CAFE intentara en breve un HALT, es decir
        intenta llevar el programa a su final.  Si utiliza el sistema
        Process, no se recomienda inducir el estado de Halt.  Y mejor
        utilice los metodos ya programados por FreePascal;  en ese caso
        mejor espere los informes de VAGANCIA y/o SUSPENDIDO.
    ErrorREPO                   :
        Principal metodo para transmitir mensajes de error.
        Para evitar la proliferacion desagradable de mensajes
        de error, se crean otras clasificaciones como
        ERRORLOAD, ERRORTXT, etc.  En muchas situaciones,
        el usuario preferirira obviar el detalle.
    MensajeTXTREPO              :
        Metodo para enviar mensajes al usuario relacionado
        con procesos TXT.  Probablemente mandara
        aqui otras subclasificaciones como TIP, NOTE, HINTS
        pero originarios de procesos TXT
    ErrorTXTREPO                :
        Principal metodo para transmitir mensajes de error
        en procesos TXT.
    DescartadoTXTREPO           :
        Un probable final de ejecucion TXT es el descarte
        al primer error, o por errores acumulados.
        Esto es forzar el final de ejecucion de un proceso en forma exitosa.
    MensajeLoadREPO             :
        Metodo para enviar mensajes al usuario relacionado
        con procesos Load.  Probablemente mandara
        aqui otras subclasificaciones como TIP, NOTE, HINTS
        pero originarios de procesos Load
    ErrorLoadREPO               :
        Principal metodo para transmitir mensajes de error
        en procesos TXT.
    DescartadoLoadREPO          :
        Un probable final de ejecucion LOAD es el descarte
        al primer error, o por errores acumulados.
        Esto es forzar el final de ejecucion de un proceso en forma exitosa.
    ErrorMultimediaREPO         :
        Principal metodo para transmitir mensajes de error
        en procesos Multimedia.
    MensajeMultimediaREPO       :
        Metodo para enviar mensajes al usuario relacionado
        con procesos Load.  Probablemente mandara
        aqui otras subclasificaciones como TIP, NOTE, HINTS
        pero originarios de procesos Load
    SuspendidoMultimediaREPO    :
        Para informar de un estado suspendido en algun
        proceso Multimedia (el boton Pause por ejemplo)
    CanceladoMultimediaREPO     :
        Para informar de la cancelacion por cualquier razon
        de un proceso Multimedia
    MensajeREPO                 :
        Metodo para enviar mensajes al usuario.
        Para mensajes 'entusiastas' probablemente sean mejor
        las alternativas TIP o NOTE que se direccionan a StdOut
    AlertaREPO                  :
        Metodo para enviar mensajes de alerta al usuario.
        Se supone que no son errores necesariamente.
        Si se trata de un error, mejor utilice ERROR.
    CanceladoREPO               :
        Metodo para enviar mensajes de cancelacion de ejecucion al usuario.
    LlaveREPO                   :
        Para solicitar algun tipo de clave, o autorizacion.
        Por ejemplo, algunos tipos de datos, tendran contrasena
        o requieren un String de Registro para la empresa
    FatalREPO                   :
        Para errores muy graves.  Estos induciran algun tipo
        de cancelacion.  Probablemente vendra un final de algun
        tipo de proceso o peor.
    FinUsuarioREPO              :
        Genera un estado de fin de usuario de la Pipe completa
        o de un proceso
    ReinicioREPO                :
        Informa de un estado de REINICIO de pipa.
        Los renglones intentaran terminar abruptamente.
        Y el contador de Pipa reiniciar a 000001
    HintREPO                    :
        Para informar de sugerencias
    VaganciaREPO                :
        Para informar al usuario que CAFE no tiene trabajo util que hacer
    RetrasoREPO                 :
        Para informar de un estado de retraso por diversas causas.
        Previsto para sincronizacion y otros usos.
    SaturadoREPO                :
        Para informar al usuario que los recursos asignados o disponibles
        escasean.  Probablemente sea recomendable disminuir las
        ordenes, o aumentar recursos
    IncompletoREPO              :
        Para informar de un estado incompleto, a definir para
        aplicaciones particulares.
    FreeDOSREPO                 :
        Para instrucciones especificas del FreeDOS.
        i.e. para informar al usuario que no se logro activar
        un emulador de sistema solicitado.
    DOSREPO                     :
        Para instrucciones especificas del DOS.
        i.e. informar al usuario que CAFE.EXE se encuentra en estado TSR
        y no es necesario el PROCESS.  Probablemente en alguna version
        futura
    WindowsREPO                 :
        Para instrucciones especificas del Windows
    LinuxREPO                   :
        Para instrucciones especificas del Linux
}

CONST
  CAFE_PrimerREPO               = Low( CAFE_RespuestaEstiloPipe );
{
  CAFE_PrimerREPO               :
        Para evitar confusion en enumeraciones y busquedas, se define
        este valor extremo del grupo, como version alternativa del Low
}

  CAFE_UltimoREPO               = High( CAFE_RespuestaEstiloPipe );
{
  CAFE_UltimoREPO               :
        Para evitar confusion en enumeraciones y busquedas, se define
        este valor extremo del grupo, como version alternativa del High
}

TYPE
  CAFE_ConjuntoRespuestaEstiloPipe      = SET OF CAFE_RespuestaEstiloPipe;
{
  CAFE_ConjuntoRespuestaEstiloPipe      :
        Para utilizar el tipo CAFE_RespuestaEstiloPipe
        como un tipo conjunto cuando se requiera
}

TYPE
  CAFE_PipeHaltException        = CLASS ( Exception )
{
  CAFE_PipeHaltException                :
        La idea es que esta exception produzca la interrupcion de la pipa, y
        probablemente descargue CAFE.EXE de RAM
}

                                  END;  { CAFE_PipeHaltException }

  CAFE_PipeFatalException       = CLASS ( CAFE_PipeHaltException )
{
  Clase para generar mensajes tipo FatalREPO
  Su objetivo es facilitar el Escape a travez de los niveles EXCEPT,
  de forma que los mensajes Fatal sean interceptados a un nivel
  inferior, y mensajes menos graves a un nivel superior
  Probablemente Fatal implique el final abrupto de un proceso
}

    TypeException       : CAFE_RespuestaEstiloPipe;
{
  TypeException         :
        Este tipo de mensaje probablemente puede asociarse con un grupo.
        Si se va a direccionar a Pipa casi deberia ser obligatorio
}

CONSTRUCTOR Create
  (       MyHelpContext : LongInt                               ); virtual;
{
  Constructor del tipo FatalREPO que utilice MyHelpContext, para elegir
  un mensaje en CAFE_ListaMensajePipe
}

CONSTRUCTOR Create
  (       MyHelpContext : LongInt;
    CONST Args          : array of Const                        ); virtual;
{
  Otro constructor pero con la flexibilidad que permite una sustitucion
  format en el mensaje pasando args sin modificacion a Format
}

DESTRUCTOR  Destroy; override;
{
  Destructor general de la clase
}

                                  END;  { CAFE_PipeFatalException }

  CAFE_PipeException    = CLASS ( CAFE_PipeFatalException )
{
  Clase general de excepciones para el grupo de Pipa.
  Existe otro grupo llamado CAFE_Exception.
  La diferencia es que este se asume direccionado a WriteLn y ReadLn a
  travez de la pipa
  Esto probablemente sea fruto de una mala planeacion,
  y se intente corregir en el futuro.
}

CONSTRUCTOR Create
  (       TypeMsg       : CAFE_RespuestaEstiloPipe;
          MyHelpContext : LongInt                               ); virtual;
{
  Constructor general de la clase
        TypeMsg         : Permite establecer un tipo de mensaje
        MyHelpContext   : Un numero de mensaje en lista CAFE_ListaMensajePipe
}

CONSTRUCTOR Create
  (       TypeMsg       : CAFE_RespuestaEstiloPipe;
          MyHelpContext : LongInt;
    CONST Args          : array of Const                        ); virtual;
{
  Constructor general de la clase, cuando se requiere una sustitucion
  con format de CAFE_ListaMensajePipe
        TypeMsg         : Permite establecer un tipo de mensaje
        MyHelpContext   : Un numero de mensaje en lista
        Args            : Parametros de sustitucion utilizando el format
}


DESTRUCTOR  Destroy; override;
{
  Destructor fundamental de clase
}

                          END;  { CAFE_PipeException }

CONST
  CAFE_NoSintaxisError          = 1;
{
  CAFE_NoSintaxisError          : Numero de identificacion para
        error tipo sintactico.  Util como una subclasificacion
        de errores
}

  CAFE_NoEjecutarError          = 2;
{
  CAFE_NoEjecutarError          : Numero de identificacion para
        error tipo Ejecutar.  Util como una subclasificacion
        de errores
}

  CAFE_NoCopiarError            = 3;
{
  CAFE_NoCopiarError            : Numero de identificacion para
        error tipo Copiar.  Se refiere a un tipo de copia
        no permitida.  Poco probable que ocurra.  Pues
        generalmente se reporatar un error sintactico o de ejecucion
}

TYPE
  CAFE_PipeEstiloCasillaMsg     =
        ( SintaxisErrorPECM     = CAFE_NoSintaxisError          ,
          EjecutarErrorPECM     = CAFE_NoEjecutarError          ,
          CopiarErrorPECM       = CAFE_NoCopiarError            );
{
  CAFE_PipeEstiloCasillaMsg     : Tipo ordinal para subclasificacion
        de mensajes.  Segun categorias generales de origen.
  SintaxisErrorPECM             : Se refiere a un error de escritura
        y sintaxis en una orden.
  EjecutarErrorPECM             : Se refiere a un error al ejecutar
        alguna orden.  Como division entre cero.
}

  CAFE_PipeCasillaException     = CLASS ( CAFE_PipeException )
{
  CAFE_PipeCasillaException     : Exception pivote, para generar
        mensajes de error estilo casilla.
        $$$$$$ERROR!!!!!!=#C(E1,E2[,E3[,E4]) 'Msg1' 'Msg2' 'TYPE'
        E1              : Numero entero positivo de Fila de casilla
        E2              : Numero entero positivo de Columna casilla
        E3              : Numero entero de clasificacion
        i.e. error Sintactico.
        E5              : Numero entero de reconocimiento
        i.e. numero de error en una lista de Strings
}

  Public
    FilaReferencia,
{
  FilaReferencia                : Para identificar una fila
        en arreglo bidimensional
}

    ColumnaReferencia           : LongInt;
{
  ColumnaReferencia             : Para identificar una columna
        en arreglo bidimensional
}

    EstiloMsgReferencia         : CAFE_PipeEstiloCasillaMsg;
{
  EstiloMsgReferencia           : Para una subclasificacion
        de mensajes
}

    BanderaPermitirLoad         : Boolean;
{
  BanderaPermitirLoad           : En procesos Load se permiten
        muchos errores, para correccion posterior por el usuario,
        esta bandera en estado TRUE le indica a la pipa que
        ignore el error.
        Advertencia: El proceso Load secuencial genera errores
        que no son tales, y se corrigen luego, cuando la
        hoja se carga completamente;  es conveniente no
        enviar falsas alarmas al usuario.
        Por ello, conviene aplicar en muchos errores Load
        el estado TRUE para revision posterior.
}

CONSTRUCTOR Create
  (       Fila,
          Columna       : LongInt;
          EstiloMsg     : CAFE_PipeEstiloCasillaMsg;
          MyHelpContext : LongInt;
          BanderaLoad   : Boolean       = FALSE                 ); virtual;
{
  CONSTRUCTOR Create
        Constructor fundamental de la exception
  Fila                  : Hace referencia a una fila en arreglo
        bidimensional
  Columna               : Hace referencia a una columna en arreglo
        bidimensional
  EstiloMsg             : Para una subclasificacion de mensajes
  MyHelpContext         : Para enumerar, el resultado en una lista
  BanderaLoad           : Valor a colocar en BanderaPermitirLoad
}

CONSTRUCTOR Create
  (       Fila,
          Columna       : LongInt;
          EstiloMsg     : CAFE_PipeEstiloCasillaMsg;
          MyHelpContext : LongInt;
    CONST Args          : array of Const;
          BanderaLoad   : Boolean       = FALSE                 ); virtual;
{
  CONSTRUCTOR Create
        Constructor fundamental de la exception
  Fila                  : Hace referencia a una fila en arreglo
        bidimensional
  Columna               : Hace referencia a una columna en arreglo
        bidimensional
  EstiloMsg             : Para una subclasificacion de mensajes
  MyHelpContext         : Para enumerar, el resultado en una lista
  Args                  : Para sustitucion en el mensaje a generar
        segun Format
  BanderaLoad           : Valor a colocar en BanderaPermitirLoad
}

                                  END;  { CLASS CAFE_PipeCasillaException }

CONST
  CAFE_PipeBegin                = 'BEGIN'         unimplemented;
{
  CAFE_PipeBegin                : StdOut
        Su objetivo es marcar el inicio de proceso.
        Mientras no aparezca se supone que CAFE no ha hecho nada
        al respecto
  000000BEGIN                   : Inicio de lista,
        se puede aplicar un 'RESET' mediante algun comando,
        pero eso destruye el TListString completo.
        Si no se encuentra, se supone que la lista de respuestas
        no existe
  ??????BEGIN                   : Inicio de procesamiento de renglon
        en una secuencia de INPUT de pipa.
        Los renglones se miden segun ReadLn y WriteLn corrientes.
        El primer renglon es 000001
}

  CAFE_PipeEnd                  = 'END'           unimplemented;
{
  CAFE_PipeEnd                  : StdOut
        Su objetivo es marcar el final de proceso de pipa
        Si aparece es el final de proceso del renglon.
        El usuario queda 'autorizado' a destruir la secuencia
        de Strings correspondientes al renglon.
  000000END                     : Fin de proceso de pipa,
        probablemente este aplicando algo similar a un
        RESET o HALT.  Algunos archivos probablemente soliciten
        un RESET, aunque no se recomienda.
        El usuario deberia deshacerse de su lista actual,
        y comenzar una nueva.
  ??????END                     : Fin de proceso de renglon.
        El usuario queda 'autorizado' a destruir las
        lecturas del renglon respectivo.
}

  CAFE_PipeResult               = 'RESULT'        unimplemented;
{
  CAFE_PipeResult               : StdOut
        Su objetivo es devolver resultados, por ejemplo
        un calculo como CALCULAR( A1*SUM( A2:A4 ) )
  000000RESULT                  : No definido por ahora
  ??????RESULT                  : Resultado (principal probablemente)
        del renglon respectivo de pipa
}

  CAFE_PipeAccion               = 'ACCION'        unimplemented;
{
  CAFE_PipeAccion               : StdOut
        Para informar que el programa hizo algo, probablemente
        no ordenado.  Pero que podria afectar al usuario.
        i.e. Descomprimir un archivo muy grande sin pedir permiso
        y guardarlo en disco
  000000Accion                  : Para indicar acciones
  ??????Accion                  : No definido
}

  CAFE_PipeNull                 = 'NULL'          unimplemented;
{
  CAFE_PipeNull                 : StdOut
        Para informar que un renglon de pipa es vacio o equivalente
  000000NULL                    : no definido
  ??????NULL                    : Para informar que un renglon de pipa
        es vacio
}

  CAFE_PipeEcho                 = 'ECHO'          unimplemented;
{
  CAFE_PipeEcho                 : StdOut
        Su objetivo es repetir las ordenes recibidas, puede
        activarse o desactivarse
  000000ECHO                    : No definido por ahora
  ??????ECHO                    : Repite el renglon de pipa
}

  CAFE_PipeRem                  = 'REM'           unimplemented;
{
  CAFE_PipeRem                  : StdOut
        Pasar mensajes REM al estilo DOS.
        Probable respuesta a una orden REM de usuario o TXT.
  000000REM                     : REM dificil de asociar
        a algun renglon especifico
  ??????REM                     : REM relacionado con un renglon de pipe
}

  CAFE_PipeDato                 = 'DATO'          unimplemented;
{
  CAFE_PipeDato                 : StdOut
        Para enviar datos.  Por ejemplo, un bloque
        de hoja de calculo
  000000DATO                    : Dato global, probablemente para
        inicializacion de la sincronia de pipa.
  ??????DATO                    : Dato respuesta a un renglon de pipa
}

  CAFE_PipeExito                = 'EXITO'         unimplemented;
{
  CAFE_PipeExito                : StdOut
        Algunas ordenes de usuario, enviaran un mensaje de EXITO.
        Por ejemplo, para indicar una operacion UNDO exitosa.
  000000EXITO                   : Proceso general exitoso,
        por ejemplo una inicializacion compleja.
  ??????EXITO                   : Indica exito de un proceso de renglon.
}

  CAFE_PipeEspero               = 'ESPERO'        unimplemented;
{
  CAFE_PipeEspero               : StdOut
        Para solicitar actos o informacion por parte del programa
        de Aplicacion;  que probablemente generen un
        temporal estado pasivo.
  000000ESPERO                  : Para indicar una orden de
        espera de caracter general a la pipa.  Probablemente
        CAFE quede vagabundo, mientras no reciba informacion.
  ??????ESPERO                  : Espera propia de algun
        renglon, es probable que la ejecucion de otros
        procesos continue.  Pero el renglon dicho
        se detenga.  Por ejemplo, una descompresion de archivo
        que necesite una clave.
}

  CAFE_PipeParcial              = 'PARCIAL'       unimplemented;
{
  CAFE_PipeParcial              : StdOut
        Similar a CAFE_PipeExito, pero para subetapas de un proceso
        mayor.  Por ejemplo, un proceso parcial de interpretacion
        y el proceso total fuera ejecucion.
  000000PARCIAL                 : Para subprocesos globales exitosos
  ??????PARCIAL                 : Para subprocesos de renglon exitosos
}

  CAFE_PipeSuspendido           = 'SUSPENDIDO'    unimplemented;
{
  CAFE_PipeSuspendido           : StdOut
        Para indicar que CAFE.EXE se encuentra suspendido.
        FreePascal puede suspender procesos externos sin problemas,
        pero probablemente convenga mandar una llamada
        previa a la pipa que lo permita.
  000000SUSPENDIDO              : Para indicar que el interprete
        de pipa se encuentra en estado suspendido
  ??????SUSPENDIDO              : No definido por ahora
}

  CAFE_PipeBeginLoad            = 'BEGINLOAD'     unimplemented;
{
  CAFE_PipeBeginLoad            : StdOut
        Para indicar inicio de un proceso de Load,
        probablemente desde archivo.
        Aunque tambien podria aplicarse para algun tipo de ClipBoard,
        si se define.  Los procesos LOAD generan por ejemplo,
        cuando no se detienen al primer error
        listas de errores.
        La generacion o ausencia de estos errores se
        detecta facilmente con AceptadoLoad
  000000BEGINLOAD               : Para indicar un proceso LOAD de
        caracter general, como fuentes, etc...
  ??????BEGINLOAD               : Para indicar un proceso LOAD
        asociado con una orden de renglon de pipa
}

  CAFE_PipeEndLoad              = 'ENDLOAD'       unimplemented;
{
  CAFE_PipeEndLoad              : StdOut
        Para indicar final de un proceso de Load.  Ya no deberian
        recibirse mas mensajes por el acto load concreto.
  000000ENDLOAD                 : Para indicar un fin de proceso
        LOAD de caracter generar, como fuentes, etc
  ??????ENDLOAD                 : Para indicar un fin de proceso
        LOAD asociado con un renglon de pipa
}

  CAFE_PipeAceptadoLoad         = 'ACEPTADOLOAD'  unimplemented;
{
  CAFE_PipeAceptadoLoad         = StdOut
        Para indicar un proceso Load sin objeciones detectadas
  000000ACEPTADOLOAD            : Para indicar al usuario
        un perfecto load de caracter general
  ??????ACEPTADOLOAD            : Para indicar un load
        sin objeciones asociado con un renglon
}

  CAFE_PipeBeginSave            = 'BEGINSAVE'     unimplemented;
{
  CAFE_PipeBeginSave            : StdOut
        Para indicar el inicio de un proceso Save.  Probablemente
        alguno particularmente extenso.
  000000BEGINSAVE               : Para indicar al usuario
        un inicio de proceso Save de caracter general
  ??????BEGINSAVE               : Para indicar el inicio
        de un proceso Save asociado con un renglon
}

  CAFE_PipeEndSave              = 'ENDSAVE'       unimplemented;
{
  CAFE_PipeEndSave              : StdOut
        Para indicar el final de un proceso Save.
        Ya no deberian recibirse mas mensajes
        por este motivo.
  000000ENDSAVE                 : Para indicar al usuario
        el final de un proceso Save de caracter general.
  ??????ENDSAVE                 : Para indicar al usuario
        el final de un proceso Save asociado con un renglon de pipa
}

  CAFE_PipeBeginTXT             = 'BEGINTXT'      unimplemented;
{
  CAFE_PipeBeginTXT             : StdOut
        Para indicar el inicio de un proceso estilo TXT, o sea
        una lectura de archivo TXT de ordenes
  000000BEGINTXT                : para indicar inicio de un proceso
        TXT de caracter general
  ??????BEGINTXT                : para indicar inicio de un proceso
        TXT vinculado con un renglo de pipa
}

  CAFE_PipeEndTXT               = 'ENDTXT'        unimplemented;
{
  CAFE_PipeEndTXT               : StdOut
        Para indicar el fin de un proceso estilo TXT, o sea
        una lectura de archivo TXT de ordenes
  000000ENDTXT                  : para indicar fin de un proceso
        TXT de caracter general
  ??????ENDTXT                  : para indicar fin de un proceso
        TXT vinculado con un renglo de pipa
}

  CAFE_PipePerfectoTxt          = 'PERFECTOTXT'   unimplemented;
{
  CAFE_PipePerfectoTxt          = StdOut
        Para indicar un proceso Load sin objeciones detectadas
  000000PERFECTOTXT             : Para indicar al usuario
        un perfecto proceso TXT de caracter general
  ??????PERFECTOTXT             : Para indicar un proceso TXT
        sin objeciones asociado con un renglon
}

  CAFE_PipeBeginMultimedia      = 'BEGINMULTIMEDIA'       unimplemented;
{
  CAFE_PipeBeginMultimedia      : StdOut
        Para indicar el inicio de un proceso estilo Multimedia, o sea
        archivos grandes que requieren tiempo sincronizado con el usuario
        y aplicaciones similares
  000000BEGINMULTIMEDIA         : para indicar inicio de un proceso
        Multimedia de caracter general
  ??????BEGINMULTIMEDIA         : para indicar inicio de un proceso
        Multimedia vinculado con un renglo de pipa
}

  CAFE_PipeDatoMultimedia       = 'DATOMULTIMEDIA'        unimplemented;
{
  CAFE_PipeDatoMultimedia       : StdOut
        Para indicar una transferencia de dato estilo Multimedia
        compatible con el formato ReadLn WriteLn.
        Tambien podria servir de antecedente para
        una orden WAIT para transferencia de binarios.
  000000DATOMULTIMEDIA          : para indicar transferencia de
        dato simple Multimedia de caracter general
  ??????DATOMULTIMEDIA          : para indicar transferencia de
        dato simple Multimedia vinculado con un renglon de pipa
}

  CAFE_PipePeticionMultimedia   = 'PETICIONMULTIMEDIA'    unimplemented;
{
  CAFE_PipePeticionMultimedia   : StdOut
        Para peticiones de parte de CAFE al usuario, relacionados
        con ejecucion tipo Multimedia
  000000PETICIONMULTIMEDIA      : para indicar peticion de datos
        o acciones tipo Multimedia de caracter general
  ??????PETICOINMULTIMEDIA      : para indicar peticion de datos
        o acciones tipo Multimedia vinculados con un renglon de pipa
}

  CAFE_PipeEndMultimedia        = 'ENDMULTIMEDIA'         unimplemented;
{
  CAFE_PipeEndMultimedia        : StdOut
        Para indicar el final de un proceso estilo Multimedia, o sea
        archivos grandes que requieren tiempo sincronizado con el usuario
        y aplicaciones similares
  000000ENDMULTIMEDIA           : para indicar final de un proceso
        Multimedia de caracter general
  ??????ENDMULTIMEDIA           : para indicar final de un proceso
        Multimedia vinculado con un renglo de pipa
}

  CAFE_PipeNombre               = 'NOMBRE'        unimplemented;
{
  CAFE_PipeNombre               : StdOut
        Para transferencia de datos importantes de algunas ordenes.
        Que convenca identificar con un Nombre o Identificador importante.
        Si se trata de un nombre de archivo, talvez convenga utilizar
        ARCHIVO
  000000NOMBRE                  : para indicar Nombre y datos generales
        en inicializacion
  ??????NOMBRE                  : para indicar respuesta de String
        importante de un renglon de pipa.  Se recomienda uno a lo sumo
        por renglon, pero no existe esa restriccion
}

  CAFE_PipeNumeroId             = 'NUMEROID'      unimplemented;
{
  CAFE_PipeNumeroId             : StdOut
        Para transferencia de numeros "Handle", o claves
        de acceso para ordenes y similar.  Probable sustituto
        de un NOMBRE
  000000NUMEROID                : para indicar NumeroID en un
        proceso general
  ??????NUMEROID                : para indicar NumeroID generado
        en algun proceso de renglon de pipa
}

  CAFE_PipeArchivo              = 'ARCHIVO'       unimplemented;
{
  CAFE_PipeArchivo              : StdOut
        Para transmitir informacion relevante de archivo,
        como el nombre en disco de algun dato
  000000ARCHIVO                 : para transmitir informacion
        relevante de archivo en un proceso general
  ??????ARCHIVO                 : para transmitir informacion
        relevante de archivo en un proceso de renglon de pipa
}

  CAFE_PipeSystem               = 'SYSTEM'        unimplemented;
{
  CAFE_PipeSystem               : StdOut
        Para transmitir informacion relevante para el Sistema Operativo
        de una forma que resulte bastante independiente del
        sistema particular.  Se admiten algunas transferencia
        particulares como el estilo de nombre de directorio
  000000SYSTEM                  : transferencia de informacion
        vinculado al sistema operativo para procesos
        de tipo general
  ??????SYSTEM                  : transferencia de informacion
        vinculado al sistema operativo para procesos
        vinculados con un renglon de pipa
}

  CAFE_PipeStream               = 'STREAM'        unimplemented;
{
  CAFE_PipeStream               : StdOut
        Para transmitir informacion relevante de Stream
        Por ejemplo INPUT, OUTPUT y StdErr en Process se
        manejan como TStream
  000000STREAM                  : para transmitir informacion
        relevante de Stream en un proceso general
  ??????STREAM                  : para transmitir informacion
        relevante de Stream en un proceso de renglon de pipa
}

  CAFE_PipePeticion             = 'PETICION'      unimplemented;
{
  CAFE_PipePeticion             : StdOut
        Para transmitir "peticiones" al programa controlador de pipa.
        Como mas informacion o similar.
  000000PETICION                : para transmitir peticion en
        un proceso de caracter general
  ??????PETICION                : para transmitir peticion en
        un proceso vinculado a un renglon de pipa
}

  CAFE_PipeNote                 = 'NOTE'          unimplemented;
{
  CAFE_PipeNote                 : StdOut
        Pasar mensajes NOTE al estilo FreePascal
        Probable alguna advertencia o curiosidad de importancia
        secundaria
  000000NOTE                    : Note dificil de asociar
        a algun renglon especifico
  ??????NOTE                    : Note relacionado con un renglon de pipe
}

  CAFE_PipeDerecho              = 'DERECHO'       unimplemented;
{
  CAFE_PipeDerecho              : StdOut
        Asociado con asuntos de autoria y derechos intelectuales.
        Aparte de informacion de derechos de uso como FreeWare o Patente
  000000DERECHO                 : Informacion relativa a derechos
        intelectuales y similares de un proceso general
  ??????DERECHO                 : Informacion relativa a derechos
        intelectuales y similares para un proceso de renglon de pipa
}

  CAFE_PipeTip                  = 'TIP'           unimplemented;
{
  CAFE_PipeTip                  : StdOut
        Pasar mensajes TIP, es decir.  Sugerencias para el usuario
        que se supone recibira con agrado, para mejorar en el uso
        del programa
  000000TIP                     : TIP de caracter general
  ??????TIP                     : TIP para un renglon de pipa
}

  CAFE_PipePublicidad           = 'PUBLICIDAD'    unimplemented;
{
  CAFE_PipePublicidad           : StdOut
        Asociado con asuntos de publicidad.
        Por ejemplo, para sugerir la compra de camisetas FreePascal
  000000PUBLICIDAD              : Publicidad de caracter general
  ??????PUBLICIDAD              : Publicidad particular para
        un renglon de pipa
}

  CAFE_PipeWait                 = 'WAIT'          unimplemented;
{
  CAFE_PipeWait                 : StdOut
        Para transferencia de datos binarios, es decir de formato libre,
        utilizando la pipa de StdOut.
        La idea :
        Cada interprete utilizara su propio sintaxis
        Controlador lee en StdOut 000000WAIT=000025IMAGEN4D 251
        Entonces deja de aplicar ReadLn, PORQUE DEJO DE SERVIR
        y espera un par de minutos y derrepente...
        Controlador lee en StdErr 000000LIBREWAIT=000025BIN 251 1020200
        Entonces el controlador lee 1020200 Bytes desde StdOut
        y luego sigue aplicando ReadLn como siempre
        y lee en StdOut 000251PETICION=000000CONTINUAR
        y manda CONTINUAR a la pipa respectiva
  000000WAIT                    : instruccion WAIT unica por el momento
        para facilitar su deteccion
  ??????WAIT                    : no definida

}

  CAFE_PipeLibreWait            = 'LIBREWAIT'     unimplemented;
{
  CAFE_PipeLibreWait            : StdErr
        Para indicar al usuario, que esta listo el dato WAIT, y
        puede proceder a su lectura.  O bien simplemente
        para finalizar el estado WAIT
  000000LIBREWAIT               : instruccion para liberar el estado WAIT
  ??????LIBREWAIT               : no definida
}

  CAFE_PipeBeginStdErr          = 'BEGINSTDERR'   unimplemented;
{
  CAFE_PipeBeginStdErr          : StdErr
        Para indicar el inicio de una secuencia de mensajes en
        StdErr.  La idea es que si no aparece esta orden,
        no se detectan errores en el renglon de pipa respectivo.
        Sin embargo, no todo reporte es un error verdadero;
        pues HINTS y MENSAJES tambien se envian aqui.
  000000BEGINSTDERR             : para iniciar secuencia de errores
        en proceso general
  ??????BEGINSTDERR             : para iniciar secuencia de mensajes
        de error en proceso de renglon de pipa
}

  CAFE_PipeEndStdErr            = 'ENDSTDERR'     unimplemented;
{
  CAFE_PipeEndStdErr            : StdErr
        Para finalizar una secuencia de errores, la idea es
        que esto autoriza al 'usuario' a olvidarse del asunto
        iniciado con BEGINSTDERR
  000000ENDSTDERR               : para iniciar una secuencia de
        mensajes en StdErr de proceso general
  ??????ENDSTDERR               : para finalizar una secuencia
        de mensajes de StdErr de proceso de renglon
}

  CAFE_PipeFracaso              = 'FRACASO'       unimplemented;
{
  CAFE_PipeFracaso              : StdErr
        Para indicar la interrupcion, fracaso o fallo de
        un proceso.
  000000FRACASO                 : para indicar un fracaso en
        proceso general
  ??????FRACASO                 : para indicar un fracaso en
        proceso de renglon de pipa
}

  CAFE_PipeHalt                 = 'HALT'          unimplemented;
{
  CAFE_PipeHalt                 : StdErr
        Informa al usuario que CAFE intentara en breve un HALT, es decir
        intenta llevar el programa a su final.  Si utiliza el sistema
        Process, no se recomienda inducir el estado de Halt.  Y mejor
        utilice los metodos ya programados por FreePascal;  en ese caso
        mejor espere los informes de VAGANCIA y/o SUSPENDIDO.
  000000HALT                    : Indicacion de HALT
  ??????HALT                    : No definido
}

  CAFE_PipeError                = 'ERROR'         unimplemented;
{
  CAFE_PipeError                : StdErr
        Principal metodo para transmitir mensajes de error.
        Para evitar la proliferacion desagradable de mensajes
        de error, se crean otras clasificaciones como
        ERRORLOAD, ERRORTXT, etc.  En muchas situaciones,
        el usuario preferirira obviar el detalle.
  000000ERROR                   : Indicacion de error en proceso general
  ??????ERROR                   : Indicacion de error en proceso de
        renglon de pipa
}

  CAFE_PipeMensajeTXT           = 'MENSAJETXT'    unimplemented;
{
  CAFE_PipeMensajeTXT           : StdErr
        Metodo para enviar mensajes al usuario relacionado
        con procesos TXT.  Probablemente mandara
        aqui otras subclasificaciones como TIP, NOTE, HINTS
        pero originarios de procesos TXT
  000000MENSAJETXT              : Mensaje para un proceso TXT de
        caracter general
  ??????MENSAJETXT              : Mensaje para un proceso TXT
        asociado con un renglon de pipa
}

  CAFE_PipeErrorTXT             = 'ERRORTXT'      unimplemented;
{
  CAFE_PipeErrorTXT             : StdErr
        Principal metodo para transmitir mensajes de error
        en procesos TXT.
  000000ERROR                   : Indicacion de error en proceso TXT
        de caracter general
  ??????ERROR                   : Indicacion de error en proceso TXT
        asociado con un renglon de pipa
}

  CAFE_PipeDescartadoTXT        = 'DESCARTADOTXT'         unimplemented;
{
  CAFE_PipeDescartadoTXT        : StdErr
        Un probable final de ejecucion TXT es el descarte
        al primer error, o por errores acumulados.
        Esto es forzar el final de ejecucion de un proceso en forma exitosa.
  000000ERROR                   : Indicacion de descarte en proceso TXT
        de caracter general
  ??????ERROR                   : Indicacion de descarte en proceso TXT
        asociado con un renglon de pipa
}

  CAFE_PipeMensajeLoad          = 'MENSAJELOAD'           unimplemented;
{
  CAFE_PipeMensajeLoad          : StdErr
        Metodo para enviar mensajes al usuario relacionado
        con procesos Load.  Probablemente mandara
        aqui otras subclasificaciones como TIP, NOTE, HINTS
        pero originarios de procesos Load
  000000MENSAJELOAD             : Mensaje para un proceso Load de
        caracter general
  ??????MENSAJELOAD             : Mensaje para un proceso Load
        asociado con un renglon de pipa
}

  CAFE_PipeErrorLoad            = 'ERRORLOAD'     unimplemented;
{
  CAFE_PipeErrorLoad            : StdErr
        Principal metodo para transmitir mensajes de error
        en procesos TXT.
  000000ERRORLOAD               : Indicacion de error en proceso Load
        de caracter general
  ??????ERRORLOAD               : Indicacion de error en proceso Load
        asociado con un renglon de pipa
}

  CAFE_PipeDescartadoLoad       = 'DESCARTADOLOAD'        unimplemented;
{
  CAFE_PipeDescartadoLoad       : StdErr
        Un probable final de ejecucion LOAD es el descarte
        al primer error, o por errores acumulados.
        Esto es forzar el final de ejecucion de un proceso en forma exitosa.
  000000ERRORLOAD               : Indicacion de descarte en proceso Load
        de caracter general
  ??????ERRORLOAD               : Indicacion de descarte en proceso Load
        asociado con un renglon de pipa
}

  CAFE_PipeErrorMultimedia      = 'ERRORMULTIMEDIA'       unimplemented;
{
  CAFE_PipeErrorMultimedia      : StdErr
        Principal metodo para transmitir mensajes de error
        en procesos Multimedia.
  000000ERRORMULTIMEDIA         : Indicacion de error en proceso Multimedia
        de caracter general
  ??????ERRORMULTIMEDIA         : Indicacion de error en proceso Multimedia
        asociado con un renglon de pipa
}

  CAFE_PipeMensajeMultimedia    = 'MENSAJEMULTIMEDIA'     unimplemented;
{
  CAFE_PipeMensajeMultimedia    : StdErr
        Metodo para enviar mensajes al usuario relacionado
        con procesos Load.  Probablemente mandara
        aqui otras subclasificaciones como TIP, NOTE, HINTS
        pero originarios de procesos Load
  000000MENSAJEMULTIMEDIA       : Mensaje para un proceso Multimedia de
        caracter general
  ??????MENSAJEMULTIMEDIA       : Mensaje para un proceso Multimedia
        asociado con un renglon de pipa
}

  CAFE_PipeSuspendidoMultimedia = 'SUSPENDIDOMULTIMEDIA'  unimplemented;
{
  CAFE_PipeSuspendidoMultimedia : StdErr
        Para informar de un estado suspendido en algun
        proceso Multimedia (el boton Pause por ejemplo)
  000000SUSPENDIDOMULTIMEDIA    : Mensaje de suspendido para un proceso
        Multimedia de caracter General
  ??????SUSPENDIDOMULTIMEDIA    : Mensaje de suspendido para un proceso
        Multimedia de renglon de pipa
}

  CAFE_PipeCanceladoMultimedia  = 'CANCELADOMULTIMEDIA'   unimplemented;
{
  CAFE_PipeCanceladoMultimedia  : StdErr
        Para informar de la cancelacion por cualquier razon
        de un proceso Multimedia
  000000CanceladoMultimedia     : Mensaje de cancelar para un proceso
        Multimedia de caracter general
  ??????CanceladoMultimedia     : Mensaje de suspendido para un proceso
        Multimedia asociado con un renglon de pipa
}

  CAFE_PipeMensaje              = 'MENSAJE'       unimplemented;
{
  CAFE_PipeMensaje              : StdErr
        Metodo para enviar mensajes al usuario.
        Para mensajes 'entusiastas' probablemente sean mejor
        las alternativas TIP o NOTE que se direccionan a StdOut
  000000MENSAJE                 : Mensaje para un proceso general
  ??????MENSAJE                 : Mensaje para un renglon de pipa
}

  CAFE_PipeAlerta               = 'ALERTA'        unimplemented;
{
  CAFE_PipeAlerta               : StdErr
        Metodo para enviar mensajes de alerta al usuario.
        Se supone que no son errores necesariamente.
        Si se trata de un error, mejor utilice ERROR.
  000000MENSAJE                 : Alerta para un proceso general
  ??????MENSAJE                 : Alerta para un renglon de pipa
}

  CAFE_PipeCancelado            = 'CANCELADO'     unimplemented;
{
  CAFE_PipeCancelado            : StdErr
        Metodo para enviar mensajes de cancelacion de ejecucion al usuario.
  000000CANCELADO               : Cancelado para un proceso general
  ??????CANCELADO               : Cancelado para un renglon de pipa
}

  CAFE_PipeLlave                = 'LLAVE'         unimplemented;
{
  CAFE_PipeLlave                : StdErr
        Para solicitar algun tipo de clave, o autorizacion.
        Por ejemplo, algunos tipos de datos, tendran contrasena
        o requieren un String de Registro para la empresa
  000000LLAVE                   : Solicitud de llave para un proceso general
  ??????LLAVE                   : Solicitud de llave para un renglon de pipa
}

  CAFE_PipeFatal                = 'FATAL'         unimplemented;
{
  CAFE_PipeFatal                : StdErr
        Para errores muy graves.  Estos induciran algun tipo
        de cancelacion.  Probablemente vendra un final de algun
        tipo de proceso o peor.
  000000ERROR                   : Para indicar error grave de proceso
        general, probablemente se induzca un REINICIO
  ??????ERROR                   : Indicacion de error Fatal para un
        renglon de pipa
}

  CAFE_PipeFinUsuario           = 'FINUSUARIO'    unimplemented;
{
  CAFE_PipeFinUsuario           : StdErr
        Genera un estado de fin de usuario de la Pipe completa
        o de un proceso
  000000FINUSUARIO              : Indica un estado de fin de Usuario
        para el proceso total
  ??????FINUSUARIO              : Indica un estado de fin de Usuario
        para un renglon de pipa
}

  CAFE_PipeReinicio             = 'REINICIO'      unimplemented;
{
  CAFE_PipeReinicio             : StdErr
        Informa de un estado de REINICIO de pipa.
        Los renglones intentaran terminar abruptamente.
        Y el contador de Pipa reiniciar a 000001
  000000REINICIO                : Para indicar un estado
        de reinicio de pipa
  ??????REINICIO                : Sin definir
}

  CAFE_PipeHint                 = 'HINT'          unimplemented;
{
  CAFE_Hint                     : StdErr
        Para informar de sugerencias
  000000HINT                    : Una sugerencia para proceso general
  ??????HINT                    : Una sugerencia para renglon de pipa
}

  CAFE_PipeVagancia             = 'VAGANCIA'      unimplemented;
{
  CAFE_Vagancia                 : StdErr
        Para informar al usuario que CAFE no tiene trabajo util que hacer
  000000VAGANCIA                : Informa el estado de vagancia
  ??????VAGANCIA                : Sin definir
}

  CAFE_PipeRetraso              = 'RETRASO'       unimplemented;
{
  CAFE_PipeRetraso              : StdErr
        Para informar de un estado de retraso por diversas causas.
        Previsto para sincronizacion y otros usos.
  000000RETRASO                 : Informa de un estado de retraso
        en un proceso general
  ??????RETRASO                 : Informa de un estado de retraso
        en un proceso de renglon de pipa
}

  CAFE_PipeSaturado             = 'SATURADO'      unimplemented;
{
  CAFE_PipeSaturado             : StdErr
        Para informar al usuario que los recursos asignados o disponibles
        escasean.  Probablemente sea recomendable disminuir las
        ordenes, o aumentar recursos
  000000SATURADO                : Informa de un estado de saturacion
        general
  ??????SATURADO                : No definido
}

  CAFE_PipeIncompleto           = 'INCOMPLETO'    unimplemented;
{
  CAFE_PipeIncompleto           : StdErr
        Para informar de un estado incompleto, a definir para
        aplicaciones particulares.
  000000INCOMPLETO              : Informa de un estado incompleto
        para un proceso general
  ??????INCOMPLETO              : Informa de un estado incompleto
        para un proceso de pipa de renglon
}

  CAFE_PipeFreeDOS              = 'FREEDOS'       unimplemented;
{
  CAFE_PipeFreeDOS              : StdErr
        Para instrucciones especificas del FreeDOS.
        i.e. para informar al usuario que no se logro activar
        un emulador de sistema solicitado.
  000000FREEDOS                 : Indicaciones del sistema FreeDOS de
        caracter general
  ??????FREEDOS                 : Indicaciones del sistema FreeDOS
        para renglon de pipa
}

  CAFE_PipeDOS                  = 'DOS'           unimplemented;
{
  CAFE_PipeDOS                  : StdErr
        Para instrucciones especificas del DOS.
        i.e. informar al usuario que CAFE.EXE se encuentra en estado TSR
        y no es necesario el PROCESS.  Probablemente en alguna version
        futura
  000000DOS                     : Indicaciones del sistema DOS de
        caracter general
  ??????DOS                     : Indicaciones del sistema DOS
        para renglon de pipa
}

  CAFE_PipeWindows              = 'WINDOWS'       unimplemented;
{
  CAFE_PipeWindows              : StdErr
        Para instrucciones especificas del Windows
  000000WINDOWS                 : Indicaciones del sistema WINDOWS de
        caracter general
  ??????WINDOWS                 : Indicaciones del sistema WINDDOS
        para renglon de pipa
}

  CAFE_PipeLinux                = 'LINUX'         unimplemented;
{
  CAFE_PipeLinux                : StdErr
        Para instrucciones especificas del Linux
  000000LINUX                   : Indicaciones del sistema LINUX de
        caracter general
  ??????LINUX                   : Indicaciones del sistema LINUX
        para renglon de pipa
}

TYPE
  CAFE_TListaMensajePipe        = CLASS  ( TStringList )
{
  CAFE_TListaMensajePipe        :
        Clase de TStringList creada para acumular mensajes a transmitir
        en la pipa, se asume que solo existira una instancia para
        disminuir confusion
        La idea es que acumula mensajes por tipo y los numera
        TYPE$$$$$$=Msg
        TYPE            : tipo de mensaje como ERROR, FATAL, etc
        $$$$$$          : numero identificador no cero
        Msg             : mensaje sin comilla, puede tener clave %S
                          separada por espacios vacios del resto
                          si necesario
        El programador deberia disponer de una lista "clara", que
        pueda transmitir al usuario del process o similar para
        que pueda traducirlo a idiomas diferentes o lo que requiera
}

    Public
CONSTRUCTOR Create; virtual;
{
  Establecer caracteristicas basicas del tipo como Sorted, dupError,
        casesensitive
}

DESTRUCTOR  Destroy; override;
{
  Destructor basico de clase
}

FUNCTION    AgregarMensajeMultiple
  (       TypeMsg               : CAFE_RespuestaEstiloPipe;
          IDClave               : LongInt;
    CONST Msg                   : ShortString                   ) : Boolean;
{
  FUNCTION AgregarMensajeMultiple
        Proceso basico para agregar nuevos mensajes a la lista
        de forma que cumplan con el formato y se impidan duplicaciones
        sin RAISE.  Simplemente mandara un FALSE para informar de
        un intento de duplicacion o valor inadecuado.
        Este es especial para ciertos tipos, en los que se pretende
        permitir origen multiple.  Por ejemplo ErrorREPO,
        concordara como ErrorLoadREPO, ErrorTXTREPO, en muchas circunstancias
        Recordar que no se permiten ID cero o negativo
  TypeMsg                       : Para indicar el tipo de mensaje a agregar
        recordar que formara parte de la construccion Name=Value
  IDClave                       : Numero a asociar al mensaje,
        probablemente el valor a agregar a HelpContext
  Msg                           : Mensaje a pasar a la lista "Value"
  FUNCTION AgregarMensajeMultiple : Devuelve TRUE para exito FALSE fracaso
}


FUNCTION    AgregarMensaje
  (       TypeMsg               : CAFE_RespuestaEstiloPipe;
          IDClave               : LongInt;
    CONST Msg                   : ShortString                   ) : Boolean;
{
  FUNCTION AgregarMensaje
        Proceso basico para agregar nuevos mensajes a la lista
        de forma que cumplan con el formato y se impidan duplicaciones
        sin RAISE.  Simplemente mandara un FALSE para informar de
        un intento de duplicacion o valor inadecuado.
        Recordar que no se permiten ID cero o negativo
  TypeMsg                       : Para indicar el tipo de mensaje a agregar
        recordar que formara parte de la construccion Name=Value
  IDClave                       : Numero a asociar al mensaje,
        probablemente el valor a agregar a HelpContext
  Msg                           : Mensaje a pasar a la lista "Value"
  FUNCTION AgregarMensaje       : Devuelve TRUE para exito FALSE fracaso
}

FUNCTION    LeerMensaje
  (       TypeMsg               : CAFE_RespuestaEstiloPipe;
          IDClave               : LongInt               ) : ShortString;
{
  FUNCTION LeerMensaje
        Proceso basico para lectura de mensajes, de forma que
        al usuario le resulte mas facil el acceso, sin generar por
        si mismo el formato "Name=Value" FUNCTION Es Overload para admitir
        parametros de sustitucion format.  Se recomienda para
        facilitar las cosas utilizar unicamente %s sin espacio en blanco
        O utilizar un formato de mensaje como #C, para casillas, etc.
  TypeMsg                       : Tipo de mensaje a leer
  IDClave                       : Clave asignada para la lectura.
  FUNCTION LeerMensaje          : Devuelve el texto solicitado
        o StringNulo si no encuentra
}

FUNCTION    LeerMensaje
  (       TypeMsg               : CAFE_RespuestaEstiloPipe;
          IDClave               : LongInt;
    CONST Args                  : array of Const        ) : ShortString;
{
  FUNCTION LeerMensaje
        Proceso basico para lectura de mensajes, de forma que
        al usuario le resulte mas facil el acceso, sin generar por
        si mismo el formato "Name=Value" FUNCTION Es Overload para admitir
        parametros de sustitucion format.  Se recomienda para
        facilitar las cosas utilizar unicamente %s sin espacio en blanco
        O utilizar un formato de mensaje como #C, para casillas, etc.
  TypeMsg                       : Tipo de mensaje a leer
  IDClave                       : Clave asignada para la lectura.
  Args                          : Parametros a pasar al format
  FUNCTION LeerMensaje          : Devuelve el texto solicitado
        o String Nulo si no encuentra
  ADVERTENCIA:
        Un error en el Format que es probable, genera un StringNulo
        sin exception, pues se asume que al usuario no le interesa
        tanta preocupacion por un mensaje de error.
        El resultado en la pipa seria probablemente un mensaje
        de error sin descripcion
}

                                  END;  { CAFE_TListaMensajePipe }

VAR
  CAFE_ListaMensajePipe         : CAFE_TListaMensajePipe;
{
  CAFE_ListaMensajePipe         :
        Cada vez que desee agregar un mensaje a la lista de errores
        permanente, se supone que deberia ser agregada a esta variable;
        en lo que a la pipa se refiere
}

CONST
  CAFE_PrecisionListaMensajePipe                        = 6;
{
  CAFE_PrecisionListaMensajePipe :
        Constate para establecer la presicion en la lista
        de mensajes de pipa en el formato
        TYPE$$$$$$=Msg
        TYPE            : tipo de mensaje como ERROR, FATAL, etc
        $$$$$$          : numero identificador no cero
        Msg             : mensaje sin comilla, puede tener clave %S
                          separada por espacios vacios del resto
                          si necesario
}

  CAFE_InicioCodigoNumeral                              = '#0';
{
  CAFE_InicioCodigoNumeral      :
        Inicio con el que se reconoce el sistema de reporte
        de mensajes Numeral
        $$$$$$ERROR!!!!!!=#0%%%%%% 'Msg1' 'Msg2' 'TYPE'
  %%%%%%                : Numero de error en alguna lista
  Para los demas ver la descripcion mas adelante
}

  CAFE_InicioCodigoCasilla                              = '#C';
{
  CAFE_InicioCodigoCasilla      :
        Inicio con el que se reconoce el sistema de reporte
        de mensajes estilo Casilla
        Se suponen hacen referencia a algun arreglo bidimensional
        $$$$$$ERROR!!!!!!=#C(E1,E2[,E3[,E4]) 'Msg1' 'Msg2' 'TYPE'
  E1                    : Numero entero positivo de Fila de casilla
  E2                    : Numero entero positivo de Columna casilla
  E3                    : Numero entero de clasificacion
        i.e. error Sintactico.
        Si se trata de RESULT o DATOS
        hace referencia al tipo de casilla
  E4                    : Numero entero de reconocimiento
        i.e. numero de error en una lista de Strings
        Si se trata de RESULT o DATOS
        hace referencia al modo de despliegue de datos a continuacion
        (como visualizacion por valor, o por funcion)
  Para los demas ver la descripcion mas adelante
}


TYPE
  CAFE_MatrizRenglonConteo      =
        ARRAY [ CAFE_PrimerREPO..CAFE_UltimoREPO ] OF LongInt;
{
  CAFE_MatrizRenglonConteo      :
        Para determinar el "Name" de un error, existe un numero de
        secuencia de tipo.  Este tipo de
        matriz se utiliza para llevar el conteo
}

VAR
  CAFE_NulaMatrizRenglonConteo  : CAFE_MatrizRenglonConteo;
{
  CAFE_NulaMatrizRenglonConteo  : Se requiere con frecuencia anular
        estras matrices de conteo.  Esta variable semiconstante
        es util con este fin.
}

CONST
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
  CAFE_NameEstiloPipe           : ARRAY [ CAFE_PrimerREPO..CAFE_UltimoRepo ]
                                  OF String     =
        ( CAFE_PipeBegin          , CAFE_PipeEnd                    ,
          CAFE_PipeResult         , CAFE_PipeAccion                 ,
          CAFE_PipeEcho           , CAFE_PipeRem                    ,
          CAFE_PipeDato           , CAFE_PipeExito                  ,
          CAFE_PipeEspero         , CAFE_PipeParcial                ,
          CAFE_PipeSuspendido     , CAFE_PipeBeginLoad              ,
          CAFE_PipeEndLoad        , CAFE_PipeAceptadoLoad           ,
          CAFE_PipeBeginSave      , CAFE_PipeEndSave                ,
          CAFE_PipeBeginTXT       , CAFE_PipeEndTXT                 ,
          CAFE_PipePerfectoTXT    , CAFE_PipeBeginMultimedia        ,
          CAFE_PipeDatoMultimedia , CAFE_PipePeticionMultimedia     ,
          CAFE_PipeEndMultimedia  , CAFE_PipeNombre                 ,
          CAFE_PipeNumeroID       , CAFE_PipeArchivo                ,
          CAFE_PipeSystem         , CAFE_PipeStream                 ,
          CAFE_PipePeticion       , CAFE_PipeNote                   ,
          CAFE_PipeDerecho        , CAFE_PipeTip                    ,
          CAFE_PipePublicidad     , CAFE_PipeWait                   ,
          CAFE_PipeLibreWait      , CAFE_PipeBeginStdErr            ,
          CAFE_PipeEndStdErr      , CAFE_PipeFracaso                ,
          CAFE_PipeHalt           , CAFE_PipeError                  ,
          CAFE_PipeMensajeTXT     , CAFE_PipeErrorTXT               ,
          CAFE_PipeDescartadoTXT  , CAFE_PipeMensajeLoad            ,
          CAFE_PipeErrorLoad      , CAFE_PipeDescartadoLoad         ,
          CAFE_PipeErrorMultimedia, CAFE_PipeMensajeMultimedia      ,
          CAFE_PipeSuspendidoMultimedia                             ,
          CAFE_PipeCanceladoMultimedia                              ,
          CAFE_PipeMensaje        , CAFE_PipeAlerta                 ,
          CAFE_PipeCancelado      , CAFE_PipeLlave                  ,
          CAFE_PipeFatal          , CAFE_PipeFinUsuario             ,
          CAFE_PipeReinicio       , CAFE_PipeHint                   ,
          CAFE_PipeVagancia       , CAFE_PipeRetraso                ,
          CAFE_PipeSaturado       , CAFE_PipeIncompleto             ,
          CAFE_PipeFreeDOS        , CAFE_PipeDOS                    ,
          CAFE_PipeWindows        , CAFE_PipeLinux                  ,
          CAFE_PipeNull           );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
{
  CAFE_NameEstiloPipe           : Sirve para transformar
        el dato ordinal en un String apropiado para la pipa
}

TYPE
  CAFE_DescriptorPipeItem       =
                ( ActivoPIPE, SimplePIPE, MemoriaPIPE, InputOutputPIPE,
                        AcumuladoTimerPIPE,
                        LoadPIPE, BasicPIPE,
                        SavePIPE, BatPIPE, MultimediaPIPE,
                        InicializarPIPE, FinalizarPIPE, SuspendidoPIPE );
{
  CAFE_DescriptorPipeItem       : Su objetivo es especificar el origen
        y caracteristicas basicas de ejecucion de un PipeItem, es decir
        una orden den renglon
  ActivoPIPE                    :
        Para indicar que el PipeItem tiene informacion util
  SimplePIPE                    :
        Para compatibilidad con futuras versiones, se supone
        que en un inicio los mensajes de Pipa seran clasificados
        como SimplePIPE, asi que usted deberia revisar esta clasificacion
        antes de interpretacion, y de no estar activa ejecutar
        una nueva version virtual
  MemoriaPIPE                   :
        Para indicar que la pipa se ejecuta en memoria RAM
  InputOutputPIPE               :
        Para indicar que la pipa se ejecuta con el Input Output Standard
        lo que podria ocurrir en el futuro en un mediante un Process FPC
  AcumuladoTimerPIPE            :
        Para indicar que el renglon es acumulado en la PIPA, es
        decir su ejecucion se difiere para despues, probablemente
        en forma simultanea a otras actividades
  LoadPIPE                      :
        Para indicar que la orden tuvo su origen en un proceso LOAD
  BasicPIPE                     :
        Para indicar que el PipeItem es acumulado segun reglas similares
        al BASIC antiguo.  Es decir un identificador de numero se convierte
        en LABEL secuencial y no se ejecuta hasta que se indique
  SavePIPE                      :
        Para indicar que la orden tuvo su origen en un proceso SAVE
  BatPIPE                       :
        Para indicar que la orden se ejecuta mediante un proceso TXT
  MultimediaPIPE                :
        Orden de pipa asociado con procesos Multimedia
  InicializarPIPE               :
        Indica que la pipa se somete a un proceso de Inicializacion,
        Puede que renglones complejos, necesiten actividades
        especiales
  FinalizarPIPE                 :
        Indica que la pipa se somete a un proceso de Finalizacion,
        Es probable que la pipa necesite generar algun tipo de SAVE
        condicionado o similar.
  SuspendidoPIPE                :
        Indica que la pipa se somete a un proceso de suspension.
        Es decir cese de actividades y espera.
}

  CAFE_ConjuntoDescriptorPipeItem               =
                                SET OF CAFE_DescriptorPipeItem;
{
  CAFE_ConjuntoDescriptorPipeItem               :
        Para utilizar el tipo CAFE_DescriptorPipeItem como conjunto
}

  CAFE_MultiVariant             = ARRAY OF Variant;
{
  CAFE_MultiVariant             : Para paso de parametros custom.
        Se utiliza este tipo por ser muy flexible.
}

  CAFE_FuncionForPipe           = FUNCTION
  ( VAR   ConteoRegresivo,
          Param1,
          Param2,
          Param3                : LongInt;
          MyParam               : CAFE_MultiVariant;
          ForzarReset           : Boolean = FALSE       ) : Boolean OF Object;
{
  CAFE_FuncionForPipe           : Para definir una funcion de ejecucion
        diferida en la pipa.  ConteoRegresivo, se supone que se ejecuta
        hasta cero, y entonces llama si es necesario a una funcion
        de Reset para el proceso.  Se define como parametro VAR
        para facilitar su programacion
        La bandera ForzarReset, se utiliza si se desea
        que el mismo metodo se encargue del Reset y de la operacion normal
}

  CAFE_PipeItem                 = CLASS  ( TStreamCollectionItem )
{
  CAFE_PipeItem                 : Clase basica para acumular ordenes
        de renglon de pipa, con algunas caracteristicas
        basicas de control en el tiempo
}

  Public
    OrdenString                 : AnsiString;
{
  OrdenString                   : Contiene la orden recibida como ReadLn,
        en este punto se supone una por ReadLn, aunque el traductor
        podria permitir otro esquema
}

    PipeID                      : LongInt;
{
  PipeID                        : Para identificar la orden
        con un numero de renglon o similar
}

    ImportanciaPipe             : LongInt;
{
  ImportanciaPipe               : Valor asignado para que el programa
        valore cuanto tiempo asignarle a la orden
}

    TiempoPipe                  : TDateTime;
{
  TiempoPipe                    : Variable para llevar el control
        del tiempo efectivamente asignado a la orden
}

    AuxiliarBasic               : LongInt;
{
  AuxiliarBasic                 : Valor util si la orden es
        rotulada como un Label estilo Basic antiguo (numeros)
}

    DescriptorItem              : CAFE_ConjuntoDescriptorPipeItem;
{
  DescriptorItem                : Conjunto para dar una descripcion
        general de la orden pipe
}

  Public
CONSTRUCTOR Create
  (       ACollection           : TCollection                   ); override;
{
  Herencias de TStreamCollectionItem nunca deberian crearse en forma
  independiente (ver Manual Classes)
        ACollection             : PipeItem deberia pertenecer a alguna
                coleccion concreta y utilizar los metodos
                correctos de cambio de administrador
}

  Public
DESTRUCTOR  Destroy; override;
{
  Unica forma para remover Items desde una TStreamCollection, deje que
  ella se encargue
}

                                  END;  { CLASS CAFE_PipeItem }

  CAFE_InterfacePipe            = INTERFACE ( CAFE_InterfaceBasico )
                                  [CAFE_GUIDInterfacePipe]
{
  CAFE_InterfacePipe            : Interface encargada de la ejecucion
        de las ordenes de pipa.  Note que CAFE_Tu1 crea una pipa "tonta",
        en CAFE.Exe probablemente toda la interpretacion se asigne
        a los manejadores, y la comunicacion se logra por medio
        de la Interface
}

PROCEDURE   EjecutarOrden
  (       Solicitud             : CAFE_PipeItem                         );
{
  PROCEDURE EjecutarOrden
        Se supone que este deberia ser la orden correcta,
        Para que el manejador tome las deciciones pertinentes  de
        acumulacion, o alguien asuma dicha resonsabilidad,
        en esta version no esta implementada
  Solicitud                     : Orden transcrita como PipeItem
        a transferir al manejador respectivo
}

PROCEDURE   EjecutarRenglonCompleted
  ( CONST OrdenPipe             : String                                );
{
  PROCEDURE EjecutarRenglonCompleted
        Transfiere una orden de la pipa al manejador, como un String.
        En esta version se transfiere la orden hasta Completed, por ello
        es innecesario el PipeItem
  OrdenPipe                     : Orden leida por la pipa que
        se transfiere al manejador con el interprete sintactico
        adecuado
}

FUNCTION    ReadItemID
  (     Ide                     : String        ) : CAFE_InterfaceBasico;
{
  FUNCTION ReadItemID
        Consideramos que la lectura ID, es innecesaria.  Su utilidad
        aqui radica para aclararle al programador la estructura
        de la Interface
        Es decir:
        El manejador es una Inteface que maneja una lista de interfaces
        i.e. cinco hojas de calculo con comunicacion entre ellas
        Es probable que en algunos modelos de pipa, existan
        interpretes sintacticos invocables.  Por ejemplo el I
        D['TEMPORAL'], podria
        en cargarse de la sintaxis general, pero por el momento.
        No se hara tal cosa.
        Pipas mas avanzadas podria asumir algunas
        ordenes como la vinculacion de Interfaces...
        En esta version estas ordenes se relegan a la interface principal
        que las distribuye a las demas
  Ide                           : Nombre de interface a accesar
}

FUNCTION    ReadAdministrador                           : TCustomApplication;
{
  ReadAdministrador             : Nuestra interface requiere acceso
        la pipa, ni modo...
}

  Property
    ID[ ide : String  ]         : CAFE_InterfaceBasico
                                  Read  ReadItemID;
{
  ID                            : Tipo array para accesar a los
        diferentes manejadores subordinados.  No se recomieda su
        uso por el momento.
}

  Property
    Administrador               : TCustomApplication
                                  Read  ReadAdministrador;
{
  Administrador                 : Para facilitarle al manejador
        el acceso a la pipa.
        Su principal uso por ahora, sera el descargue de mensajes
        a la pipa, para ser transferidos al usuario
}

  END experimental;  { INTERFACE CAFE_InterfacePipe }

  CAFE_TCollectionPipeItem      = CLASS  ( TOwnedCollection )
{
  CAFE_TCollectionPipeItem      : Para crear grupos de PipeItem,
        puesto que los datos en el administrador de pipa,
        se manejaran sobre todo a nivel de Coleccion y no
        como PipeItem individual
}

CONSTRUCTOR Create; virtual;
{
  Sustituye al Create de TOwnedCollection, pues ya el tipo esta decidido
}

  Public
DESTRUCTOR  Destroy; override;
{
  Destructor basico de la unidad
}

  Private
FUNCTION    ReadItemID
  (     Ide                     : LongInt               ) : CAFE_PipeItem;

  Public
  Property
    ID[ ide : Integer ]         : CAFE_PipeItem
                                  Read  ReadItemID;
{
  ID                            : Acceso estilo array
        Instance.ID[ Clave ] a los elementos CAFE_PipeItem del array
}

                                  END;  { CLASS CAFE_TCollectionPipeItem }

  CAFE_PipeParametro            = CLASS  ( CAFE_PipeItem )
{
  Evolucion de PipeItem, cuyo objetivo es el control de ordenes
  acumuladas.  En la actualidad puede considerarse codigo ocioso
}

  Public
    //  OrdenString                 : AnsiString;
    //  PipeID                      : LongInt;
    //  ImportanciaPipe             : LongInt;
    //  AuxiliarBasic               : LongInt;
    //  DescriptorItem              : CAFE_ConjuntoDescriptorPipeItem;
    CuentaRegresivaPipe         : LongInt;
{
  CuentaRegresivaPipe           : Lleva el conteo de los llamadas
        al metodo, su actualizacion es obligacion de
        FuncionRutinaPipe, que lo recibe como parametro VAR
        Al llegar a cero deberia llamarse si necesario a
        FuncionResetPipe, que podria ser NIL o la misma
        FuncionRutinaPipe.  Luego probablemente se destruira
        el PipeParametro.
}

    Param1Pipe,
{
  Param1Pipe                    : Primer parametro VAR a pasar
        a FuncionRutinaPipe
}

    Param2Pipe,
{
  Param2Pipe                    : Segundo parametro VAR a pasar
        a FuncionRutinaPipe
}

    Param3Pipe                  : LongInt;
{
  Param3Pipe                    : Tercer parametro VAR a pasar
        a FuncionRutinaPipe
}

    ConteoRenglon               : CAFE_MatrizRenglonConteo;
{
  ConteoRenglon                 : Para llevar el conteo conveniente
        para los mensajes generados debido al renglon de pipa,
        recuerde que se solicita numeracion unica y secuencial
}

    GrupoParametro              : CAFE_MultiVariant;
{
  GrupoParametro                : Paquete de parametros a pasar
        si lo requiere a FuncionRutinaPipe de gran versatilidad.
        Admisible NIL
}

    FuncionRutinaPipe           : CAFE_FuncionForPipe;
{
  FuncionRutinaPipe             : Metodo para ejecutar la orden
        acumulada de pipa
}

    FuncionResetPipe            : CAFE_FuncionForPipe;
{
  FuncionResetPipe              : Metodo optativo, puede ser NIL,
        para llamar cuando el conteo regresivo llega a cero
        antes de la destruccion de la orden
}

    PruebaSubsistencia1         : Pointer;
{
  PruebaSubsistencia1           : Numero utilizado para asegurar
        la subsistencia de la instancia del objeto
        que corresponde al metodo.  Un valor de cero, lo
        inhabilita.
}

    PruebaSubsistencia2         : PtrInt;
{
  PruebaSubsistencia2           : Numero utilizado para asegurar
        la subsistencia de la instancia del objeto
        que corresponde al metodo.  Un valor de cero, lo
        inhabilita.
}

    SubLista                    : CAFE_TCollectionPipeItem;
{
  SubLista                      : Algunos renglones complejos
        requieran acumuladores de renglones.
        Esta estructura facilitaria eventualmente el anidamiento
        de llamados TXT o similar.  La idea es que SubLista
        acumula temporalmente las ordenes, mientras se decide
        la forma de ejecucion
}

  Public
CONSTRUCTOR Create
  (       ACollection           : TCollection                   ); override;
{
  Herencias de TStreamCollectionItem nunca deberian crearse en forma
  independiente (ver Manual Classes)
}

FUNCTION    EjecutarPruebaSubsistencia                  : Boolean; virtual;
{
  FUNCTION EjecutarPruebaSubsistencia
        Realiza una prueba para asegurar la subsistencia
        de la instancia del objeto que contiene el metodo
        de FuncionRutinaPipe.
        PruebaSubsistencia1     : valor VMT sin modificar
        PruebaSubsistencia2     : valor GetHashCode (virtual)
        Las pruebas se inhabilitan con un cero, en tal caso devuelve
        TRUE tambien
  FUNCION EjecutarPruebaSubsistencia            : devuelve TRUE
        para indicar exito en las prueba, FALSE para fracaso
}

FUNCTION    EstablecerFuncionRutinaID
  (       SumarDescriptor       : CAFE_ConjuntoDescriptorPipeItem;
          ContadorRegresivo     : LongInt;
          FuncionRutina         : CAFE_FuncionForPipe;
          FuncionReset          : CAFE_FuncionForPipe;
          Param1                : LongInt               = 0;
          Param2                : LongInt               = 0;
          Param3                : LongInt               = 0;
          PaqueteParametro      : CAFE_MultiVariant     = NIL   ) : LongInt;
{
  FUNCTION EstablecerFuncionRutinaID
        Metodo facil para establecer parametros iniciales de
        un tipo PipeParametro.
        FUNCION Calcula los valores de PruebaSubsistencia,
        y asigna valores Default en caso de no requerir algunos datos
        Se espera que ContadorRegresivo y FuncionRutina, y quiza
        Param1 sean suficientes la mayoria de las veces
        La programacion simple recomendaria que el PipeItem
        nunca fuera accesado directamente por el manejador,
        ni siquiera a travez de este metodo.
        Probablemente existiria en el futuro un metodo en
        la pipa como TCustomApplication que se encargue de
        llamar a esta FUNCION
        Note que FUNCTION retorna el PipeID, dato que podria
        ser suficiente, junto con la variable de pipa,
        para escribir mensajes en la misma con metodos apropiados
  SumarDescriptor               : Valido [], agrega caracteristicas
        al descriptor del PipeParametro
  ContadorRegresivo             : Valor inicial obligatorio de algun contador
        hasta cero, que se actualiza como VAR en cada llamado
        a FuncionRutina
  FuncionRutina                 : Metodo obligatorio para tramitar
        el renglon de PipeParametro
  FuncionReset                  : Metodo optativo para llamar cuando
        el contador llega a cero, podria ser la misma FuncionRutina
  Param1                        : Valor inicial del primer parametro
        VAR a pasar a FuncionRutina
  Param2                        : Valor inicial del segundo parametro
        VAR a pasar a FuncionRutina
  Param3                        : Valor inicial del tercer parametro
        VAR a pasar a FuncionRutina
  PaqueteParametro              : Permite agregar un paquete de variantes
        a FuncionRutina.
        En el destructor se asigna Null a todos los variantes y se
        llama finalmente a SetLength( PaqueteParametro, 0 )
        condicionado a no NIL,
        probablemente esto sea suficiente la mayoria de las veces
  FUNCTION EstablecerFuncionRutinaID            : Da el numero
        de PipeID respectivo para facilitar localizacion
}

  Public
DESTRUCTOR  Destroy; override;
{
  Unica forma para remover Items desde una TStreamCollection, deje que
  ella se encargue
}

                                  END;  { CAFE_PipeParametro }

  CAFE_ReferenciaTStringPipe0   = CLASS OF CAFE_TStringPipe0;
{
  CAFE_ReferenciaTStringPipe0   : Como es muy probable la duplicacion
        de las listas, se crea una referencia interior para
        facilitar el proceso
}

  CAFE_TStringPipe0             = CLASS ( TStringList )
{
  Clase para crear listas de String estilo pipa.  Probablemente
  sean estilo FIFO, no ordenadas, CaseSensitive y dupAccept
  BaseConteo se utiliza para controlar
  las salidas, de forma que su numero indica
  el numero de salidas, para corregir la numeracion interior.
  La validez de este supuesto se verifica con BanderaBaseConteo
  i.e. se han generado 1010 renglones de pipa pero se han eliminado
  990 renglones, entonces BaseConteo = 990, de forma
  que el renglon 1000 se asigne en varios metodos a dato 10
  Por el momento el unico metodo de interes que utiliza la numeracion
  es TijeraString
}

      Public
    BaseConteo                  : LongInt;
{
  BaseConteo                    : Lleva la cuenta de salidas FIFO
        para corregir la numeracion a Renglon de Pipa, permitiendo
        eliminar datos de lista
}

    BanderaBaseConteo           : Boolean;
{
  BanderaBaseConteo             : Si TRUE indica que el valor
        BaseConteo es significativo.  Algunas operaciones
        Tijera podrian dejar el valor de BaseConteo sin significado
        No actualizamos los metodos anteriores, asi que
        CUIDADO
}

    MoldeTStrings               : CAFE_ReferenciaTStringPipe0;
{
  MoldeTStrings                 : Referencia interior por comodidad
        en las operaciones de duplicado y extraccion
}

CONSTRUCTOR Create; virtual;
{
  Constructor principal de la clase que asigna valores iniciales
  dupAccept, no Sorted, case sensitive, etc.
}

FUNCTION    TijeraStrings
  (       InicioTijera, FinalTijera     : LongInt;
          EliminarOrigen        : Boolean = FALSE       ) : CAFE_TStringPipe0;
{
  FUNCTION TijeraStrings
        InicioTijera y Final Tijera cuentan a partir de uno,
        y toman en cuenta si definido BaseConteo.
        Esto es para concordar con el numero de renglon de Pipa,
        que numera a partir de uno.
        Se supone que FijoStrings es el metodo para extraer datos
        de esta clase.  Tijera permite extraer grupos grandes
        datos de datos cuando ello se requiera;  pero
        se recomienda el uso de FifoStrings, que intenta
        aplicar FreeAndNil al objeto asociado (si no NIL), y Tijera no lo hace
        En algunos procesos de preparacion, probablemente
        sea de mayor comodidad el uso de TijeraStrings
        Para que BaseConteo sea relevante InicioTijera debera
        ser igual a BaseConteo+1 cuando aplique EliminarOrigen.
  InicioTijera                  : Numeracion a partir de uno
        que toma en cuenta BaseConteo si definido para iniciar la extraccion
  FinTijera                     : Numeracion a partir de uno que toma
        en cuenta BaseConteo si definido para terminar extraccion
  EliminarOrigen                : Si TRUE elimina los datos de
        la lista intentan conservar si posible BaseConteo
        (InicioTijera=BaseConteo+1)
  FUNCTION TijeraStrings        : devuelve la lista solicitada, que
        bien podria ser una secuencia vacia.  Unicamente
        devuelve los Strings;  los objetos no se devuelven
  NOTA: Valores fuera de rango se tratan de arreglar con EnsureRange,
        Aunque algunas cosas no serian admisibles con lista vacia
        En general se perdona el exceso en FinalTijera
        FinalTijera < InicioTijera devolveria lista vacia
}

FUNCTION    FifoStrings                                   : AnsiString;
{
  FUNCTION FifoStrings          :
        Devuelve el String[0], llamando a FreeInstance del objeto
        si existe, y destruyendo el dato.
        Incremente en uno BaseConteo
  FUNCTION FifoStrings          : Devuelve el String solicitado
}

DESTRUCTOR  Destroy; override;
{
  Destructor fundamental de la clase
}

                                  END;  { CLASS CAFE_TStrinsPipe0 }

  CAFE_TriplePipeMemory         = CLASS ( TCustomApplication )
{
  Administrador de pipa, que maneja la informacion probablemente
  en memoria RAM, su evolucion podria utilizar StdOutput, etc...
  La idea...
  Las ordenes se reciben de fuente externa a la clase en PipeInputText
  Dichas ordenes se ejecutan mediante InterfaceEjecutora
  La mayoria de los valores actuales se pueden considerar unimplemented
  para el futuro
}

      Public
    AplicacionSubordinada       : Boolean;
{
  AplicacionSubordinada         : Bandera que indica si
        la aplicacion es Subordinada o es la aplicacion principal,
        en estilo Process probablemente asuma el papel
        de aplicacion principal, esto conlleva que
        accesa al Input y Output
        TRUE es subordinada
        FALSE es principal
}

    BanderaWaitOnCompleted      : Boolean;
{
  BanderaWaitOnCompleted        : Establece que la pipa
        ejecuta las ordenes hasta completadas sin acumulacion
        temporal de las mimas
        TRUE se ejecutan las ordenes completas sin acumulacion
        FALSE no es asi
}

    BanderaInhabilitarBinarios  : Boolean;
{
  BanderaInhabilitarBinarios    : El objetivo de esta Boolean
        es prohibir por default y si se requiere la transferencia
        de binarios en la pipa.  Para que el usuario
        puede estar tranquilo de que todas
        las lecturas pueden realizarse completamente con ReadLn
        sin tener que esperar nada diferente.
        Es importante por compatibilidad con futuras versiones.
        i.e. una version de CAFE que quiera transmitir un
        icono publicitario, esta bandera TRUE por default
        lo prohibe.
        Otra alternativa mas complicada seria que
        el usuario programara la intercepcion de los binarios
        Pero en algun proceso como "Calculo del Area de un Circulo",
        carezca de interes tanta complejidad.
        El programa mandaria al usuario un mensaje de PETICION o
        MENSAJE, solicitando la activacion de la lectura de binarios,
        que el usuario podria ignorar
}

    BanderaConteoPrincipalRenglon               : Boolean;
{
  BanderaConteoPrincipalRenglon : Existen procesos como el LOAD
        que no contabilizan renglones al nivel Principal.
        Esta bandera sirve para informar que ciertas
        ordenes estan ejecutandose sin conteo de Renglon.
        No deberia utilizarla el usuario.
}

    BanderaLoad                                 : Boolean;
{
  BanderaLoad                   : Bandera para avisar a la
        pipa que se encuentra en un estado Load
}

    BanderaBasic                                : Boolean;
{
  BanderaBasic                  : Bandera para avisar a la
        pipa que se encuentra en un estado de ejecucion estilo
        Basic antiguo.  Es decir con Label numerado.
}

    BanderaEcho                                 : Boolean;
{
  BanderaEcho                   : La pipa solicita ECHO para
        sus ordenes de renglon
}

    ConteoPrincipalRenglon      : LongInt;
{
  ConteoPrincipalRenglon        : Los procesos de pipa, generalmente
        estan asociados a un numero de orden.  Su valor
        se mantiene actualizado en esta variable
}

    PipeInputMemory             : TStream;
{
  PipeInputMemory               :
        TStream probablemente asociado con PipeInputText.
        Corresponden a las entradas a la Pipa desde alguna fuente
        en sintaxis final del programa
}

    PipeOutputMemory            : TStream;
{
  PipeOutputMemory              :
        TStream probablemente asociado con PipeOutputText.
        Corresponden a las salidas de la Pipa segun
        las reglas generales de Pipa
}

    PipeStdErrMemory            : TStream;
{
  PipeStdErrMemory              :
        TStream probablemente asociado con PipeStdErrText.
        Corresponden a las salidas de la Pipa segun
        las reglas generales de Pipa.
        La pipa posee un paralelismo
        como es usual en FPC.EXE con Output, Input y StdErr
}

    PipeBufferFile              : TFileStream;
{
  PipeBufferFile                :
        TStream pivote, utilizado probablemente para la lectura/escritura
        rapida y temporal de archivos.  Seguramente se
        destruye y se regenera con frecuencia
}

    PipeInputText               : TextFile;
{
  PipeInputText                 :
        TextFile asociado con PipeInputMemory, para facilitar
        el empleo de instrucciones tipo ReadLn
}

    PipeOutputText              : TextFile;
{
  PipeOutputText                :
        TextFile asociado con PipeOutputMemory, para facilitar
        el empleo de instrucciones tipo WriteLn
}

    PipeStdErrText              : TextFile;
{
  PipeStdErrText                :
        TextFile asociado con PipeStdErrMemory, para facilitar
                el empleo de instrucciones tipo WriteLn
}

    ConteoGeneral0              : CAFE_MatrizRenglonConteo;
{
  ConteoGeneral0                : Para ubicar contador de mensajes
        Output y StdErr de caracter general.  Identificados
        con numeracion de Renglon 0.  Recuerde que hay dos
        tipos de mensajes los generales y los especificos
        de renglon de pipa.
}

    StringsInput                : CAFE_TStringPipe0;
{
  StringsInput                  : Traduce cuando se requiera la pipa Input
        en listas de Strings, lo cual probablemente sea util;
        en varios procesos.
}

    StringsOutput               : CAFE_TStringPipe0;
{
  StringsOutput                 : Acumula previamente los mensajes Output
        como listas de Strings, cuando se requiera.  Muchos procedimientos
        se les permite accesar a listas de Strings, pero
        no escriben directamente al TEXT
}

    StringsStdErr               : CAFE_TStringPipe0;
{
  StringsStdErr                 : Acumula previamente los mensajes StdErr
        como listas de Strings, cuando se requiera.  Muchos procedimientos
        se les permite accesar a listas de Strings, pero
        no escriben directamente al TEXT
}

    TimerAcumulado              : TFPTimerMultiSistema unimplemented;
{
  TimerAcumulado                : Previsto para llevar el control
        de procesos acumulados
}

    TimerInterior               : TFPTimerMultiSistema unimplemented;
{
  TimerInterior                 : Previsto para sincronizar entre
        el tiempo de procesos externos e internos de la pipa,
        cuando la pipa se encuentra en estado paralelo
}

    TimerActualizar             : TFPTimerMultiSistema unimplemented;
{
  TimerActualizar               : Previsto para llevar el control
        de procesos tipo Actualizacion.  Es decir;  procesos que
        se puedan ejecutar rapidamente, y que se requieran cada
        cierto tiempo mas o menos constante.
}

    MemoriaProcesoAcumulado     : CAFE_TCollectionPipeItem unimplemented;
{
  MemoriaProcesoAcumulado       : Lista principal de PipeParametros
        como renglones a ejecutar en diferido y poco a poco
}

    MemoriaProcesoActualizar    : CAFE_TCollectionPipeItem unimplemented;
{
  MemoriaProcesoActualizar      : Ordenes de ejecucion rapida y repetida
}

    MemoriaBasic                : CAFE_TCollectionPipeItem unimplemented;
{
  MemoriaBasic                  : Ordenes a ejecutar segun identificadores
        Label secuenciales, a imitacion del basic antiguo
}

    MemoriaPivote               : CAFE_TCollectionPipeItem unimplemented;
{
  MemoriaPivote                 : Memoria de ordenes auxiliares, probablemente
        utilizado en lectura y creacion de listas temporales
}

  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
    InterfaceEjecutora          : CAFE_InterfacePipe;
{
  InterfaceEjecutora            : Encargado del trabajo Real;  es decir
        el interprete y ejecutor final de ordenes
}
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }

CONSTRUCTOR Create
  (       AOwner                : TComponent                    ); override;
{
  Constructor principal de la clase
}

DESTRUCTOR  Destroy; override;
{
  Destructor principal de la clase
}

PROCEDURE   Initialize; override;
{
  PROCEDURE Initialize
        Previsto para agregar procesos de inicializacion
        La idea es definir las caracteristicas de la pipa
        y luego aplicar initialize
}

PROCEDURE   WaitOnCompleted; virtual;
{
  PROCEDURE WaitOnCompleted
        Procedimiento principal en version preliminar de la pipa.
        Que ejecuta unicamente en modo WaitOnCompleted;
        es decir recibe la lista de ordenes y la ejecuta inmediamente
        hasta que se completa la lista completa.  E igual
        cada renglon de dicha lista.
}

  Private
FUNCTION    ReadBanderaProcesoAcumulado                         : Boolean;

  Private
FUNCTION    ReadBanderaProcesoInterior                          : Boolean;

  Private
FUNCTION    ReadBanderaProcesoActualizar                        : Boolean;

      Property
    BanderaProcesoInterior      : Boolean
                                  READ  ReadBanderaProcesoInterior;
{
  BanderaProcesoInterior        : Bandera para determinar
        si existe transicion entre procesos interiores y externos a la pipa
}

      Property
    BanderaProcesoAcumulado     : Boolean
                                  READ  ReadBanderaProcesoAcumulado;
{
  BanderaProcesoAcumulado       : Bandera para indicar solicitud de cambio
        o sobretiempo de ejecucion en un proceso acumulado
}

      Property
    BanderaProcesoActualizar    : Boolean
                                  READ  ReadBanderaProcesoActualizar;
{
  BanderaProcesoActualizar      : Bandera para indicar solicitud o retraso
        en procesos de actualizacion
}

                                  END;  { CAFE_TriplePipeMemory }

  CAFE_InterfaceTraductora      = INTERFACE ( CAFE_InterfaceBasico )
                                  [CAFE_GUIDInterfaceTraductora]
{
  Interface con la mision de traducir el lenguaje entre el usuario
        de la pipa y el interprete verdadero (InterfaceEjecutora)
        La idea es que PipeInputText, PipeOutputText, PipeStdErrText
        reciba mensajes en el idioma definitivo de pipa.
        Sin embargo, se permitira cambiar el modo de lenguaje
        con el usuario final de pipa a travez de un traductor.
        i.e. cambio de HOLA --> HELLO
        o mas profundo, utilizar sintaxis pascal o diferente...
}

FUNCTION    TraducirOrden
  ( CONST Solicitud             : String;
    VAR   Desplazado            : LongInt;
    OUT   Faltante              : Boolean       ) : CAFE_TCollectionPipeItem;
{
  FUNCTION TraducirOrden
        Recibe un String de ordenes, y lo convierte en una colecction
        de PipeItem, que probablemente se redirigiran
        a PipeInputText o similar
        La idea por ejemplo es recibir un mensaje
        en sintaxis pascal multirenglon y cambiarlo a varias
        ordenes de sintaxis de pipa
        Por ello es necesario desplazado, para ubicarse en el
        Byte adecuado, por ejemplo despues del punto y coma final
  Solicitud                     : El string a traducir, que puede
        estar conbinado con otros
  Desplazado                    : INPUT la traduccion comienza
        en Desplazado, es decir el primer CHAR mas desplazado Bytes...
        OUTPUT lo ubica para una siguiente lectura en Solicitud
  Faltante                      : TRUE indica que existen mas
        ordenes e informacion en Solicitud.  Lo que es logico
        si se cambia de ordenes de renglon a otro tipo
        de separacion
        FALSE si ya se termino
  FUNCTION TraducirOrden        : Devuelve una lista de PipeItem
        probablemente simple que corresponda
}

FUNCTION    TraduccionBiunivoca
  ( CONST Solicitud             : String                ) : ShortString;
{
  FUNCTION TraduccionBiunivoca
        En el modo BiunivocoInputMOET IN ModalidadTraductor
        Se asume que cada entrada en la pipa traductora
        corresponde a una unica entrada en la pipa ejecutora
        i.e. un simple cambio de palabras por idioma
  Solicitud                     : Lectura que se recibio en la pipa traductora
  FUNCTION TraduccionBiunivoca  : String para ser enviado a la pipa ejecutora
}

FUNCTION    TraducirRespuesta
  ( CONST Msg                   : String;
    OUT   CustomTipo            : CAFE_RespuestaEstiloPipe;
    OUT   RenglonPipe           : LongInt;
    OUT   CustomSalida          : LongInt               ) : ShortString;
{
  FUNCTION TraducirRespuesta
        Su objetivo es traducir Msg, probablemente leido
        en PipeOutputText o PipeStdErrText, en otro mensaje, o
        simplemente desaparecerlo con una salida ''.
        Las demas salidas pueden ser utiles para el administrador de
        la traduccion para tomar decisiones
  Msg                           : Mensaje a traducir en sintaxis
        de pipa corriente
  CustomTipo                    : Devuelve el tipo de mensaje traducido
  RenglonPipe                   : Devuelve el renglon de pipa traducido
  CustomSalida                  : Custom para comunicar la
        interface con alguna herencia de la pipa traductora si se requiere
  FUNCTION TraducirRespuesta    : Devuelve el mensaje a escribir
        en la salida traducida, que puede ser '', en tal caso
        probablemente no se escriba nada, ni WriteLn
}

FUNCTION    ReadAdministradorTraductor                  : TCustomApplication;
{
  FUNCTION ReadAdministradorTraductor
        Para leer la propiedad AdministradorTraductor
  FUNCTION ReadAdministradorTraductor   : devuelve la propiedad
        requerida
}

  Property
    AdministradorTraductor      : TCustomApplication
                                  Read  ReadAdministradorTraductor;
{
  AdministradorTraductor        :
        La interface probablemente requiere informacion de la pipa
        Se hace la diferencia con Administrador en otras interfaces;
        para evitar confusion en la implementacion de las mismas
}

                                  END;  { CAFE_InterfaceTraductora }

  CAFE_EstiloTraductor          = ( DirectoMOET        ,
                DirectoInputMOET  , BiunivocoInputMOET ,
                DirectoOutputMOET , DirectoStdErrMOET  ,
                StdErrToOutputMOET, SoloResultadoMOET  );
{
  CAFE_EstiloTraductor          :
        Variable para describir el tipo de traductor y caracteristicas
        fundamentales
  DirectoMoet                   : Indica un traductor completamente pasivo,
        La pipa se comporta como si no existiera.
        Las entradas y salidas se dirigen directamente a la pipa en
        formato general.  En este modo no se requiere implementar
        la interface de traduccion.
  DirectoInputMOET              : Indica un traductor en que el Input
        se dirige directamente al interprete sin traduccion
  BiunivocoInputMOET            : Indica que cada renglon de traduccion
        corresponde a un unico renglon de interprete
  DirectoOutputMOET             : Indica que en traductor el Output
        se direcciona directamente al usuario sin proceso de traduccion
  DirectoStdErrMOET             : Indica que en traductor el Output
        se direcciona directamente al usuario sin proceso de traduccion
  StdErrToOutputMOET            : El output y el StdErr de usuario
        concuerdan
  SoloResultadoMOET             : Indica que el usuario desea
        eliminar la mayoria de mensajes, y conservar resultados,
        datos y 'EXITO' 'FRACASO' 'FATAL' casi sin descripciones
        Se recomienda aplicar StdErrToOutputMOET para aumentar
        simplicidad.  Y probablemente deberia escribir y leer
        casi inmediatamente para evitar confusion.
        Este modo no necesita implementar un Traductor
        NOTA : EXITO en un proceso Load no implica que los datos
        no tengan errores.  Usted elimino los mensajes...
}

  CAFE_ConjuntoEstiloTraductor  = SET OF CAFE_EstiloTraductor;
{
  CAFE_ConjuntoEstiloTraductor  : Para manejar el tipo ordenado
        CAFE_EstiloTraductor como conjunto
}

  CAFE_TriplePipeTraductor      = CLASS ( CAFE_TriplePipeMemory )
{
  Aunque en la actualidad es completamente innecesaria, esta prevista
  para agregarle flexibilidad de sintaxis y lenguaje a la pipa
}

      Public
    BanderaDirectoSubordinado   : Boolean;
{
  BanderaDirectoSubordinado     : en estado TRUE indica como DirectoMOET
        la pasividad del traductor.  Se supone que esta es la bandera
        que se consulta y no en realidad DirectoMOET aunque
        es obligatoria la coherencia FALSE se ignora
}

    BanderaTIOStream            : Boolean;
{
  BanderaTIOStream              : en estado TRUE indica que
        PipeInput, PipeOutput y PipeStdErr son descendientes de TIOStream.
        Es decir direccionana a Input, Output y StdErr principal
}

    ModalidadTraductor          : CAFE_ConjuntoEstiloTraductor;
{
  ModalidadTraductor            : Conjunto de caracteristicas
        para describir el traductor
}

    PipeInput                   : TStream;
{
  PipeInput                     : El traductor en operacion recibiria
        la informacion aqui, y luego de traducirla la direccionaria
        a PipeInputText
}

    PipeOutput                  : TStream;
{
  PipeOutput                    : El traductor en operacion leeria
        los mensajes en PipeOutputText y los traduciria a algun
        formato y los coloca finalmente aqui para el usuario
}

    PipeStdErr                  : TStream;
{
  PipeStdErr                    : El traductor en operacion leeria
        los mensajes en PipeStdErrText y los traduciria a algun
        formato y los coloca finalmente aqui para el usuario
}

    Pipe_In                     : TextFile;
{
  Pipe_In                       : Tipo Text asociado con PipeInput,
        en algunos modos podria utilizarse para INPUT principal
        // modo BanderaTIOStream TRUE
        PipeInput       := TIOStream.Create( iosInput );
        AssignStream( Pipe_In, PipeInput );
        // Comun a los modos que soporten Reset (el Stream debe soportarlo)
        Reset( Pipe_In );
        ReadLn( Pipe_In, OrdenRenglon );
}

    Pipe_Out                    : TextFile;
{
  Pipe_Out                      : Tipo Text asociado con PipeOutput,
        en algunos modos podria utilizarse para OUTPUT principal
        // modo BanderaTIOStream TRUE
        PipeOutput      := TIOStream.Create( iosOutput );
        AssignStream( Pipe_Out, PipeOutput );
        // Comun a los modos que soporten Rewrite (el Stream debe soportarlo)
        ReWrite( Pipe_Out );
        WriteLn( Pipe_Out, PrimerMensaje );
}

    Pipe_StdErr                 : TextFile;
{
  Pipe_StdErr                   : Tipo Text asociado con PipeStdErr,
        en algunos modos podria utilizarse para OUTPUT principal
        // modo BanderaTIOStream TRUE
        PipeStdErr      := TIOStream.Create( iosStdErr );
        AssignStream( Pipe_StdErr, PipeStdErr );
        // Comun a los modos que soporten Rewrite (el Stream debe soportarlo)
        ReWrite( Pipe_StdErr );
        WriteLn( Pipe_StdErr, PrimerMensajeError );
}

    InterfaceTraductora         : CAFE_InterfaceTraductora;
{
  Traductor                     : Verdadero trabajador de la traduccion,
        que se encarga de la traduccion cuando activa.  Podria
        ser el mismo o diferente de CAFE_TripleMemory.InterfaceEjectora
}

CONSTRUCTOR Create
  (       AOwner                : TComponent                    ); override;
{
  Constructor principal de la clase
}

DESTRUCTOR  Destroy; override;
{
  Destructor principal de la clase
}

PROCEDURE   Initialize; override;
{
  PROCEDURE Initialize
        Para agregar procesos adicionales de inicializacion de la pipa
}

PROCEDURE   ResetOutWaitOnCompleted;
{
  PROCEDURE ResetOutWaitOnCompleted
        Procedimiento para preparar la lectura en Pipe_Out y Pipe_StdErr
        en modo Wait On Completed, su objetivo
        es aplicar Reset y apuntar a cero en los lectores,
        cuanto el TStream es compatible con TMemoryStream,
        El tipo TIOStream no lo requiere
}

PROCEDURE   ReWriteOutWaitOnCompleted;
{
  PROCEDURE ReWriteOutWaitOnCompleted
        Procedimiento para terminar lectura en Pipe_Out y Pipe_StdErr
        en modo WaitOnCompleted, su objetivo
        es aplicar ReWrite y aplicar TMemoryStream.Clear,
        esto inicializar los TEXT para escribir nuevamente
        en ellos mensajes.  Se deberia aplicar si lo requieren
        en los tipos compatible con TMemoryStream.
        Innecesario en TIOStream
}

PROCEDURE   WaitOnCompleted; override;
{
  PROCEDURE WaitOnCompleted
        Procedimiento principal en version preliminar de la pipa.
        Que ejecuta unicamente en modo WaitOnCompleted;
        es decir recibe la lista de ordenes y la ejecuta inmediamente
        hasta que se completa la lista completa.  E igual
        cada renglon de dicha lista.  Aqui probablemente aplica traductor
}

PROCEDURE   ResultadoWaitOnCompleted
  (       ListaRespuesta        : TStringList;
    CONST MyOrden               : ShortString;
          ListaError            : TStringList   = NIL                   );

                                  END;  { CAFE_TriplePipeTraductor }

FUNCTION    IncTiempoTom
  ( CONST AValue                : TDateTime;
    CONST ANumberOfTom          : Int64                         ) : TDateTime;
{
  FUNCTION IncTiempoTom
        Permite incrementar el TiempoTom de un valor TDateTime
        El tiempo Tom es la unidad de tiempo utilizada en CAFE.EXE
  AValue                        : Es el valor TDateTime original
  ANumberOfTom                  : Es el numero entero de tom a incrementar
  IncTiempoTom                  : Da el nuevo valor TDateTime incrementado
}

FUNCTION    CAFE_GenerarMensajeOutPut
  ( CONST MsgPreQuoted          : ShortString;
          Renglon               : LongInt;
          Repeticion            : LongInt;
          SelectorTipo          : CAFE_RespuestaEstiloPipe;
    CONST CadenaInicial         : ShortString   = ''         ) : ShortString;
{
  FUNCTION CAFE_GenerarMensajeOutPut
        Funcion generadora de mensajes para que calce con sintaxis,
        $$$$$$TIPO!!!!!!=CADENAINICIAL MSGPREQUOTED
        $$$$$$                  : Se refiere a renglon
        TIPO                    : Se refiere a SelectorTipo
        !!!!!!                  : Se refiere a Repeticion
        CadenaInicial           : Sin cambios
        MsgPreQuoted            : Sin cambios;  se asume
                que contiene mensajes, uno tras otro entrecomillados
                separados por espacios en blanco.  Podria ser solo uno
        '=', ' '                : El igual y el espacio vacio
                despues de CadenaInicial son agregados por FUNCTION siempre
        Ejemplo Renglon = 12, Repeticion = 1, SelectorTipo = FatalREPO,
                CadenaInicial = #0023 MsgPreQuoted='Archivo Inexistente'
        OUTPUT : 000012FATAL000001=#0023 'Archivo Inexistente'
  MsgPreQuoted          : Contiene uno o mas Strings separados por espacios
        vacios y que han sido previamente PreQuoted.
        Esto no se revisa simplemente se adiciona al Output
  Renglon               : Numero de renglon de pipa, 0 si general
  Repeticion            : Numero para vez de tipo de orden por renglon
        de forma que su identificador siempre sea unico por Reset
  SelectorTipo          : Para identificar el tipo de mensaje
  CadenaInicial         : Mensaje de caracteristicas descriptivas
        a agregar antes de MsgPreQuoted.  i.e. el numero de error
        en una lista compartida.
  FUNCTION CAFE_GenerarMensajeOutPut    : String de salida del
        generador de mensaje
}

FUNCTION    CAFE_GenerarMensajeOutPutCodigoNumeral
  ( CONST MsgPreQuoted          : ShortString;
          Renglon               : LongInt;
          Repeticion            : LongInt;
          SelectorTipo          : CAFE_RespuestaEstiloPipe;
          CodigoNumeral         : LongInt                    ) : ShortString;
{
  FUNCTION CAFE_GenerarMensajeOutPutCodigoNumeral
        Funcion generadora de mensajes para que calce con sintaxis,
        $$$$$$TIPO!!!!!!=#0%%%%%% MsgPreQuoted
        $$$$$$                  : Se refiere a renglon
        TIPO                    : Se refiere a SelectorTipo
        !!!!!!                  : Se refiere a Repeticion
        %%%%%%                  : Codigo numeral
        MsgPreQuoted            : Sin cambios;  se asume
                que contiene mensajes, uno tras otro entrecomillados
                separados por espacios en blanco.  Podria ser solo uno
        '=#0', ' '              : Los signos indicados
                son agregados por FUNCTION siempre
        Ejemplo Renglon = 12, Repeticion = 1, SelectorTipo = FatalREPO,
                CodigoNumeral = 23 MsgPreQuoted='Archivo Inexistente'
        OUTPUT : 000012FATAL000001=#000023 'Archivo Inexistente'
  MsgPreQuoted          : Contiene uno o mas Strings separados por espacios
        vacios y que han sido previamente PreQuoted.
        Esto no se revisa simplemente se adiciona al Output
  Renglon               : Numero de renglon de pipa, 0 si general
  Repeticion            : Numero para vez de tipo de orden por renglon
        de forma que su identificador siempre sea unico por Reset
  SelectorTipo          : Para identificar el tipo de mensaje
  CodigoNumeral         : El numero de error en una lista compartida
  FUNCTION CAFE_GenerarMensajeOutPutCodigoNumeral            :
                        String de salida del generador de mensaje
}

FUNCTION    CAFE_GenerarMensajeOutPutCodigoCasilla
  ( CONST MsgPreQuoted          : ShortString;
          Renglon               : LongInt;
          Repeticion            : LongInt;
          SelectorTipo          : CAFE_RespuestaEstiloPipe;
          Fila,
          Columna,
          ClasificacionVariante,
          CodigoNumeral         : LongInt                    ) : ShortString;
{
  FUNCTION CAFE_GenerarMensajeOutPutCodigoCasilla
        Funcion generadora de mensajes para que calce con sintaxis casilla,
        $$$$$$TIPO!!!!!!=#C(F,C,CV,CN) MsgPreQuoted
        $$$$$$                  : Se refiere a renglon
        TIPO                    : Se refiere a SelectorTipo
        !!!!!!                  : Se refiere a Repeticion
        F                       : Fila como entero positivo
        C                       : Columna como entero positivo
        CV                      : Clasificacion variable como entero positivo
        CN                      : Codigo Numeral como entero positivo
        MsgPreQuoted            : Sin cambios;  se asume
                que contiene mensajes, uno tras otro entrecomillados
                separados por espacios en blanco.  Podria ser solo uno
        '=C(', ',', ')', ' '    : Los signos indicados
                son agregados por FUNCTION siempre
        Ejemplo Renglon = 12, Repeticion = 1, SelectorTipo = FatalREPO,
                CodigoNumeral = 23 MsgPreQuoted='Archivo Inexistente'
        OUTPUT : 000012FATAL000001=#000023 'Archivo Inexistente'
  MsgPreQuoted          : Contiene uno o mas Strings separados por espacios
        vacios y que han sido previamente PreQuoted.
        Esto no se revisa simplemente se adiciona al Output
  Renglon               : Numero de renglon de pipa, 0 si general
  Repeticion            : Numero para vez de tipo de orden por renglon
        de forma que su identificador siempre sea unico por Reset
  SelectorTipo          : Para identificar el tipo de mensaje
  Fila                  : Numero de fila
  Columna               : Numero de columna
  ClasificacionVariante : Numero de clasificacion de error, o bien
        podria servir como clasificacion de tipo de dato en casilla
  CodigoNumeral         : El numero de error en una lista compartida.
        o bien como modalidad de despliegue de casilla
  FUNCTION CAFE_GenerarMensajeOutPutCodigoCasilla            :
                        String de salida del generador de mensaje
}

FUNCTION    CAFE_DescomponerMensajeOutput
  ( CONST MsgDescomponer        : ShortString;
    OUT   Renglon               : LongInt;
    OUT   Repeticion            : LongInt;
    OUT   SelectorTipo          : CAFE_RespuestaEstiloPipe;
    OUT   CadenaInicial         : ShortString           ) : CAFE_TStringList;
{
  FUNCTION CAFE_DescomponerMensajeOutput
        La idea de FUNCTION es suministrar al usuario o traductor de la pipa
        de alguna funcion sencilla de interpretacion de mensajes
        que funcione casi siempre.  No funcionaria por supuesto,
        en mensajes traducidos que no respeten el formato general
  MsgDescomponer                : Mensaje recibido OUTPUT
  Renglon                       : Renglon indicado en el mensaje
  Repeticion                    : Numero de repeticion del estilo de orden
  SelectorTipo                  : Tipo de mensaje recibido
  CadenaInicial                 : Seccion de cadena inicial del mensaje
  FUNCTION CAFE_DescomponerMensajeOutput        : Extraccion de todos
        los mensajes entrecomillados.  En caso de error devuelve NIL.
        Ningun mensaje es TStringList.Count = 0 que es muy diferente.
}

FUNCTION    CAFE_DescomponerCadenaInicialMensajeOutput
  ( CONST CadenaInicial         : ShortString;
    OUT   Estilo                : CAFE_EstiloCadenaInicial
                                                        ) : TIntegerDynArray;
{
  FUNCTION CAFE_DescomponerCadenaInicialMensajeOutput
        Se supone que Cadena Inicial consiste en una secuencia
        de numeros enteros descriptores, y un estilo.
        el estilo se devuelve en OUT Estilo
        los numeros enteros se devuelven en FUNCTION
        NoReconocidoRECI indica que no fue entendido segun los criterios
  CadenaInicial                 : Cadena a traducir
  Valores                       : El estilo detectado NoReconocidoRECI
        indica que no se detecto ningun estilo
  FUNCTION CAFE_DescomponerCadenaInicialMensajeOutput :
        devuelve un arreglo con los enteros descriptores que
        podria ser NIL (existen mensajes sin cadena inicial InexistenteRECI)
}

FUNCTION    CAFE_AnalisisMensajeOutputStdErr
  ( CONST MsgDescomponer        : ShortString;
    OUT   Renglon               : LongInt;
    OUT   Repeticion            : LongInt;
    OUT   SelectorTipo          : CAFE_RespuestaEstiloPipe;
    OUT   Estilo                : CAFE_EstiloCadenaInicial;
    OUT   ListaDescriptores     : TIntegerDynArray      ) : CAFE_TStringList;
{
  PROCEDURE CAFE_AnalisisMensajeOutputStdErr
        Este PROCEDURE brinda una forma de descomponer los mensajes Standard
        de la pipa en sus elementos constituyentes, i.e.
               ######TIPO$$$$$$=#C(F,C,CV,CN) MsgPreQuoted
        Renglon recibiria ######, Repeticion $$$$$$, SelectorTipo TIPORepo,
        Estilo CasillaRECI, ListaDescriptores [F,C,CV,CN],
        FUNCTION = extraccion de strings... en MsgPreQuotes
        La salida variara segun el estilo del mensajes,
        En la actualidad solo estan programados CasillaRECI, NumeralRECI
                e InexistenteRECI
  MsgDescomponer                : es el mensaje a descomponer en elementos
  Renglon                       : se refiere al numero de renglon de pipa
        indicado en el mensaje
  Repeticion                    : se refiere al numero de repeticion
        de tipo de mensaje en el renglon
  SelectorTipo                  : se refiere al tipo de mensaje de renglon
  Estilo                        : para identificar el estilo del mensaje
        NoReconocidoRECI indica incompatibilidad o algun error.
        InexistenteRECI no es error.  Simplemente viene el mensaje simple
        o sin mensaje del todo.
  ListaDescriptores             : Los estilos contienen numeros descriptores
        para facilitar la traduccion e identificacion del mensaje
        mediante procesamiento.
  FUNCTION CAFE_AnalisisMensajeOutputStdErr     : devuelve una lista
        de Strings de mensajes, que podria ser NIL para indicar ninguno.
        NOTA: NIL no se interpreta como error, utilice Estilo para
        detectar el error como NoReconocidoRECI
}

PROCEDURE ReWrite27
  ( VAR MyText          : TextFile;
        Control         : TMemoryStream                                 );
{
  PROCEDURE ReWrite27
        Desagradable sustitucion del ReWrite, debido a problemas.
        Se supone que se suplantara en el futuro.
        Es un punto vulnerable de incompatibilidad a futuro.
        Funcionaria solo con los tipos indicados.
        La alternativa anterior era utiliza un TMemoryStream.Clear
        conbinado con un Seek( 0, soFromBeginning ) y el Rewrite( MyText )
        pero el programa mostro inestabilidad.
}


IMPLEMENTATION

VAR
  ImplementationSintactico,
  Implementation2Sintactico             : CAFE_CharByte2Sintactico;
  ImplementationCadena27                : ShortString   =
        #26#26#26#26#26#26#26#26#26#26#26#26#26#26#26#26+
        #26#26#26#26#26#26#26#26#26#26#26#26#26#26#26#26+
        #26#26#26#26#26#26#26#26#26#26#26#26#26#26#26#26+
        #26#26#26#26#26#26#26#26#26#26#26#26#26#26#26#26+
        #26#26#26#26#26#26#26#26#26#26#26#26#26#26#26#26+
        #26#26#26#26#26#26#26#26#26#26#26#26#26#26#26#26+
        #26#26#26#26#26#26#26#26#26#26#26#26#26#26#26#26+
        #26#26#26#26#26#26#26#26#26#26#26#26#26#26#26#26;

CONST
  ImplementationTamanoSintactico        = 1000;

VAR
  ImplementationSizeReWrite27           : LongInt               = 0;

PROCEDURE ReWrite27
  ( VAR MyText          : TextFile;
        Control         : TMemoryStream                                 );
BEGIN
  IF ( ImplementationSizeReWrite27 <> 0 ) AND
     ( Control.GetSize <> ImplementationSizeReWrite27 )
  THEN Control.Size      := ImplementationSizeReWrite27;
  Control.Seek( 0, soFromBeginning );
  Close( MyText );
  ReWrite( MyText );
  Write( MyText, ImplementationCadena27 );
  Write( MyText, ImplementationCadena27 );
  Write( MyText, ImplementationCadena27 );
  Write( MyText, ImplementationCadena27 );
  Write( MyText, ImplementationCadena27 );
  Write( MyText, ImplementationCadena27 );
  Write( MyText, ImplementationCadena27 );
  Write( MyText, ImplementationCadena27 );
  ImplementationSizeReWrite27   := Control.GetSize;
  Control.Seek( 0, soFromBeginning );
  ReWrite( MyText );
END;

FUNCTION    IncTiempoTom
  ( CONST AValue                : TDateTime;
    CONST ANumberOfTom          : Int64                         ) : TDateTime;
CONST
  TomForDay                     = 70329600;

BEGIN  { FUNCTION IncTiempoTom }
  IncTiempoTom                  := AValue+ANumberOfTom/TomForDay;
END;   { FUNCTION IncTiempoTom }

CONSTRUCTOR CAFE_TCollectionPipeItem.Create;
{ virtual; }
BEGIN  { CONSTRUCTOR CAFE_TCollectionPipeItem }
  Inherited Create( NIL, CAFE_PipeParametro );
END;   { CONSTRUCTOR CAFE_TCollectionPipeItem }

DESTRUCTOR  CAFE_TCollectionPipeItem.Destroy;
{ override; }
BEGIN  { DESTRUCTOR CAFE_TCollectionPipeItem.Destroy }
  Inherited;
END;   { DESTRUCTOR CAFE_TCollectionPipeItem.Destroy }

FUNCTION    CAFE_TCollectionPipeItem.ReadItemID
  (     Ide                     : LongInt               ) : CAFE_PipeItem;
VAR
  PivoteItem                    : TCollectionItem;

BEGIN  { FUNCTION CAFE_TCollectionPipeItem.ReadItem }
  PivoteItem                    := FindItemID( Ide );
  IF PivoteItem = NIL
  THEN ReadItemID               := NIL
  ELSE ReadItemID               := PivoteItem as CAFE_PipeItem;
END;   { FUNCTION CAFE_TCollectionPipeItem.ReadItem }

CONSTRUCTOR CAFE_TStringPipe0.Create;
{ virtual; }
BEGIN  { CONSTRUCTOR CAFE_TStringPipe0.Create }
  Inherited;
  Sorted                        := FALSE;
  Duplicates                    := dupAccept;
  CaseSensitive                 := TRUE;
  NameValueSeparator            := CAFE_NameValueSeparator;
  BaseConteo                    := 0;
  BanderaBaseConteo             := TRUE;
  MoldeTStrings                 := CAFE_TStringPipe0;
END;   { CONSTRUCTOR CAFE_TStringPipe0.Create }

FUNCTION    CAFE_TStringPipe0.TijeraStrings
  (       InicioTijera, FinalTijera     : LongInt;
          EliminarOrigen        : Boolean = FALSE       ) : CAFE_TStringPipe0;
// InicioTijera y FinalTijera se numeran a partir de uno, y tomando
// en cuenta BaseConteo
VAR
  PivoteRespuesta               : CAFE_TStringPipe0;
  RecorreString                 : LongInt;

BEGIN  { FUNCTION CAFE_TStringPipe0.TijeraStrings }
  PivoteRespuesta               := MoldeTStrings.Create;
  IF BanderaBaseConteo THEN BEGIN
    InicioTijera                := InicioTijera-BaseConteo;
    FinalTijera                 := FinalTijera-BaseConteo;
  END;  { IF BanderaBaseConteo }
  IF ( InicioTijera > Count ) OR ( FinalTijera <= 0 ) THEN BEGIN
    TijeraStrings               := PivoteRespuesta;
    Exit;
  END;  { IF ( InicioTijera >= Count ) OR (FinalTijera < 0 ) }
  InicioTijera                := EnsureRange( InicioTijera, 1, Count );
  FinalTijera                 := EnsureRange( FinalTijera, 1, Count );
  IF EliminarOrigen           AND
    ( InicioTijera > 1 )      AND
    ( FinalTijera >= InicioTijera )
  THEN BanderaBaseConteo      := FALSE;
  FOR RecorreString := InicioTijera TO FinalTijera DO BEGIN
    PivoteRespuesta.Add( Strings[ RecorreString-1 ] );
  END;  { FOR RecorreString }
  IF EliminarOrigen THEN BEGIN
    FOR RecorreString := InicioTijera TO FinalTijera DO BEGIN
      Inc( BaseConteo );
      Delete( InicioTijera-1 );
    END;  { FOR RecorreString }
  END;  { IF EliminarOrigen }
  TijeraStrings                 := PivoteRespuesta;
END;   { FUNCTION CAFE_TStringPipe0.TijeraStrings }

FUNCTION    CAFE_TStringPipe0.FifoStrings                       : AnsiString;
BEGIN  { FUNCTION CAFE_TStringPipe0.FifoStrings }
  IF Count <> 0 THEN BEGIN
    FifoStrings                 := Strings[ 0 ];
    IF Objects[ 0 ] <> NIL THEN Objects[ 0 ].FreeInstance;
    Delete( 0 );
    Inc( BaseConteo );
  END ELSE BEGIN  { IF Count <> 0 ELSE }
    FifoStrings                 := '';
  END;            { IF Count <> 0 ELSE }
END;   { FUNCTION CAFE_TStringPipe0.FifoStrings }

DESTRUCTOR  CAFE_TStringPipe0.Destroy;
{ override; }
BEGIN  { CAFE_TStringPipe0.Destroy }
  BaseConteo                    := 0;
  BanderaBaseConteo             := TRUE;
  Inherited;
END;   { CAFE_TStringPipe0.Destroy }

CONSTRUCTOR CAFE_PipeItem.Create
  (       ACollection           : TCollection                           );
{ override; }
BEGIN  { CONSTRUCTOR CAFE_PipeItem.Create }
  Inherited Create( ACollection );
  OrdenString                   := '';
  PipeID                        := 0;
  ImportanciaPipe               := 0;
  TiempoPipe                    := 0;
  AuxiliarBasic                 := 0;
  DescriptorItem                := [];
END;   { CONSTRUCTOR CAFE_PipeItem.Create }

DESTRUCTOR  CAFE_PipeItem.Destroy;
{ override; }
BEGIN  { DESTRUCTOR CAFE_PipeItem.Destroy }
  OrdenString                   := '';
  PipeID                        := 0;
  ImportanciaPipe               := 0;
  TiempoPipe                    := 0;
  AuxiliarBasic                 := 0;
  DescriptorItem                := [];
  Inherited;
END;   { DESTRUCTOR CAFE_PipeItem.Destroy }

CONSTRUCTOR CAFE_PipeParametro.Create
  (       ACollection           : TCollection                           );
{ override; }
VAR
  RecorreTipo                   : CAFE_RespuestaEstiloPipe;

BEGIN  { CONSTRUCTOR CAFE_PipeParametro.Create }
  Inherited Create( ACollection );
  CuentaRegresivaPipe           := 0;
  Param1Pipe                    := 0;
  Param2Pipe                    := 0;
  Param3Pipe                    := 0;
  FOR RecorreTipo IN CAFE_RespuestaEstiloPipe
  DO ConteoRenglon[ RecorreTipo ]               := 0;
  GrupoParametro                := NIL;
  FuncionRutinaPipe             := NIL;
  FuncionResetPipe              := NIL;
  PruebaSubsistencia1           := NIL;
  PruebaSubsistencia2           := 0;
  SubLista                      := NIL;
END;   { CONSTRUCTOR CAFE_PipeParametro.Create }

DESTRUCTOR  CAFE_PipeParametro.Destroy;
{ override; }
VAR
  RecorreVariant                : LongInt;
  RecorreTipo                   : CAFE_RespuestaEstiloPipe;

BEGIN  { DESTRUCTOR CAFE_PipeParametro.Destroy }
  CuentaRegresivaPipe           := 0;
  Param1Pipe                    := 0;
  Param2Pipe                    := 0;
  Param3Pipe                    := 0;
  FOR RecorreTipo IN CAFE_RespuestaEstiloPipe
  DO ConteoRenglon[ RecorreTipo ]               := 0;
  IF GrupoParametro <> NIL
  THEN FOR RecorreVariant := Low( GrupoParametro ) TO High ( GrupoParametro )
       DO GrupoParametro[ RecorreVariant ]      := Null;
  SetLength( GrupoParametro, 0 );
  FuncionRutinaPipe             := NIL;
  FuncionResetPipe              := NIL;
  PruebaSubsistencia1           := NIL;
  PruebaSubsistencia2           := 0;
  FreeAndNil( SubLista );
  Inherited;
END;   { DESTRUCTOR CAFE_PipeParametro.Destroy }

FUNCTION    CAFE_PipeParametro.EjecutarPruebaSubsistencia       : Boolean;
{ virtual; }
VAR
  MyDoblePointer                : PPointer;
  MyPrueba                      : PPointer;
  MyObjectInterior              : TObject;

BEGIN  { FUNCTION CAFE_PipeParametro.EjecutarPruebaSubsistencia }
  IF NOT( [ ActivoPIPE, AcumuladoTimerPipe ] <=
                        DescriptorItem ) THEN Exit( FALSE );
  IF FuncionRutinaPipe = NIL THEN Exit( FALSE );
  MyDoblePointer                := Pointer( @FuncionRutinaPipe );
  MyPrueba                      := MyDoblePointer[ 1 ];
  IF PruebaSubsistencia1 <> NIL
  THEN IF PruebaSubsistencia1 <> MyPrueba^
       THEN Exit( FALSE );
  MyObjectInterior              := TObject( MyPrueba );
  // Asignacion peligrosa, la idea
  // es que MyObjectInterior apunte a la base de TObject en RAM
  // para poder aplicar GetHashCode
  IF PruebaSubsistencia2 <> 0
  THEN IF MyObjectInterior.GetHashCode <> PruebaSubsistencia2
       THEN Exit( FALSE );
  EjecutarPruebaSubsistencia    := TRUE;
END;   { FUNCTION CAFE_PipeParametro.EjecutarPruebaSubsistencia }

FUNCTION    CAFE_PipeParametro.EstablecerFuncionRutinaID
  (       SumarDescriptor       : CAFE_ConjuntoDescriptorPipeItem;
          ContadorRegresivo     : LongInt;
          FuncionRutina         : CAFE_FuncionForPipe;
          FuncionReset          : CAFE_FuncionForPipe;
          Param1                : LongInt               = 0;
          Param2                : LongInt               = 0;
          Param3                : LongInt               = 0;
          PaqueteParametro      : CAFE_MultiVariant     = NIL   ) : LongInt;
VAR
  MyObjectInterior              : TObject;
  MyPunteroEspecial             : PPointer;
  MyPPointer                    : PPointer;
  RecorreVariant                : LongInt;

BEGIN  { FUNCTION CAFE_PipeParametro.EstablecerFuncionRutinaID }
  DescriptorItem
  +=    SumarDescriptor;
  CuentaRegresivaPipe           := ContadorRegresivo;
  Param1Pipe                    := Param1;
  Param2Pipe                    := Param2;
  Param3Pipe                    := Param3;
  IF GrupoParametro <> NIL
  THEN FOR RecorreVariant := Low( GrupoParametro ) TO High ( GrupoParametro )
       DO GrupoParametro[ RecorreVariant ]      := Null;
  SetLength( GrupoParametro, 0 );
  GrupoParametro                := PaqueteParametro;
  FuncionRutinaPipe             := FuncionRutina;
  FuncionResetPipe              := FuncionReset;
  MyPunteroEspecial             := Pointer( @FuncionRutina );
  IF MyPunteroEspecial <> NIL THEN BEGIN
    MyPPointer                  := MyPunteroEspecial[ 1 ];
    PruebaSubsistencia1         := MyPPointer^;
    MyObjectInterior            := TObject( MyPPointer );
    PruebaSubsistencia2         := MyObjectInterior.GetHashCode;
    // Asignacion peligrosa
    // se asume que se logra que MyPPointer apunte
    // a la base de la clase
  END ELSE BEGIN  { IF MyPunteroEspecial <> NIL ELSE }
    PruebaSubsistencia1         := NIL;
  END;            { IF MyPunteroEspecial <> NIL ELSE }
  EstablecerFuncionRutinaID     := PipeID;
END;   { FUNCTION CAFE_PipeParametro.EstablecerFuncionRutinaID }

CONSTRUCTOR CAFE_Manejador0.Create
  (       ACollection           : TCollection                           );
{ override; }
BEGIN  { CONSTRUCTOR CAFE_Manejador0.Create }
  Inherited Create( ACollection );
  DisplayName                   := '';
END;   { CONSTRUCTOR CAFE_Manejador0.Create }

DESTRUCTOR  CAFE_Manejador0.Destroy;
{ override; }
BEGIN  { CONSTRUCTOR CAFE_Manejador0.Create }
  Inherited;
  DisplayName                   := '';
END;   { CONSTRUCTOR CAFE_Manejador0.Create }

PROCEDURE   CAFE_Manejador0.SetDisplayNameI
  (       MyName                : String                                );
{ override; }
BEGIN  { PROCEDURE CAFE_Manejador0.SetDisplayNameI }
  DisplayNameI                  := MyName;
END;   { PROCEDURE CAFE_Manejador0.SetDisplayNameI }

FUNCTION    CAFE_Manejador0.GetDisplayNameI                     : String;
{ override; }
BEGIN  { FUNCTION CAFE_Manejador0.GetDisplayNameI }
  GetDisplayNameI               := DisplayNameI;
END;   { FUNCTION CAFE_Manejador0.GetDisplayNameI }

FUNCTION    CAFE_Manejador0.
                Leer_Actual                     : TStreamCollectionItem;
BEGIN  { FUNCTION CAFE_Manejador0.Leer_Actual }
  Leer_Actual                   := Self;
END;   { FUNCTION CAFE_Manejador0.Leer_PaqueteVisible }

CONSTRUCTOR CAFE_TriplePipeMemory.Create
  (       AOwner                : TComponent                    );
{ override; }
VAR
  RecorreREPO                   : CAFE_RespuestaEstiloPipe;

BEGIN  { CONSTRUCTOR CAFE_TriplePipeMemory.Create }
  Inherited Create( AOwner );
  StopOnException               := TRUE;
  // Para excepciones no procesadas por el sistema de mensajes
  CaseSensitiveOptions          := FALSE;
  AplicacionSubordinada         := TRUE;
  BanderaWaitOnCompleted        := TRUE;
  BanderaInhabilitarBinarios    := TRUE;
  BanderaConteoPrincipalRenglon := TRUE;
  BanderaLoad                   := FALSE;
  BanderaBasic                  := FALSE;
  BanderaEcho                   := TRUE;
  ConteoPrincipalRenglon        := 0;
  PipeInputMemory               := NIL;
  PipeOutputMemory              := NIL;
  PipeStdErrMemory              := NIL;
  StringsInput                  := NIL;
  StringsOutput                 := NIL;
  StringsStdErr                 := NIL;
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
  TimerAcumulado                := 0.0;
  TimerInterior                 := 0.0;
  TimerActualizar               := 0.0;
  MemoriaProcesoAcumulado       := NIL;
  MemoriaProcesoActualizar      := NIL;
  MemoriaBasic                  := NIL;
  MemoriaPivote                 := NIL;
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
  InterfaceEjecutora            := NIL;
  FOR RecorreREPO IN CAFE_RespuestaEstiloPipe
  DO ConteoGeneral0[ RecorreREPO ]              := 0;
END;   { CONSTRUCTOR CAFE_TriplePipeMemory.Create }

DESTRUCTOR  CAFE_TriplePipeMemory.Destroy;
{ override; }
VAR
  RecorreREPO                   : CAFE_RespuestaEstiloPipe;

BEGIN  { DESTRUCTOR CAFE_TriplePipeMemory.Destroy }
  AplicacionSubordinada         := TRUE;
  BanderaWaitOnCompleted        := TRUE;
  BanderaInhabilitarBinarios    := TRUE;
  BanderaConteoPrincipalRenglon := TRUE;
  BanderaLoad                   := FALSE;
  BanderaBasic                  := FALSE;
  BanderaEcho                   := TRUE;
  ConteoPrincipalRenglon        := 0;
  FOR RecorreREPO IN CAFE_RespuestaEstiloPipe
  DO ConteoGeneral0[ RecorreREPO ]              := 0;
  Close( PipeInputText );
  Close( PipeOutputText );
  Close( PipeStdErrText );
  FreeAndNil( PipeInputMemory );
  FreeAndNil( PipeOutputMemory );
  FreeAndNil( PipeStdErrMemory );
  FreeAndNil( PipeBufferFile );
  FreeAndNil( StringsInput );
  FreeAndNil( StringsOutPut );
  FreeAndNil( StringsStdErr );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
  TimerAcumulado                := 0.0;
  TimerInterior                 := 0.0;
  TimerActualizar               := 0.0;
  FreeAndNil( MemoriaProcesoAcumulado );
  FreeAndNil( MemoriaProcesoActualizar );
  FreeAndNil( MemoriaBasic );
  FreeAndNil( MemoriaPivote );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
  InterfaceEjecutora            := NIL;
  Inherited;
  // La interface es independiente
END;   { DESTRUCTOR CAFE_TriplePipeMemory.Destroy }

PROCEDURE   CAFE_TriplePipeMemory.Initialize;
{ override; }
BEGIN  { PROCEDURE CAFE_TriplePipeMemory.Initialize }
  PipeInputMemory               := TMemoryStream.Create;
  PipeOutputMemory              := TMemoryStream.Create;
  PipeStdErrMemory              := TMemoryStream.Create;
  PipeBufferFile                := NIL;
  StringsInput                  := NIL;
  StringsOutPut                 := CAFE_TStringPipe0.Create;
  StringsStdErr                 := CAFE_TStringPipe0.Create;
  AssignStream( PipeInputText, PipeInputMemory );
  Reset( PipeInputText );
  AssignStream( PipeOutputText, PipeOutputMemory );
  ReWrite( PipeOutputText );
  ReWrite27( PipeOutputText, PipeOutputMemory as TMemoryStream );
  AssignStream( PipeStdErrText, PipeStdErrMemory );
  ReWrite( PipeStdErrText );
  ReWrite27( PipeStdErrText, PipeStdErrMemory as TMemoryStream );
  Inherited;
END;   { PROCEDURE CAFE_TriplePipeMemory.Initialize }

FUNCTION    CAFE_GenerarMensajeOutPut
  ( CONST MsgPreQuoted          : ShortString;
          Renglon               : LongInt;
          Repeticion            : LongInt;
          SelectorTipo          : CAFE_RespuestaEstiloPipe;
    CONST CadenaInicial         : ShortString   = ''         ) : ShortString;
// ######TIPO$$$$$$=CadenaInicial MsgPreQuoted
// A msg se le adicionan comillas a ClaveInicial no
// ###### = Renglon
// $$$$$$ = Repeticion

BEGIN  { FUNCTION CAFE_GenerarMensajeOutput }
  CAFE_GenerarMensajeOutput          :=
        Format( '%.*d'+CAFE_NameEstiloPipe[ SelectorTipo ]+
                '%.*d'+CAFE_NameValueSeparator+
                CadenaInicial+' '+MsgPreQuoted,
                [ CAFE_PrecisionNumeroRenglon, Renglon,
                  CAFE_PrecisionRepeticionRenglon, Repeticion ] )
END;   { FUNCTION CAFE_GenerarMensajeOutput }

FUNCTION    CAFE_GenerarMensajeOutPutCodigoNumeral
  ( CONST MsgPreQuoted          : ShortString;
          Renglon               : LongInt;
          Repeticion            : LongInt;
          SelectorTipo          : CAFE_RespuestaEstiloPipe;
          CodigoNumeral         : LongInt                    ) : ShortString;
// ######TIPO$$$$$$=#0%%%%%% MsgPreQuoted
// A msg se le adicionan comillas a ClaveInicial no
// ###### = Renglon
// $$$$$$ = Repeticion
// %%%%%% = CodigoNumeral

BEGIN  { FUNCTION CAFE_GenerarMensajeOutputCodigoNumeral }
  CAFE_GenerarMensajeOutputCodigoNumeral             :=
        Format( '%.*d'+CAFE_NameEstiloPipe[ SelectorTipo ]+
                '%.*d'+CAFE_NameValueSeparator+CAFE_InicioCodigoNumeral+
                '%.*d'+' '+MsgPreQuoted,
                [ CAFE_PrecisionNumeroRenglon, Renglon,
                  CAFE_PrecisionRepeticionRenglon, Repeticion,
                  CAFE_PrecisionListaMensajePipe, CodigoNumeral ] )
END;   { FUNCTION CAFE_GenerarMensajeOutputCodigoNumeral }

FUNCTION    CAFE_GenerarMensajeOutPutCodigoCasilla
  ( CONST MsgPreQuoted          : ShortString;
          Renglon               : LongInt;
          Repeticion            : LongInt;
          SelectorTipo          : CAFE_RespuestaEstiloPipe;
          Fila,
          Columna,
          ClasificacionVariante,
          CodigoNumeral         : LongInt                    ) : ShortString;
// ######TIPO$$$$$$=#C(F,C,CV,CN) MsgPreQuoted
// A msg se le adicionan comillas a ClaveInicial no
// ###### = Renglon
// $$$$$$ = Repeticion
// F      = Fila
// C      = Columna
// CV     = ClasificacionVariante
// CN     = CodigoNumeral

BEGIN  { FUNCTION CAFE_GenerarMensajeOutputCodigoCasilla }
  CAFE_GenerarMensajeOutputCodigoCasilla             :=
        Format( '%.*d'+CAFE_NameEstiloPipe[ SelectorTipo ]+
                '%.*d'+CAFE_NameValueSeparator+CAFE_InicioCodigoCasilla+
                '('+'%d'+','+'%d'+','+'%d'+','+'%d'+')'+' '+MsgPreQuoted,
                [ CAFE_PrecisionNumeroRenglon, Renglon,
                  CAFE_PrecisionRepeticionRenglon, Repeticion,
                  Fila, Columna, ClasificacionVariante, CodigoNumeral ] )
END;   { FUNCTION CAFE_GenerarMensajeOutputCodigoCasilla }

PROCEDURE   CAFE_TriplePipeMemory.WaitOnCompleted;
{ virtual; }
VAR
  MyError                       : CAFE_PipeFatalException;
  NuevaOrden                    : ShortString;
  MyString                      : ShortString;

BEGIN  { WaitOnCompleted }
  IF BanderaWaitOnCompleted THEN BEGIN
    IF PipeInputMemory is TMemoryStream
    THEN PipeInputMemory.Seek( 0, soFromBeginning );
    Reset( PipeInputText );
    WHILE NOT( Eof( PipeInputText ) OR Terminated ) DO BEGIN
      ReadLn( PipeInputText, NuevaOrden );
//      InterfaceEjecutora.Actual.GetInterfaceByStr
//                ( CAFE_GUIDInterfacePipe, MyInterfacePipe );
//      IF NuevaOrden <> '' THEN BEGIN
//        IF NuevaOrden[ 1 ] = #26 THEN Continue;
//      END;  { IF NuevaOrden <> '' }
      TRY
        IF BanderaConteoPrincipalRenglon THEN BEGIN
          IF ConteoPrincipalRenglon = CAFE_MaximoNumeroRenglon
          THEN ConteoPrincipalRenglon           := 0;
          Inc( ConteoPrincipalRenglon );
        END;  { IF BanderaConteoPrincipalRenglon }
        InterfaceEjecutora.EjecutarRenglonCompleted( NuevaOrden );
      EXCEPT
        ON MyError : CAFE_PipeFatalException
        DO BEGIN
          WriteLn( PipeStdErrText, CAFE_GenerarMensajeOutputCodigoNumeral
                      ( QuotedStr( MyError.Message ), 0,
                        ConteoGeneral0[ FatalREPO ], FatalREPO,
                        MyError.HelpContext ) );
          // REGLAS Para generar este error
          // Utilice internamente
          // RAISE CAFE_PipeFatalException.Create( MyHelpContext );
          //    MyHelpContext      : el numero de mensaje que usted desea
          // Por supuesto no deberia detener CAFE_FatalException antes
          // si es lo que desea
          // De esta forma lograra coherencia con todo el sistema
          // Si el mensaje necesita sustitucion previa
          // RAISE CAFE_PipeFatalException.Create( MyHelpContext, Args );
          //    Args               : array of CONST para Format
          // Si usted necesita un nuevo mensaje en lista
          // Haga esto en alguna rutina de inicializacion
          // IF NOT( CAFE_ListaMensajePipe.AgregarMensaje
          //              ( FatalREPO, MyCustomID, NuevoMensaje ) )
          // THEN WriteLn( 'MyCustomID repetido...' );
          // Formato de salida
          // 000000FATAL!!!!!!=#0HelpContext 'Message'
          //    000000          : La numeracion 0 lo clasifica
          //                      como error FATAL general
          //    !!!!!!          : Numero de error Fatal general
          //    #0              : Obligatorio para este tipo de error
          //                      Ver reglas de error
          //    HelpContext     : Se sustituye por su valor numerico
          //                      como String
          //    Message         : Se agrega las comillas que no tenian antes
          Inc( ConteoGeneral0[ FatalREPO ] );
        END;  { ON CAFE_PipeException }
      END;  { TRY }
    END;  { WHILE NOT( Eof( PipeInputText ) ) }
//    IF PipeInputMemory is TMemoryStream
//    THEN ( PipeInputMemory as TMemoryStream ).Clear;
    // No parece muy conveniente, pero es lo que ha funcionado
    // espero cambiarlo en el futuro
    ReWrite27( PipeInputText, PipeInputMemory as TMemoryStream );
    FOR MyString IN StringsOutput DO BEGIN
      WriteLn( PipeOutputText, MyString );
    END;  { FOR MyString }
    StringsOutput.Clear;
    FOR MyString IN StringsStdErr DO BEGIN
      WriteLn( PipeStdErrText, MyString );
    END;  { FOR MyString }
    StringsStdErr.Clear;
  END;  { IF BanderaWaitConpleted }
END;   { WaitOnCompleted }

CONSTRUCTOR CAFE_TriplePipeTraductor.Create
  (       AOwner                : TComponent                    );
{ override; }
BEGIN  { CONSTRUCTOR CAFE_TriplePipeTraductor.Create }
  Inherited Create( AOwner );
  BanderaDirectoSubordinado     := TRUE;
  BanderaTIOStream              := FALSE;
  ModalidadTraductor            := [ DirectoMOET ];
  PipeInput                     := NIL;
  PipeOutPut                    := NIL;
  PipeStdErr                    := NIL;
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
  InterfaceTraductora           := NIL;
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
END;   { CONSTRUCTOR CAFE_TriplePipeTraductor.Create }

DESTRUCTOR  CAFE_TriplePipeTraductor.Destroy;
{ override; }
BEGIN  { DESTRUCTOR CAFE_TriplePipeTraductor.Destroy }
  IF DirectoInputMOET IN ModalidadTraductor
  THEN PipeInput              := NIL
  ELSE BEGIN
    Close( Pipe_In );
    FreeAndNil( PipeInput );
  END;
  IF DirectoOutputMOET IN ModalidadTraductor
  THEN PipeOutput             := NIL
  ELSE BEGIN
    Close( Pipe_Out );
    FreeAndNil( PipeOutput );
  END;
  IF ( DirectoStdErrMOET  IN ModalidadTraductor ) OR
     ( StdErrToOutputMOET IN ModalidadTraductor )
  THEN PipeStdErr             := NIL
  ELSE BEGIN
    Close( Pipe_StdErr );
    FreeAndNil( PipeStdErr );
  END;
  BanderaDirectoSubordinado   := TRUE;
  BanderaTIOStream            := FALSE;
  ModalidadTraductor          := [ DirectoMOET ];
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
  InterfaceTraductora         := NIL;
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
  inherited;
END;   { DESTRUCTOR CAFE_TriplePipeTraductor.Destroy }

PROCEDURE   CAFE_TriplePipeTraductor.Initialize;
{ override; }
BEGIN  { PROCEDURE CAFE_TriplePipeTraductor.Initialize }
  IF BanderaDirectoSubordinado OR ( DirectoMOET IN ModalidadTraductor )
  THEN BEGIN
    BanderaDirectoSubordinado           := TRUE;
    ModalidadTraductor
    +=          [ DirectoMOET, DirectoInputMOET,
                  DirectoOutputMOET, DirectoStdErrMOET ];
  END ELSE BEGIN  { IF BanderaDirectoSubordinado ELSE }
    IF BanderaTIOStream THEN BEGIN
      ModalidadTraductor
      -=        [ DirectoMOET, DirectoInputMOET,
                  DirectoOutputMOET, DirectoStdErrMOET ];
      PipeInput                           := TIOStream.Create( iosInput );
      PipeOutPut                          := TIOStream.Create( iosOutput );
      IF StdErrToOutputMOET IN ModalidadTraductor
      THEN PipeStdErr                     := PipeOutput
      ELSE PipeStdErr                     := TIOStream.Create( iosError );
      AssignStream( Pipe_In, PipeInput );
      Reset( Pipe_In );
      AssignStream( Pipe_Out, PipeOutput );
      Rewrite( Pipe_Out );
      AssignStream( Pipe_StdErr, PipeStdErr );
      Rewrite( Pipe_StdErr );
    END ELSE BEGIN  { IF BanderaTIOStream ELSE }
      IF NOT ( DirectoInputMOET IN ModalidadTraductor ) THEN BEGIN
        PipeInput                       := TMemoryStream.Create;
        AssignStream( Pipe_In, PipeInput );
        Reset( Pipe_In );
      END;  { IF NOT( DirectoInputMOET IN ModalidadTraductor ) }
      IF NOT ( DirectoOutputMOET IN ModalidadTraductor ) THEN BEGIN
        PipeOutput                      := TMemoryStream.Create;
        AssignStream( Pipe_Out, PipeOutput );
        ReWrite( Pipe_Out );
        Rewrite27( Pipe_Out, PipeOutput as TMemoryStream );
      END;  { IF NOT( DirectoOutputMOET IN ModalidadTraductor ) }
      IF StdErrToOutputMOET IN ModalidadTraductor THEN BEGIN
        IF DirectoOutputMOET IN ModalidadTraductor
        THEN Include( ModalidadTraductor, DirectoStdErrMOET )
        ELSE Exclude( ModalidadTraductor, DirectoStdErrMOET );
        PipeStdErr                      := PipeOutput;
        AssignStream( Pipe_StdErr, PipeStdErr );
        ReWrite( Pipe_StdErr );
        Rewrite27( Pipe_StdErr, PipeStdErr as TMemoryStream );
      END ELSE BEGIN  { IF StdErrToOutputMOET IN ModalidadTraductor ELSE }
        IF NOT ( DirectoStdErrMOET IN ModalidadTraductor ) THEN BEGIN
          PipeStdErr                    := TMemoryStream.Create;
          AssignStream( Pipe_StdErr, PipeStdErr );
          ReWrite( Pipe_StdErr );
          Rewrite27( Pipe_StdErr, PipeStdErr as TMemoryStream );
        END;  { IF NOT( DirectoStdErrMOET IN ModalidadTraductor ) }
      END;            { IF StdErrToOutputMOET IN ModalidadTraductor ELSE }
    END;            { IF BanderaTIOStream ELSE }
  END;            { IF BanderaDirectoSubordinado ELSE }
  Inherited;
  IF DirectoInputMOET IN ModalidadTraductor THEN BEGIN
    PipeInput                           := PipeInputMemory;
    AssignStream( Pipe_In, PipeInput );
    Reset( Pipe_In );
  END;  { IF DirectoInputMOET IN ModalidadTraductor }
  IF DirectoOutputMOET IN ModalidadTraductor THEN BEGIN
    PipeOutput                          := PipeOutputMemory;
    AssignStream( Pipe_Out, PipeOutput );
    ReWrite( Pipe_Out );
    ReWrite27( Pipe_Out, PipeOutput as TMemoryStream );
  END;  { IF DirectoOutputMOET IN ModalidadTraductor }
  IF DirectoStdErrMOET IN ModalidadTraductor THEN BEGIN
    PipeOutput                          := PipeOutputMemory;
    AssignStream( Pipe_StdErr, PipeOutput );
    ReWrite( Pipe_StdErr );
    ReWrite27( Pipe_StdErr, PipeOutput as TMemoryStream );
  END;  { IF DirectoStdErrMOET IN ModalidadTraductor }
END;   { PROCEDURE CAFE_TriplePipeTraductor.Initialize }

PROCEDURE   CAFE_TriplePipeTraductor.ResetOutWaitOnCompleted;
BEGIN  { PROCEDURE CAFE_TriplePipeTraductor.ResetOutWaitOnCompleted }
  IF PipeOutput is TMemoryStream THEN BEGIN
    Reset( Pipe_Out );
    PipeOutput.Seek( 0, soFromBeginning );
  END;  { IF PipeOutput is TMemoryStream }
  IF PipeStdErr is TMemoryStream THEN BEGIN
    Reset( Pipe_StdErr );
    PipeStdErr.Seek( 0, soFromBeginning );
  END;  { IF PipeStdErr is TMemoryStream }
END;   { PROCEDURE CAFE_TriplePipeTraductor.ResetOutWaitOnCompleted }

PROCEDURE   CAFE_TriplePipeTraductor.ReWriteOutWaitOnCompleted;
BEGIN  { PROCEDURE CAFE_TriplePipeTraductor.ReWriteOutWaitOnCompleted }
  IF PipeOutput is TMemoryStream THEN BEGIN
    ReWrite27( Pipe_Out, PipeOutput as TMemoryStream );
//    ( PipeOutput as TMemoryStream ).Clear;
  END;  { IF PipeOutput is TMemoryStream }
  IF PipeStdErr is TMemoryStream THEN BEGIN
    ReWrite27( Pipe_StdErr, PipeStdErr as TMemoryStream );
//    ( PipeStdErr as TMemoryStream ).Clear;
  END;  { IF PipeStdErr is TMemoryStream }
END;   { PROCEDURE CAFE_TriplePipeTraductor.ReWriteOutWaitOnCompleted }

PROCEDURE   CAFE_TriplePipeTraductor.WaitOnCompleted;
{ override; }
VAR
  PivoteLista                   : CAFE_TStringList;
  PivoteMsg,
  NuevoMsg,
  NuevoInput                    : ShortString;
  ListaDescriptores             : TIntegerDynArray;
  Renglon,
  Repeticion,
  RenglonPipe,
  CustomSalida                  : LongInt;
  SelectorTipo,
  CustomTipo                    : CAFE_RespuestaEstiloPipe;
  Estilo                        : CAFE_EstiloCadenaInicial;

BEGIN  { PROCEDURE CAFE_TriplePipeTraductor.WaitOnCompleted }
  IF NOT( DirectoInputMOET IN ModalidadTraductor ) THEN BEGIN
    IF NOT( BiunivocoInputMOET IN ModalidadTraductor)
    THEN Include( ModalidadTraductor, BiunivocoInputMOET );
    IF PipeInput is TMemoryStream
    THEN BEGIN
      PipeInput.Seek( 0, soFromBeginning );
      Reset( Pipe_In );
    END;  { IF PipeInput is TMemoryStream }
//    IF PipeInputMemory is TMemoryStream
//    THEN ( PipeInputMemory as TMemoryStream ).Clear;
    ReWrite27( PipeInputText, PipeInputMemory as TMemoryStream );
    IF BanderaTIOStream  THEN BEGIN
      ReadLn( Pipe_In, NuevoInput );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
      IF InterfaceTraductora <> NIL
      THEN NuevoMsg                             :=
                InterfaceTraductora.TraduccionBiunivoca( NuevoInput )
      ELSE NuevoMsg             := NuevoInput;
      WriteLn( PipeInputText, NuevoMsg );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
    END ELSE BEGIN  { IF BanderaTIOStream ELSE }
      WHILE NOT( EOF( Pipe_In ) OR Terminated ) DO BEGIN
        ReadLn( Pipe_In, NuevoInput );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
        IF InterfaceTraductora <> NIL
        THEN NuevoMsg                             :=
                  InterfaceTraductora.TraduccionBiunivoca( NuevoInput )
        ELSE NuevoMsg             := NuevoInput;
        WriteLn( PipeInputText, NuevoMsg );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
      END;  { WHILE NOT( EOF( Pipe_In ) ) }
    END;            { IF BanderaTIOStream ELSE }
    IF PipeInput is TMemoryStream
    THEN BEGIN
//      ( PipeInput as TMemoryStream ).Clear;
      ReWrite27( Pipe_In, PipeInput as TMemoryStream );
    END;  { IF PipeInput is TMemoryStream }
  END;  { IF NOT( DirectoInputMOET IN ModalidadTraductor ) }
  Inherited;
  IF SoloResultadoMOET IN ModalidadTraductor THEN BEGIN
    IF NOT( DirectoOutputMOET IN ModalidadTraductor ) THEN BEGIN
      IF PipeOutputMemory is TMemoryStream
      THEN PipeOutputMemory.Seek( 0, soFromBeginning );
      Reset( PipeOutputText );
      WHILE NOT( EOF( PipeOutputText ) ) DO BEGIN
        ReadLn( PipeOutputText, NuevoMsg );
        PivoteLista             := CAFE_AnalisisMensajeOutputStdErr
                ( NuevoMsg, Renglon, Repeticion, SelectorTipo,
                  Estilo, ListaDescriptores );
        IF PivoteLista <> NIL THEN BEGIN
          SetLength( ListaDescriptores, 0 );
          PivoteMsg             := '';
          CASE SelectorTipo OF
            ResultREPO            : PivoteMsg     := PivoteLista[ 0 ];
            DatoREPO              : PivoteMsg     := PivoteLista[ 0 ];
            NombreREPO            : PivoteMsg     := PivoteLista[ 0 ];
            ExitoREPO             : PivoteMsg     := 'EXITO';
          END;  { CASE SelectorTipo }
          IF PivoteMsg <> '' THEN WriteLn( Pipe_Out, PivoteMsg );
        END;  { IF PivoteLista <> NIL }
        FreeAndNIL( PivoteLista );
      END;  { WHILE NOT( EOF( PipeOutText ) ) }
//      IF PipeOutputMemory is TMemoryStream
//      THEN ( PipeOutputMemory as TMemoryStream ).Clear;
      ReWrite27( PipeOutputText, PipeOutputMemory as TMemoryStream );
    END;  { IF NOT( DirectoOutputMOET IN ModalidadTraductor ) }
    IF NOT( DirectoStdErrMOET IN ModalidadTraductor ) THEN BEGIN
      IF PipeStdErrMemory is TMemoryStream
      THEN PipeStdErrMemory.Seek( 0, soFromBeginning );
      Reset( PipeStdErrText );
      WHILE NOT( EOF( PipeStdErrText ) ) DO BEGIN
        ReadLn( PipeStdErrText, NuevoMsg );
        PivoteLista             := CAFE_AnalisisMensajeOutputStdErr
                ( NuevoMsg, Renglon, Repeticion, SelectorTipo,
                  Estilo, ListaDescriptores );
        IF PivoteLista <> NIL THEN BEGIN
          SetLength( ListaDescriptores, 0 );
          PivoteMsg             := '';
          CASE SelectorTipo OF
            FracasoREPO         : PivoteMsg     := 'FRACASO';
            FatalREPO           : PivoteMsg     := 'FATAL';
          END;  { CASE SelectorTipo }
          IF PivoteMsg <> '' THEN WriteLn( Pipe_StdErr, PivoteMsg );
        END;  { IF PivoteLista <> NIL }
        FreeAndNIL( PivoteLista );
      END;  { WHILE NOT( EOF( PipeOutText ) ) }
//      IF PipeStdErrMemory is TMemoryStream
//      THEN ( PipeStdErrMemory as TMemoryStream ).Clear;
      ReWrite27( PipeStdErrText, PipeStdErrMemory as TMemoryStream );
    END;  { IF NOT( DirectoStdErrMOET IN ModalidadTraductor ) }
  END ELSE BEGIN  { IF SoloResultadoMOET IN ModalidadTraductor }
    IF NOT( DirectoOutputMOET IN ModalidadTraductor ) THEN BEGIN
      IF PipeOutputMemory is TMemoryStream
      THEN PipeOutputMemory.Seek( 0, soFromBeginning );
      Reset( PipeOutputText );
      WHILE NOT( EOF( PipeOutputText ) ) DO BEGIN
        ReadLn( PipeOutputText, NuevoMsg );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
        IF InterfaceTraductora <> NIL
        THEN PivoteMsg                            :=
                  InterfaceTraductora.TraducirRespuesta
                ( NuevoMsg, CustomTipo, RenglonPipe, CustomSalida )
        ELSE PivoteMsg            := NuevoMsg;
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
        IF PivoteMsg <> '' THEN WriteLn( Pipe_Out, PivoteMsg );
      END;  { WHILE NOT( EOF( PipeOutText ) ) }
//      IF PipeOutputMemory is TMemoryStream
//      THEN ( PipeOutputMemory as TMemoryStream ).Clear;
      ReWrite27( PipeOutputText, PipeOutputMemory as TMemoryStream );
    END;  { IF NOT( DirectoOutputMOET IN ModalidadTraductor ) }
    IF NOT( DirectoStdErrMOET IN ModalidadTraductor ) THEN BEGIN
      IF PipeStdErrMemory is TMemoryStream
      THEN PipeStdErrMemory.Seek( 0, soFromBeginning );
      Reset( PipeStdErrText );
      WHILE NOT( EOF( PipeStdErrText ) ) DO BEGIN
        ReadLn( PipeStdErrText, NuevoMsg );
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    OFF             }
  {$ENDIF                       }
        IF InterfaceTraductora <> NIL
        THEN PivoteMsg                            :=
                  InterfaceTraductora.TraducirRespuesta
                ( NuevoMsg, CustomTipo, RenglonPipe, CustomSalida )
        ELSE PivoteMsg            := NuevoMsg;
  {$IFDEF       SILENCIAR       }
  {$WARNINGS    ON              }
  {$ENDIF                       }
        IF PivoteMsg <> '' THEN WriteLn( Pipe_StdErr, PivoteMsg );
      END;  { WHILE NOT( EOF( PipeOutText ) ) }
//      IF PipeStdErrMemory is TMemoryStream
//      THEN ( PipeStdErrMemory as TMemoryStream ).Clear;
      ReWrite27( PipeStdErrText, PipeStdErrMemory as TMemoryStream );
    END;  { IF NOT( DirectoStdErrMOET IN ModalidadTraductor ) }
  END;            { IF SoloResultadoMOET IN ModalidadTraductor }
END;   { PROCEDURE CAFE_TriplePipeTraductor.WaitOnCompleted }

FUNCTION    CAFE_TriplePipeMemory.ReadBanderaProcesoInterior    : Boolean;
BEGIN  { FUNCTION ...ReadBanderaProcesoInterior }
  ReadBanderaProcesoInterior    := FALSE;
END;   { FUNCTION ...ReadBanderaProcesoInterior }

FUNCTION    CAFE_TriplePipeMemory.ReadBanderaProcesoAcumulado   : Boolean;
BEGIN  { FUNCTION ...ReadBanderaProcesoAcumulado }
  ReadBanderaProcesoAcumulado   := FALSE;
END;   { FUNCTION ...ReadBanderaProcesoAcumulado }

FUNCTION    CAFE_TriplePipeMemory.ReadBanderaProcesoActualizar  : Boolean;
BEGIN  { FUNCTION ...ReadBanderaProcesoActualizar }
  ReadBanderaProcesoActualizar  := FALSE;
END;   { FUNCTION ...ReadBanderaProcesoActualizar }

CONSTRUCTOR CAFE_TListaMensajePipe.Create;
{ virtual; }
BEGIN  { CONSTRUCTOR CAFE_TListaMensajePipe.Create }
  inherited;
  Sorted                        := TRUE;
  Duplicates                    := dupError;
  CaseSensitive                 := TRUE;
  NameValueSeparator            := CAFE_NameValueSeparator;
END;   { CONSTRUCTOR CAFE_TListaMensajePipe.Create }

DESTRUCTOR  CAFE_TListaMensajePipe.Destroy;
{ override; }
BEGIN  { DESTRUCTOR CAFE_TListaMensajePipe.Done }
  inherited;
END;   { DESTRUCTOR CAFE_TListaMensajePipe.Done }

FUNCTION    CAFE_TListaMensajePipe.AgregarMensajeMultiple
  (       TypeMsg               : CAFE_RespuestaEstiloPipe;
          IDClave               : LongInt;
    CONST Msg                   : ShortString                   ) : Boolean;
VAR
  PivoteRespuesta               : Boolean;

BEGIN  { FUNCTION CAFE_TListaMensajePipe.AgregarMensajeMultiple }
  IF TypeMsg = MensajeREPO THEN BEGIN
    PivoteRespuesta             :=
        AgregarMensaje( MensajeREPO, IDClave, Msg );
    IF PivoteRespuesta
    THEN PivoteRespuesta        :=
        AgregarMensaje( MensajeLoadREPO, IDClave, Msg );
    IF PivoteRespuesta
    THEN PivoteRespuesta        :=
        AgregarMensaje( MensajeTXTREPO, IDClave, Msg );
    AgregarMensajeMultiple      := PivoteRespuesta;
  END ELSE BEGIN  { IF TypeMsg = MensajeREPO ELSE }
    IF TypeMsg = ErrorREPO THEN BEGIN
      PivoteRespuesta             :=
          AgregarMensaje( ErrorREPO, IDClave, Msg );
      IF PivoteRespuesta
      THEN PivoteRespuesta        :=
          AgregarMensaje( ErrorLoadREPO, IDClave, Msg );
      IF PivoteRespuesta
      THEN PivoteRespuesta        :=
          AgregarMensaje( ErrorTXTREPO, IDClave, Msg );
      AgregarMensajeMultiple      := PivoteRespuesta;
    END ELSE BEGIN  { IF TypeMsg = ErrorREPO ELSE }
      AgregarMensajeMultiple      :=
          AgregarMensaje( TypeMsg, IDClave, Msg );
    END;            { IF TypeMsg = ErrorREPO ELSE }
  END;            { IF TypeMsg = MensajeREPO ELSE }
END;   { FUNCTION CAFE_TListaMensajePipe.AgregarMensajeMultiple }

FUNCTION    CAFE_TListaMensajePipe.AgregarMensaje
  (       TypeMsg               : CAFE_RespuestaEstiloPipe;
          IDClave               : LongInt;
    CONST Msg                   : ShortString                   ) : Boolean;
VAR
  PivoteString                  : ShortString;
BEGIN  { FUNCTION CAFE_TListaMensajePipe.AgregarMensaje }
  IF IDClave <= 0 THEN BEGIN
    AgregarMensaje              := FALSE;
    Exit;
  END;  { IF IDClave >= 0 }
  PivoteString                  :=
                Format( CAFE_NameEstiloPipe[ TypeMsg ]+'%.*d',
                        [ CAFE_PrecisionListaMensajePipe, IDClave ] );
  IF Values[ PivoteString ] <> '' THEN BEGIN
    AgregarMensaje              := FALSE;
    Exit;
  END;  { IF Value[ PivoteString ] <> '' }
  Add( PivoteString+CAFE_NameValueSeparator+Msg );
  AgregarMensaje                := TRUE;
END;   { FUNCTION CAFE_TListaMensajePipe.AgregarMensaje }

FUNCTION    CAFE_TListaMensajePipe.LeerMensaje
  (       TypeMsg               : CAFE_RespuestaEstiloPipe;
          IDClave               : LongInt               ) : ShortString;
VAR
  PivoteString                  : ShortString;

BEGIN  { FUNCTION CAFE_TListaMensajePipe.LeerMensaje }
  PivoteString                  :=
                Format( CAFE_NameEstiloPipe[ TypeMsg ]+'%.*d',
                        [ CAFE_PrecisionListaMensajePipe, IDClave ] );
  LeerMensaje                   := Values[ PivoteString ];
END;   { FUNCTION CAFE_TListaMensajePipe.LeerMensaje }

FUNCTION    CAFE_TListaMensajePipe.LeerMensaje
  (       TypeMsg               : CAFE_RespuestaEstiloPipe;
          IDClave               : LongInt;
    CONST Args                  : array of Const        ) : ShortString;
VAR
  PivoteString                  : ShortString;

BEGIN  { FUNCTION CAFE_TListaMensajePipe.LeerMensaje }
  PivoteString                  :=
                Format( CAFE_NameEstiloPipe[ TypeMsg ]+'%.*d',
                        [ CAFE_PrecisionListaMensajePipe, IDClave ] );
  TRY
    PivoteString                := Format( Values[ PivoteString ], Args );
  EXCEPT
    ON EConvertError
    DO PivoteString             := '';
  END;  { TRY }
  LeerMensaje                   := PivoteString;
END;   { FUNCTION CAFE_TListaMensajePipe.LeerMensaje }

CONSTRUCTOR CAFE_PipeFatalException.Create
  (       MyHelpContext : LongInt                                       );
{ virtual; }
VAR
  PivoteString                  : ShortString;

BEGIN  { CONSTRUCTOR CAFE_PipeFatalException.Create }
  TypeException         := FatalREPO;
  PivoteString          :=
                Format( CAFE_NameEstiloPipe[ FatalREPO ]+'%.*d',
                        [ CAFE_PrecisionListaMensajePipe, MyHelpContext ] );
  Message               := CAFE_ListaMensajePipe.Values[ PivoteString ];
  IF Message <> '' THEN HelpContext             := MyHelpContext;
END;   { CONSTRUCTOR CAFE_PipeFatalException.Create }

CONSTRUCTOR CAFE_PipeFatalException.Create
  (       MyHelpContext : LongInt;
    CONST Args          : array of Const                        );
{ virtual; }
VAR
  PivoteString                  : ShortString;

BEGIN  { CONSTRUCTOR CAFE_PipeFatalException.Create }
  TypeException         := FatalREPO;
  PivoteString          :=
                Format( CAFE_NameEstiloPipe[ FatalREPO ]+'%.*d',
                        [ CAFE_PrecisionListaMensajePipe, MyHelpContext ] );
  PivoteString          := CAFE_ListaMensajePipe.Values[ PivoteString ];
  TRY
    PivoteString        := Format( PivoteString, Args );
  EXCEPT
    ON EConvertError
    DO PivoteString     := '';
  END;
  Message               := PivoteString;
  IF Message <> '' THEN HelpContext             := MyHelpContext;
END;   { CONSTRUCTOR CAFE_PipeFatalException.Create }

DESTRUCTOR  CAFE_PipeFatalException.Destroy;
{ override; }
BEGIN  { DESTRUCTOR CAFE_PipeFatalException.Destroy }
END;   { DESTRUCTOR CAFE_PipeFatalException.Destroy }

CONSTRUCTOR CAFE_PipeException.Create
  (       TypeMsg       : CAFE_RespuestaEstiloPipe;
          MyHelpContext : LongInt                                       );
{ virtual; }
VAR
  PivoteString          : ShortString;

BEGIN  { CONSTRUCTOR CAFE_PipeException.Create }
  TypeException         := ErrorREPO;
  PivoteString          :=
                Format( CAFE_NameEstiloPipe[ TypeMsg ]+'%.*d',
                        [ CAFE_PrecisionListaMensajePipe, MyHelpContext ] );
  Message               := CAFE_ListaMensajePipe.Values[ PivoteString ];
  IF Message <> '' THEN BEGIN
    HelpContext             := MyHelpContext;
    TypeException           := TypeMsg;
  END;  { IF Message <> '' }
END;   { CONSTRUCTOR CAFE_PipeException.Create }

CONSTRUCTOR CAFE_PipeException.Create
  (       TypeMsg       : CAFE_RespuestaEstiloPipe;
          MyHelpContext : LongInt;
    CONST Args          : array of Const                                );
{ virtual; }
VAR
  PivoteString          : ShortString;

BEGIN  { CONSTRUCTOR CAFE_PipeException.Create }
  TypeException         := ErrorREPO;
  PivoteString          :=
                Format( CAFE_NameEstiloPipe[ TypeMsg ]+'%.*d',
                        [ CAFE_PrecisionListaMensajePipe, MyHelpContext ] );
  PivoteString          := CAFE_ListaMensajePipe.Values[ PivoteString ];
  TRY
    PivoteString        := Format( PivoteString, Args );
  EXCEPT
    ON EConvertError
    DO PivoteString     := '';
  END;
  Message               := PivoteString;
  IF Message <> '' THEN BEGIN
    HelpContext             := MyHelpContext;
    TypeException           := TypeMsg;
  END;  { IF Message <> '' }
END;   { CONSTRUCTOR CAFE_PipeException.Create }

DESTRUCTOR  CAFE_PipeException.Destroy;
{ override; }
BEGIN  { DESTRUCTOR CAFE_PipeException.Destroy }
END;   { DESTRUCTOR CAFE_PipeException.Destroy }

CONSTRUCTOR CAFE_PipeCasillaException.Create
  (       Fila,
          Columna       : LongInt;
          EstiloMsg     : CAFE_PipeEstiloCasillaMsg;
          MyHelpContext : LongInt;
          BanderaLoad   : Boolean       = FALSE                         );
{ virtual; }
BEGIN  { CONSTRUCTOR CAFE_PipeCasillaException.Create }
  Inherited Create( ErrorREPO, MyHelpContext );
  FilaReferencia        := Fila;
  ColumnaReferencia     := Columna;
  EstiloMsgReferencia   := EstiloMsg;
  BanderaPermitirLoad   := BanderaLoad;
END;   { CONSTRUCTOR CAFE_PipeCasillaException.Create }

CONSTRUCTOR CAFE_PipeCasillaException.Create
  (       Fila,
          Columna       : LongInt;
          EstiloMsg     : CAFE_PipeEstiloCasillaMsg;
          MyHelpContext : LongInt;
    CONST Args          : array of Const;
          BanderaLoad   : Boolean       = FALSE                         );
{ virtual; }
BEGIN  { CONSTRUCTOR CAFE_PipeCasillaException.Create }
  Inherited Create( ErrorREPO, MyHelpContext, Args );
  FilaReferencia        := Fila;
  ColumnaReferencia     := Columna;
  EstiloMsgReferencia   := EstiloMsg;
  BanderaPermitirLoad   := BanderaLoad;
END;   { CONSTRUCTOR CAFE_PipeCasillaException.Create }

FUNCTION    CAFE_DescomponerMensajeOutput
  ( CONST MsgDescomponer        : ShortString;
    OUT   Renglon               : LongInt;
    OUT   Repeticion            : LongInt;
    OUT   SelectorTipo          : CAFE_RespuestaEstiloPipe;
    OUT   CadenaInicial         : ShortString           ) : CAFE_TStringList;
VAR
  MyStringList                  : CAFE_TStringList;
  PivoteString                  : ShortString;
  PosicionFinal,
  PosicionActual                : LongInt;
  PosComilla,
  PosPivote                     : Byte;
  BanderaTipo                   : Boolean;

LABEL
  SalidaFalsa;

BEGIN  { FUNCTION CAFE_DescomponerMensajeOutput }
  MyStringList                  := NIL;
  PosPivote                     :=
                AnsiPos( CAFE_NameValueSeparator, MsgDescomponer );
  IF PosPivote <=
       ( CAFE_PrecisionNumeroRenglon+CAFE_PrecisionRepeticionRenglon+1 )
  THEN GOTO SalidaFalsa;
  PivoteString                  :=
        Copy( MsgDescomponer, 1, CAFE_PrecisionNumeroRenglon );
  TRY
    Renglon                     := StrToInt( PivoteString );
  EXCEPT
    ON EConvertError
    DO BEGIN
      CAFE_DescomponerMensajeOutput             := NIL;
      Exit;
    END;  { ON EConvertError }
  END;  { TRY }
  IF PosPivote <= CAFE_PrecisionRepeticionRenglon THEN GOTO SalidaFalsa;
  PivoteString                  :=
        Copy( MsgDescomponer, PosPivote-CAFE_PrecisionRepeticionRenglon,
                                        CAFE_PrecisionRepeticionRenglon );
  TRY
    Repeticion                  := StrToInt( PivoteString );
  EXCEPT
    ON EConvertError
    DO BEGIN
      CAFE_DescomponerMensajeOutput             := NIL;
      Exit;
    END;  { ON EConvertError }
  END;  { TRY }
  PivoteString                  :=
        Copy( MsgDescomponer, CAFE_PrecisionNumeroRenglon+1,
                        PosPivote-CAFE_PrecisionNumeroRenglon
                        -CAFE_PrecisionRepeticionRenglon-1 );
  BanderaTipo                   := FALSE;
  FOR SelectorTipo IN CAFE_RespuestaEstiloPipe DO BEGIN
    IF PivoteString = CAFE_NameEstiloPipe[ SelectorTipo ] THEN  BEGIN
      BanderaTipo               := TRUE;
      Break;
    END;  { FOR SelectorTipo IN CAFE_RespuestaEstiloPipe }
  END;  { FOR RecorreTipo IN CAFE_RespuestaEstiloPipe }
  IF NOT( BanderaTipo ) THEN GOTO SalidaFalsa;
  PosComilla                    := AnsiPos( '''', MsgDescomponer );
  MyStringList                  := TStringList.Create;
  MyStringList.Sorted           := FALSE;
  IF PosComilla <> 0 THEN BEGIN
    // NOTA : AnsiExtractQuotedStr de FPC.exe
    // no hace nada si la comilla es interior, pero trabaja
    // bien en los limites
    // FPC 2.4.2. Dic 2011
    IF PosComilla <= PosPivote THEN GOTO SalidaFalsa;
    CadenaInicial               :=
        Trim( Copy( MsgDescomponer, PosPivote+1, PosComilla-PosPivote-1 ) );
    Implementation2Sintactico.InsertarString( MsgDescomponer );
    PosicionActual              := 0;
    PosicionFinal               := 0;
    WHILE ImplementationSintactico.ExtraccionByteDuplicadoString
        ( Implementation2Sintactico, PosicionActual, PosicionFinal,
          CAFE_ByteStringSintactico, FALSE ) DO BEGIN
      MyStringList.Add( ImplementationSintactico.MemoriaVector );
      PosicionActual            := PosicionFinal;
    END;  { WHILE ExtraccionByteDuplicadoString }
    IF CAFE_IntentoInfructuosoSintactico THEN GOTO SalidaFalsa;
  END ELSE BEGIN  { IF PosComilla <> 0 ELSE }
    CadenaInicial               :=
        Trim( Copy( MsgDescomponer, PosPivote+1, Length( MsgDescomponer ) ) );
  END;            { IF PosComilla <> 0 ELSE }
  CAFE_DescomponerMensajeOutput := MyStringList;
  Exit;
SalidaFalsa :
  FreeAndNIL( MyStringList );
  CAFE_DescomponerMensajeOutput := NIL;
END;   { FUNCTION CAFE_DescomponerMensajeOutput }

FUNCTION    CAFE_DescomponerCadenaInicialMensajeOutput
  ( CONST CadenaInicial         : ShortString;
    OUT   Estilo                : CAFE_EstiloCadenaInicial
                                                        ) : TIntegerDynArray;
VAR
  PivoteRespuesta               : CAFE_EstiloCadenaInicial;
  PivoteCadena,
  PivoteString                  : ShortString;
  Valores                       : TIntegerDynArray;
  Valor1                        : LongInt;
  PivoteInicioParentesis,
  PivoteFinParentesis           : Byte;

LABEL
  SalidaFinal;

    { ANIDADO }
  FUNCTION    AnidadoExtraerLongInt
    ( CONST MyCadena            : AnsiString            ) : TIntegerDynArray;
  VAR
    AnidadoString,
    PivoteCadena                : AnsiString;
    PivoteLista                 : TIntegerDynArray;
    PosComa,
    ConteoInterno               : LongInt;

  CONST
    MaxInterno                  = 15;

  BEGIN  { FUNCTION AnidadoExtraerLongInt }
    SetLength( PivoteLista, MaxInterno );
    ConteoInterno               := 0;
    PivoteCadena                := MyCadena;
    REPEAT
      PosComa                   := AnsiPos( ',' , PivoteCadena );
      IF PosComa = 0
      THEN AnidadoString        := PivoteCadena
      ELSE BEGIN  { IF PosComa = 0 ELSE }
        AnidadoString           := Copy( PivoteCadena, 1, PosComa-1 );
        PivoteCadena            :=
                Copy( PivoteCadena, PosComa+1, Length( PivoteCadena ) );
      END;        { IF PosComa = 0 ELSE }
      TRY
        PivoteLista[ ConteoInterno ]            := StrToInt( AnidadoString );
        Inc( ConteoInterno );
        IF ConteoInterno = MaxInterno
        THEN RAISE EConvertError.Create( 'EXCESO PARAMETROS' );
      EXCEPT
        ON EConvertError
        DO BEGIN
          SetLength( PivoteLista, 0 );
          AnidadoExtraerLongInt                 := NIL;
          Exit;
        END;  { ON EConvertError }
      END;  { TRY }
    UNTIL PosComa       = 0;
    AnidadoExtraerLongInt               :=
                        Copy( PivoteLista, 0, ConteoInterno );
    SetLength( PivoteLista, 0 );
  END;   { FUNCTION AnidadoExtraerLongInt }
    { ANIDADO }

BEGIN  { CAFE_DescomponerCadenaInicialMensajeOutput }
  PivoteRespuesta               := NoReconocidoRECI;
  SetLength( Valores, 0 );
  IF CadenaInicial = '' THEN BEGIN
    Estilo                      := InexistenteRECI;
    CAFE_DescomponerCadenaInicialMensajeOutput  := NIL;
    Exit;
  END;  { IF PivoteString}
  PivoteString                  := Copy( CadenaInicial, 1, 2 );
  IF PivoteString = CAFE_InicioCodigoNumeral THEN BEGIN
    PivoteString                :=
                Copy( CadenaInicial, 2, Length( CadenaInicial ) );
    TRY
      Valor1                    := StrToInt( PivoteString );
    EXCEPT
      CAFE_DescomponerCadenaInicialMensajeOutput        := NIL;
      Estilo                    := NoReconocidoRECI;
      Exit;
    END;  { TRY }
    SetLength( Valores, 1 );
    Valores[ 0 ]                := Valor1;
    PivoteRespuesta             := NumeralRECI;
  END;  { IF PivoteString = CAFE_InicioCodigoNumeral }
  PivoteInicioParentesis        := AnsiPos( '(', CadenaInicial );
  PivoteFinParentesis           := AnsiPos( ')', CadenaInicial );
  IF ( PivoteInicioParentesis = 3 ) AND
     ( PivoteFinParentesis    = Length( CadenaInicial ) ) THEN BEGIN
    PivoteCadena                :=
              Copy( CadenaInicial, 4, Length( CadenaInicial )-4 );
    Valores                     := AnidadoExtraerLongInt( PivoteCadena );
    IF Valores = NIL THEN GOTO SalidaFinal;
    IF PivoteString = CAFE_InicioCodigoCasilla THEN BEGIN
      IF Length( Valores ) <> 4 THEN GOTO SalidaFinal;
      PivoteRespuesta           := CasillaRECI;
    END;  { IF PivoteString = CAFE_InicioCodigoCasilla }
    IF PivoteRespuesta = NoReconocidoRECI THEN SetLength( Valores, 0 );
  END;  { IF ( PivoteInicioParentesis = 3 ) AND ... }
SalidaFinal :
  Estilo                        := PivoteRespuesta;
  CAFE_DescomponerCadenaInicialMensajeOutput            := Valores;
END;   { CAFE_DescomponerCadenaInicialMensajeOutput }

FUNCTION    CAFE_AnalisisMensajeOutputStdErr
  ( CONST MsgDescomponer        : ShortString;
    OUT   Renglon               : LongInt;
    OUT   Repeticion            : LongInt;
    OUT   SelectorTipo          : CAFE_RespuestaEstiloPipe;
    OUT   Estilo                : CAFE_EstiloCadenaInicial;
    OUT   ListaDescriptores     : TIntegerDynArray      ) : CAFE_TStringList;
VAR
  CadenaInicial                 : ShortString;
  PivoteListaString             : CAFE_TStringList;
  PivoteListaEntera             : TIntegerDynArray;

BEGIN  { FUNCTION CAFE_AnalisisMensajeOutputStdErr }
  ListaDescriptores             := NIL;
  PivoteListaString             := CAFE_DescomponerMensajeOutput
    ( MsgDescomponer, Renglon, Repeticion, SelectorTipo, CadenaInicial );
  IF PivoteListaString <> NIL THEN BEGIN
    PivoteListaEntera           := CAFE_DescomponerCadenaInicialMensajeOutput
                                   ( CadenaInicial, Estilo );
    ListaDescriptores           := PivoteListaEntera;
  END;  { IF PivoteListaString <> NIL }
  CAFE_AnalisisMensajeOutputStdErr      := PivoteListaString;
END;   { FUNCTION CAFE_AnalisisMensajeOutputStdErr }

PROCEDURE   CAFE_TriplePipeTraductor.ResultadoWaitOnCompleted
  (       ListaRespuesta        : TStringList;
    CONST MyOrden               : ShortString;
          ListaError            : TStringList   = NIL                   );
VAR
  UnaCadena                     : ShortString;

BEGIN  { FUNCTION CAFE_TriplePipeTraductor.ResultadoWaitOnCompleted }
  WriteLn( Pipe_In, MyOrden );
  WaitOnCompleted;
  ResetOutWaitOnCompleted;
  WHILE NOT( Eof( Pipe_Out ) ) DO BEGIN
    ReadLn( Pipe_Out, UnaCadena );
    ListaRespuesta.Add( UnaCadena );
  END;  { WHILE NOT( Eof( Pipe_Out ) ) }
  IF ListaError = NIL THEN BEGIN
    WHILE NOT( Eof( Pipe_StdErr ) ) DO BEGIN
      ReadLn( Pipe_StdErr, UnaCadena );
      ListaRespuesta.Add( UnaCadena );
    END;  { WHILE NOT( Eof( Pipe_StdErr ) ) }
  END ELSE BEGIN  { IF ListaError = NIL ELSE }
    WHILE NOT( Eof( Pipe_StdErr ) ) DO BEGIN
      ReadLn( Pipe_StdErr, UnaCadena );
      ListaError.Add( UnaCadena );
    END;  { WHILE NOT( Eof( Pipe_StdErr ) ) }
  END;            { IF ListaError = NIL ELSE }
  ReWriteOutWaitOnCompleted;
END;   { FUNCTION CAFE_TriplePipeTraductor.ResultadoWaitOnCompleted }

VAR
  RecorreMensaje                : CAFE_RespuestaEstiloPipe;
INITIALIZATION
  CAFE_ListaMensajePipe         := CAFE_TListaMensajePipe.Create;
  ImplementationSintactico      :=
        CAFE_CharByte2Sintactico.Create( ImplementationTamanoSintactico );
  Implementation2Sintactico     :=
        CAFE_CharByte2Sintactico.Create( ImplementationTamanoSintactico );
  FOR RecorreMensaje IN CAFE_RespuestaEstiloPipe
  DO CAFE_NulaMatrizRenglonConteo[ RecorreMensaje ]     := 0;
FINALIZATION
  FreeAndNil( CAFE_ListaMensajePipe );
  FreeAndNil( ImplementationSintactico );
  FreeAndNil( Implementation2Sintactico );
END.
