Subsections

24 The VIDEO unit

videoex

The Video unit implements a screen access layer which is system independent. It can be used to write on the screen in a system-independent way, which should be optimal on all platforms for which the unit is implemented.

The working of the Video is simple: After calling InitVideo, the array VideoBuf contains a representation of the video screen of size ScreenWidth*ScreenHeight, going from left to right and top to bottom when walking the array elements: VideoBuf[0] contains the character and color code of the top-left character on the screen. VideoBuf[ScreenWidth] contains the data for the character in the first column of the second row on the screen, and so on.

To write to the 'screen', the text to be written should be written to the VideoBuf array. Calling UpdateScreen will then cp the text to the screen in the most optimal way. (an example can be found further on).

The color attribute is a combination of the foreground and background color, plus the blink bit. The bits describe the various color combinations:

bits 0-3
The foreground color. Can be set using all color constants.
bits 4-6
The background color. Can be set using a subset of the color constants.
bit 7
The blinking bit. If this bit is set, the character will appear blinking.
Each possible color has a constant associated with it, see page [*] for a list of constants.

The contents of the VideoBuf array may be modified: This is 'writing' to the screen. As soon as everything that needs to be written in the array is in the VideoBuf array, calling UpdateScreen will copy the contents of the array screen to the screen, in a manner that is as efficient as possible.

The updating of the screen can be prohibited to optimize performance; To this end, the LockScreenUpdate function can be used: This will increment an internal counter. As long as the counter differs from zero, calling UpdateScreen will not do anything. The counter can be lowered with UnlockScreenUpdate. When it reaches zero, the next call to UpdateScreen will actually update the screen. This is useful when having nested procedures that do a lot of screen writing.

The video unit also presents an interface for custom screen drivers, thus it is possible to override the default screen driver with a custom screen driver, see the SetVideoDriver call. The current video driver can be retrieved using the GetVideoDriver call.

Remark: The video unit should not be used together with the crt unit. Doing so will result in very strange behaviour, possibly program crashes.

1 Constants, Type and variables


1 Constants

The following constants describe colors that can be used as foreground and background colors.
Black         = 0;
Blue          = 1;
Green         = 2;
Cyan          = 3;
Red           = 4;
Magenta       = 5;
Brown         = 6;
LightGray     = 7;
The following color constants can be used as foreground colors only:
DarkGray      = 8;
LightBlue     = 9;
LightGreen    = 10;
LightCyan     = 11;
LightRed      = 12;
LightMagenta  = 13;
Yellow        = 14;
White         = 15;
The foreground and background color can be combined to a color attribute with the following code:
Attr:=ForeGroundColor + (BackGroundColor shl 4);
The color attribute can be logically or-ed with the blink attribute to produce a blinking character:
Blink         = 128;
But not all drivers may support this.

The following constants describe the capabilities of a certain video mode:

cpUnderLine     = $0001;
cpBlink         = $0002;
cpColor         = $0004;
cpChangeFont    = $0008;
cpChangeMode    = $0010;
cpChangeCursor  = $0020;
The following constants describe the various supported cursor modes:
crHidden        = 0;
crUnderLine     = 1;
crBlock         = 2;
crHalfBlock     = 3;
When a video function needs to report an error condition, the following constants are used:
vioOK              = 0;
errVioBase         = 1000;
errVioInit         = errVioBase + 1; { Initialization error}
errVioNotSupported = errVioBase + 2; { Unsupported function }
errVioNoSuchMode   = errVioBase + 3; { No such video mode }
The following constants can be read to get some information about the current screen:
ScreenWidth     : Word = 0;  { Width of the screen, in characters  }
ScreenHeight    : Word = 0;  { Height of the screen, in characters }
LowAscii        : Boolean = true;
NoExtendedFrame : Boolean = false;
FVMaxWidth      = 132;
The error-handling code uses the following constants:
errOk              = 0;
ErrorCode: Longint = ErrOK;
ErrorInfo: Pointer = nil;
ErrorHandler: TErrorHandler = DefaultErrorHandler;
The ErrorHandler variable can be set to a custom-error handling function. It is set by default to the DefaultErrorHandler function.

2 Types

The TVideoMode record describes a videomode. Its fields are self-explaining: Col,Row describe the number of columns and rows on the screen for this mode. Color is True if this mode supports colors, or False if not.
  PVideoMode = ^TVideoMode;
  TVideoMode = record
    Col,Row : Word;
    Color   : Boolean;
  end;
