                         Shareware Centrum 1.0
                        Plugin developer guide
                          (c) Serge Sushko,
                          sushko@iname.com,
                   http://members.tripod.com/~sushko/

Contents
~~~~~~~~
1. Introduction
2. Plugin interface
    a. Overview
	b. Exported function definition
	c. Plugin data storage
3. Plugin interface: objects
	a. Overview
	b. Application object
	c. Main window object
	d. User list object
	e. User dialog object
	f. Product list object
	g. Product dialog object
	h. To do list object
	i. To do dialog object
	j. Site list object
	k. Site dialog object
	l. Parameters dialog object
	m. About dialog object
4. Database structure

1. Introduction
~~~~~~~~~~~~~~~
As a developer, you probably have came in touch in situation with new feature, when you could not decide whether to add it to your program or not. So did I; a large number of functions, absolutelly necessary to several people, are not usefull to the others, and one must be an outstanding marketer to decide whether to implement it (and make the program heavy) or not (and loose some of the potential customers). The only solution is to make your program constist of removable blocks (except the kernel, supposely), that means - to add plugin-enabling architecture.

In this document you will find:
- Common Shareware Centrum plugin interface definition, described in chapter 2a, 2b;
- Plugin data storage hints, described in chapter 2c;
- Plugin "objects" description (chapters 3.x);
- Shareware Centrum database structure description (chapters 4.x).


2. Plugin interface
~~~~~~~~~~~~~~~~~~~

2a Overview.
-----------
Shareware Centrum considers to be a plugin any file, that:
- is located in any subdirectory of the folder, specified in the "Plugin directory" key of the "[Common]" section of the currently used SC.INI initialization file;
- is being a windows dynamic linked library and named "plugin.dll";
- exports "NotifyPlugin" function, described in next chapter.
It means, by the way, that to install a plugin you need just to place it in the specified folder and restart program if necessary.

2b Exported function definition
-------------------------------
Shareware Centrum application from the plugin developer's point of view could be imagined as a set of "objects" (class instances), having "properties" (class members), "actions" (class methods), "notifications" (something similar to Delphi events or Windows messaging system) and "errors" (plugin interface error codes). All "objects", "properties", "actions", "notifications" and "errors" are identified by integer constants, defined in scPlugin.pas source file, for exaple:
	POBJECT_USER - User object (user edit dialog)
	PPROPERTY_FIRSTNAME - User first name property of POBJECT_USER or POBJECT_USERLIST objects
	PACTION_SETDATA - action, which command Shareware Centrum to write data to some property of some object
	PACTION_LOADPLUGIN - notification, sent to plugin when it is being loaded
	PERROR_READONLY - operation (probably writing data by PACTION_SETDATA action) failed because requested object or property can be accessed only for reading in current context/time.
	
All the data transfer between Shareware Centrum host application and plugin is based on two functions, QueryHost and NotifyPlugin, and is sometimes similar to windows messages mechanism. All the functions in this document are described in standard Borland Delphi terms: I have not enough C/C++ experience to define them in C-standards. But, AFAIK, standard pascal PChar datatype is ordinar C/C++ (char*), and other used datatypes are common for all windows 32-bit compilers. 

All the significant data is passed from/to the plugin in string representation, what means that string data is passed "as is", and all other types of data are converted to string representation (according to current Windows regional settings) before transfer from/to plugin.  So,
	String values are passed "as is";
	
	Integer values are being converted to string, period separator is not used;
	
	Floating point values are being converted to string according to the current windows regional settings default format, period separator is not used;
	
	Date values are being converted to string using short date format according to the current windows regional settings default format;
	
	Boolean values are being converted to string format: '1' means 'true', '0' means 'false'.
Let us consider how it works.

As it was described above, every plugin must export a NotifyPlugin function, defined as:

	procedure NotifyPlugin(iSender, iAction, iCookie : Integer);
	
This function is used by host (i.e. Shareware Centrum program) to notify the plugin about different events, happened to the program: loading/unloading plugin, opening/closing windows, loading/saving data, etc. The object, who have sent a notification, notification meaning, and, probably, additional data are stored in the function parameters:

	iSender: identifier of the object, who sent notification, f.e. main window user list, user edit dialog, application in common, etc. All object identifiers are listed in the POBJECT_* integer constants (see scPlugin for detailes);
	
	iAction: identifier of the notification, that was sent. All notification identifiers are listed in the PACTION_* integer constants (see scPlugin.pas for detailes);
	
	iCookie: this parameter is used to transfer additional data to/from the plugin and is ignored in most cases.
	
Here we'll place several examples of how NotifyPlugin is called from the application. The first one is a notification, that was sent to plugin when the user has opened a "user dialog" to create a new user or edit an existing one:

	NotifyPlugin(POBJECT_USER, PACTION_SETFOCUS, 0);
	
The second exaple shows how Shareware Centrum notifies plugins when the user has changed the value of a control in the user dialog:

	NotifyPlugin(POBJECT_USER, PACTION_CHANGED, 0);
	
Nextly, the user pressed "Save" button in the user dialog. In this case, Shareware Centrum notifies plugins two times: before and after the save routine is called:

	NotifyPlugin(POBJECT_USER, PACTION_BEFORESAVE, 0);
	//  internally saving all the data
	NotifyPlugin(POBJECT_USER, PACTION_AFTERSAVE, 0);
	
