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

UNIT Win; { Win.Pas }

{$S-}{$I-}{$R-}

INTERFACE

USES Crt, Cursor, FadeUnit;

TYPE
  PTitleStr = ^TitleStr;
  TitleStr = STRING [63];

  PFrame = ^TFrame;
  TFrame = ARRAY [1..8] OF CHAR;

  TVertFrameChars = ARRAY [1..3] OF CHAR;

  { Text color attr type }

  PTextAttr = ^TTextAttr;
  TTextAttr = BYTE;

  { Window rectangle type }

  PRect = ^TRect;
  TRect = RECORD
    Left, Top, Right, Bottom : BYTE
  END;

  PWinState = ^TWinState;
  TWinState = RECORD
    WindMin,
    WindMax : WORD;
    WHEREX,
    WHEREY : BYTE;
    TextAttr : TTextAttr
  END;

  PWinRec = ^TWinRec;
  TWinRec = RECORD
    Next : PWinRec;
    State : TWinState;
    Title : PTitleStr;
    TitleColor,
    FrameColor : TTextAttr;
    Size : WORD;
    Buffer : POINTER
  END;

  PWindowStruct = ^TWindowStruct;
  TWindowStruct = RECORD
    Rect : TRect;
    TitleColor,
    FrameColor : TTextAttr;
    Title : TitleStr
  END;

CONST
  None = '';

  VertFrame   : TVertFrameChars = '³ºÛ';

  { Display combination codes returned by the GetDisplay function }

  gdNoDisplay = $00; { No display }
  gdMono      = $01; { Monochrome adapter w/ monochrome display }
  gdCGA       = $02; { CGA w/ color display }
  gdEGA       = $04; { EGA w/ color display }
  gdEGAMono   = $05; { EGA w/ monochrome display }
  gdPGA       = $06; { PGA w/ color display }
  gdVGAMono   = $07; { VGA w/ monochrome analog display }
  gdVGA       = $08; { VGA w/ color analog display }
  gdMCGADig   = $0A; { MCGA w/ digital color display }
  gdMCGAMono  = $0B; { MCGA w/ monochrome analog display }
  gdMCGA      = $0C; { MCGA w/ color analog display }
  gdUnknown   = $FF; { Unknown display type }

  { Window frame classes }

  SingleFrame : TFrame       = 'ÚÄ¿³³ÀÄÙ';
  DoubleFrame : TFrame       = 'ÉÍ»ººÈͼ';
  SingleDoubleFrame : TFrame = 'ÖÄ·ººÓĽ';
  DoubleSingleFrame : TFrame = 'Õ͸³³Ô;';
  BarFrame : TFrame          = 'ÛßÛÛÛÛÜÛ';

  { Window frame constants }

  frNone         = 0;  { Window has no frame }
  frSingle       = 1;  { Window has single frame }
  frSingleDouble = 2;  { Window has single (horiz) and double (vert) frames }
  frDouble       = 3;  { Window has double frame }
  frDoubleSingle = 4;  { Window has double (horiz) and single (vert) frames }
  frBar          = 5;  { Window has a rectangular bar frame }

  { Shadow color attributes }

  winShadowAttr : TTextAttr = $07;

  FontOpenReg : ARRAY [1..10] OF BYTE =
    ($02, $04, $04, $07, $05, $00, $06, $04, $04, $02);
  FontCloseReg : ARRAY [1..10] OF BYTE =
    ($02, $03, $04, $03, $05, $10, $06, $0E, $04, $00);

  FadeDelay = 10; { Fade screen delay time for
    SaveDosScreen and RestoreDosScreen functions }

VAR
  WinShadow : BOOLEAN;
  WinCount : INTEGER;
  TopWindow : PWinRec;
  WinExplodeDelay, ScreenHeight, WinFrame : BYTE;
  ScreenWidth : WORD;
  Screen : POINTER;

