mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 21:07:54 +02:00
358 lines
9.1 KiB
ObjectPascal
358 lines
9.1 KiB
ObjectPascal
{****************************************************************************
|
|
|
|
|
|
Standard CRT unit.
|
|
Free Pascal runtime library for OS/2.
|
|
Copyright (c) 1997 Daniel Mantione.
|
|
|
|
This file may be reproduced and modified under the same conditions
|
|
as all other Free Pascal source code.
|
|
|
|
****************************************************************************}
|
|
|
|
unit crt;
|
|
|
|
interface
|
|
|
|
{$INLINE ON}
|
|
|
|
{$i crth.inc}
|
|
|
|
procedure Window32 (X1, Y1, X2, Y2: dword);
|
|
procedure GotoXY32 (X, Y: dword);
|
|
function WhereX32: dword;
|
|
function WhereY32: dword;
|
|
|
|
|
|
var
|
|
ScreenHeight, ScreenWidth: dword;
|
|
(* API *)
|
|
|
|
|
|
implementation
|
|
|
|
{uses keyboard, video;}
|
|
|
|
|
|
{$i textrec.inc}
|
|
|
|
const
|
|
VioHandle: word = 0;
|
|
|
|
|
|
type
|
|
TKbdKeyInfo = record
|
|
CharCode, ScanCode: char;
|
|
fbStatus, bNlsShift: byte;
|
|
fsState: word;
|
|
Time: longint;
|
|
end;
|
|
|
|
VioModeInfo = record
|
|
cb: word; { length of the entire data
|
|
structure }
|
|
fbType, { bit mask of mode being set}
|
|
Color: byte; { number of colors (power of 2) }
|
|
Col, { number of text columns }
|
|
Row, { number of text rows }
|
|
HRes, { horizontal resolution }
|
|
VRes: word; { vertical resolution }
|
|
fmt_ID, { attribute format }
|
|
Attrib: byte; { number of attributes }
|
|
Buf_Addr, { physical address of
|
|
videobuffer, e.g. $0b800}
|
|
Buf_Length, { length of a videopage (bytes)}
|
|
Full_Length, { total video-memory on video-
|
|
card (bytes)}
|
|
Partial_Length: longint; { ????? info wanted !}
|
|
Ext_Data_Addr: pointer; { ????? info wanted !}
|
|
end;
|
|
|
|
TVioCursorInfo=record
|
|
case boolean of
|
|
false: (
|
|
yStart: word; {Cursor start (top) scan line (0-based)}
|
|
cEnd: word; {Cursor end (bottom) scan line}
|
|
cx: word; {Cursor width (0=default width)}
|
|
Attr: word); {Cursor colour attribute (-1=hidden)}
|
|
true:(
|
|
yStartInt: integer; {integer variants can be used to specify negative}
|
|
cEndInt: integer; {negative values (interpreted as percentage by OS/2)}
|
|
cxInt: integer;
|
|
AttrInt: integer);
|
|
end;
|
|
PVioCursorInfo = ^TVioCursorInfo;
|
|
|
|
|
|
function KbdCharIn (var AKeyRec: TKbdKeyInfo; Wait, KbdHandle: longint):
|
|
word; cdecl;
|
|
external 'EMXWRAP' index 204;
|
|
function KbdPeek (var AKeyRec: TKbdKeyInfo; KbdHandle: longint): word; cdecl;
|
|
external 'EMXWRAP' index 222;
|
|
|
|
function DosSleep (Time: cardinal): word; cdecl;
|
|
external 'DOSCALLS' index 229;
|
|
function VioScrollUp (Top, Left, Bottom, Right, Lines: longint;
|
|
var ScrEl: word; VioHandle: word): word; cdecl;
|
|
external 'EMXWRAP' index 107;
|
|
{$WARNING ScrEl as word not DBCS safe!}
|
|
function VioScrollDn (Top, Left, Bottom, Right, Lines: longint;
|
|
var ScrEl: word; VioHandle: word): word; cdecl;
|
|
external 'EMXWRAP' index 147;
|
|
function VioScrollRight (Top, Left, Bottom, Right, Columns: word;
|
|
var ScrEl: word; VioHandle: word): word; cdecl;
|
|
external 'EMXWRAP' index 112;
|
|
{external 'VIOCALLS' index 12;}
|
|
function VioGetCurPos (var Row, Column: word; VioHandle: word): word; cdecl;
|
|
external 'EMXWRAP' index 109;
|
|
function VioSetCurPos (Row, Column, VioHandle: word): word; cdecl;
|
|
external 'EMXWRAP' index 115;
|
|
function VioWrtCharStrAtt (S: PChar; Len, Row, Col: longint; var Attr: byte;
|
|
VioHandle: word): word; cdecl;
|
|
external 'EMXWRAP' index 148;
|
|
function VioGetMode (var AModeInfo: VioModeInfo; VioHandle: word): word; cdecl;
|
|
external 'EMXWRAP' index 121;
|
|
function VioSetMode (var AModeInfo: VioModeInfo; VioHandle: word): word; cdecl;
|
|
external 'EMXWRAP' index 122;
|
|
function VioSetCurType (var CurData: TVioCursorInfo; VioHandle: word): word;
|
|
cdecl;
|
|
external 'EMXWRAP' index 132;
|
|
{external 'VIOCALLS' index 32;}
|
|
function VioGetCurType (var CurData: TVioCursorInfo; VioHandle: word): word;
|
|
cdecl;
|
|
external 'EMXWRAP' index 127;
|
|
{external 'VIOCALLS' index 27;}
|
|
function VioCreatePS (var VPS: word; Depth, Width, Format, Attrs: integer;
|
|
Reserved: word): word; cdecl;
|
|
external 'EMXWRAP' index 156;
|
|
{external 'VIOCALLS' index 56;}
|
|
function DosBeep (Freq, MS: cardinal): cardinal; cdecl;
|
|
external 'DOSCALLS' index 286;
|
|
|
|
|
|
|
|
threadvar
|
|
ExtKeyCode: char;
|
|
|
|
|
|
|
|
function KeyPressed: boolean;
|
|
{Checks if a key is pressed.}
|
|
var
|
|
AKeyRec: TKbdKeyinfo;
|
|
begin
|
|
if ExtKeyCode <> #0 then
|
|
KeyPressed := true
|
|
else
|
|
KeyPressed := (KbdPeek (AKeyRec, 0) = 0)
|
|
and ((AKeyRec.fbStatus and $40) <> 0);
|
|
end;
|
|
|
|
|
|
function ReadKey: char;
|
|
{Reads the next character from the keyboard.}
|
|
var
|
|
AKeyRec: TKbdKeyInfo;
|
|
C, S: char;
|
|
begin
|
|
if ExtKeyCode <> #0 then
|
|
begin
|
|
ReadKey := ExtKeyCode;
|
|
ExtKeyCode := #0
|
|
end
|
|
else
|
|
begin
|
|
KbdCharIn (AKeyRec, 0, 0);
|
|
C := AKeyRec.CharCode;
|
|
S := AKeyRec.ScanCode;
|
|
if (C = #224) and (S <> #0) then
|
|
C := #0;
|
|
if C = #0 then
|
|
ExtKeyCode := S;
|
|
ReadKey := C;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure GetScreenCursor (var X, Y: dword);inline;
|
|
(* Return current cursor postion - 0-based. *)
|
|
var
|
|
X0, Y0: word;
|
|
begin
|
|
X := 0;
|
|
Y := 0;
|
|
if VioGetCurPos (Y0, X0, VioHandle) = 0 then
|
|
begin
|
|
X := X0;
|
|
Y := Y0;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure SetScreenCursor (X, Y: dword); inline;
|
|
(* Set current cursor postion - 0-based. *)
|
|
begin
|
|
VioSetCurPos (Y, X, VioHandle);
|
|
end;
|
|
|
|
|
|
procedure RemoveLines (Row: dword; Cnt: dword); inline;
|
|
(* Remove Cnt lines from screen starting with (0-based) Row. *)
|
|
var
|
|
ScrEl: word;
|
|
begin
|
|
ScrEl := $20 or (TextAttr shl 8);
|
|
VioScrollUp (Row + WindMinY, WindMinX, WindMaxY, WindMaxX, Cnt, ScrEl,
|
|
VioHandle);
|
|
end;
|
|
|
|
|
|
procedure ClearCells (X, Y, Cnt: dword); inline;
|
|
(* Clear Cnt cells in line Y (0-based) starting with position X (0-based). *)
|
|
var
|
|
ScrEl: word;
|
|
begin
|
|
ScrEl := $20 or (TextAttr shl 8);
|
|
VioScrollRight (Y, X, Y, X + Pred (Cnt), Cnt, ScrEl, VioHandle);
|
|
end;
|
|
|
|
|
|
procedure InsLine;
|
|
(* Inserts a line at cursor position. *)
|
|
var
|
|
ScrEl: word;
|
|
begin
|
|
ScrEl := $20 or (TextAttr shl 8);
|
|
VioScrollDn (Pred (WhereY32) + WindMinY, WindMinX, WindMaxY, WindMaxX, 1,
|
|
ScrEl, VioHandle);
|
|
end;
|
|
|
|
|
|
procedure SetScreenMode (Mode: word);
|
|
var
|
|
NewMode: VioModeInfo;
|
|
begin
|
|
NewMode.cb := 8;
|
|
VioGetMode (NewMode, VioHandle);
|
|
NewMode.fbType := 1; {Non graphics colour mode.}
|
|
NewMode.Color := 4; {We want 16 colours, 2^4=16 - requests for BW ignored.}
|
|
case Mode and $FF of
|
|
BW40, CO40: NewMode.Col := 40;
|
|
BW80, CO80: NewMode.Col := 80;
|
|
else
|
|
begin
|
|
(* Keep current amount of columns! *)
|
|
end;
|
|
end;
|
|
case Mode and $100 of
|
|
0: NewMode.Row := 25;
|
|
$100: NewMode.Row := 50
|
|
else
|
|
begin
|
|
(* Keep current amount of rows! *)
|
|
end;
|
|
end;
|
|
VioSetMode (NewMode, VioHandle);
|
|
ScreenWidth := NewMode.Col;
|
|
ScreenHeight := NewMode.Row;
|
|
end;
|
|
|
|
|
|
procedure Delay (Ms: word);
|
|
{Waits ms milliseconds.}
|
|
begin
|
|
DosSleep (Ms)
|
|
end;
|
|
|
|
|
|
procedure WriteNormal (C: char; X, Y: dword); inline;
|
|
(* Write C to console at X, Y (0-based). *)
|
|
begin
|
|
VioWrtCharStrAtt (@C, 1, Y, X, TextAttr, VioHandle);
|
|
end;
|
|
|
|
|
|
procedure WriteBell; inline;
|
|
(* Write character #7 - beep. *)
|
|
begin
|
|
DosBeep (800, 250);
|
|
end;
|
|
|
|
|
|
|
|
{****************************************************************************
|
|
Extra Crt Functions
|
|
****************************************************************************}
|
|
|
|
|
|
procedure CursorOn;
|
|
var
|
|
I: TVioCursorInfo;
|
|
begin
|
|
VioGetCurType (I, VioHandle);
|
|
with I do
|
|
begin
|
|
yStartInt := -90;
|
|
cEndInt := -100;
|
|
Attr := 15;
|
|
end;
|
|
VioSetCurType (I, VioHandle);
|
|
end;
|
|
|
|
|
|
procedure CursorOff;
|
|
var
|
|
I: TVioCursorInfo;
|
|
begin
|
|
VioGetCurType (I, VioHandle);
|
|
I.AttrInt := -1;
|
|
VioSetCurType (I, VioHandle);
|
|
end;
|
|
|
|
|
|
procedure CursorBig;
|
|
var
|
|
I: TVioCursorInfo;
|
|
begin
|
|
VioGetCurType (I, VioHandle);
|
|
with I do
|
|
begin
|
|
yStart := 0;
|
|
cEndInt := -100;
|
|
Attr := 15;
|
|
end;
|
|
VioSetCurType (I, VioHandle);
|
|
end;
|
|
|
|
|
|
(* Include common, platform independent part. *)
|
|
{$I crt.inc}
|
|
|
|
|
|
{Initialization.}
|
|
|
|
var
|
|
CurMode: VioModeInfo;
|
|
begin
|
|
if not (IsConsole) then
|
|
VioCreatePS (VioHandle, 25, 80, 1, 1, 0);
|
|
{ InitVideo;}
|
|
CurMode.cb := SizeOf (CurMode);
|
|
VioGetMode (CurMode, VioHandle);
|
|
ScreenWidth := CurMode.Col;
|
|
ScreenHeight := CurMode.Row;
|
|
LastMode := 0;
|
|
case ScreenWidth of
|
|
40: LastMode := CO40;
|
|
80: LastMode := CO80
|
|
else
|
|
LastMode := 255
|
|
end;
|
|
case ScreenHeight of
|
|
50: LastMode := LastMode + $100
|
|
else
|
|
LastMode := LastMode + $FF00;
|
|
end;
|
|
CrtInit;
|
|
end.
|