And, at least, user aquired to close the user dialog (probably by pressing "close" button or clicking the "x" button in the dialog header). The program notifies plugins that the user dialog is about to close:
	
	NotifyPlugin(POBJECT_USER, PACTION_KILLFOCUS, 0);
	
When receiving notification, plugin might ask the program to perform some actions for him: read/write data, create/destroy/change menu items, etc. All this requests are sent to the host program by calling "QueryHost" function, "exported" by the application and defined as follows:

	function  QueryHost(iObject   : Integer;
						iProperty : Integer;
						iAction   : Integer;
						pczParam  : PChar;
						iCookie   : Integer) : Integer;

As in NotifyPlugin function, the meaning of the action and the objects to be changed as a result of QueryHost call are encoded in the QueryHost parameters:

	iObject: identifies an "object" in Shareware Centrum plugin interface and can obtain values from the POBJECT_* integer constants (see scPlugin.pas for detailes);
	
	iProperty: identifies a "property" of an object in Shareware Centrum plugin interface and can obtain values from the PPROPERTY_* integer constants (see scPlugin.pas for detailes);

	iAction: identifies an "action" in Shareware Centrum plugin interface and can obtain values from the PACTION_* integer constants (see scPlugin.pas for detailes);

	pczParam: this PChar (C/C++ char*) parameter is used to transfer data from/to the application. See examples below for detailes;
	
	iCookie: as in NotifyPlugin function, this parameter is used to store additional data and is ignored in most cases;
	
The QueryHost function returns an error code after completition. All error codes returned by this function are listed in the PERROR_* integer constants (see scPlugin.pas for further detailes).
	
Let's consider how the plugin, for example, will retrieve the user first and last names from the user dialog, concatenate them and store the full user name in the "comments" field in the dialog. First al all, we retrieve first and last user names from the user dialog:

	getmem(pczFirstName, PCOMMON_MAXSTRLEN);
	getmem(pczLastName, PCOMMON_MAXSTRLEN);
	QueryHost(POBJECT_USER, PPROPERTY_FIRSTNAME, PACTION_GETDATA, pczFirstName, 0);
	QueryHost(POBJECT_USER, PPROPERTY_LASTNAME,  PACTION_GETDATA, pczLastName,  0);
	
Then, concatenating first and last user names and storing result in the pczFirstName variable by standard "strcat" function:

	strcat(pczFirstName, pczLastName);
	
and, at least, storing the full user name into the "Comments" field of the user dialog and disposing the memory allocated:

	QueryHost(POBJECT_USER, PPROPERTY_COMMENT, PACTION_SETDATA, pczFirstName, 0);
	freemem(pczFirstName, PCOMMON_MAXSTRLEN);
	freemem(pczLastName, PCOMMON_MAXSTRLEN);

For best understanding we've omited here all the error-handling actions, based on the QueryHost return codes. As you have seen, the Shareware Centrum plugin interface is rather simple and has easy-to-remember mnemonics, similar to standard OOP syntax.

Please note that you have to allocate enough memory for the pczParam parameter before using QueryHost function. We suggest to use PCOMMON_MAXSTRLEN integer constant for the size of allocation memory block: this must be enough in most data transfer routines.

2c. Plugin data storage
-----------------------
Being itself a database-maintaining application, Shareware Centrum expects that some of installed plugin will also want to maintain their own data, probably attached to existing Shareware Centrum objects such as User, Product, Site, etc. Deciding how to store his own data, plugin developer has to ways: to use "usial" or "internal" data storage.

When using "usial" way to store data, plugin uses external databases, external tables or additional fields in Shareware Centum database tables to store it's own data. Since Shareware Centrum does not know anything about this storage objects, plugin developer has to organize all data read/write/maintain routines. This "usial" way of storing plugin data seems to be obvious and, from my point of view, there is nothing to discuss here.

When using "internal" way to store plugin data, plugin developer uses special Shareware Centrum data storage fields and a special mechanism to access it's data. Nearly every Shareware Centrum database table have an additional field, named "AddInfo" (BLOB Memo type) to store plugin data, and Shareware Centrum application provide a special mechanism to access these fields.

Being a BLOB Memo field, AddInfo fields are able to store as much text information as needed, and it's logical data structure is designed in such a way that it can store several items of plugin information at one time. Here and further we shall call such "virtual fields" "AddInfo keys", and their values - "AddInfo key values". For example if there are two plugins installed and the first one, "plugin 1", wants to store AddInfo keys "date_of_birth" and "maiden_name" in Shareware Centrum User object, and the second, "plugin 2", want to store AddInfo key "sex" in Shareware Centrum User object, all this data will be successfully stored and maintained in Shareware Centrum AddInfo field of table "user" in this example.

