Data Structure

Top  Previous  Next

Here is a general description of the architecture and concept of the RTF engine, for your reference.

Please read this carefully! This knowledge is necessary for you to understand WPTools Version 9.

 

The architecture of WPTools was created to support the separation between data and display.

 

So, on the one hand there are the data storage object, on the other hand the display and edit logic which uses the data storage object. It is possible that multiple editors work with the same data object and display the text at different zoom levels. It is also possible to just have one editor which is using one of a set of data objects.

This make some elegant solutions possible - ie. create MDI editor without using MDI windows! (See demo DynAssign)

 

Since not all details are listed here, please look for further information on the classes written in bold in the online help (reference).

 

In the WPTools RTF-Engine (we always refer to the 'RTF-Engine', however this does not mean that the engine is limited to the Rich-Text, *.RTF), a text is split up into several parts. The main parts are stored in two objects which are linked together:

 

a) RTF Data is stored in the TWPRTFDataCollection (see:Multiple Editors for the Same Text)

b) RTF properties, such as paragraph or number styles, are stored in the TWPRTFProps object. (see: Share Styles between TWPRichText)

 

    Datastructures

 

Note: This concept allows multiple TWPRTFDataCollection objects to share the same TWPRTFProps object. Thus, they share the same attribute identifier (such as index values for colors). If you use this feature you can simply copy texts parts between RTFData objects or compare text.

 

The TWPRTFDataCollection also hosts the text cursor (TWPRTFDataCursor) and a few parameters which are shared by the RTF editors (TWPRTFDataCollectionEngineParams). This means that even if you have several editors using one TWPRTFDataCollection there is only one cursor which is the same for all editors attached. The cursor object also controls text selection and changing properties of the selected text (SelectedTextAttr : TWPSelectedTextAttrInterface) or the current writing mode (CurrentCharAttr : TWPCursorCharAttrInterface). It also contains the CPAttr (TWPTAttrEmulator) interface which changes the attribute at the cursor position. (Please see last inheritance chart and "Character Attributes" below)

 

The TWPRTFDataCollection is home to the TWPRTFDataBlock collection items. Such an item contains the text which is displayed. The text body and the header or footer texts are all different collection items. When a new text is loaded, it is first loaded into a new TWPRtfDataBlock and, if everything is all right, then inserted into the body. The editor can display any of the RTFDataBlocks, or even display several at once.

 

The TWPRTFDataBlock contains the text within a nested list of TParagraph objects. The TParagraph objects are linked using the references NextPar/PrevPar and for nested dependencies, ChildPar/ParentPar references.

 

Note: WPTools 4 only supported linking in one level using next/prev pointers. The new TParagraph object contains functions to emulate these pointers. Using this function it is still very easy to create a loop which checks all paragraphs in a text. The first paragraph is referenced by the property FirstPar.

 

The TParagraph class inherits the complete functionality of the TWPTextStyle class which contains the code to maintain attributes and tab stops. The TWPTextStyle class is also used by other classes which need this functionality.

clip0001

 

How does TParagraph store the text?

 

The text is separated into characters, character attributes and objects. Each of these elements is stored in its own dynamic array. For the characters an array of WideChar is used, the character attributes are stored in an array of cardinal (double word) values. When objects are used, you can read the TWPTextObject for a certain position in the paragraph using the array ObjectRef. The count of elements is stored in the variable CharCount.

 

Note:

The TParagraph class has several functions to insert and delete text and objects.

 

In the instance that it is part of a table, TParagraph also has functions to find other parts of the same table (rows, cells or the parent table object). The memory architecture of a table is very similar to the system used by HTML:

 

  clip0016

 

(All rows of a table and all cells of one row are connected using NextPar/PrevPar, the levels are created using ChildPar/ParentPar.)

 

There are also useful properties which provide reference to the parent row or the parent table of a cell, or, for cells which are in a nested table (= table in a table cell), to get the first level ("ParentParent") row or table.

 

To copy the first row of a table after the current row you can use this simple code:

  current_row.NextPar := current_table.RowFirst.Duplicate(true, true);

 

In this code the first row is duplicated and inserted into the chain of rows by assigning it to the NextPar property. Duplicate() needs two parameters, the first enables the copying of the text (othwise only the properties are copied) the second enables the copying of the children, in case of a table row this are the cells.

 

Paragraph Attributes:

 