FUNCTION  GetDisplay : BYTE;
PROCEDURE SetTextFont (VAR Font; StartChar, BytePerChar, CharCount : BYTE);
FUNCTION  GetTextFont (FontCode : BYTE) : POINTER;
PROCEDURE WriteStr (X, Y : BYTE; S : STRING; Color : TTextAttr);
PROCEDURE WriteStrV (X, Y : BYTE; S : STRING; Color : TTextAttr);
PROCEDURE WriteChar (X, Y, Count : BYTE; Ch : CHAR; Color : TTextAttr);
PROCEDURE FillWin (Ch : CHAR; Color : TTextAttr);
PROCEDURE ReadWin (VAR Buf);
PROCEDURE WriteWin (VAR Buf);
FUNCTION  WinSize : WORD;
PROCEDURE SaveWin (VAR W : TWinState);
PROCEDURE RestoreWin (VAR W : TWinState);
PROCEDURE GetFrame (FrameNum : BYTE; VAR Frame : TFrame);
PROCEDURE FrameWin (Title : TitleStr;
                    Frame : TFrame; TitleColor, FrameColor : TTextAttr);
PROCEDURE UnFrameWin;
FUNCTION  ScrReadChar (X, Y : BYTE) : CHAR;
PROCEDURE ScrWriteChar (X, Y : BYTE; Ch : CHAR);
FUNCTION  ScrReadAttr (X, Y : BYTE) : TTextAttr;
PROCEDURE ScrWriteAttr (X, Y : BYTE; Color : TTextAttr);
PROCEDURE WindowIndirect (Rect : TRect);
FUNCTION  PtInRect (X, Y : BYTE; Rect : TRect) : BOOLEAN;
PROCEDURE GetWindowRect (VAR Rect : TRect);
PROCEDURE GetWindowRectExt (X1, Y1, X2, Y2 : BYTE; VAR Rect : TRect);
PROCEDURE ClearWin (X1, Y1, X2, Y2 : BYTE; Color : TTextAttr);
PROCEDURE ShadowWin (X1, Y1, X2, Y2 : BYTE);
PROCEDURE CreateWin (X1, Y1, X2, Y2 : BYTE;
                    TitleColor, FrameColor : TTextAttr; Title : TitleStr);
PROCEDURE CreateWinIndirect (WS : TWindowStruct);
FUNCTION  OpenWin (X1, Y1, X2, Y2 : BYTE;
                  TitleColor, FrameColor : TTextAttr; Title : TitleStr) : BOOLEAN;
FUNCTION  OpenWinIndirect (WS : TWindowStruct) : BOOLEAN;
FUNCTION  CloseWin : BOOLEAN;
FUNCTION  MoveWin (Left, Top : BYTE) : BOOLEAN;
FUNCTION  SaveDOSScreen (UseFade, RestoreScreen : BOOLEAN) : BOOLEAN;
FUNCTION  RestoreDOSScreen (UseFade : BOOLEAN) : BOOLEAN;
PROCEDURE SetBlink (BlinkOn : BOOLEAN);

IMPLEMENTATION

{$L win.obj}

VAR OldCursor : WORD;

FUNCTION MakeWord (HI, LO : BYTE) : WORD; assembler;
Asm
  MOV AH, HI
  MOV AL, LO
END; { MakeWord }

FUNCTION GetDisplay; assembler;
Asm
MOV AX, 1A00h
  INT 10h
  MOV AL, BL
END; { GetDisplay }

PROCEDURE SetRegisters; near; assembler;
asm
  MOV AX, SEG @Data
  MOV DS, AX
  MOV CX, 0002h
  MOV DX, 03C4h
  CALL @@1
  MOV CX, 0003h
  MOV DL, 0CEh
@@1 :
  LODSB
  OUT DX, AL
INC DX
  LODSB
OUT DX, AL
  DEC DX
  LOOP @@1
END; { SetRegisters }

PROCEDURE SetTextFont; assembler;
Asm
  MOV BX, SegA000
  PUSH DS
  MOV AX, WORD PTR [Font + 2]
  MOV DS, AX
  XOR AX, AX
  MOV AL, StartChar
  MOV DI, AX
  MOV SI, WORD PTR [Font]
  MOV AX, BX
  MOV BL, BytePerChar
XOR BH, BH
  PUSH ES
MOV ES, AX
  MOV CL, 5
  SHL DI, CL
  PUSH SI
  PUSH DS
  CLI
  MOV SI, OFFSET FontOpenReg
  CALL SetRegisters
  POP DS
  POP SI
  MOV AX, DI
@@1 :
  MOV DI, AX
  MOV CX, BX
  REP MOVSB
  ADD AX, 0020h
  DEC CharCount
JNE @@1
  MOV SI, OFFSET FontCloseReg
CALL SetRegisters
  STI
  POP ES
  POP DS
END; { SetTextFont }