To access this data, plugin has to call QueryHost function in standard way as it is required to access other (not AddInfo) object properties and was demonstrated above. The only difference is:

	when plugin calls QueryHost to read data from ordinary Shareware Centrum object property, such as FirstName property of the User object, Shareware Centrum ignores initial value of the pczParam parameter, using it only to transfer data from the host to the plugin:
		//  plugin source
		getmem(pczParam, PCOMMON_MAXSTRLEN);
		QueryHost(POBJECT_USER, PPROPERTY_FIRSTNAME, PACTION_GETDATA, pczParam, 0);
	and then reads user first name, placed to the pczParam parameter, and disposes memory allocated for pczParam variable;
	
	when plugin calls QueryHost to read data from AddInfo object property, Shareware Centrum expects the name of the AddInfo key in the pczParam parameter ("date_of_birth" in the example above), and places the result value in the same parameter when executed:
		//  plugin source
		getmem(pczParam, PCOMMON_MAXSTRLEN);
		strcopy(pczParam, 'date_of_birth');
		QueryHost(POBJECT_USER, PPROPERTY_ADDINFO, PACTION_GETDATA, pczParam, 0);
	and then reads user date of birth, placed to the pczParam parameter, and disposes memory allocated for pczParam variable;

	when plugin calls QueryHost to write data to the ordinary Shareware Centrum object property, such as FirstName property of the user object, Shareware Centrum ignores value of iCookie parameter:
		//  plugin source
		getmem(pczParam, PCOMMON_MAXSTRLEN);
		QueryHost(POBJECT_USER, PPROPERTY_FIRSTNAME, PACTION_GETDATA, pczParam, 0)
	and then disposes memory allocated for pczParam variable;
	
	when plugin calls QueryHost to write data to AddInfo object property, Shareware centrum expects the name of the AddInfo key in the pczParam parameter ("date_of_birth" in the example above), and the pointer to the new value of this AddInfo key, placed to iCookie parameter:
		//  plugin source
		getmem(pczKeyName,  PCOMMON_MAXSTRLEN);
		getmem(pczKeyValue, PCOMMON_MAXSTRLEN);
		strcopy(pczKeyName,  'date_of_birth');
		strcopy(pczKeyValue, '01/01/1970');
		QueryHost(POBJECT_USER, PPROPERTY_ADDINFO, PACTION_SETDATA, pczKeyName,
			Integer(Pointer(pczKeyValue)));
	and then disposes memory allocated for pczKeyName and pczKeyValue variables.
		
As we have already mentioned, all the data is passed from/to the plugin in string representation, what means that string data is passed "as is", and all other types of data are converted to string representation (according to current Windows regional settings) before transfer from/to plugin. And what about AddInfo key values?

All AddInfo key values are assumed by Shareware Centrum to be of string type, and the empty string (zero-size string) is mentioned as a value of not-existing key. If plugin aquires to read the value of absent key from the AddInfo property of one of the Shareware Centrum objects, the empty string will be returned; if plugin writes an empty string to the AddInfo key of some Shareware Centrum object, this key will be deleted; if plugin aquires to write not-empty data to the not-existing key of AddInfo property of any Shareware Centrum object, the key will be created and the value will be written. An exaple below shows a previously described "plugin 1" plugin behaviour on the newly created user record with absolutelly empty AddInfo property:

	//  plugin source - reading data from (empty) AddInfo property
	getmem(pczParam,  PCOMMON_MAXSTRLEN);
	strcopy(pczParam,  'date_of_birth');
	QueryHost(POBJECT_USER, PPROPERTY_ADDINFO, PACTION_GETDATA, pczParam, 0);
	// key does not exist; empty string is placed to the pczParam variable
	freemem(pczParam, PCOMMON_MAXSTRLEN);
		
	//  plugin source - writing data to (initially empty) AddInfo property
	getmem(pczKeyName,  PCOMMON_MAXSTRLEN);
	getmem(pczKeyValue, PCOMMON_MAXSTRLEN);
	strcopy(pczKeyName,  'date_of_birth');
	strcopy(pczKeyValue, '01/01/1970');
	QueryHost(POBJECT_USER, PPROPERTY_ADDINFO, PACTION_SETDATA, pczKeyName,
		Integer(Pointer(pczKeyValue)));
	//  key 'date_of_birth' was created and a '01/01/1970' string value was written
			

	//  plugin source - reading data from AddInfo once more
	getmem(pczParam,  PCOMMON_MAXSTRLEN);
	strcopy(pczParam,  'date_of_birth');
	QueryHost(POBJECT_USER, PPROPERTY_ADDINFO, PACTION_GETDATA, pczParam, 0);
	// '01/01/1970' string is placed by host application to the pczParam variable
	freemem(pczParam, PCOMMON_MAXSTRLEN);
		
	//  plugin source - writing empty string to AddInfo key
	getmem(pczKeyName,  PCOMMON_MAXSTRLEN);
	getmem(pczKeyValue, PCOMMON_MAXSTRLEN);
	strcopy(pczKeyName,  'date_of_birth');
	strcopy(pczKeyValue, '');
	QueryHost(POBJECT_USER, PPROPERTY_ADDINFO, PACTION_SETDATA, pczKeyName,
		Integer(Pointer(pczKeyValue)));
	//  key 'date_of_birth' was deleted because plugin requested to write empty string to it

	//  plugin source - reading data from AddInfo
	getmem(pczParam,  PCOMMON_MAXSTRLEN);
	strcopy(pczParam,  'date_of_birth');
	QueryHost(POBJECT_USER, PPROPERTY_ADDINFO, PACTION_GETDATA, pczParam, 0);
	// key does not exist; empty string is placed to the pczParam variable
	freemem(pczParam, PCOMMON_MAXSTRLEN);