WPTools Version 9 supports many different paragraph, table and border attributes. These attributes are identified by a code, the WPAT_code. (The constants all start with WPAT_). It is important to remember that not all property ids make sense in all TParagraph objects, for example a table row cannot use the column width property. Some properties override each other (WPAT_ColWidth override WPAT_ColWidth_PC) and some are reserved for future versions. To read a, attribute you can use the method TParagraph.AGet( code, value ). 'Value' is passed as var parameter (by reference) and is only modified if that property was defined by this TParagraph or TWPTextStyle. In case the property was defined the function AGet returns true, otherwise false. Alternatively you can use the function AGetDef( code, default_value ). Here the value of the property is returned if defined, otherwise the provided default value. There are more 'A' methods, to delete a property (ADel), to read the properties of the paragraph or the style it uses (AGetInherited), to read and set a color value (AGetColor, ASetColor). Please see the TParagraph reference in the HLP file.

 

Important: The method TWPTextStyle.AGet(WPAT_code : Integer; var Value : Integer) is a functions which returns a boolean value. The return code is false if the property with the id WPAT_code was not defined. In this case the variable "Value" will not be modified! Please make sure you initialized the variable Value!

 

Attributes can also be set with the function SetProperty(code,value). This function returns a reference to the paragraph so you can simple connect calls with '.' without the need to have an additional variable:  par.SetProperty(WPAT_IndentLeft, 360).SetProperty(IndentFirst, -360);

 

Tabstops:

Tabstops, well... the tab positions actually, are not stored as WPAT_ properties. They are accessed through several methods, such as TabstopAdd, TabstopMove or TabstopGet. (See reference).

 

Character Attributes:

 

As stated character attributes are stored in just one double byte value. You may ask, 'How can this work?'  Particularly since WPTools Version 9 supports 15 different character attributes with multiple settings possible for each of these.

 

WPTools Version 9 does not save the attributes directly in this CharAttr value. It only saves an index there. This is then used to retrieve the actual attributes from a global attribute cache.

We find this concept ideal - other text editors use start/end tags to store character attributes, others even split up the text into elements which are using the same combination of attribute styles. In both cases it is extremely difficult to 'apply' a certain attribute to text. Our concept makes it possible to simply set a number value and the style is changed.

If styles have to be updated, the interface classes, such as TWPAbstractCharAttrInterface, make it easy to create and use the index values.

 

WPRichText1.AttrHelper.Clear;

WPRichText1.AttrHelper.SetFontName('Courier New');

WPRichText1.AttrHelper.SetColor(clGreen);

WPRichText1.ActiveParagraph.SetText(

 'Some green text',

 WPRichText1.AttrHelper.CharAttr);

WPRichText1.DelayedReformat;

 

Explanation: AttrHelper is an object of class TWPStoredCharAttrInterface. It calculates "CharAttr" index values. 'Clear' will delete all attributes - the CharAttr index will be 0. SetFontName and SetColor are used to define new character attribute. Reading the property CharAttr (inside the call to the TParagraph method SetText) will create a new CharAttr index which is used for the text. The calculated CharAttr can be used at different places for text which should look the same. It will become invalid when the document is cleared by TWPRichText.Clear. Read more...

 

If your program manipulates the text by direct access to the TParagraph objects it is required to call ReformatAll before the change becomes visible.

 

WPTools 8 introduces the property TemplatePar within TParagraph. It is used only by the tabels created the new dynamic table feature. Using template paragraphs, the method GridUpdate can be used to (re)create a table using a definition stored in the paragraph list starting with TemplatePar. This feature should only be used with the TWPTableProducer component.

 

 

Inheritance Charts:

 

Here you see the editor TWPRichText,and the TWPRTFEnginePaint object which is the RTF Engine (used by the TWPRichText as object 'Memo', the TWPRichTextLabel inherits from it):

 

 

clip0009            

                      clip0010

 

Please note that we now use format strings to pass properties to the reader and writer classes. Example: WPRichText1.AsANSIString('RTF-onlybody') creates a string in RTF format which contains only the body text.

 

This are the standard reader and writer classes:

 

clip0025

 

To update TParagraph and TWPTextStyle objects you will have to use the "A" methods (ASet, AGet) - the interface classes are only used to either change the current writing mode or the attributes of multiple paragraphs and characters (such as selected text).

clip0155

All classes which change the attribute of certain elements inherit from TWPAbstractCharAttrInterface. In cases where it makes sense the classes are also able to change paragraph attributes as well. The only exception is TWPAttrEmulator, which does not work like the other interfaces since it is mainly used to offer compatibility to the WPRichText.CPAttr pointer in WPTools 4.

 

Icons in TWPToolbar

 

The buttons use an old 16 color resource included as resource file. This is useful for test projects only. For "real" project simply add a TWPImageList component to the main form or a data module with the provided icon images.

 

Inplace Editors

 

Inplace editors inherit from the class TWPToolsInplaceEditorAbstractBase. Objects of this class are stored with a paragraph as paragraph-object. They can also be attached to a TWPTextObject (image type) - in this case, the object uses a temporary TParagraph object which maintains the editor. Se unit WPCTRInplaceWinEdit for the implementation of the inplace editors. Currently only the check box can be used.