Palm Conduit for Delphi Beta v0.1



This is the first beta release of a set of VCL components and Delphi classes to enable Palm conduits to be developed in Delphi. In this release, the components will only function while Delphi is running. The product includes Delphi translations of the Sync Manager, Hot Sync Log, and Conduit API functions, all of which will be available in the source code of the release version. Any feedback is welcome, including, but not limited to : Please send all communications to jim.cooper@virgin.net

Updates will be available from Tabdee Ltd website.


Warning : Use this product at your own risk, as it may not be completely stable. Ensure that you have secure backups of all critical data on your Palm using something like BackupBuddy before starting to develop your conduit by any method. I speak from experience!

It is assumed that you will use these components along with the documentation in the CDK. If you don't understand something in this documentation, then that should be your first reference. You may also find the book Palm Programming, The Developer's Guide by Rhodes and McKeehan useful.

This product supports the CDK v3 and upwards, and is designed for use in Delphi 5. It may work in earlier 32-bit versions of Delphi, but it hasn't been tested (and in any case you would need the source code version).



How does it work?

All Palm conduits are dlls called by the HotSync application. These dlls have the following set of possible entry points :
  1. CfgConduit

  2. Newer version of ConfigureConduit. If it does not exist, the HotSync Manager calls ConfigureConduit.
  3. ConfigureConduit

  4. Called by the HotSync Manager when the user tries to change the conduit setup.
  5. ConfigureSubscription

  6. Called by the file-linking dll.
  7. GetConduitInfo

  8. Returns information about your conduit.
  9. GetConduitName

  10. Called whenever the HotSync manager needs the conduit's name.
  11. GetConduitVersion

  12. Called to retrieve the version number of your conduit.
  13. ImportData

  14. Called when importing data if using file-linking.
  15. OpenConduit

  16. Called to perform the synchronisation of data.
  17. SubscriptionSupported

  18. Called to determine if file-linking supported.
The Palm Conduit for Delphi implements ConfigureConduit, GetConduitInfo, GetConduitName, GetConduitVersion and OpenConduit. Of these, you will be able to override the default behaviour for ConfigureConduit and OpenConduit.

OpenConduit is the most critical entry point, as this is where the actual synchronisation code must be.

The product does not implement the CfgConduit entry point; it is left for your use, should you need it.

In order to make life a little easier, much of the Sync Manager API has been encapsulated in 2 components, modelled on Delphi's TDatabase and TDataset components. Note : These controls are not descendants of these components. You cannot connect the TtabdConduitDb to any data-aware controls, for instance. This is not really a problem as there should be no user interaction during a syncing operation (the user may be connecting over a modem, for instance, and unable to see the PC screen). If there is sufficient demand, this may change in future versions.


Installation

Unpack the zip file into a suitable directory, keeping the directory structure.
Add the TabdPalmConduit.dcu file to a package of your choice.


Creating a conduit.

1. Open a new project to create a dll.
2. Add a data module to the project (you should not normally create any forms).
3. Drop a TtabdConduit onto the data module and set the relevant properties.
4. Drop a TtabdConduitDb onto the data module and set the relevant properties (database name, fields etc).
5. Add an event handler for the TtabdConduit.OnOpenConduit event. You do not need to add the SyncStarted, SyncAborted or SyncFinished type HotSync log messages, as they are sent automatically.
6. Optionally deal with the OnConfigureConduit event.
7. Compile the dll, ensuring that the HotSync manager can find the target.
8. Test.



Not what you're looking for?

This is not the only way of writing conduits in Delphi. You can also try :
EHAND Connect, an excellent ActiveX control.
ConduitDB, another Delphi control.



The components


TtabdConduit

This component controls the conduit. There can only be one instance of a TtabdConduit in your dll.

Methods

constructor Create(AOwner : TComponent);
destructor Destroy;
The usual component constructor and destructor.

procedure AddLogEntry(const Msg : string);
Adds an entry to the HotSync log.

procedure YieldCycles(MaxMilliSecs : WORD);
Wrapper for the SyncYieldCycles function.

procedure TestSyncApi(const ErrorMsg : string;ReturnValue : Integer);
Calls to Sync Manager API functions should se this procedure to test the results. It will convert error numbers into Delphi exceptions


Properties

ConduitHandle : TCondHandle
Read only. Supplies a conduit handle that can be used in Sync Manager API calls.

ConduitVersion : DWord
Read only. Returns the complete conduit version number, derived from the MajorVersion and MinorVersion properties.