3. Plugin interface: objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3.a Overview
------------
As we have mentioned in Plugin Interface Overview (chapter 2.a), plugin deleloper can think about Shareware Centrum application as about several object instances, working together. Each object has properties, actions, send notifications, is able to return error codes. All this object data (objects, properties, actions, notifications and errors) are identified by plugin by their idetifiers, integer constants, defined in scPlugin.pas source file. Here we will list all Shareware Centrum objects with their identifiers:
	POBJECT_APPLICATION  //  application in common
	POBJECT_MAINWINDOW   //  main application window
	POBJECT_PRODUCTLIST  //  product list in main window
	POBJECT_USERLIST     //  user list in main window
	POBJECT_TODOLIST     //  todo list in main window
	POBJECT_SITELIST     //  site list in main window
	POBJECT_PRODUCT      //  product window
	POBJECT_USER         //  user window
	POBJECT_TODO         //  todo window
	POBJECT_SITE         //  site window
	POBJECT_PARAMWINDOW  //  report parameters window
	POBJECT_ABOUT        //  about window
This constants can (and should) be used in iObject parameter of QueryHost function and iSender parameter of NotifyPlugin function. Let us consider each object separatelly.

3.b Application object
----------------------
An application object was designed to collect all "system-level" routines, applicapable to the Shareware Centrum in common, such as user interface language changing notification, or database tables data refresh request. The "object tree" of an Application object is shown below:
	POBJECT_APPLICATION
	  PROPERTIES
		PPROPERTY_LANGUAGE    : used to retrieve full path to current language file, 
								f.e. c:\sc\english.lng
		PPROPERTY_WORKPLACEID : used to retrieve current workplaceID for the current computer
		PPROPERTY_USERS       : returns '1' if the main window user page is visible (not
		                        hidden), '0' otherwise;
		PPROPERTY_PRODUCTS    : returns '1' if the main window products page is visible (not
		                        hidden), '0' otherwise;
		PPROPERTY_TODO        : returns '1' if the main window to do page is visible (not
		                        hidden), '0' otherwise;
		PPROPERTY_SITES       : returns '1' if the main window sites page is visible (not
		                        hidden), '0' otherwise;
		PPROPERTY_ERRORSTRING : used to retrieve an error message in current language for
		                        the error code, specified in pczParam parameter
		PPROPERTY_DBDIRECTORY : used to retrieve the current database directory
	  ACTIONS
	    PACTION_GETDATA       : used to read value of the specified property
		PACTION_REFRESHTABLES : used to force Shareware Table re-read all data tables. Can be usefull if the plugin changes database tables itself;
	  NOTIFICATIONS
	    PACTION_LOADPLUGIN    : the first notification sent to plugin when it is loaded.
		                        iCookie parameter contains pointer to the QueryHost function
		PACTION_LOADEDFROM    : is sent immediatelly after PACTION_LOADPLUGIN. iCookie parameter contains pointer to the full plugin DLL path;
		PACTION_CLOSEPLUGIN   : is sent before unloading plugin on program exit.
		PACTION_LANGCHANGED   : sent when user requested to change interface language
		PACTION_SAVESETTINGS  : sent when user requested to save interface settings
	  ERRORS
	    PERROR_SUCCESS           : operation finished successfully
		PERROR_PROPERTY_NOTEXIST : specified property does not exist

3.c Main window object
----------------------
Main window object, with POBJECT_MAINWINDOW identifier, represents the main program window. Please do not confuse main window object with user, product, to do or site list, placed on it: plugin must access these objects via their own identifiers as described in next chapters.
	POBJECT_MAINWINDOW
	  PROPERTIES
	    PPROPERTY_MENUITEM : menu modifications (see below)
	  ACTIONS
	    PACTION_SETHINT    : menu modifications (see below)
	    PACTION_SETVISIBLE : menu modifications (see below)
	    PACTION_SETENABLED : menu modifications (see below)
	    PACTION_SETCHECKED : menu modifications (see below)
	    PACTION_SETSHORTCUT: menu modifications (see below)
	  NOTIFICATIONS
	    PACTION_SETFOCUS   : sent when main window is activated
		PACTION_KILLFOCUS  : sent when main window is deactivated
	  ERRORS
	    PERROR_PROPERTY_NOTEXIST : attemption to access not-existing property
	    PERROR_SUCCESS           : operation finished successfully
		
