Contributor: SWAG SUPPORT TEAM        

unit dbaseiii;
{ unit including procedures for accessing DBaseIII files}

interface

uses Crt;

Procedure OpenDBFData;
Procedure OpenDBFMemo;
Procedure ReadDBFRecord(I : Longint);
Procedure WriteDBFRecord;
Procedure ReadDBFMemo(BlockNumber : integer);
Procedure WriteDBFMemo(var BlockNumberString : string);
Procedure CloseDBFData;
Procedure CloseDBFMemo;

const
        DBFMaxRecordLength = 4096;
        DBFMemoBlockLength =  512;
        DBFMaxMemoLength   = 4096;

type
        DBFHeaderRec = Record
                HeadType                : byte;
                Year                        : byte;
                Month                        : byte;
                Day                                : byte;
                RecordCount                : longint;
                HeaderLength        : integer;
                RecordSize          : integer;
                Garbage                         : array[1..20] of byte;
        end;

type
        DBFFieldRec = Record
                FieldName                : array[1..11] of char;
                FieldType                : char;
                Spare1,
                Spare2                        : integer;
                Width                        : byte;
                Dec                                : byte;
                WorkSpace                : array[1..14] of byte;
        end;

var
        DBFFileName                         : string;

        DBFDataFile                                : File;
        DBFDataFileAvailable        : boolean;
        DBFBuffer                                : array [1..DBFMaxRecordLength] of char;

        DBFHeading                                : DBFHeaderRec;

        DBFField                                : DBFFieldRec;
        DBFFieldCount                        : integer;
        DBFFieldContent                        : array [1..128] of string;

        DBFNames                                : array [1..128] of string[10];
        DBFLengths                                : array [1..128] of byte;
        DBFTypes                                : array [1..128] of char;
        DBFDecimals                                : array [1..128] of byte;
        DBFContentStart                        : array [1..128] of integer;

        DBFMemoFile                                : File;
        DBFMemoFileAvailable        : boolean;
        DBFMemoBuffer                        : Array [1..DBFMemoBlockLength] of byte;
        DBFMemo                                        : Array [1..DBFMaxMemoLength] of char;

        DBFMemoLength                        : integer;
        DBFMemoEnd                                : boolean;
        DBFMemoBlock                        : integer;

        DBFDeleteField                        : char;
        DBFFieldStart                        : integer;

        DBFRecordNumber                        : longint;

(****************************************************************)

implementation

(****************************************************************)

Procedure ReadDBFHeader;

var
        RecordsRead : integer;

begin
        BlockRead (DBFDataFile, DBFHeading, SizeOf(DBFHeading), RecordsRead);
end;

(*****************************************************************)

Procedure ProcessField (F : DBFFieldRec;
                                                I : integer);
var
        J : integer;