ApiMajorVersion : DWord
Read only. Returns the HotSync API major version number.

ApiMinorVersion : DWord
Read only. Returns the HotSync API minor version number.

PathName : string
LocalName : string
UserName : string
Registry : string
RootKey : HKEY
All read only. Correspond to members of CSyncProperties (see CDK docs).

ConduitName : string
Conduit name as displayed and used by HotSync Manager.

DefaultAction : TSyncTypes
Default type of hotsync. Can be one of :
stFast,stSlow,stHHtoPC,stPCtoHH,stInstall,stBackup,stDoNothing, stProfileInstall

MajorVersion : Byte
Conduit (ie your dll) major version number.

MinorVersion : Byte
Conduit (ie your dll) minor version number.


Events

OnOpenConduit
The most important event. The handler for this event does all the syncing.

OnConfigureConduit
Add ahandler for this event to override the default conduit configuration. Alternatively, you could implement the CfgConduit entry point.



TtabdConduitDb

This component provides access to a database on the Palm. Note : Only one Palm database can be open at a time. This is a limitation imposed by the CDK. However, the types of Palm databases that can be synchronised are small by comparison with normal PC memory, so you could easily read entire databases into memory, if needed.

Currently this component only works with record databases, not resource databases. This may change in future if there is any demand.

Methods

constructor Create(AOwner : TComponent);
destructor Destroy;
The usual component constructor and destructor.

procedure Open;
procedure Close;
Methods to control opening and closing the database. Remember that only one can be open at a time.

procedure ReadAppInfo;
procedure ReadSortInfo;
Methods to read AppInfo and SortInfo blocks so that they are accessible from the AppInfoFields and SortInfoFields properties.

procedure WriteAppInfo;
procedure WriteSortInfo;
Methods to read from the AppInfoFields and SortInfoFields properties and save the information back into the AppInfo and SortInfo blocks.

procedure First;
procedure Next;
procedure Prior;
procedure Last;
Methods to move through the database. Similar to those in a TDataset.

procedure PurgeAllRecords;
procedure PurgeAllRecordsInCategory(CatId : SmallInt);
procedure PurgeDeletedRecords;
Methods to purge records. They correspond to the Sync Manager API functions of the same names. The Palm documentation suggests that PurgeAllRecordsInCategory should not be called while iterating through the database.

procedure Find(RecId : DWORD);
Searches for a record with the given id.

procedure Append;
procedure Edit;
procedure Post;
procedure Cancel;
procedure Delete;
Similar to TDataset methods. There is no way to guarantee where Append will add the new record (see the CDK docs for more information).

procedure AddField(const AName : string;ADataType : TtabdPalmFieldType;ASize : Integer);
A way to programmatically define members of the Fields property. Usually you would do this visually with the property editor. Available data types are :
pftUnknown,pftByte,pftSmallint,pftLongint,pftBoolean,pftSingle,pftDouble, pftDate,pftTime,pftString,pftBlob

pftSmallint is 16 bits, pftLongint is 32-bits. pftDate and pftTime use the Palm date and time formats (see the CDK for details).

ASize is ignored except for pftString and pftByte types. You should set the set to 0 if they are variable length fields (eg like the Address Book fields).

function FieldByName(const FieldName : string) : TtabdPalmField;
Similar to the TDataset function of the same name.

procedure Reset;
procedure NextInCategory;
procedure NextModified;
procedure NextModifiedInCategory;
These methods correspond to the Palm iteration functions of the same names. Palm advise not to modify the database while performing these iterations. You must also call Reset before any of the other methods.

function DebugRawRecAsStr : string; function DebugAppInfoAsStr : string; function DebugSortInfoAsStr : string;
Methods to help when debugging. They return the record, AppInfo block and SortInfo blocks as strings. Any null characters are replaced by '0' and any unprintable characters by '*'.


Properties

FileHandle : Byte
Read only. Returns a file handle that can be used in Sync Manager API calls.

Active : Boolean
Same as the TDataset property of the same name.

RecordCount : Word
Read only. Returns the number of records in the database.

CurrentRecordNum : Integer
The current record number in the database. Changing this moves the cursor. The first record is 0.

Eof : Boolean
Read only. Returns True if at the end of the database.

Bof : Boolean
Read only. Returns True if at the beginning of the database.

State : TtabdPalmDbState
Read only. Returns the database state. Can be one of :
pdsInactive,pdsBrowse,pdsAppend,pdsEdit