3.d User list object
--------------------
User list object (POBJECT_USERLIST) is a table with user records on the Users main window page. While accessing User list properties plugin can read available user properties and receive notifications on activation/deactivation, row changing and some others. User list can be accessed by plugin for reading only.
	POBJECT_USERLIST
	  PROPERTIES
        PPROPERTY_WORKPLACEID  : current record workplace id
        PPROPERTY_ID           : current record id
        PPROPERTY_TITLE        : user full name
        PPROPERTY_LASTUPDATE   : when current record was updated last time
        PPROPERTY_COMMENT      : comments on current user
        PPROPERTY_ADDINFO      : AddInfo property (see above)
        PPROPERTY_COUNTRYID    : country id user is living in
        PPROPERTY_COUNTRYNAME  : country name user is living in
        PPROPERTY_FIRSTNAME    : user first name
        PPROPERTY_MIDDLENAME   : user middle name
        PPROPERTY_LASTNAME     : user last name
        PPROPERTY_COMPANY      : company the user is working in
        PPROPERTY_POSITION     : user position (appointment) in this company
        PPROPERTY_STATENAME    : state/province name user is living in
        PPROPERTY_CITY         : city name user is living in
        PPROPERTY_ZIP          : user zip or postal code
        PPROPERTY_STREET       : user street address
        PPROPERTY_POCTYPE1     : type of the primary POC
        PPROPERTY_POC1         : primary POC URL
        PPROPERTY_POCTYPE2     : type of the secondary POC
        PPROPERTY_POC2         : secondary POC URL
        PPROPERTY_POCTYPE3     : type of the third POC
        PPROPERTY_POC3         : third POC URL
        PPROPERTY_HASFOCUS     : checks whether the user list has focus
	  ACTIONS
	    PACTION_GETDATA        : read data from the property
	  NOTIFICATIONS
	    PACTION_SETFOCUS       : sent when the list is activated
		PACTION_KILLFOCUS      : sent when the list is deactivated
		PACTION_ROWCHANGED     : sent every time another row is selected
	  ERRORS
	    PERROR_SUCCESS         : operation finished successfully
	    PERROR_NOTAPPLICAPABLE : operation is not applicapable
		PERROR_PROPERTY_NOTEXIST : specified property does not exist

3.e User dialog object
----------------------
User dialog object (having identifier POBJECT_USER) represents the dialog Shareware Centrum user is working with when creating new user or changing existing user attributes. Being accessible for reading and writing both, User dialog, however, does not provide a plugin access to several "system" properties, such as WorkplaceID, ID and LastUpdate.