begin
        with F do
        begin
                DBFNames [I] := '';
                J := 1;
                while (J<11) and (FieldName[J] <> #0) do
                        begin
                                DBFNames[I] := DBFNames[I] + FieldName [J];
                                J := J + 1;
                        end;
                DBFLengths [I]                 := Width;
                DBFTypes [I]                 := FieldType;
                DBFDecimals [I]         := Dec;
                DBFContentStart [I] := DBFFieldStart;
                DBFFieldStart                 := DBFFieldStart + Width;
        end;
end;

(***************************************************************)

Procedure ReadFields;

var
        I                         : integer;
        RecordsRead : integer;

begin
        Seek(DBFDataFile,32);
        I := 1;
        DBFFieldStart := 2;
        DBFField.FieldName[1] := ' ';
        while (DBFField.FieldName[1] <> #13) do
                begin
                        BlockRead(DBFDataFile,DBFField.FieldName[1],1);
                        if (DBFField.FieldName[1] <> #13) then
                                begin
                                        BlockRead(DBFDataFile, DBFField.FieldName[2],SizeOf(DBFField) - 1, RecordsRead);
                                        ProcessField (DBFField, I);
                                        I := I + 1;
                                end;
                end;
        DBFFieldCount := I - 1;
end;

(***********************************************************)

Procedure OpenDBFData;

begin
        DBFDataFileAvailable := false;
        Assign(DBFDataFile, DBFFileName+'.DBF');

{$I-}
        Reset(DBFDataFile,1);
        If IOResult<>0 then exit;
{$I+}

        DBFDataFileAvailable := true;
        Seek(DBFDataFile,0);
        ReadDBFHeader;
        ReadFields;
end;

(******************************************************************)

Procedure CloseDBFData;

begin
        if DBFDataFileAvailable then Close(DBFDataFile);
end;

(*******************************************************************)

Procedure OpenDBFMemo;

begin
        DBFMemoFileAvailable := false;
        Assign(DBFMemoFile, DBFFileName+'.DBT');

{$I-}
        Reset(DBFMemoFile,1);
        If IOResult<>0 then exit;
{$I+}

        DBFMemoFileAvailable := true;
        Seek(DBFMemoFile,0);
end;

(*******************************************************************)

Procedure CloseDBFMemo;

begin
        If DBFMemoFileAvailable then close(DBFMemoFile);
end;

(*******************************************************************)

Procedure GetDBFFields;

var
        I                         : byte;
        J                         : integer;
        Response         : string;

begin
        DBFDeleteField := DBFBuffer[1];
        For I:=1 to DBFFieldCount do
                begin
                        DBFFieldContent[I] := '';
                        For J := DBFContentStart[I] to DBFContentStart [I] + DBFLengths[I] -1 do
                                DBFFieldContent[I] := DBFFieldContent[I] + DBFBuffer[J];
                        For J := 1 to DBFLengths[I] do
                                if DBFFieldContent[J]=#0 then DBFFieldContent[J]:=#32;
                end;
end;

(***********************************************************************)

Procedure ReadDBFRecord (I : Longint);

var
        RecordsRead : integer;

begin
        Seek(DBFDataFile, DBFHeading.HeaderLength + DBFHeading.RecordSize * (I - 1));
        BlockRead (DBFDataFile, DBFBuffer, DBFHeading.RecordSize, RecordsRead);
        GetDBFFields;
end;

(**********************************************************************)

Procedure ReadDBFMemo(BlockNumber : integer);

var
        I                         : integer;
        RecordsRead        : word;

begin
        DBFMemoLength := 0;
        DBFMemoEnd := false;
        If not DBFMemoFileAvailable then
                begin
                        DBFMemoEnd := true;
                        exit;
                end;
        FillChar(DBFMemo[1],DBFMaxMemoLength,#0);
        Seek(DBFMemoFile,BlockNumber*DBFMemoBlockLength);
        repeat
                BlockRead(DBFMemoFile,DBFMemoBuffer,DBFMemoBlockLength,RecordsRead);
                For I := 1 to RecordsRead  do
                        begin
                                DBFMemoLength := DBFMemoLength + 1;
                                DBFMemo[DBFMemoLength] := chr(DBFMemoBuffer[I] and $7F);
                                If (DBFMemoBuffer[I] = $1A) or (DBFMemoBuffer[I] = $00) then
                                        begin
                                                DBFMemoEnd := true;
                                                DBFMemoLength := DBFMemoLength - 1;
                                                exit;
                                        end;
                        end;
        until DBFMemoEnd;
end;

(*********************************************************************)

Procedure WriteDBFMemo  {(var BlockNumberString : string)};

var
        K : integer;
        ReturnCode : integer;

begin
        Val(BlockNumberString,DBFMemoBlock,ReturnCode);
        If ReturnCode>0 then DBFMemoBlock := 0;
        If DBFMemoBlock>0 then
                begin
                        Writeln;
                        ReadDBFMemo(DBFMemoBlock);
                        If DBFMemoLength=0 then exit;
                        For K := 1 to DBFMemoLength do
                                Write(DBFMemo[K]);
                        WriteLn;
                end;
end;

(****************************************************************)

Procedure WriteDBFRecord;

var
        J : byte;

begin
        For J := 1 to DBFFieldCount do
                begin
                        Write(DBFNames[J]);
                        GoToXY(12,J);
                        WriteLn(DBFFieldContent[J]);
                        if DBFTypes[J]='M' then WriteDBFMemo(DBFFieldContent[J]);
                end;
end;

(*******************************************************************)

begin
end.