home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / extra18 / grdlagen / umleitg / hrdosum.pas next >
Encoding:
Pascal/Delphi Source File  |  1992-01-22  |  14.7 KB  |  564 lines

  1. (* ------------------------------------------------- *)
  2. (*                     HRDOSUM.PAS                   *)
  3. (*            (c) 1992 H.Rüter & DMV-Verlag          *)
  4. (* ------------------------------------------------- *)
  5. (* Diese Unit ermöglicht es Dos-IN/OUT-Umleitungen   *)
  6. (* zu erkennen.                                      *)
  7. (* Programme die mit dieser Unit erstellt werden,    *)
  8. (* können diese Umleitungen für eigene Zwecke nutzen.*)
  9. (* Wichtig ist,daß im Hauptprogramm die Unit CRT vor *)
  10. (* HRDOSUM initialisiert wird, damit die Umleitungen *)
  11. (* auch realisiert werden.                           *)
  12. (* Die umgeleiteten Ein/Ausgaben sind immer auf dem  *)
  13. (* Bildschirm zu sehen, damit man auch weiß, was da  *)
  14. (* umgeleitet wird können. ( -> Uses Crt,HRDOSUM ... *)
  15. (* ------------------------------------------------- *)
  16. UNIT HRDosUm;
  17. {$M 1024,0,0,I-,R-,S-,N-,V-,B-,A+,D+}
  18.                    (* Höchstmögliche Geschwindigkeit *)
  19.  
  20. INTERFACE
  21.  
  22. TYPE
  23.   InOutModus =
  24.      (NoRedirection,
  25.          (* Keine Umleitung                          *)
  26.      InputRedirection,
  27.          (* Input kommt aus redir. Datei             *)
  28.      OutPutRedirection,
  29.          (* Alle Write(Ln)-Aufrufe werden umgeleitet *)
  30.      AllScreenRedirection,
  31.          (* Alles auf dem Bildschirm wird umgeleitet *)
  32.      ProtRedirection);
  33.          (* Eingaben werden protokolliert            *)
  34.  
  35. CONST
  36.   EoFLine      : BOOLEAN = FALSE;
  37.   EoFInput     : BOOLEAN = FALSE;
  38.       { Für Inputumleitung :
  39.           True -> kein Zeichen im Puffer }
  40.  
  41.  
  42.   FUNCTION DosOutputRedirected : BOOLEAN;
  43.     { Screen-Output umgeleitet ?  }
  44.   FUNCTION DosInputRedirected : BOOLEAN;
  45.     { Input umgeleitet         ?  }
  46.   PROCEDURE ChangeInOutModus(Mode : InOutModus);
  47.     { Ändert den Umleitungsmodus  }
  48.   FUNCTION  GetInOutModus : InOutModus;
  49.     { Liefert den Umleitungsmodus }
  50.  
  51.   FUNCTION ReadKey : CHAR;
  52.     { Ersetzt CRT-READKEY         }
  53.   FUNCTION KeyPressed : BOOLEAN;
  54.     { Ersetzt CRT-KEYPRESSED      }
  55.  
  56.   PROCEDURE SetInputDelay(Sec1000 : WORD);
  57.     { Zur Simulation von Eingaben wird die
  58.       Eingabegeschwindigkeit verringert }
  59.  
  60.   PROCEDURE SetReadKeyMode(Redirected : BOOLEAN);
  61.     { Falls Redirected = TRUE, werden Eingaben
  62.       via »ReadKey« ebenfalls umgeleitet }
  63.   FUNCTION  GetReadKeyMode : BOOLEAN;
  64.     { Liefert den momentanen ReadKey-Modus }
  65.  
  66.   PROCEDURE ChangeSightAbleMode(Sight:Boolean);
  67.     { Wenn OutPut-Umleitung aktiv, kann man hier
  68.       die Sichtbarkeit auf dem Screen beeinflussen }
  69.   FUNCTION OutPutSightAble : BOOLEAN;
  70.     { Umgeleiteter Output auch auf Screen sichtbar  }
  71.  
  72.   PROCEDURE InSightOnOff(Sight : BOOLEAN);
  73.     { Wenn InPut-Umleitung aktiv, kann man hier
  74.       die Sichtbarkeit auf dem Screen beeinflussen }
  75.  
  76.   FUNCTION InPutSightAble : BOOLEAN;
  77.     { Umgeleiteter Input auch auf Screen sichtbar  }
  78.  
  79.   PROCEDURE ProtOut;
  80.     { Schaltet Protokollierung für
  81.       Read(ln)/Write(ln)/ReadKey aus }
  82.   PROCEDURE ProtOn;
  83.     { Schaltet Protokollierung für
  84.       Read(ln)/Write(ln)/ReadKey wieder ein}
  85.  
  86. IMPLEMENTATION
  87.  
  88. USES Crt, Dos;
  89.  
  90. TYPE
  91.   StdDateien       = (InputD,OutPutD,ErrorD,AuxD,PrnD);
  92.   LHTTYP           = ARRAY [0..$FF] OF BYTE;
  93.   LHtPtr           = ^LHTTyp;
  94.  
  95.   TreiberFunc      =
  96. {$IFNDEF VER40}
  97.     FUNCTION (VAR F : TextRec) : INTEGER;
  98. {$ELSE}
  99.     Pointer;
  100. {$ENDIF}
  101.  
  102. CONST
  103.   StdHandles       : ARRAY[0..4] OF BYTE = (1,1,1,0,2);
  104.   PufferSize       = 1024;
  105.   EoFile           = #26;
  106.  
  107.   InDelay          : WORD    = 100;
  108.   PufferPos        : WORD    =   0;
  109.   ActPufferSize    : WORD    =   0;
  110.  
  111.   ReadKeyReDir     : BOOLEAN = FALSE;
  112.   ReFilled         : BOOLEAN = FALSE;
  113.   OutSight         : BOOLEAN = TRUE;
  114.   InSight          : BOOLEAN = TRUE;
  115.   ActModus         : InOutModus = NoRedirection;
  116.   Prot             : BOOLEAN = TRUE;
  117.  
  118. VAR
  119.   OldCrtIn,
  120.   OldCrtInFlush,
  121.   OldCrtOut,
  122.   OldCrtOutFlush,
  123.   OldSystemOut,
  124.   OldSystemFlush,
  125.   OldSystemIn,
  126.   OldSystemInFlush : TreiberFunc;
  127.  
  128.   Puffer           : ARRAY [1..PufferSize] OF CHAR;
  129.   LHTAdr           : LHTPtr;
  130.   Regs             : Registers;
  131.  
  132.  
  133.   FUNCTION GetLHTAdr : LHTPtr;
  134.     { Liefert die Start-Adresse
  135.       der L(ocal)H(andle)T(abelle) }
  136.   BEGIN
  137.     GetLHTAdr := LHTPtr(Ptr(MemW[PrefixSeg:$36],
  138.                             MemW[PrefixSeg:$34]));
  139.   END;
  140.  
  141.   FUNCTION IsUmgeleitet(Datei : StdDateien) : BOOLEAN;
  142.   BEGIN
  143.     IsUmgeleitet := LHTAdr^[Ord(Datei)] <>
  144.                     StdHandles[Ord(Datei)];
  145.   END;
  146.  
  147.   FUNCTION DosOutputRedirected : BOOLEAN;
  148.   BEGIN
  149.     DosOutputRedirected := IsUmgeleitet(OutputD);
  150.   END;
  151.  
  152.   FUNCTION DosInputRedirected : BOOLEAN;
  153.   BEGIN
  154.     DosInputRedirected := IsUmgeleitet(InputD);
  155.   END;
  156.  
  157. {$IFDEF Ver40 }
  158.   FUNCTION CallCrtOutFunc(VAR TR : TextRec) : INTEGER;
  159.   INLINE($FF/$1E/OldCrtOut );   { Call Far }
  160.  
  161.   FUNCTION CallSystemOutFunc(VAR TR: TextRec): INTEGER;
  162.   INLINE($FF/$1E/OldSystemOut );   { Call Far }
  163.  
  164.   FUNCTION CallCrtInFunc(VAR TR : TextRec) : INTEGER;
  165.   INLINE($FF/$1E/OldCrtIn );   { Call Far }
  166. {$ENDIF }
  167.  
  168.   PROCEDURE GetInOutAdr;
  169.     { Diese Prozedur holt sämtliche für die Unit
  170.       wichtigen Adressen der TextRec-Routinen }
  171.   BEGIN
  172.     AssignCrt(Input);
  173.       { Auf jeden Fall Crt-Routinen initialisieren }
  174.     RESET(Input);
  175.     WITH TextRec(Input) DO BEGIN
  176.       OldCrtIn      := TreiberFunc(InOutFunc);
  177.       OldCrtInFlush := TreiberFunc(FlushFunc);
  178.     END;
  179.     Assign(Input,'');
  180.       { Auf System-Routinen umschalten }
  181.     RESET(Input);
  182.     WITH TextRec(Input) DO BEGIN
  183.       OldSystemIn      := TreiberFunc(InOutFunc);
  184.       OldSystemInFlush := TreiberFunc(FlushFunc);
  185.     END;
  186.     AssignCrt(Input);          { Input wieder via CRT }
  187.     Reset(Input);
  188.     AssignCrt(Output);      { Output via CRT-Routinen }
  189.     Rewrite(Output);
  190.     WITH TextRec(Output) DO BEGIN
  191.       OldCrtOut      := TreiberFunc(InOutFunc);
  192.       OldCrtOutFlush := TreiberFunc(FlushFunc);
  193.     END;
  194.     Assign(Output,'');   { Output via System-Routinen }
  195.     Rewrite(Output);
  196.     WITH TextRec(Output) DO BEGIN
  197.       OldSystemOut      := TreiberFunc(InOutFunc);
  198.       OldSystemFlush    := TreiberFunc(FlushFunc);
  199.     END;
  200.     AssignCrt(Output);
  201.                      { Output wieder via CRT-Routinen }
  202.     Rewrite(Output);
  203.   END;
  204.  
  205.   PROCEDURE WriteOutPut(Puffer : Pointer; Size : WORD);
  206.     { Schreibt Size Zeichen aus dem
  207.       Puffer in Standard-OutPut }
  208.   BEGIN
  209.     WITH Regs DO BEGIN
  210.       AH := $40;
  211.       BX := Ord(OutPutD);         { Handle ! }
  212.       CX := Size;
  213.       DS := Seg(Puffer^);
  214.       DX := Ofs(Puffer^);
  215.       MsDos(Regs);
  216.       IF (Odd(Flags AND fCarry)) OR (AX = 0) THEN BEGIN
  217.         AssignCrt(Output);
  218.         Rewrite(Output);
  219.         WriteLn('Fehler bei Zeichenausgabe ',
  220.                 'auf OUTPUT',^G);
  221.         WriteLn('Programmabbruch !!!');
  222.         Writeln('Fehler : ', AX);
  223.         Halt;
  224.       END;
  225.     END;
  226.   END;
  227.  
  228.   PROCEDURE FillInputBuffer;
  229.     { Füllt den EingabePuffer mit Zeichen
  230.       aus der Standard-Eingabe }
  231.     { Wenn keine Zeichen mehr in Standard-Eingabe,
  232.       dann EOFINPUT := TRUE }
  233.   BEGIN
  234.     WITH Regs DO BEGIN
  235.       AH := $3F;
  236.       BX := Ord(InputD);            { Handle ! }
  237.       CX := PufferSize;
  238.       DS := Seg(Puffer);
  239.       DX := Ofs(Puffer);
  240.       MsDos(Regs);
  241.       IF Odd(Flags AND fCarry) THEN BEGIN
  242.         WriteLn('Fehler bei Zeicheneinlesen ',
  243.                 'über Standardeingabe.', ^G);
  244.         WriteLn('Programmabbruch !!!');
  245.         WriteLn('Fehler : ', AX);
  246.         Halt;
  247.       END;
  248.       ActPufferSize := AX;
  249.                         { Aktuelle Puffergröße merken }
  250.       EoFInput := (ActPufferSize = 0);
  251.     END;
  252.   END;
  253.  
  254.   FUNCTION DosReadC : CHAR;
  255.     { Liest ein Zeichen aus dem Eingabepuffer aus }
  256.   VAR
  257.     C : CHAR;
  258.   BEGIN
  259.     IF PufferPos = 0 THEN BEGIN
  260.                               { Nur bei Programmstart }
  261.       FillInputBuffer;
  262.       PufferPos := 1;
  263.     END;
  264.     IF NOT EOFInPut THEN BEGIN
  265.       C  := Puffer[PufferPos];   { Zeichen holen }
  266.       IF (Succ(PufferPos) <= PufferSize) AND
  267.          (Puffer[Succ(PufferPos)] = EoFile) THEN
  268.         EoFInput := TRUE;
  269.     END;
  270.     IF PufferPos < ActPufferSize THEN
  271.       Inc(PufferPos)
  272.     ELSE BEGIN
  273.       FillInputBuffer;
  274.       { Wenn Puffer geleert, dann versuchen,
  275.         Puffer neu zu füllen }
  276.       PufferPos := 1;
  277.     END;
  278.     IF Not(c IN [#10,#13]) THEN
  279.       Delay(Abs(InDelay-(InDelay MOD 10) *
  280.             Random(InDelay MOD 20)) MOD 1000);
  281.       { Maximale Simulationsverzögerung 1000 mSec }
  282.     DosReadC := C;
  283.   END;
  284.  
  285.   PROCEDURE GetString(VAR S : STRING);
  286.     { Holt eine String aus dem InputPuffer }
  287.   VAR
  288.     Ch : CHAR;
  289.   BEGIN
  290.     S := '';
  291.     EoFLine := FALSE;
  292.     IF EoFInput THEN Exit;
  293.     WHILE NOT EoFInput AND
  294.           NOT EoFLine DO BEGIN
  295.                  { Einlesen, bis CRLF oder File-Ende }
  296.       Ch := DosReadC;
  297.       S  := S + Ch;
  298.       IF InSight THEN Write(Ch);
  299.         { Bei "Sichtbarkeitsmodus" Zeichen schreiben }
  300.       IF Ch = #10 THEN EoFLine := TRUE;
  301.     END;
  302.   END;
  303.  
  304. {$F+ }
  305.   FUNCTION NewOut(VAR F : TextRec) : INTEGER;
  306.     { Neue Output-Routine für Textausgaben }
  307.   VAR
  308.     Result   : INTEGER;
  309.     F2       : TextRec;
  310.   BEGIN
  311.     F2 := F;
  312. {$IFNDEF VER40 }
  313.       { Alte Screen-OutPutroutine aufrufen }
  314.     IF OutSight THEN Result := OldCrtOut(F)
  315.                 ELSE Result := 0;
  316.     IF (Result = 0) AND Prot THEN
  317.       Result := OldSystemOut(F2);
  318. {$ELSE }
  319.       { .. und dasselbe für Turbo Version 4.0 }
  320.     IF OutSight THEN Result := CallCrtOutFunc(F)
  321.                 ELSE Result := 0;
  322.     IF (Result = 0) AND Prot THEN
  323.       Result := CallSystemOutFunc(F2);
  324. {$ENDIF }
  325.     NewOut := Result;
  326.   END;
  327.  
  328.   FUNCTION NewIn(VAR F : TextRec) : INTEGER;
  329.     { Neue Inputroutine für Texteingaben }
  330.   VAR
  331.     i               : Word;
  332.     s               : String;
  333.   BEGIN
  334.     WITH F DO BEGIN
  335.       GetString(s);  { String aus Inputpuffer holen.. }
  336.                      {... und in F einbauen           }
  337.       FOR i := 1 TO Length(s) DO
  338.         BufPtr^[Pred(i)] := s[i];
  339.       IF Length(s) > 0 THEN BufEnd := Succ(Length(s))
  340.                        ELSE BufEnd := 0;
  341.                                   { Pufferende setzen }
  342.       BufPos := 0;
  343.     END;
  344.     NewIn := 0;
  345.   END;
  346.  
  347.   FUNCTION NewInFlush(VAR F : TextRec) : INTEGER;
  348.     { Neue InputFlushroutine für Texteingaben }
  349.   BEGIN
  350.     WITH F DO BEGIN
  351.       BufPos := 0;
  352.       BufEnd := 0;
  353.     END;
  354.     NewInFlush := 0;
  355.   END;
  356.  
  357.   FUNCTION NewInOut(VAR F : TextRec) : INTEGER;
  358.     { Neue Inputroutine für Output-Umleitung }
  359.   VAR
  360.     Result : INTEGER;
  361.   BEGIN
  362.     WITH F DO BEGIN
  363. {$IfNDEF VER40 }
  364.       Result := OldCrtIn(F);
  365.         { Eingabe mit alter Routine holen..}
  366. {$ELSE }
  367.       Result := CallCrtInFunc(F);
  368. {$ENDIF }
  369.       IF (Result = 0) AND Prot THEN
  370.         WriteOutPut(BufPtr, BufEnd);
  371.                                 {..und protokollieren }
  372.     END;
  373.     NewInOut := Result;
  374.   END;
  375. {$F- }
  376.  
  377.   PROCEDURE AssignNewInput;
  378.     { Neue Routinen zur Eingabeumleitung auf die
  379.       entsprechenden Zeiger setzen }
  380.   BEGIN
  381.     Reset(Input);
  382.     WITH TextRec(Input) DO BEGIN
  383.       InOutFunc := @NewIn;
  384.       FlushFunc := @NewInFlush;
  385.     END;
  386.   END;
  387.  
  388.   PROCEDURE AssignNewOutPut;
  389.     { Neue Routinen zur Ausgabeumleitung auf die
  390.       entsprechenden Zeiger setzen }
  391.   BEGIN
  392.     Rewrite(Output);
  393.     WITH TextRec(Output) DO BEGIN
  394.       InOutFunc := @NewOut;
  395.       FlushFunc := @NewOut;
  396.     END;
  397.   END;
  398.  
  399.   PROCEDURE AssignOldOutPut;
  400.     { CRT-Ausgaberoutinen setzen }
  401.   BEGIN
  402.     Rewrite(Output);
  403.     WITH TextRec(Output) DO BEGIN
  404.       InOutFunc := @OldCrtOut;
  405.       FlushFunc := @OldCrtOutFlush;
  406.     END;
  407.   END;
  408.  
  409.   PROCEDURE AssignOldInPut;
  410.     { CRT-Eingaberoutinen setzen }
  411.   BEGIN
  412.     Reset(Input);
  413.     WITH TextRec(InPut) DO BEGIN
  414.       InOutFunc := @OldCrtIn;
  415.       FlushFunc := @OldCrtInFlush;
  416.     END;
  417.   END;
  418.  
  419.   PROCEDURE AssignProtInPut;
  420.     { Neue Eingaberoutinen für Outputumleitung setzen }
  421.   BEGIN
  422.     Reset(Input);
  423.     WITH TextRec(InPut) DO BEGIN
  424.       InOutFunc := @NewInOut;
  425.       FlushFunc := @OldCrtInFlush;
  426.     END;
  427.   END;
  428.  
  429.   PROCEDURE AssignAllProt;
  430.     { Neue Routinen für Umleitung des gesamten
  431.       Screen-Outputs setzen }
  432.   BEGIN
  433.     AssignProtInput;
  434.     AssignNewOutPut;
  435.   END;
  436.  
  437.   FUNCTION GetInOutModus : InOutModus;
  438.   BEGIN
  439.     GetInOutModus := ActModus;
  440.   END;
  441.  
  442.   PROCEDURE ChangeInOutModus(Mode : InOutModus);
  443.   BEGIN
  444.     CASE Mode OF
  445.       NoRedirection       :
  446.         BEGIN
  447.           AssignOldInput; AssignOldOutPut;
  448.         END;
  449.       InputRedirection    :
  450.         BEGIN
  451.           AssignNewInput; SetReadKeyMode(TRUE);
  452.         END;
  453.       OutPutRedirection   : AssignNewOutPut;
  454.       ProtRedirection     :
  455.         BEGIN
  456.           AssignProtInput;
  457.         END;
  458.       OutPutRedirection   : AssignNewOutPut;
  459.       AllScreenRedirection: AssignAllProt;
  460.     END;
  461.     ActModus := Mode;
  462.     Prot     := TRUE;
  463.   END;
  464.  
  465.   FUNCTION ReadC : CHAR;
  466.   VAR
  467.     C : CHAR;
  468.   BEGIN
  469.     C := Crt.ReadKey;
  470.     IF (ActModus IN
  471.         [ProtRedirection, AllScreenRedirection]) AND
  472.         Prot THEN
  473.       WriteOutPut(@C, 1);
  474.     ReadC := C;
  475.   END;
  476.  
  477.   FUNCTION ReadKey : CHAR;
  478.   BEGIN
  479.     IF (ActModus IN [InputRedirection]) AND
  480.         ReadKeyReDir THEN
  481.       ReadKey := DosReadC
  482.     ELSE
  483.       ReadKey := ReadC;
  484.   END;
  485.  
  486.   FUNCTION KeyPressed : BOOLEAN;
  487.   BEGIN
  488.     IF (ActModus = InputRedirection) AND
  489.         ReadKeyReDir THEN
  490.       KeyPressed  := NOT EoFInput
  491.     ELSE
  492.       KeyPressed  := Crt.KeyPressed;
  493.   END;
  494.  
  495.   PROCEDURE SetInputDelay(Sec1000 : WORD);
  496.   BEGIN
  497.     InDelay := Sec1000;
  498.   END;
  499.  
  500.   PROCEDURE SetReadKeyMode(Redirected : BOOLEAN);
  501.   BEGIN
  502.     ReadKeyRedir := Redirected;
  503.   END;
  504.  
  505.   FUNCTION GetReadKeyMode : BOOLEAN;
  506.   BEGIN
  507.     GetReadKeyMode := ReadKeyRedir;
  508.   END;
  509.  
  510.   FUNCTION OutPutSightAble : BOOLEAN;
  511.   BEGIN
  512.     OutPutSightable := OutSight;
  513.   END;
  514.  
  515.   PROCEDURE ChangeSightAbleMode(Sight : BOOLEAN);
  516.   BEGIN
  517.     OutSight := Sight;
  518.   END;
  519.  
  520.   FUNCTION InPutSightAble : BOOLEAN;
  521.   BEGIN
  522.     InPutSightable := InSight;
  523.   END;
  524.  
  525.   PROCEDURE InSightOnOff(Sight : BOOLEAN);
  526.   BEGIN
  527.     InSight := Sight;
  528.   END;
  529.  
  530.   FUNCTION DosVersionsNr : WORD;
  531.   BEGIN
  532.     WITH Regs DO BEGIN
  533.       AH   := $30;
  534.       MsDos(Regs);
  535.       IF AL = 0 THEN DosVersionsNr := 1
  536.                 ELSE DosVersionsNr := AL;
  537.     END;
  538.   END;
  539.  
  540.   PROCEDURE ProtOut;
  541.   BEGIN
  542.     Prot := FALSE;
  543.   END;
  544.  
  545.   PROCEDURE ProtON;
  546.   BEGIN
  547.     PROT := TRUE;
  548.   END;
  549.  
  550. BEGIN
  551.   IF DosversionsNr < 2 THEN BEGIN
  552.     WriteLn('Falsche DOS-Version !!!');
  553.     WriteLn('Programm ', ParamStr(0),
  554.             ' läuft erst ab DOS-Version 2.0');
  555.     WriteLn('Programmabbruch !!!',^G^G);
  556.     Halt;
  557.   END;
  558.   Randomize;
  559.   GetInOutAdr;
  560.   LHTAdr := GetLHTAdr;
  561. END.
  562. (* ------------------------------------------------- *)
  563. (*             Ende von HRDOSUM.PAS                  *)
  564.