home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* LOOP.PAS *)
- (* Abbruch von Endlos-Schleifen mit einem Turbo Pascal *)
- (* unter Verwendung der Unit TSR.PAS aus PASCAL 5/1988 *)
- (* (c) 1989 Waldemar Zylka & TOOLBOX *)
- (* ------------------------------------------------------ *)
- PROGRAM LOOP;
-
- {$R-,S-,V-,B-,I-,N-} (* damit alles schneller ist *)
- {$M 1024,1,1} (* Minimum Stack und Heap *)
-
- USES Tsr, Crt, Dos;
-
- CONST HotKey = $6200; (* HotKey : Ctrl-F5 *)
- HotTaste = 'Ctrl-F5';
- Name = 'Loop v1.0';
- Aktivierung = ' aktivieren.';
- Meldung0 = ' bereits geladen, bitte mit ';
- VAR Regs : Registers;
-
- {$F+} (* Tsr wird benutzt: FAR Codierung *)
-
- TYPE StatusZeile = ARRAY [0..79] OF WORD;
- ScreenInhalt = ARRAY [0..79] OF WORD;
-
- CONST LoopInit : BOOLEAN = FALSE;
- MonoScreen = $B000; ColorScreen = $B800;
- ColorStatBold : BYTE = Yellow;
- ColorStatNorm : BYTE = LightCyan;
- ColorStatBack : BYTE = blue;
- BoldBegin = '';
- BoldEnd = '';
- Meldung1 = ' Programm abbrechen ? (J/N) ';
- Meldung2 =
- ' Programmabbruch nicht möglich, da DOS aktiv';
- VAR DosByteOff,
- DosByteSeg : WORD;
- Keller : ^StatusZeile;
- Screen : ^ScreenInhalt;
- ScreenMode : BYTE ABSOLUTE $0040:$0049;
- VideoBuffer : WORD;
-
- (* ------------------------------------------------------ *)
- (* Diese Prozedur der Tsr-Unit hinzufügen; *)
- (* den Prozedurkopf in den Interface-Teil eintragen. *)
- (* Zusätzlich muß die Prozedur SwitchStack - bisher eine *)
- (* Unterprozedur von Int16_ - verschoben werden, damit *)
- (* sie von SwitchBackDos genutzt werden kann. *)
- (* ------------------------------------------------------ *)
- { !!!!
- PROCEDURE SwitchBackDos;
- (* bricht das aktuelle Programm ab, dies *)
- BEGIN (* ist etwa bei unendlichen Schleifen gut*)
- SetIntVec($16, CurrInt16);
- SwitchBack; (* aus der alten Int16_ Prozedur *)
- Regs.AX := $4CC8; (* ExitCode = 200 *)
- Msdos(Regs);
- END;
- !!!! }
-
- (* ------------------------------------------------------ *)
- PROCEDURE InitLoop;
- (* Bildschirmtyp und Adresse ermitteln *)
- BEGIN
- IF ScreenMode = Mono THEN VideoBuffer := MonoScreen
- ELSE VideoBuffer := ColorScreen;
- Screen := Ptr(VideoBuffer, $0000);
- LoopInit := TRUE;
- END;
-
- (* ------------------------------------------------------ *)
- PROCEDURE WriteCharVideo(x, y : BYTE; Zeichen : CHAR;
- Attr : BYTE);
- (* Schreibt Zeichen mit Attr direkt an der Position (x,y) *)
- (* in den Bildschirm *)
- VAR Offset : INTEGER;
- BEGIN
- Offset := Pred(x) SHL 1 + Pred(y)*160;
- MemW[VideoBuffer:Offset] := Ord(Zeichen) ;
- MemW[VideoBuffer:Succ(Offset)] := Attr ;
- END;
-
- (* ------------------------------------------------------ *)
- PROCEDURE RefZeile(StatusLine : STRING);
- (* Referenzzeile schreiben, oberste Bildschirmzeile *)
- VAR UrAttr, j, i : BYTE;
- BEGIN
- IF NOT LoopInit THEN InitLoop;
- New(Keller);
- Move(Screen^[0], Keller^, SizeOf(Keller^));
- UrAttr := TextAttr;
- (* Turbos TextAttr speichern *)
- TextColor(ColorStatNorm);
- (* Turbos TextAttr verändern *)
- TextBackground(ColorStatBack);
- FOR i := 1 TO 79 DO WriteCharVideo(i, 1, ' ', TextAttr);
- (* Untergrund *)
- j := 1;
- FOR i := 1 TO BYTE(StatusLine[0]) DO BEGIN
- IF (StatusLine[i] = BoldBegin) THEN BEGIN
- (* BoldZeichen liegt vor *)
- TextColor(ColorStatBold);
- Inc(i); (* Turbos TextAttr verändern *)
- END;
- IF (StatusLine[i] = BoldEnd) THEN BEGIN
- (* BoldModus Ende-Zeichen *)
- TextColor(ColorStatNorm);
- Inc(i); (* Turbos TextAttr verändern *)
- END;
- WriteCharVideo(j, 1, StatusLine[i], TextAttr);
- (* Text schreiben *)
- Inc(j);
- END;
- TextAttr := UrAttr; (* Turbos TextAttr restaurieren *)
- END;
-
- (* ------------------------------------------------------ *)
- PROCEDURE RmRefZeile;(* Referenzzeile verschwinden lassen *)
- BEGIN
- Move(Keller^, Screen^[0], SizeOf(Keller^));
- Dispose(Keller);
- END;
-
- (* ------------------------------------------------------ *)
- PROCEDURE EndlosLoop;
- (* Abbruch von laufenden Programmen, EndlosLoops *)
- VAR k : CHAR;
- (* Wird als residente Routine installiert *)
- BEGIN
- IF (Mem[DosByteOff:DosByteSeg] = 0) THEN BEGIN
- (* DOS ist nicht aktiv *)
- RefZeile(Meldung1); (* also melden wir uns *)
- REPEAT
- IF KeyPressed THEN (* und fragen höflich: *)
- k := ReadKey; (* "Abbruch ?" *)
- UNTIL ((UpCase(k) = 'J') OR (UpCase(k) = 'N'));
- IF (UpCase(k) = 'J') THEN BEGIN (* Also abbrechen *)
- RmRefZeile;
- SwitchBackDos; (* Stack umschalten, dann zurück *)
- END ELSE RmRefZeile;
- END ELSE BEGIN (* DOS ist gerade noch aktiv *)
- RefZeile(Meldung2); (* also teilen wir es mit .... *)
- Delay(2000); (* ... warten etwas und *)
- RmRefZeile; (* machen alles rückgängig. *)
- END;
- END;
-
- {$F-} (* Ende FAR Modell *)
-
- (* ------------------------------------------------------ *)
-
- FUNCTION LoopInstall : BOOLEAN;
- (* Loop bereits installiert ? *)
- (* Schützt vor mehrmaliger Installation *)
- VAR Jahr, Monat, Tag, WochTag : WORD;
- BEGIN
- GetDate(Jahr, Monat, Tag, WochTag);
- Write(^M^J, Name);
- IF (MemW[0:$3FA] = Tag) AND
- (MemW[0:$3FE] = Jahr) THEN BEGIN (* Check Marke *)
- Sound(300); WriteLn(Meldung0 + HotTaste + Aktivierung);
- Delay(200); NoSound;
- Halt(255); (* ExitCode 255 *)
- LoopInstall := TRUE;
- Exit;
- END ELSE BEGIN
- MemW[0:$3FA] := Tag;
- (* InstallationsMarke schreiben ins Intr $FF *)
- MemW[0:$3FE] := Jahr;
- DirectVideo := TRUE;
- CheckSnow := FALSE; (* siehe Handbuch, S.125 *)
- WriteLn(' installiert, bitte mit ',
- HotTaste, ' aktivieren.');
- LoopInstall := FALSE;
- END;
- END;
-
- BEGIN (* Hauptprogramm *)
- IF (NOT LoopInstall) THEN BEGIN
- Regs.ax := $3400;
- (* DOS Flag (Anzahl aktiver Dos Funktionen) über *)
- MsDos(Regs);
- (* undokumentierte Funktion 34H Intr21 abfragen: *)
- DosByteOff := Regs.bx;
- (* mem[DosByteSeg:DosByteOff] = 0 Aufruf möglich *)
- DosByteSeg := Regs.es;
- (* mem[....:....] <> 0 Dos Funktion aktiv, Auf- *)
- (* ruf führt zum Systemcrash *)
- MakeResident(@EndlosLoop, HotKey);
- END;
- END.
- (* ------------------------------------------------------ *)
- (* Ende von LOOP.PAS *)