TVideoCell describes one character on the screen. One of the bytes contains the color attribute with which the character is drawn on the screen, and the other byte contains the ASCII code of the character to be drawn. The exact position of the different bytes in the record is operating system specific. On most little-endian systems, the high byte represents the color attribute, while the low-byte represents the ASCII code of the character to be drawn.
TVideoCell = Word;
PVideoCell = ^TVideoCell;
The TVideoBuf and PVideoBuf are two types used to represent the screen.
TVideoBuf = array[0..32759] of TVideoCell;
PVideoBuf = ^TVideoBuf;
The following type is used when reporting error conditions:
TErrorHandlerReturnValue = (errRetry, errAbort, errContinue);
Here, errRetry means retry the operation, errAbort abort and return error code and errContinue means abort without returning an errorcode.

The TErrorHandler function is used to register an own error handling function. It should be used when installing a custom error handling function, and must return one of the above values.

TErrorHandler = 
  function (Code: Longint; Info: Pointer): TErrorHandlerReturnValue;
Code should contain the error code for the error condition, and the Info parameter may contain any data type specific to the error code passed to the function.

The TVideoDriver record can be used to install a custom video driver, with the SetVideoDriver call:

TVideoDriver = Record
  InitDriver        : Procedure;
  DoneDriver        : Procedure;
  UpdateScreen      : Procedure(Force : Boolean);
  ClearScreen       : Procedure;
  SetVideoMode      : Function (Const Mode : TVideoMode) : Boolean;
  GetVideoModeCount : Function : Word;
  GetVideoModeData  : Function(Index : Word; Var Data : TVideoMode) : Boolean;
  SetCursorPos      : procedure (NewCursorX, NewCursorY: Word);
  GetCursorType     : function : Word;
  SetCursorType     : procedure (NewType: Word);
  GetCapabilities   : Function : Word;
end;

3 Variables

The following variables contain information about the current screen status:
ScreenColor      : Boolean;
CursorX, CursorY : Word;
ScreenColor indicates whether the current screen supports colors. CursorX,CursorY contain the current cursor position.

The following variable forms the heart of the Video unit: The VideoBuf array represents the physical screen. Writing to this array and calling UpdateScreen will write the actual characters to the screen.

VideoBuf     : PVideoBuf;
OldVideoBuf  : PVideoBuf;
VideoBufSize : Longint;
The OldVideoBuf contains the state of the video screen after the last screen update. The UpdateScreen function uses this array to decide which characters on screen should be updated, and which not.

Note that the OldVideoBuf array may be ignored by some drivers, so it should not be used. The Array is in the interface section of the video unit mainly so drivers that need it can make use of it.

2 Functions and Procedures

The examples in this section make use of the unit vidutil, which contains the TextOut function. This function writes a text to the screen at a given location. It looks as follows:

Example
unit vidutil;

Interface

uses
  video;

{$ifndef cpu86}
{$error This example only works on intel 80x86 machines}
{$endif}
  

Procedure TextOut(X,Y : Word;Const S : String);

Implementation
  
Procedure TextOut(X,Y : Word;Const S : String);

Var
  W,P,I,M : Word;

begin
  P:=((X-1)+(Y-1)*ScreenWidth);
  M:=Length(S);
  If P+M>ScreenWidth*ScreenHeight then
    M:=ScreenWidth*ScreenHeight-P;
  For I:=1 to M do
    VideoBuf^[P+I-1]:=Ord(S[i])+($07 shl 8);
end;
  
end.


1 ClearScreen

Declaration
procedure ClearScreen;
Description
ClearScreen clears the entire screen, and calls UpdateScreen after that. This is done by writing spaces to all character cells of the video buffer in the default color (lightgray on black, color attribute $07).
Errors
None.
See also
InitVideo, UpdateScreen

Example
program testvideo;

uses video,keyboard,vidutil;

{$ifndef cpu86}
{$error This example only works on intel 80x86 machines}
{$endif}

Var 
  i : longint;
  k : TkeyEvent;
  
begin
  InitVideo;
  InitKeyboard;
  For I:=1 to 10 do
    TextOut(i,i, 'Press any key to clear screen');
  UpdateScreen(false);
  K:=GetKeyEvent;
  ClearScreen;
  TextOut(1,1,'Cleared screen. Press any key to end');  
  UpdateScreen(true);
  K:=GetKeyEvent;
  DoneKeyBoard;
  DoneVideo;
