          13 

        

      

        

            
 TDataSet.     TDataSet   ;   
 ,       . 

        

       ,      
   . 

    1  ASCII-   
        ,    
  .     ASCII-   
   ,    BDE. 

      Delphi 3        
.   Delphi  1  2    
   :   Paradox  dBASE   
 Delphi Client/Server   SQL-.   
    ,    
    ODBC-,  1     
 BDE.    ,  ODBC-   
  .     ODBC-    ? 
 Delphi 3       ,   
      - 1  . 
  .. ! 
      Delphi 3    .   
            
  .       
  Fields Editor,    ,   ,  
    Delphi. 
      ,   TDataSet Delphi 3     
  TBDEDafaSet     BDE API.    
TB'D'E'DStaSet      BDE 
  , TQuery, TStoredProc  ..    
  TD'ataSet  ,     
     .    
    TDataSet  ,    
   Delphi.    20  
  TDataSet,      . 

    309 

       :  -   
 ,     ,    
Object Pascal.       16, " 
'',  17, " ".  , ,  
           .  
     ,     . 

     TDataSet,      

           : 
,  ,  ,   TDataSet.  
        TDataSet, 
   .     
,     ,     
    .  . 13.1     
  TDataSet,    , 
,  ,     .  
  TDataSet        
,        ,   
  .       
TDataSet    ,   TDataSet 
     . 

     13.1.     TDataSet   
   

                         

    	Active,Open, Close 
    	First,Last,Next,Prior,MoveBy,Refresh,EOF,BOF, IsEmpty 
    	Edit,  Insert,  InsertRecord, Append, AppendRecord, Delete, 
Post,  Cancel,  Modified, State, CheckBrowseMode, SetFields 
      	BookmarkValid, CompareBookmarks, GotoBookmark, 
FreeBookmark, Get-Bookmark, Bookmark 
        	ControlsDisabled, DisableControls, 
EnableControls, IsLinkedTo 
    	BeforeOpen,  AfterOpen,  BeforeClose, AfterClose, Beforelnsert, 
Afterlnsert, BeforeEdit, AfterEdit, BeforePost, AfterPost, BeforeCancel, 
AfterCancel, BeforeDelete, AfterDelete, BeforeScroll, After-Scroll, 
OnCalcFields, OnDeleteError, OnEditError, OnNewRecord, On-PostError 
      	FieldByName, FieldByNumber, FieldDefs, FieldCount, Fields, 
FieldValues, DefaultFields, FindField, GetFieldList, GetFieldNames, 
Up-dateRecord, ClearFields 
        	ActiveBuffer, CursorPosChanged, 
GetCsurrentRecord, Translate, RecordSize 

       ,   . 13.1,    
         
 Fields Editor,       , 
 ,    ..      ,  
    ,   TDataSet.   
?       . 
      ,    .   
 . 
        . 
       . 
        . 

    310                                      III.     


      ASCII-   

            
,   ,        
  ,      . 
      ,   
  ASCII-,       
    .  TFixedAsciiDataSet 
       TStringList,  
       . 
      ,    
 ,    ,  ,   
 .       ,     
   SCH. 
        ,  Delphi    : 
TBDEDataSet (  SOURCE \VCL\DBTABLES. )  TClientDataSet (  
\SOURCE\VCL\DATASET. ).   '"5~ 
  .  '~     
,     "151. ' 
     TFixedAsciiDataSet    ,   
 ,  ,    ASCII- BDE. 
     ,   
    .  ,   
   TFixedAsciiDataSet      
  ,      ASCII- BDE. 
           ,   
 BDE32 . HLP.    ,      
Delphi   BDE.     Windows 95 "   Windows NT 4.0, 
        Start^Programs^ 
Borland Delphi 3 (riycK^riporpaMMbi^Borland Delphi 3). 
        ,    ,  
    ,        
 Delphi EMPLOYEE. DB.       Delphi 
