Lotus 1-2-3 ADK - 123BASE.TXT

This file includes information about:
 - the LSX123Base class implemented in this ADK.
 - how to use this class in your LSXs for 1-2-3.
 - how to get at properties and methods of 1-2-3 objects.
 - memory management features of 1-2-3 ADK.
 - accessing cell data.
 - other tips.

================================================================================
Summary

All LSX classes are normally all derived from the LSXBase class.   This class provides various functionality to maintain memory, provide access to the LSX API, etc.  Following LSX Toolkit examples or using the LSX Wizard to create your LSX will produce classes that derive from LSXBase.

Classes that are designed to make use of 123 functionality can benefit by instead deriving from LSX123Base.  LSX123Base itself derives from LSXBase.   It adds functionality specifically designed to facilitate access to 123 and provide correct management of 123 resources.  This new functionality is documented below.

================================================================================
Property and Method access

Access to 1-2-3 data and functionality in your LSX is through the LSX API.  You actually send the messages to the 1-2-3 LSX Client in the same way as LotusScript does (hence you can repeat anything you do in LotusScript in your LSX).  High level methods are provided to conveniently access 123 properties and methods.  These methods are defined in LSX123BS.HPP.  They act on objects as they are passed to you by LotusScript.

The properties of objects can be accessed in a number of different ways:
 - pass the property as a basic data type to your LSX method.
 - pass a 1-2-3 object which the method uses to drill down through the
   class structure (as in LotusScript).
 - pass a 1-2-3 object and then access a property a number of levels down in the
   object structure using one of the flat properties.  These correspond more
   closely to the way that the information is stored in 1-2-3 and provide much
   quicker access to the information.
For more information about getting access to properties and methods of 1-2-3 objects look in the file cmdid.txt.

First the basic object functionality:

ObjGetProp(             // gets a property from a 1-2-3 object.
        LSCLIHANDLE&  hADT,	// the object handle
	PLSVALUE      pRet,	// pointer to LSVALUE where return will be
	LSADTPROPID   idProp );	// property ID from l123cmds.h

ObjSetProp(			// set a property on a 1-2-3 object
        LSCLIHANDLE&  hADT,	// the object handle
	PLSVALUE      pRet,	// pointer to LSVALUE where prop value is
        LSADTPROPID   idProp );	// property ID from l123cmds.h

ObjDoMethod(		// execute a method or function on 1-2-3 object
	LSCLIHANDLE&  hADT,     // the object handle
	PLSVALUE      pArgs,    // pArgs[0] = return LSVALUE
                                // pArgs[1 and more] = LSVALUEs of arguments
	LSUSHORT      nArg,     // # of arguments (+1 if function)
	LSADTMETHODID idMeth);  // method ID from l123cmds.h

These inline methods allow you to access some commonly used (and global) properties:

ObjGetParent(		// get parent object from 1-2-3 object
	LSCLIHANDLE&  hADT,	// the object handle
	PLSVALUE      pRet);	// pointer to LSVALUE where return will be

ObjGetName(			// get name from 1-2-3 object
	LSCLIHANDLE&  hADT,	// the object handle
	PLSVALUE      pRet);	// pointer to LSVALUE where return will be

ObjGetApp(			// get application object from 1-2-3 object
	LSCLIHANDLE&  hADT,	// the object handle
	PLSVALUE      pRet);	// pointer to LSVALUE where return will be

There's also a range-specific function to get it's dimensions:

GetRangeDim(            // return the dimensions of a range to a structure.
        LSCLIHANDLE&  hADT,     // the object handle
	RANGEDIM&     RangeDim);// pointer to RANGEDIM where return will be

================================================================================
Object Memory Management

Some of the functions above return 1-2-3 objects (e.g. getting a property of an object which is also an object).  These must be correctly managed to avoid memory leakage.  The same applies to strings that you get or send to LotusScript.  If you're going to be keeping an object from one call to the next, or if you're passing a 1-2-3 object back to LotusScript to be used in the script, then you should add a reference to it to prevent it from moving.  The LSX123Base class keeps a linked list of referenced values and removes any outstanding references during termination.

To create a LSVALUE that will have references removed, call the GetKeptValue() function (no parameters).  You can then access the returned LSVALUE to give it the correct 1-2-3 value.  To add a reference to the object within 1-2-3 call InitRefKeptValue() passing the LSVALUE from GetKeptValue.  This calls 1-2-3 to tell it to keep this object in memory and records the reference so it can later be removed.

If you've already been given an LSVALUE to which you want to add a reference, call the inline function KeepValue to obtain a pointer to a linked LSVALUE.  This function calls the two previous functions and makes the code more readable.

In both of these cases call ReleaseKeptValue to remove the reference and release  the LSVALUE (i.e. remove it from the list stored in the base class).  If a value obtained from GetKeptValue is to be reused DerefKeptValue can be called to remove the reference without releasing the linked LSVALUE structure.