end.


2 DefaultErrorHandler

Declaration
function DefaultErrorHandler(AErrorCode: Longint; AErrorInfo: Pointer): TErrorHandlerReturnValue;
Description
DefaultErrorHandler is the default error handler used by the video driver. It simply sets the error code AErrorCode and AErrorInfo in the global variables ErrorCode and ErrorInfo and returns errContinue.
Errors
None.
See also


3 DoneVideo

Declaration
procedure DoneVideo;
Description
DoneVideo disables the Video driver if the video driver is active. If the videodriver was already disabled or not yet initialized, it does nothing. Disabling the driver means it will clean up any allocated resources, possibly restore the screen in the state it was before InitVideo was called. Particularly, the VideoBuf and OldVideoBuf arrays are no longer valid after a call to DoneVideo.

The DoneVideo should always be called if InitVideo was called. Failing to do so may leave the screen in an unusable state after the program exits.

Errors
Normally none. If the driver reports an error, this is done through the ErrorCode variable.
See also
InitVideo

For an example, see most other functions.


4 GetCapabilities

Declaration
function GetCapabilities: Word;
Description
GetCapabilities returns the capabilities of the current driver. It is an or-ed combination of the following constants:
cpUnderLine
The driver supports underlined characters.
cpBlink
The driver supports blinking characters.
cpColor
The driver supports colors.
cpChangeFont
The driver supports the setting of a screen font. Note, however, that a font setting API is not supported by the video unit.
cpChangeMode
The driver supports the setting of screen modes.
cpChangeCursor
The driver supports changing the cursor shape.
Note that the video driver should not yet be initialized to use this function. It is a property of the driver.
Errors
None.
See also
GetCursorType, GetVideoDriver

Example
Program Example4;

{ Program to demonstrate the GetCapabilities function. }

Uses video;

Var
  W: Word;

  Procedure TestCap(Cap: Word; Msg : String);
  
  begin
    Write(Msg,' : ');
    If (W and Cap=Cap) then
      Writeln('Yes')
    else
      Writeln('No');
  end;

begin
  W:=GetCapabilities;
  Writeln('Video driver supports following functionality');
  TestCap(cpUnderLine,'Underlined characters');
  TestCap(cpBlink,'Blinking characters');
  TestCap(cpColor,'Color characters');
  TestCap(cpChangeFont,'Changing font');
  TestCap(cpChangeMode,'Changing video mode');
  TestCap(cpChangeCursor,'Changing cursor shape');
end.


5 GetCursorType

Declaration
function GetCursorType: Word;
Description
GetCursorType returns the current cursor type. It is one of the following values:
crHidden
The cursor is currently hidden.
crUnderLine
The cursor is currently the underline character.
crBlock
The cursor is currently the block character.
crHalfBlock
The cursur is currently a block with height of half the character cell height.
Note that not all drivers support all types of cursors.
Errors
None.
See also
SetCursorType, GetCapabilities

Example
Program Example5;

{ Program to demonstrate the GetCursorType function. }

Uses video,keyboard,vidutil;

Const
  Cursortypes : Array[crHidden..crHalfBlock] of string = 
    ('Hidden','UnderLine','Block','HalfBlock');

begin
  InitVideo;
  InitKeyboard;
  TextOut(1,1,'Cursor type: '+CursorTypes[GetCursorType]);
  TextOut(1,2,'Press any key to exit.');
  UpdateScreen(False);
  GetKeyEvent;
  DoneKeyboard;
  DoneVideo;
end.


6 GetLockScreenCount

Declaration
Function GetLockScreenCount : integer;
Description
GetLockScreenCount returns the current lock level. When the lock level is zero, a call to UpdateScreen will actually update the screen.
Errors
None.
See also
LockScreenUpdate, UnlockScreenUpdate, UpdateScreen

Example
Program Example6;

{ Program to demonstrate the GetLockScreenCount function. }

Uses video,keyboard,vidutil;

Var
  I : Longint;
  S : String;
  
