unit Datasrc;{generic data source interface, used e.g. for printing
  with prndata.pas}

interface
const
  NoDataSrc = nil;
{daXXXX datasrc actions}
  daStartPage = 1;
  daFinishPage = 2;
  daSetPaperMargins = 3;
  daDoRecord = 4;

  daResetSource = 10;
  daSkip = 11;
  daPrintRecord = 13;    {preceded by call GetInit(dpRecordLineCount)}
{/daXXXX}

{dpXXXX datasrc properties}
  dpRecordCount = 1;
  dpRecordLineCount = 2; {counts lines needed if the current
                          record would be printed}

{/dpXXXX}

type
  PDataShower = pointer;
  PData = pointer;

  TDataSrcProperty = integer;

  TDataSrcOpen = function(AData:PData; ADataShower:PDataShower):boolean;
  TDataSrcDoAction = function(AData:PData; da:TDataSrcAction; ADataShower:PDataShower):boolean;
  TDataSrcGetInt = function(AData:PData; dp:TDataSrcProperty):longint;
  TDataSrcSetInt = function(AData:PData; dp:TDataSrcProperty; AValue:longint):boolean;
  TDataSrcClose = procedure(AData:PData);

  TDataSrcInfo = record
    Open:TDataSrcOpen;
    DoAction:TDataSrcDoAction;
    GetInt:TDataSrcGetInt;
    SetInt:TDataSrcSetInt;
    Close:TDataSrcClose;
    DataShower:PDataShower;
    Data:PData;
  end;

  PDataSrc = ^TDataSrcInfo;

function DataSrcInit(
  const ADataSrcRecord:TDataSrcInfo;
  AData:PData;
  ADataShower:PDataShower;
  var ADataSrc:PDataSrc):boolean;{$IFDEF PMODE}export;{$ENDIF}
function DataSrcDoAction(ADataSrc:PDataSrc; da:TDataSrcAction):boolean;
  {$IFDEF PMODE}export;{$ENDIF}
function DataSrcGetInt(ADataSrc:PDataSrc; dp:TDataSrcProperty):longint;
  {$IFDEF PMODE}export;{$ENDIF}
function DataSrcSetInt(ADataSrc:PDataSrc; dp:TDataSrcProperty; AValue:longint):boolean;
  {$IFDEF PMODE}export;{$ENDIF}
function DataSrcDone(var ADataSrc:PDataSrc):boolean;
  {$IFDEF PMODE}export;{$ENDIF}

implementation
uses mytype, msgu;

function IsValidDataSrc(ADataSrc:PDataSrc):boolean;
begin
  IsValidDataSrc := false;
  if ADataSrc = nil then begin
    SysError('DataSrc.InvalidDataSrc');
    exit;
  end;
  IsValidDataSrc := true;
end;

function DataSrcInit(const ADataSrcRecord:TDataSrcRecord;
  AData:PData;
  ADataShower:PDataShower;
  var ADataSrc:PDataSrc):boolean;
begin
  DataSrcInit := false;
  ADataSrc := New(PDataSrc);
  if ADataSrc = nil then
    exit;
  if not Assigned(ADataSrcRecord.) then begin
    SysError('DataSrc.Reset not assigned.');
    exit;
  end;
  if not Assigned(ADataSrcRecord.Skip) then begin
    SysError('DataSrc.Skip not assigned.');
    exit;
  end;
  if not Assigned(ADataSrcRecord.DoRecord) then begin
    SysError('DataSrc.DoRecord not assigned.');
    exit;
  end;

  ADataSrc^ := ADataSrcRecord;
  ADataSrc^.Data := AData;
  ADataSrc^.DataShower := ADataShower;
end;

function DataSrcDoAction(ADataSrc:PDataSrc; da:TDataSrcAction):boolean;
begin
  DataSrcDoAction := false;
  if not IsValidDataSrc(ADataSrc) then
    exit;
  DataSrcReset := ADataSrc^.DoAction(ADataSrc^.Data, da, ADataSrc^.DataShower);
end;

function DataSrcGetInt(ADataSrc:PDataSrc; dp:TDataSrcProperty):longint;
begin
  DataSrcGetInt := false;
  if not IsValidDataSrc(ADataSrc) then
    exit;
  DataSrcGetInt := ADataSrc^.GetInt(ADataSrc^.Data, dp);
end;

function DataSrcSetInt(ADataSrc:PDataSrc; dp:TDataSrcProperty; AValue:longint):boolean;
begin
  DataSrcSetInt := false;
  if not IsValidDataSrc(ADataSrc) then
    exit;
  DataSrcSetInt := ADataSrc^.SetInt(ADataSrc^.Data, dp, AValue);
end;

function DataSrcDone(var ADataSrc:PDataSrc):boolean;
begin
  DataSrcDone := false;
  if not IsValidDataSrc(ADataSrc) then
    exit;
  Dispose(ADataSrc);
  ADataSrc := nil;
  DataSrcDone := true;
end;

end.
