home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
ANSICRT2.ZIP
/
ANSICRT.PAS
next >
Wrap
Pascal/Delphi Source File
|
1993-03-21
|
7KB
|
231 lines
UNIT AnsiCrt;
{ Ian Hinson using Turbo Pascal 6.0
3:633/357 18 March 1993 }
{ This Unit contains most functions & procedures in common use in the
CRT Unit. To that extent it is intended as a replacement to the CRT unit
and should not be used at the same time.
See the INTERFACE section for a list of constants, variables, functions
and procedures provided by this unit.
DosCrt differs from the CRT Unit in that DOS is used for input and output.
This provides the following advantages:
1. Output can be redirected using DOS redirection
2. The routines should work on any 80x86 based machine using compatible
DOS (although non-IBMPC architectures have long since been driven from
consideration through programmers writing to the hardware environment
instead of the operating system.)
3. The use of DOS standard input/output and ANSI means that programs that
use this unit may feasibly be operated via a remote ANSI terminal.
This unit has been adapted from the unit ANSCRT.PAS by Rick Housh.
However, a new approach used to implement most procedures (see below)
means the code is practically all new, except for the simplest procedures.
e.g. ClrScr, ClrEol, and most cursor functions.
I have reworked the TextColor procedure by using a Decision Tree
implementation technique instead of conventional structured logic
programming; With the desired result that:
1) there is now only ONE Ansi sequence written to the output device
for each invocation of TextColor.
2) those sequences contain no redundancy e.g. (no) turning on bold when it
was already on, or (no) resetting all attributes when all that is needed
is to ADD an attribute.
The original ANSCrt Unit used a 'broad-brush' approach which simplified
the logic but caused redundancy of Ansi sequences.
Ansi detection has been made into a separate user-available function.
I have rewritten Keypressed and ReadKey. I don't believe that the speed
required for these routines is so great that ASM or INLINE code is
warranted, so I opted for the clearer DOS Unit 'Registers' method.
User variables CheckEOF and TextAttr were abolished since they weren't
fully implemented anyway. }
INTERFACE
CONST
Black = 0; Blue = 1; Green = 2; Cyan = 3;
Red = 4; Magenta = 5; Brown = 6; LightGray = 7;
DarkGray = 8; LightBlue = 9; LightGreen = 10; LightCyan = 11;
LightRed = 12; LightMagenta = 13; Yellow = 14; White = 15;
Blink = 128;
VAR CheckBreak: BOOLEAN;
FUNCTION KeyPressed : BOOLEAN;
FUNCTION ReadKey : CHAR;
FUNCTION AnsiDetected: BOOLEAN; { new to this unit }
PROCEDURE TextColor(fore : Byte);
PROCEDURE TextBackGround(back : BYTE);
PROCEDURE NormVideo;
PROCEDURE LowVideo;
PROCEDURE HighVideo;
PROCEDURE ClrEol;
PROCEDURE ClrScr;
PROCEDURE WhereXY(VAR x,y: BYTE); { new to this unit }
FUNCTION WhereX: BYTE;
FUNCTION WhereY: BYTE;
PROCEDURE GotoXY(x,y: BYTE);
IMPLEMENTATION
USES Dos;
CONST forestr: ARRAY[Black..LightGray] OF STRING[2]
= ('30','34','32','36','31','35','33','37');
backstr: ARRAY[Black..LightGray] OF STRING[2]
= ('40','44','42','46','41','45','43','47');
decisiontree: ARRAY[BOOLEAN, BOOLEAN, BOOLEAN, BOOLEAN] OF INTEGER =
((((0,1),(2,0)),((1,1),(3,3))),(((4,5),(6,4)),((0,5),(2,0))));
VAR forecolour, backcolour: BYTE; { stores last colours set }
boldstate, blinkstate: BOOLEAN;
FUNCTION KeyPressed : BOOLEAN;
{ Detects whether a key is pressed. Key remains in kbd buffer}
VAR r: REGISTERS;
BEGIN
r.AH := $0B;
MsDos(r);
Keypressed := (r.AL = $FF)
END;
FUNCTION ReadKey : CHAR;
{ Will wait for key }
VAR r: REGISTERS;
BEGIN
r.AH := $07;
MsDos(r);
IF CheckBreak AND (r.AL = $03) THEN Intr($23,r);
ReadKey := Chr(r.AL)
END;
FUNCTION AnsiDetected: BOOLEAN;
{ Detects whether ANSI is installed. }
VAR dummy: CHAR;
BEGIN Write(#27'[6n'); { Ask for cursor position report via }
IF NOT keypressed { the ANSI driver. }
THEN AnsiDetected := FALSE
ELSE BEGIN
AnsiDetected := TRUE;
{ empty the keyboard buffer }
REPEAT Dummy := Readkey UNTIL NOT Keypressed
END
END;
PROCEDURE TextColor(fore : Byte);
VAR
blinknow, boldnow: BOOLEAN;
outstr: STRING;
BEGIN
blinknow := (fore AND $80) = $80;
boldnow := (fore AND $08) = $08;
fore := fore AND $07; { mask out intensity and blink attributes }
forecolour := fore;
CASE decisiontree[blinknow, blinkstate, boldnow, boldstate] OF
0: outstr := Concat(#27,'[',forestr[fore],'m');
1: outstr := Concat(#27,'[0;',backstr[backcolour],';',forestr[fore],'m');
2: outstr := Concat(#27,'[1;',forestr[fore],'m');
3: outstr := Concat(#27,'[0;1;',backstr[backcolour],';',forestr[fore],'m');
4: outstr := Concat(#27,'[5;',forestr[fore],'m');
5: outstr := Concat(#27,'[0;5;',backstr[backcolour],';',forestr[fore],'m');
6: outstr := Concat(#27,'[1;5;',forestr[fore],'m');
END; { CASE }
Write(outstr);
blinkstate := blinknow;
boldstate := boldnow;
END;
PROCEDURE TextBackGround(back: BYTE);
VAR outstring: STRING;
BEGIN
IF Back > 7 THEN Exit; { No such thing as bright or blinking backgrounds }
BackColour := Back;
outstring := Concat(#27,'[',backstr[back],'m');
Write(outstring)
END;
PROCEDURE NormVideo;
BEGIN
Write(#27'[0m');
forecolour := LightGray;
backcolour := Black;
boldstate := FALSE;
blinkstate := FALSE
END;
PROCEDURE LowVideo;
BEGIN
IF blinkstate THEN forecolour := forecolour OR $80; { retain blinking }
TextColor(forecolour); { stored forecolour never contains bold attr }
END;
PROCEDURE HighVideo;
BEGIN
IF NOT boldstate THEN
BEGIN
boldstate := TRUE;
Write(#27,'[1m')
END;
END;
PROCEDURE ClrEol;
BEGIN
Write(#27'[K')
END;
PROCEDURE ClrScr;
BEGIN
Write(#27'[2J');
END;
PROCEDURE WhereXY(VAR x,y: BYTE);
VAR
ch : char;
st : String;
st1: String[2];
i : integer;
BEGIN
Write(#27'[6n'); { Ansi string to get X-Y position }
st := '';
REPEAT
ch := readkey; { Get one }
st := st + ch; { Build string }
UNTIL ch = 'R';
WHILE Keypressed DO ch := ReadKey; {clear kbd buffer}
St1 := copy(St,6,2); { Pick off substring having number in ASCII}
Val(St1,x,i); { Make it numeric }
St1 := copy(St,3,2); { Pick off substring having number in ASCII}
Val(St1,y,i); { Make it numeric }
END;
FUNCTION WhereX: BYTE;
VAR x,y: BYTE;
BEGIN
WhereXY(x,y);
WhereX := x
END;
FUNCTION WhereY: BYTE;
VAR x,y: BYTE;
BEGIN
WhereXY(x,y);
WhereY := y
END;
PROCEDURE GotoXY(x,y: BYTE);
BEGIN
IF (x < 1) OR (y < 1) THEN Exit;
IF (x > 80) OR (y > 25) THEN Exit;
Write(#27'[',y,';',x,'H');
END;
BEGIN
CheckBreak := TRUE;
forecolour := LightGray;
backcolour := Black;
boldstate := FALSE;
blinkstate := FALSE
END.