begin
  InitVideo;
  InitKeyboard;
  TextOut(1,1,'Press key till new text appears.');
  UpdateScreen(False);
  Randomize;
  For I:=0 to Random(10)+1 do
    LockScreenUpdate;
  I:=0;  
  While GetLockScreenCount<>0 do
    begin
    Inc(I);
    Str(I,S);
    UnlockScreenUpdate;
    GetKeyEvent;
    TextOut(1,1,'UnLockScreenUpdate had to be called '+S+' times');
    UpdateScreen(False);
    end;
  TextOut(1,2,'Press any key to end.');
  UpdateScreen(False);
  GetKeyEvent;
  DoneKeyboard;
  DoneVideo;
end.


7 GetVideoDriver

Declaration
Procedure GetVideoDriver (Var Driver : TVideoDriver);
Declaration
GetVideoDriver retrieves the current videodriver and returns it in Driver. This can be used to chain video drivers.
Errors
None.
See also
SetVideoDriver

For an example, see the section on writing a custom video driver.


8 GetVideoMode

Declaration
procedure GetVideoMode(var Mode: TVideoMode);
Description
GetVideoMode returns the settings of the currently active video mode. The row,col fields indicate the dimensions of the current video mode, and Color is true if the current video supports colors.
Errors
None.
See also
SetVideoMode, GetVideoModeData

Example
Program Example7;

{ Program to demonstrate the GetVideoMode function. }

Uses video,keyboard,vidutil;

Var 
  M : TVideoMode;
  S : String;
  
begin
  InitVideo;
  InitKeyboard;
  GetVideoMode(M);
  if M.Color then 
    TextOut(1,1,'Current mode has color')
  else  
    TextOut(1,1,'Current mode does not have color');
  Str(M.Row,S);  
  TextOut(1,2,'Number of rows    : '+S);
  Str(M.Col,S);  
  TextOut(1,3,'Number of columns : '+S);
  Textout(1,4,'Press any key to exit.');
  UpdateScreen(False);   
  GetKeyEvent;
  DoneKeyboard;
  DoneVideo;
end.


9 GetVideoModeCount

Declaration
Function GetVideoModeCount : Word;
Description
GetVideoModeCount returns the number of video modes that the current driver supports. If the driver does not support switching of modes, then 1 is returned.

This function can be used in conjunction with the GetVideoModeData function to retrieve data for the supported video modes.

Errors
None.
See also
GetVideoModeData, GetVideoMode

Example
Program Example8;

{ Program to demonstrate the GetVideoModeCount function. }

Uses video,keyboard,vidutil;

Procedure DumpMode (M : TVideoMode; Index : Integer);

Var
 S : String;

begin
  Str(Index:2,S);
  inc(Index);
  TextOut(1,Index,'Data for mode '+S+': ');
  if M.Color then 
    TextOut(19,Index,'   color,')
  else  
    TextOut(19,Index,'No color,');
  Str(M.Row:3,S);  
  TextOut(28,Index,S+' rows');
  Str(M.Col:3,S);  
  TextOut(36,index,S+' columns');
end;

Var 
  i,Count : Integer;
  m : TVideoMode;
  
begin
  InitVideo;
  InitKeyboard;
  Count:=GetVideoModeCount;
  For I:=1 to Count do
    begin
    GetVideoModeData(I-1,M);
    DumpMode(M,I-1);
    end;
  TextOut(1,Count+1,'Press any key to exit');  
  UpdateScreen(False);
  GetKeyEvent;
  DoneKeyboard;
  DoneVideo;
end.


10 GetVideoModeData

Declaration
Function GetVideoModeData(Index : Word; Var Data: TVideoMode) : Boolean;
Description
GetVideoModeData returns the characteristics of the Index-th video mode in Data. Index is zero based, and has a maximum value of GetVideoModeCount-1. If the current driver does not support setting of modes (GetVideoModeCount=1) and Index is zero, the current mode is returned.

The function returns True if the mode data was retrieved succesfully, False otherwise.

Errors
In case Index has a wrong value, False is returned.
See also
GetVideoModeCount, SetVideoMode, GetVideoMode

For an example, see GetVideoModeCount.


11 InitVideo

Declaration
procedure InitVideo;
Description
InitVideo Initializes the video subsystem. If the video system was already initialized, it does nothing. After the driver has been initialized, the VideoBuf and OldVideoBuf pointers are initialized, based on the ScreenWidth and ScreenHeight variables. When this is done, the screen is cleared.
Errors
if the driver fails to initialize, the ErrorCode variable is set.
See also
DoneVideo

For an example, see most other functions.


12 LockScreenUpdate

