mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-18 08:59:32 +02:00

they're a total mess ATM, under fixing/cleanup, but IDE start up at least git-svn-id: trunk@6086 -
429 lines
11 KiB
ObjectPascal
429 lines
11 KiB
ObjectPascal
{
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 2006 by Karoly Balogh
|
|
member of the Free Pascal development team
|
|
|
|
Video unit for Amiga and MorphOS
|
|
|
|
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
|
|
|
|
uses
|
|
intuition;
|
|
|
|
{$i videoh.inc}
|
|
|
|
var
|
|
videoWindow : pWindow;
|
|
|
|
implementation
|
|
|
|
uses
|
|
// dos
|
|
exec,graphics;
|
|
|
|
{$i video.inc}
|
|
|
|
{$i videodata.inc}
|
|
|
|
const
|
|
LastCursorType: word = crUnderline;
|
|
OrigScreen: PVideoBuf = nil;
|
|
OrigScreenSize: cardinal = 0;
|
|
|
|
var
|
|
videoColorMap : pColorMap;
|
|
videoPens : array[0..15] of longint;
|
|
|
|
oldCursorX, oldCursorY: longint;
|
|
visibleCursor: boolean;
|
|
oldvisibleCursor: boolean;
|
|
|
|
procedure SysInitVideo;
|
|
var counter: longint;
|
|
begin
|
|
writeln('sysinitvideo');
|
|
InitGraphicsLibrary;
|
|
InitIntuitionLibrary;
|
|
{
|
|
ScreenColor:=true;
|
|
GetConsoleScreenBufferInfo(TextRec(Output).Handle, OrigConsoleInfo);
|
|
GetConsoleCursorInfo(TextRec(Output).Handle, OrigConsoleCursorInfo);
|
|
OrigCP := GetConsoleCP;
|
|
ConsoleInfo:=OrigConsoleInfo;
|
|
ConsoleCursorInfo:=OrigConsoleCursorInfo;
|
|
{
|
|
About the ConsoleCursorInfo record: There are 3 possible
|
|
structures in it that can be regarded as the 'screen':
|
|
- dwsize : contains the cols & row in current screen buffer.
|
|
- srwindow : Coordinates (relative to buffer) of upper left
|
|
& lower right corners of visible console.
|
|
- dmMaximumWindowSize : Maximal size of Screen buffer.
|
|
The first implementation of video used srWindow. After some
|
|
bug-reports, this was switched to dwMaximumWindowSize.
|
|
}
|
|
with ConsoleInfo.dwMaximumWindowSize do
|
|
begin
|
|
ScreenWidth:=X;
|
|
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;
|
|
}
|
|
videoWindow:=OpenWindowTags(Nil, [
|
|
WA_Left,50,
|
|
WA_Top,50,
|
|
WA_InnerWidth,80*8,
|
|
WA_InnerHeight,25*16,
|
|
// WA_IDCMP,IDCMP_MOUSEBUTTONS Or IDCMP_RAWKEYS,
|
|
WA_IDCMP,IDCMP_VANILLAKEY Or IDCMP_RAWKEY,
|
|
WA_Title,DWord(PChar('Free Pascal Video Output')),
|
|
WA_Flags,(WFLG_GIMMEZEROZERO Or WFLG_SMART_REFRESH Or WFLG_NOCAREREFRESH Or WFLG_ACTIVATE Or WFLG_DRAGBAR Or WFLG_DEPTHGADGET)
|
|
]);
|
|
|
|
ScreenWidth := 80;
|
|
ScreenHeight := 25;
|
|
|
|
videoColorMap := pScreen(videoWindow^.WScreen)^.ViewPort.ColorMap;
|
|
for counter:=0 to 15 do begin
|
|
videoPens[counter]:=ObtainPen(videoColorMap,-1,
|
|
vgacolors[counter,0] shl 24,vgacolors[counter,1] shl 24,vgacolors[counter,2] shl 24,
|
|
PEN_EXCLUSIVE);
|
|
// writeln(videoPens[counter]);
|
|
// XXX: do checks for -1 colors (KB)
|
|
end;
|
|
|
|
CursorX:=0;
|
|
CursorY:=0;
|
|
oldCursorX:=0;
|
|
oldCursorY:=0;
|
|
visibleCursor:=true;
|
|
oldvisibleCursor:=true;
|
|
end;
|
|
|
|
|
|
procedure SysDoneVideo;
|
|
var counter: longint;
|
|
begin
|
|
if videoWindow<>nil then CloseWindow(videoWindow);
|
|
for counter:=0 to 15 do ReleasePen(videoColorMap,videoPens[counter]);
|
|
|
|
{
|
|
SetConsoleScreenBufferSize (TextRec (Output).Handle, OrigConsoleInfo.dwSize);
|
|
SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, OrigConsoleInfo.srWindow);
|
|
SetConsoleCursorInfo(TextRec(Output).Handle, OrigConsoleCursorInfo);
|
|
SetConsoleCP(OrigCP);
|
|
}
|
|
end;
|
|
|
|
|
|
|
|
function SysVideoModeSelector (const VideoMode: TVideoMode): boolean;
|
|
|
|
{
|
|
var MI: Console_Screen_Buffer_Info;
|
|
C: Coord;
|
|
SR: Small_Rect;
|
|
}
|
|
begin
|
|
{
|
|
if not (GetConsoleScreenBufferInfo (TextRec (Output).Handle, MI)) then
|
|
SysVideoModeSelector := false
|
|
else
|
|
begin
|
|
with MI do
|
|
begin
|
|
C.X := VideoMode.Col;
|
|
C.Y := VideoMode.Row;
|
|
end;
|
|
with SR do
|
|
begin
|
|
Top := 0;
|
|
Left := 0;
|
|
{ First, we need to make sure we reach the minimum window size
|
|
to always fit in the new buffer after changing buffer size. }
|
|
Right := MI.srWindow.Right - MI.srWindow.Left;
|
|
if VideoMode.Col <= Right then
|
|
Right := Pred (VideoMode.Col);
|
|
Bottom := MI.srWindow.Bottom - MI.srWindow.Top;
|
|
if VideoMode.Row <= Bottom then
|
|
Bottom := Pred (VideoMode.Row);
|
|
end;
|
|
if SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, SR) then
|
|
if SetConsoleScreenBufferSize (TextRec (Output).Handle, C) then
|
|
begin
|
|
with SR do
|
|
begin
|
|
{ Now, we can resize the window to the final size. }
|
|
Right := Pred (VideoMode.Col);
|
|
Bottom := Pred (VideoMode.Row);
|
|
end;
|
|
if SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, SR) then
|
|
begin
|
|
SysVideoModeSelector := true;
|
|
SetCursorType (LastCursorType);
|
|
ClearScreen;
|
|
end
|
|
else
|
|
begin
|
|
SysVideoModeSelector := false;
|
|
SetConsoleScreenBufferSize (TextRec (Output).Handle, MI.dwSize);
|
|
SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, MI.srWindow);
|
|
SetCursorType (LastCursorType);
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
SysVideoModeSelector := false;
|
|
SetConsoleWindowInfo (cardinal (TextRec (Output).Handle), true, MI.srWindow);
|
|
SetCursorType (LastCursorType);
|
|
end
|
|
else
|
|
SysVideoModeSelector := false;
|
|
end;
|
|
}
|
|
end;
|
|
|
|
Const
|
|
SysVideoModeCount = 6;
|
|
SysVMD : Array[0..SysVideoModeCount-1] of TVideoMode = (
|
|
(Col: 40; Row: 25; Color: True),
|
|
(Col: 80; Row: 25; Color: True),
|
|
(Col: 80; Row: 30; Color: True),
|
|
(Col: 80; Row: 43; Color: True),
|
|
(Col: 80; Row: 50; Color: True),
|
|
(Col: 80; Row: 25; Color: True) // Reserved for TargetEntry
|
|
);
|
|
|
|
|
|
Function SysSetVideoMode (Const Mode : TVideoMode) : Boolean;
|
|
|
|
Var
|
|
I : Integer;
|
|
|
|
begin
|
|
{
|
|
I:=SysVideoModeCount-1;
|
|
SysSetVideoMode:=False;
|
|
While (I>=0) and Not SysSetVideoMode do
|
|
If (Mode.col=SysVMD[i].col) and
|
|
(Mode.Row=SysVMD[i].Row) and
|
|
(Mode.Color=SysVMD[i].Color) then
|
|
SysSetVideoMode:=True
|
|
else
|
|
Dec(I);
|
|
If SysSetVideoMode then
|
|
begin
|
|
if SysVideoModeSelector(Mode) then
|
|
begin
|
|
ScreenWidth:=SysVMD[I].Col;
|
|
ScreenHeight:=SysVMD[I].Row;
|
|
ScreenColor:=SysVMD[I].Color;
|
|
end else SysSetVideoMode := false;
|
|
end;
|
|
}
|
|
end;
|
|
|
|
Function SysGetVideoModeData (Index : Word; Var Data : TVideoMode) : boolean;
|
|
|
|
begin
|
|
SysGetVideoModeData:=(Index<=high(SysVMD));
|
|
If SysGetVideoModeData then
|
|
Data:=SysVMD[Index];
|
|
end;
|
|
|
|
Function SysGetVideoModeCount : Word;
|
|
|
|
begin
|
|
SysGetVideoModeCount:=SysVideoModeCount;
|
|
end;
|
|
|
|
procedure SysClearScreen;
|
|
begin
|
|
UpdateScreen(true);
|
|
end;
|
|
|
|
|
|
procedure DrawChar(x,y: longint; bitmap: pBitmap; drawCursor: boolean);
|
|
var tmpCharData: word;
|
|
tmpChar : byte;
|
|
tmpRow : byte;
|
|
tmpFGColor : byte;
|
|
tmpBGColor : byte;
|
|
var
|
|
counterX, counterY:longint;
|
|
sX,sY: longint;
|
|
begin
|
|
tmpCharData:=VideoBuf^[y*ScreenWidth+x];
|
|
tmpChar :=tmpCharData and $0ff;
|
|
tmpFGColor :=(tmpCharData shr 8) and %00001111;
|
|
tmpBGColor :=(tmpCharData shr 12) and %00000111;
|
|
|
|
// write('"',char(tmpChar),'" ',tmpChar);
|
|
sX:=x*8;
|
|
sY:=y*16;
|
|
|
|
SetAPen(videoWindow^.RPort,videoPens[tmpBGColor]);
|
|
RectFill(videoWindow^.RPort, sX, sY, sX + 7, sY + 15);
|
|
|
|
SetAPen(videoWindow^.Rport,videoPens[tmpFGColor]);
|
|
for counterY:=0 to 15 do begin
|
|
tmpRow:=vgafont[tmpChar,counterY];
|
|
if (tmpRow>0) then begin
|
|
for counterX:=0 to 7 do begin
|
|
if ((tmpRow and (1 shl counterX)) > 0) then
|
|
WritePixel(videoWindow^.RPort,sX+counterX,sY+counterY);
|
|
end;
|
|
end;
|
|
end;
|
|
if drawCursor then begin
|
|
gfxMove(videoWindow^.RPort,sX,sY+14); Draw(videoWindow^.RPort,sX+7,sY+14);
|
|
gfxMove(videoWindow^.RPort,sX,sY+15); Draw(videoWindow^.RPort,sX+7,sY+15);
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
procedure SysUpdateScreen(force: boolean);
|
|
var
|
|
BufCounter : Longint;
|
|
smallforce : boolean;
|
|
|
|
counter, counterX, counterY: longint;
|
|
var
|
|
tmpBitmap : tBitmap;
|
|
begin
|
|
if force then
|
|
smallforce:=true
|
|
else begin
|
|
counter:=0;
|
|
while not smallforce and (counter<(VideoBufSize div 4)-1) do begin
|
|
if PDWord(VideoBuf)[counter]<>PDWord(OldVideoBuf)[counter] then smallforce:=true;
|
|
counter+=1;
|
|
end;
|
|
end;
|
|
|
|
BufCounter:=0;
|
|
if smallforce then begin
|
|
for counterY:=0 to ScreenHeight-1 do begin
|
|
for counterX:=0 to ScreenWidth-1 do begin
|
|
if VideoBuf^[BufCounter]<>OldVideoBuf^[BufCounter] then
|
|
DrawChar(counterX,counterY,@tmpBitmap,false);
|
|
Inc(BufCounter);
|
|
end;
|
|
end;
|
|
move(VideoBuf^,OldVideoBuf^,VideoBufSize);
|
|
end;
|
|
|
|
if (oldvisibleCursor<>visibleCursor) or (CursorX<>oldCursorX) or (CursorY<>oldCursorY) then begin
|
|
writeln('kurzor:',cursorx,' ',cursory);
|
|
DrawChar(oldCursorY,oldCursorX,@tmpBitmap,false);
|
|
DrawChar(CursorY,CursorX,@tmpBitmap,visibleCursor);
|
|
oldCursorX:=CursorX;
|
|
oldCursorY:=CursorY;
|
|
oldVisibleCursor:=visibleCursor;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure SysSetCursorPos(NewCursorX, NewCursorY: Word);
|
|
begin
|
|
CursorX:=NewCursorY;
|
|
CursorY:=NewCursorX;
|
|
SysUpdateScreen(false);
|
|
end;
|
|
|
|
function SysGetCapabilities: Word;
|
|
begin
|
|
SysGetCapabilities:=cpColor or cpChangeCursor;
|
|
end;
|
|
|
|
function SysGetCursorType: Word;
|
|
begin
|
|
if not visibleCursor then SysGetCursorType:=crHidden
|
|
else SysGetCursorType:=crUnderline;
|
|
|
|
{
|
|
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
|
|
if newType=crHidden then visibleCursor:=false
|
|
else visibleCursor:=true;
|
|
SysUpdateScreen(false);
|
|
{
|
|
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;
|
|
|
|
|
|
|
|
const
|
|
SysVideoDriver : TVideoDriver = (
|
|
InitDriver : @SysInitVideo;
|
|
DoneDriver : @SysDoneVideo;
|
|
UpdateScreen : @SysUpdateScreen;
|
|
ClearScreen : @SysClearScreen;
|
|
SetVideoMode : @SysSetVideoMode;
|
|
GetVideoModeCount : @SysGetVideoModeCount;
|
|
GetVideoModeData : @SysGetVideoModeData;
|
|
SetCursorPos : @SysSetCursorPos;
|
|
GetCursorType : @SysGetCursorType;
|
|
SetCursorType : @SysSetCursorType;
|
|
GetCapabilities : @SysGetCapabilities
|
|
|
|
);
|
|
|
|
|
|
initialization
|
|
SetVideoDriver(SysVideoDriver);
|
|
end.
|