{ ************************************************************************** }
{ OBJIO.PAS                      Version 3.0                     (c) Mr Vain }
{                                01.07.                                      }
{                                                                            }
{ ObjectIO beinhaltet die Ein- und Ausgaberoutinen zur Ansteuerung des Bild- }
{ schirmspeichers und OffScreen-Speichers, Maussteuerung und Tastaturabfrage }
{ ************************************************************************** }

UNIT OBJIO;

INTERFACE

USES
  CRT, DOS;

TYPE
  ScreenBuf=ARRAY[0..3999] OF BYTE;

  PMausDataRec=^MausDataRec;
  MausDataRec=RECORD
    PosX, PosY  : WORD;
    KeyLeft     : BOOLEAN;
    KeyRight    : BOOLEAN;
    LastKeyLeft : BOOLEAN;
    LastKeyRight: BOOLEAN;
  END;  (* Rec MausDataRec *)

  PMaus=^TMaus;
  TMaus=OBJECT
    PRIVATE
      OnFlag                    : BOOLEAN;
      ReleaseFlag               : BOOLEAN;
      CursorData                : PMausDataRec;
      AXreg, BXreg, CXreg, DXreg: WORD;
    PRIVATE
      PROCEDURE   Reset;
      PROCEDURE   Run(VAR wAX, wBX, wCX, wDX: WORD);
    PUBLIC
      CONSTRUCTOR Init;
      PROCEDURE   GetData;
      FUNCTION    GetPosX: BYTE;
      FUNCTION    GetPosY: BYTE;
      FUNCTION    GetKeyLeft: BOOLEAN;
      FUNCTION    GetKeyRight: BOOLEAN;
      FUNCTION    GetKeyRelease: BOOLEAN;
      FUNCTION    GetLastKeyLeft: BOOLEAN;
      FUNCTION    GetLastKeyRight: BOOLEAN;
      PROCEDURE   SwOFF;
      PROCEDURE   SwON;
      DESTRUCTOR  Done;
  END;  (* OBJECT TMaus *)

CONST
  MouseNone=0;
  MouseLeft=1;
  MouseRight=2;

VAR
  Screen   : POINTER;
  OffScreen: ^ScreenBuf;
  Maus     : PMaus;

PROCEDURE ClearOffScreen;
PROCEDURE Cursor(sichtbar: BOOLEAN);
FUNCTION  DOWNCASE(ch: CHAR): CHAR;
PROCEDURE DrawText(px, py, pcol: BYTE; zeile: STRING);
PROCEDURE DrawBox(x1, y1, x2, y2, col: BYTE; fc: CHAR);
PROCEDURE HShadow(px, py, pw: BYTE);
PROCEDURE VShadow(px, py, ph: BYTE);
FUNCTION  INT2STR(L: LONGINT; Stellen: SHORTINT): STRING;
FUNCTION  REAL2STR(R: REAL; Zeichen, Stellen: SHORTINT): STRING;
FUNCTION  STR2INT(S: STRING): INTEGER;
FUNCTION  STR2REAL(S: STRING): REAL;
PROCEDURE SaveScreen(VAR MausPtr: PMaus);
PROCEDURE UpdateScreen;

IMPLEMENTATION

PROCEDURE ClearOffScreen;
BEGIN
  DrawBox(1,1,80,25,7,' ');
END;

PROCEDURE Cursor(sichtbar: BOOLEAN);
VAR
  reg: Registers;
BEGIN
  reg.ah:=1;
  IF (sichtbar=TRUE) THEN BEGIN
    reg.ch:=6;
    reg.cl:=7;
    INTR(16,reg);
  END  (* IF *)
  ELSE BEGIN
    reg.ch:=32;
    reg.cl:=7;
    INTR(16,reg);
  END;  (* ELSE *)
END;

FUNCTION DOWNCASE(ch: CHAR): CHAR;
VAR
  ChCode: BYTE;
