123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564 |
- {
- System independent low-level video interface for OS/2
- $Id$
- }
- uses
- {$IFDEF PPC_FPC}
- DosCalls, VioCalls;
- {$ELSE}
- {$IFDEF PPC_VIRTUAL}
- Os2Base;
- {$ENDIF}
- {$ENDIF}
- {$IFNDEF FPC}
- type
- cardinal = longint;
- {$ENDIF}
- const
- InitVideoCalled: boolean = false;
- LastCursorType: word = crUnderline;
- EmptyCell: cardinal = $0720;
- OrigScreen: PVideoBuf = nil;
- OrigScreenSize: cardinal = 0;
- {$IFDEF PPC_VIRTUAL}
- type
- TVioCursorInfo = VioCursorInfo;
- TVioModeInfo = VioModeInfo;
- TVioIntensity = VioIntensity;
- {$ENDIF}
- var OrigCurType: TVioCursorInfo;
- OrigVioMode: TVioModeInfo;
- OrigHighBit: TVioIntensity;
- OrigCurRow: word;
- OrigCurCol: word;
- CellHeight: byte;
- OldVideoBuf: PVideoBuf;
- procedure TargetEntry;
- var P: PVideoModeList;
- PScr: pointer;
- begin
- {Remember original video mode, cursor type and high bit behaviour setting}
- OrigVioMode.cb := SizeOf (OrigVioMode);
- VioGetMode (OrigVioMode, 0);
- VioGetCurType (OrigCurType, 0);
- VioGetCurPos (OrigCurRow, OrigCurCol, 0);
- with OrigHighBit do
- begin
- cb := 6;
- rType := 2;
- end;
- VioGetState (OrigHighBit, 0);
- {Register the curent video mode in Modes if not there yet}
- with OrigVioMode do
- begin
- P := Modes;
- while (P <> nil) and ((P^.Row <> Row) or (P^.Col <> Col)
- or (P^.Color <> (Color >= Colors_16))) do
- P := P^.Next;
- if P = nil then
- {Assume we have at least 16 colours available in "colour" modes}
- RegisterVideoMode (Col, Row, Color >= Colors_16,
- {$IFDEF FPC}
- @DefaultVideoModeSelector, 0);
- {$ELSE}
- DefaultVideoModeSelector, 0);
- {$ENDIF}
- end;
- {Get the address of the original videobuffer and size.}
- if VioGetBuf (PScr, PWord (@OrigScreenSize)^, 0) = 0 then
- begin
- {$IFDEF BIT_32}
- {$IFDEF PPC_VIRTUAL}
- SelToFlat (PScr);
- {$ELSE}
- PScr := SelToFlat (TFarPtr (PScr));
- {$ENDIF}
- {$ENDIF}
- GetMem (OrigScreen, OrigScreenSize);
- Move (PScr^, OrigScreen^, OrigScreenSize);
- end;
- end;
- procedure TargetExit;
- begin
- end;
- procedure CheckCellHeight;
- var OldCD, CD: TVioCursorInfo;
- begin
- VioGetCurType (OldCD, 0);
- Move (OldCD, CD, SizeOf (CD));
- with CD do
- begin
- Attr := 0;
- yStart := word (-90);
- cEnd := word (-100);
- end;
- VioSetCurType (CD, 0);
- VioGetCurType (CD, 0);
- CellHeight := CD.cEnd;
- VioSetCurType (OldCD, 0);
- end;
- procedure RegisterVideoModes;
- begin
- { BW modes are rejected on my (colour) configuration. I can't imagine
- OS/2 running on MCGA anyway... ;-)
- RegisterVideoMode (40, 25, False, @DefaultVideoModeSelector, 0);
- RegisterVideoMode (80, 25, False, @DefaultVideoModeSelector, 0);
- }
- {$IFDEF FPC}
- RegisterVideoMode (40, 25, True, @DefaultVideoModeSelector, 0);
- RegisterVideoMode (80, 25, True, @DefaultVideoModeSelector, 0);
- RegisterVideoMode (80, 30, True, @DefaultVideoModeSelector, 0);
- RegisterVideoMode (80, 43, True, @DefaultVideoModeSelector, 0);
- RegisterVideoMode (80, 50, True, @DefaultVideoModeSelector, 0);
- {$ELSE}
- RegisterVideoMode (40, 25, True, DefaultVideoModeSelector, 0);
- RegisterVideoMode (80, 25, True, DefaultVideoModeSelector, 0);
- RegisterVideoMode (80, 30, True, DefaultVideoModeSelector, 0);
- RegisterVideoMode (80, 43, True, DefaultVideoModeSelector, 0);
- RegisterVideoMode (80, 50, True, DefaultVideoModeSelector, 0);
- {$ENDIF}
- { The following modes wouldn't work on plain VGA; is it useful to check
- for their availability on the program startup?
- RegisterVideoMode (132, 25, True, @DefaultVideoModeSelector, 0);
- RegisterVideoMode (132, 30, True, @DefaultVideoModeSelector, 0);
- RegisterVideoMode (132, 43, True, @DefaultVideoModeSelector, 0);
- RegisterVideoMode (132, 50, True, @DefaultVideoModeSelector, 0);
- }
- end;
- procedure SetHighBitBlink (Blink: boolean);
- var VI: TVioIntensity;
- begin
- with VI do
- begin
- cb := 6;
- rType := 2;
- fs := byte (not (Blink));
- end;
- VioSetState (VI, 0);
- end;
- procedure InitVideo;
- var MI: TVioModeInfo;
- begin
- if InitVideoCalled then
- FreeMem (OldVideoBuf, VideoBufSize);
- OldVideoBuf := nil;
- InitVideoCalled := true;
- VideoBufSize := 0;
- MI.cb := SizeOf (MI);
- VioGetMode (MI, 0);
- with MI do
- begin
- ScreenWidth := Col;
- ScreenHeight := Row;
- ScreenColor := Color >= Colors_16;
- end;
- VioGetCurPos (CursorY, CursorX, 0);
- LowAscii := true;
- SetCursorType (LastCursorType);
- {Get the address of the videobuffer.}
- {$IFDEF PPC_VIRTUAL}
- if VioGetBuf (pointer (VideoBuf), PWord (@VideoBufSize)^, 0) = 0 then
- begin
- SelToFlat (pointer (VideoBuf));
- {$ELSE}
- if VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
- begin
- {$IFDEF BIT_32}
- VideoBuf := SelToFlat (TFarPtr (VideoBuf));
- {$ENDIF}
- {$ENDIF}
- SetHighBitBlink (true);
- GetMem (OldVideoBuf, VideoBufSize);
- Move (VideoBuf^, OldVideoBuf^, VideoBufSize);
- end
- else
- ErrorHandler (errVioInit, nil);
- end;
- procedure SetCursorPos (NewCursorX, NewCursorY: word);
- begin
- if VioSetCurPos (NewCursorY, NewCursorX, 0) = 0 then
- begin
- CursorX := NewCursorX;
- CursorY := NewCursorY;
- end
- else
- {Do not set an error code; people should fix invalid NewCursorX
- or NewCursorY values when designing, there is no need for detecting
- these errors at runtime.}
- RunError (225);
- end;
- function GetCursorType: word;
- var CD: TVioCursorInfo;
- begin
- VioGetCurType (CD, 0); {Never fails, because handle is default handle.}
- with CD do
- begin
- CursorLines := Succ (cEnd) - yStart;
- if Attr = word (-1) then
- GetCursorType := crHidden
- else
- {Because the cursor's start and end lines are returned, we'll have
- to guess heuristically what cursor type we have.}
- if CursorLines = 0 then
- {Probably this does not occur, but you'll never know.}
- GetCursorType := crHidden
- else if CursorLines <= Succ (CellHeight div 4) then
- GetCursorType := crUnderline
- else if CursorLines <= Succ (CellHeight div 2) then
- GetCursorType := crHalfBlock
- else
- GetCursorType := crBlock;
- end;
- end;
- procedure SetCursorType (NewType: word);
- var CD: TVioCursorInfo;
- begin
- VioGetCurType (CD, 0);
- with CD do
- begin
- case NewType of
- crHidden: Attr := word (-1);
- crUnderline:
- begin
- Attr := 0;
- yStart := word (-90);
- cEnd := word (-100);
- end;
- crHalfBlock:
- begin
- Attr := 0;
- yStart := word (-50);
- cEnd := word (-100);
- end;
- crBlock:
- begin
- Attr := 0;
- yStart := 0;
- cEnd := word (-100);
- end;
- end;
- VioSetCurType (CD, 0);
- VioGetCurType (CD, 0);
- CursorLines := Succ (cEnd) - yStart;
- end;
- end;
- procedure DoneVideo;
- var PScr: pointer;
- ScrSize: cardinal;
- begin
- if InitVideoCalled then
- begin
- LastCursorType := GetCursorType;
- ClearScreen;
- {Restore original settings}
- VioSetMode (OrigVioMode, 0);
- CheckCellHeight;
- {Set CursorX and CursorY}
- SetCursorPos (0, 0);
- VioSetState (OrigHighBit, 0);
- VioSetCurType (OrigCurType, 0);
- VioSetCurPos (OrigCurRow, OrigCurCol, 0);
- FreeMem (OldVideoBuf, VideoBufSize);
- OldVideoBuf := nil;
- VideoBufSize := 0;
- InitVideoCalled := false;
- if (OrigScreenSize <> 0) and (OrigScreen <> nil) then
- begin
- ScrSize := 0;
- if (VioGetBuf (PScr, PWord (@ScrSize)^, 0) = 0)
- and (ScrSize = OrigScreenSize) then
- begin
- {$IFDEF BIT_32}
- {$IFDEF PPC_VIRTUAL}
- SelToFlat (PScr);
- {$ELSE}
- PScr := SelToFlat (TFarPtr (PScr));
- {$ENDIF}
- {$ENDIF}
- Move (OrigScreen^, PScr^, OrigScreenSize);
- VioShowBuf (0, ScrSize, 0);
- end;
- end;
- end;
- end;
- function GetCapabilities: word;
- begin
- GetCapabilities := $3F;
- end;
- function DefaultVideoModeSelector (const VideoMode: TVideoMode; Params: longint): boolean;
- var OldMI, MI: TVioModeInfo;
- begin
- OldMI.cb := SizeOf (OldMI);
- if VioGetMode (OldMI, 0) <> 0 then
- DefaultVideoModeSelector := false
- else
- begin
- with MI do
- begin
- cb := 8;
- fbType := 1;
- if VideoMode.Color then
- Color := Colors_16
- else
- Color := Colors_2;
- Col := VideoMode.Col;
- Row := VideoMode.Row;
- end;
- if VioSetMode (MI, 0) = 0 then
- {$IFDEF PPC_VIRTUAL}
- if VioGetBuf (pointer (VideoBuf),
- PWord (@VideoBufSize)^, 0) = 0 then
- begin
- SelToFlat (pointer (VideoBuf));
- {$ELSE}
- if VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0) = 0 then
- begin
- {$IFDEF BIT_32}
- VideoBuf := SelToFlat (TFarPtr (VideoBuf));
- {$ENDIF}
- {$ENDIF}
- DefaultVideoModeSelector := true;
- SetHighBitBlink (true);
- CheckCellHeight;
- SetCursorType (LastCursorType);
- ClearScreen;
- end
- else
- begin
- DefaultVideoModeSelector := false;
- VioSetMode (OldMI, 0);
- {$IFDEF PPC_VIRTUAL}
- VioGetBuf (pointer (VideoBuf),
- PWord (@VideoBufSize)^, 0);
- SelToFlat (pointer (VideoBuf));
- {$ELSE}
- VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0);
- {$IFDEF BIT_32}
- VideoBuf := SelToFlat (TFarPtr (VideoBuf));
- {$ENDIF}
- {$ENDIF}
- SetHighBitBlink (true);
- CheckCellHeight;
- SetCursorType (LastCursorType);
- ClearScreen;
- end
- else
- begin
- DefaultVideoModeSelector := false;
- {$IFDEF PPC_VIRTUAL}
- VioGetBuf (pointer (VideoBuf), PWord (@VideoBufSize)^, 0);
- SelToFlat (pointer (VideoBuf));
- {$ELSE}
- VioGetBuf (VideoBuf, PWord (@VideoBufSize)^, 0);
- {$IFDEF BIT_32}
- VideoBuf := SelToFlat (TFarPtr (VideoBuf));
- {$ENDIF}
- {$ENDIF}
- SetHighBitBlink (true);
- SetCursorType (LastCursorType);
- end;
- end;
- end;
- procedure ClearScreen;
- begin
- VioScrollDn (0, 0, word (-1), word (-1), word (-1), PWord (@EmptyCell)^, 0);
- Move (VideoBuf^, OldVideoBuf^, VideoBufSize);
- end;
- {$IFDEF PPC_FPC}
- {$ASMMODE INTEL}
- {$ENDIF}
- procedure UpdateScreen (Force: boolean);
- {$IFDEF BIT_32}
- var SOfs, CLen: cardinal;
- {$ELSE}
- var SOfs, CLen: word;
- {$ENDIF}
- begin
- if LockUpdateScreen = 0 then
- begin
- if not (Force) then
- begin
- {$IFDEF BIT_32}
- asm
- cld
- mov esi, VideoBuf
- mov edi, OldVideoBuf
- mov eax, VideoBufSize
- mov ecx, eax
- shr ecx
- shr ecx
- repe
- cmpsd
- inc cx
- mov SOfs, ecx
- or ecx, ecx
- jz @no_update
- mov Force, 1
- std
- mov edi, eax
- mov esi, VideoBuf
- add eax, esi
- sub eax, 4
- mov esi, eax
- mov eax, OldVideoBuf
- add eax, edi
- sub eax, 4
- mov edi, eax
- repe
- cmpsd
- inc ecx
- shl ecx
- shl ecx
- mov CLen, ecx
- cld
- @no_update:
- end;
- SOfs := VideoBufSize - (SOfs shl 2);
- {$ELSE}
- asm
- cld
- push ds
- lds si, VideoBuf
- les di, OldVideoBuf
- mov ax, word ptr VideoBufSize
- mov cx, ax
- shr cx
- repe
- cmpsw
- inc cx
- mov SOfs, cx
- or cx, cx
- jz @no_update
- mov Force, 1
- std
- mov di, ax
- mov si, offset VideoBuf
- add ax, si
- dec ax
- dec ax
- mov si, ax
- mov ax, offset OldVideoBuf
- add ax, di
- dec ax
- dec ax
- mov di, ax
- repe
- cmpsw
- inc cx
- shl cx
- mov CLen, cx
- cld
- @no_update:
- pop ds
- end;
- Inc (SOfs);
- SOfs := VideoBufSize - (SOfs shl 1);
- {$ENDIF}
- end else
- begin
- SOfs := 0;
- CLen := VideoBufSize;
- end;
- if Force then
- begin
- VioShowBuf (SOfs, CLen, 0);
- Move (VideoBuf^ [SOfs div SizeOf (TVideoCell)],
- OldVideoBuf^ [SOfs div SizeOf (TVideoCell)], CLen);
- end;
- end;
- end;
- {
- $Log$
- Revision 1.11 2000-10-15 20:52:56 hajny
- * optimization of UpdateScreen finished
- Revision 1.10 2000/10/11 20:10:04 hajny
- * compatibility enhancements
- Revision 1.9 2000/10/11 05:28:29 hajny
- * really a faster version now ;-)
- Revision 1.8 2000/10/10 20:28:18 hajny
- * screen updates speeded up
- Revision 1.7 2000/10/08 18:40:58 hajny
- * SetCursorType corrected
- Revision 1.6 2000/10/08 14:13:19 hajny
- * ClearScreen correction, screen restored on exit
- Revision 1.5 2000/10/04 11:53:31 pierre
- Add TargetEntry and TargetExit (merged)
- Revision 1.4 2000/09/26 18:15:29 hajny
- + working with VP/2 already (not FPC yet)!
- Revision 1.3 2000/09/24 19:53:03 hajny
- * OS/2 implementation almost finished, not debugged yet
- Revision 1.2 2000/07/13 11:32:26 michael
- + removed logs
- }
|