FUNCTION GetTextFont; assembler;
Asm
  MOV AX, 1130h
  MOV BH, FontCode
  INT 10h
  MOV AX, BP
  MOV DX, ES
END; { GetTextFont }

PROCEDURE WriteStr (X, Y : BYTE; S : STRING; Color : TTextAttr); EXTERNAL;

PROCEDURE WriteStrV (X, Y : BYTE; S : STRING; Color : TTextAttr);
VAR Index : INTEGER;
BEGIN
  FOR Index := 1 TO LENGTH (S) DO
    WriteChar (X, PRED (Y + Index), 1, S [Index], Color)
END; { WriteStrV }

PROCEDURE WriteChar (X, Y, Count : BYTE; Ch : CHAR; Color : TTextAttr);
EXTERNAL;

PROCEDURE FillWin (Ch : CHAR; Color : TTextAttr); EXTERNAL;
PROCEDURE WriteWin (VAR Buf); EXTERNAL;
PROCEDURE ReadWin (VAR Buf); EXTERNAL;
FUNCTION  WinSize : WORD; EXTERNAL;

PROCEDURE SaveWin (VAR W : TWinState);
BEGIN
  W.WindMin := WindMin;
  W.WindMax := WindMax;
W.WHEREX := WHEREX;
  W.WHEREY := WHEREY;
W.TextAttr := TextAttr
END; { SaveWin }

PROCEDURE RestoreWin (VAR W : TWinState);
BEGIN
  WindMin := W.WindMin;
  WindMax := W.WindMax;
  GOTOXY (W.WHEREX, W.WHEREY);
  TextAttr := W.TextAttr
END; { RestoreWin }

PROCEDURE GetFrame (FrameNum : BYTE; VAR Frame : TFrame);
BEGIN
  CASE FrameNum OF
    frSingle : Frame := SingleFrame;
    frDouble : Frame := DoubleFrame;
    frSingleDouble : Frame := SingleDoubleFrame;
frDoubleSingle : Frame := DoubleSingleFrame;
    frBar : Frame := BarFrame;
ELSE FILLCHAR (Frame, SIZEOF (Frame), BYTE ( - 1) )
  END
END; { GetFrame }

PROCEDURE FrameWin (Title : TitleStr;
  Frame : TFrame; TitleColor, FrameColor : TTextAttr);

VAR W, H, Y : WORD;

BEGIN
W := LO (WindMax) - LO (WindMin) + 1;
H := HI (WindMax) - HI (WindMin) + 1;
WriteChar (1, 1, 1, Frame [1], FrameColor);
WriteChar (2, 1, W - 2, Frame [2], FrameColor);
WriteChar (W, 1, 1, Frame [3], FrameColor);
IF LENGTH (Title) > W - 2 THEN Title [0] := CHR (W - 2);
WriteStr ( (W - LENGTH (Title) ), 1, Title, TitleColor);

FOR Y := 2 TO H - 1 DO
BEGIN
WriteChar (1, Y, 1, Frame [4], FrameColor);
    WriteChar (W, Y, 1, Frame [5], FrameColor)
END;
  WriteChar (1, H, 1, Frame [6], FrameColor);
  WriteChar (2, H, W - 2, Frame [7], FrameColor);
  WriteChar (W, H, 1, Frame [8], FrameColor);
  INC (WindMin, $0101);
  DEC (WindMax, $0101)
END; { FrameWin }

PROCEDURE UnFrameWin;
BEGIN
  DEC (WindMin, $0101);
  INC (WindMax, $0101)
END; { UnFrameWin }

FUNCTION ScrReadChar; assembler;
Asm
  LES DI, Screen
  XOR AH, AH
  MOV AL, Y
DEC AX
  MUL ScreenWidth
  SHL AX, 1
  XOR DH, DH
  MOV DL, X
  SHL DX, 1
  DEC DX
  DEC DX
  ADD AX, DX
  MOV DI, AX
  MOV AL, BYTE PTR [ES : DI]
  {ScrReadChar := Char(Ptr(Seg(Screen^),
    (Y - 1) * ScreenWidth * 2 + (X * 2) - 2)^)}
END; { ScrReadChar }

PROCEDURE ScrWriteChar; assembler;
Asm
  LES DI, Screen
  XOR AH, AH