Declaration
Procedure LockScreenUpdate;
Description
LockScreenUpdate increments the screen update lock count with one. As long as the screen update lock count is not zero, UpdateScreen will not actually update the screen.

This function can be used to optimize screen updating: If a lot of writing on the screen needs to be done (by possibly unknown functions), calling LockScreenUpdate before the drawing, and UnlockScreenUpdate after the drawing, followed by a UpdateScreen call, all writing will be shown on screen at once.

Errors
None.
See also
UpdateScreen, UnlockScreenUpdate, GetLockScreenCount

For an example, see GetLockScreenCount.


13 SetCursorPos

Declaration
procedure SetCursorPos(NewCursorX, NewCursorY: Word);
Description
SetCursorPos positions the cursor on the given position: Column NewCursorX and row NewCursorY. The origin of the screen is the upper left corner, and has coordinates (0,0).

The current position is stored in the CursorX and CursorY variables.

Errors
None.
See also
SetCursorType

Example
program example2;

uses video,keyboard;

{$ifndef cpu86}
{$error This example only works on intel 80x86 machines}
{$endif}

Var
  P,PP,D : Integer;
  K: TKeyEvent;
  
  Procedure PutSquare (P : INteger; C : Char);
  
  begin
    VideoBuf^[P]:=Ord(C)+($07 shl 8);
    VideoBuf^[P+ScreenWidth]:=Ord(c)+($07 shl 8);
    VideoBuf^[P+1]:=Ord(c)+($07 shl 8);
    VideoBuf^[P+ScreenWidth+1]:=Ord(c)+($07 shl 8);
  end;

begin
  InitVideo;
  InitKeyBoard;
  P:=0;
  PP:=-1;
  Repeat
    If PP<>-1 then
      PutSquare(PP,' ');
    PutSquare(P,'#');
    SetCursorPos(P Mod ScreenWidth,P div ScreenWidth);
    UpdateScreen(False);
    PP:=P;  
    Repeat
      D:=0;
      K:=TranslateKeyEvent(GetKeyEvent);
      Case GetKeyEventCode(K) of
        kbdLeft : If (P Mod ScreenWidth)<>0 then 
                   D:=-1;
        kbdUp : If P>=ScreenWidth then
                 D:=-ScreenWidth;
        kbdRight : If ((P+2) Mod ScreenWidth)<>0 then
                   D:=1;
        kbdDown : if (P<(VideoBufSize div 2)-(ScreenWidth*2)) then
                   D:=ScreenWidth;
      end;             
    Until (D<>0) or (GetKeyEventChar(K)='q');
    P:=P+D;
  until GetKeyEventChar(K)='q';
  DoneKeyBoard;
  DoneVideo;
end.


14 SetCursorType

Declaration
procedure SetCursorType(NewType: Word);
Description
SetCursorType sets the cursor to the type specified in NewType.
crHidden
the cursor is not visible.
crUnderLine
the cursor is a small underline character (usually denoting insert mode).
crBlock
the cursor is a block the size of a screen cell (usually denoting overwrite mode).
crHalfBlock
the cursor is a block half the size of a screen cell.
Errors
None.
See also
SetCursorPos


15 SetVideoDriver

Declaration
Function SetVideoDriver (Const Driver : TVideoDriver) : Boolean;
Description
SetVideoDriver sets the videodriver to be used to Driver. If the current videodriver is initialized (after a call to InitVideo) then it does nothing and returns False.

A new driver can only be installed if the previous driver was not yet activated (i.e. before a call to InitVideo) or after it was deactivated (i.e after a call to DoneVideo).

For more information about installing a videodriver, see section viddriver.

Errors
If the current driver is initialized, then False is returned.
See also
The example video driver in section viddriver

For an example, see the section on writing a custom video driver.


16 SetVideoMode

Declaration
Function SetVideoMode(Mode: TVideoMode) : Boolean;
Description
SetVideoMode sets the video mode to the mode specified in Mode:
  TVideoMode = record
    Col,Row : Word;
    Color   : Boolean;
  end;
If the call was succesful, then the screen will have Col columns and Row rows, and will be displaying in color if Color is True.

The function returns True if the mode was set succesfully, False otherwise.

Note that the video mode may not always be set. E.g. a console on Linux or a telnet session cannot always set the mode. It is important to check the error value returned by this function if it was not succesful.

