fpc/rtl/win32/video.pp
2001-09-21 19:50:18 +00:00

410 lines
10 KiB
ObjectPascal

{
$Id$
This file is part of the Free Pascal run time library.
Copyright (c) 1999-2000 by Florian Klaempfl
member of the Free Pascal development team
Video unit for Win32
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
unit Video;
interface
{$i videoh.inc}
implementation
uses
windows,dos;
{$i video.inc}
var
OldVideoBuf : PVideoBuf;
ConsoleInfo : TConsoleScreenBufferInfo;
ConsoleCursorInfo : TConsoleCursorInfo;
MaxVideoBufSize : DWord;
procedure SysInitVideo;
begin
ScreenColor:=true;
GetConsoleScreenBufferInfo(TextRec(Output).Handle, ConsoleInfo);
GetConsoleCursorInfo(TextRec(Output).Handle, ConsoleCursorInfo);
with ConsoleInfo.srWindow do
begin
ScreenWidth:=right-left+1;
ScreenHeight:=bottom-top+1;
end;
{ srWindow is sometimes bigger then dwMaximumWindowSize
this led to wrong ScreenWidth and ScreenHeight values PM }
{ damned: its also sometimes less !! PM }
with ConsoleInfo.dwMaximumWindowSize do
begin
{if ScreenWidth>X then}
ScreenWidth:=X;
{if ScreenHeight>Y then}
ScreenHeight:=Y;
end;
{ TDrawBuffer only has FVMaxWidth elements
larger values lead to crashes }
if ScreenWidth> FVMaxWidth then
ScreenWidth:=FVMaxWidth;
CursorX:=ConsoleInfo.dwCursorPosition.x;
CursorY:=ConsoleInfo.dwCursorPosition.y;
if not ConsoleCursorInfo.bvisible then
CursorLines:=0
else
CursorLines:=ConsoleCursorInfo.dwSize;
{ allocate back buffer }
MaxVideoBufSize:= ScreenWidth * ScreenHeight * 2;
VideoBufSize:=ScreenWidth*ScreenHeight*2;
GetMem(VideoBuf,MaxVideoBufSize);
GetMem(OldVideoBuf,MaxVideoBufSize);
end;
procedure SysDoneVideo;
begin
SetCursorType(crUnderLine);
FreeMem(VideoBuf,MaxVideoBufSize);
FreeMem(OldVideoBuf,MaxVideoBufSize);
VideoBufSize:=0;
VideoInitialized:=false;
end;
function SysGetCapabilities: Word;
begin
SysGetCapabilities:=cpColor or cpChangeCursor;
end;
procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
var
pos : COORD;
begin
pos.x:=NewCursorX;
pos.y:=NewCursorY;
SetConsoleCursorPosition(TextRec(Output).Handle,pos);
CursorX:=pos.x;
CursorY:=pos.y;
end;
function SysGetCursorType: Word;
begin
GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
if not ConsoleCursorInfo.bvisible then
SysGetCursorType:=crHidden
else
case ConsoleCursorInfo.dwSize of
1..30:
SysGetCursorType:=crUnderline;
31..70:
SysGetCursorType:=crHalfBlock;
71..100:
SysGetCursorType:=crBlock;
end;
end;
procedure SysSetCursorType(NewType: Word);
begin
GetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
if newType=crHidden then
ConsoleCursorInfo.bvisible:=false
else
begin
ConsoleCursorInfo.bvisible:=true;
case NewType of
crUnderline:
ConsoleCursorInfo.dwSize:=10;
crHalfBlock:
ConsoleCursorInfo.dwSize:=50;
crBlock:
ConsoleCursorInfo.dwSize:=99;
end
end;
SetConsoleCursorInfo(TextRec(Output).Handle,ConsoleCursorInfo);
end;
function DefaultVideoModeSelector(const VideoMode: TVideoMode; Params: Longint): Boolean;
begin
DefaultVideoModeSelector:=true;
end;
procedure SysClearScreen;
begin
FillWord(VideoBuf^,VideoBufSize div 2,$0720);
UpdateScreen(true);
end;
{$IFDEF FPC}
function WriteConsoleOutput(hConsoleOutput:HANDLE; lpBuffer:pointer; dwBufferSize:COORD; dwBufferCoord:COORD;
var lpWriteRegion:SMALL_RECT):WINBOOL; external 'kernel32' name 'WriteConsoleOutputA';
{$ENDIF}
procedure SysUpdateScreen(Force: Boolean);
type TmpRec = Array[0..(1024*32) - 1] of TCharInfo;
type WordRec = record
One, Two: Byte;
end; { wordrec }
var
BufSize,
BufCoord : COORD;
WriteRegion : SMALL_RECT;
LineBuf : ^TmpRec;
BufCounter : Longint;
LineCounter,
ColCounter : Longint;
smallforce : boolean;
(*
begin
if LockUpdateScreen<>0 then
exit;
if not force then
begin
asm
movl VideoBuf,%esi
movl OldVideoBuf,%edi
movl VideoBufSize,%ecx
shrl $2,%ecx
repe
cmpsl
setne force
end;
end;
if Force then
begin
BufSize.X := ScreenWidth;
BufSize.Y := ScreenHeight;
BufCoord.X := 0;
BufCoord.Y := 0;
with WriteRegion do
begin
Top :=0;
Left :=0;
Bottom := ScreenHeight-1;
Right := ScreenWidth-1;
end;
New(LineBuf);
BufCounter := 0;
for LineCounter := 1 to ScreenHeight do
begin
for ColCounter := 1 to ScreenWidth do
begin
LineBuf^[BufCounter].UniCodeChar := Widechar(WordRec(VideoBuf^[BufCounter]).One);
LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
Inc(BufCounter);
end; { for }
end; { for }
WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
Dispose(LineBuf);
move(VideoBuf^,OldVideoBuf^,VideoBufSize);
end;
end;
*)
var
x1,y1,x2,y2 : longint;
begin
if force then
smallforce:=true
else
begin
asm
movl VideoBuf,%esi
movl OldVideoBuf,%edi
movl VideoBufSize,%ecx
shrl $2,%ecx
repe
cmpsl
orl %ecx,%ecx
jz .Lno_update
movb $1,smallforce
.Lno_update:
end;
end;
if SmallForce then
begin
BufSize.X := ScreenWidth;
BufSize.Y := ScreenHeight;
BufCoord.X := 0;
BufCoord.Y := 0;
with WriteRegion do
begin
Top :=0;
Left :=0;
Bottom := ScreenHeight-1;
Right := ScreenWidth-1;
end;
New(LineBuf);
BufCounter := 0;
x1:=ScreenWidth+1;
x2:=-1;
y1:=ScreenHeight+1;
y2:=-1;
for LineCounter := 1 to ScreenHeight do
begin
for ColCounter := 1 to ScreenWidth do
begin
if (WordRec(VideoBuf^[BufCounter]).One<>WordRec(OldVideoBuf^[BufCounter]).One) or
(WordRec(VideoBuf^[BufCounter]).Two<>WordRec(OldVideoBuf^[BufCounter]).Two) then
begin
if ColCounter<x1 then
x1:=ColCounter;
if ColCounter>x2 then
x2:=ColCounter;
if LineCounter<y1 then
y1:=LineCounter;
if LineCounter>y2 then
y2:=LineCounter;
end;
{$ifdef HASWIDECHAR}
{$ifdef VER1_0}
LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One;
{$else}
LineBuf^[BufCounter].UniCodeChar := Widechar(WordRec(VideoBuf^[BufCounter]).One);
{$endif}
{$else}
LineBuf^[BufCounter].UniCodeChar := WordRec(VideoBuf^[BufCounter]).One);
{$endif}
{ If (WordRec(VideoBuf^[BufCounter]).Two and $80)<>0 then
LineBuf^[BufCounter].Attributes := $100+WordRec(VideoBuf^[BufCounter]).Two
else }
LineBuf^[BufCounter].Attributes := WordRec(VideoBuf^[BufCounter]).Two;
Inc(BufCounter);
end; { for }
end; { for }
BufSize.X := ScreenWidth;
BufSize.Y := ScreenHeight;
with WriteRegion do
begin
if force then
begin
Top := 0;
Left :=0;
Bottom := ScreenHeight-1;
Right := ScreenWidth-1;
BufCoord.X := 0;
BufCoord.Y := 0;
end
else
begin
Top := y1-1;
Left :=x1-1;
Bottom := y2-1;
Right := x2-1;
BufCoord.X := x1-1;
BufCoord.Y := y1-1;
end;
end;
{
writeln('X1: ',x1);
writeln('Y1: ',y1);
writeln('X2: ',x2);
writeln('Y2: ',y2);
}
WriteConsoleOutput(TextRec(Output).Handle, LineBuf, BufSize, BufCoord, WriteRegion);
Dispose(LineBuf);
move(VideoBuf^,OldVideoBuf^,VideoBufSize);
end;
end;
procedure RegisterVideoModes;
begin
{ don't know what to do for win32 (FK) }
RegisterVideoMode(80, 25, True, @DefaultVideoModeSelector, $00000003);
end;
Const
SysVideoDriver : TVideoDriver = (
InitDriver : @SysInitVideo;
DoneDriver : @SysDoneVideo;
UpdateScreen : @SysUpdateScreen;
ClearScreen : @SysClearScreen;
SetVideoMode : Nil;
HasVideoMode : Nil;
SetCursorPos : @SysSetCursorPos;
GetCursorType : @SysGetCursorType;
SetCursorType : @SysSetCursorType;
GetCapabilities : @SysGetCapabilities
);
initialization
SetVideoDriver(SysVideoDriver);
RegisterVideoModes;
finalization
UnRegisterVideoModes;
end.
{
$Log$
Revision 1.6 2001-09-21 19:50:19 michael
+ Merged driver support from fixbranch
Revision 1.5 2001/08/01 18:01:20 peter
* WChar fix to compile also with 1.0.x
Revision 1.4 2001/07/30 15:01:12 marco
* Fixed wchar=word to widechar conversion
Revision 1.3 2001/06/13 18:32:55 peter
* fixed crash within donevideo (merged)
Revision 1.2 2001/04/10 21:28:36 peter
* removed warnigns
Revision 1.1.2.5 2001/09/21 18:42:09 michael
+ Implemented support for custom video drivers.
Revision 1.1.2.4 2001/06/12 22:34:20 pierre
* avoid crash at exit of IDE
Revision 1.1.2.3 2001/04/10 20:33:04 peter
* remove some warnings
Revision 1.1.2.2 2001/04/02 13:29:41 pierre
* avoid crash if DoneVideo called twice
Revision 1.1.2.1 2001/01/30 21:52:03 peter
* moved api utils to rtl
Revision 1.1 2001/01/13 11:03:59 peter
* API 2 RTL commit
}