MOV AL, Y
  DEC AX
  MUL ScreenWidth
  SHL AX, 1
  XOR DH, DH
  MOV DL, X
  SHL DX, 1
  DEC DX
  DEC DX
  ADD AX, DX
  MOV DI, AX
  MOV AL, Ch
  MOV BYTE PTR [ES : DI], AL
  {Char(Ptr(Seg(Screen^),
    (Y - 1) * ScreenWidth * 2 + (X * 2) - 2)^) := Ch}
END; { ScrWriteChar }

FUNCTION ScrReadAttr; assembler;
Asm
LES DI, Screen
  XOR AH, AH
  MOV AL, Y
  DEC AX
  MUL ScreenWidth
  SHL AX, 1
  XOR DH, DH
  MOV DL, X
  SHL DX, 1
  DEC DX
  ADD AX, DX
  MOV DI, AX
  MOV AL, BYTE PTR [ES : DI]
  {ScrReadAttr := TTextAttr(Ptr(Seg(Screen^),
    (Y - 1) * ScreenWidth * 2 + (X * 2) - 1)^)}
END; { ScrReadAttr }

PROCEDURE ScrWriteAttr; assembler;
Asm
LES DI, Screen
  XOR AH, AH
  MOV AL, Y
  DEC AX
  MUL ScreenWidth
  SHL AX, 1
  XOR DH, DH
  MOV DL, X
  SHL DX, 1
  DEC DX
  ADD AX, DX
  MOV DI, AX
  MOV AL, Color
  MOV BYTE PTR [ES : DI], AL
  {TTextAttr(Ptr(Seg(Screen^),
(Y - 1) * ScreenWidth * 2 + (X * 2) - 1)^) := Color}
END; { ScrWriteAttr }

PROCEDURE WindowIndirect (Rect : TRect);
BEGIN
  WITH Rect DO WINDOW (Left, Top, Right, Bottom)
END; { WindowIndirect }

FUNCTION PtInRect (X, Y : BYTE; Rect : TRect) : BOOLEAN;
BEGIN
  WITH Rect DO
    PtInRect := (X IN [Left..Right]) AND (Y IN [Top..Bottom])
END; { PtInRect }

PROCEDURE GetWindowRect (VAR Rect : TRect); assembler;
Asm
  LES DI, Rect
  MOV AX, WindMin
  MOV BX, WindMax
INC AL
  INC AH
  INC BL
  INC BH
MOV [ES : DI] (TRect) .Left, AL
  MOV [ES : DI] (TRect) .Top, AH
  MOV [ES : DI] (TRect) .Right, BL
  MOV [ES : DI] (TRect) .Bottom, BH
END; { GetWindowRect }

PROCEDURE GetWindowRectExt (X1, Y1, X2, Y2 : BYTE; VAR Rect : TRect); assembler;
Asm
  LES DI, Rect
  MOV AL, X1
  MOV AH, Y1
  MOV BL, X2
  MOV BH, Y2
  MOV [ES : DI] (TRect) .Left, AL
  MOV [ES : DI] (TRect) .Right, BL
MOV [ES : DI] (TRect) .Top, AH
  MOV [ES : DI] (TRect) .Bottom, BH
END; { GetWindowRectExt }

PROCEDURE ClearWin (X1, Y1, X2, Y2 : BYTE; Color : TTextAttr); assembler;
Asm
  MOV AX, 0600h
  MOV BH, Color
  MOV CL, X1
  DEC CL
  MOV CH, Y1
  DEC CH
  MOV DL, X2
  DEC DL
  MOV DH, Y2
  DEC DH
  INT 10h
END; { ClearWin }

PROCEDURE ShadowWin;
VAR P, I : BYTE;
BEGIN
  I := Y2 + 1;
FOR P := X1 + 2 TO X2 + 2 DO
    ScrWriteAttr (P, I, ScrReadAttr (P, I) AND WinShadowAttr);
  I := X2 + 1;
  FOR P := Y1 + 1 TO Y2 + 1 DO
  BEGIN
    ScrWriteAttr (I, P, ScrReadAttr (I, P) AND WinShadowAttr);
    ScrWriteAttr (I + 1, P, ScrReadAttr (I + 1, P) AND WinShadowAttr)
  END
END; { ShadowWin }

PROCEDURE CreateWin (X1, Y1, X2, Y2 : BYTE;
  TitleColor, FrameColor : TTextAttr; Title : TitleStr);
