[Back to SCREEN SWAG index]  [Back to Main SWAG index]  [Original]

{----------------------------------------------------------------------------}
{ NAME		  : SCREEN.PAS 																  }
{ DESCRIPTION : Dynamic Windowing Unit 												  }
{ AUTHOR 	  : Kim Forwood  <kim.forwood@access.cn.camriv.bc.ca>            }
{ DATE		  : May 30, 1996  															  }
{----------------------------------------------------------------------------}
UNIT Screen;
{$A-,B-,D+,E-,I-,L+,N-,O-,P-,Q-,R-,S-,V-,X-}
INTERFACE
type
	Row = array[1..160] of byte;
	LineArray = array[1..25] of ^Row;
	WinRec = record
		PWin: ^LineArray;
		X1, X2, Y1, Y2: byte;
		Xcoord, Ycoord: byte;
		Wdth,Hght: byte;
		Loc: integer;
      Attr: byte;
	end;
type
   TScrArray = array[0..3999] of byte;
   ScrRec = record
      ScreenArray: TScrArray;
      Xcoord: byte;
      Ycoord: byte;
      TxAttr: byte;
   end;
const
	WinNum: byte = 0;                   { specifies to the current window }
var
	W: array[1..10] of WinRec;          { increase this for more windows  }

   { returns the address of video memory }
   FUNCTION  VidSeg: word;
   { direct video text and color handling routines }
	FUNCTION  ReadXY(X,Y: byte): char;
	PROCEDURE WriteXY(X,Y: byte; Ch: char);
	PROCEDURE ColorXY(X,Y,Attr: byte);
	PROCEDURE ColorAt(X,Y,Len,Attr: byte);
	PROCEDURE WriteAt(X,Y: byte; S: string);
   PROCEDURE ColorWrite(X,Y,Attr: byte; S: string);
   PROCEDURE ColorBlock(x1,y1,x2,y2,Attr: byte);
	FUNCTION  ReadScreen(X,Y,Len: byte): string;
   { save and restore text video to disk file }
	PROCEDURE ScreenSave(FName: string);
	PROCEDURE ScreenRestore(FName: string);
   { close the current pop-up window }
	PROCEDURE CloseWindow;
   { various pop-up window routines }
	PROCEDURE PopWindow(x1,y1,x2,y2,Attr,bAttr,Frame: byte);
	PROCEDURE TitleWindow(x1,y1,x2,y2,Attr,bAttr,tAttr,Frame: byte; Title: string);
	PROCEDURE PlainWindow(x1,y1,x2,y2,Attr: byte);
	PROCEDURE ShadowWindow(x1,y1,x2,y2,Attr,bAttr,Frame: byte);
	PROCEDURE ShadowTitleWindow(x1,y1,x2,y2,Attr,bAttr,tAttr,Frame: byte; Title: string);
	PROCEDURE DialogWindow(Attr,Frame: byte; S: string);
	PROCEDURE MsgWindow(Attr,Frame: byte; S: string);
   PROCEDURE TimedMsgWindow(Attr,Frame: byte; S: string; Wait: word);
	PROCEDURE PromptWindow(var Ch: char; Attr,Frame: byte; S: string);

IMPLEMENTATION
uses Crt;
const
	NilFrame: string[6] = '      ';      { frame 0 }
	SglFrame: string[6] = 'ijڿÀÙ';      { frame 1 }
	DblFrame: string[6] = 'ͺɻȼ';      { frame 2 }
var
	WP: array[1..10] of pointer;
	ArraySize: word;
   Location: word;
	VS : word;

{============================================================================}
 FUNCTION VidSeg: word;
{----------------------------------------------------------------------------}
BEGIN
   if Mem[$0000:$0449] = 7 then VidSeg := $B000
   else VidSeg := $B800;
END; { VidSeg }
{============================================================================}
 FUNCTION ReadXY(X,Y: byte): char;
{----------------------------------------------------------------------------}
begin
	ReadXY := Chr(Mem[VS:160*(Y-1)+2*(X-1)]);
end; { ReadXY }
{============================================================================}
 PROCEDURE WriteXY(X,Y: byte; Ch: char);
{----------------------------------------------------------------------------}
begin
	Mem[VS:160*(Y-1)+2*(X-1)] := Ord(Ch);
end; { WriteXY }
{============================================================================}
 PROCEDURE ColorXY(X,Y,Attr: byte);
{----------------------------------------------------------------------------}
begin
	Mem[VS:160*(Y-1)+2*(X-1)+1] := Attr;
end; { ColorXY }
{============================================================================}
 PROCEDURE ColorAt(X,Y,Len,Attr: byte);
{----------------------------------------------------------------------------}
var
	I: byte;