Attributes : Byte Read only. The attributes of the current record. These values are allowed :
sraRecAttrDeleted, sraRecAttrDirty, sraRecAttrBusy, sraRecAttrSecret, sraRecAttrArchived
The are combined with the or operator (so you need to use and to test for them).

property CategoryId : SmallInt
Category of the current record. Also used to define the category for Palm iteration functions.

property CurrentRecord : PByte
The current record as an array of bytes (the property is a pointer of type PByte). Usually you should access the record via the Fields property.

property RecordSize : DWord
Read only. Size of current record (Palm records are not necessarily of a fixed size). Currently the maximum size is 65536 bytes (ie 216).

property AppInfoBlock : PByte
The AppInfo block as an array of bytes. Usually you should access the block via the AppInfoFields property.

property AppInfoSize : Word
Read only. Size of the AppInfo block.

property SortInfoBlock : PByte
The SortInfo block as an array of bytes. Usually you should access the block via the SortInfoFields property.

property SortInfoSize : Word
Read only. Size of the SortInfo block.

property FileName : string
The database name on the Palm. Note that these are case sensitive.

property CardNum : Byte
Memory card number. Normally set to 0.

property OpenMode : Byte
Database opening mode. The following flags should be combined with the or operator :
omDbShowSecret, omDbExclusive, omDbWrite, omDbRead
The default is omDbWrite or omDbRead or omDbExclusive

property Fields : TtabdPalmFields
Record field definitions and values of the current record. See TtabdPalmField for more information.

property AppInfoFields : TtabdPalmFields
AppInfo block field definitions and values. Also uses TtabdPalmFields.

property SortInfoFields : TtabdPalmFields
AppInfo block field definitions and values. Also uses TtabdPalmFields.


Events

property OnTestFieldExistsForRead
property OnTestFieldExistsForWrite

Some databases do not include a field in a record if that field is empty. For instance, the Address Book string fields are included or not depending on values in the Flags field. Respond to these events to check whether a field should be read, or to set the flag to say whether it does or not when writing a record back to the Palm. See the demo for an example.

property BeforeOpen
property AfterOpen
property BeforeClose
property AfterClose
property BeforeAppend
property AfterAppend
property BeforeEdit
property AfterEdit
property BeforePost
property AfterPost
property BeforeCancel
property AfterCancel
property BeforeDelete
property AfterDelete
property OnNewRecord

Database state change events similar to those in TDatasets.



EtabdConduitError

Class of exception raised by the Palm Conduit for Delphi classes. Same as a normal exception, but with the addition of an error number property, which corresponds to those in the CDK. Also adds a HotSync log entry consisting of the error message. Usually raised by the TestSyncApi method.


constructor CreateError(const Msg : string;ErrorNum : Integer);
property ConduitError : Integer;



TtabdPalmFields

A collection of TtabdPalmField objects. Used for the Fields, AppInfoFields and SortInfoFields properties of TtabdConduitDB components.
It has the overridden Add function and Items property common to all TCollection decendants.



TtabdPalmField

Like a simplified version of the normal TField objects. However, there is only one class for all field types, and they do not connect to data-aware controls.


Methods

constructor Create(Collection : TCollection);
Normal overridden TCollectionItem constructor. You should not normally need to call this directly.

procedure Assign(Source : TPersistent);
Normal overridden TCollectionItem Assign method.


Properties

property ArraySize : Integer
Some fields might actually be arrays (eg the list of categories in an AppInfo block). This field is set to the number of elements in the array. It defaults to 1, ie just a normal single valued field.

property ArrayValue[Index : Integer] : Variant
Used to get and set the value of an array field. ArrayValue[0] is equivalent to using the Value property.

property FieldName : string
Field name. Used by the FieldByName method of TtabdConduitDb components.

property DataType : TtabdPalmFieldType
Field data type. Can be one of :
pftUnknown,pftByte,pftSmallint,pftLongint,pftBoolean,pftSingle,pftDouble, pftDate,pftTime,pftString,pftBlob

pftSmallint is 16 bits, pftLongint is 32-bits. pftDate and pftTime use the Palm date and time formats (see the CDK for details).

property Size : Integer
Size of the field. It is ignored except for pftString and pftByte types. You should set the size to 0 if they are variable length fields (eg like the Address Book fields).

property Value : Variant
Value of the field as a variant. For a pftBlob this is a pointer into an array of bytes.

property AsInteger : Integer
Get and set the field value as an integer. Only applies field with relevant data types.

property AsDateTime : TDateTime
Get and set the field value as a Delphi TDateTime onject. Only applies field with relevant data types.