One more significant note: Shareware Centrum designed in such a way, that when a record is initially created, it's identifier (xxxID in common case) are set to zero, the initialized when record is being saved and never changes in future. So, you can learn whether user is dealing with new record or an existing one by aquiring the record ID and checking whether it is equal to zero.
	POBJECT_USER
	  PROPERTIES

	      properties of the user himself

        PPROPERTY_WORKPLACEID  : current record workplace id
        PPROPERTY_ID           : current record id (zero if new record)
        PPROPERTY_TITLE        : user full name
        PPROPERTY_LASTUPDATE   : when current record was updated last time
        PPROPERTY_COMMENT      : comments on current user
        PPROPERTY_ADDINFO      : AddInfo property (see above)
        PPROPERTY_COUNTRYID    : country id user is living in
        PPROPERTY_COUNTRYNAME  : country name user is living in
        PPROPERTY_FIRSTNAME    : user first name
        PPROPERTY_MIDDLENAME   : user middle name
        PPROPERTY_LASTNAME     : user last name
        PPROPERTY_COMPANY      : company the user is working in
        PPROPERTY_POSITION     : user position (appointment) in this company
        PPROPERTY_STATENAME    : state/province name user is living in
        PPROPERTY_CITY         : city name user is living in
        PPROPERTY_ZIP          : user zip or postal code
        PPROPERTY_STREET       : user street address
        PPROPERTY_POCTYPE1     : type of the primary POC
        PPROPERTY_POC1         : primary POC URL
        PPROPERTY_POCTYPE2     : type of the secondary POC
        PPROPERTY_POC2         : secondary POC URL
        PPROPERTY_POCTYPE3     : type of the third POC
        PPROPERTY_POC3         : third POC URL
        PPROPERTY_HASFOCUS     : checks whether the user list has focus

		  properties of purchased products: purchases, already added to the list

        PPROPERTY_PRODUCTWORKPLACEID   	+ PMASK_OLDITEM	: Product workplace id
        PPROPERTY_PRODUCTID            	+ PMASK_OLDITEM	: Product id
        PPROPERTY_PRODUCTTITLE         	+ PMASK_OLDITEM	: Product title
        PPROPERTY_VERSIONWORKPLACEID   	+ PMASK_OLDITEM	: Version workplace id
        PPROPERTY_VERSIONID            	+ PMASK_OLDITEM	: Version id
        PPROPERTY_VERSIONNUMBER        	+ PMASK_OLDITEM	: Version number
        PPROPERTY_TYPE                 	+ PMASK_OLDITEM	: Purchase type
        PPROPERTY_QTY                  	+ PMASK_OLDITEM	: Number of licenses purchased
        PPROPERTY_PRICE                	+ PMASK_OLDITEM	: Product price
        PPROPERTY_PAYED                	+ PMASK_OLDITEM	: Amount of money payed
        PPROPERTY_PURCHASEDON          	+ PMASK_OLDITEM	: date of purchase
        PPROPERTY_PAYMETHODWORKPLACEID 	+ PMASK_OLDITEM	: payment method workplace id
        PPROPERTY_PAYMETHODID          	+ PMASK_OLDITEM	: payment method id
        PPROPERTY_PAYMETHODNAME        	+ PMASK_OLDITEM	: payment method name
        PPROPERTY_REGNUMBER            	+ PMASK_OLDITEM	: registration number
        PPROPERTY_ORDERID              	+ PMASK_OLDITEM	: order/invoice id
        PPROPERTY_FOUNDWORKPLACEID     	+ PMASK_OLDITEM	: "found on" workplace id
        PPROPERTY_FOUNDID              	+ PMASK_OLDITEM	: "found on" id
        PPROPERTY_FOUNDNAME            	+ PMASK_OLDITEM	: "found on" name
        PPROPERTY_DLOADEDWORKPLACEID   	+ PMASK_OLDITEM	: "downloaded from" workplace id
        PPROPERTY_DLOADEDID            	+ PMASK_OLDITEM	: "downloaded from" id
        PPROPERTY_DLOADEDNAME          	+ PMASK_OLDITEM	: "downloaded from" name
        PPROPERTY_REGISTEREDWORKPLACEID	+ PMASK_OLDITEM	: "registered with" workplace id
        PPROPERTY_REGISTEREDID         	+ PMASK_OLDITEM	: "registered with" id
        PPROPERTY_REGISTEREDNAME       	+ PMASK_OLDITEM	: "registered with" name
        PPROPERTY_COMMENT              	+ PMASK_OLDITEM	: purchase comments

		  properties of purchased products: new purchases, not added to the list
		  (i.e. values of controls on the purchase page control on the dialog)

        PPROPERTY_PRODUCTWORKPLACEID   	+ PMASK_NEWITEM	: Product workplace id
        PPROPERTY_PRODUCTID            	+ PMASK_NEWITEM	: Product id
        PPROPERTY_PRODUCTTITLE         	+ PMASK_NEWITEM	: Product title
        PPROPERTY_VERSIONWORKPLACEID   	+ PMASK_NEWITEM	: Version workplace id
        PPROPERTY_VERSIONID            	+ PMASK_NEWITEM	: Version id
        PPROPERTY_VERSIONNUMBER        	+ PMASK_NEWITEM	: Version number
        PPROPERTY_TYPE                 	+ PMASK_NEWITEM	: Purchase type
        PPROPERTY_QTY                  	+ PMASK_NEWITEM	: Number of licenses purchased
        PPROPERTY_PRICE                	+ PMASK_NEWITEM	: Product price
        PPROPERTY_PAYED                	+ PMASK_NEWITEM	: Amount of money payed
        PPROPERTY_PURCHASEDON          	+ PMASK_NEWITEM	: date of purchase
        PPROPERTY_PAYMETHODWORKPLACEID 	+ PMASK_NEWITEM	: payment method workplace id
        PPROPERTY_PAYMETHODID          	+ PMASK_NEWITEM	: payment method id
        PPROPERTY_PAYMETHODNAME        	+ PMASK_NEWITEM	: payment method name
        PPROPERTY_REGNUMBER            	+ PMASK_NEWITEM	: registration number
        PPROPERTY_ORDERID              	+ PMASK_NEWITEM	: order/invoice id
        PPROPERTY_FOUNDWORKPLACEID     	+ PMASK_NEWITEM	: "found on" workplace id
        PPROPERTY_FOUNDID              	+ PMASK_NEWITEM	: "found on" id
        PPROPERTY_FOUNDNAME            	+ PMASK_NEWITEM	: "found on" name
        PPROPERTY_DLOADEDWORKPLACEID   	+ PMASK_NEWITEM	: "downloaded from" workplace id
        PPROPERTY_DLOADEDID            	+ PMASK_NEWITEM	: "downloaded from" id
        PPROPERTY_DLOADEDNAME          	+ PMASK_NEWITEM	: "downloaded from" name
        PPROPERTY_REGISTEREDWORKPLACEID	+ PMASK_NEWITEM	: "registered with" workplace id
        PPROPERTY_REGISTEREDID         	+ PMASK_NEWITEM	: "registered with" id
        PPROPERTY_REGISTEREDNAME       	+ PMASK_NEWITEM	: "registered with" name
        PPROPERTY_COMMENT              	+ PMASK_NEWITEM	: purchase comments
	  ACTIONS
	    PACTION_GETDATA        : read data from the property
	    PACTION_SETDATA        : write data to  the property
	  NOTIFICATIONS
	    PACTION_SETFOCUS       : sent when the list is activated
		PACTION_KILLFOCUS      : sent when the list is deactivated
		PACTION_ROWCHANGED     : sent every time another row is selected
		PACTION_CHANGED        : sent every time user property value has changed
		PACTION_BEFORESAVE     : sent before save routine will be called
		PACTION_AFTERSAVE      : sent after save routine has finished
	  ERRORS
	    PERROR_SUCCESS           : operation finished successfully
	    PERROR_NOTAPPLICAPABLE   : operation is not applicapable
		PERROR_PROPERTY_NOTEXIST : specified property does not exist
		PERROR_NOCURRENTITEM     : no listbox item was selected (listbox empty?)
		PERROR_READONLY          : property can be accessed only for reading