begin
	for I := 1 to Len do
		Mem[VS:160*(Y-1)+((X+I-1)*2-2)+1] := Attr;
end; { ColorAt }
{============================================================================}
 PROCEDURE WriteAt(X,Y: byte; S: string);
{----------------------------------------------------------------------------}
var
	I: byte;
begin
	for I := 1 to Length(S) do
		Mem[VS:160*(Y-1)+((X+I-1)*2-2)] := Ord(S[I]);
end; { WriteAt }
{============================================================================}
 PROCEDURE ColorWrite(X,Y,Attr: byte; S: string);
{----------------------------------------------------------------------------}
var
   I: byte;
begin
	for I := 1 to Length(S) do begin
		Mem[VS:160*(Y-1)+((X+I-1)*2-2)] := Ord(S[I]);
		Mem[VS:160*(Y-1)+((X+I-1)*2-2)+1] := Attr;
   end;
end; { ColorWrite }
{============================================================================}
 PROCEDURE ColorBlock(x1,y1,x2,y2,Attr: byte);
{----------------------------------------------------------------------------}
var
   Wdth,Hght,I: byte;
begin
   Wdth := X2-X1+1;
   Hght := Y2-Y1+1;
  	for I := 1 to Hght do
      ColorAt(x1,y1-1+I,Wdth,Attr);
end; { ColorBlock }
{============================================================================}
 FUNCTION ReadScreen(X,Y,Len: byte): string;
{----------------------------------------------------------------------------}
var
	S: string[80];
	C: char;
	I: byte;
begin
	S := '';
	for I := 0 to Len-1 do begin
		C := Chr(Mem[VS:160*(Y-1)+2*((X+I)-1)]);
		S := S + C;
	end;
	ReadScreen := S;
end; { ReadScreen }
{============================================================================}
 PROCEDURE ScreenSave(FName: string);
{----------------------------------------------------------------------------}
var
   F: file of ScrRec;
   W: ^ScrRec;
   P: pointer;
begin
	if MaxAvail < 4096 then Exit;
   GetMem(W,SizeOf(ScrRec));
  	W^.Xcoord := WhereX;
	W^.Ycoord := WhereY;
   W^.TxAttr := TextAttr;
	Move(Mem[VS:0000],W^.ScreenArray,4000);
   Assign(F,FName);
   ReWrite(F);
   Write(F,W^);
   Close(F);
   FreeMem(W,SizeOf(ScrRec));
end; { ScreenSave }
{============================================================================}
 PROCEDURE ScreenRestore(FName: string);
{----------------------------------------------------------------------------}
var
   F: file of ScrRec;
   W: ^ScrRec;
   P: pointer;
begin
	if MaxAvail < 4096 then Exit;
   GetMem(W,SizeOf(ScrRec));
   Assign(F,FName);
   {$I-}
   ReSet(F);
   {$I+}
   if IoResult <> 0 then Exit;
   Read(F,W^);
   Close(F);
   Erase(F);
	Move(W^.ScreenArray,Mem[VidSeg:0000],4000);
	Window(1,1,80,25);
	GotoXY(W^.Xcoord,W^.Ycoord);
   TextAttr := W^.TxAttr;
   FreeMem(W,SizeOf(ScrRec));
end; { ScreenRestore }
{============================================================================}
 PROCEDURE GetWindow(X1,Y1,X2,Y2: byte);
{----------------------------------------------------------------------------}
var
   I: byte;
begin
	if (x2 < 79) and (y2 < 25) then begin
		Inc(x2,2);
		Inc(y2);
	end;
	W[WinNum].Loc := (160*(Y1-1)+2*X1)-2;
	W[WinNum].Wdth := (X2-X1+1)*2;
	W[WinNum].Hght := (Y2-Y1+1);
	ArraySize := W[WinNum].Wdth*W[WinNum].Hght;
	Location := W[WinNum].Loc;
	with W[WinNum] do
		for I := 1 to Hght do begin
			GetMem(PWin^[I],Wdth);
			Move(Mem[VS:Location],PWin^[I]^,Wdth);
			Inc(Location,160);
		end;
end; { GetWindow }
{============================================================================}
 PROCEDURE CloseWindow;
{----------------------------------------------------------------------------}
var
	Wdth,Hght,I: byte;