VAR
W, H : WORD;
DX, DY : BYTE;
F : TFrame;
BEGIN
IF WinFrame <> frNone THEN
BEGIN
GetFrame (WinFrame, F);
IF WinExplodeDelay <> 0 THEN
BEGIN
DX := X1 + 2;
DY := Y1 + 2;
REPEAT
IF WinShadow = TRUE THEN
ShadowWin (X1, Y1, DX, DY);
WINDOW (X1, Y1, DX, DY);
FrameWin (Title, F, TitleColor, FrameColor);
ClearWin (X1 + 1, Y1 + 1, DX - 1, DY - 1, FrameColor);
 IF DX < X2 THEN INC (DX, 2);
 IF DX > X2 THEN DX := X2;
IF DY < Y2 THEN INC (DY);
DELAY (WinExplodeDelay)
UNTIL (DX = X2) AND (DY = Y2)
END;
IF WinShadow = TRUE THEN ShadowWin (X1, Y1, X2, Y2);
WINDOW (X1, Y1, X2, Y2);
FrameWin (Title, F, TitleColor, FrameColor);
ClearWin (SUCC (X1), SUCC (Y1), PRED (X2), PRED (Y2), FrameColor)
  END;
  WINDOW (X1, Y1, X2, Y2);
  IF WinShadow THEN INC (WindMax, $0102)
END; { CreateWin }

PROCEDURE CreateWinIndirect;
BEGIN
  WITH WS, WS.Rect DO
    CreateWin (Left, Top, Right, Bottom, TitleColor, FrameColor, Title)
END; { CreateWinIndirect }

FUNCTION OpenWin (X1, Y1, X2, Y2 : BYTE;
  TitleColor, FrameColor : TTextAttr; Title : TitleStr) : BOOLEAN;
VAR W : PWinRec;
BEGIN
  OpenWin := FALSE;
  IF MAXAVAIL > SIZEOF (TWinRec) THEN
BEGIN
    NEW (W);
    W^.Next := TopWindow;
    SaveWin (W^.State);
    IF MAXAVAIL > LENGTH (Title) + 1 THEN
    BEGIN
      GETMEM (W^.Title, LENGTH (Title) + 1);
      W^.Title^ := Title;
      W^.TitleColor := TitleColor;
      W^.FrameColor := FrameColor;
      WINDOW (X1, Y1, X2, Y2);
      IF WinShadow = TRUE THEN INC (WindMax, $0102);
      IF MAXAVAIL > WinSize THEN
      BEGIN
W^.Size := WinSize;
GETMEM (W^.Buffer, W^.Size);
ReadWin (W^.Buffer^);
CreateWin (X1, Y1, X2, Y2, TitleColor, FrameColor, Title);
 TopWindow := W;
INC (WinCount);
OpenWin := TRUE
      END
    END
  END
END; { OpenWin }

FUNCTION OpenWinIndirect;
BEGIN
  WITH WS, WS.Rect DO OpenWinIndirect := OpenWin (Left,
    Top, Right, Bottom, TitleColor, FrameColor, Title)
END; { OpenWinIndirect }

FUNCTION CloseWin : BOOLEAN;
VAR W : PWinRec;
BEGIN
  CloseWin := FALSE;
  IF Assigned (TopWindow) AND (WinCount > 0) THEN
  BEGIN
W := TopWindow;
    WITH W^ DO
    BEGIN
      WriteWin (Buffer^);
      FREEMEM (Buffer, W^.Size);
      FREEMEM (Title, LENGTH (Title^) + 1);
      RestoreWin (State);
      TopWindow := Next
    END;
    DISPOSE (W);
    DEC (WinCount);
    CloseWin := TRUE
  END
END; { CloseWin }

FUNCTION MoveWin;
VAR W : PWinRec;
BEGIN
  MoveWin := FALSE;
IF (MAXAVAIL > SIZEOF (TWinRec) ) AND Assigned (TopWindow) THEN
  BEGIN
    NEW (W);
    IF MAXAVAIL > WinSize THEN
    BEGIN
      SaveWin (W^.State);
      W^.State.WindMin := MakeWord (Top, Left) - $0101;
      W^.State.WindMax := W^.State.WindMin + WindMax - WindMin;

      IF WinShadow THEN DEC (WindMax, $0102);
      W^.Size := WinSize;

      GETMEM (W^.Buffer, W^.Size);
      ReadWin (W^.Buffer^);

IF WinShadow THEN INC (WindMax, $0102);
      WriteWin (TopWindow^.Buffer^);

      RestoreWin (W^.State);