3.f Product list object
-----------------------
Product list object (POBJECT_PRODUCTLIST) is a table with product records on the Products main window page. While accessing product list properties plugin can read available properties and receive notifications on activation/deactivation, row changing and some others. Product list can be accessed by plugin for reading only.

	POBJECT_PRODUCTLIST
	  PROPERTIES
        PPROPERTY_WORKPLACEID  : current record workplace id
        PPROPERTY_ID           : current record id
        PPROPERTY_TITLE        : product title
        PPROPERTY_PRODUCTTITLE : same as previous
        PPROPERTY_LASTUPDATE   : when current record was updated last time
        PPROPERTY_COMMENT      : comments on current product
        PPROPERTY_ADDINFO      : AddInfo property (see above)
        PPROPERTY_HASFOCUS     : checks whether the product list has focus
	  ACTIONS
	    PACTION_GETDATA        : read data from the property
	  NOTIFICATIONS
	    PACTION_SETFOCUS       : sent when the list is activated
		PACTION_KILLFOCUS      : sent when the list is deactivated
		PACTION_ROWCHANGED     : sent every time another row is selected
	  ERRORS
	    PERROR_SUCCESS         : operation finished successfully
	    PERROR_NOTAPPLICAPABLE : operation is not applicapable
		PERROR_PROPERTY_NOTEXIST : specified property does not exist

3.g Product dialog object
-------------------------
Product dialog object (having identifier POBJECT_PRODUCT) represents the dialog Shareware Centrum user is working with when creating new product or changing existing product attributes. Being accessible for reading and writing both, Product dialog, however, does not provide a plugin access to several "system" properties, such as WorkplaceID, ID and LastUpdate.

	POBJECT_PRODUCT
	  PROPERTIES

	      properties of the product itself

        PPROPERTY_WORKPLACEID  : current record workplace id
        PPROPERTY_ID           : current record id
        PPROPERTY_TITLE        : product title
        PPROPERTY_PRODUCTTITLE : same as previous
        PPROPERTY_LASTUPDATE   : when current record was updated last time
        PPROPERTY_COMMENT      : comments on current product
        PPROPERTY_ADDINFO      : AddInfo property (see above)
        PPROPERTY_HASFOCUS     : checks whether the product list has focus

		  Properties of version, already added to the version list
		
        PPROPERTY_WORKPLACEID        + PMASK_VERSION + PMASK_OLDITEM : version workplace id
        PPROPERTY_VERSIONWORKPLACEID + PMASK_VERSION + PMASK_OLDITEM : same as above
        PPROPERTY_ID                 + PMASK_VERSION + PMASK_OLDITEM : version id
        PPROPERTY_VERSIONID          + PMASK_VERSION + PMASK_OLDITEM : same as above
        PPROPERTY_VERSIONNUMBER      + PMASK_VERSION + PMASK_OLDITEM : version number
        PPROPERTY_SUBVERSION         + PMASK_VERSION + PMASK_OLDITEM : subversion (alpha/beta/gamma/release candidate/release)
        PPROPERTY_ADDINFO            + PMASK_VERSION + PMASK_OLDITEM : AddInfo property
        PPROPERTY_COUNT              + PMASK_VERSION + PMASK_OLDITEM : Version count
        PPROPERTY_CURRITEM           + PMASK_VERSION + PMASK_OLDITEM : Number of current item
        PPROPERTY_RELEASEDATE        + PMASK_VERSION + PMASK_OLDITEM : Version release date
        PPROPERTY_STATE              + PMASK_VERSION + PMASK_OLDITEM : Version status (freeware, free beta, shareware, commercial)
        PPROPERTY_PRICE              + PMASK_VERSION + PMASK_OLDITEM : Version price
        PPROPERTY_COMMENT            + PMASK_VERSION + PMASK_OLDITEM : Version comments

		  Properties of a new version, i.e. values of controls, placed on the "General"
		  page of the version page control on the product dialog
		
        PPROPERTY_VERSIONNUMBER      + PMASK_VERSION + PMASK_NEWITEM : version number
        PPROPERTY_SUBVERSION         + PMASK_VERSION + PMASK_NEWITEM : subversion (alpha/beta/gamma/release candidate/release)
        PPROPERTY_RELEASEDATE        + PMASK_VERSION + PMASK_NEWITEM : Version release date
        PPROPERTY_STATE              + PMASK_VERSION + PMASK_NEWITEM : Version status (freeware, free beta, shareware, commercial)
        PPROPERTY_PRICE              + PMASK_VERSION + PMASK_NEWITEM : Version price
        PPROPERTY_COMMENT            + PMASK_VERSION + PMASK_NEWITEM : Version comments
		
		  Properties of the shareware archive, the current version was uploaded to
        		  
      ACTIONS
	    PACTION_GETDATA        : read data from the property
	    PACTION_SETDATA        : write data to  the property
	  NOTIFICATIONS
	    PACTION_SETFOCUS       : sent when the list is activated
		PACTION_KILLFOCUS      : sent when the list is deactivated
		PACTION_ROWCHANGED     : sent every time another row is selected
		PACTION_CHANGED        : sent every time any property value has changed
		PACTION_BEFORESAVE     : sent before save routine will be called
		PACTION_AFTERSAVE      : sent after save routine has finished
	  ERRORS
	    PERROR_SUCCESS           : operation finished successfully
	    PERROR_NOTAPPLICAPABLE   : operation is not applicapable
		PERROR_PROPERTY_NOTEXIST : specified property does not exist
		PERROR_NOCURRENTITEM     : no listbox item was selected (listbox empty?)
		PERROR_READONLY          : property can be accessed only for reading