begin
   Location := W[WinNum].Loc;
	Wdth := W[WinNum].Wdth;
	Hght := W[WinNum].Hght;
	ArraySize := Wdth*Hght;
	for I := 1 to Hght do begin
		Move(W[WinNum].PWin^[I]^,Mem[VS:Location],Wdth);
		Inc(Location,160);
	end;
	Window(W[WinNum].X1, W[WinNum].Y1, W[WinNum].X2, W[WinNum].Y2);
	GotoXY(W[WinNum].Xcoord,W[WinNum].Ycoord);
   TextAttr := W[WinNum].Attr;
   begin
      for I := 1 to Hght do FreeMem(W[WinNum].PWin^[I],Wdth);
	   Dispose(W[WinNum].PWin);
   end;
	Dec(WinNum);
end; { CloseWindow }
{============================================================================}
 PROCEDURE DrawBox(X1,Y1,X2,Y2,Attr,Frame: byte);
{----------------------------------------------------------------------------}
var
	X, Y: byte;
	Fm: string[6];
begin
	if Frame = 0 then Fm := NilFrame;
	if Frame = 1 then Fm := SglFrame;
	if Frame = 2 then Fm := DblFrame;
	for X := (X1+1) to (X2-1) do begin
		Mem[VS:160*(Y1-1)+2*(X-1)] := Ord(Fm[1]);
		Mem[VS:160*(Y1-1)+2*(X-1)+1] := Attr;
	end;
	for X := (X1+1) to (X2-1) do begin
		Mem[VS:160*(Y2-1)+2*(X-1)] := Ord(Fm[1]);
		Mem[VS:160*(Y2-1)+2*(X-1)+1] := Attr;
	end;
	for Y := (Y1+1) to (Y2-1) do begin
		Mem[VS:160*(Y-1)+2*(X1-1)] := Ord(Fm[2]);
		Mem[VS:160*(Y-1)+2*(X1-1)+1] := Attr;
		Mem[VS:160*(Y-1)+2*(X2-1)] := Ord(Fm[2]);
		Mem[VS:160*(Y-1)+2*(X2-1)+1] := Attr;
	end;
	Mem[VS:160*(Y1-1)+2*(X1-1)] := Ord(Fm[3]);
	Mem[VS:160*(Y1-1)+2*(X1-1)+1] := Attr;
	Mem[VS:160*(Y1-1)+2*(X2-1)] := Ord(Fm[4]);
	Mem[VS:160*(Y1-1)+2*(X2-1)+1] := Attr;
	Mem[VS:160*(Y2-1)+2*(X1-1)] := Ord(Fm[5]);
	Mem[VS:160*(Y2-1)+2*(X1-1)+1] := Attr;
	Mem[VS:160*(Y2-1)+2*(X2-1)] := Ord(Fm[6]);
	Mem[VS:160*(Y2-1)+2*(X2-1)+1] := Attr;
end; { DrawBox }
{============================================================================}
 PROCEDURE DrawTitleBox(x1,y1,x2,y2,Attr,tAttr,Frame: byte; Title: string);
{----------------------------------------------------------------------------}
var
	X, Y: byte;
begin
	DrawBox(x1,y1,x2,y2,Attr,Frame);
	Title := ' ' + Title + ' ';
	WriteAt(x1+1,y1,Title);
	ColorAt(x1+1,y1,Length(Title),tAttr);
end; { DrawTitleBox }
{============================================================================}
 PROCEDURE DrawShadow(X1,Y1,X2,Y2: byte);
{----------------------------------------------------------------------------}
var
	I,X,Y: byte;
	J: word;
begin
	if (x2 < 79) and (y2 < 25) then begin
		X := X2;
		Y := Y1;
		for I := 1 to Y2-Y1+1 do begin
			J := 160*(Y)+2*(X)+1;
			Mem[VS:J] := $08;
			Mem[VS:J+2] := $08;
			Inc(Y);
		end;
		J := 160*(Y2)+2*(X1+1)+1;
		for I := 1 to X2-X1+1 do begin
			Mem[VS:J] := $08;
			Inc(J,2);
		end;
	end;
end; { DrawShadow }
{============================================================================}
 PROCEDURE WindowInit(x1,y1,x2,y2: byte);
{----------------------------------------------------------------------------}
begin
	Inc(WinNum);
	New(W[WinNum].PWin);
	W[WinNum].Xcoord := WhereX;
	W[WinNum].Ycoord := WhereY;
   W[WinNum].Attr := TextAttr;
	W[WinNum].X1 := Lo(WindMin)+1;
	W[WinNum].X2 := Lo(WindMax)+1;
	W[WinNum].Y1 := Hi(WindMin)+1;
	W[WinNum].Y2 := Hi(WindMax)+1;
end; { WindowInit }
{============================================================================}
 PROCEDURE PopWindow(x1,y1,x2,y2,Attr,bAttr,Frame: byte);
{----------------------------------------------------------------------------}
begin
	if MaxAvail < 4096 then Exit;
	WindowInit(x1,y1,x2,y2);
	Window(1,1,80,25);
	GetWindow(x1,y1,x2,y2);
	DrawBox(x1,y1,x2,y2, bAttr, Frame);
	Window(x1+1,y1+1,x2-1,y2-1);
	TextAttr := Attr;
	ClrScr;
