
                     NON-VIEW OBJECTS INCLUDING STREAMS.
                     -----------------------------------

 Thus far the object types considered have all been views, descendant from
 TView.  The non-view types, descendant from the root object type TObject
 include streams, resource files, collections and string lists.

 A stream is a generalized object for handling input and output.  TStream is
 the base abstract object providing polymorphic I/O to and from a storage
 device.

 A resource file is a special kind of stream where generic objects can be
 indexed via string keys.

 Collections involve TCollection which implements a general set of items,
 including arbitrary objects of different types.

 String lists are formed from TStringList which implements a special kind of
 string resource in which strings can be accessed via a numerical index.


 Collections.
 ------------

 A TCollection type is an object designed to extend the normal behaviour of
 a Pascal array.  It has built-in methods for handling the array and it also
 allows dynamic sizing.  It is polymorphic by virtue of the fact that it
 uses untyped pointers and so allows the collection to consist of objects,
 and non-objects, of different types and sizes.

 This release from the normal strict type checking of Pascal requires care
 on the part of the programmer.  Furthermore, if non-TObject items are used
 in a collection, then GetItem, PutItem and FreeItem must be modified, as
 done in TStringCollection.

 TCollection (pp221-226) has four fields, a pointer to an array of item
 pointers, a count of the current number of items, the currently allocated
 size (limit), an increment value (delta) for use when the collection has to
 grow . There are 23 methods, including Init, Load, Store, Insert, Done and
 three iterator methods ForEach, FirstThat, LastThat.

 The example program TVGUID17.PAS illustrates the use of collections for a
 client account object type, TClient, whose data fields are Account, Name
 and Phone, all of type PString.  PClient points to the object TClient,
 whose constructor requires three parameters, NewAccount, NewName and
 NewPhone, all of type string.  The NewStr function is used in this
 constructor to provide the PString types to the data fields as shown:

      Account := NewStr(NewAccount);
      Name := NewStr(NewName);
      Phone := NewStr(NewPhone);

 Similarly, in the destructor TClient.Done the DisposeStr function is used,
 as follows:         DisposeStr(Account);
                     ...

 The New function is used to allocate and initialize the collection as
 follows:

      ClientList := New(PCollection, Init(10, 5);

      pointer of type PCollection, initialized with limit of 10 and delta 5.

 One of TCollection's methods, the Insert procedure, is then used to insert
 an item into the collection.  One parameter is required, the item pointer,
 itself derived from the New function, including initialization, as follows:

 WITH ClientList^ DO
 BEGIN
   Insert(New(PClient, Init('91-100', 'Anders, Smitty', '(406) 111-2222')));
   ...
   ...

 The ForEach iterator method is used in the example program to assist in
 printing the information relating to all clients.  Essentially a procedure
 Printall, which has one parameter, a pointer C of type PCollection, is
 written with a nested procedure PrintClient, which does the actual printing
 for each client.  The main procedure then calls the nested one as follows:

      C^.ForEach(@PrintClient); {for each item in C}

 Details of the iterator methods are given on pages 141-143 of the Guide. 
 All iterators must call FAR local procedures, as explained on page 142 of
 the Guide.

 Program TVGUID18.PAS deals with sorted collections, whilst TVGUID19.PAS
 relates to string collections.

 Thus far, the items of each collection are of the same type, but it is
 possible to have items treated polymorphically.  Collections can store any
 object that is a descendant of TObject and they can be mixed.  The example
 program TVGUID20.PAS puts three different graphical objects into a
 collection.  (Note the warning in the Guide and in the program about the
 full graph save option -g, the use of the GRAPH unit and the path to the
 BGI file).

 A procedure MakeCollection, with parameter 'List', uses a pointer P to
 GraphObject types, which may be points, rectangles or circles to insert the
 objects into the collection with the statement:

      List^.Insert(P);

 This graphics collection is used in an extended version of this program,
 TVGUID21.PAS, which puts the collection on a stream to a disk file
 GRAPHICS.STM, which is then read by another program TVGUID22.PAS, as
 explained below.

 Streams.
 --------

 A Turbo Vision stream is a collection of objects directed to or from a
 file, EMS, a serial port or some other device.  The I/O transfer occurs at
 the object level rather than the data level, which is typical of a record.

 Turbo Pascal requires that files must be typed and that the type must be
 determined at compile time, but it does not allow the creation of a typed
 file of objects.

 Objects probably contain virtual methods, whose address is determined at
 run-time, so that storing the VMT information outside the program is
 pointless.  Streams provide a simple means of storing object data outside
 the program, provided the object is a descendant of TObject.

 All standard Turbo Vision objects are ready to be used with streams and all
 Turbo vision streams know about the standard objects.  New object types
 derived from one of the standard objects can easily be prepared for stream
 use and streams alerted to their existence.

 Each Turbo Vision object type is assigned a unique registration number,
 which is written to the stream ahead of the object's data.  Then when the
 object is read back from the stream, the registration number is received
 first and Turbo Vision knows how much data to read and what VMT to attach
 to it.

 Stream registration is a simple two-step process of defining a stream
 registration record which is then passed to the global procedure
 RegisterType.

 Stream registration records are of type TStreamRec, which is defined as
 follows:
                     PStreamRec = ^TStreamRec;
                     TStreamRec = RECORD
                     ObjType: Word;
                     VmtLink: Word;
                     Load: Pointer;
                     Store: Pointer;
                     Next: Word;
                     END;

 By convention, all Turbo Vision stream registration records are given the
 same name as the corresponding object type, with the initial letter 'T'
 replaced by 'R'.  Thus the registration record for TDeskTop is RDeskTop.

 The 'object type' field is a unique type-identifier number (ID), in the
 range 100-65535, assigned by the programmer (0-99 reserved for the standard
 objects).  The programmer must keep a library of ID numbers and make them
 available to users of any units.

 The 'VmtLink' field is a link to the object's virtual method table assigned
 as the offset of the type of object:

      RSomeObject.VmtLink := Ofs(TypeOf(TSomeObject)^);

 The 'Load' and 'Store' fields contain the addresses of the Load and Store
 methods of the object, respectively:

      RSomeObject.Load := @TSomeObject.Load;
      RSomeObject.Store := @TSomeObject.Store;

 The final field, 'Next', is assigned by 'RegisterType' (see below) and not
 by the programmer.  It involves an internal linked list of stream
 registration records.

 Examples of registration records for graphical objects are shown in the
 programs TVGUID21.PAS AND TVGUID22.PAS, which write a stream to disk and
 read the stream from disk, respectively.  Since the type TStreamRec is
 already defined in OBJECTS.TPU, the registration record is a record
 constant, for example:

      CONST
      RGraphPoint: TStreamRec = (
           ObjType: 150;
           VmtLink: Ofs(TypeOf(TGraphPoint)^);
           Load: @TGraphPoint.Load;
           Store: @TGraphPoint.Store;

 After the construction of the stream registration record, the standard
 procedure 'RegisterType' (p 364) is called with the record as its
 parameter.  Thus in TVGUID21.PAS there are statements like:

      RegisterType(RGraphPoint);

 The actual reading and writing of objects to the stream is handled by
 methods called Load and Store.  Each object must have these methods to be
 usable by streams, but they are not called directly.  They are called by
 the Get and Put methods of TStream (pp 296-7).

 Thus in the demonstration programs TVGUID21.PAS and TVGUID22.PAS the
 variable declarations are:

      VAR
      GraphicsList: PCollection;
      GraphicsStream: TBufStream;

 TBufStream inherits the static method 'Put' from TStream, but has its own
 Init method:

      CONSTRUCTOR Init(FileName: FNameStr; Mode, Size: Word);

 So the appropriate statements for putting the stream on disk are:

      GraphicsStream.Init('GRAPHICS.STM', stCreate, 1024);
      GraphicsStream.Put(GraphicsList);
      GraphicsStream.Done;

 Whilst for reading from the disk the statements are:

      WITH GraphicsStream DO
      BEGIN
      Init('GRAPHICS.STM', stOpen, 1024);
      GraphicsList := PCollection(Get);
      Done;
      ...
      END;


 Both the two graphics demonstration programs mentioned above contain over
 200 lines of statements, but most relate to graphical object programming
 and the part relating to streams has been sufficiently described for the
 complete understanding of these programs.

 As an exercise, the user is invited to add other graphical objects to the
 program, such as a full line and an arc and to add these to the stream.
 Another exercise could involve 'streaming' the objects of another program,
 such as TVGUID17.PAS or any other object program.


 STREAMS.TXT
 25.3.91