3.h Todo list object
-------------------------
Todo list object (POBJECT_TODOLIST) is a table with "to do" records on the Todo main window page. While accessing todo list properties plugin can read available properties and receive notifications on activation/deactivation, row changing and some others. Todo list can be accessed by plugin for reading only.

	POBJECT_TODOLIST
	  PROPERTIES
        PPROPERTY_WORKPLACEID         : current record workplace id
        PPROPERTY_ID                  : current record id
        PPROPERTY_TITLE               : product title
        PPROPERTY_LASTUPDATE          : when current record was updated last time
        PPROPERTY_COMMENT             : comments on current product
        PPROPERTY_ADDINFO             : AddInfo property (see above)
        PPROPERTY_HASFOCUS            : checks whether the product list has focus
        PPROPERTY_PRODUCTTITLE        : title of the product
        PPROPERTY_TYPE                : todo type
        PPROPERTY_VERSIONWORKPLACEID  : version workplace id
        PPROPERTY_VERSIONID           : version id
        PPROPERTY_STATE               : todo state
        PPROPERTY_PRIORITY            : todo priority
        PPROPERTY_REPORTEDWORKPLACEID : workplace id of the user, reported the bug
        PPROPERTY_REPORTEDID          : id of the user, reported the bug
        PPROPERTY_REPORTEDNAME        : full name of the user, reported the bug
        PPROPERTY_REPORTEDON          : date of bug report
        PPROPERTY_FIXEDWORKPLACEID    : workplace id of the user, fixed the bug
        PPROPERTY_FIXEDID             : id of the user, fixed the bug
        PPROPERTY_FIXEDNAME           : full name of the user, fixed the bug
        PPROPERTY_FIXEDON             : date of bug fix
        PPROPERTY_VERIFIEDWORKPLACEID : workplace id of the user, verified the bug
        PPROPERTY_VERIFIEDID          : id of the user, verified the bug
        PPROPERTY_VERIFIEDNAME        : full name of the user, verified the bug
        PPROPERTY_VERIFIEDON          : date of bug verification
        PPROPERTY_VERSIONNUMBER       : number of product version todo is applied to
	  ACTIONS
	    PACTION_GETDATA               : read data from the property
	  NOTIFICATIONS
	    PACTION_SETFOCUS              : sent when the list is activated
		PACTION_KILLFOCUS             : sent when the list is deactivated
		PACTION_ROWCHANGED            : sent every time another row is selected
	  ERRORS
	    PERROR_SUCCESS                : operation finished successfully
	    PERROR_NOTAPPLICAPABLE        : operation is not applicapable
		PERROR_PROPERTY_NOTEXIST      : specified property does not exist

3.i Todo dialog object
-------------------------
To do dialog object (having identifier POBJECT_TODO) represents the dialog Shareware Centrum user is working with when creating/recording new bug, suggestion or to do for existing product version or changing existing record attributes. Being accessible for reading and writing both, Todo dialog, however, does not provide a plugin access to several "system" properties, such as WorkplaceID, ID and LastUpdate.

	POBJECT_TODO
	  PROPERTIES
        PPROPERTY_WORKPLACEID         : current record workplace id
        PPROPERTY_ID                  : current record id
        PPROPERTY_TITLE               : to do title
        PPROPERTY_PRODUCTTITLE        : same as previous
        PPROPERTY_LASTUPDATE          : when current record was updated last time
        PPROPERTY_COMMENT             : comments on current product
        PPROPERTY_ADDINFO             : AddInfo property (see above)
        PPROPERTY_HASFOCUS            : checks whether the product list has focus
        PPROPERTY_TYPE                : todo type
        PPROPERTY_STATE               : todo state
        PPROPERTY_PRIORITY            : todo priority
        PPROPERTY_REPORTEDWORKPLACEID : workplace id of the user, reported the bug
        PPROPERTY_REPORTEDID          : id of the user, reported the bug
        PPROPERTY_REPORTEDNAME        : full name of the user, reported the bug
        PPROPERTY_REPORTEDON          : date of bug report
        PPROPERTY_FIXEDWORKPLACEID    : workplace id of the user, fixed the bug
        PPROPERTY_FIXEDID             : id of the user, fixed the bug
        PPROPERTY_FIXEDNAME           : full name of the user, fixed the bug
        PPROPERTY_FIXEDON             : date of bug fix
        PPROPERTY_VERIFIEDWORKPLACEID : workplace id of the user, verified the bug
        PPROPERTY_VERIFIEDID          : id of the user, verified the bug
        PPROPERTY_VERIFIEDNAME        : full name of the user, verified the bug
        PPROPERTY_VERIFIEDON          : date of bug verification
        PPROPERTY_VERSIONNUMBER       : number of product version todo is applied to
      ACTIONS
	    PACTION_GETDATA        : read data from the property
	    PACTION_SETDATA        : write data to  the property
	  NOTIFICATIONS
	    PACTION_SETFOCUS       : sent when the list is activated
		PACTION_KILLFOCUS      : sent when the list is deactivated
		PACTION_ROWCHANGED     : sent every time another row is selected
		PACTION_CHANGED        : sent every time any property value has changed
		PACTION_BEFORESAVE     : sent before save routine will be called
		PACTION_AFTERSAVE      : sent after save routine has finished
	  ERRORS
	    PERROR_SUCCESS           : operation finished successfully
	    PERROR_NOTAPPLICAPABLE   : operation is not applicapable
		PERROR_PROPERTY_NOTEXIST : specified property does not exist
		PERROR_READONLY          : property can be accessed only for reading