ReadWin (TopWindow^.Buffer^);

      IF WinShadow THEN DEC (WindMax, $0102);
      WriteWin (W^.Buffer^);
      IF WinShadow THEN
      BEGIN
ShadowWin (Left, Top, SUCC (LO (WindMax) ), SUCC (HI (WindMax) ) );
INC (WindMax, $0102)
      END;
      FREEMEM (W^.Buffer, W^.Size);
      MoveWin := TRUE
    END;
    DISPOSE (W)
  END
END; { MoveWin }

FUNCTION SaveDOSScreen;
BEGIN
  IF NOT GetDisplay IN [gdEGA..gdMCGA] THEN UseFade := FALSE;

  OldCursor := GetCursorType;
  SetCursor (CursorOff);

  IF UseFade THEN FadeOut (FadeDelay);

  asm
    PUSH WORD PTR [WinShadow]
    MOV WinShadow, FALSE
  END;

  SaveDOSScreen := OpenWin (1, 1,
    ScreenWidth, ScreenHeight, Black, Black, None);

  asm
POP WORD PTR [WinShadow]
  END;

  IF RestoreScreen THEN WriteWin (TopWindow^.Buffer^);

  IF UseFade THEN FadeIn (0)

END; { SaveDOSScreen }

FUNCTION RestoreDOSScreen;
BEGIN
  IF NOT GetDisplay IN [gdEGA..gdMCGA] THEN UseFade := FALSE;

  WINDOW (1, 1, ScreenWidth, ScreenHeight);
  asm
    MOV WinShadow, FALSE
  END;
  IF UseFade THEN SetBrightness (0);
  RestoreDOSScreen := CloseWin;

  IF UseFade THEN FadeIn (FadeDelay);

  SetCursorType (OldCursor);
SetCursor (CursorOn)
END; { RestoreDOSScreen }

PROCEDURE SetBlink (BlinkOn : BOOLEAN);
CONST PortVal : ARRAY [0..4] OF BYTE = ($0C, $08, $0D, $09, $09);
VAR
  PortNum : WORD;
  Index, PVal : BYTE;
BEGIN
  IF LastMode = Mono THEN
  BEGIN
    PortNum := $3B8;
    Index := 4
  END ELSE
    IF GetDisplay IN [gdEGA..gdMCGA] THEN
BEGIN
      INLINE (
$8A / $5E / < BlinkOn /     { MOV BL, [BP+<BlinkOn] }
$B8 / $03 / $10 /          { MOV AX, $1003 }
$CD / $10);             { MOV $10 }
      EXIT
    END ELSE
      BEGIN
PortNum := $3D8;
CASE LastMode OF
  0..3 : Index := LastMode;
  ELSE EXIT
END
      END;
   PVal := PortVal [Index];
   IF BlinkOn THEN
   PVal := PVal OR $20;
   Port [PortNum] := PVal
END; { SetBlink }

FUNCTION HeapFunc (Size : WORD) : INTEGER; far; assembler;
Asm
  MOV AX, 1
END; { HeapFunc }

BEGIN
  HeapError := @HeapFunc;
  WinCount := 0;
  WinShadow := TRUE;
  WinFrame := frSingle;
  WinExplodeDelay := 10; { set no explode }
  TopWindow := NIL;
  IF LastMode = Mono THEN
    Screen := PTR (SegB000, 0) ELSE
  BEGIN
    Screen := PTR (SegB800, 0);
    IF (LastMode AND Font8x8) <> 0 THEN
ScreenHeight := Mem [Seg0040 : $0084] ELSE ScreenHeight := 25
END;
ScreenWidth := MemW [Seg0040 : $004A];
InitCol;       { Save original palette }
SetBlink (TRUE) { Set blinking }
END. { Win.Pas }

{--------------------------------  XX3402 CODE ---------------------}
{ CUT OUT THE FOLLOWING AND USE XX3402 TO DECODE TO OBTAIN WIN.OBJ  }