end; { PopWindow }
{============================================================================}
 PROCEDURE TitleWindow(x1,y1,x2,y2,Attr,bAttr,tAttr,Frame: byte; Title: string);
{----------------------------------------------------------------------------}
begin
	if MaxAvail < 4096 then Exit;
	WindowInit(x1,y1,x2,y2);
	Window(1,1,80,25);
	GetWindow(x1,y1,x2,y2);
	DrawTitleBox(X1,Y1,X2,Y2,bAttr,tAttr,Frame,Title);
	Window(X1+1,Y1+1,X2-1,Y2-1);
	TextAttr := Attr;
	ClrScr;
end; { TitleWindow }
{============================================================================}
 PROCEDURE PlainWindow(x1,y1,x2,y2,Attr: byte);
{----------------------------------------------------------------------------}
begin
	if MaxAvail < 4096 then Exit;
	WindowInit(x1,y1,x2,y2);
	GetWindow(x1,y1,x2,y2);
	Window(x1,y1,x2,y2);
	TextAttr := Attr;
	ClrScr;
end; { PlainWindow }
{============================================================================}
 PROCEDURE ShadowWindow(x1,y1,x2,y2,Attr,bAttr,Frame: byte);
{----------------------------------------------------------------------------}
begin
	if MaxAvail < 4096 then Exit;
	WindowInit(x1,y1,x2,y2);
	Window(1,1,80,25);
	GetWindow(x1,y1,x2,y2);
	DrawBox(X1,Y1,X2,Y2,bAttr,Frame);
	DrawShadow(X1,Y1,X2,Y2);
	Window(X1+1,Y1+1,X2-1,Y2-1);
	TextAttr := Attr;
	ClrScr;
end; { ShadowWindow }
{============================================================================}
 PROCEDURE ShadowTitleWindow(x1,y1,x2,y2,Attr,bAttr,tAttr,Frame: byte; Title: string);
{----------------------------------------------------------------------------}
begin
	if MaxAvail < 4096 then Exit;
	WindowInit(x1,y1,x2,y2);
	Window(1,1,80,25);
	GetWindow(x1,y1,x2,y2);
	DrawTitleBox(X1,Y1,X2,Y2,bAttr,tAttr,Frame,Title);
	DrawShadow(X1,Y1,X2,Y2);
	Window(X1+1,Y1+1,X2-1,Y2-1);
	TextAttr := Attr;
	ClrScr;
end; { ShadowTitleWindow }
{============================================================================}
 PROCEDURE DialogWindow(Attr,Frame: byte; S: string);
{----------------------------------------------------------------------------}
var
	x1, x2: integer;
	Ch: char;
begin
	x1 := 40 - (Length(S) div 2) - 2;
	x2 := 40 + (Length(S) div 2) + 2;
	{CursOff;}
	ShadowWindow(x1,10,x2,12,Attr,Attr,Frame);
	Write(' ', S);
	Ch := ReadKey;
	CloseWindow;
end; { DialogWindow }
{============================================================================}
 PROCEDURE MsgWindow(Attr,Frame: byte; S: string);
{----------------------------------------------------------------------------}
var
	x1, x2: integer;
begin
	x1 := 40 - (Length(S) div 2) - 2;
	x2 := 40 + (Length(S) div 2) + 2;
	{CursOff;}
	ShadowWindow(x1,12,x2,14,Attr,Attr,Frame);
	Write(' ', S);
end; { MsgWindow }
{============================================================================}
 PROCEDURE TimedMsgWindow(Attr,Frame: byte; S: string; Wait: word);
{----------------------------------------------------------------------------}
begin
   MsgWindow(Attr,Frame,S);
   Delay(Wait);
   CloseWindow;
end; { TimedMsgWindow }
{============================================================================}
 PROCEDURE PromptWindow(var Ch: char; Attr,Frame: byte; S: string);
{----------------------------------------------------------------------------}
var
	x1, x2: integer;
begin
	x1 := 40 - (Length(S) div 2) - 2;
	x2 := 40 + (Length(S) div 2) + 2;
	{CursOff;}
	ShadowWindow(x1,12,x2,14,Attr,Attr,Frame);
	Write(' ', S);
	Ch := UpCase(ReadKey);
	CloseWindow;
end; { PromptWindow }
BEGIN
   VS := VidSeg;
END.

[Back to SCREEN SWAG index]  [Back to Main SWAG index]  [Original]