TBatchMove.   13.1   ,    
  EMPLOYEE. TXT.       . 

     13.1. \UDELPHi3\CHPl3\EMPLOYEE. SCH.    
   

     Filetype=Fixed 
    CharSet=ascii 
    Fieldl=EmpNo,Long Integer,11,00,00 
    Field2=FirstName,Char,20,00,11 
    Field3=LastName,Char,15,00,31 
    Field4=PhoneExt,Char,04,00,46 
    Field5=HireDate,TimeStamp,30,00,50 
    Field6=Salary,Float,20,02,80 
    
     ,       , 
         , 
     . 
       .   ASCII- BDE 
   (DELIMITED  FIXED),     
   .  ,   
   FIXED.   CharSet   
 BDE. , ,     ,   
 ,   .    
   "Fieldx=",     (,  Fieldl, Field2  
..).         
,   . 
    1. Field Name.    ,      Paradox. 
    2. Data Type.    (. 13.2). 
    3. Field Size.    ,     
  20    .     
  ,     ,   
   (  "/"  ":''). 

     13.                            311 

    4. Precision.  ,     ( 
  FLOAT).    TFixedAsciiDataSet . 
    5. Field Offset.         
.     BDE Fixed.    
 TFixedAsciiDataSet,       
,     . 
     . 13,2    .   ,  
           
Delphi,           . 
    
     13.2.     

      	 

    Char	  
    Float	64-     
    Number	16-  
    Long Integer	32-   
    Bool	()  (  F) 
    Date	  (,   ) 
    Time	  (,   ) 
    Time stamp	 / (,   ) 


        

    ,    ,   ,      
.  TFixedAsciiDataSet ,   
   .      
,         ,   
 13.2.      TFixedAsciiDataSet, , 
 ,  ,  ,    TDataSet.  
,    ,   TDataSet      
    . 
       TDataSet    . 
   TDataSet     
   ^^    (    
TFixedAsciiDataSet).  ,  TDataSet    
      .   
   TDataSet   ,   
     ,    
 TDataSource.      TDataSet   
?  ,        
   ,     , , 
    . 
     ,      
 .  _,     
, .,   '"  
    TDataSet.     
 ^^         
   ,     , 
     TDataSet    
.    ,    , 
  private   TFixedAsciiDataSet    
    ,    
 ,      .    
      13.2,     
 .  ASCIIDRV. PAS     . 

    312                                       III.     


    1  13.2. \UDELPHI3\CHP13\ASCIIDRV.PAS. 

        TFixedAsciiDataSet,    
,         

    ""TfTxedAs'ciiDataset = class (TDataSet) 
    "^                       Lir^t 
    FTextRecords    TStrings;//     . 
    FFieldInfo      TList;   //       . 
    FRawBufSize    ^; //    . 
    FRecBufSize     Integer; // FRawBufSize +   TRecInfo. 
    FRecInfoOfa     Integer; //    TRecInfo   . 
    FCurRec         Integer; //   . 
    FFileName       string; //   ASCII-. 
    FLastBookmark   Integer; //  . 
    FSaveChanges    Boolean; // ,    . 
    procedure PopulateFieldDefsFromSchema; 
    protected 
    //  Dataset,    . 
    // ,      
    . 
    procedure Internal-Open; override; 
    procedure InternalInitFieldDefs; override; 
    procedure InternalClose; override; 
    function IsCursorOpen: Boolean; override; 
    //     . 
    procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override; 
    procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override; 
    function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override; 
    procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override; 
    procedure InternalSetToRecord(Buffer: PChar); override; 
    procedure InternalGotoBookmark(Bookmark: Pointer); override; 
    //     Dataset. 
    function GetRecordCount: Integer; override; 
    function AllocRecordBuffer: PChar; override; 
    procedure FreeRecordBuffer(var Buffer: PChar); override; 
    function GetRecord(Buffer: PChar; GetMode: TGetMode; 
    DoCheck: Boolean): TGetResult; override; 
    function GetRecordSize: Word; override; 
    procedure InternalInitRecord(Buffer: PChar); override; 
    procedure InternalAddRecord(Buffer: Pointer; Append: Boolean); override; 
    procedure InternalPost; override; 
    procedure InternalDelete; override; 
    //    Dataset. 
    procedure SetFieldData(Field: TField; Buffer: Pointer); override; 
    function GetFieldData(Field: TField; 
    Buffer: Pointer): Boolean; override; 
    //    Dataset. 
    procedure InternalFirst; override; 
    procedure InternalLast; override; 
    //     Dataset. 
    procedure InternalHandleException; override; 
    protected 
    procedure SetFileName(Value : Strings
    published 
    property FileName: string read FFileName write SetFileName; 
    property Active; 
    property BeforeOpen; 
    property AfterOpen; 
    property BeforeClose; 


     13.                           313 


    property AfterClose; 
    property Beforelnsert; 
    property Afterlnsert; 
    property BeforeEdit; 
    property AfterEdit; 
    property BeforePost; 
    property AfterPost; 
    property BeforeCancel; 
    property AfterCancel 
    property BeforeDelete; 
    property AfterDelete 
    property BeforeScroll; 
    property AfterScroll 
    property OnCalcFields; 
    property OnDeleteError; 
    property OnEditError 
    property OnNewRecord 
    property OnPostError 
    end; 


     

     ,    TFixedAsciiDataSet,  
       .   
,    TDataSet      
,   -    ,     
        
 ,      ,  . 

    ,       

          . 
     InternalOpen 
     InternalInitFieldDefs 
     InternalClose 
    IsCursorOpen 
          13.3. 
       InternalOpen.      
,        (  
InternalInitFieldDefs)     ,   
  ,   ,    
    ,     . 
       InternalOpen   TFixedAsciiDataSet   
,    , ,  ,     
TStringsList (FTextRecords).      
 ,      . 
  InternalOpen   13.3    
   . 

      
            
.   ^    ,    
 . 

      FieldDefs  TDataSet   , 
     .     
InternalInitFieldDefs, ,   ,  private 
PopulateFieldDefsFromSchema.        SCH  
        FieldDefs  TDataSet. 
       13.4. 

    314                                      III.     

         ,     
(FRawBufSize),          
 ,        
  ,    .   
     (TRecInfo)    
. ,   ,    
,    TRecInfo.      
 FRawBufSize, ,    ,  
  (F^RecInfoOfs)      
TRecInfo   . ,  Boorinarksize  
   ,       . 
     InternalClose ,   - , ,  
,    ,     
TStringsList (FTextRecords),    ,   
    {crii7coK~Fi7eldlnfo).  
   FFieldlnfo. 
     IsCursorOpen    TDataSet   , 
  ,   (  )   Result, 
 ,     FTextRecords. 

    ;  13.3. \UDELPHI3\CHP13\ASCIIDRV. PAS.  , 
    

    TFixedAsciiDataSet 
    procedure TFixedAsciiDataset.InternalOpen; 
    //--_-_--_--_ 
    // .    ,    
    //                     
    //                ,     
    //                  . 
    //___ 
    var 
    I: Integer; 
    begin 
    FTextRecords := TStringList.Create; 
    try 
    //        . 
    if not FileExists(FileName) then Abort; 
    FTextRecords.LoadFromFile(FileNameTT""' 
    //      . 
    for I := 1 to FTextRecords-Count do 
    FTextRecords.Objects[I - 1] := Pointer(I); 
    //      . 
    //       0  
    // FTextRecords.Count - 1,  -1  FTextRecords.Count 
    //     BOF  EOF 
    // . 
    FCurRec := -1;    //     BOF. 
    FLastBookmark := FTextRecords.Count; 
    //     ,    
    //  TField   . , , 
    //  . 
    InternalInitFieldDefs; 
    if DefaultFields then CreateFields; 
    BindFields(True) ; 
    //      TRecInfo 
    //   . 
    FRecInfoOfs := FRawBufSize; 
    //     (,    
    //   ,    RecordSize,   
    //   ). 
    FRecBufSize := FRecInfoOfs + SizeOf(TRecInfo); 
    //  TDataSet,     . 


     13.                            315 


    BookmarkSize := SizeOf(Integer); 
    except 
    FTextRecords.Free; 
    FTextRecords := Nil; 
    Active := False; 
    Showmessage('Error opening text file: ' + FileName); 
    raise; 
    end; 
    end; 
    procedure TFixedAsciiDataset.InternallnitFieldDefs ; 
    // 
    // .        
    //                   FieldDefs,     
    //                   . 
    // 
    begin 
    PopuI ateFieldDefsFromSenema; 
    end; 
    procedure TFixedAsciiDataset.InternalClose; 
    // 
    // .    ,   
    //                ,   - . 
    //                  - .  , 
    //                  finally,    
    //                    . 
    // 
    var 
    I : Integer; 
    begin 
    if FSaveChanges then FTextRecords.SaveToFile(FileName); 
    FTextRecords.Free; 
    FTextRecords := nil; 
    FLastBookmark := 0; 
    FCurRec := -1; 
    BindFieldsJFalse) ; 
    Ti~'De'tau 1 t'Fi e 1 d s'"'t hen DestroyFields; 
    //     
    if Assigned(FFieldInfo) then 
    try 
    if FFieldInfo.Count > 0 then 
    for I := 0 to FFieldInfo.Count - 1 do 
    FreeMem(PFieldInfo(FFieldInfo[I]), SizeOf(TFieldInfo)) ; 
    finally 
    FFieldInfo.Free; // ,     . 
    FFieldInfo := Nil; 
    end; 
    end; 
    function TFixedAsciiDataset.IsCursorOpen: Boolean; 
    // 
    // .     .   
    //                  ,      
    //                dsInActive. 
    // 
    begin 
    Result := Assigned(FTextRecords) ; 
    end;          '~" 

          ,    
 .    ' FieldDefs    
         ,  
  ProcessField    TFieldInfo   
FFieldInfo,   

    316                                      III.     

               
,  ,   " ".  
ProcessField       (. . 13.2)  
       TDataSet: ftString, ftFloat, 
ftlnteger, ftBoolean, ftDate, ftTime  ftDateTime. 

      13.4. \UDELPHl3\CHPl3\ASCHDRV. PAS.    
 TFixedAsciiDataSet | 

    procedure TFixedAsciiDataset.PopulateFieldDefsFromSchema; 
    // 
    // .   ,      
    //                   FileName. 
    // <Field<# = <FieldName>,<Field Type>,<Field Size>, 
    //                 <Precision>,<0ffset> 
    // 
    // <Field Type>      : CHAR, FLOAT, 
    //                  NUMERIC, BOOL, LONG INTEGER, DATE, TIME  
    //                  TIMESTAMP. 
    // <Field Size>       . 
    //                     
    //                    /   
    //                  '/'  ':'. 
    // <Precision>       . 
    //                    , 
    //                        
    //                  . 
    //<0ffset>             
    //                  ,    
    //                  .   , 
    //                         
    //                 <Field Size>.      
    //                  BDE. 
    // 
    var 
    SchemaFile : TStrings; 
    CalculatedOfset : Integer; 
    I : Integer; 
    const ValidFieldTypes : array[1..9] of string = ('CHAR', 'FLOAT', 
    'NUMERIC','BOOL', 'LONGINT', 'LONG INTEGER' , 'DATE', 
    'TIME','TIMESTAMP') ; 
    FieldTypes: array[1..9] of TFieldType = (ftString, ftFloat, 
    ftlnteger, ftBoolean, ftlnteger, ftlnteger, ftDate, 
    ftTime,ftDateTime) ; 
    procedure ProcessField(Fieldlnfo : String); 
    ////----------------------
    // .      
    //              ,    ; 
    //// 
    var 
    FieldName, FieldTypeToken : String; 
    FIdSize, J : Integer; 
    FieldType : TFieldType; 
    FieldInfoRec : PFieldInfo; 
    function NextToken : String; 
    //// 
    // .     
    //               (   ..) 
    ////------ 
    var 
    DelimPos : Integer; 
    begin 
    DelimPos := AnsiPos(',', Fieldlnfo); 


     13.                           317 


    if DelimPos = 0 then 
    Result := Trim(FieldInfo) 
    else 
    begin 
    Result := TrimfCopy(Fieldlnfo, 1, DelimPos - 1)); 
    Fieldlnfo := Trim(Copy(FieldInfo, DelimPos + 1, 255)); 
    end; 
    end; 
    begin 
    with FieldDefs do 
    try 
    FieldName := NextToken;         //   . 
    FieldTypeToken := NextToken;    //   . 
    //    ,     
    //      ValidFieldTypes. 
    FieldType := ftUnknown; 
    for J := Low(ValidFieldTypes) to High(ValidFieldTypes) do 
    if FieldTypeToken = ValidFieldTypes[J] then 
    begin 
    FieldType := FieldTypes[J] ; 
    Break; 
    end; 
    FIdSize := StrToInt( NextToken ); //    NextToken; 
    //   
    //    
    // . 
    NextToken;                        //    . 
    //   ,  ,    
    //  ,  ,    
    //  . 
    GetMem(FieldInfoRec, SizeOf(TFieldInfo)) ; 
    with FieldInfoRec^ do 
    begin 
    FieldOfs := CalculatedOfset; 
    FieldSize := FIdSize; 
    end; 
    FFieldInfo.Add(FieldInfoRec) ; 
    Inc(CalculatedOfset, FIdSize);    //  . 
    FRawBufSize := CalculatedOfset; //   
    //  . 
    //       
    //     FieldDef  . 
    if FieldType  ftString then FIdSize := 0; 
    //        FieldDef. 
    // .      1. 
    TFieldDef.Create(FieldDefs, FieldName, FieldType, FIdSize, 
    False, FieldDefs.Count + 1) ; 
    except 
    raise EDatabaseError.Create ( 
    'Schema Read Error: Error processing field ' + FieldName + ' in schema file') 
    end; 
    end; 
    procedure ProcessTokens(const LeftToken, RightToken : String); 
    // 
    // .      BDE-. 
    //                    
    //               ,    
    318                                      III.     

    //               DELIMITER  SEPARATOR  . 
    //               ,      
    //               ,      
    //              CHARSET  .    
    //                [TableName],   
    //               BDE-. ,      , 
    //                ,     FIXED   
    //                   . 
    // 
    begin 
    //    . 
    if Length(LeftToken) > 0 then 
    if (LeftToken = 'CHARSET') or 
    (LeftToken = 'DELIMITER') or 
    (LeftToken = 'SEPARATOR') or 
    (LeftToken[l] = '[') then Exit; 
    if (LeftToken = 'FILETYPE') and (RightToken <> 'FIXED') then 
    Raise Exception.Create ( 
    'Schema Read Error: FILETYPE must be FIXED'); 
    //     . 
    if AnsiPos('FIELD', LeftToken) > 0 then 
    ProcessField(RightToken) ; 
    end; 
    function GetSchemaFileName : String; 
    // 
    // .       
    //               . 
    // 
    begin 
    Result := ExtractFileName(FileName); 
    Result := CopyfResult, 1, AnsiPosC.', Result) ) + 'SCH'; 
    Result := ExtractFilePath(FileName) + Result; 
    end; 
    var 
    LeftStr, RightStr, SchemaFileName : String; 
    begin 
    CalculatedOfset := 1; 
    FieldDefs.Clear; 
    SchemaFile := TStringList.Create; 
    try 
    SchemaFileName := GetSchemaFileName; 
    if not FileExists(SchemaFileName) then Abort; 
    FFieldInfo := TList.Create; 
    try 
    SchemaFile.LoadFromFile( SchemaFileName ); 
    for I := 0 to SchemaFile.Count - 1 do 
    begin 
    LeftStr := AnsiUpperCase(Trim(Copy(SchemaFile[I], 1, AnsiPos ('=', 
SchemaFile[I]) - 1))); 
    RightStr := AnsiUpperCase(Trim(Copy(SchemaFile[I], 
    AnsiPos ('=', SchemaFile[I]) + 1, 255 ))); 
    ProcessTokens(LeftStr, RightStr) ; 
    end; 
    except 
    FFieldInfo.Free; 
    end; 
    finally 
    SchemaFile.Free; 
    end; 
    end; 


     13.                            319 


       

     (bookmarks)        
  .    ,  
   ,  ,  
   .   TDataSet  
  ,      . 
 ,         
 .    TDataSet,     
 .  TDataSet      
   ^  . 
     Delphi 1         
  ,     GetBookmark (. 
 ,  ).    ,  
        FreeBookmark,  
    . 

    TBookmark = Pointer; 

     Delphi 3  TBookmark   ,    
      Bookmark.   
  TBookmarkStr,       

    AnsiString. '"r<h              T"            " 
    TBookmarkStr = string; 

          ,   
 .,     ,   
    THna'AnsiString.      
     Delphi.                 """""''"" 
           . 

     GetBookmarkData 
     SetBookmarkData 
     GetBookmarkFlag 
     SetBookmarkFlag 
     InternalSetToRecord 
     InternalGotoBookmark 

     ,         
     ( ),    
       . 
            
TFixedAsciiDataSet,   ,       
 .   TFixedAsciiDataSet    
       .   
   - Objects   FTextRecords  
     ,      : 

    for I := I to FText.Count do 
    FTextRecords.Objects [1-1] := Pointer(I); 

     ,   TDataSet     
,   ,      
 TRecInfo,      . 
  TRecInf    ,   TDataSet. 
       TRecInfo. 

    PRecInfo = ^TRecInfo; 
    TRecInfo = packed record 
    Bookmark: Integer; 
    BookmarkFlag: TBookmarkFlag; 
    end; 

     , ,   Bookmark,    
BookmarkFj.pJ^'1-.       TDataSet 
,        
     ,       
 TDataSet.    . 

    ActiveBuffer 1 
    I                         |  I  | 
    ActiveBuffer + FRecInfoOfs----^ 


    320                                      III.     

            , 
       TRednfo   
 ,    '    
GetBookmarkData      .   ' 
       ,  GetRecord,    
  ,    TDataSet  , 
   ,   TRednfo. 

      1 
    ,          
 .    TDataSet   . 

    , , ,   GetBookmarkData, SetBookmarkData, 
GetBookmarkFlag  SetBookmarkFlag   TDataSet.  
  .       13.5.  
     . 
         BookmarkFlags?  TDataSet  
     :    
,       .  (EOF). 
  BookmarkFlags,     ,  
  TDataSet.       
        GetRecord 
 TDataSet.  GetRecord     . 
       , ,     
   .      
InternalSetToRecord  InternalGotoBookmark.        
    TDataSet     , 
   . 
              . 
 InternalSetToRecord   InternalGotoBookmark,  
InternalGotoBookmark    .   
 ^^_     
.  trrt'en'CTtSe'ETo'Record ~    
   ,   InternalGotoBookmark   
  . 
      TFixedAsciiDataset  InternalGotoBookmark  
 IndexOfObject  FTextRecords  TStringList   
 .    ,   (FCurRec) 
  .       . 
 ,     .     
 . 

     13.5. ASCIIDRV. .     
TFixedAsciiDataset        . 

    procedure TFixedAsciiDataset.GetBookmarkData(Buffer: PChar; 
    Data: Pointer); 
    // 
    // .      , 
    //                    TDataSet.   
    //                       TRednfo,  
    //                      ,   
    //                       ''""''?';' ---""""""'""""" 
    // 
    begin 
    PInteger(Data) /\ := PRednfo (Buffer + FRednfoOfs) .Bookmark; 
    end; 
    procedure TFixedAsciiDataset.SetBookmarkData(Buffer: PChar; 
    Data: Pointer) ; 
    // 
    // .       
    //                  ,   TDataSet.  
    //                       TRednfo, 
    //                       ,  
    //                    . 
    // 
    begin 
    PRednfo (Buffer + FRednfoOfs) .Bookmark := PInteger (Data) "; 
    end; 


     13.                            321 
    11  Delnhi 


    function TFixedAsciiDataset.GetBookmarkFlag(Buffer: PChar) : 
    TBookmarkFlag; 
    // 
    // .  BookmarkFlag   ,  
    //                    TDataSet. BookmarkFlag  
    //                       TRecInfo,  
    //                       ,   
    //                   . 
    // 
    begin 
    Result := PRednfo (Buffer + FRednfoOfs) .BookmarkFlag; 
    end; 
    procedure TFixedAsciiDataset.SetBookmarkFlag(Buffer: PChar; 
    Value: TBookmarkFlag); 
    // 
    // .   BookmarkFlag   
    //                   ,   TDataSet. BookmarkFlag 
    //                        TRecInfo, 
    //                        ,  
    //                     . 
    // 
    begin 
    PRednfo (Buffer + FRednfoOfs) . BookmarkFlag := Value; 
    end; 
    procedure TFixedAsciiDataset.InternalSetToRecord(Buffer: PChar) ; 
    // 
    // .      ,    
    //                   InternalGotoBookmark,      
    //                    . 
    // 
    begin 
    InternalGotoBookmark (@PRednfo (Buffer + FRednfoOfs) .Bookmark) ; 
    end; 
    procedure TFixedAsciiDataset.InternalGotoBookmark(Bookmark: 
    Pointer) ; 
    // 
    // .       , 
    //                     .    , 
    //                    . 
    // 
    var 
    Index: Integer; 
    begin 
    Index := FTextRecords.IndexOfObject(TObject(PInteger(Bookmark) /\)); 
    if Index <> -1 then 
    FCurRec := Index 
    else 
    DatabaseError('Bookmark not found'); 
    end; 
      
            . 
    I GetRecordCount 
     AllocRecordBuffer 
    II FreeRecordBuffer 
     GetRecordSize 
     InternalInitRecord 


    322                                      III.     


     InternalAddRecord 
     Internal-Post 
     Internal-Delete 
     GetRecord 

        ,     ,  
   ( ,       13.6). 
     InternalInitRecord ,    TDataSet 
   .      
 TFixedAsciiDataSet     (  
ASCII 32). 
     InternalAddRecord ,      
  InsertRecord  AppendRecord.  InternalAddRecord 
   ,       
  TDataSet. 
     ,  TDataSet  ,   
 InsertRecord  AppendRecord,       
 SetFieldData,   .  SetFieldData 
    ,   " ".   
13.6 ,        . 
     InternalPost ,     ( 
)   Insert, Append  Edit.  ,  
,  ,    InternalAddRecord (   
     ). 
     InternalDelete    ,     
  FTextRecords  TStringList,     
  (FCurRec). 
    ,   ,  GetRecord,  ,   
.         TDataSet  
,    .     
 (TGetResult),    TDataSet  
   .  , TGetResult,  : 

    TGetResult = (grOK, grBOF, grEOF, grError) ; 

    , ,  GetRecord   ,   
DoCheck  (True)   .    , 
 , ,        . 

    j  13.6. ASCIIDRV. .     
TFixedAsciiDataSet              j 

    function TFixedAsciiDataSet.GetRecordCount: Longint; 
    // 
    // .       
    //                     . 
    // 
    begin 
    Result := FTextRecords.Count; 
    end; 
    function TFixedAsciiDataSet.AllocRecordBuffer: PChar; 
    // 
    // .   .   
    //                    FRecBufSize,     
    //                     TRecInfo. 
    // 
    begin 
    Result := StrAlloc(FRecBufSize); 
    end; 
    procedure TFixedAsciiDataSet.FreeRecordBuffer(var Buffer: PChar); 
    // 
    // .   .    
    //                     ,   FRecBufSize 
    //                    . 
    // 
    begin 
    StrDispose(Buffer) ; 
    end; 


     13.                            323 


    function TFixedAsciiDataset.GetRecordSize: Word; 
    // 
    // .    ""    
    //                    TRecInfo. 
    // 
    begin 
    Result := FRawBufSize; 
    end; 
    procedure TFixedAsciiDataset.InternalInitRecord(Buffer: PChar); 
    // 
    // .   TDataSet.InitRecord  
    //                  TDataSet.ClearFields    
    //                  .     
    //                     ( Null), ,  
    //                   GetFieldData  ,   
    //                   . 
    // 
    begin 
    FillCharfBuffer^, RecordSize, 32); 
    end; 
    procedure TFixedAsciiDataset.InternalAddRecord(Buffer: Pointer; 
    Append: Boolean); 
    // 
    // .    TDataSet.InsertRecord 
    //                   TDataSet.AppendRecord.    
    //                    , FLastBookmark,  
    //                          
    //                    ,   
    //                        . 
    // 
    begin 
    Inc(FLastBookmark) ; 
    if Append then InternalLast; 
    FTextRecords.InsertObject(FCurRec, PChar(Buffer), Pointer(FLastBookmark)) ; 
    FSaveChanges := True; 
    end; 
    procedure TFixedAsciiDataset. Internal-Post; 
    // 
    // . ,     
    //                 ,    . 
    //                       
    //                       . 
    // 
    begin 
    if State = dsEdit then 
    FTextRecords[FCurRec] := ActiveBuffer 
    else 
    begin 
    //   ( ) ,     
    //  . 
    Inc(FLastBookmark) ; 
    FTextRecords.InsertObject(FCurRec, ActiveBuffer, 
    Pointer(FLastBookmark)); 
    end; 
    //  ,     
    //    . 
    FSaveChanges := True; 
    end; 


    324                                      III.     


    procedure TFixedAsciiDataset.InternalDelete; 
    // 
    // .  ,   ,  
    //                        . 
    //                     .  ,  , 
    //                    ,  ,   
    //                       1. 
    // 
    begin 
    FTextRecords.Delete(FCurRec) ; 
    if FCurRec >= FTextRecords.Count then Dec(FCurRec); 
    FSaveChanges := True; 
    end; 
    function TFixedAsciiDataset.GetRecord(Buffer: PChar; 
    GetMode: TGetMode; DoCheck: Boolean): TGetResult; 
    // 
    // .   ,    
    //                   :    ,  
    //                    .    
    //                   (TGetResult) ,   DoCheck  True  
    //                   ,   
    //                  . 
    // 
    begin 
    if FTextRecords.Count < 1 then 
    Result := grEOF 
    else begin 
    Result := grOK; 
    case GetMode of 
    gmNext: 
    if FCurRec >= RecordCount - 1 then 
    Result := grEOF 
    else 
    Inc(FCurRec) ; 
    gmPrior: 
    if FCurRec <= 0 then 
    Result := grBOF 
    else 
    Dec(FCurRec) ; 
    gmCurrent: 
    if (FCurRec < 0) or (FCurRec >= RecordCount) then 
    Result := grError; 
    end; 
    if Result = grOK then 
    begin 
    StrLCopy(Buffer, PChar(FTextRecords[FCurRec]), FRecBufSize) ; 
    with PRednfo (Buffer + FRednfoOfs)  do 
    begin 
    BookmarkFlag := bfCurrent; 
    Bookmark := Integer(FTextRecords.Objects[FCurRec]); 
    end; 
    end else 
    if (Result = grError) and DoCheck then 
    DatabaseError('No Records'); 
    end; 
    end; 


      

          GetFieldData  SetFieldData. 
     GetFieldData    TField    . 
  FieldNo  DataType  TField,  GetFieldData 
            
 .        ,  
