{ TPANSI Ver 2.2 (c) September 1988 by James R. Louvau. } { This code may be freely used and distributed for NON-COMMERCIAL applications} { only! Permission for use of any other kind must come from the author, } { IN WRITING! It may be distributed under the name TPANSI (any version) only } { if left in it's ORIGINAL FORM! Experimentation and additions are expected } { and encouraged, but I won't take responsability for anybody else's source } { code without seeing and authorizing it first. Have fun, and I hope it helps!} {USAGE: } { Include TPANSIx in your UNITS as: } { USES TPansi; } { } { Whenever you want output thru an ansi filter, just output to the } { ansi file as: } { writeln(ansi,^[,'[5mThis will display blinking'); } { } { ansi is defined globally as: } { var } { ansi: TEXT; } { and is automatically set up and opened for OUTPUT by the unit, just } { like Turbo's 'output' file. } { READS are unaffected by TPANSI. } { TPANSI is aware, and conforms to all of Turbo's built in settings } { and variables. i.e.: } { DirectVideo, CheckSnow, WhereX, Window, etc. work as intended. } { } { There is also a global boolean variable called 'ansion', that is set } { to TRUE upon initialization, that may be used to toggle the } { processing of ANSI escape sequences on and off. } { } {HISTORY: } { Version 1.0 - Initial release } { Version 2.0 - Most low level routines re-coded as inline assembly } { code for speed. } { Changed PutC to allow direct screen writes. } { Implemented global variable 'ansion' for to facilitate } { enable/disable of ANSI processing. } { Version 2.1 - Changed scroll routine for linefeeds @ bottom of window } { or screen, to do direct video ram to video ram moves } { when DirectVideo is on, for scrolling speed. } { Version 2.2 - Added code to check current video mode and to check for } { an EGA/VGA. This procedure automatically sets CheckSnow } { to FALSE upon startup if it detects mode 7 (monochrome) } { or if it finds an EGA/VGA card - also for speed. } { } {$R-,S+,I+,D+,F-,V-,B-,N-,L+ } {$M 65520,0,655360 } unit tpansi; interface uses crt,dos; const ansion:boolean=TRUE; ansisz:word=$0080; leftarrowkey=#75; rightarrowkey=#77; insertkey=#82; deletekey=#83; homekey=#71; endkey=#79; var ansiin,ansiout:text; procedure getcursortype(var top,bottom:integer); procedure assignansi(var f:text); implementation var r:registers; procedure getcursortype(var top,bottom:integer); begin {rcg11172000 commented out.} (* inline($b8/$00/$03/ {mov ax,$0300} $31/$db/ {xor bx,bx} $cd/$10/ {int $10} $31/$c0/ {xor ax,ax} $88/$e8/ {mov al,ch} $c4/$be/>top/ {les di,>top[bp]} $ab/ {stosw} $88/$c8/ {mov al,cl} $c4/$be/>bottom/ {les di,>bottom[bp]} $ab); {stosw} *) end; procedure setcursortype(top,bottom:integer); begin {rcg11172000 commented out.} (* inline($b8/$00/$01/ {mov ax,$0100} $8a/$6e/x/ { les di,>x[bp] } $ab/ { stosw } $88/$f0/ { mov al,dh } $c4/$be/>y/ { les di,>y[bp] } $ab); { stosw } *) end; procedure setxy(x,y:integer); begin {rcg11172000 commented out.} (* inline($8b/$9e/>x/ { mov bx,>x[bp] } $8b/$86/>y/ { mov ax,>y[bp] } $3e/$8b/$0e/>windmin/ {ds:mov cx,word PTR[>WindMin] } $3e/$8b/$16/>windmax/ {ds:mov dx,word PTR[>WindMax] } $88/$c7/ { mov bh,al } $38/$cb/ { cmp bl,cl } $73/$04/ { jae C0 } $88/$cb/ { mov bl,cl } $eb/$06/ { jmp short C1 } $38/$d3/ {C0:cmp bl,dl } $76/$02/ { jbe C1 } $88/$d3/ { mov bl,dl } $38/$ef/ {C1:cmp bh,ch } $73/$04/ { jae C2 } $88/$ef/ { mov bh,ch } $eb/$06/ { jmp short C3 } $38/$f7/ {C2:cmp bh,dh } $76/$02/ { jbe C3 } $88/$f7/ { mov bh,dh } $89/$da/ {C3:mov dx,bx } $31/$db/ { xor bx,bx } $b8/$00/$02/ { mov ax,$0200 } $cd/$10); { int $10 } *) end; procedure putc(c:char); begin {rcg11172000 commented out.} (* inline($3e/$a0/>directvideo/ { ds:mov al,byte PTR[>DirectVideo] } $3c/$01/ { cmp al,1 } $75/$5b/ { jne BIOS } $b8/$40/$00/ { mov ax,$0040 } $8e/$c0/ { mov es,ax } $26/$8b/$1e/$50/$00/ { es:mov bx,word PTR[$0050] } $26/$a1/$4a/$00/ { es:mov ax,word PTR[$004A] } $31/$c9/ { xor cx,cx } $88/$f9/ { mov cl,bh } $f7/$e1/ { mul cx } $30/$ff/ { xor bh,bh } $01/$d8/ { add ax,bx } $d1/$e0/ { shl ax,1 } $89/$c7/ { mov di,ax } $26/$a0/$49/$00/ { es:mov al,byte PTR[$0049] } $3c/$07/ { cmp al,7 } $75/$05/ { jne COLO } $b8/$00/$b0/ { mov ax,$B000 } $eb/$03/ { jmp short MONO } $b8/$00/$b8/ {COLO: mov ax,$B800 } $8e/$c0/ {MONO: mov es,ax } $8a/$46/textattr/ { ds:mov ah,byte PTR[>TextAttr] } $3e/$8a/$1e/>checksnow/ { ds:mov bl,byte PTR[>CheckSnow] } $80/$fb/$01/ { cmp bl,1 } $74/$04/ { je SLOW } $ab/ { stosw } $e9/$28/$00/ { jmp EXIT } $89/$c3/ {SLOW: mov bx,ax } $ba/$da/$03/ { mov dx,$03DA } $ec/ {HORZ: in al,dx } $d0/$d8/ { rcr al,1 } $72/$fb/ { jc HORZ } $fa/ { cli } $ec/ {VERT: in al,dx } $24/$09/ { and al,9 } $75/$fb/ { jnz VERT } $89/$d8/ { mov ax,bx } $ab/ { stosw } $fb/ { sti } $e9/$11/$00/ { jmp EXIT } $b4/$09/ {BIOS: mov ah,$09 } $8a/$46/textattr/ { ds:mov bl,byte PTR[>TextAttr] } $b9/$01/$00/ { mov cx,$0001 } $cd/$10); { int $10 } {EXIT: } *) end; procedure scroll; begin {rcg11172000 commented out.} (* inline($3e/$a0/>directvideo/ { ds:mov al,byte PTR[>DirectVideo] } $3e/$8b/$0e/>windmin/ { ds:mov cx,word PTR[>WindMin] } $3e/$8b/$16/>windmax/ { ds:mov dx,word PTR[>WindMax] } $3c/$01/ { cmp al,1 } $74/$03/ { je DIRECT } $e9/$a4/$00/ { jmp BIOS } $1e/ {DIRECT: push ds } $31/$c0/ { xor ax,ax } $8e/$c0/ { mov es,ax } $26/$8b/$1e/$4a/$04/ { es:mov bx,word PTR[$044A] } $88/$f0/ { mov al,dh } $28/$e8/ { sub al,ch } $50/ { push ax } $88/$d0/ { mov al,dl } $28/$c8/ { sub al,cl } $fe/$c0/ { inc al } $50/ { push ax } $88/$e8/ { mov al,ch } $f7/$e3/ { mul bx } $30/$ed/ { xor ch,ch } $01/$c8/ { add ax,cx } $d1/$e0/ { shl ax,1 } $89/$c7/ { mov di,ax } $d1/$e3/ { shl bx,1 } $01/$d8/ { add ax,bx } $89/$c6/ { mov si,ax } $b9/$00/$b0/ { mov cx,$B000 } $26/$a0/$49/$04/ { es:mov al,byte PTR[$0449] } $3c/$07/ { cmp al,7 } $74/$04/ { je MONO } $81/$c1/$00/$08/ { add cx,$0800 } $8e/$c1/ {MONO: mov es,cx } $fc/ { cld } $59/ { pop cx } $5A/ { pop dx } $d1/$eb/ { shr bx,1 } $29/$cb/ { sub bx,cx } $d1/$e3/ { shl bx,1 } $3e/$a0/>checksnow/ { ds:mov al,byte PTR[>CheckSnow] } $8c/$c0/ { mov ax,es } $8e/$d8/ { mov ds,ax } $3c/$01/ { cmp al,1 } $75/$1f/ { jne FAST } $52/ {SLOW0: push dx } $51/ { push cx } $ba/$da/$03/ {SLOW1: mov dx,$03DA } $ec/ {HORZ: in al,dx } $d0/$d8/ { rcr al,1 } $72/$fb/ { jc HORZ } $fa/ { cli } $ec/ {VERT: in al,dx } $24/$09/ { and al,9 } $75/$fb/ { jnz VERT } $a5/ { movsw } $fb/ { sti } $e2/$ee/ { loop SLOW1 } $59/ { pop cx } $5a/ { pop dx } $01/$de/ { add si,bx } $01/$df/ { add di,bx } $4a/ { dec dx } $74/$0d/ { jz FILL } $eb/$e1/ { jmp short SLOW0 } $51/ {FAST: push cx } $f2/$a5/ { rep movsw } $59/ { pop cx } $01/$df/ { add di,bx } $01/$de/ { add si,bx } $4a/ { dec dx } $75/$f5/ { jnz FAST } $1f/ {FILL: pop ds } $3e/$8a/$26/>textattr/ { ds:mov ah,byte PTR[>TextAttr] } $b0/$20/ { mov al,' ' } $3e/$8a/$1e/>checksnow/ { ds:mov bl,byte PTR[>CheckSnow] } $80/$fb/$01/ { cmp bl,1 } $75/$16/ { jne FAST1 } $89/$c3/ { mov bx,ax } $ba/$da/$03/ { mov dx,$03DA } $ec/ {HORZ1: in al,dx } $d0/$d8/ { rcr al,1 } $72/$fb/ { jc HORZ1 } $fa/ { cli } $ec/ {VERT1: in al,dx } $24/$09/ { and al,9 } $75/$fb/ { jnz VERT1 } $ab/ { stosw } $fb/ { sti } $e2/$f1/ { loop HORZ1 } $eb/$0e/ { jmp short DONE } $f2/$ab/ {FAST1: rep stosw } $eb/$0a/ { jmp short DONE } $b8/$01/$06/ {BIOS: mov ax,$0601 } $3e/$8a/$3e/>textattr/ { ds:mov bh,byte PTR[>TextAttr] } $cd/$10) { int $10 } {DONE: } *) end; procedure carriagereturn; var x,y:integer; begin getxy(x,y); if (x>lo(windmin)) then setxy(lo(windmin),y); end; procedure linefeed; var x,y:integer; begin getxy(x,y); if (ylo(windmin)) then setxy(pred(x),y) else if (y>hi(windmin)) then setxy(lo(windmax),pred(y)); {* putc(' ');*} {* messing up message ANSI B.S.!!!!! *} end; procedure character(c:char); var x,y:integer; begin getxy(x,y); putc(c); if (x0) or (e<>0) then n:=0 else n:=integer(l); getnumber:=n; end; {$I+} end; procedure ansiup(var s:string); var x,y,n:integer; begin getxy(x,y); n:=getnumber(s); if (n<1) then n:=1; y:=y-lo(n); if (yhi(windmax)) then y:=hi(windmax); setxy(x,y); end; procedure ansidn(var s:string); var x,y,n:integer; begin getxy(x,y); n:=getnumber(s); if (n<1) then n:=1; y:=y+lo(n); if (y>hi(windmax)) then y:=hi(windmax) else if (ylo(windmax)) then x:=lo(windmax); setxy(x,y); end; procedure ansirt(var s:string); var x,y,n:integer; begin getxy(x,y); n:=getnumber(s); if (n<1) then n:=1; x:=x+lo(n); if (x>lo(windmax)) then x:=lo(windmax) else if (x0) and (y>0)) then gotoxy(x,y); end; procedure ansicl; begin clreol; end; procedure ansics(var s:string); begin if (getnumber(s)=2) then clrscr; end; procedure reverse; begin {rcg11172000 commented out.} (* inline($3e/$a0/>textattr/ { ds:mov al,byte PTR[TextAttr] } $88/$c3/ { mov bl,al } $80/$e3/$07/ { and bl,7 } $b9/$04/$00/ { mov cx,4 } $d2/$e3/ { shl bl,cl } $88/$c7/ { mov bh,al } $b9/$04/$00/ { mov cx,4 } $d2/$ef/ { shr bh,cl } $80/$e7/$07/ { and bh,7 } $24/$88/ { and al,136 } $08/$fb/ { or bl,bh } $08/$d8/ { or al,bl } $3e/$a2/>textattr); { ds:mov byte PTR[TextAttr],al } *) end; procedure conceal; begin (* inline($3e/$a0/>textattr/ { ds:mov al,byte PTR[>TextAttr] } $24/$70/ { and al,112 } $88/$c3/ { mov bl,al } $b9/$04/$00/ { mov cx,4 } $d2/$eb/ { shr bl,cl } $08/$d8/ { or al,bl } $3e/$a2/>textattr); { ds:mov byte PTR[>TextAttr],al } *) end; procedure ansico(var s:string); var n:integer; procedure ftc(f:byte); begin textattr:=(textattr and 248) or f; end; procedure btc(b:byte); begin textattr:=(textattr and 143) or (b shl 4); end; begin if (length(s)=0) then normvideo; while (length(s)>0) do begin n:=getnumber(s); if (n<0) then n:=0; { : B : b b b : f f f f : } case lo(n) of 0:textattr:=7; { normal video } 1:textattr:=textattr or 8; { turn on f1 } 2:textattr:=textattr and 247; { knock off f1 } 5:textattr:=textattr or 128; { turn on B } 6:textattr:=textattr or 128; { turn on B } 7:reverse; 8:conceal; 30:ftc(black); 31:ftc(red); 32:ftc(green); 33:ftc(brown); 34:ftc(blue); 35:ftc(magenta); 36:ftc(cyan); 37:ftc(lightgray); 40:btc(black); 41:btc(red); 42:btc(green); 43:btc(brown); 44:btc(blue); 45:btc(magenta); 46:btc(cyan); 47:btc(lightgray) end; end; end; procedure ansioutput(c:char); const isansi:boolean=FALSE; ansis:string=''; lastc:char=#0; begin if (isansi) and (ansion) then begin if (c in ['H','F','A'..'D','s','u','J','K','m']) then begin case c of 'H','F':ansito(ansis); 'A':ansiup(ansis); 'B':ansidn(ansis); 'C':ansirt(ansis); 'D':ansilt(ansis); 's':ansixy(TRUE); 'u':ansixy(FALSE); 'J':ansics(ansis); 'K':ansicl; 'm':ansico(ansis); end; isansi:=FALSE; end else if (c in ['0'..'9',';']) and (length(ansis)<255) then ansis:=ansis+c else isansi:=FALSE; end else begin if (c<' ') then case c of #7 : bell; #8 : backspace; #10: linefeed; #12: clrscr; #13: carriagereturn; #27: if (lastc=c) then character(^[); else character(c); end else if (lastc<>^[) then character(c) else if (c='[') and (ansion) then begin isansi:=TRUE; ansis:=''; end else begin character(^[); character(c); end; end; lastc:=c end; procedure showstr(var b:textbuf; p,l:word); var n:word; begin for n:=p to (p+l) do character(b[n]); end; procedure setsnow; begin {rcg11172000 commented out.} (* inline($3e/$a0/>directvideo/ { ds:mov al,byte PTR[>DirectVideo] } $3c/$01/ { cmp al,1 } $74/$07/ { jz DIRECT } $b8/$00/$0f/ { mov ax,$0F00 } $cd/$10/ { int $10 } $eb/$08/ { jmp short CHKMODE } $31/$c0/ {DIRECT: xor ax,ax } $8e/$c0/ { mov es,ax } $26/$a0/$49/$04/ { es:mov al,byte PTR[$0449] } $3c/$07/ {CHKMODE: cmp al,7 } $74/$0c/ { je SETFAST } $b4/$12/ { mov ah,$12 } $bb/$10/$ff/ { mov bx,$FF10 } $cd/$10/ { int $10 } $80/$ef/$ff/ { sub bh,$FF } $74/$04/ { jz NOTFAST } $31/$c0/ {SETFAST: xor ax,ax } $eb/$02/ { jmp short SET } $b0/$01/ {NOTFAST: mov al,$01 } $3e/$a2/>checksnow); {SET: ds:mov byte PTR[>CheckSnow],al } *) end; {$F+} function closeansiout(var t:textrec):integer; begin t.mode:=fmclosed; closeansiout:=0; end; function closeansiin(var t:textrec):integer; begin t.mode:=fmclosed; closeansiin:=0; end; function sendansiout(var t:textrec):integer; var p:word; begin with t do begin if (mode=fmoutput) then begin p:=0; while (pbufsize) then m:=bufsize-2; repeat setxy(x+p,y); c:=readkey; case c of #0:begin c:=readkey; case c of leftarrowkey : if (p>0) then dec(p); rightarrowkey: if (p0) then if (p=l) then begin dec(p); dec(l); bufptr^[p]:=#0; setxy(x+p,y); putc(' '); end else begin if (p>0) then dec(p); move(bufptr^[p+1],bufptr^[p],l-p-1); bufptr^[l-1]:=' '; showstr(bufptr^,p,l-p); dec(l); end else if (p>0) and (l=0) then dec(p); #27:begin fillchar(bufptr^,l,' '); showstr(bufptr^,0,l); l:=0; p:=0; end; #13:{null}; #10:c:=#13 else begin if (p