BEGIN
  ChCode:=ORD(ch);
  CASE ch OF 'A'..'Z': ChCode:=ChCode+32;
  END;  (* CASE *)
  ch:=CHR(ChCode);
  DOWNCASE:=ch;
END;

PROCEDURE DrawText(px, py, pcol: BYTE; zeile: STRING);
VAR
  ii, len: BYTE;
BEGIN
  len:=LENGTH(zeile);
  IF (len>0) THEN
    FOR ii:=0 TO len-1 DO BEGIN
      MEM[SEG(OffScreen^):(px-1+ii)*2+(py-1)*160]:=ORD(zeile[ii+1]);
      MEM[SEG(OffScreen^):(px-1+ii)*2+(py-1)*160+1]:=pcol;
    END;
END;

PROCEDURE DrawBox(x1, y1, x2, y2, col: BYTE; fc: CHAR);
VAR
  ii   : BYTE;
  cFill: STRING;
BEGIN
  cFill:='';
  FOR ii:=x1 TO x2 DO cFill:=cFill+fc;
  FOR ii:=y1 TO y2 DO DrawText(x1,ii,col,cFill);
END;

PROCEDURE HShadow(px, py, pw: BYTE);
VAR
  ii: BYTE;
BEGIN
  FOR ii:=px TO px+pw-1 DO
    MEM[SEG(OffScreen^):(ii-1)*2+(py-1)*160+1]:=8;
END;

PROCEDURE VShadow(px, py, ph: BYTE);
VAR
  ii: BYTE;
BEGIN
  FOR ii:=py TO py+ph-1 DO
    MEM[SEG(OffScreen^):(px-1)*2+(ii-1)*160+1]:=8;
END;

FUNCTION INT2STR(L: LONGINT; Stellen: SHORTINT): STRING;
{ CONVERTS AN INTEGER TO A STRING }
VAR
  S: STRING;
BEGIN
  STR(L:Stellen,S);
  INT2STR:=S;
END; { INT2STR }

FUNCTION REAL2STR(R: REAL; Zeichen, Stellen: SHORTINT): STRING;
{ CONVERTS AN REAL TO A STRING }
VAR
  S: STRING;
BEGIN
  STR(R:Zeichen:Stellen,S);
  REAL2STR:=S;
END; { REAL2STR }

FUNCTION STR2INT(S: STRING): INTEGER;
VAR
  wert, control: INTEGER;
BEGIN
  wert:=0;
  VAL(S,wert,control);
  STR2INT:=wert;
END;

FUNCTION STR2REAL(S: STRING): REAL;
VAR
  wert   : REAL;
  control: INTEGER;
BEGIN
  wert:=0;
  VAL(S,wert,control);
  STR2REAL:=wert;
END;

PROCEDURE SaveScreen(VAR MausPtr: PMaus);
BEGIN
  MausPtr^.SwOFF;
  MOVE(Screen^,OffScreen^,SizeOf(ScreenBuf));
  MausPtr^.SwON;
END;

PROCEDURE UpdateScreen;
BEGIN
  MOVE(OffScreen^,Screen^,SizeOf(ScreenBuf));
END;

CONSTRUCTOR TMaus.Init;
BEGIN
  OnFlag:=TRUE;
  ReleaseFlag:=FALSE;
  AXreg:=0;  BXreg:=0;  CXreg:=0;  DXreg:=0;
  CursorData:=NIL;

  NEW(CursorData);
  WITH CursorData^ DO BEGIN
    PosX:=0;  PosY:=0;   KeyLeft:=FALSE;  KeyRight:=FALSE;
    LastKeyLeft:=FALSE;  LastKeyRight:=FALSE;
  END;
  Reset;
END;

PROCEDURE TMaus.GetData;
VAR
  LastBXreg: WORD;