The mode can be set when the video driver has not yet been initialized (i.e. before InitVideo was called) In that case, the video mode will be stored, and after the driver was initialized, an attempt will be made to set the requested mode. Changing the video driver before the call to InitVideo will clear the stored video mode.

To know which modes are valid, use the GetVideoModeCount and GetVideoModeData functions. To retrieve the current video mode, use the GetVideoMode procedure.

Errors
If the specified mode cannot be set, then errVioNoSuchMode may be set in ErrorCode
See also
GetVideoModeCount GetVideoModeData GetVideoMode


17 UnlockScreenUpdate

Declaration
Procedure UnlockScreenUpdate;
Description
UnlockScreenUpdate decrements the screen update lock count with one if it is larger than zero. When the lock count reaches zero, the UpdateScreen will actually update the screen. No screen update will be performed as long as the screen update lock count is nonzero. This mechanism can be used to increase screen performance in case a lot of writing is done.

It is important to make sure that each call to LockScreenUpdate is matched by exactly one call to UnlockScreenUpdate

Errors
None.
See also
LockScreenUpdate, GetLockScreenCount, UpdateScreen

For an example, see GetLockScreenCount.


18 UpdateScreen

Declaration
procedure UpdateScreen(Force: Boolean);
Description
UpdateScreen synchronizes the actual screen with the contents of the VideoBuf internal buffer. The parameter Force specifies whether the whole screen has to be redrawn (Force=True) or only parts that have changed since the last update of the screen.

The Video unit keeps an internal copy of the screen as it last wrote it to the screen (in the OldVideoBuf array). The current contents of VideoBuf are examined to see what locations on the screen need to be updated. On slow terminals (e.g. a LINUX telnet session) this mechanism can speed up the screen redraw considerably.

Errors
None.
See also
ClearScreen

For an example, see most other functions.


3 Writing a custom video driver

Writing a custom video driver is not difficult, and generally means implementing a couple of functions, which whould be registered with the SetVideoDriver function. The various functions that can be implemented are located in the TVideoDriver record:
TVideoDriver = Record
  InitDriver        : Procedure;
  DoneDriver        : Procedure;
  UpdateScreen      : Procedure(Force : Boolean);
  ClearScreen       : Procedure;
  SetVideoMode      : Function (Const Mode : TVideoMode) : Boolean;
  GetVideoModeCount : Function : Word;
  GetVideoModeData  : Function(Index : Word; Var Data : TVideoMode) : Boolean;
  SetCursorPos      : procedure (NewCursorX, NewCursorY: Word);
  GetCursorType     : function : Word;
  SetCursorType     : procedure (NewType: Word);
  GetCapabilities   : Function : Word;
end;
Not all of these functions must be implemented. In fact, the only absolutely necessary function to write a functioning driver is the UpdateScreen function. The general calls in the Video unit will check which functionality is implemented by the driver.

The functionality of these calls is the same as the functionality of the calls in the video unit, so the expected behaviour can be found in the previous section. Some of the calls, however, need some additional remarks.

InitDriver
Called by InitVideo, this function should initialize any data structures needed for the functionality of the driver, maybe do some screen initializations. The function is guaranteed to be called only once; It can only be called again after a call to DoneVideo. The variables ScreenWidth and ScreenHeight should be initialized correctly after a call to this function, as the InitVideo call will initialize the VideoBuf and OldVideoBuf arrays based on their values.
DoneDriver
This should clean up any structures that have been initialized in the InitDriver function. It should possibly also restore the screen as it was before the driver was initialized. The VideoBuf and OldVideoBuf arrays will be disposed of by the general DoneVideo call.
UpdateScreen
This is the only required function of the driver. It should update the screen based on the VideoBuf array's contents. It can optimize this process by comparing the values with values in the OldVideoBuf array. After updating the screen, the UpdateScreen procedure should update the OldVideoBuf by itself. If the Force parameter is True, the whole screen should be updated, not just the changed values.
ClearScreen
If there is a faster way to clear the screen than to write spaces in all character cells, then it can be implemented here. If the driver does not implement this function, then the general routines will write spaces in all video cells, and will call UpdateScreen(True).
SetVideoMode
Should set the desired video mode, if available. It should return True if the mode was set, False if not.
GetVideoModeCount
Should return the number of supported video modes. If no modes are supported, this function should not be implemented; the general routines will return 1. (for the current mode)
GetVideoModeData
Should return the data for the Index-th mode; Index is zero based. The function should return true if the data was returned correctly, false if Index contains an invalid index. If this is not implemented, then the general routine will return the current video mode when Index equals 0.
GetCapabilities
If this function is not implemented, zero (i.e. no capabilities) will be returned by the general function.