All of these methods call the methods ObjAddRef() and ObjDropRef().  These methods work directly on 1-2-3 objects without using the features of the base class.  No record is kept and nothing will be freed in case of exception.  They shouldn't be used but it might be useful to take a look at the implementation in the file lsx123bs.cpp.

================================================================================
Cell Data Access

Some 1-2-3 functions in LotusScript were designed specifically for fast data access to the contents (but not the styles) of the cells in a range by an external function.  Functions are provided to facilitate this access and correctly manage string memory.  To manage the memory correctly you must keep track of where the cell data originated.  To aid in this there is type distinction between celldata structures obtained from 1-2-3 and those created locally.  Adherence to strict type should maintain data integrity.

All cell data is returned and stored as a CELLDATA123 or CELLDATALCL structures (they're both in fact identical).  These consist of a header, as a CELLDATAHDR, that contains the size of the range and the data follows as a C array.  The data can be returned as either an array of char* or of doubles (cast as long).

The reason for the two identical structures is to use the typing from C++ to make sure that locally allocated memory is freed locally and memory allocated by 1-2-3 is freed by 1-2-3.

Here's a summary of the implemented functions.  Consult the header file lsx123bs.hpp for full details.

These functions take advantage of the 1-2-3 LotusScript functions that copy a range to and from a CELLDATA123 (or CELLDATALCL) structure.  They are all simple shells for the LotusScript functions themselves:

GetCellValues      - takes a range and returns CELLDATA123.
FreeCellValues     - frees CELLDATA123 (so must only be used with return value
                     of GetCellValues).
SetCellValues      - sets the contents of a 1-2-3 range to the values in the
                     passed CELLDATA123 or CELLDATALCL.

These functions deal with locally created cell data:

CopyCellDataHdr    - creates a new CELLDATALCL (uninitialized array) with the
                     size and header of the CELLDATAHDR passed.
CreateCellDataHdr  - creates a new CELLDATALCL (uninitialized array) with the
                     size and header of the 1-2-3 range object passed.
FreeLocalCellData  - frees locally allocated cell data (CELLDATALCL).

These functions make it easier to access the properties of cell data and make your code more readable:

CellDataAdr        - returns a pointer to the C array containing the cell data
                     (just after the header structure).
CellDataRows       - returns the number of rows in some cell data.
CellDataCols       - returns the number of columns in some cell data.
CellDataSheets     - returns the number of sheets in some cell data.

================================================================================
Installing this class

The installation process for the 1-2-3 ADK assumes that you've already installed the LSX Toolkit.  It adds the source code for the LSX123Base class and modifies some of the make files to add them into the default build process.  If you're having problems installing this class into your LSX Toolkit then consult the file install.txt.  Note that after the 1-2-3 ADK is installed, it will be necessary to rebuild the common code for your LSX Toolkit to make sure that the 1-2-3 specific code has been compiled.

The class is implemented and defined in these two files (in the lsx\src\common directory):
 	Lsx123bs.hpp
	Lsx123bs.cpp

The following files provide 123 class and enum ids.  They are in the lsx\inc directory on the CD:
	L123cmds.h
	L123enid.h

Updated versions of L123cmds.h and L123enid.h may be available.  It is not necessary to rebuild existing LSXs with the new files.  However, constants may be defined to access new functionality in later versions of 123.  Participants in beta programs may get copies of such files with constants for functionality under development.  If such functionality is being used, be sure to obtain the final version of these files and rebuild before releasing an LSX.  These constants will not change after the release of the product for which they were developed.

================================================================================
Using this class

Only classes that will make direct use of 123 properties or methods will significantly benefit from this class.

To use the class, change the definition derivation from LSXBase to LSX123Base.  You will need to do this for all classes that will call any of the methods detailed above.  Once the inheritance has been changed the classes should work and initialize in the same way but the new methods will be available.   Obviously, it's then necessary to include lsx123bs.hpp where lsxbase.hpp is included.   Be sure to change the conditional including logic appropriately.  Read lsx123bs.hpp for specific notes.

If you've generated a skeleton LSX using the LSX wizard then it is also necessary to change the linkresp.w32 file to include the lsx123bs.obj file (just copy the line for lsxbase.obj).  This file lists the object files that are to be linked when the LSX is compiled using the do_it batch file.

================================================================================
Other tips

As you change 1-2-3 properties and run methods the changes appear immediately in 1-2-3 (i.e. before your LSX finishes).  If you're updating a lot of cell information this can be a bit disconcerting for the user.  The LotusScript property application.UpdateSheetDisplay represented by the command id TRTSESSIONPREFS_PROP_UPDATESHEETDISPLAY stops all display updates when updates are made by your LSX.  The updates will all appear when your LSX finishes and the user only sees completed updates.
