[Back to TSR SWAG index] [Back to Main SWAG index] [Original]
{
>Basically a function that allows me to have 3 lines at the top non scrollabl
>(that I can change, the content of the lines), but so the stuff underthem
>scrolles...
Well, when you don't like the way the BIOS scrolls the screen, change
the BIOS!
Here's an interesting program that I just wrote for this purpose. It
installs a TSR-like program that interferes with the BIOS scroll-up
routine and forces the top to be a variable you set.
While debugging the program, I ran into a bit of trouble with the way
that TP handles interrupts. If you notice, half of the ISR has turned
into restoring the registers that TP trashes!
}
Uses Dos, Crt; {Crt only used by main pgm}
var
TopLine : byte;
OldInt : Procedure;
{Procedure Catch is the actual ISR, filtering out BIOS SCROLL-UP commands, and
forcing the top of the scroll to be the value [TopLine] }
{$F+}
procedure Catch(Flags, rCS, rIP, rAX, rBX, rCX, rDX, rSI, rDI, rDS, rES, rBP: Word); Interrupt;
{ Procedure Catch; interrupt;}
begin {Catch}
asm
MOV AX, Flags
SAHF
MOV AX, rAX
MOV BX, rBX
MOV CX, rCX
MOV DX, rDX
MOV SI, rSI
MOV DI, rDI
CMP AH, 06
JNE @Pass
CMP CH, TopLine
JA @Pass
MOV CH, TopLine
@Pass:
end;
OldInt; {Pass through to old handler}
asm
MOV rAX, AX
MOV rBX, BX
MOV rCX, CX
MOV rDX, DX
MOV rSI, SI
MOV rDI, DI
end;
end; {Catch}
{$F-}
Procedure Install;
begin
GetIntVec($10, Addr(OldInt));
SetIntVec($10, Addr(Catch));
end;
Procedure DeInstall;
begin
SetIntVec($10, Addr(OldInt));
end;
begin
ClrScr;
DirectVideo := TRUE;
TopLine := 5; {Keep 5+1 lines at top of screen}
Install;
while true do readln;
end.
{
>p.p.s I also need a routine (preferably in Turbo Pascal 7 ASM) that saves t
> content of the current screen in an ANSI file on the disk. I saw one
> a while ago in SWAG, but I can't seem to find it now (I'm a dist site
> but still can't find it).
Also, since I didn't have anything better to do, I sat down and did a
version of your screen->ANSI. It's rather primitive... it does a 80x24
dump with auto-EOLn seensing, does no CRLF if the line is 80 chars long
(relies on screen wrap) and no macroing. If you want to, you can add
macroing, which replaces a number of spaces with a single ANSI 'set
cursor' command. Well, here goes...
}
Procedure Xlate(var OutFile : text); {by Erik Anderson}
{The screen is basically an array of elements, each element containing one
a one-byte character and a one-byte color attribute}
const
NUMROWS = 25;
NUMCOLS = 80;
type
ElementType = record
ch : char;
Attr : byte;
end;
ScreenType = array[1..NUMROWS,1..NUMCOLS] of ElementType;
{The Attribute is structured as follows:
bit 0: foreground blue element
bit 1: " green element
bit 2: " red element
bit 3: high intensity flag
bit 4: background blue element
bit 5: " green element
bit 6: " red element
bit 7: flash flag
The following constant masks help the program acess different parts
of the attribute}
const
TextMask = $07; {0000 0111}
BoldMask = $08; {0000 1000}
BackMask = $70; {0111 0000}
FlshMask = $80; {1000 0000}
BackShft = 4;
ESC = #$1B;
{ANSI colors are not the same as IBM colors... this table fixes the
discrepancy:}
ANSIcolors : array[0..7] of byte = (0, 4, 2, 6, 1, 5, 3, 7);
{This procedure sends the new attribute to the ANSI dump file}
Procedure ChangeAttr(var Outfile : text; var OldAtr : byte; NewAtr : byte);
var
Connect : string[1]; {Is a seperator needed?}
begin
Connect := '';
write(Outfile, ESC, '['); {Begin sequence}
If (OldAtr AND (BoldMask+FlshMask)) <> {Output flash & blink}
(NewAtr AND (BoldMask+FlshMask)) then begin
write(Outfile, '0');
If NewAtr AND BoldMask <> 0 then write(Outfile, ';1');
If NewAtr AND FlshMask <> 0 then write(Outfile, ';5');
OldAtr := $FF; Connect := ';'; {Force other attr's to print}
end;
If OldAtr AND BackMask <> NewAtr AND BackMask then begin
write(OutFile, Connect,
ANSIcolors[(NewAtr AND BackMask) shr BackShft] + 40);
Connect := ';';
end;
If OldAtr AND TextMask <> NewAtr AND TextMask then begin
write(OutFile, Connect,
ANSIcolors[NewAtr AND TextMask] + 30);
end;
write(outfile, 'm'); {Terminate sequence}
OldAtr := NewAtr;
end;
{Does this character need a changing of the attribute? If it is a space,
then only the background color matters}
Function AttrChanged(Attr : byte; ThisEl : ElementType) : boolean;
var
Result : boolean;
begin
Result := FALSE;
If ThisEl.ch = ' ' then begin
If ThisEl.Attr AND BackMask <> Attr AND BackMask then
Result := TRUE;
end else begin
If ThisEl.Attr <> Attr then Result := TRUE;
end;
AttrChanged := Result;
end;
var
Screen : ScreenType absolute $b800:0000;
ThisAttr, TestAttr : byte;
LoopRow, LoopCol, LineLen : integer;
begin {Xlate}
ThisAttr := $FF; {Force attribute to be set}
For LoopRow := 1 to NUMROWS do begin
LineLen := NUMCOLS; {Find length of line}
While (LineLen > 0) and (Screen[LoopRow, LineLen].ch = ' ')
and not AttrChanged($00, Screen[LoopRow, LineLen])
do Dec(LineLen);
For LoopCol := 1 to LineLen do begin {Send stream to file}
If AttrChanged(ThisAttr, Screen[LoopRow, LoopCol])
then ChangeAttr(Outfile, ThisAttr, Screen[LoopRow, LoopCol].Attr);
write(Outfile, Screen[LoopRow, LoopCol].ch);
end;
If LineLen < 80 then writeln(OutFile); {else wraparound occurs}
end;
end; {Xlate}
var
OutFile : text;
begin
Assign(OutFile, 'dump.scn');
Rewrite(OutFile);
Xlate(OUtFile);
Close(OUtFile);
end.
[Back to TSR SWAG index] [Back to Main SWAG index] [Original]