* XX3402 - 000678 - 090894 - - 72 - - 85 - 53801 - - - - - - - - - WIN.OBJ - - 1 - OF - - 1
U + Y + - rRdPWt - IooHW0 + + + + + QJ5JmMawUELBnNKpWP4Jm60 - KNL7nOKxi61AiAda61k - + uTBN
0Fo5RqZi9Y3HHKe6 + k - + uImK + U + + O6U1 + 20VZ7M4 + + F2EJF - FdU5 + 2U + + + 6 - + FKK - U + 2Eox2
FIKM - k + cEE21 + E5mX - s + 0IB6FIB9IotDJk + 5JoZCF2p7HU + 5JoZCF2p - K + - gY + w + + + 66Jp77
J2JLGIsh + + 0lY + s + + + 65FYZAH3R7HWA + + 04E2 + + + + UZLIYZIFIB6EJ6H + + 0NY + w + + + 66Jp77
J2JHJ36 + + + 1HY + s + + + 65JoZCIoZOFH6 - + DqE1U + + + URGFI32JoZC8 + + + 7sU2 + 20W + N4UFE20
+ + - JWyn2LUUaWUyyJE1ckE - RmUc + JMjgWYs8jbg + u92 + LQc8 + 9tv + Cg6jdc + ukCyeU - JWykn
mMgK + + 081U + + 8gd - IJ7Ku9o + LZdNzgMuBU2 + RixRmUE + 5cda - gJq02Nm3em9qCmc + LLvyimc
+ LHvWwCfyy9g5wCgey9w5wC8FUW8NUNm36jMv8U - RTjuv8U - RDi9kujvsiz1wuj15UMTWzT2
TUPc2E07TUMTklv3RUPc - E07RUMTkr6JfMjMv8U - RTjuv8U - RDi9kujvsin1wuL1WZMCzgc0
3U + + QZMu3U + + Rp08RUnynU6q + E - mFHcq + E - rDn9hsniU + + + ekjv + CgVm + cf6i2 + + Xg08lWPq
7Yc + AjM1kh5UWzWs + 9UaU1t7 + + Rp + fGkXg0uqUDwU1s + + + 5ztgCV + + + f - U + + - E2 - xiHFsAja
b2k + l + dI + gEOJ + 9273E0l0ZI + gEiJ + 92BkM - + gEv - U21l2o4 + ED2pkM - + gHR - U21lCU4 + E92
vUM - + wHr - U21lGk4 + E53AkM - + wIr - U20Gcc0 + + - o
* * * * * END OF BLOCK 1 * * * * *


{--------------------------------   ASSEMBLY CODE ---------------------}
{ COMPILE THE FOLLOWING WITH TASM                                      }

; {*** WIN.ASM ***}

        TITLE   WIN

        LOCALS  @@
 P286

; Coordinate RECORD

X               EQU     (BYTE PTR 0)
Y               EQU     (BYTE PTR 1)

; BIOS workspace equates

CrtMode         EQU     (BYTE PTR 49H)
CrtWidth        EQU     (BYTE PTR 4AH)

DATA    SEGMENT WORD PUBLIC

; Externals from CRT UNIT

        EXTRN   CheckSnow : BYTE, WindMin : WORD, WindMax : WORD

DATA    ENDS

CODE    SEGMENT BYTE PUBLIC

        ASSUME  CS : CODE, DS : DATA

; PROCEDURE WriteStr (X, Y : BYTE; S : STRING; Attr : BYTE);

        PUBLIC  WriteStr

WriteStr :

        PUSH    BP
MOV     BP, SP
        LES     BX, [BP + 8]
        MOV     CL, ES : [BX]
        MOV     SI, OFFSET CS : CrtWriteStr
        CALL    CrtWrite
        POP     BP
        RETF    10

; PROCEDURE WriteChar (X, Y, Count : BYTE; Ch : CHAR; Attr : BYTE);

        PUBLIC  WriteChar

WriteChar :

        PUSH    BP
        MOV     BP, SP
        MOV     CL, [BP + 10]
        MOV     SI, OFFSET CS : CrtWriteChar
CALL    CrtWrite
        POP     BP
        RETF    10

; PROCEDURE FillWin (Ch : CHAR; Attr : BYTE);

        PUBLIC  FillWin

FillWin :

        MOV     SI, OFFSET CS : CrtWriteChar
        JMP     SHORT CommonWin

; PROCEDURE ReadWin (VAR Buf);

        PUBLIC  ReadWin

ReadWin :

        MOV     SI, OFFSET CS : CrtReadWin
        JMP     SHORT CommonWin

; PROCEDURE WriteWin (VAR Buf);

        PUBLIC  WriteWin

WriteWin :

        MOV     SI, OFFSET CS : CrtWriteWin

; Common FillWin / ReadWin / WriteWin routine