The following unit shows how to override a video driver, with a driver that writes debug information to a file.

Example
unit viddbg;

Interface

uses video;


Procedure StartVideoLogging;
Procedure StopVideoLogging;
Function  IsVideoLogging : Boolean;
Procedure  SetVideoLogFileName(FileName : String);

Const
  DetailedVideoLogging : Boolean = False;

Implementation

uses sysutils,keyboard;

var
  NewVideoDriver,
  OldVideoDriver : TVideoDriver;
  Active,Logging : Boolean;
  LogFileName : String;
  VideoLog : Text;

Function TimeStamp : String;

begin
  TimeStamp:=FormatDateTime('hh:nn:ss',Time());
end;
  
Procedure StartVideoLogging;

begin
  Logging:=True;
  Writeln(VideoLog,'Start logging video operations at: ',TimeStamp);
end;

Procedure StopVideoLogging;

begin
  Writeln(VideoLog,'Stop logging video operations at: ',TimeStamp);
  Logging:=False;
end;

Function IsVideoLogging : Boolean;

begin
  IsVideoLogging:=Logging;
end;

Var
  ColUpd,RowUpd : Array[0..1024] of Integer;

Procedure DumpScreenStatistics(Force : Boolean);

Var
  I,Count : Integer;

begin
  If Force then
    Write(VideoLog,'forced ');
  Writeln(VideoLog,'video update at ',TimeStamp,' : ');
  FillChar(Colupd,SizeOf(ColUpd),#0);
  FillChar(Rowupd,SizeOf(RowUpd),#0);
  Count:=0;
  For I:=0 to VideoBufSize div SizeOf(TVideoCell) do
    begin
    If VideoBuf^[i]<>OldVideoBuf^[i] then
      begin 
      Inc(Count);
      Inc(ColUpd[I mod ScreenWidth]);
      Inc(RowUpd[I div ScreenHeight]);
      end;
    end;
  Write(VideoLog,Count,' videocells differed divided over ');
  Count:=0;
  For I:=0 to ScreenWidth-1 do 
    If ColUpd[I]<>0 then 
      Inc(Count);
  Write(VideoLog,Count,' columns and ');
  Count:=0;
  For I:=0 to ScreenHeight-1 do 
    If RowUpd[I]<>0 then 
      Inc(Count);
  Writeln(VideoLog,Count,' rows.');
  If DetailedVideoLogging Then
   begin
   For I:=0 to ScreenWidth-1 do
     If (ColUpd[I]<>0) then
       Writeln(VideoLog,'Col ',i,' : ',ColUpd[I]:3,' rows changed');
   For I:=0 to ScreenHeight-1 do
     If (RowUpd[I]<>0) then
       Writeln(VideoLog,'Row ',i,' : ',RowUpd[I]:3,' colums changed');
   end;      
end;

Procedure LogUpdateScreen(Force : Boolean);

begin
  If Logging then
    DumpScreenStatistics(Force);
  OldVideoDriver.UpdateScreen(Force);
end;

Procedure LogInitVideo;

begin
  OldVideoDriver.InitDriver();
  Assign(VideoLog,logFileName);
  Rewrite(VideoLog);
  Active:=True;
  StartVideoLogging;
end;

Procedure LogDoneVideo;

begin
  StopVideoLogging;
  Close(VideoLog);
  Active:=False;
  OldVideoDriver.DoneDriver();
end;

Procedure SetVideoLogFileName(FileName : String);

begin
  If Not Active then
    LogFileName:=FileName;
end;

Initialization
  GetVideoDriver(OldVideoDriver);
  NewVideoDriver:=OldVideoDriver;
  NewVideoDriver.UpdateScreen:=@LogUpdateScreen;
  NewVideoDriver.InitDriver:=@LogInitVideo;
  NewVideoDriver.DoneDriver:=@LogDoneVideo;
  LogFileName:='Video.log';
  Logging:=False;
  SetVideoDriver(NewVideoDriver);
end.

The unit can be used in any of the demonstration programs, by simply including it in the uses clause. Setting DetailedVideoLogging to True will create a more detailed log (but will also slow down functioning)



2004-02-13