BEGIN
  LastBXreg:=BXreg;
  CursorData^.LastKeyLeft:=CursorData^.KeyLeft;
  CursorData^.LastKeyRight:=CursorData^.KeyRight;
  AXreg:=3;  Run(AXreg,BXreg,CXreg,DXreg);
  IF (LastBXreg > BXreg) THEN ReleaseFlag:=TRUE
  ELSE ReleaseFlag:=FALSE;

  CursorData^.PosX:=(CXreg DIV 8)+1;
  CursorData^.PosY:=(DXreg DIV 8)+1;
  CASE BXreg OF 1: CursorData^.KeyLeft:=TRUE;
                2: CursorData^.KeyRight:=TRUE;
                0: BEGIN
                     CursorData^.KeyLeft:=FALSE;
                     CursorData^.KeyRight:=FALSE;
                   END;
  END;  (* CASE *)
END;

PROCEDURE TMaus.Reset;
BEGIN
  AXreg:=0;  Run(AXreg,BXreg,CXreg,DXreg);
  AXreg:=1;  Run(AXreg,BXreg,CXreg,DXreg);
END;

PROCEDURE TMaus.Run(VAR wAX, wBX, wCX, wDX: WORD);
VAR
  Reg: Registers;
BEGIN
  {
  ASM
    MOV AX,wAX
    MOV BX,wBX
    MOV CX,wCX
    MOV DX,wDX
    INT $33
    MOV wAX,AX
    MOV wBX,BX
    MOV wCX,CX
    MOV wDX,DX
  END;  (* ASM *)
  }
  Reg.AX:=wAX;
  Reg.BX:=wBX;
  Reg.CX:=wCX;
  Reg.DX:=wDX;
  INTR($33,Reg);
  wAX:=Reg.AX;
  wBX:=Reg.BX;
  wCX:=Reg.CX;
  wDX:=Reg.DX;

END;

FUNCTION TMaus.GetPosX: BYTE;
BEGIN
  GetPosX:=CursorData^.PosX;
END;  (* Func TMaus.GetPosX *)

FUNCTION TMaus.GetPosY: BYTE;
BEGIN
  GetPosY:=CursorData^.PosY;
END;  (* Func TMaus.GetPosY *)

FUNCTION TMaus.GetKeyLeft: BOOLEAN;
BEGIN
  GetKeyLeft:=CursorData^.KeyLeft;
END;  (* Func TMaus.GetKeyLeft *)

FUNCTION TMaus.GetKeyRight: BOOLEAN;
BEGIN
  GetKeyRight:=CursorData^.KeyRight;
END;  (* Func TMaus.GetKeyRight *)

FUNCTION TMaus.GetKeyRelease: BOOLEAN;
BEGIN
  GetKeyRelease:=ReleaseFlag;
END;  (* Func TMaus.GetKeyRelease *)

FUNCTION TMaus.GetLastKeyLeft: BOOLEAN;
BEGIN
  GetLastKeyLeft:=CursorData^.LastKeyLeft;
END;  (* Func TMaus.GetLastKeyLeft *)

FUNCTION TMaus.GetLastKeyRight: BOOLEAN;
BEGIN
  GetLastKeyRight:=CursorData^.LastKeyRight;
END;  (* Func TMaus.GetLastKeyRight *)

PROCEDURE TMaus.SwOFF;
BEGIN
  IF (OnFlag=TRUE) THEN BEGIN
    AXreg:=2;  Run(AXreg,BXreg,CXreg,DXreg);
    OnFlag:=FALSE;
  END;  (* IF OnFlag *)
END;  (* Proc TMaus.SwOFF *)

PROCEDURE TMaus.SwON;
BEGIN
  IF (OnFlag=FALSE) THEN BEGIN
    AXreg:=1;  Run(AXreg,BXreg,CXreg,DXreg);
    OnFlag:=TRUE;
  END;  (* IF OnFlag *)
END;  (* Proc TMaus.SwON *)

DESTRUCTOR TMaus.Done;
BEGIN
  SwOFF;
  DISPOSE(CursorData);
END;

BEGIN
  NEW(OffScreen);
  Screen:=PTR($B800,0);
  ClearOffScreen;
END.