Pascal Screen

Screen

unit Screen; {$IfNDef Os2}{$G+,F+}{$EndIf}
{ ######################################################################### }
                                  interface
{ ######################################################################### }

type  String8  = String[8];  { for Window: 'Íͺº»¼ÉÈ','Äij³¿ÙÚÀ','ÜßÛÛÜßÜß' }
var VideoMem : Pointer;                                    { video memory   }

{ Text output }
procedure WriteSt(x,y,Attr:Byte; Stro:String);   { output string to (x,y)  +}
procedure WriteCh(x,y,Attr:Byte; What:Char);     { write a char to (x,y)   +}
procedure WriteVr(x,y,Attr,Rep:Byte; What:Char); { repeat REP chars (verti)+}
procedure WriteHr(x,y,Attr,Rep:Byte; What:Char); { repeat REP chars (horis)+}
{ Special funcs }
procedure WriteMenu(X,Y:Byte; Stroka:String);    { writest(), '&'-selector +}
procedure WriteSelected( X,Y,Size:Byte);         { select the block        +}
{ Windows and Screens }
procedure ClrScrn(What:Char;Attr:Byte);          { clear the screen        +}
procedure Window(x1,y1,x2,y2,Attr:Byte);         { create a window         +}
procedure WinBor(x1,y1,x2,y2,Attr:Byte;Mask:String8); { window + border    =}
procedure PushScreen;                            { save the state          =}
procedure PopScreen;                             { restore the state       =}
{ Video Modes and Settings }
procedure Set80x25;                              { set 80x25x16 text mode  +}
procedure Set80x30;                              { set 80x30x16 text mode  +}{$Ifndef Os2}
procedure Set80x30PrintScreen;                   { enables PrScreen30 linesD}{$EndIf}
procedure SwitchMonitor(OnOff:Boolean);          { on/off the monitor      +}
procedure SetBlink(OnOff:Boolean);               { enable/disable blinking +}
procedure SetCursor(OnOff:Boolean);              { enable/disable cursor   +}
procedure EditCursor(StLine,EnLine:Byte);        { changes the cursor view +}
{ Cursor }
procedure GotoXY(x,y:Byte);                      { moves the cursor to(x,y)+}
function  WhereX:Byte;                           { gets cursor pos(x)      +}
function  WhereY:Byte;                           { gets cursor pos(y)      +}
{ Misc }
procedure Move(var Source,Dest; Count:Word);     { copy bytes (dos: faster)+}
procedure UpdateScreen;                          { updates the screen      O}
procedure WaitRetrace;                           { waits the retrace       +}

{ ######################################################################### }
                                implementation
{ ######################################################################### }

{$IfDef Os2}
{ ######################################################################### }
{ ##                                OS / 2                               ## }
{ ######################################################################### }
Uses Os2Base;

procedure WriteSt;                                                { WriteSt }
  var b      : Byte;
      VidMem : LongInt;
  begin
    VidMem:=LongInt(VideoMem)+((y*5)shl 5)-162+(x shl 1);
    b:=1;
    while b<Length(Stro)*2 do begin
      inc(b);
      Mem[VidMem+b-2]:=Byte(Stro[b div 2]);
      inc(b);
      Mem[VidMem+b-2]:=Attr;
    end;
  end; { WriteSt }

procedure WriteCh;                                                { WriteCh }
  begin
    WriteSt(x,y,Attr,What);
  end; { WriteCh }

procedure WriteVr;                                                { WriteVr }
  var b : Byte;
  begin
    for b:=1 to Rep do WriteSt(x,b+y-1,Attr,What);
  end; { WriteVr }

procedure WriteHr;                                                { WriteHr }
  var b : Byte;
      s : String;
  begin
    s:='';
    for b:=1 to Rep do s:=s+What;
    WriteSt(x,y,Attr,s);
  end; { WriteHr }

procedure WriteMenu;
  var i : Byte;
      di: shortint;
  begin
    if Pos('&',Stroka)=0 then WriteSt(x,y,$70,Stroka)
    else begin
      di:=-1;
      i:=1;
      while i<=Length(Stroka) do begin
        if Stroka[i]<>'&' then WriteCh(x+di+i,y,$70,Stroka[i])
        else begin
          dec(di);
          inc(i);
          WriteCh(x+di+i,y,$71,Stroka[i]);
        end;
        inc(i);
      end;
    end;
  end; { WriteMenu }

procedure WriteSelected;
  var b      : Byte;
      VidMem : LongInt;
  begin
    VidMem:=LongInt(VideoMem)+((y*5)shl 5)-162+(x shl 1);
    b:=1;
    while b<Size*2 do begin
      inc(b);
      inc(b);
      if (Mem[VidMem+b] and $0F)=1 then Mem[VidMem+b]:=$8E
      else Mem[VidMem+b]:=$8F;
    end;
  end; { WriteSelected }

procedure ClrScrn;                                                { ClrScrn }
  var b : Byte;
      s : String;
  begin
    s:='';
    for b:=1 to 80 do s:=s+What;
    for b:=1 to 50 do WriteSt(1,b,Attr,s);
  end; { ClrScrn }

procedure Window;                                                  { Window }
  var b : Byte;
      s : String;
  begin
    s:='';
    for b:=1 to x2-x1+1 do s:=s+' ';
    for b:=y1 to y2 do WriteSt(x1,b,Attr,s);
  end; { Window }

procedure Set80x25;                                              { Set80x25 }
  var Mode : VioModeInfo;
  begin
    Mode.cb:=8;
    Mode.fbType:=5;
    Mode.Color:=8;
    Mode.Col:=80;
    Mode.Row:=25;
    VioSetMode(Mode,0);
    SetBlink(False);
  end; { Set80x25 }

procedure Set80x30;                                              { Set80x30 }
  var Mode : VioModeInfo;
  begin
    Mode.cb:=8;
    Mode.fbType:=5;
    Mode.Color:=8;
    Mode.Col:=80;
    Mode.Row:=30;
    VioSetMode(Mode,0);
    SetBlink(False);
  end; { Set80x30 }

procedure SetBlink;                                              { SetBlink }
  var State : VioPalState;
  begin
    State.cb:=6;
    State.rType:=2;
    State.iFirst:=Ord(not OnOff);
    VioSetState(State,0);
  end; { SetBlink }

procedure SetCursor;                                            { SetCursor }
  var CurData : VioCursorInfo;
  begin
    VioGetCurType(CurData,0);
    CurData.Attr:=Ord(OnOff)-1;
    VioSetCurType(CurData,0);
  end; { SetCursor }

procedure EditCursor;                                          { EditCursor }
  var CurData : VioCursorInfo;
  begin
    CurData.yStart:=stLine;
    CurData.cEnd:=enLine;
    CurData.cx:=1;
    CurData.Attr:=0;
    VioSetCurType(CurData,0);
  end; { EditCursor }

procedure GotoXY;                                                  { GotoXy }
  begin
    VioSetCurPos(y-1,x-1,0);
  end; { GotoXY }

function WhereX;                                                   { WhereX }
  var a,b : SmallWord;
  begin
    VioGetCurPos(a,b,0);
    WhereX:=b+1;
  end; { WhereX }

function WhereY;                                                   { WhereX }
  var a,b : SmallWord;
  begin
    VioGetCurPos(a,b,0);
    WhereY:=a+1;
  end; { WhereY }

procedure SwitchMonitor;                                    { SwitchMonitor }
  begin
    Port[$3C4]:=1;
    if OnOff then Port[$3C5]:=0
    else Port[$3C5]:=Port[$3C5] or $20;
  end; { SwitchMonitor }

procedure Move;                                                      { Move }
  begin
    System.Move(Source,Dest,Count);
  end; { Move }

procedure CountB800;                                            { CountB800 }
  var BufSize : SmallWord;
      Address : Pointer;
  begin
    VioGetBuf(Address,BufSize,0);
    SelToFlat(Address);
    VideoMem:=Address;
  end; { CountB800 }

{$Else}
{ ######################################################################### }
{ ##                                  DOS                                ## }
{ ######################################################################### }

procedure WriteSt; assembler; asm                                 { WriteSt }
    push  ds
    les   di,VideoMem
    mov   al,byte ptr [y]
    dec   al
    mov   cl,160
    mul   cl
    dec   [x]
    shl   [x],1
    add   al,[x]
    adc   ah,0
    add   di,ax
    lds   si,[Stro]
    mov   cl,[ds:si]
    cmp   cl,0
    je    @@e
    xor   ch,ch
    inc   si
    mov   ah,[Attr]
@@a:lodsb
    stosw
    loop  @@a
@@e:pop   ds
  end; { WriteSt }

procedure WriteCh; assembler; asm                                 { WriteCh }
    les   di,VideoMem
    mov   al,byte ptr [y]
    dec   al
    mov   cl,160
    mul   cl
    dec   [x]
    shl   [x],1
    add   al,[x]
    adc   ah,0
    add   di,ax
    mov   ah,[Attr]
    mov   al,[What]
    stosw
  end; { WriteCh }

procedure WriteVr; assembler; asm                                 { WriteVr }
    les   di,VideoMem
    mov   al,byte ptr [y]
    dec   al
    mov   cl,160
    mul   cl
    dec   [x]
    shl   [x],1
    add   al,[x]
    adc   ah,0
    add   di,ax
    mov   ah,[Attr]
    mov   al,[What]
    mov   cl,[Rep]
    xor   ch,ch
@@a:stosw
    add   di,158
    loop  @@a
  end; { WriteVr }

procedure WriteHr; assembler; asm                                 { WriteHr }
    les   di,VideoMem
    mov   al,byte ptr [y]
    dec   al
    mov   cl,160
    mul   cl
    dec   [x]
    shl   [x],1
    add   al,[x]
    adc   ah,0
    add   di,ax
    mov   ah,[Attr]
    mov   al,[What]
    mov   cl,[Rep]
    xor   ch,ch
    rep   stosw
  end; { WriteHr }

procedure WriteMenu; assembler; asm                             { WriteMenu }
    push   ds
    les    di,VideoMem
    mov    al,byte ptr [y]
    dec    al
    mov    cl,160
    mul    cl
    shl    byte ptr [x],1
    add    al,byte ptr [x]
    adc    ah,0
    add    di,ax
    lds    si,[Stroka]
    lodsb
    mov    cl,al
    xor    ch,ch
@@l:mov    ah,70h
    lodsb
    cmp    al,"&"
    jnz    @@s
    inc    ah
    lodsb
    dec    cx
@@s:stosw
    loop   @@l
    pop    ds
  end; { WriteMenu }

procedure WriteSelected; assembler; asm                     { WriteSelected }
    push   ds
    les    di,VideoMem
    mov    al,byte ptr [y]
    dec    al
    mov    cl,160
    mul    cl
    shl    byte ptr [x],1
    add    al,byte ptr [x]
    adc    ah,0
    mov    cl,Size
    lds    si,VideoMem
    add    di,ax
    add    si,ax
    xor    ch,ch
@@a:lodsw
    and    ah,0Fh
    cmp    ah,1
    mov    ah,8Eh
    je     @@s
    inc    ah
@@s:stosw
    loop   @@a
    pop    ds
  end; { WriteSelected }

procedure ClrScrn; assembler; asm                                 { ClrScrn }
    les   di,VideoMem
    mov   ah,[Attr]
    mov   al,[What]
    mov   cx,4000
    rep   stosw
  end; { ClrScrn }

procedure Window; assembler; asm                                   { Window }
    les   di,VideoMem
    mov   al,byte ptr [y1]   { count offset }
    dec   al
    mov   cl,160
    mul   cl
    xor   ch,ch              { get repeat rate }
    mov   cl,[x2]
    sub   cl,[x1]
    inc   cl
    mov   bh,cl              { bh:swap: <-x-> count }
    mov   cl,[y2]            { bl:swap: _/y/^ count }
    sub   cl,[y1]
    inc   cl
    dec   [x1]               { continue with offset }
    shl   [x1],1
    add   al,[x1]
    adc   ah,0
    add   di,ax               { ok, caught it }
    mov   dx,di
    mov   ah,[Attr]
    mov   al,' '
@@a:mov   bl,cl
    mov   cl,bh
    rep   stosw
    mov   cl,bl
    add   dx,160
    mov   di,dx
    loop  @@a
  end; { Window }

procedure Set80x25; assembler; asm                               { Set80x25 }
    mov   ax,0003h
    int   10h
    mov   ax,1003h  { no_blink }
    xor   bl,bl
    int   10h
  end; { Set80x25 }

procedure Set80x30; assembler; asm                               { Set80x30 }
    cli
    mov   ax,40h
    mov   es,ax
    mov   ax,8192d
    mov   [es:4Ch],ax
    mov   al,29d
    mov   [es:84h],al
    mov   dx,[es:$63]
    mov   es,ax
    mov   ax,$0C11
    out   dx,ax           { 0C11 }
    mov   ax,$0D06
    out   dx,ax           { 0D06 }
    mov   ax,$3E07
    out   dx,ax           { 3E07 }
    mov   ax,$EA10
    out   dx,ax           { EA10 }
    mov   ax,$8C11
    out   dx,ax           { 8C11 }
    mov   ax,$DF12
    out   dx,ax           { DF12 }
    mov   ax,$E715
    out   dx,ax           { E715 }
    mov   ax,$0616
    out   dx,ax           { 0616 }
    mov   dx,3CCh
    in    al,dx
    and   al,33h
    or    al,0C4h
    mov   dx,3C2h
    out   dx,al
    sti
  end; { Set80x30 }

procedure Set80x30PrintScreen; assembler; asm         { Set80x30PrintScreen }
    mov   ah,12h
    mov   bl,20h
    int   10h
  end; { Set80x30PrintScreen }

procedure SwitchMonitor; assembler; asm                     { SwitchMonitor }
    mov   dx,3C4h
    mov   al,1
    out   dx,al
    inc   dx
    mov   al,0
    out   dx,al
    cmp   [OnOff],False
    jne   @@F
    in    al,dx
    or    al,20h
    out   dx,al
@@F:
  end; { SwitchMonitor }

procedure SetBlink; assembler; asm                               { SetBlink }
    mov   ax,1003h
    mov   bl,[OnOff]
    int   10h
  end; { SetBlink }

procedure SetCursor; assembler; asm                             { SetCursor }
    mov   ah,01h
    cmp   [OnOff],False
    je    @@a
    mov   cx,1312h
    jmp   @@b
@@a:mov   cx,2020h
@@b:int   10h
  end; { SetCursor }

procedure EditCursor; assembler; asm                           { EditCursor }
    mov   ah,01h
    mov   ch,[StLine]
    mov   cl,[EnLine]
    int   10h
  end; { EditCursor }

procedure GotoXY; assembler; asm                                   { GotoXy }
    mov   ah,02h
    xor   bh,bh
    mov   dh,[y]
    mov   dl,[x]
    dec   dh
    dec   dl
    int   10h
  end; { GotoXY }

function WhereX; assembler; asm                                    { WhereX }
    mov   ah,03h
    xor   bh,bh
    int   10h
    mov   al,dl
    inc   al
  end; { WhereX }

function WhereY; assembler; asm                                    { WhereX }
    mov   ah,03h
    xor   bh,bh
    int   10h
    mov   al,dh
    inc   al
  end; { WhereY }

procedure Move; assembler; asm                                       { Move }
    push  ds
    lds   si,Source
    les   di,Dest
    mov   ax,[Count]
    mov   cx,ax
    shr   cx,1
    rep   movsw
    test  ax,1
    jz    @@e
    movsb
@@e:pop   ds
  end; { Move }

{$EndIf}
{ ######################################################################### }
{ ##                                ANY OS                               ## }
{ ######################################################################### }

procedure WinBor;                                                  { WinBor }
  begin
    Window(X1,Y1,X2,Y2,Attr);
    WriteHr(x1+1,y1,Attr,x2-x1-1,Mask[1]);
    WriteHr(x1+1,y2,Attr,x2-x1-1,Mask[2]);
    WriteVr(x1,y1+1,Attr,y2-y1-1,Mask[3]);
    WriteVr(x2,y1+1,Attr,y2-y1-1,Mask[4]);
    WriteCh(x2,y1,Attr,Mask[5]);
    WriteCh(x2,y2,Attr,Mask[6]);
    WriteCh(x1,y1,Attr,Mask[7]);
    WriteCh(x1,y2,Attr,Mask[8]);
  end; { WinBor }

var Saved : array[1..4000] of Word;              { saved screen: max 80x50  }

procedure PushScreen;                                          { PushScreen }
  begin
    Move(VideoMem^,Saved,8000);
  end; { PushScreen }

procedure PopScreen;                                            { PopScreen }
  begin
    Move(Saved,VideoMem^,8000);
  end; { PopScreen }

procedure WaitRetrace;                                        { WaitRetrace }
  {$IfDef Os2} begin
{    while Port[$3DA]<>8 do;}
  {$Else} assembler; asm
    mov   dx,$3DA
@V1:in    al,dx
    test  al,08h
    jz    @v1
  {$EndIf}
  end; { WaitRetrace }

procedure UpdateScreen;                                      { UpdateScreen }
  begin
    {$IfDef OS2}
    VioShowBuf(0,4000,0);
    {$EndIf}
  end; { UpdateScreen }

begin
  asm cld end;
  {$IfDef Os2} CountB800;
  {$Else}      VideoMem:=Ptr($B800,0); {$EndIf}
end.