( ) 

     13.                           325 

            .  
. 13.3    ,    
TDataSet,    ,    TFixedAsciiDataSet. 
     SetFieldData  ,  ,  
  GetFieldData.      Fie Id   
.        (  
 )     ,   
   TField.  SetFieldData   
          
.       ,   . 
13.3,     . ,   
,       . 
        TDataSet,   , 
 GetFieldData  SetFieldData      
-  . 

     13.3.   ,   
GetFieldData  SetFieldData 

     	     TFixedAsciiDataSet 

    ftString	Pchar  	    nil 
    ftFloat	Ptr  8-  Double	     
    ftlnteger	Ptr  4-  Integer	   
    ftBoolean	Ptr  2-  WordBool. False 0 True  0	  
  Fxxxx 
    ftDate	Ptr  4-  Integer   1/1/0001+1	  
    ftTime	Ptr  4-  Integer   	  
    ftDateTime	Ptr  8-  Double	 /   
 1/1/0001+1 

     13.7. ASCIIDRV. PAS.     TFixedAsciiDataSet 

    function TFixedAsciiDataSet.GetFieldData(Field: TFieid; 
    Buffer: Pointer): Boolean; 
    //_ 
    // .        . 
    // 
    var 
    FieldAddrInBuffer : Pointer; 
    FieldText : String; 
    function AsciiDateTimeToDateTime(DateTimeStr : String): Double; 
    const 
    TimeDelta : Double = 0; 
    var 
    AM_PM_Pos : Byte; 
    begin 
    AM_PM_Pos := AnsiPosCM', AnsiUpperCase (DateTimeStr) ) - 1; 
    if AM_PM_Pos > 0 then 
    begin 
    if UpCase(DateTimeStr[AM_PM_Pos]) = 'P' then 
    TimeDelta := 0.5;   //    ; 
    //  12 . 
    DateTimeStr := Trim(Copy(DateTimeStr, I, AM_PM_Pos - 1)); 
    end; 


    326                                      III.     


    Result := TimeStampToMSecs(DateTimeToTimeStamp( 
    StrToDateTime(DateTimeStr) + TimeDelta)) ; 
    end; 
    begin 
    Result := False; 
    if IsEmpty or (Field.FieldNo < 1) then Exit; 
    //if Field.FieldNo = 0 then Showmessage('Field.Name'); 
    with Field, PFieldInfo(FFieldInfo[FieldNo - 1])" do 
    try 
    FieldAddrInBuffer := Pointer(Integer(ActiveBuffer) + FieldOfs - 1); 
    //      . 
    FieldText := '' ; 
    SetLength(FieldText, FieldSize + 1); 
    StrLCopytPChar(FieldText), FieldAddrInBuffer, FieldSize); 
    FieldText := Trim(FieldText); 
    if Length(TrimRight(FieldText)) = 0 then Exit; 
    //  /    . 
    case Field.DataType of 
    ftString:   StrLCopy(Buffer, FieldAddrInBuffer, FieldSize); 
    ftFloat:    Double(Buffer") := StrToFloat(FieldText); 
    ftlnteger: Longint(Buffer") := SysUtils.StrToInt(FieldText); 
    ftBoolean: WordBool(Buffer") := FieldText[1] = ''; 
    ftDate:     Longint(Buffer") := 
    DateTimeToTimeStamp(StrToDate(FieldText)).Date; 
    ftTime:     Longint(Buffer") := 
    DateTimeToTimeStamp(StrToTime(FieldText)).Time; 
    ftDateTime: Double(Buffer") := 
    AsciiDateTimeToDateTime(FieldText) ; 
    end; 
    except 
    //    ,   
    //    ()    . 
    //      False,  
    // ,      Null. 
    //  Result   False . 
    end; 
    //   ,    True. 
    Result := True; 
    end; 
    procedure TFixedAsciiDataset.SetFieldData(Field: TField; 
    Buffer: Pointer) ; 
    //-___
    // .       
    //                . 
    // 
    function Right Justify(const Str : String; Size : Integer):String; 
    // 
    // .     
    //             ,      
    //               . 
    // 
    begin 
    SetLength(Result, Size); 
    FillMemory(Pointer(Result), Size, ORD(' ')); 
    Result := Result + Str; 
    Result := Copy(Result, Length(Result) - Size + 1, Size); 
    end; 


     13.                            327 


    const 
    TrueText : PChar = "I" ; 
    FalseText : PChar = 'F'; 
    var 
    FieldAddrInBuffer : Pointer; 
    TempStr : String; 
    StrSize : Integer; 
    TimeStamp :TTimeStamp; 
    begin 
    if Field.FieldNo < 0 then Exit; 
    With field, PFleldInfofFrieldInfo[FieldNo - 1])" do 
    try 
    FieldAddrInBuffer := Pointer(Integer(ActiveBuffer) + FieldOfs - 1); 
    FillMemory(FieldAddrInBuffer, FieldSize, ORD(' ')); //  . 
    case  DataType  of 
    ftString: 
    begin 
    StrSize := StrLen(Buffer) ; 
    if StrSize > FieldSize then StrSize := FieldSize; 
    MoveMemory(FieldAddrInBuffer, Buffer, StrSize); 
    end; 
    ftBoolean: 
    if WordBool(Buffer") then 
    MoveMemory(FieldAddrInBuffer, TrueText, FieldSize) 
    else 
    MoveMemory(FieldAddrInBuffer, FalseText, FieldSize); 
    ftlnteger: 
    begin 
    TempStr := Right Justify(IntToStr (Longint(Buffer")), FieldSize); 
    MoveMemory(FieldAddrInBuffer, Pointer(TempStr), FieldSize); 
    end; 
    ftFloat: 
    begin 
    TempStr := RightJustifytFloatToStr(Double(Buffer")), FieldSize); 
    MoveMemory(FieldAddrInBuffer, Pointer(TempStr), FieldSize); 
    end; 
    ftDate: 
    begin 
    TimeStamp.Time : 0; 
    TimeStamp.Date := Longint (Buffer") ; 
    TempStr := DateTimeToStr(TimeStampToDateTime(TimeStamp)); 
    MoveMemory(FieldAddrInBuffer, Pointer(TempStr), FieldSize); 
    end; 
    ftTime: 
    begin 
    TimeStamp.Time := Longint(Buffer") ; 
    TimeStamp.Date := 0; 
    TempStr := DateTimeToStr(TimeStampToDateTime(TimeStamp)); 
    MoveMemory(FieldAddrInBuffer, Pointer(TempStr), FieldSize); 
    end; 
    ftDateTime: 
    begin 
    TempStr := FormatDateTime(ShortDateFormat + ' ' + 
    ShortTimeFormat, TimeStampToDateTime( MSecsToTimeStamp(Double(Buffer")))) ; 
    MoveMemory(FieldAddrInBuffer, Pointer(TempStr), Length(TempStr)); 
    end; 
    end; 
    except 
    Abort; 
    end; 
    DataEvent(deFieldChange, Longint(Field)) ; 
    end; 


    328                                      III.     


      

             . 
       
InternalFirst  InternalLast     13.8.  InternalFirst 
      (FCurRec)  1  
  , ..  -1.  InternalLast,   , 
      FTextRecords . Count, 
  1    .    ,  
   ,    .   
   ,       
  .       Resync 
 TDataSet. 

     13.8. ASCIIDRV. .   TFixedAsciiDataSet  
  

    procedure TFixedAsciiDataset.InternalFirst; 
    //_
    // .     .  
    //             ,       
    //                 . 
    //                     
    //                Resync. 
    // 
    begin 
    FCurRec := -1; 
    end; 
    procedure TFixedAsciiDataset.InternalLast; 
    // 
    // .     . 
    //                    FTextRecords.Count    
    //                       FCurRec. 
    // 
    begin 
    FCurRec := FTextRecords.Count; 
    end; 


        

       TDataSet,   , 
InternalHandleException, ,      
     .   TFixedAsciiDataset 
      
  Delphi,     13.9. 

    1  13.9. ASCIIDRV. PAS.     
 TFixedAsciiDataset 

    procedure TFixedAsciiDataset.InternalHandleException; 
    begin 
    Application.HandleException(Self) ; 
    end; 


     

        ,       
  Delphi 3.       
TFixedAsciiDataSet,   ASCIIDRV. PAS.     
,    TFixedAsciiDataSet    Delphi. 
         ,  
 Delphi    .   13.10  
 Register,    . 

     13.                            329 


     13.10. \UDELPHI3\CHP13\ASCIIDRV.PAS. 

     Register   TFixedAsciiData- ,f| 
    Set    Delphi                                           
                       ' 
    procedure Register; 
    implementation 
    uses SysUtils, Forms, Dialogs; 
    procedure Registers
    begin 
    RegisterComponents('UDelphi3',[Asciidrv.TFixedAsciiDataset]) ; 
    end; 

    ,    ,    
  .        
 . 
    1.   File^Close All     . 
    2.   File^New     Package. 
    3.     New Package,   File Name  
   Delphi 3\Bin (, \ PROGRAM FILES\BORLAND\DELPHI 3\BIN) 
     (AS  DRV 30). 
    4.   Description  UD3 Chapter 13 - Custom DataSet Example. 
    5.    . 
    6.        Add    
 ASCIIDRV. PAS. 
    (      \UDELPHI3\CH13.) 
    
    7.   Requires      Add,  
  .    Add Package   
 : VCLDB30.    ,   VCL30   . 
    8.    Install. 
    9.    Package. 
            UDelphi3  
TFixedAsciiDataset  .      ,  
   ASCII-.    
TFixedAsciiDataset  ,   : 
\UDELPHI3\CH13\CUSTOMDB. DPR. 
     ,       
    .     
  ,      .   
      ,  
 .          , 
  ,     
 .      ,   , 
  . 

    330                                      III.     