CommonWin :

        PUSH    BP
        MOV     BP, SP
XOR     CX, CX
        MOV     DX, WindMin
        MOV     CL, WindMax.X
        SUB     CL, DL
        INC     CX
@@1 :    PUSH    CX
        PUSH    DX
        PUSH    SI
        CALL    CrtBlock
        POP     SI
        POP     DX
        POP     CX
        INC     DH
        CMP     DH, WindMax.Y
        JBE     @@1
        POP     BP
        RETF    4

; WRITE STRING TO screen

CrtWriteStr :

        PUSH    DS
        MOV     AH, [BP + 6]
        LDS     SI, [BP + 8]
        INC     SI
        JC      @@4
@@1 :    LODSB
        MOV     BX, AX
@@2 :    IN      AL, DX
        TEST    AL, 1
        JNE     @@2
        CLI
@@3 :    IN      AL, DX
        TEST    AL, 1
        JE      @@3
MOV     AX, BX
        STOSW
        STI
        LOOP    @@1
        POP     DS
        RET
@@4 :    LODSB
        STOSW
        LOOP    @@4
        POP     DS
        RET

; WRITE characters TO screen

CrtWriteChar :

        MOV     AL, [BP + 8]
        MOV     AH, [BP + 6]
JC      @@4
        MOV     BX, AX
@@1 :    IN      AL, DX
        TEST    AL, 1
        JNE     @@1
        CLI
@@2 :    IN      AL, DX
        TEST    AL, 1
        JE      @@2
        MOV     AX, BX
        STOSW
        STI
        LOOP    @@1
        RET
@@4 :    REP     STOSW
        RET

; READ WINDOW buffer from screen

CrtReadWin :

        PUSH    DS
        PUSH    ES
        POP     DS
        MOV     SI, DI
        LES     DI, [BP + 6]
        CALL    CrtCopyWin
        MOV     [BP + 6], DI
        POP     DS
        RET

; WRITE WINDOW buffer TO screen

CrtWriteWin :

        PUSH    DS
LDS     SI, [BP + 6]
        CALL    CrtCopyWin
        MOV     [BP + 6], SI
        POP     DS
        RET

; WINDOW buffer COPY routine

CrtCopyWin :

        JC      @@4
@@1 :    LODSW
        MOV     BX, AX
@@2 :    IN      AL, DX
        TEST    AL, 1
        JNE     @@2
        CLI
@@3 :    IN      AL, DX
TEST    AL, 1
        JE      @@3
        MOV     AX, BX
        STOSW
        STI
        LOOP    @@1
        RET
@@4 :    REP     MOVSW
        RET

; DO screen operation
; IN    CL = Buffer LENGTH
;       SI = WRITE PROCEDURE POINTER
;       BP = Stack frame POINTER

CrtWrite :

        MOV     DL, [BP + 14]
DEC     DL
        ADD     DL, WindMin.X
        JC      CrtExit
        CMP     DL, WindMax.X
        JA      CrtExit
        MOV     DH, [BP + 12]
        DEC     DH
        ADD     DH, WindMin.Y
        JC      CrtExit
        CMP     DH, WindMax.Y
        JA      CrtExit
        XOR     CH, CH
        JCXZ    CrtExit
        MOV     AL, WindMax.X
        SUB     AL, DL
        INC     AL
        CMP     CL, AL
        JB      CrtBlock
MOV     CL, AL

; DO screen operation
; IN    CL = Buffer LENGTH
;       DX = CRT coordinates
;       SI = PROCEDURE POINTER

CrtBlock :

        MOV     AX, 40H
        MOV     ES, AX
        MOV     AL, DH
        MUL     ES : CrtWidth
        XOR     DH, DH
        ADD     AX, DX
        SHL     AX, 1
        MOV     DI, AX
        MOV     AX, 0B800H
CMP     ES : CrtMode, 7
        JNE     @@1
        MOV     AH, 0B0H
@@1 :    MOV     ES, AX
        MOV     DX, 03DAH
        CLD
        CMP     CheckSnow, 1
        JMP     SI

; EXIT from screen operation

CrtExit :

        RET

; FUNCTION WinSize : WORD;

        PUBLIC  WinSize

WinSize :

MOV     AX, WindMax
SUB     AX, WindMin
ADD     AX, 101H
MUL     AH
SHL     AX, 1
RETF

CODE    ENDS

END



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