| Story Library |
The engine has reserved some space for the application to define attributes of its own. These go between ClientBegin and ClientEnd of the appropriate enum. The application is expected to define its own constants that map into this range, in one of its own header files, eg:
// ApplicationTypes.h
const Story::GlyphInt::Type MyFirstAtt = Story::GlyphInt::ClientBegin+0;
const Story::GlyphInt::Type MySecondAtt = Story::GlyphInt::ClientBegin+1;
This makes MyFirstAtt a compile-time constant of the correct type and value, that can be used like Story::CGlyphAtts::Get(MyFirstAtt), etc.
The amount of space is set by some defines in Config. Changing config values, or adding new attributes outside of the ClientBegin/End ranges, would of course mean recompiling the text engine source. Little else is needed, though; the text engine should resize its data structures to fit.
Later versions of the text engine may change the number of built-in attributes, which will mean a change to the ClientBegin values. You probably won't need to store the index constants in a file, but if you do, you should be prepared to remap them when reading old files. The engine already does this for its own archive format. See CDeltas<Key,Value,end>::Serialize( CArchive &ar, int clientBegin, int clientEnd ).
During file import, the engine ignores unknown attributes and gives missing ones their default values, so adding or removing an attribute does not itself make old files unreadable. Changing the meaning of an attribute, however, will.
If you need an attribute more complex than bool, int, float or CString, you use the GlyphAtt enum and create a subclass of Story::CAtt. Story::CAtt is an abstract class which declares the comparison, hashing, sharing, cloning, immutability and serialization which the engine needs. Story::CListAtt is an example of a CAtt subclass for paragraphs.
new CCmdApplyGlyphDelta( Delta( GlyphBool::IsItalic, true ) );
creates a command which will make the selected text italic. You can make more complex deltas by creating a CGlyphAttsDelta explicitly and adding each change to it:
CPtr<CGlyphAttsDelta> pDelta = new CGlyphAttsDelta;
pDelta->Add( GlyphBool::IsItalic, true );
pDelta->Add( GlyphInt::Weight, 20 );
new CCmdApplyGlyphDelta( pDelta );
creates a command which changes both weight and the italic style. You can also make a delta as the difference of two CGlyphAtts.
A Story::CGlyphAtts is actually a delta plus the name of a style. The style describes the base formatting and the delta describes any changes applied on top. The combined effect of all those deltas is represented by a Story::CGlyphFlat, which Story::CGlyphAtts also stores, and which provides a fast, simple, plain representation of the final glyph's attributes.
enum { Unchecked, Checked, Indeterminate };
void CPagePlusView::OnUpdateItalic( CCmdUI* pCmdUI )
{
GlyphBool::Type att = GlyphBool::IsItalic;
CSelection *pSelection = GetCurrentSelection();
CPtr<CGlyphAttsRange> pRange = pSelection->GetGlyphAttsRange();
int check = pRange->Contains( att ) ? Indeterminate :
pRange->Get( att ) ? Checked : Unchecked;
pCmdUI->SetCheck( check );
}