home *** CD-ROM | disk | FTP | other *** search
- {$A+,B-,D+,E+,F-,I+,L+,N+,O-,R-,S-,V-}
- Unit Windows;
-
- Interface
-
- Uses Crt;
-
- Const
- On = True;
- Off = False;
- Type
- BorderType = (None,Single,Double,DoubleTop,DoubleSide,Solid);
- TitleType = (LeftJustify,Centered,RightJustify);
- ScreenType = Array[0..3999] of Byte;
- ScreenPtr = ^ScreenRecord;
- ScreenRecord = Record
- Screen : ^ScreenType; { points to saved screen tile }
- uX,uY,lX,lY : Byte; { holds new window coordinates }
- UpperCors : Word; { holds old window coordinates }
- LowerCors : Word; { holds window coordinates }
- OldAttr : Word; { holds character attribute }
- XY : Word; { holds the cursor position }
- Cursor : Word; { holds the cursor shape }
- Previous : ScreenPtr; { pointer to underlying window }
- End;
-
-
- Var
- UnderScreen : ScreenPtr; { points to the saved screen }
- UseMono : Boolean; { true if use B/W attribute only }
- TranslateBW : Boolean; { change attributes when mono? }
-
- Procedure Initialize;
-
- Procedure DrawBox(X1,Y1,X2,Y2,Forground,Background : Integer;
- Border : BorderType);
-
- Procedure Title(Line : String;TitleFormat : TitleType;Border : BorderType);
-
- Procedure Footer(Line : String;TitleFormat : TitleType;Border : BorderType);
-
- Procedure Cursor(State : Boolean);
- { Turns the cursor on or off. }
-
- Procedure DuplicateChar(Character : Char;Count : Integer);
-
- Procedure DrawVerticalLine(X,Y,Length : Word;Border : BorderType);
-
- Procedure DrawHorizontalLine(X,Y,Length : Word;Border :BorderType);
-
- Procedure SaveScreen(X1,Y1,X2,Y2 : Integer);
-
- Procedure MakeWindow(X1,Y1,X2,Y2,Forground,BackGround : Integer;
- Border : BorderType);
-
- Procedure RemoveWindow;
-
- Function VideoMode : Byte;
-
- InLine($B4/$0F/ { mov ah,0Fh }
- $CD/$10); { int 10h }
-
- Procedure GotoXYAbs(XY : Word);
-
- InLine($5A/ { pop dx }
- $B4/$02/ { mov ah,2 }
- $30/$FF/ { xor bh,bh }
- $CD/$10); { int 10h }
-
- Function WhereXYAbs : Word;
-
- InLine($B4/$03/ { mov ah,3 }
- $30/$FF/ { xor bh,bh }
- $CD/$10/ { int 10h }
- $89/$D0); { mov ax,dx }
-
- Procedure SetCursor(Cursor : Word);
-
- InLine($59/ { pop cx }
- $B4/$01/ { mov ah,1 }
- $CD/$10); { int 10h }
-
- Function CursorShape : Word;
-
- InLine($B4/$03/ { mov ah,3 }
- $30/$FF/ { xor bh,bh }
- $CD/$10/ { int 10h }
- $89/$C8); { mov ax,cx }
-
- Type
- BorderPart = (Top,Side,UpperLeft,UpperRight,LowerLeft,LowerRight,
- TopConnect,BottomConnect,LeftConnect,RightConnect,Cross);
-
- Const
- Borders : Array[Single..Solid,Top..Cross] of Char =
- (('─','│','┌','┐','└','┘','┬','┴','├','┤','┼'), {single}
- ('═','║','╔','╗','╚','╝','╦','╩','╠','╣','╬'), {double}
- ('═','│','╒','╕','╘','╛','╤','╧','╞','╡','╪'), {combo }
- ('─','║','╓','╖','╙','╜','╥','╨','╟','╢','╫'), {combo }
- (' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '));{solid }
-
- { window type 0 has no border, type 5 uses the space character }
-
- Implementation
-
- Var
- MonoScreen : ScreenType Absolute $B000:0000; { monochome screen }
- ColorScreen : ScreenType Absolute $B800:0000; { CGA screen }
- CurrentScreen : ScreenPtr; { place to save screen info }
- ScreenSaved : Boolean; { Are any windows on the heap?}
-
- Procedure Cursor(State : Boolean); External; {$L cursor.obj }
-
- Procedure ScreenToBuffer(Var Source,Target : ScreenType;
- X1,Y1,X2,Y2: Integer);
-
- Var
- Loop : Word;
- Width : Integer;
- Offset : Integer;
- TIndex : Integer;
- SIndex : Integer;
-
- Begin
- Offset := Pred(X1) Shl 1;
- Width := (X2 - Pred(X1)) Shl 1;
- For Loop := Y1 to Y2 Do
- Begin
- SIndex := Pred(Loop) * 160 + Offset;
- TIndex := (Loop-Y1) * Width;
- If CheckSnow Then Repeat Until Port[$3DA] AND 1 = 1;
- Move(Source[SIndex],Target[TIndex],Width);
- End;
- End;
-
- Procedure BufferToScreen(Var Source,Target : ScreenType;
- X1,Y1,X2,Y2: Integer);
-
- Var
- Loop : Word;
- Width : Integer;
- Offset : Integer;
- SIndex : Integer;
- TIndex : Integer;
-
- Begin
- Offset := Pred(X1) Shl 1;
- Width := (X2 - Pred(X1)) Shl 1;
- For Loop := Y1 to Y2 Do
- Begin
- TIndex := Pred(Loop) * 160 + Offset;
- SIndex := (Loop-Y1) * Width;
- If CheckSnow Then Repeat Until Port[$3DA] AND 9 = 9;
- Move(Source[SIndex],Target[TIndex],Width);
- End;
- End;
-
- Procedure SaveScreen(X1,Y1,X2,Y2 : Integer);
-
- { saves the screen memory, window coordinates, }
- { cursor position, and character attribute. }
-
- Var
- ScreenSize : Integer;
- Width : Integer;
- Height : Integer;
- NewScreen : ScreenPtr;
-
- Begin
- Width := Succ(X2) - X1;
- Height := Succ(Y2) - Y1;
- ScreenSize := (Width * Height) Shl 1;
- GetMem(NewScreen,SizeOf(ScreenRecord));
- With NewScreen^ Do
- Begin
- uX := X1;
- uY := Y1;
- lX := X2;
- lY := Y2;
- GetMem(Screen,ScreenSize);
- If ScreenSaved
- Then Previous := CurrentScreen
- Else Previous := Nil;
- ScreenSaved := True;
- If VideoMode = 7
- Then ScreenToBuffer(MonoScreen,Screen^,X1,Y1,X2,Y2)
- Else ScreenToBuffer(ColorScreen,Screen^,X1,Y1,X2,Y2);
- UpperCors := WindMin; { save the window coordinates }
- LowerCors := WindMax;
- OldAttr := TextAttr; { save the character attribute }
- XY := WhereXYAbs; { save the cursor position }
- Cursor := CursorShape;
- End;
- CurrentScreen := NewScreen;
- UnderScreen := CurrentScreen;
- End;
-
- Procedure DropWindow;
-
- Var
- OldScreen : ScreenPtr;
-
- Begin
- With CurrentScreen^ Do
- Begin
- If Previous = Nil Then ScreenSaved := False;
- OldScreen := CurrentScreen; { release heap memory }
- CurrentScreen := Previous;
- UnderScreen := CurrentScreen;
- FreeMem(OldScreen,SizeOf(ScreenRecord));
- End;
- End;
-
- Procedure RemoveWindow;
-
- { Restores screen memory, window coordinates, }
- { cursor position, and character attribute. }
-
- Var
- Height : Integer;
- Width : Integer;
- ScreenSize : Integer;
-
-
- Begin
- If Not ScreenSaved Then Exit;
- With CurrentScreen^ Do
- Begin
- If VideoMode = 7 Then
- BufferToScreen(Screen^,MonoScreen,uX,uY,lX,lY)
- Else BufferToScreen(Screen^,ColorScreen,uX,uY,lX,lY);
- Width := Succ(lX) - uX;
- Height := Succ(lY) - uY;
- ScreenSize := (Width * Height) Shl 1;
- FreeMem(Screen,ScreenSize);
- WindMin := UpperCors; { restore the window coordinates }
- WindMax := LowerCors;
- TextAttr := OldAttr; { restore the character attribute }
- GotoXYAbs(XY); { restore the cursor position }
- SetCursor(Cursor);
- DropWindow;
- End;
- End;
-
- Procedure DuplicateChar(Character : Char;Count : Integer);
-
- { Uses the BIOS to write multiple copies of a character to the screen }
-
- Begin
- InLine($8A/$46/<Character/ { mov al,byte ptr char[bp] }
- $8B/$4E/<Count/ { mov cx,count[bp] }
- $B4/$09/ { mov ah,09h }
- $8A/$1E/>TextAttr/ { mov bl,[TextAttr] }
- $32/$FF/ { xor bh,bh }
- $CD/$10); { int 10h }
- End;
-
- Procedure HeaderFooter(Line : String;
- Row : Integer;
- TitleFormat : TitleType;
- Border : BorderType);
-
- Var
- WMin,WMax : Word;
- oX,oY,X : Integer;
- Center : Integer;
- Len : Integer;
-
- Begin
- WMin := WindMin;
- WMax := WindMax;
- oX := WhereX;
- oY := WhereY;
- WindMin := WMin - $0101;
- WindMax := WMax + $0101;
- Len := Length(Line) Shr 1;
- Case TitleFormat Of
- LeftJustify : X := 3;
- Centered : X := ((Succ(Lo(WindMax)) - Lo(WindMin)) Shr 1) - Len;
- RightJustify : X := Lo(WindMax) - Lo(Windmin) - Length(Line) - 2;
- End;
- GotoXY(X,Row);
- Write(Borders[Border,RightConnect],Line,Borders[Border,LeftConnect]);
- WindMin := WMin;
- WindMax := WMax;
- GotoXY(oX,oY);
- End;
-
-
- Procedure Title(Line : String;
- TitleFormat : TitleType;
- Border : BorderType);
-
- Begin
- HeaderFooter(Line,1,TitleFormat,Border);
- End;
-
- Procedure Footer(Line : String;
- TitleFormat : TitleType;
- Border : BorderType);
-
- Begin
- HeaderFooter(Line,Hi(WindMax)-Hi(WindMin)+3,TitleFormat,Border);
- End;
-
- Procedure FastPutVertical(Ch : Char;Count,Col,Row : Word); External;
- Procedure FastPutHorizontal(Ch : Char;Count,Col,Row : Word); External;
- {$L fastput.obj}
-
- Procedure DrawVerticalLine(X,Y,Length : Word;Border : BorderType);
-
- { draws a vertical line with the proper connection }
- { type for interfacing with a surrounding window. }
-
- Var
- Loop : Word;
- WMax : Word;
- WMin : Word;
- xX,xY : Integer;
-
- Begin
- WMax := WindMax;
- WMin := WindMin;
- xX := WhereX;
- xY := WhereY;
- Window(1,1,80,25);
- FastPutVertical(Borders[Border,Side],Length-2,X,Succ(Y));
- GotoXY(X,Y);
- Write(Borders[Border,TopConnect]);
- GotoXY(X,Y+Pred(Length));
- Write(Borders[Border,BottomConnect]);
- WindMax := WMax;
- WindMin := WMin;
- GotoXY(xX,xY);
- End;
-
- Procedure DrawHorizontalLine(X,Y,Length : Word;Border :BorderType);
-
- { draws a horizontal line with the proper connection }
- { type for interfacing with a surrounding window. }
-
- Var
- Loop : Word;
- WMax : Word;
- WMin : Word;
- xX,xY : Integer;
-
- Begin
- WMax := WindMax;
- WMin := WindMin;
- xX := WhereX;
- xY := WhereY;
- Window(1,1,80,25);
- GotoXY(X,Y);
- Write(Borders[Border,LeftConnect]);
- GotoXY(X+Pred(Length),Y);
- Write(Borders[Border,RightConnect]);
- FastPutHorizontal(Borders[Border,Top],Length-2,Succ(X),Y);
- WindMax := WMax;
- WindMin := WMin;
- GotoXY(xX,xY);
- End;
-
- Procedure DrawBox(X1,Y1,X2,Y2,Forground,Background : Integer;Border : BorderType);
-
- { Draws a double box around the window and reduces the window size. }
- { Inputs are the same as for MakeWindow. }
-
- Var
- Loop : Integer;
-
- Begin
- If UseMono Then
- Begin { Make sure the attributes can be }
- Forground := 7; { seen on a monochrome screen. }
- Background := 0;
- End;
- TextColor(Forground);
- TextBackground(Background);
- Window(1,1,80,25);
- If Border = None
- Then Window(X1,Y1,X2,Y2)
- Else Begin
- FastPutVertical(Borders[Border,Side],Y2-Y1,X1,Succ(Y1));
- FastPutVertical(Borders[Border,Side],Y2-Y1,X2,Succ(Y1));
- GotoXY(X1,Y1);
- FastPutHorizontal(Borders[Border,Top],X2-X1,X1,Y1);{ top }
- FastPutHorizontal(Borders[Border,Top],X2-X1,X1,Y2);{ bottom }
- Write(Borders[Border,UpperLeft]); { upper left }
- GotoXY(X2,Y1);
- Write(Borders[Border,UpperRight]); { upper right }
- GotoXY(X1,Y2);
- Write(Borders[Border,LowerLeft]); { lower left }
- FastPutHorizontal(Borders[Border,LowerRight],1,X2,Y2); { lower right }
- Window(Succ(X1),Succ(Y1),Pred(X2),Pred(Y2)); { reduce the window size }
- End;
- ClrScr;
- End;
-
- Procedure MakeWindow(X1,Y1,X2,Y2,Forground,BackGround : Integer;
- Border : BorderType);
-
- { Saves the screen and draws a box. }
-
- { Inputs are: The four window coordinates, }
- { the forground color, }
- { the background color, and }
- { the border type (see DrawBox) }
-
- Begin
- SaveScreen(X1,Y1,X2,Y2);
- DrawBox(X1,Y1,X2,Y2,Forground,Background,Border);
- End;
-
- Function EGA : Boolean;
-
- Begin
- If (MemW[$C000:$001E] = $4249) And (Mem[$C000:$0020] = $4D)
- Then EGA := TRUE
- Else EGA := FALSE;
- End;
-
- Procedure Initialize;
-
- Begin
- UseMono := FALSE;
- ScreenSaved := FALSE;
- UnderScreen := Nil; { no screens saved }
- DirectVideo := TRUE;
- CheckSnow := TRUE;
- If (VideoMode = 7) Or EGA Then CheckSnow := FALSE;
- If VideoMode = 7 Then UseMono := True;
- End;
-
- Begin
- Initialize;
- End.
-